mirror of
git://sourceware.org/git/lvm2.git
synced 2025-12-25 20:23:49 +03:00
Compare commits
309 Commits
old-v2_02_
...
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 | ||
|
|
075b4bef3f | ||
|
|
b59fce4393 | ||
|
|
8674a25eb8 | ||
|
|
10bf8fd2cd | ||
|
|
57cb22ff3c | ||
|
|
0162abdcae | ||
|
|
5801171518 | ||
|
|
bf1edbd1e2 | ||
|
|
a8484d987d | ||
|
|
9b2147f608 | ||
|
|
32530b378e | ||
|
|
a42905efa6 | ||
|
|
c59745f9dd | ||
|
|
b4ad9a5d08 | ||
|
|
3ead7a38b1 | ||
|
|
bf90435200 | ||
|
|
9c181fa3d3 | ||
|
|
3af0b1eb90 | ||
|
|
7110c318ee | ||
|
|
49a552ccdc | ||
|
|
57685f17a9 | ||
|
|
a1c09a463f | ||
|
|
194121760a | ||
|
|
6a987d46bf | ||
|
|
e3db0b39b9 | ||
|
|
4d4f0ee188 | ||
|
|
ac7334c167 | ||
|
|
e7bdd69af0 | ||
|
|
fefc655969 | ||
|
|
4dceaef60e | ||
|
|
6fc10dd3ae | ||
|
|
1ecd05a584 | ||
|
|
976acaca31 | ||
|
|
b4e5131d59 | ||
|
|
49f7cfefd7 | ||
|
|
fc365092f6 | ||
|
|
7f26240442 | ||
|
|
db559bb20a | ||
|
|
52850faa15 | ||
|
|
57d9a6c836 | ||
|
|
752c880bfc | ||
|
|
d83a354781 | ||
|
|
17dd81336d | ||
|
|
eaa46a2575 | ||
|
|
fc0ec1e71e | ||
|
|
fb2f92df1d | ||
|
|
74adbb77b7 | ||
|
|
788e544e1d | ||
|
|
368a0d4d2d | ||
|
|
962b7222d0 | ||
|
|
17c1f54369 | ||
|
|
33ae38e71b | ||
|
|
ef58af4bf1 | ||
|
|
3fad2db2f8 | ||
|
|
9feaeb28ca | ||
|
|
0075364715 | ||
|
|
99c5da5da5 | ||
|
|
22c957bc20 | ||
|
|
3316d59910 | ||
|
|
a109ce1eca | ||
|
|
e581a78d65 | ||
|
|
3c78f9900c | ||
|
|
bd606943e6 | ||
|
|
6381666df4 | ||
|
|
736f1aa301 | ||
|
|
b1a4eac7a8 | ||
|
|
8226a5276b | ||
|
|
77ad0bb12e | ||
|
|
9412b42206 | ||
|
|
2a91d87074 | ||
|
|
4a23617d79 | ||
|
|
0e2ceed74d | ||
|
|
ed56aed8eb | ||
|
|
8d909cbdc0 | ||
|
|
bf98943cbb | ||
|
|
6ff4552be2 | ||
|
|
1c7eb79370 | ||
|
|
f095a75f1e | ||
|
|
f70af6018c | ||
|
|
71b3b1ff4c | ||
|
|
d9fefa0c6c | ||
|
|
3bfe922381 | ||
|
|
a85cf17bf1 | ||
|
|
dbb5a09918 | ||
|
|
93e5097f20 | ||
|
|
dd53f2dc83 | ||
|
|
2b83c80593 | ||
|
|
6930f60c06 | ||
|
|
376b76e75c | ||
|
|
1ddd4509dc | ||
|
|
6af3f4f4cf | ||
|
|
6726c5f958 | ||
|
|
d5a9c43cb2 |
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
|
||||
|
||||
198
WHATS_NEW
198
WHATS_NEW
@@ -1,3 +1,201 @@
|
||||
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.
|
||||
Fix vgsplit to only move hidden 'snapshotN' LVs when necessary.
|
||||
Update vgsplit tests for lvnames on the cmdline.
|
||||
Update vgsplit man page to reflect lvnames on the cmdline.
|
||||
Update vgsplit to take "-n LogicalVolumeName" on the cmdline.
|
||||
Use clustered mirror log with pvmove in clustered VGs, if available.
|
||||
Fix some pvmove error status codes.
|
||||
Fix vgsplit error paths to release vg_to lock.
|
||||
Indicate whether or not VG is clustered in vgcreate log message.
|
||||
Mention default --clustered setting in vgcreate man page.
|
||||
Add config file overrides to clvmd when it reads the active LVs list.
|
||||
Fix vgreduce to use vg_split_mdas to check sufficient mdas remain.
|
||||
Add (empty) orphan VGs to lvmcache during initialisation.
|
||||
Fix orphan VG name used for format_pool.
|
||||
Create a fid for internal orphan VGs.
|
||||
Update lvmcache VG lock state for all locking types now.
|
||||
Fix output if overriding command_names on cmdline.
|
||||
Add detection of clustered mirror log capability.
|
||||
Add check to vg_commit() ensuring VG lock held before writing new VG metadata.
|
||||
Add validation of LV name to pvmove -n.
|
||||
Make clvmd refresh the context correctly when lvm.conf is updated.
|
||||
Add some basic internal VG lock validation.
|
||||
Add per-command flags to control which commands use the VG metadata cache.
|
||||
Fix vgsplit locking of new VG (2.02.30).
|
||||
Avoid erroneous vgsplit error message for new VG. (2.02.29)
|
||||
Suppress duplicate message when lvresize fails because of invalid vgname.
|
||||
Cache VG metadata internally while VG lock is held.
|
||||
Fix redundant lvresize message if vg doesn't exist.
|
||||
Fix another allocation bug with clvmd and large node IDs.
|
||||
Add find_lv_in_lv_list() and find_pv_in_pv_list().
|
||||
Fix uninitialised variable in clvmd that could cause odd hangs.
|
||||
Add vgmerge tests.
|
||||
Add pvseg_is_allocated() for identifying a PV segment allocated to a LV.
|
||||
Add list_move() for moving elements from one list to another.
|
||||
Add 'is_reserved_lvname()' for identifying hidden LVs.
|
||||
Correct command name in lvmdiskscan man page.
|
||||
clvmd no longer crashes if it sees nodeids over 50.
|
||||
Fix potential deadlock in clvmd thread handling.
|
||||
Refactor text format initialisation into _init_text_import.
|
||||
Escape double quotes and backslashes in external metadata and config data.
|
||||
Add functions for escaping double quotes in strings.
|
||||
Rename count_chars_len to count_chars.
|
||||
Use return_0 in a couple more places.
|
||||
Correct a function name typo in _line_append error message.
|
||||
Include limits.h in clvmd so it compiles with newer headers.
|
||||
Add VirtIO disks (virtblk) to filters.
|
||||
Fix resetting of MIRROR_IMAGE and VISIBLE_LV after removal of LV. (2.02.30)
|
||||
Fix remove_layer_from_lv to empty the LV before removing it. (2.02.30)
|
||||
Add missing no-longer-used segs_using_this_lv test to check_lv_segments.
|
||||
Remove redundant non-NULL tests before calling free in clvmd.c.
|
||||
Avoid a compiler warning: make is_orphan's parameter const.
|
||||
Fix lvconvert detection of mirror conversion in progress. (2.02.30)
|
||||
Avoid automatic lvconvert polldaemon invocation when -R specified. (2.02.30)
|
||||
Fix 'pvs -a' to detect VGs of PVs without metadata areas.
|
||||
Divide up internal orphan volume group by format type.
|
||||
Update usage message for clvmd.
|
||||
Fix clvmd man page not to print <br> and clarified debug options.
|
||||
Fix lvresize to support /dev/mapper prefix in the LV name.
|
||||
Fix unfilled parameter passed to fsadm from lvresize.
|
||||
Update fsadm to call lvresize if the partition size differs (with option -l).
|
||||
Fix fsadm to support VG/LV names.
|
||||
|
||||
Version 2.02.33 - 31st January 2008
|
||||
===================================
|
||||
Fix mirror log name construction during lvconvert. (2.02.30)
|
||||
Make monitor_dev_for_events recurse through the stack of LVs.
|
||||
Clean up some more compiler warnings.
|
||||
Some whitespace tidy-ups.
|
||||
Use stack return macros throughout.
|
||||
Rely upon internally-cached PV labels while corresponding VG lock is held.
|
||||
|
||||
Version 2.02.32 - 29th January 2008
|
||||
===================================
|
||||
Fix two check_lv_segments error messages to show whole segment.
|
||||
|
||||
38
WHATS_NEW_DM
38
WHATS_NEW_DM
@@ -1,5 +1,36 @@
|
||||
Version 1.02.25 -
|
||||
====================================
|
||||
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
|
||||
=================================
|
||||
Remove redundant if-before-free tests.
|
||||
Use log_warn for reporting field help text instead of log_print.
|
||||
Change cluster mirror log type name (s/clustered_/clustered-/)
|
||||
|
||||
@@ -35,7 +66,7 @@ Version 1.02.22 - 21st August 2007
|
||||
Version 1.02.21 - 13th July 2007
|
||||
================================
|
||||
Introduce _LOG_STDERR to send log_warn() messages to stderr not stdout.
|
||||
Fix dmsetup -o devno string termination. (1.02.20)
|
||||
Fix dmsetup -o devno string termination. (1.02.20)
|
||||
|
||||
Version 1.02.20 - 15th June 2007
|
||||
================================
|
||||
@@ -323,4 +354,3 @@ Version 1.00.08 - 27 Feb 2004
|
||||
Fixed DESTDIR for make install/install_static_lib.
|
||||
Updated README/INSTALL to reflect move to sources.redhat.com.
|
||||
Updated autoconf files to 2003-06-17.
|
||||
|
||||
|
||||
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, 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -297,6 +296,8 @@ static void get_members()
|
||||
{
|
||||
int retnodes;
|
||||
int status;
|
||||
int i;
|
||||
int high_nodeid = 0;
|
||||
|
||||
num_nodes = cman_get_node_count(c_handle);
|
||||
if (num_nodes == -1) {
|
||||
@@ -325,11 +326,10 @@ static void get_members()
|
||||
exit(6);
|
||||
}
|
||||
|
||||
if (node_updown == NULL) {
|
||||
size_t buf_len = sizeof(int) * max(num_nodes, max_updown_nodes);
|
||||
node_updown = malloc(buf_len);
|
||||
if (node_updown)
|
||||
memset(node_updown, 0, buf_len);
|
||||
/* Get the highest nodeid */
|
||||
for (i=0; i<retnodes; i++) {
|
||||
if (nodes[i].cn_nodeid > high_nodeid)
|
||||
high_nodeid = nodes[i].cn_nodeid;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <getopt.h>
|
||||
#include <syslog.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <libdlm.h>
|
||||
|
||||
#include "clvmd-comms.h"
|
||||
@@ -146,8 +147,10 @@ static void usage(char *prog, FILE *file)
|
||||
fprintf(file, "\n");
|
||||
fprintf(file, " -V Show version of clvmd\n");
|
||||
fprintf(file, " -h Show this help information\n");
|
||||
fprintf(file, " -d Don't fork, run in the foreground\n");
|
||||
fprintf(file, " -d Set debug level\n");
|
||||
fprintf(file, " If starting clvmd then don't fork, run in the foreground\n");
|
||||
fprintf(file, " -R Tell all running clvmds in the cluster to reload their device cache\n");
|
||||
fprintf(file, " -C Sets debug level (from -d) on all clvmd instances clusterwide\n");
|
||||
fprintf(file, " -t<secs> Command timeout (default 60 seconds)\n");
|
||||
fprintf(file, " -T<secs> Startup timeout (default none)\n");
|
||||
fprintf(file, "\n");
|
||||
@@ -179,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);
|
||||
@@ -188,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;
|
||||
@@ -527,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;
|
||||
@@ -538,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);
|
||||
}
|
||||
@@ -630,7 +687,7 @@ static void main_loop(int local_sock, int cmd_timeout)
|
||||
}
|
||||
|
||||
if (FD_ISSET(thisfd->fd, &in)) {
|
||||
struct local_client *newfd;
|
||||
struct local_client *newfd = NULL;
|
||||
int ret;
|
||||
|
||||
/* Do callback */
|
||||
@@ -901,8 +958,7 @@ static int read_from_local_sock(struct local_client *thisfd)
|
||||
}
|
||||
|
||||
/* Free the command buffer */
|
||||
if (thisfd->bits.localsock.cmd)
|
||||
free(thisfd->bits.localsock.cmd);
|
||||
free(thisfd->bits.localsock.cmd);
|
||||
|
||||
/* Clear out the cross-link */
|
||||
if (thisfd->bits.localsock.pipe_client != NULL)
|
||||
@@ -937,8 +993,7 @@ static int read_from_local_sock(struct local_client *thisfd)
|
||||
}
|
||||
|
||||
/* Free any old buffer space */
|
||||
if (thisfd->bits.localsock.cmd)
|
||||
free(thisfd->bits.localsock.cmd);
|
||||
free(thisfd->bits.localsock.cmd);
|
||||
|
||||
/* See if we have the whole message */
|
||||
argslen =
|
||||
@@ -984,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)) {
|
||||
@@ -1055,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;
|
||||
|
||||
@@ -1166,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) {
|
||||
@@ -1415,7 +1472,8 @@ next_pre:
|
||||
DEBUGLOG("Waiting for next pre command\n");
|
||||
|
||||
pthread_mutex_lock(&client->bits.localsock.mutex);
|
||||
if (client->bits.localsock.state != PRE_COMMAND) {
|
||||
if (client->bits.localsock.state != PRE_COMMAND &&
|
||||
!client->bits.localsock.finished) {
|
||||
pthread_cond_wait(&client->bits.localsock.cond,
|
||||
&client->bits.localsock.mutex);
|
||||
}
|
||||
@@ -1437,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;
|
||||
|
||||
@@ -1545,8 +1604,7 @@ static void send_local_reply(struct local_client *client, int status, int fd)
|
||||
}
|
||||
thisreply = thisreply->next;
|
||||
|
||||
if (tempreply->replymsg)
|
||||
free(tempreply->replymsg);
|
||||
free(tempreply->replymsg);
|
||||
free(tempreply);
|
||||
}
|
||||
|
||||
@@ -1577,8 +1635,7 @@ static void free_reply(struct local_client *client)
|
||||
|
||||
thisreply = thisreply->next;
|
||||
|
||||
if (tempreply->replymsg)
|
||||
free(tempreply->replymsg);
|
||||
free(tempreply->replymsg);
|
||||
free(tempreply);
|
||||
}
|
||||
client->bits.localsock.replies = NULL;
|
||||
@@ -1613,7 +1670,7 @@ static void send_version_message()
|
||||
static int send_message(void *buf, int msglen, const char *csid, int fd,
|
||||
const char *errtext)
|
||||
{
|
||||
int len;
|
||||
int len = 0;
|
||||
int saved_errno = 0;
|
||||
struct timespec delay;
|
||||
struct timespec remtime;
|
||||
@@ -1730,8 +1787,7 @@ static __attribute__ ((noreturn)) void *lvm_thread_fn(void *arg)
|
||||
pthread_mutex_unlock(&lvm_thread_mutex);
|
||||
|
||||
process_work_item(cmd);
|
||||
if (cmd->msg)
|
||||
free(cmd->msg);
|
||||
free(cmd->msg);
|
||||
free(cmd);
|
||||
|
||||
pthread_mutex_lock(&lvm_thread_mutex);
|
||||
@@ -1824,8 +1880,9 @@ static int open_local_sock()
|
||||
log_error("Can't create local socket: %m");
|
||||
return -1;
|
||||
}
|
||||
/* Set Close-on-exec */
|
||||
/* Set Close-on-exec & non-blocking */
|
||||
fcntl(local_socket, F_SETFD, 1);
|
||||
fcntl(local_socket, F_SETFL, fcntl(local_socket, F_GETFL, 0) | O_NONBLOCK);
|
||||
|
||||
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||
memcpy(sockaddr.sun_path, CLVMD_SOCKNAME, sizeof(CLVMD_SOCKNAME));
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2002-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.
|
||||
*
|
||||
@@ -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,13 +400,13 @@ 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)) {
|
||||
/* Reinitialise various settings inc. logging, filters */
|
||||
if (!refresh_toolcontext(cmd)) {
|
||||
if (do_refresh_cache()) {
|
||||
log_error("Updated config file invalid. Aborting.");
|
||||
pthread_mutex_unlock(&lvm_lock);
|
||||
return EINVAL;
|
||||
@@ -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);
|
||||
@@ -437,7 +525,7 @@ int post_lock_lv(unsigned char command, unsigned char lock_flags,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check if a VG is un use by LVM1 so we don't stomp on it */
|
||||
/* Check if a VG is in use by LVM1 so we don't stomp on it */
|
||||
int do_check_lvm1(const char *vgname)
|
||||
{
|
||||
int status;
|
||||
@@ -470,9 +558,10 @@ static void drop_vg_locks()
|
||||
char line[255];
|
||||
FILE *vgs =
|
||||
popen
|
||||
("lvm pvs --nolocking --noheadings -o vg_name", "r");
|
||||
("lvm pvs --config 'log{command_names=0 prefix=\"\"}' --nolocking --noheadings -o vg_name", "r");
|
||||
|
||||
sync_unlock("P_orphans", LCK_EXCL);
|
||||
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...
|
||||
@@ -511,7 +611,7 @@ static void *get_initial_state()
|
||||
char line[255];
|
||||
FILE *lvs =
|
||||
popen
|
||||
("lvm lvs --nolocking --noheadings -o vg_uuid,lv_uuid,lv_attr,vg_attr",
|
||||
("lvm lvs --config 'log{command_names=0 prefix=\"\"}' --nolocking --noheadings -o vg_uuid,lv_uuid,lv_attr,vg_attr",
|
||||
"r");
|
||||
|
||||
if (!lvs)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <libdevmapper.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "clvm.h"
|
||||
#include "refresh_clvmd.h"
|
||||
|
||||
@@ -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)/$<
|
||||
|
||||
|
||||
@@ -125,8 +125,9 @@ out_parse:
|
||||
return ME_IGNORE;
|
||||
}
|
||||
|
||||
static void _temporary_log_fn(int level, const char *file,
|
||||
int line, const char *format)
|
||||
static void _temporary_log_fn(int level, const char *file __attribute((unused)),
|
||||
int line __attribute((unused)),
|
||||
const char *format)
|
||||
{
|
||||
if (!strncmp(format, "WARNING: ", 9) && (level < 5))
|
||||
syslog(LOG_CRIT, "%s", format);
|
||||
@@ -164,7 +165,8 @@ static int _remove_failed_devices(const char *device)
|
||||
return (r == 1) ? 0 : -1;
|
||||
}
|
||||
|
||||
void process_event(struct dm_task *dmt, enum dm_event_mask event,
|
||||
void process_event(struct dm_task *dmt,
|
||||
enum dm_event_mask event __attribute((unused)),
|
||||
void **unused __attribute((unused)))
|
||||
{
|
||||
void *next = NULL;
|
||||
@@ -222,8 +224,11 @@ void process_event(struct dm_task *dmt, enum dm_event_mask event,
|
||||
pthread_mutex_unlock(&_event_mutex);
|
||||
}
|
||||
|
||||
int register_device(const char *device, const char *uuid, int major, int minor,
|
||||
void **unused __attribute((unused)))
|
||||
int register_device(const char *device,
|
||||
const char *uuid __attribute((unused)),
|
||||
int major __attribute((unused)),
|
||||
int minor __attribute((unused)),
|
||||
void **unused __attribute((unused)))
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
@@ -259,8 +264,11 @@ out:
|
||||
return r;
|
||||
}
|
||||
|
||||
int unregister_device(const char *device, const char *uuid, int major, int minor,
|
||||
void **unused __attribute((unused)))
|
||||
int unregister_device(const char *device,
|
||||
const char *uuid __attribute((unused)),
|
||||
int major __attribute((unused)),
|
||||
int minor __attribute((unused)),
|
||||
void **unused __attribute((unused)))
|
||||
{
|
||||
pthread_mutex_lock(&_register_mutex);
|
||||
|
||||
|
||||
@@ -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)/$<
|
||||
|
||||
|
||||
@@ -54,8 +54,10 @@ struct snap_status {
|
||||
*/
|
||||
static pthread_mutex_t _event_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
static void _temporary_log_fn(int level, const char *file,
|
||||
int line, const char *format)
|
||||
static void _temporary_log_fn(int level,
|
||||
const char *file __attribute((unused)),
|
||||
int line __attribute((unused)),
|
||||
const char *format)
|
||||
{
|
||||
if (!strncmp(format, "WARNING: ", 9) && (level < 5))
|
||||
syslog(LOG_CRIT, "%s", format);
|
||||
@@ -115,7 +117,8 @@ fail:
|
||||
dm_event_handler_destroy(dmevh);
|
||||
}
|
||||
|
||||
void process_event(struct dm_task *dmt, enum dm_event_mask event,
|
||||
void process_event(struct dm_task *dmt,
|
||||
enum dm_event_mask event __attribute((unused)),
|
||||
void **private)
|
||||
{
|
||||
void *next = NULL;
|
||||
@@ -161,8 +164,11 @@ out:
|
||||
pthread_mutex_unlock(&_event_mutex);
|
||||
}
|
||||
|
||||
int register_device(const char *device, const char *uuid, int major, int minor,
|
||||
void **private)
|
||||
int register_device(const char *device,
|
||||
const char *uuid __attribute((unused)),
|
||||
int major __attribute((unused)),
|
||||
int minor __attribute((unused)),
|
||||
void **private)
|
||||
{
|
||||
int r = 0;
|
||||
int *percent_warning = (int*)private;
|
||||
@@ -201,8 +207,11 @@ out:
|
||||
return r;
|
||||
}
|
||||
|
||||
int unregister_device(const char *device, const char *uuid, int major, int minor,
|
||||
void **unused __attribute((unused)))
|
||||
int unregister_device(const char *device,
|
||||
const char *uuid __attribute((unused)),
|
||||
int major __attribute((unused)),
|
||||
int minor __attribute((unused)),
|
||||
void **unused __attribute((unused)))
|
||||
{
|
||||
pthread_mutex_lock(&_register_mutex);
|
||||
|
||||
|
||||
@@ -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)/$<
|
||||
|
||||
|
||||
@@ -125,8 +125,9 @@ out_parse:
|
||||
return ME_IGNORE;
|
||||
}
|
||||
|
||||
static void _temporary_log_fn(int level, const char *file,
|
||||
int line, const char *format)
|
||||
static void _temporary_log_fn(int level, const char *file __attribute((unused)),
|
||||
int line __attribute((unused)),
|
||||
const char *format)
|
||||
{
|
||||
if (!strncmp(format, "WARNING: ", 9) && (level < 5))
|
||||
syslog(LOG_CRIT, "%s", format);
|
||||
@@ -164,7 +165,8 @@ static int _remove_failed_devices(const char *device)
|
||||
return (r == 1) ? 0 : -1;
|
||||
}
|
||||
|
||||
void process_event(struct dm_task *dmt, enum dm_event_mask event,
|
||||
void process_event(struct dm_task *dmt,
|
||||
enum dm_event_mask event __attribute((unused)),
|
||||
void **unused __attribute((unused)))
|
||||
{
|
||||
void *next = NULL;
|
||||
@@ -222,8 +224,11 @@ void process_event(struct dm_task *dmt, enum dm_event_mask event,
|
||||
pthread_mutex_unlock(&_event_mutex);
|
||||
}
|
||||
|
||||
int register_device(const char *device, const char *uuid, int major, int minor,
|
||||
void **unused __attribute((unused)))
|
||||
int register_device(const char *device,
|
||||
const char *uuid __attribute((unused)),
|
||||
int major __attribute((unused)),
|
||||
int minor __attribute((unused)),
|
||||
void **unused __attribute((unused)))
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
@@ -259,8 +264,11 @@ out:
|
||||
return r;
|
||||
}
|
||||
|
||||
int unregister_device(const char *device, const char *uuid, int major, int minor,
|
||||
void **unused __attribute((unused)))
|
||||
int unregister_device(const char *device,
|
||||
const char *uuid __attribute((unused)),
|
||||
int major __attribute((unused)),
|
||||
int minor __attribute((unused)),
|
||||
void **unused __attribute((unused)))
|
||||
{
|
||||
pthread_mutex_lock(&_register_mutex);
|
||||
|
||||
|
||||
@@ -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)/$<
|
||||
|
||||
|
||||
@@ -54,8 +54,10 @@ struct snap_status {
|
||||
*/
|
||||
static pthread_mutex_t _event_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
static void _temporary_log_fn(int level, const char *file,
|
||||
int line, const char *format)
|
||||
static void _temporary_log_fn(int level,
|
||||
const char *file __attribute((unused)),
|
||||
int line __attribute((unused)),
|
||||
const char *format)
|
||||
{
|
||||
if (!strncmp(format, "WARNING: ", 9) && (level < 5))
|
||||
syslog(LOG_CRIT, "%s", format);
|
||||
@@ -115,7 +117,8 @@ fail:
|
||||
dm_event_handler_destroy(dmevh);
|
||||
}
|
||||
|
||||
void process_event(struct dm_task *dmt, enum dm_event_mask event,
|
||||
void process_event(struct dm_task *dmt,
|
||||
enum dm_event_mask event __attribute((unused)),
|
||||
void **private)
|
||||
{
|
||||
void *next = NULL;
|
||||
@@ -161,8 +164,11 @@ out:
|
||||
pthread_mutex_unlock(&_event_mutex);
|
||||
}
|
||||
|
||||
int register_device(const char *device, const char *uuid, int major, int minor,
|
||||
void **private)
|
||||
int register_device(const char *device,
|
||||
const char *uuid __attribute((unused)),
|
||||
int major __attribute((unused)),
|
||||
int minor __attribute((unused)),
|
||||
void **private)
|
||||
{
|
||||
int r = 0;
|
||||
int *percent_warning = (int*)private;
|
||||
@@ -201,8 +207,11 @@ out:
|
||||
return r;
|
||||
}
|
||||
|
||||
int unregister_device(const char *device, const char *uuid, int major, int minor,
|
||||
void **unused __attribute((unused)))
|
||||
int unregister_device(const char *device,
|
||||
const char *uuid __attribute((unused)),
|
||||
int major __attribute((unused)),
|
||||
int minor __attribute((unused)),
|
||||
void **unused __attribute((unused)))
|
||||
{
|
||||
pthread_mutex_lock(&_register_mutex);
|
||||
|
||||
|
||||
@@ -25,7 +25,8 @@ devices {
|
||||
# list of regular expressions in turn and the first match is used.
|
||||
preferred_names = [ ]
|
||||
|
||||
# preferred_names = [ "^/dev/mpath/", "^/dev/[hs]d" ]
|
||||
# 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 \
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
@@ -391,12 +391,26 @@ int target_version(const char *target_name, uint32_t *maj,
|
||||
return r;
|
||||
}
|
||||
|
||||
int module_present(const char *target_name)
|
||||
{
|
||||
int ret = 0;
|
||||
#ifdef MODPROBE_CMD
|
||||
char module[128];
|
||||
|
||||
if (dm_snprintf(module, sizeof(module), "dm-%s", target_name) < 0) {
|
||||
log_error("module_present module name too long: %s",
|
||||
target_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = exec_cmd(MODPROBE_CMD, module, "", "");
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
int target_present(const char *target_name, int use_modprobe)
|
||||
{
|
||||
uint32_t maj, min, patchlevel;
|
||||
#ifdef MODPROBE_CMD
|
||||
char module[128];
|
||||
#endif
|
||||
|
||||
if (!activation())
|
||||
return 0;
|
||||
@@ -406,14 +420,7 @@ int target_present(const char *target_name, int use_modprobe)
|
||||
if (target_version(target_name, &maj, &min, &patchlevel))
|
||||
return 1;
|
||||
|
||||
if (dm_snprintf(module, sizeof(module), "dm-%s", target_name)
|
||||
< 0) {
|
||||
log_error("target_present module name too long: %s",
|
||||
target_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!exec_cmd(MODPROBE_CMD, module, "", ""))
|
||||
if (!module_present(target_name))
|
||||
return_0;
|
||||
}
|
||||
#endif
|
||||
@@ -666,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.
|
||||
@@ -679,6 +718,7 @@ int monitor_dev_for_events(struct cmd_context *cmd,
|
||||
struct list *tmp, *snh, *snht;
|
||||
struct lv_segment *seg;
|
||||
int (*monitor_fn) (struct lv_segment *s, int e);
|
||||
uint32_t s;
|
||||
|
||||
/* skip dmeventd code altogether */
|
||||
if (dmeventd_monitor_mode() == DMEVENTD_MONITOR_IGNORE)
|
||||
@@ -715,6 +755,19 @@ int monitor_dev_for_events(struct cmd_context *cmd,
|
||||
list_iterate(tmp, &lv->segments) {
|
||||
seg = list_item(tmp, struct lv_segment);
|
||||
|
||||
/* Recurse for AREA_LV */
|
||||
for (s = 0; s < seg->area_count; s++) {
|
||||
if (seg_type(seg, s) != AREA_LV)
|
||||
continue;
|
||||
if (!monitor_dev_for_events(cmd, seg_lv(seg, s),
|
||||
monitor)) {
|
||||
log_error("Failed to %smonitor %s",
|
||||
monitor ? "" : "un",
|
||||
seg_lv(seg, s)->name);
|
||||
r = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!seg_monitored(seg) || (seg->status & PVMOVE))
|
||||
continue;
|
||||
|
||||
|
||||
@@ -30,6 +30,9 @@ struct lvinfo {
|
||||
uint32_t read_ahead;
|
||||
};
|
||||
|
||||
/* target attribute flags */
|
||||
#define MIRROR_LOG_CLUSTERED 0x00000001U
|
||||
|
||||
void set_activation(int activation);
|
||||
int activation(void);
|
||||
|
||||
@@ -37,6 +40,7 @@ int driver_version(char *version, size_t size);
|
||||
int library_version(char *version, size_t size);
|
||||
int lvm1_present(struct cmd_context *cmd);
|
||||
|
||||
int module_present(const char *target_name);
|
||||
int target_present(const char *target_name, int use_modprobe);
|
||||
int target_version(const char *target_name, uint32_t *maj,
|
||||
uint32_t *min, uint32_t *patchlevel);
|
||||
@@ -87,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);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
@@ -100,10 +100,8 @@ static struct dm_task *_setup_task(const char *name, const char *uuid,
|
||||
{
|
||||
struct dm_task *dmt;
|
||||
|
||||
if (!(dmt = dm_task_create(task))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!(dmt = dm_task_create(task)))
|
||||
return_NULL;
|
||||
|
||||
if (name)
|
||||
dm_task_set_name(dmt, name);
|
||||
@@ -127,10 +125,8 @@ static int _info_run(const char *name, const char *dlid, struct dm_info *info,
|
||||
|
||||
dmtask = mknodes ? DM_DEVICE_MKNODES : DM_DEVICE_INFO;
|
||||
|
||||
if (!(dmt = _setup_task(name, dlid, 0, dmtask))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(dmt = _setup_task(name, dlid, 0, dmtask)))
|
||||
return_0;
|
||||
|
||||
if (!with_open_count)
|
||||
if (!dm_task_no_open_count(dmt))
|
||||
@@ -160,9 +156,9 @@ int device_is_usable(dev_t dev)
|
||||
struct dm_task *dmt;
|
||||
struct dm_info info;
|
||||
const char *name;
|
||||
uint64_t start, length;
|
||||
char *target_type = NULL;
|
||||
char *params;
|
||||
uint64_t start, length;
|
||||
char *target_type = NULL;
|
||||
char *params;
|
||||
void *next = NULL;
|
||||
int r = 0;
|
||||
|
||||
@@ -190,13 +186,13 @@ int device_is_usable(dev_t dev)
|
||||
/* FIXME Also check for mirror block_on_error and mpath no paths */
|
||||
/* For now, we exclude all mirrors */
|
||||
|
||||
do {
|
||||
next = dm_get_next_target(dmt, next, &start, &length,
|
||||
&target_type, ¶ms);
|
||||
/* Skip if target type doesn't match */
|
||||
if (target_type && !strcmp(target_type, "mirror"))
|
||||
do {
|
||||
next = dm_get_next_target(dmt, next, &start, &length,
|
||||
&target_type, ¶ms);
|
||||
/* Skip if target type doesn't match */
|
||||
if (target_type && !strcmp(target_type, "mirror"))
|
||||
goto out;
|
||||
} while (next);
|
||||
} while (next);
|
||||
|
||||
/* FIXME Also check dependencies? */
|
||||
|
||||
@@ -259,10 +255,8 @@ static int _status_run(const char *name, const char *uuid,
|
||||
char *type = NULL;
|
||||
char *params = NULL;
|
||||
|
||||
if (!(dmt = _setup_task(name, uuid, 0, DM_DEVICE_STATUS))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(dmt = _setup_task(name, uuid, 0, DM_DEVICE_STATUS)))
|
||||
return_0;
|
||||
|
||||
if (!dm_task_no_open_count(dmt))
|
||||
log_error("Failed to disable open_count");
|
||||
@@ -348,10 +342,8 @@ static int _percent_run(struct dev_manager *dm, const char *name,
|
||||
*percent = -1;
|
||||
|
||||
if (!(dmt = _setup_task(name, dlid, event_nr,
|
||||
wait ? DM_DEVICE_WAITEVENT : DM_DEVICE_STATUS))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
wait ? DM_DEVICE_WAITEVENT : DM_DEVICE_STATUS)))
|
||||
return_0;
|
||||
|
||||
if (!dm_task_no_open_count(dmt))
|
||||
log_error("Failed to disable open_count");
|
||||
@@ -387,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);
|
||||
@@ -401,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);
|
||||
@@ -443,10 +434,8 @@ struct dev_manager *dev_manager_create(struct cmd_context *cmd,
|
||||
struct dm_pool *mem;
|
||||
struct dev_manager *dm;
|
||||
|
||||
if (!(mem = dm_pool_create("dev_manager", 16 * 1024))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!(mem = dm_pool_create("dev_manager", 16 * 1024)))
|
||||
return_NULL;
|
||||
|
||||
if (!(dm = dm_pool_alloc(mem, sizeof(*dm))))
|
||||
goto_bad;
|
||||
@@ -509,10 +498,8 @@ int dev_manager_snapshot_percent(struct dev_manager *dm,
|
||||
*/
|
||||
log_debug("Getting device status percentage for %s", name);
|
||||
if (!(_percent(dm, name, dlid, "snapshot", 0, NULL, percent,
|
||||
NULL))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
NULL)))
|
||||
return_0;
|
||||
|
||||
/* FIXME dm_pool_free ? */
|
||||
|
||||
@@ -544,10 +531,8 @@ int dev_manager_mirror_percent(struct dev_manager *dm,
|
||||
|
||||
log_debug("Getting device mirror status percentage for %s", name);
|
||||
if (!(_percent(dm, name, dlid, "mirror", wait, lv, percent,
|
||||
event_nr))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
event_nr)))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -643,11 +628,11 @@ static int _add_dev_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
|
||||
if (!(dlid = build_dlid(dm, lv->lvid.s, layer)))
|
||||
return_0;
|
||||
|
||||
log_debug("Getting device info for %s [%s]", name, dlid);
|
||||
if (!_info(name, dlid, 0, 1, 0, &info, NULL)) {
|
||||
log_error("Failed to get info for %s [%s].", name, dlid);
|
||||
return 0;
|
||||
}
|
||||
log_debug("Getting device info for %s [%s]", name, dlid);
|
||||
if (!_info(name, dlid, 0, 1, 0, &info, NULL)) {
|
||||
log_error("Failed to get info for %s [%s].", name, dlid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (info.exists && !dm_tree_add_dev(dtree, info.major, info.minor)) {
|
||||
log_error("Failed to add device (%" PRIu32 ":%" PRIu32") to dtree",
|
||||
@@ -691,31 +676,25 @@ static struct dm_tree *_create_partial_dtree(struct dev_manager *dm, struct logi
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_add_lv_to_dtree(dm, dtree, lv)) {
|
||||
stack;
|
||||
goto fail;
|
||||
}
|
||||
if (!_add_lv_to_dtree(dm, dtree, lv))
|
||||
goto_bad;
|
||||
|
||||
/* Add any snapshots of this LV */
|
||||
list_iterate_safe(snh, snht, &lv->snapshot_segs)
|
||||
if (!_add_lv_to_dtree(dm, dtree, list_struct_base(snh, struct lv_segment, origin_list)->cow)) {
|
||||
stack;
|
||||
goto fail;
|
||||
}
|
||||
if (!_add_lv_to_dtree(dm, dtree, list_struct_base(snh, struct lv_segment, origin_list)->cow))
|
||||
goto_bad;
|
||||
|
||||
/* Add any LVs used by segments in this LV */
|
||||
list_iterate_items(seg, &lv->segments)
|
||||
for (s = 0; s < seg->area_count; s++)
|
||||
if (seg_type(seg, s) == AREA_LV && seg_lv(seg, s)) {
|
||||
if (!_add_lv_to_dtree(dm, dtree, seg_lv(seg, s))) {
|
||||
stack;
|
||||
goto fail;
|
||||
}
|
||||
if (!_add_lv_to_dtree(dm, dtree, seg_lv(seg, s)))
|
||||
goto_bad;
|
||||
}
|
||||
|
||||
return dtree;
|
||||
|
||||
fail:
|
||||
bad:
|
||||
dm_tree_free(dtree);
|
||||
return NULL;
|
||||
}
|
||||
@@ -843,7 +822,7 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
|
||||
layer ? "-" : "", layer ? : "");
|
||||
|
||||
if (seg_present->segtype->ops->target_present &&
|
||||
!seg_present->segtype->ops->target_present(seg_present)) {
|
||||
!seg_present->segtype->ops->target_present(seg_present, NULL)) {
|
||||
log_error("Can't expand LV %s: %s target support missing "
|
||||
"from kernel?", seg->lv->name, seg_present->segtype->name);
|
||||
return 0;
|
||||
@@ -856,7 +835,7 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
|
||||
|
||||
/* If this is a snapshot origin, add real LV */
|
||||
if (lv_is_origin(seg->lv) && !layer) {
|
||||
if (seg->lv->vg->status & CLUSTERED) {
|
||||
if (vg_is_clustered(seg->lv->vg)) {
|
||||
log_error("Clustered snapshots are not yet supported");
|
||||
return 0;
|
||||
}
|
||||
@@ -948,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) {
|
||||
@@ -987,10 +966,10 @@ static int _create_lv_symlinks(struct dev_manager *dm, struct dm_tree_node *root
|
||||
name = dm_tree_node_get_name(child);
|
||||
|
||||
if (name && lvlayer->old_name && *lvlayer->old_name && strcmp(name, lvlayer->old_name)) {
|
||||
if (!dm_split_lvm_name(dm->mem, lvlayer->old_name, &vgname, &lvname, &layer)) {
|
||||
log_error("_create_lv_symlinks: Couldn't split up old device name %s", lvlayer->old_name);
|
||||
return 0;
|
||||
}
|
||||
if (!dm_split_lvm_name(dm->mem, lvlayer->old_name, &vgname, &lvname, &layer)) {
|
||||
log_error("_create_lv_symlinks: Couldn't split up old device name %s", lvlayer->old_name);
|
||||
return 0;
|
||||
}
|
||||
fs_rename_lv(lvlayer->lv, name, lvname);
|
||||
} else if (!dev_manager_lv_mknodes(lvlayer->lv))
|
||||
r = 0;
|
||||
@@ -1010,11 +989,14 @@ static int _remove_lv_symlinks(struct dev_manager *dm, struct dm_tree_node *root
|
||||
int r = 1;
|
||||
|
||||
while ((child = dm_tree_next_child(&handle, root, 0))) {
|
||||
if (!dm_split_lvm_name(dm->mem, dm_tree_node_get_name(child), &vgname, &lvname, &layer)) {
|
||||
if (!dm_split_lvm_name(dm->mem, dm_tree_node_get_name(child), &vgname, &lvname, &layer)) {
|
||||
r = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!*vgname)
|
||||
continue;
|
||||
|
||||
/* only top level layer has symlinks */
|
||||
if (*layer)
|
||||
continue;
|
||||
@@ -1039,10 +1021,10 @@ static int _clean_tree(struct dev_manager *dm, struct dm_tree_node *root)
|
||||
if (!(uuid = dm_tree_node_get_uuid(child)))
|
||||
continue;
|
||||
|
||||
if (!dm_split_lvm_name(dm->mem, name, &vgname, &lvname, &layer)) {
|
||||
log_error("_clean_tree: Couldn't split up device name %s.", name);
|
||||
return 0;
|
||||
}
|
||||
if (!dm_split_lvm_name(dm->mem, name, &vgname, &lvname, &layer)) {
|
||||
log_error("_clean_tree: Couldn't split up device name %s.", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Not meant to be top level? */
|
||||
if (!*layer)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
@@ -138,7 +138,7 @@ static int _mk_link(const char *dev_dir, const char *vg_name,
|
||||
}
|
||||
|
||||
/* To reach this point, the VG must have been locked.
|
||||
* As locking fails if the VG is active under LVM1, it's
|
||||
* As locking fails if the VG is active under LVM1, it's
|
||||
* now safe to remove any LVM1 devices we find here
|
||||
* (as well as any existing LVM2 symlink). */
|
||||
if (!lstat(lvm1_group_path, &buf)) {
|
||||
@@ -175,10 +175,8 @@ static int _mk_link(const char *dev_dir, const char *vg_name,
|
||||
}
|
||||
|
||||
#ifdef HAVE_SELINUX
|
||||
if (!dm_set_selinux_context(lv_path, S_IFLNK)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!dm_set_selinux_context(lv_path, S_IFLNK))
|
||||
return_0;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
@@ -225,17 +223,13 @@ static int _do_fs_op(fs_op_t type, const char *dev_dir, const char *vg_name,
|
||||
switch (type) {
|
||||
case FS_ADD:
|
||||
if (!_mk_dir(dev_dir, vg_name) ||
|
||||
!_mk_link(dev_dir, vg_name, lv_name, dev)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
!_mk_link(dev_dir, vg_name, lv_name, dev))
|
||||
return_0;
|
||||
break;
|
||||
case FS_DEL:
|
||||
if (!_rm_link(dev_dir, vg_name, lv_name) ||
|
||||
!_rm_dir(dev_dir, vg_name)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
!_rm_dir(dev_dir, vg_name))
|
||||
return_0;
|
||||
break;
|
||||
/* FIXME Use rename() */
|
||||
case FS_RENAME:
|
||||
@@ -316,10 +310,8 @@ static int _fs_op(fs_op_t type, const char *dev_dir, const char *vg_name,
|
||||
{
|
||||
if (memlock()) {
|
||||
if (!_stack_fs_op(type, dev_dir, vg_name, lv_name, dev,
|
||||
old_lv_name)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
old_lv_name))
|
||||
return_0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
567
lib/cache/lvmcache.c
vendored
567
lib/cache/lvmcache.c
vendored
@@ -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) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@@ -17,18 +17,24 @@
|
||||
#include "lvmcache.h"
|
||||
#include "toolcontext.h"
|
||||
#include "dev-cache.h"
|
||||
#include "locking.h"
|
||||
#include "metadata.h"
|
||||
#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? */
|
||||
|
||||
int lvmcache_init(void)
|
||||
{
|
||||
@@ -46,9 +52,125 @@ int lvmcache_init(void)
|
||||
if (!(_lock_hash = dm_hash_create(128)))
|
||||
return 0;
|
||||
|
||||
if (_vg_global_lock_held)
|
||||
lvmcache_lock_vgname(VG_GLOBAL, 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Volume Group metadata cache functions */
|
||||
static void _free_cached_vgmetadata(struct lvmcache_vginfo *vginfo)
|
||||
{
|
||||
if (!vginfo || !vginfo->vgmetadata)
|
||||
return;
|
||||
|
||||
dm_free(vginfo->vgmetadata);
|
||||
|
||||
vginfo->vgmetadata = NULL;
|
||||
|
||||
log_debug("Metadata cache: VG %s wiped.", vginfo->vgname);
|
||||
}
|
||||
|
||||
static void _store_metadata(struct lvmcache_vginfo *vginfo,
|
||||
struct volume_group *vg, unsigned precommitted)
|
||||
{
|
||||
int size;
|
||||
|
||||
if (vginfo->vgmetadata)
|
||||
_free_cached_vgmetadata(vginfo);
|
||||
|
||||
if (!(size = export_vg_to_buffer(vg, &vginfo->vgmetadata))) {
|
||||
stack;
|
||||
return;
|
||||
}
|
||||
|
||||
vginfo->precommitted = precommitted;
|
||||
|
||||
log_debug("Metadata cache: VG %s stored (%d bytes%s).", vginfo->vgname,
|
||||
size, precommitted ? ", precommitted" : "");
|
||||
}
|
||||
|
||||
static void _update_cache_info_lock_state(struct lvmcache_info *info,
|
||||
int locked,
|
||||
int *cached_vgmetadata_valid)
|
||||
{
|
||||
int was_locked = (info->status & CACHE_LOCKED) ? 1 : 0;
|
||||
|
||||
/*
|
||||
* Cache becomes invalid whenever lock state changes unless
|
||||
* exclusive VG_GLOBAL is held (i.e. while scanning).
|
||||
*/
|
||||
if (!vgname_is_locked(VG_GLOBAL) && (was_locked != locked)) {
|
||||
info->status |= CACHE_INVALID;
|
||||
*cached_vgmetadata_valid = 0;
|
||||
}
|
||||
|
||||
if (locked)
|
||||
info->status |= CACHE_LOCKED;
|
||||
else
|
||||
info->status &= ~CACHE_LOCKED;
|
||||
}
|
||||
|
||||
static void _update_cache_vginfo_lock_state(struct lvmcache_vginfo *vginfo,
|
||||
int locked)
|
||||
{
|
||||
struct lvmcache_info *info;
|
||||
int cached_vgmetadata_valid = 1;
|
||||
|
||||
list_iterate_items(info, &vginfo->infos)
|
||||
_update_cache_info_lock_state(info, locked,
|
||||
&cached_vgmetadata_valid);
|
||||
|
||||
if (!cached_vgmetadata_valid)
|
||||
_free_cached_vgmetadata(vginfo);
|
||||
}
|
||||
|
||||
static void _update_cache_lock_state(const char *vgname, int locked)
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
|
||||
if (!(vginfo = vginfo_from_vgname(vgname, NULL)))
|
||||
return;
|
||||
|
||||
_update_cache_vginfo_lock_state(vginfo, locked);
|
||||
}
|
||||
|
||||
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()) {
|
||||
@@ -56,10 +178,17 @@ void lvmcache_lock_vgname(const char *vgname, int read_only __attribute((unused)
|
||||
return;
|
||||
}
|
||||
|
||||
if (dm_hash_lookup(_lock_hash, vgname))
|
||||
log_error("Internal error: Nested locking attempted on VG %s.",
|
||||
vgname);
|
||||
|
||||
if (!dm_hash_insert(_lock_hash, vgname, (void *) 1))
|
||||
log_error("Cache locking failure for %s", vgname);
|
||||
|
||||
_vgs_locked++;
|
||||
_update_cache_lock_state(vgname, 1);
|
||||
|
||||
if (strcmp(vgname, VG_GLOBAL))
|
||||
_vgs_locked++;
|
||||
}
|
||||
|
||||
int vgname_is_locked(const char *vgname)
|
||||
@@ -72,11 +201,16 @@ int vgname_is_locked(const char *vgname)
|
||||
|
||||
void lvmcache_unlock_vgname(const char *vgname)
|
||||
{
|
||||
/* FIXME: Clear all CACHE_LOCKED flags in this vg */
|
||||
if (!dm_hash_lookup(_lock_hash, vgname))
|
||||
log_error("Internal error: Attempt to unlock unlocked VG %s.",
|
||||
vgname);
|
||||
|
||||
_update_cache_lock_state(vgname, 0);
|
||||
|
||||
dm_hash_remove(_lock_hash, vgname);
|
||||
|
||||
/* FIXME Do this per-VG */
|
||||
if (!--_vgs_locked)
|
||||
if (strcmp(vgname, VG_GLOBAL) && !--_vgs_locked)
|
||||
dev_close_all();
|
||||
}
|
||||
|
||||
@@ -85,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;
|
||||
|
||||
@@ -97,7 +254,7 @@ struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname, const char *vgid)
|
||||
return NULL;
|
||||
|
||||
if (vgid)
|
||||
do
|
||||
do
|
||||
if (!strncmp(vgid, vginfo->vgid, ID_LEN))
|
||||
return vginfo;
|
||||
while ((vginfo = vginfo->next));
|
||||
@@ -170,9 +327,6 @@ const char *vgname_from_vgid(struct dm_pool *mem, const char *vgid)
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
const char *vgname = NULL;
|
||||
|
||||
if (!*vgid)
|
||||
vgname = ORPHAN;
|
||||
|
||||
if ((vginfo = vginfo_from_vgid(vgid)))
|
||||
vgname = vginfo->vgname;
|
||||
|
||||
@@ -182,7 +336,56 @@ const char *vgname_from_vgid(struct dm_pool *mem, const char *vgid)
|
||||
return vgname;
|
||||
}
|
||||
|
||||
struct lvmcache_info *info_from_pvid(const char *pvid)
|
||||
static int _info_is_valid(struct lvmcache_info *info)
|
||||
{
|
||||
if (info->status & CACHE_INVALID)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* The caller must hold the VG lock to manipulate metadata.
|
||||
* In a cluster, remote nodes sometimes read metadata in the
|
||||
* knowledge that the controlling node is holding the lock.
|
||||
* So if the VG appears to be unlocked here, it should be safe
|
||||
* to use the cached value.
|
||||
*/
|
||||
if (info->vginfo && !vgname_is_locked(info->vginfo->vgname))
|
||||
return 1;
|
||||
|
||||
if (!(info->status & CACHE_LOCKED))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _vginfo_is_valid(struct lvmcache_vginfo *vginfo)
|
||||
{
|
||||
struct lvmcache_info *info;
|
||||
|
||||
/* Invalid if any info is invalid */
|
||||
list_iterate_items(info, &vginfo->infos)
|
||||
if (!_info_is_valid(info))
|
||||
return 0;
|
||||
|
||||
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.
|
||||
*/
|
||||
struct lvmcache_info *info_from_pvid(const char *pvid, int valid_only)
|
||||
{
|
||||
struct lvmcache_info *info;
|
||||
char id[ID_LEN + 1] __attribute((aligned(8)));
|
||||
@@ -196,6 +399,9 @@ struct lvmcache_info *info_from_pvid(const char *pvid)
|
||||
if (!(info = dm_hash_lookup(_pvid_hash, id)))
|
||||
return NULL;
|
||||
|
||||
if (valid_only && !_info_is_valid(info))
|
||||
return NULL;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
@@ -221,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! */
|
||||
@@ -266,6 +471,51 @@ int lvmcache_label_scan(struct cmd_context *cmd, int full_scan)
|
||||
return r;
|
||||
}
|
||||
|
||||
struct volume_group *lvmcache_get_vg(const char *vgid, unsigned precommitted)
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
struct volume_group *vg;
|
||||
struct format_instance *fid;
|
||||
|
||||
if (!vgid || !(vginfo = vginfo_from_vgid(vgid)) || !vginfo->vgmetadata)
|
||||
return NULL;
|
||||
|
||||
if (!_vginfo_is_valid(vginfo))
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* 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 && !memlock()))
|
||||
return NULL;
|
||||
|
||||
if (!(fid = vginfo->fmt->ops->create_instance(vginfo->fmt,
|
||||
vginfo->vgname,
|
||||
vgid, NULL)))
|
||||
return_NULL;
|
||||
|
||||
if (!(vg = import_vg_from_buffer(vginfo->vgmetadata, fid)) ||
|
||||
!vg_validate(vg)) {
|
||||
_free_cached_vgmetadata(vginfo);
|
||||
return_NULL;
|
||||
}
|
||||
|
||||
log_debug("Using cached %smetadata for VG %s.",
|
||||
vginfo->precommitted ? "pre-committed" : "", vginfo->vgname);
|
||||
|
||||
return vg;
|
||||
}
|
||||
|
||||
struct list *lvmcache_get_vgids(struct cmd_context *cmd, int full_scan)
|
||||
{
|
||||
struct list *vgids;
|
||||
@@ -279,7 +529,7 @@ struct list *lvmcache_get_vgids(struct cmd_context *cmd, int full_scan)
|
||||
}
|
||||
|
||||
list_iterate_items(vginfo, &_vginfos) {
|
||||
if (!str_list_add(cmd->mem, vgids,
|
||||
if (!str_list_add(cmd->mem, vgids,
|
||||
dm_pool_strdup(cmd->mem, vginfo->vgid))) {
|
||||
log_error("strlist allocation failed");
|
||||
return NULL;
|
||||
@@ -302,7 +552,7 @@ struct list *lvmcache_get_vgnames(struct cmd_context *cmd, int full_scan)
|
||||
}
|
||||
|
||||
list_iterate_items(vginfo, &_vginfos) {
|
||||
if (!str_list_add(cmd->mem, vgnames,
|
||||
if (!str_list_add(cmd->mem, vgnames,
|
||||
dm_pool_strdup(cmd->mem, vginfo->vgname))) {
|
||||
log_error("strlist allocation failed");
|
||||
return NULL;
|
||||
@@ -328,7 +578,7 @@ struct list *lvmcache_get_pvids(struct cmd_context *cmd, const char *vgname,
|
||||
return pvids;
|
||||
|
||||
list_iterate_items(info, &vginfo->infos) {
|
||||
if (!str_list_add(cmd->mem, pvids,
|
||||
if (!str_list_add(cmd->mem, pvids,
|
||||
dm_pool_strdup(cmd->mem, info->dev->pvid))) {
|
||||
log_error("strlist allocation failed");
|
||||
return NULL;
|
||||
@@ -344,7 +594,7 @@ struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
|
||||
struct lvmcache_info *info;
|
||||
|
||||
/* Already cached ? */
|
||||
if ((info = info_from_pvid((char *) pvid))) {
|
||||
if ((info = info_from_pvid((char *) pvid, 0))) {
|
||||
if (label_read(info->dev, &label, UINT64_C(0))) {
|
||||
info = (struct lvmcache_info *) label->info;
|
||||
if (id_equal(pvid, (struct id *) &info->dev->pvid))
|
||||
@@ -355,7 +605,7 @@ struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
|
||||
lvmcache_label_scan(cmd, 0);
|
||||
|
||||
/* Try again */
|
||||
if ((info = info_from_pvid((char *) pvid))) {
|
||||
if ((info = info_from_pvid((char *) pvid, 0))) {
|
||||
if (label_read(info->dev, &label, UINT64_C(0))) {
|
||||
info = (struct lvmcache_info *) label->info;
|
||||
if (id_equal(pvid, (struct id *) &info->dev->pvid))
|
||||
@@ -369,7 +619,7 @@ struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
|
||||
lvmcache_label_scan(cmd, 2);
|
||||
|
||||
/* Try again */
|
||||
if ((info = info_from_pvid((char *) pvid))) {
|
||||
if ((info = info_from_pvid((char *) pvid, 0))) {
|
||||
if (label_read(info->dev, &label, UINT64_C(0))) {
|
||||
info = (struct lvmcache_info *) label->info;
|
||||
if (id_equal(pvid, (struct id *) &info->dev->pvid))
|
||||
@@ -380,34 +630,62 @@ struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int _drop_vginfo(struct lvmcache_info *info)
|
||||
static int _free_vginfo(struct lvmcache_vginfo *vginfo)
|
||||
{
|
||||
if (!list_empty(&info->list)) {
|
||||
list_del(&info->list);
|
||||
list_init(&info->list);
|
||||
}
|
||||
struct lvmcache_vginfo *primary_vginfo, *vginfo2;
|
||||
int r = 1;
|
||||
|
||||
if (info->vginfo && list_empty(&info->vginfo->infos)) {
|
||||
dm_hash_remove(_vgname_hash, info->vginfo->vgname);
|
||||
if (info->vginfo->next) {
|
||||
if (!dm_hash_insert(_vgname_hash, info->vginfo->vgname, info->vginfo->next)) {
|
||||
log_error("vg hash re-insertion failed: %s",
|
||||
info->vginfo->vgname);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
_free_cached_vgmetadata(vginfo);
|
||||
|
||||
if (info->vginfo->vgname)
|
||||
dm_free(info->vginfo->vgname);
|
||||
if (info->vginfo->creation_host)
|
||||
dm_free(info->vginfo->creation_host);
|
||||
if (*info->vginfo->vgid)
|
||||
dm_hash_remove(_vgid_hash, info->vginfo->vgid);
|
||||
list_del(&info->vginfo->list);
|
||||
dm_free(info->vginfo);
|
||||
}
|
||||
vginfo2 = primary_vginfo = vginfo_from_vgname(vginfo->vgname, NULL);
|
||||
|
||||
info->vginfo = 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)
|
||||
_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;
|
||||
}
|
||||
@@ -418,10 +696,10 @@ void lvmcache_del(struct lvmcache_info *info)
|
||||
if (info->dev->pvid[0] && _pvid_hash)
|
||||
dm_hash_remove(_pvid_hash, info->dev->pvid);
|
||||
|
||||
_drop_vginfo(info);
|
||||
_drop_vginfo(info, info->vginfo);
|
||||
|
||||
info->label->labeller->ops->destroy_label(info->label->labeller,
|
||||
info->label);
|
||||
info->label);
|
||||
dm_free(info);
|
||||
|
||||
return;
|
||||
@@ -443,29 +721,36 @@ static int _lvmcache_update_pvid(struct lvmcache_info *info, const char *pvid)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _lvmcache_update_vgid(struct lvmcache_info *info, const char *vgid)
|
||||
/*
|
||||
* vginfo must be info->vginfo unless info is NULL (orphans)
|
||||
*/
|
||||
static int _lvmcache_update_vgid(struct lvmcache_info *info,
|
||||
struct lvmcache_vginfo *vginfo,
|
||||
const char *vgid)
|
||||
{
|
||||
if (!vgid || !info->vginfo ||
|
||||
!strncmp(info->vginfo->vgid, vgid, ID_LEN))
|
||||
if (!vgid || !vginfo ||
|
||||
!strncmp(vginfo->vgid, vgid, ID_LEN))
|
||||
return 1;
|
||||
|
||||
if (info->vginfo && *info->vginfo->vgid)
|
||||
dm_hash_remove(_vgid_hash, info->vginfo->vgid);
|
||||
if (vginfo && *vginfo->vgid)
|
||||
dm_hash_remove(_vgid_hash, vginfo->vgid);
|
||||
if (!vgid) {
|
||||
log_debug("lvmcache: %s: clearing VGID", dev_name(info->dev));
|
||||
log_debug("lvmcache: %s: clearing VGID", info ? dev_name(info->dev) : vginfo->vgname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
strncpy(info->vginfo->vgid, vgid, ID_LEN);
|
||||
info->vginfo->vgid[ID_LEN] = '\0';
|
||||
if (!dm_hash_insert(_vgid_hash, info->vginfo->vgid, info->vginfo)) {
|
||||
strncpy(vginfo->vgid, vgid, ID_LEN);
|
||||
vginfo->vgid[ID_LEN] = '\0';
|
||||
if (!dm_hash_insert(_vgid_hash, vginfo->vgid, vginfo)) {
|
||||
log_error("_lvmcache_update: vgid hash insertion failed: %s",
|
||||
info->vginfo->vgid);
|
||||
vginfo->vgid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_debug("lvmcache: %s: setting %s VGID to %s", dev_name(info->dev),
|
||||
info->vginfo->vgname, info->vginfo->vgid);
|
||||
if (!is_orphan_vg(vginfo->vgname))
|
||||
log_debug("lvmcache: %s: setting %s VGID to %s",
|
||||
dev_name(info->dev), vginfo->vgname,
|
||||
vginfo->vgid);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -556,25 +841,20 @@ static int _insert_vginfo(struct lvmcache_vginfo *new_vginfo, const char *vgid,
|
||||
|
||||
static int _lvmcache_update_vgname(struct lvmcache_info *info,
|
||||
const char *vgname, const char *vgid,
|
||||
uint32_t vgstatus, const char *creation_host)
|
||||
uint32_t vgstatus, const char *creation_host,
|
||||
const struct format_type *fmt)
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo, *primary_vginfo;
|
||||
struct lvmcache_vginfo *vginfo, *primary_vginfo, *orphan_vginfo;
|
||||
struct lvmcache_info *info2, *info3;
|
||||
char mdabuf[32];
|
||||
// struct lvmcache_vginfo *old_vginfo, *next;
|
||||
|
||||
/* If vgname is NULL and we don't already have a vgname,
|
||||
* assume ORPHAN - we want every entry to have a vginfo
|
||||
* attached for scanning reasons.
|
||||
*/
|
||||
if (!vgname && !info->vginfo) {
|
||||
vgname = ORPHAN;
|
||||
vgid = ORPHAN;
|
||||
}
|
||||
|
||||
if (!vgname || (info->vginfo && !strcmp(info->vginfo->vgname, vgname)))
|
||||
if (!vgname || (info && info->vginfo && !strcmp(info->vginfo->vgname, vgname)))
|
||||
return 1;
|
||||
|
||||
/* Remove existing vginfo entry */
|
||||
_drop_vginfo(info);
|
||||
if (info)
|
||||
_drop_vginfo(info, info->vginfo);
|
||||
|
||||
/* Get existing vginfo or create new one */
|
||||
if (!(vginfo = vginfo_from_vgname(vgname, vgid))) {
|
||||
@@ -587,9 +867,9 @@ static int _lvmcache_update_vgname(struct lvmcache_info *info,
|
||||
dm_hash_remove(_vgname_hash, old_vginfo->vgname);
|
||||
if (old_vginfo->next) {
|
||||
if (!dm_hash_insert(_vgname_hash, old_vginfo->vgname, old_vginfo->next)) {
|
||||
log_error("vg hash re-insertion failed: %s",
|
||||
log_error("vg hash re-insertion failed: %s",
|
||||
old_vginfo->vgname);
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} else do {
|
||||
@@ -606,11 +886,11 @@ static int _lvmcache_update_vgname(struct lvmcache_info *info,
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Rename so can assume new name does not already exist
|
||||
// Rename so can assume new name does not already exist
|
||||
if (!dm_hash_insert(_vgname_hash, vginfo->vgname, vginfo->next)) {
|
||||
log_error("vg hash re-insertion failed: %s",
|
||||
vginfo->vgname);
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
***/
|
||||
@@ -625,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);
|
||||
@@ -642,17 +944,28 @@ static int _lvmcache_update_vgname(struct lvmcache_info *info,
|
||||
***/
|
||||
}
|
||||
|
||||
info->vginfo = vginfo;
|
||||
list_add(&vginfo->infos, &info->list);
|
||||
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));
|
||||
|
||||
/* FIXME Check consistency of list! */
|
||||
vginfo->fmt = info->fmt;
|
||||
vginfo->fmt = fmt;
|
||||
|
||||
log_debug("lvmcache: %s: now %s%s%s%s%s", dev_name(info->dev),
|
||||
!is_orphan_vg(vgname) ? "in VG " : "orphaned", vgname,
|
||||
vginfo->vgid[0] ? " (" : "",
|
||||
vginfo->vgid[0] ? vginfo->vgid : "",
|
||||
vginfo->vgid[0] ? ")" : "");
|
||||
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] ? ")" : "", mdabuf);
|
||||
} else
|
||||
log_debug("lvmcache: initialised VG %s", vgname);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -692,23 +1005,50 @@ static int _lvmcache_update_vgstatus(struct lvmcache_info *info, uint32_t vgstat
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lvmcache_add_orphan_vginfo(const char *vgname, struct format_type *fmt)
|
||||
{
|
||||
if (!_lock_hash && !lvmcache_init()) {
|
||||
log_error("Internal cache initialisation failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _lvmcache_update_vgname(NULL, vgname, vgname, 0, "", fmt);
|
||||
}
|
||||
|
||||
int lvmcache_update_vgname_and_id(struct lvmcache_info *info,
|
||||
const char *vgname, const char *vgid,
|
||||
uint32_t vgstatus, const char *creation_host)
|
||||
{
|
||||
if (!vgname && !info->vginfo) {
|
||||
log_error("Internal error: NULL vgname handed to cache");
|
||||
/* FIXME Remove this */
|
||||
vgname = info->fmt->orphan_vg_name;
|
||||
vgid = vgname;
|
||||
}
|
||||
|
||||
/* If 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) ||
|
||||
!_lvmcache_update_vgid(info, vgid) ||
|
||||
creation_host, info->fmt) ||
|
||||
!_lvmcache_update_vgid(info, info->vginfo, vgid) ||
|
||||
!_lvmcache_update_vgstatus(info, vgstatus, creation_host))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lvmcache_update_vg(struct volume_group *vg)
|
||||
int lvmcache_update_vg(struct volume_group *vg, unsigned precommitted)
|
||||
{
|
||||
struct pv_list *pvl;
|
||||
struct lvmcache_info *info;
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
char pvid_s[ID_LEN + 1] __attribute((aligned(8)));
|
||||
|
||||
pvid_s[sizeof(pvid_s) - 1] = '\0';
|
||||
@@ -716,13 +1056,18 @@ int lvmcache_update_vg(struct volume_group *vg)
|
||||
list_iterate_items(pvl, &vg->pvs) {
|
||||
strncpy(pvid_s, (char *) &pvl->pv->id, sizeof(pvid_s) - 1);
|
||||
/* FIXME Could pvl->pv->dev->pvid ever be different? */
|
||||
if ((info = info_from_pvid(pvid_s)) &&
|
||||
if ((info = info_from_pvid(pvid_s, 0)) &&
|
||||
!lvmcache_update_vgname_and_id(info, vg->name,
|
||||
(char *) &vg->id,
|
||||
vg->status, NULL))
|
||||
return_0;
|
||||
}
|
||||
|
||||
/* store text representation of vg to cache */
|
||||
if (vg->cmd->current_settings.cache_vgmetadata &&
|
||||
(vginfo = vginfo_from_vgname(vg->name, NULL)))
|
||||
_store_metadata(vginfo, vg, precommitted);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -743,12 +1088,10 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
|
||||
strncpy(pvid_s, pvid, sizeof(pvid_s));
|
||||
pvid_s[sizeof(pvid_s) - 1] = '\0';
|
||||
|
||||
if (!(existing = info_from_pvid(pvid_s)) &&
|
||||
!(existing = info_from_pvid(dev->pvid))) {
|
||||
if (!(label = label_create(labeller))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!(existing = info_from_pvid(pvid_s, 0)) &&
|
||||
!(existing = info_from_pvid(dev->pvid, 0))) {
|
||||
if (!(label = label_create(labeller)))
|
||||
return_NULL;
|
||||
if (!(info = dm_malloc(sizeof(*info)))) {
|
||||
log_error("lvmcache_info allocation failed");
|
||||
label_destroy(label);
|
||||
@@ -804,11 +1147,9 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
|
||||
/* Has labeller changed? */
|
||||
if (info->label->labeller != labeller) {
|
||||
label_destroy(info->label);
|
||||
if (!(info->label = label_create(labeller))) {
|
||||
if (!(info->label = label_create(labeller)))
|
||||
/* FIXME leaves info without label! */
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
return_NULL;
|
||||
info->label->info = info;
|
||||
}
|
||||
label = info->label;
|
||||
@@ -840,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);
|
||||
@@ -853,21 +1193,30 @@ 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);
|
||||
dm_free(vginfo);
|
||||
if (!_free_vginfo(vginfo))
|
||||
stack;
|
||||
} while ((vginfo = next));
|
||||
}
|
||||
|
||||
static void _lvmcache_destroy_lockname(int present __attribute((unused)))
|
||||
static void _lvmcache_destroy_lockname(struct dm_hash_node *n)
|
||||
{
|
||||
/* Nothing to do */
|
||||
char *vgname;
|
||||
|
||||
if (!dm_hash_get_data(_lock_hash, n))
|
||||
return;
|
||||
|
||||
vgname = dm_hash_get_key(_lock_hash, n);
|
||||
|
||||
if (!strcmp(vgname, VG_GLOBAL))
|
||||
_vg_global_lock_held = 1;
|
||||
else
|
||||
log_error("Internal error: Volume Group %s was not unlocked",
|
||||
dm_hash_get_key(_lock_hash, n));
|
||||
}
|
||||
|
||||
void lvmcache_destroy(void)
|
||||
void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans)
|
||||
{
|
||||
struct dm_hash_node *n;
|
||||
log_verbose("Wiping internal VG cache");
|
||||
|
||||
_has_scanned = 0;
|
||||
@@ -891,10 +1240,16 @@ void lvmcache_destroy(void)
|
||||
}
|
||||
|
||||
if (_lock_hash) {
|
||||
dm_hash_iter(_lock_hash, (dm_hash_iterate_fn) _lvmcache_destroy_lockname);
|
||||
dm_hash_iterate(n, _lock_hash)
|
||||
_lvmcache_destroy_lockname(n);
|
||||
dm_hash_destroy(_lock_hash);
|
||||
_lock_hash = NULL;
|
||||
}
|
||||
|
||||
if (!list_empty(&_vginfos))
|
||||
log_error("Internal error: _vginfos list should be empty");
|
||||
list_init(&_vginfos);
|
||||
|
||||
if (retain_orphans)
|
||||
init_lvmcache_orphans(cmd);
|
||||
}
|
||||
|
||||
18
lib/cache/lvmcache.h
vendored
18
lib/cache/lvmcache.h
vendored
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@@ -20,7 +20,8 @@
|
||||
#include "uuid.h"
|
||||
#include "label.h"
|
||||
|
||||
#define ORPHAN ""
|
||||
#define ORPHAN_PREFIX "#"
|
||||
#define ORPHAN_VG_NAME(fmt) ORPHAN_PREFIX "orphans_" fmt
|
||||
|
||||
#define CACHE_INVALID 0x00000001
|
||||
#define CACHE_LOCKED 0x00000002
|
||||
@@ -43,6 +44,8 @@ struct lvmcache_vginfo {
|
||||
char _padding[7];
|
||||
struct lvmcache_vginfo *next; /* Another VG with same name? */
|
||||
char *creation_host;
|
||||
char *vgmetadata; /* Copy of VG metadata as format_text string */
|
||||
unsigned precommitted; /* Is vgmetadata live or precommitted? */
|
||||
};
|
||||
|
||||
/* One per device */
|
||||
@@ -59,7 +62,7 @@ struct lvmcache_info {
|
||||
};
|
||||
|
||||
int lvmcache_init(void);
|
||||
void lvmcache_destroy(void);
|
||||
void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans);
|
||||
|
||||
/* Set full_scan to 1 to reread every filtered device label or
|
||||
* 2 to rescan /dev for new devices */
|
||||
@@ -70,13 +73,14 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
|
||||
struct device *dev,
|
||||
const char *vgname, const char *vgid,
|
||||
uint32_t vgstatus);
|
||||
int lvmcache_add_orphan_vginfo(const char *vgname, struct format_type *fmt);
|
||||
void lvmcache_del(struct lvmcache_info *info);
|
||||
|
||||
/* Update things */
|
||||
int lvmcache_update_vgname_and_id(struct lvmcache_info *info,
|
||||
const char *vgname, const char *vgid,
|
||||
uint32_t vgstatus, const char *hostname);
|
||||
int lvmcache_update_vg(struct volume_group *vg);
|
||||
int lvmcache_update_vg(struct volume_group *vg, unsigned precommitted);
|
||||
|
||||
void lvmcache_lock_vgname(const char *vgname, int read_only);
|
||||
void lvmcache_unlock_vgname(const char *vgname);
|
||||
@@ -86,7 +90,7 @@ const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid);
|
||||
struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname,
|
||||
const char *vgid);
|
||||
struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid);
|
||||
struct lvmcache_info *info_from_pvid(const char *pvid);
|
||||
struct lvmcache_info *info_from_pvid(const char *pvid, int valid_only);
|
||||
const char *vgname_from_vgid(struct dm_pool *mem, const char *vgid);
|
||||
struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid);
|
||||
int vgs_locked(void);
|
||||
@@ -104,4 +108,8 @@ struct list *lvmcache_get_vgids(struct cmd_context *cmd, int full_scan);
|
||||
struct list *lvmcache_get_pvids(struct cmd_context *cmd, const char *vgname,
|
||||
const char *vgid);
|
||||
|
||||
/* Returns cached volume group metadata. */
|
||||
struct volume_group *lvmcache_get_vg(const char *vgid, unsigned precommitted);
|
||||
void lvmcache_drop_metadata(const char *vgname);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
@@ -282,10 +282,8 @@ static int _init_tags(struct cmd_context *cmd, struct config_tree *cft)
|
||||
if (!cmd->hosttags && find_config_int(cft->root, "tags/hosttags",
|
||||
DEFAULT_HOSTTAGS)) {
|
||||
/* FIXME Strip out invalid chars: only A-Za-z0-9_+.- */
|
||||
if (!_set_tag(cmd, cmd->hostname)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!_set_tag(cmd, cmd->hostname))
|
||||
return_0;
|
||||
cmd->hosttags = 1;
|
||||
}
|
||||
|
||||
@@ -301,17 +299,13 @@ static int _init_tags(struct cmd_context *cmd, struct config_tree *cft)
|
||||
}
|
||||
if (cn->child) {
|
||||
passes = 0;
|
||||
if (!_check_host_filters(cmd, cn->child, &passes)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!_check_host_filters(cmd, cn->child, &passes))
|
||||
return_0;
|
||||
if (!passes)
|
||||
continue;
|
||||
}
|
||||
if (!_set_tag(cmd, tag)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!_set_tag(cmd, tag))
|
||||
return_0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -385,10 +379,8 @@ static int _init_lvm_conf(struct cmd_context *cmd)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!_load_config_file(cmd, "")) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!_load_config_file(cmd, ""))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -400,11 +392,8 @@ static int _init_tag_configs(struct cmd_context *cmd)
|
||||
|
||||
/* Tag list may grow while inside this loop */
|
||||
list_iterate_items(sl, &cmd->tags) {
|
||||
if (!_load_config_file(cmd, sl->str)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!_load_config_file(cmd, sl->str))
|
||||
return_0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -424,10 +413,8 @@ static int _merge_config_files(struct cmd_context *cmd)
|
||||
|
||||
list_iterate_items(cfl, &cmd->config_files) {
|
||||
/* Merge all config trees into cmd->cft using merge/tag rules */
|
||||
if (!merge_config_tree(cmd, cmd->cft, cfl->cft)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!merge_config_tree(cmd, cmd->cft, cfl->cft))
|
||||
return_0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -542,7 +529,7 @@ static struct dev_filter *_init_filter_components(struct cmd_context *cmd)
|
||||
|
||||
/*
|
||||
* sysfs filter. Only available on 2.6 kernels. Non-critical.
|
||||
* Listed first because it's very efficient at eliminating
|
||||
* Listed first because it's very efficient at eliminating
|
||||
* unavailable devices.
|
||||
*/
|
||||
if (find_config_tree_bool(cmd, "devices/sysfs_scan",
|
||||
@@ -694,10 +681,8 @@ static int _init_formats(struct cmd_context *cmd)
|
||||
return 0;
|
||||
}
|
||||
if (!(lib = load_shared_library(cmd, cv->v.str,
|
||||
"format", 0))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
"format", 0)))
|
||||
return_0;
|
||||
|
||||
if (!(init_format_fn = dlsym(lib, "init_format"))) {
|
||||
log_error("Shared library %s does not contain "
|
||||
@@ -736,6 +721,17 @@ static int _init_formats(struct cmd_context *cmd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int init_lvmcache_orphans(struct cmd_context *cmd)
|
||||
{
|
||||
struct format_type *fmt;
|
||||
|
||||
list_iterate_items(fmt, &cmd->formats)
|
||||
if (!lvmcache_add_orphan_vginfo(fmt->orphan_vg_name, fmt))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _init_segtypes(struct cmd_context *cmd)
|
||||
{
|
||||
struct segment_type *segtype;
|
||||
@@ -759,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;
|
||||
@@ -790,10 +791,8 @@ static int _init_segtypes(struct cmd_context *cmd)
|
||||
return 0;
|
||||
}
|
||||
if (!(lib = load_shared_library(cmd, cv->v.str,
|
||||
"segment type", 0))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
"segment type", 0)))
|
||||
return_0;
|
||||
|
||||
if (!(init_segtype_fn = dlsym(lib, "init_segtype"))) {
|
||||
log_error("Shared library %s does not contain "
|
||||
@@ -998,12 +997,16 @@ struct cmd_context *create_toolcontext(struct arg *the_args, unsigned is_static,
|
||||
if (!_init_formats(cmd))
|
||||
goto error;
|
||||
|
||||
if (!init_lvmcache_orphans(cmd))
|
||||
goto error;
|
||||
|
||||
if (!_init_segtypes(cmd))
|
||||
goto error;
|
||||
|
||||
if (!_init_backup(cmd))
|
||||
goto error;
|
||||
|
||||
cmd->default_settings.cache_vgmetadata = 1;
|
||||
cmd->current_settings = cmd->default_settings;
|
||||
|
||||
cmd->config_valid = 1;
|
||||
@@ -1060,7 +1063,7 @@ int refresh_toolcontext(struct cmd_context *cmd)
|
||||
*/
|
||||
|
||||
activation_release();
|
||||
lvmcache_destroy();
|
||||
lvmcache_destroy(cmd, 0);
|
||||
label_exit();
|
||||
_destroy_segtypes(&cmd->segtypes);
|
||||
_destroy_formats(&cmd->formats);
|
||||
@@ -1102,6 +1105,9 @@ int refresh_toolcontext(struct cmd_context *cmd)
|
||||
if (!_init_formats(cmd))
|
||||
return 0;
|
||||
|
||||
if (!init_lvmcache_orphans(cmd))
|
||||
return 0;
|
||||
|
||||
if (!_init_segtypes(cmd))
|
||||
return 0;
|
||||
|
||||
@@ -1123,7 +1129,7 @@ void destroy_toolcontext(struct cmd_context *cmd)
|
||||
|
||||
archive_exit(cmd);
|
||||
backup_exit(cmd);
|
||||
lvmcache_destroy();
|
||||
lvmcache_destroy(cmd, 0);
|
||||
label_exit();
|
||||
_destroy_segtypes(&cmd->segtypes);
|
||||
_destroy_formats(&cmd->formats);
|
||||
|
||||
@@ -34,6 +34,7 @@ struct config_info {
|
||||
int archive; /* should we archive ? */
|
||||
int backup; /* should we backup ? */
|
||||
int read_ahead; /* DM_READ_AHEAD_NONE or _AUTO */
|
||||
int cache_vgmetadata;
|
||||
const char *msg_prefix;
|
||||
struct format_type *fmt;
|
||||
uint64_t unit_factor;
|
||||
@@ -94,5 +95,6 @@ struct cmd_context *create_toolcontext(struct arg *the_args, unsigned is_static,
|
||||
void destroy_toolcontext(struct cmd_context *cmd);
|
||||
int refresh_toolcontext(struct cmd_context *cmd);
|
||||
int config_files_changed(struct cmd_context *cmd);
|
||||
int init_lvmcache_orphans(struct cmd_context *cmd);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -34,7 +34,8 @@
|
||||
enum {
|
||||
TOK_INT,
|
||||
TOK_FLOAT,
|
||||
TOK_STRING,
|
||||
TOK_STRING, /* Single quotes */
|
||||
TOK_STRING_ESCAPED, /* Double quotes */
|
||||
TOK_EQ,
|
||||
TOK_SECTION_B,
|
||||
TOK_SECTION_E,
|
||||
@@ -196,10 +197,8 @@ int read_config_fd(struct config_tree *cft, struct device *dev,
|
||||
off_t mmap_offset = 0;
|
||||
char *buf = NULL;
|
||||
|
||||
if (!(p = dm_pool_alloc(c->mem, sizeof(*p)))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(p = dm_pool_alloc(c->mem, sizeof(*p))))
|
||||
return_0;
|
||||
p->mem = c->mem;
|
||||
|
||||
/* Only use mmap with regular files */
|
||||
@@ -217,10 +216,8 @@ int read_config_fd(struct config_tree *cft, struct device *dev,
|
||||
}
|
||||
p->fb = p->fb + mmap_offset;
|
||||
} else {
|
||||
if (!(buf = dm_malloc(size + size2))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(buf = dm_malloc(size + size2)))
|
||||
return_0;
|
||||
if (!dev_read_circular(dev, (uint64_t) offset, size,
|
||||
(uint64_t) offset2, size2, buf)) {
|
||||
goto out;
|
||||
@@ -237,10 +234,8 @@ int read_config_fd(struct config_tree *cft, struct device *dev,
|
||||
|
||||
p->fe = p->fb + size + size2;
|
||||
|
||||
if (!_parse_config_file(p, cft)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
if (!_parse_config_file(p, cft))
|
||||
goto_out;
|
||||
|
||||
r = 1;
|
||||
|
||||
@@ -378,7 +373,7 @@ static int _line_append(struct output_line *outline, const char *fmt, ...)
|
||||
va_end(ap);
|
||||
|
||||
if (!dm_pool_grow_object(outline->mem, &buf[0], strlen(buf))) {
|
||||
log_error("dm_pool_grew_object failed for config line");
|
||||
log_error("dm_pool_grow_object failed for config line");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -407,9 +402,16 @@ static int _line_end(struct output_line *outline)
|
||||
|
||||
static int _write_value(struct output_line *outline, struct config_value *v)
|
||||
{
|
||||
char *buf;
|
||||
|
||||
switch (v->type) {
|
||||
case CFG_STRING:
|
||||
line_append("\"%s\"", v->v.str);
|
||||
if (!(buf = alloca(escaped_len(v->v.str)))) {
|
||||
log_error("temporary stack allocation for a config "
|
||||
"string failed");
|
||||
return 0;
|
||||
}
|
||||
line_append("\"%s\"", escape_double_quotes(buf, v->v.str));
|
||||
break;
|
||||
|
||||
case CFG_FLOAT:
|
||||
@@ -537,10 +539,8 @@ static struct config_node *_file(struct parser *p)
|
||||
{
|
||||
struct config_node *root = NULL, *n, *l = NULL;
|
||||
while (p->t != TOK_EOF) {
|
||||
if (!(n = _section(p))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(n = _section(p)))
|
||||
return_0;
|
||||
|
||||
if (!root)
|
||||
root = n;
|
||||
@@ -555,25 +555,19 @@ static struct config_node *_section(struct parser *p)
|
||||
{
|
||||
/* IDENTIFIER SECTION_B_CHAR VALUE* SECTION_E_CHAR */
|
||||
struct config_node *root, *n, *l = NULL;
|
||||
if (!(root = _create_node(p))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(root = _create_node(p)))
|
||||
return_0;
|
||||
|
||||
if (!(root->key = _dup_tok(p))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(root->key = _dup_tok(p)))
|
||||
return_0;
|
||||
|
||||
match(TOK_IDENTIFIER);
|
||||
|
||||
if (p->t == TOK_SECTION_B) {
|
||||
match(TOK_SECTION_B);
|
||||
while (p->t != TOK_SECTION_E) {
|
||||
if (!(n = _section(p))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(n = _section(p)))
|
||||
return_0;
|
||||
|
||||
if (!root->child)
|
||||
root->child = n;
|
||||
@@ -584,10 +578,8 @@ static struct config_node *_section(struct parser *p)
|
||||
match(TOK_SECTION_E);
|
||||
} else {
|
||||
match(TOK_EQ);
|
||||
if (!(root->v = _value(p))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(root->v = _value(p)))
|
||||
return_0;
|
||||
}
|
||||
|
||||
return root;
|
||||
@@ -600,10 +592,8 @@ static struct config_value *_value(struct parser *p)
|
||||
if (p->t == TOK_ARRAY_B) {
|
||||
match(TOK_ARRAY_B);
|
||||
while (p->t != TOK_ARRAY_E) {
|
||||
if (!(l = _type(p))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(l = _type(p)))
|
||||
return_0;
|
||||
|
||||
if (!h)
|
||||
h = l;
|
||||
@@ -656,14 +646,23 @@ static struct config_value *_type(struct parser *p)
|
||||
v->type = CFG_STRING;
|
||||
|
||||
p->tb++, p->te--; /* strip "'s */
|
||||
if (!(v->v.str = _dup_tok(p))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(v->v.str = _dup_tok(p)))
|
||||
return_0;
|
||||
p->te++;
|
||||
match(TOK_STRING);
|
||||
break;
|
||||
|
||||
case TOK_STRING_ESCAPED:
|
||||
v->type = CFG_STRING;
|
||||
|
||||
p->tb++, p->te--; /* strip "'s */
|
||||
if (!(v->v.str = _dup_tok(p)))
|
||||
return_0;
|
||||
unescape_double_quotes(v->v.str);
|
||||
p->te++;
|
||||
match(TOK_STRING_ESCAPED);
|
||||
break;
|
||||
|
||||
default:
|
||||
log_error("Parse error at byte %" PRIptrdiff_t " (line %d): expected a value",
|
||||
p->tb - p->fb + 1, p->line);
|
||||
@@ -734,7 +733,7 @@ static void _get_token(struct parser *p, int tok_prev)
|
||||
break;
|
||||
|
||||
case '"':
|
||||
p->t = TOK_STRING;
|
||||
p->t = TOK_STRING_ESCAPED;
|
||||
p->te++;
|
||||
while ((p->te != p->fe) && (*p->te) && (*p->te != '"')) {
|
||||
if ((*p->te == '\\') && (p->te + 1 != p->fe) &&
|
||||
@@ -799,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)) {
|
||||
@@ -847,10 +844,8 @@ static char *_dup_tok(struct parser *p)
|
||||
{
|
||||
size_t len = p->te - p->tb;
|
||||
char *str = dm_pool_alloc(p->mem, len + 1);
|
||||
if (!str) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!str)
|
||||
return_0;
|
||||
strncpy(str, p->tb, len);
|
||||
str[len] = '\0';
|
||||
return str;
|
||||
@@ -1016,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;
|
||||
|
||||
@@ -1029,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;
|
||||
@@ -1254,7 +1248,7 @@ static unsigned _count_tokens(const char *str, unsigned len, int type)
|
||||
|
||||
c = _token_type_to_char(type);
|
||||
|
||||
return count_chars_len(str, len, c);
|
||||
return count_chars(str, len, c);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1281,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"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
@@ -87,10 +87,8 @@ int btree_insert(struct btree *t, uint32_t k, void *data)
|
||||
struct node *p, **c = _lookup(&t->root, key, &p), *n;
|
||||
|
||||
if (!*c) {
|
||||
if (!(n = dm_pool_alloc(t->mem, sizeof(*n)))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(n = dm_pool_alloc(t->mem, sizeof(*n))))
|
||||
return_0;
|
||||
|
||||
n->key = key;
|
||||
n->data = data;
|
||||
|
||||
@@ -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?
|
||||
*/
|
||||
|
||||
@@ -54,6 +54,11 @@ void list_add_h(struct list *head, struct list *elem);
|
||||
*/
|
||||
void list_del(struct list *elem);
|
||||
|
||||
/*
|
||||
* Remove an element from existing list and insert before 'head'.
|
||||
*/
|
||||
void list_move(struct list *head, struct list *elem);
|
||||
|
||||
/*
|
||||
* Is the list empty?
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -20,10 +20,8 @@ struct list *str_list_create(struct dm_pool *mem)
|
||||
{
|
||||
struct list *sl;
|
||||
|
||||
if (!(sl = dm_pool_alloc(mem, sizeof(struct list)))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!(sl = dm_pool_alloc(mem, sizeof(struct list))))
|
||||
return_NULL;
|
||||
|
||||
list_init(sl);
|
||||
|
||||
@@ -34,19 +32,15 @@ int str_list_add(struct dm_pool *mem, struct list *sll, const char *str)
|
||||
{
|
||||
struct str_list *sln;
|
||||
|
||||
if (!str) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!str)
|
||||
return_0;
|
||||
|
||||
/* Already in list? */
|
||||
if (str_list_match_item(sll, str))
|
||||
return 1;
|
||||
|
||||
if (!(sln = dm_pool_alloc(mem, sizeof(*sln)))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(sln = dm_pool_alloc(mem, sizeof(*sln))))
|
||||
return_0;
|
||||
|
||||
sln->str = str;
|
||||
list_add(sll, &sln->list);
|
||||
@@ -74,10 +68,8 @@ int str_list_dup(struct dm_pool *mem, struct list *sllnew,
|
||||
list_init(sllnew);
|
||||
|
||||
list_iterate_items(sl, sllold) {
|
||||
if (!str_list_add(mem, sllnew, dm_pool_strdup(mem, sl->str))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!str_list_add(mem, sllnew, dm_pool_strdup(mem, sl->str)))
|
||||
return_0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
@@ -236,10 +236,8 @@ static int _add_alias(struct device *dev, const char *path)
|
||||
const char *oldpath;
|
||||
int prefer_old = 1;
|
||||
|
||||
if (!sl) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!sl)
|
||||
return_0;
|
||||
|
||||
/* Is name already there? */
|
||||
list_iterate_items(strl, &dev->aliases) {
|
||||
@@ -249,10 +247,8 @@ static int _add_alias(struct device *dev, const char *path)
|
||||
}
|
||||
}
|
||||
|
||||
if (!(sl->str = dm_pool_strdup(_cache.mem, path))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(sl->str = dm_pool_strdup(_cache.mem, path)))
|
||||
return_0;
|
||||
|
||||
if (!list_empty(&dev->aliases)) {
|
||||
oldpath = list_item(dev->aliases.n, struct str_list)->str;
|
||||
@@ -294,14 +290,10 @@ static int _insert_dev(const char *path, dev_t d)
|
||||
(uint32_t) d))) {
|
||||
/* create new device */
|
||||
if (loopfile) {
|
||||
if (!(dev = dev_create_file(path, NULL, NULL, 0))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
} else if (!(dev = _dev_create(d))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(dev = dev_create_file(path, NULL, NULL, 0)))
|
||||
return_0;
|
||||
} else if (!(dev = _dev_create(d)))
|
||||
return_0;
|
||||
|
||||
if (!(btree_insert(_cache.devices, (uint32_t) d, dev))) {
|
||||
log_err("Couldn't insert device into binary tree.");
|
||||
@@ -369,10 +361,8 @@ static int _insert_dir(const char *dir)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(path = _join(dir, dirent[n]->d_name))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(path = _join(dir, dirent[n]->d_name)))
|
||||
return_0;
|
||||
|
||||
_collapse_slashes(path);
|
||||
r &= _insert(path, 1);
|
||||
@@ -400,10 +390,8 @@ static int _insert_file(const char *path)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!_insert_dev(path, 0)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!_insert_dev(path, 0))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -439,10 +427,8 @@ static int _insert(const char *path, int rec)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!_insert_dev(path, info.st_rdev)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!_insert_dev(path, info.st_rdev))
|
||||
return_0;
|
||||
|
||||
r = 1;
|
||||
}
|
||||
@@ -502,7 +488,7 @@ static int _init_preferred_names(struct cmd_context *cmd)
|
||||
if (v->type != CFG_STRING) {
|
||||
log_error("preferred_names patterns must be enclosed in quotes");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
@@ -543,16 +529,13 @@ int dev_cache_init(struct cmd_context *cmd)
|
||||
_cache.names = NULL;
|
||||
_cache.has_scanned = 0;
|
||||
|
||||
if (!(_cache.mem = dm_pool_create("dev_cache", 10 * 1024))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(_cache.mem = dm_pool_create("dev_cache", 10 * 1024)))
|
||||
return_0;
|
||||
|
||||
if (!(_cache.names = dm_hash_create(128))) {
|
||||
stack;
|
||||
dm_pool_destroy(_cache.mem);
|
||||
_cache.mem = 0;
|
||||
return 0;
|
||||
return_0;
|
||||
}
|
||||
|
||||
if (!(_cache.devices = btree_create(_cache.mem))) {
|
||||
@@ -704,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;
|
||||
}
|
||||
|
||||
@@ -170,10 +170,8 @@ static int _aligned_io(struct device_area *where, void *buffer,
|
||||
struct device_area widened;
|
||||
|
||||
if (!(where->dev->flags & DEV_REGULAR) &&
|
||||
!_get_block_size(where->dev, &block_size)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
!_get_block_size(where->dev, &block_size))
|
||||
return_0;
|
||||
|
||||
if (!block_size)
|
||||
block_size = lvm_getpagesize();
|
||||
@@ -200,10 +198,8 @@ static int _aligned_io(struct device_area *where, void *buffer,
|
||||
|
||||
/* channel the io through the bounce buffer */
|
||||
if (!_io(&widened, bounce, 0)) {
|
||||
if (!should_write) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!should_write)
|
||||
return_0;
|
||||
/* FIXME pre-extend the file */
|
||||
memset(bounce, '\n', widened.size);
|
||||
}
|
||||
@@ -340,7 +336,7 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
|
||||
|
||||
if (dev->open_count && !need_excl) {
|
||||
/* FIXME Ensure we never get here */
|
||||
log_debug("WARNING: %s already opened read-only",
|
||||
log_debug("WARNING: %s already opened read-only",
|
||||
dev_name(dev));
|
||||
dev->open_count++;
|
||||
}
|
||||
@@ -354,10 +350,8 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
|
||||
|
||||
if (dev->flags & DEV_REGULAR)
|
||||
name = dev_name(dev);
|
||||
else if (!(name = dev_name_confirmed(dev, quiet))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
else if (!(name = dev_name_confirmed(dev, quiet)))
|
||||
return_0;
|
||||
|
||||
if (!(dev->flags & DEV_REGULAR)) {
|
||||
if (stat(name, &buf) < 0) {
|
||||
@@ -522,8 +516,8 @@ static int _dev_close(struct device *dev, int immediate)
|
||||
|
||||
/* Close unless device is known to belong to a locked VG */
|
||||
if (immediate ||
|
||||
(dev->open_count < 1 &&
|
||||
(!(info = info_from_pvid(dev->pvid)) ||
|
||||
(dev->open_count < 1 &&
|
||||
(!(info = info_from_pvid(dev->pvid, 0)) ||
|
||||
!info->vginfo ||
|
||||
!vgname_is_locked(info->vginfo->vgname))))
|
||||
_close(dev);
|
||||
@@ -557,10 +551,8 @@ int dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer)
|
||||
{
|
||||
struct device_area where;
|
||||
|
||||
if (!dev->open_count) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!dev->open_count)
|
||||
return_0;
|
||||
|
||||
where.dev = dev;
|
||||
where.start = offset;
|
||||
@@ -607,10 +599,8 @@ int dev_append(struct device *dev, size_t len, void *buffer)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (!dev->open_count) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!dev->open_count)
|
||||
return_0;
|
||||
|
||||
r = dev_write(dev, dev->end, len, buffer);
|
||||
dev->end += (uint64_t) len;
|
||||
@@ -625,10 +615,8 @@ int dev_write(struct device *dev, uint64_t offset, size_t len, void *buffer)
|
||||
{
|
||||
struct device_area where;
|
||||
|
||||
if (!dev->open_count) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!dev->open_count)
|
||||
return_0;
|
||||
|
||||
where.dev = dev;
|
||||
where.start = offset;
|
||||
@@ -644,10 +632,8 @@ int dev_set(struct device *dev, uint64_t offset, size_t len, int value)
|
||||
size_t s;
|
||||
char buffer[4096] __attribute((aligned(8)));
|
||||
|
||||
if (!dev_open(dev)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!dev_open(dev))
|
||||
return_0;
|
||||
|
||||
if ((offset % SECTOR_SIZE) || (len % SECTOR_SIZE))
|
||||
log_debug("Wiping %s at %" PRIu64 " length %" PRIsize_t,
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -27,16 +27,16 @@
|
||||
#define PART_OFFSET UINT64_C(0x1BE)
|
||||
|
||||
struct partition {
|
||||
uint8_t boot_ind;
|
||||
uint8_t head;
|
||||
uint8_t sector;
|
||||
uint8_t cyl;
|
||||
uint8_t sys_ind; /* partition type */
|
||||
uint8_t end_head;
|
||||
uint8_t end_sector;
|
||||
uint8_t end_cyl;
|
||||
uint32_t start_sect;
|
||||
uint32_t nr_sects;
|
||||
uint8_t boot_ind;
|
||||
uint8_t head;
|
||||
uint8_t sector;
|
||||
uint8_t cyl;
|
||||
uint8_t sys_ind; /* partition type */
|
||||
uint8_t end_head;
|
||||
uint8_t end_sector;
|
||||
uint8_t end_cyl;
|
||||
uint32_t start_sect;
|
||||
uint32_t nr_sects;
|
||||
} __attribute__((packed));
|
||||
|
||||
static int _is_partitionable(struct device *dev)
|
||||
@@ -62,10 +62,8 @@ static int _has_partition_table(struct device *dev)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!dev_read(dev, UINT64_C(0), sizeof(buf), &buf)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
if (!dev_read(dev, UINT64_C(0), sizeof(buf), &buf))
|
||||
goto_out;
|
||||
|
||||
/* FIXME Check for other types of partition table too */
|
||||
|
||||
|
||||
@@ -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"},
|
||||
@@ -270,7 +270,7 @@ void pvdisplay_segments(const struct physical_volume *pv)
|
||||
log_print("Physical extent %u to %u:",
|
||||
pvseg->pe, pvseg->pe + pvseg->len - 1);
|
||||
|
||||
if (pvseg->lvseg) {
|
||||
if (pvseg_is_allocated(pvseg)) {
|
||||
log_print(" Logical volume\t%s%s/%s",
|
||||
pvseg->lvseg->lv->vg->cmd->dev_dir,
|
||||
pvseg->lvseg->lv->vg->name,
|
||||
@@ -307,7 +307,8 @@ void pvdisplay_full(const struct cmd_context *cmd,
|
||||
|
||||
log_print("--- %sPhysical volume ---", pv->pe_size ? "" : "NEW ");
|
||||
log_print("PV Name %s", pv_dev_name(pv));
|
||||
log_print("VG Name %s%s", pv->vg_name,
|
||||
log_print("VG Name %s%s",
|
||||
is_orphan(pv) ? "" : pv->vg_name,
|
||||
pv->status & EXPORTED_VG ? " (exported)" : "");
|
||||
|
||||
data_size = (uint64_t) pv->pe_count * pv->pe_size;
|
||||
@@ -360,10 +361,8 @@ int pvdisplay_short(const struct cmd_context *cmd __attribute((unused)),
|
||||
if (!pv)
|
||||
return 0;
|
||||
|
||||
if (!id_write_format(&pv->id, uuid, sizeof(uuid))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!id_write_format(&pv->id, uuid, sizeof(uuid)))
|
||||
return_0;
|
||||
|
||||
log_print("PV Name %s ", pv_dev_name(pv));
|
||||
/* FIXME pv->pv_number); */
|
||||
@@ -407,10 +406,8 @@ int lvdisplay_full(struct cmd_context *cmd,
|
||||
struct lv_segment *snap_seg = NULL;
|
||||
float snap_percent; /* fused, fsize; */
|
||||
|
||||
if (!id_write_format(&lv->lvid.id[1], uuid, sizeof(uuid))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!id_write_format(&lv->lvid.id[1], uuid, sizeof(uuid)))
|
||||
return_0;
|
||||
|
||||
inkernel = lv_info(cmd, lv, &info, 1, 1) && info.exists;
|
||||
|
||||
@@ -577,6 +574,8 @@ void vgdisplay_full(const struct volume_group *vg)
|
||||
{
|
||||
uint32_t access;
|
||||
uint32_t active_pvs;
|
||||
uint32_t lv_count = 0;
|
||||
struct lv_list *lvl;
|
||||
char uuid[64] __attribute((aligned(8)));
|
||||
|
||||
if (vg->status & PARTIAL_VG)
|
||||
@@ -605,13 +604,18 @@ void vgdisplay_full(const struct volume_group *vg)
|
||||
/* vg number not part of LVM2 design
|
||||
log_print ("VG # %u\n", vg->vg_number);
|
||||
*/
|
||||
if (vg->status & CLUSTERED) {
|
||||
if (vg_is_clustered(vg)) {
|
||||
log_print("Clustered yes");
|
||||
log_print("Shared %s",
|
||||
vg->status & SHARED ? "yes" : "no");
|
||||
}
|
||||
|
||||
list_iterate_items(lvl, &vg->lvs)
|
||||
if (lv_is_visible(lvl->lv) && !(lvl->lv->status & SNAPSHOT))
|
||||
lv_count++;
|
||||
|
||||
log_print("MAX LV %u", vg->max_lv);
|
||||
log_print("Cur LV %u", vg->lv_count + vg->snapshot_count);
|
||||
log_print("Cur LV %u", lv_count);
|
||||
log_print("Open LV %u", lvs_in_vg_opened(vg));
|
||||
/****** FIXME Max LV Size
|
||||
log_print ( "MAX LV Size %s",
|
||||
@@ -655,6 +659,8 @@ void vgdisplay_full(const struct volume_group *vg)
|
||||
void vgdisplay_colons(const struct volume_group *vg)
|
||||
{
|
||||
uint32_t active_pvs;
|
||||
uint32_t lv_count;
|
||||
struct lv_list *lvl;
|
||||
const char *access;
|
||||
char uuid[64] __attribute((aligned(8)));
|
||||
|
||||
@@ -663,6 +669,10 @@ void vgdisplay_colons(const struct volume_group *vg)
|
||||
else
|
||||
active_pvs = vg->pv_count;
|
||||
|
||||
list_iterate_items(lvl, &vg->lvs)
|
||||
if (lv_is_visible(lvl->lv) && !(lvl->lv->status & SNAPSHOT))
|
||||
lv_count++;
|
||||
|
||||
switch (vg->status & (LVM_READ | LVM_WRITE)) {
|
||||
case LVM_READ | LVM_WRITE:
|
||||
access = "r/w";
|
||||
@@ -698,7 +708,7 @@ void vgdisplay_colons(const struct volume_group *vg)
|
||||
(uint64_t) vg->extent_count * (vg->extent_size / 2),
|
||||
vg->extent_size / 2,
|
||||
vg->extent_count,
|
||||
vg->extent_count - vg->free_count,
|
||||
vg->extent_count - vg->free_count,
|
||||
vg->free_count,
|
||||
uuid[0] ? uuid : "none");
|
||||
return;
|
||||
|
||||
@@ -51,7 +51,8 @@ static int _errseg_add_target_line(struct dev_manager *dm __attribute((unused)),
|
||||
return dm_tree_node_add_error_target(node, len);
|
||||
}
|
||||
|
||||
static int _errseg_target_present(const struct lv_segment *seg __attribute((unused)))
|
||||
static int _errseg_target_present(const struct lv_segment *seg __attribute((unused)),
|
||||
unsigned *attributes __attribute((unused)))
|
||||
{
|
||||
static int _errseg_checked = 0;
|
||||
static int _errseg_present = 0;
|
||||
@@ -77,7 +78,7 @@ static int _errseg_modules_needed(struct dm_pool *mem,
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void _errseg_destroy(const struct segment_type *segtype)
|
||||
{
|
||||
dm_free((void *)segtype);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
@@ -50,10 +50,8 @@ struct dev_filter *composite_filter_create(int n, struct dev_filter **filters)
|
||||
{
|
||||
struct dev_filter **filters_copy, *cft;
|
||||
|
||||
if (!filters) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!filters)
|
||||
return_NULL;
|
||||
|
||||
if (!(filters_copy = dm_malloc(sizeof(*filters) * (n + 1)))) {
|
||||
log_error("composite filters allocation failed");
|
||||
|
||||
@@ -19,7 +19,8 @@
|
||||
|
||||
#ifdef linux
|
||||
|
||||
static int _ignore_md(struct dev_filter *f, struct device *dev)
|
||||
static int _ignore_md(struct dev_filter *f __attribute((unused)),
|
||||
struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "dev-cache.h"
|
||||
#include "filter-persistent.h"
|
||||
#include "lvm-file.h"
|
||||
#include "lvm-string.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
@@ -42,10 +43,8 @@ static int _init_hash(struct pfilter *pf)
|
||||
if (pf->devices)
|
||||
dm_hash_destroy(pf->devices);
|
||||
|
||||
if (!(pf->devices = dm_hash_create(128))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(pf->devices = dm_hash_create(128)))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -99,13 +98,13 @@ int persistent_filter_load(struct dev_filter *f, struct config_tree **cft_out)
|
||||
{
|
||||
struct pfilter *pf = (struct pfilter *) f->private;
|
||||
struct config_tree *cft;
|
||||
struct stat info;
|
||||
struct stat info;
|
||||
int r = 0;
|
||||
|
||||
if (!stat(pf->file, &info))
|
||||
if (!stat(pf->file, &info))
|
||||
pf->ctime = info.st_ctime;
|
||||
else {
|
||||
log_very_verbose("%s: stat failed: %s", pf->file,
|
||||
log_very_verbose("%s: stat failed: %s", pf->file,
|
||||
strerror(errno));
|
||||
return_0;
|
||||
}
|
||||
@@ -144,6 +143,7 @@ static void _write_array(struct pfilter *pf, FILE *fp, const char *path,
|
||||
{
|
||||
void *d;
|
||||
int first = 1;
|
||||
char *buf, *str;
|
||||
struct dm_hash_node *n;
|
||||
|
||||
for (n = dm_hash_get_first(pf->devices); n;
|
||||
@@ -160,7 +160,13 @@ static void _write_array(struct pfilter *pf, FILE *fp, const char *path,
|
||||
first = 0;
|
||||
}
|
||||
|
||||
fprintf(fp, "\t\t\"%s\"", dm_hash_get_key(pf->devices, n));
|
||||
str = dm_hash_get_key(pf->devices, n);
|
||||
if (!(buf = alloca(escaped_len(str)))) {
|
||||
log_error("persistent filter device path stack "
|
||||
"allocation failed");
|
||||
return;
|
||||
}
|
||||
fprintf(fp, "\t\t\"%s\"", escape_double_quotes(buf, str));
|
||||
}
|
||||
|
||||
if (!first)
|
||||
@@ -293,10 +299,8 @@ struct dev_filter *persistent_filter_create(struct dev_filter *real,
|
||||
struct pfilter *pf;
|
||||
struct dev_filter *f = NULL;
|
||||
|
||||
if (!(pf = dm_malloc(sizeof(*pf)))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!(pf = dm_malloc(sizeof(*pf))))
|
||||
return_NULL;
|
||||
memset(pf, 0, sizeof(*pf));
|
||||
|
||||
if (!(pf->file = dm_malloc(strlen(file) + 1)))
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
@@ -70,10 +70,8 @@ static int _extract_pattern(struct dm_pool *mem, const char *pat,
|
||||
/*
|
||||
* copy the regex
|
||||
*/
|
||||
if (!(r = dm_pool_strdup(mem, pat))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(r = dm_pool_strdup(mem, pat)))
|
||||
return_0;
|
||||
|
||||
/*
|
||||
* trim the trailing character, having checked it's sep.
|
||||
@@ -192,10 +190,8 @@ struct dev_filter *regex_filter_create(struct config_value *patterns)
|
||||
struct rfilter *rf;
|
||||
struct dev_filter *f;
|
||||
|
||||
if (!mem) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!mem)
|
||||
return_NULL;
|
||||
|
||||
if (!(rf = dm_pool_alloc(mem, sizeof(*rf))))
|
||||
goto_bad;
|
||||
|
||||
@@ -236,21 +236,21 @@ static int _read_dev(const char *file, dev_t *result)
|
||||
*/
|
||||
static int _read_devs(struct dev_set *ds, const char *dir, unsigned sysfs_depth)
|
||||
{
|
||||
struct dirent *d;
|
||||
DIR *dr;
|
||||
struct dirent *d;
|
||||
DIR *dr;
|
||||
struct stat info;
|
||||
char path[PATH_MAX];
|
||||
char file[PATH_MAX];
|
||||
dev_t dev = { 0 };
|
||||
int r = 1;
|
||||
|
||||
if (!(dr = opendir(dir))) {
|
||||
log_sys_error("opendir", dir);
|
||||
return 0;
|
||||
}
|
||||
if (!(dr = opendir(dir))) {
|
||||
log_sys_error("opendir", dir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while ((d = readdir(dr))) {
|
||||
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
|
||||
while ((d = readdir(dr))) {
|
||||
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
|
||||
continue;
|
||||
|
||||
if (dm_snprintf(path, sizeof(path), "%s/%s", dir,
|
||||
@@ -278,8 +278,8 @@ static int _read_devs(struct dev_set *ds, const char *dir, unsigned sysfs_depth)
|
||||
}
|
||||
}
|
||||
|
||||
if (closedir(dr))
|
||||
log_sys_error("closedir", dir);
|
||||
if (closedir(dr))
|
||||
log_sys_error("closedir", dir);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -77,6 +77,7 @@ static const device_info_t device_info[] = {
|
||||
{"xvd", 16}, /* Xen virtual block device */
|
||||
{"vdisk", 8}, /* SUN's LDOM virtual block device */
|
||||
{"ps3disk", 16}, /* PlayStation 3 internal disk */
|
||||
{"virtblk", 8}, /* VirtIO disk */
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
@@ -277,9 +278,8 @@ struct dev_filter *lvm_type_filter_create(const char *proc,
|
||||
f->private = NULL;
|
||||
|
||||
if (!_scan_proc_dev(proc, cn)) {
|
||||
stack;
|
||||
dm_free(f);
|
||||
return NULL;
|
||||
return_NULL;
|
||||
}
|
||||
|
||||
return f;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
@@ -21,7 +21,6 @@
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
#define fail do {stack; return 0;} while(0)
|
||||
#define xx16(v) disk->v = xlate16(disk->v)
|
||||
#define xx32(v) disk->v = xlate32(disk->v)
|
||||
#define xx64(v) disk->v = xlate64(disk->v)
|
||||
@@ -134,15 +133,15 @@ static int _munge_formats(struct pv_disk *pvd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* UUID too long? */
|
||||
if (pvd->pv_uuid[ID_LEN]) {
|
||||
/* UUID too long? */
|
||||
if (pvd->pv_uuid[ID_LEN]) {
|
||||
/* Retain ID_LEN chars from end */
|
||||
for (e = ID_LEN; e < sizeof(pvd->pv_uuid); e++) {
|
||||
if (!pvd->pv_uuid[e]) {
|
||||
e--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (e = ID_LEN; e < sizeof(pvd->pv_uuid); e++) {
|
||||
if (!pvd->pv_uuid[e]) {
|
||||
e--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (b = 0; b < ID_LEN; b++) {
|
||||
pvd->pv_uuid[b] = pvd->pv_uuid[++e - ID_LEN];
|
||||
/* FIXME Remove all invalid chars */
|
||||
@@ -150,7 +149,7 @@ static int _munge_formats(struct pv_disk *pvd)
|
||||
pvd->pv_uuid[b] = '#';
|
||||
}
|
||||
memset(&pvd->pv_uuid[ID_LEN], 0, sizeof(pvd->pv_uuid) - ID_LEN);
|
||||
}
|
||||
}
|
||||
|
||||
/* If UUID is missing, create one */
|
||||
if (pvd->pv_uuid[0] == '\0') {
|
||||
@@ -161,8 +160,8 @@ static int _munge_formats(struct pv_disk *pvd)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If exported, remove "PV_EXP" from end of VG name
|
||||
/*
|
||||
* If exported, remove "PV_EXP" from end of VG name
|
||||
*/
|
||||
static void _munge_exported_vg(struct pv_disk *pvd)
|
||||
{
|
||||
@@ -178,8 +177,8 @@ static void _munge_exported_vg(struct pv_disk *pvd)
|
||||
s = sizeof(EXPORTED_TAG);
|
||||
if (!strncmp((char *)pvd->vg_name + l - s + 1, EXPORTED_TAG, s)) {
|
||||
pvd->vg_name[l - s + 1] = '\0';
|
||||
pvd->pv_status |= VG_EXPORTED;
|
||||
}
|
||||
pvd->pv_status |= VG_EXPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
int munge_pvd(struct device *dev, struct pv_disk *pvd)
|
||||
@@ -218,7 +217,7 @@ static int _read_pvd(struct device *dev, struct pv_disk *pvd)
|
||||
static int _read_lvd(struct device *dev, uint64_t pos, struct lv_disk *disk)
|
||||
{
|
||||
if (!dev_read(dev, pos, sizeof(*disk), disk))
|
||||
fail;
|
||||
return_0;
|
||||
|
||||
_xlate_lvd(disk);
|
||||
|
||||
@@ -230,12 +229,12 @@ int read_vgd(struct device *dev, struct vg_disk *vgd, struct pv_disk *pvd)
|
||||
uint64_t pos = pvd->vg_on_disk.base;
|
||||
|
||||
if (!dev_read(dev, pos, sizeof(*vgd), vgd))
|
||||
fail;
|
||||
return_0;
|
||||
|
||||
_xlate_vgd(vgd);
|
||||
|
||||
if ((vgd->lv_max > MAX_LV) || (vgd->pv_max > MAX_PV))
|
||||
fail;
|
||||
return_0;
|
||||
|
||||
/* If UUID is missing, create one */
|
||||
if (vgd->vg_uuid[0] == '\0')
|
||||
@@ -254,10 +253,10 @@ static int _read_uuids(struct disk_list *data)
|
||||
|
||||
while (pos < end && num_read < data->vgd.pv_cur) {
|
||||
if (!dev_read(data->dev, pos, sizeof(buffer), buffer))
|
||||
fail;
|
||||
return_0;
|
||||
|
||||
if (!(ul = dm_pool_alloc(data->mem, sizeof(*ul))))
|
||||
fail;
|
||||
return_0;
|
||||
|
||||
memcpy(ul->uuid, buffer, NAME_LEN);
|
||||
ul->uuid[NAME_LEN - 1] = '\0';
|
||||
@@ -288,10 +287,10 @@ static int _read_lvs(struct disk_list *data)
|
||||
ll = dm_pool_alloc(data->mem, sizeof(*ll));
|
||||
|
||||
if (!ll)
|
||||
fail;
|
||||
return_0;
|
||||
|
||||
if (!_read_lvd(data->dev, pos, &ll->lvd))
|
||||
fail;
|
||||
return_0;
|
||||
|
||||
if (!_check_lvd(&ll->lvd))
|
||||
continue;
|
||||
@@ -310,10 +309,10 @@ static int _read_extents(struct disk_list *data)
|
||||
uint64_t pos = data->pvd.pe_on_disk.base;
|
||||
|
||||
if (!extents)
|
||||
fail;
|
||||
return_0;
|
||||
|
||||
if (!dev_read(data->dev, pos, len, extents))
|
||||
fail;
|
||||
return_0;
|
||||
|
||||
_xlate_extents(extents, data->pvd.pe_total);
|
||||
data->extents = extents;
|
||||
@@ -327,10 +326,11 @@ static void __update_lvmcache(const struct format_type *fmt,
|
||||
unsigned exported)
|
||||
{
|
||||
struct lvmcache_info *info;
|
||||
const char *vgname = *((char *)dl->pvd.vg_name) ?
|
||||
(char *)dl->pvd.vg_name : fmt->orphan_vg_name;
|
||||
|
||||
if (!(info = lvmcache_add(fmt->labeller, (char *)dl->pvd.pv_uuid, dev,
|
||||
(char *)dl->pvd.vg_name, vgid,
|
||||
exported ? EXPORTED_VG : 0))) {
|
||||
vgname, vgid, exported ? EXPORTED_VG : 0))) {
|
||||
stack;
|
||||
return;
|
||||
}
|
||||
@@ -347,10 +347,8 @@ static struct disk_list *__read_disk(const struct format_type *fmt,
|
||||
struct disk_list *dl = dm_pool_zalloc(mem, sizeof(*dl));
|
||||
const char *name = dev_name(dev);
|
||||
|
||||
if (!dl) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!dl)
|
||||
return_NULL;
|
||||
|
||||
dl->dev = dev;
|
||||
dl->mem = mem;
|
||||
@@ -358,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 ?
|
||||
@@ -366,20 +364,20 @@ static struct disk_list *__read_disk(const struct format_type *fmt,
|
||||
if (!*dl->pvd.vg_name) {
|
||||
log_very_verbose("%s is not a member of any format1 VG", name);
|
||||
|
||||
__update_lvmcache(fmt, dl, dev, NULL, 0);
|
||||
__update_lvmcache(fmt, dl, dev, fmt->orphan_vg_name, 0);
|
||||
return (vg_name) ? NULL : dl;
|
||||
}
|
||||
|
||||
if (!read_vgd(dl->dev, &dl->vgd, &dl->pvd)) {
|
||||
log_error("Failed to read VG data from PV (%s)", name);
|
||||
__update_lvmcache(fmt, dl, dev, NULL, 0);
|
||||
__update_lvmcache(fmt, dl, dev, fmt->orphan_vg_name, 0);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (vg_name && strcmp(vg_name, (char *)dl->pvd.vg_name)) {
|
||||
log_very_verbose("%s is not a member of the VG %s",
|
||||
name, vg_name);
|
||||
__update_lvmcache(fmt, dl, dev, NULL, 0);
|
||||
__update_lvmcache(fmt, dl, dev, fmt->orphan_vg_name, 0);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
@@ -417,10 +415,8 @@ struct disk_list *read_disk(const struct format_type *fmt, struct device *dev,
|
||||
{
|
||||
struct disk_list *dl;
|
||||
|
||||
if (!dev_open(dev)) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!dev_open(dev))
|
||||
return_NULL;
|
||||
|
||||
dl = __read_disk(fmt, dev, mem, vg_name);
|
||||
|
||||
@@ -519,7 +515,7 @@ static int _write_vgd(struct disk_list *data)
|
||||
|
||||
_xlate_vgd(vgd);
|
||||
if (!dev_write(data->dev, pos, sizeof(*vgd), vgd))
|
||||
fail;
|
||||
return_0;
|
||||
|
||||
_xlate_vgd(vgd);
|
||||
|
||||
@@ -544,7 +540,7 @@ static int _write_uuids(struct disk_list *data)
|
||||
pos, NAME_LEN);
|
||||
|
||||
if (!dev_write(data->dev, pos, NAME_LEN, ul->uuid))
|
||||
fail;
|
||||
return_0;
|
||||
|
||||
pos += NAME_LEN;
|
||||
}
|
||||
@@ -560,7 +556,7 @@ static int _write_lvd(struct device *dev, uint64_t pos, struct lv_disk *disk)
|
||||
|
||||
_xlate_lvd(disk);
|
||||
if (!dev_write(dev, pos, sizeof(*disk), disk))
|
||||
fail;
|
||||
return_0;
|
||||
|
||||
_xlate_lvd(disk);
|
||||
|
||||
@@ -588,7 +584,7 @@ static int _write_lvs(struct disk_list *data)
|
||||
}
|
||||
|
||||
if (!_write_lvd(data->dev, pos + offset, &ll->lvd))
|
||||
fail;
|
||||
return_0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -606,7 +602,7 @@ static int _write_extents(struct disk_list *data)
|
||||
|
||||
_xlate_extents(extents, data->pvd.pe_total);
|
||||
if (!dev_write(data->dev, pos, len, extents))
|
||||
fail;
|
||||
return_0;
|
||||
|
||||
_xlate_extents(extents, data->pvd.pe_total);
|
||||
|
||||
@@ -643,7 +639,7 @@ static int _write_pvd(struct disk_list *data)
|
||||
_xlate_pvd((struct pv_disk *) buf);
|
||||
if (!dev_write(data->dev, pos, size, buf)) {
|
||||
dm_free(buf);
|
||||
fail;
|
||||
return_0;
|
||||
}
|
||||
|
||||
dm_free(buf);
|
||||
@@ -707,10 +703,8 @@ static int _write_all_pvd(const struct format_type *fmt, struct disk_list *data)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (!dev_open(data->dev)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!dev_open(data->dev))
|
||||
return_0;
|
||||
|
||||
r = __write_all_pvd(fmt, data);
|
||||
|
||||
@@ -731,7 +725,7 @@ int write_disks(const struct format_type *fmt, struct list *pvs)
|
||||
|
||||
list_iterate_items(dl, pvs) {
|
||||
if (!(_write_all_pvd(fmt, dl)))
|
||||
fail;
|
||||
return_0;
|
||||
|
||||
log_very_verbose("Successfully wrote data to %s",
|
||||
dev_name(dl->dev));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
@@ -18,13 +18,10 @@
|
||||
#include "limits.h"
|
||||
#include "display.h"
|
||||
#include "toolcontext.h"
|
||||
#include "lvmcache.h"
|
||||
#include "lvm1-label.h"
|
||||
#include "format1.h"
|
||||
#include "segtype.h"
|
||||
|
||||
#define FMT_LVM1_NAME "lvm1"
|
||||
|
||||
/* VG consistency checks */
|
||||
static int _check_vgs(struct list *pvs, int *partial)
|
||||
{
|
||||
@@ -168,7 +165,6 @@ static struct volume_group *_build_vg(struct format_instance *fid,
|
||||
return vg;
|
||||
|
||||
bad:
|
||||
stack;
|
||||
dm_pool_free(mem, vg);
|
||||
return NULL;
|
||||
}
|
||||
@@ -182,10 +178,8 @@ static struct volume_group *_format1_vg_read(struct format_instance *fid,
|
||||
struct volume_group *vg = NULL;
|
||||
list_init(&pvs);
|
||||
|
||||
if (!mem) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!mem)
|
||||
return_NULL;
|
||||
|
||||
/* Strip dev_dir if present */
|
||||
vg_name = strip_dir(vg_name, fid->fmt->cmd->dev_dir);
|
||||
@@ -209,10 +203,8 @@ static struct disk_list *_flatten_pv(struct format_instance *fid,
|
||||
{
|
||||
struct disk_list *dl = dm_pool_alloc(mem, sizeof(*dl));
|
||||
|
||||
if (!dl) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!dl)
|
||||
return_NULL;
|
||||
|
||||
dl->mem = mem;
|
||||
dl->dev = pv->dev;
|
||||
@@ -224,9 +216,8 @@ static struct disk_list *_flatten_pv(struct format_instance *fid,
|
||||
!export_vg(&dl->vgd, vg) ||
|
||||
!export_uuids(dl, vg) ||
|
||||
!export_lvs(dl, vg, pv, dev_dir) || !calculate_layout(dl)) {
|
||||
stack;
|
||||
dm_pool_free(mem, dl);
|
||||
return NULL;
|
||||
return_NULL;
|
||||
}
|
||||
|
||||
return dl;
|
||||
@@ -241,10 +232,8 @@ static int _flatten_vg(struct format_instance *fid, struct dm_pool *mem,
|
||||
struct disk_list *data;
|
||||
|
||||
list_iterate_items(pvl, &vg->pvs) {
|
||||
if (!(data = _flatten_pv(fid, mem, vg, pvl->pv, dev_dir))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(data = _flatten_pv(fid, mem, vg, pvl->pv, dev_dir)))
|
||||
return_0;
|
||||
|
||||
list_add(pvds, &data->list);
|
||||
}
|
||||
@@ -252,10 +241,8 @@ static int _flatten_vg(struct format_instance *fid, struct dm_pool *mem,
|
||||
export_numbers(pvds, vg);
|
||||
export_pv_act(pvds);
|
||||
|
||||
if (!export_vg_number(fid, pvds, vg->name, filter)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!export_vg_number(fid, pvds, vg->name, filter))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -267,10 +254,8 @@ static int _format1_vg_write(struct format_instance *fid, struct volume_group *v
|
||||
struct list pvds;
|
||||
int r = 0;
|
||||
|
||||
if (!mem) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!mem)
|
||||
return_0;
|
||||
|
||||
list_init(&pvds);
|
||||
|
||||
@@ -278,7 +263,7 @@ static int _format1_vg_write(struct format_instance *fid, struct volume_group *v
|
||||
fid->fmt->cmd->filter) &&
|
||||
write_disks(fid->fmt, &pvds));
|
||||
|
||||
lvmcache_update_vg(vg);
|
||||
lvmcache_update_vg(vg, 0);
|
||||
dm_pool_destroy(mem);
|
||||
return r;
|
||||
}
|
||||
@@ -293,25 +278,17 @@ static int _format1_pv_read(const struct format_type *fmt, const char *pv_name,
|
||||
|
||||
log_very_verbose("Reading physical volume data %s from disk", pv_name);
|
||||
|
||||
if (!mem) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!mem)
|
||||
return_0;
|
||||
|
||||
if (!(dev = dev_cache_get(pv_name, fmt->cmd->filter))) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
if (!(dev = dev_cache_get(pv_name, fmt->cmd->filter)))
|
||||
goto_out;
|
||||
|
||||
if (!(dl = read_disk(fmt, dev, mem, NULL))) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
if (!(dl = read_disk(fmt, dev, mem, NULL)))
|
||||
goto_out;
|
||||
|
||||
if (!import_pv(fmt, fmt->cmd->mem, dl->dev, NULL, pv, &dl->pvd, &dl->vgd)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
if (!import_pv(fmt, fmt->cmd->mem, dl->dev, NULL, pv, &dl->pvd, &dl->vgd))
|
||||
goto_out;
|
||||
|
||||
pv->fmt = fmt;
|
||||
|
||||
@@ -344,10 +321,8 @@ static int _format1_pv_setup(const struct format_type *fmt,
|
||||
/*
|
||||
* This works out pe_start and pe_count.
|
||||
*/
|
||||
if (!calculate_extent_count(pv, extent_size, extent_count, pe_start)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!calculate_extent_count(pv, extent_size, extent_count, pe_start))
|
||||
return_0;
|
||||
|
||||
/* Retain existing extent locations exactly */
|
||||
if (((pe_start || extent_count) && (pe_start != pv->pe_start)) ||
|
||||
@@ -390,10 +365,8 @@ static int _format1_pv_write(const struct format_type *fmt, struct physical_volu
|
||||
struct lvmcache_info *info;
|
||||
|
||||
if (!(info = lvmcache_add(fmt->labeller, (char *) &pv->id, pv->dev,
|
||||
pv->vg_name, NULL, 0))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
pv->vg_name, NULL, 0)))
|
||||
return_0;
|
||||
label = info->label;
|
||||
info->device_size = pv->size << SECTOR_SHIFT;
|
||||
info->fmt = fmt;
|
||||
@@ -406,10 +379,8 @@ static int _format1_pv_write(const struct format_type *fmt, struct physical_volu
|
||||
pv->pe_size = pv->pe_count = 0;
|
||||
pv->pe_start = LVM1_PE_ALIGN;
|
||||
|
||||
if (!(mem = dm_pool_create("lvm1 pv_write", 1024))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(mem = dm_pool_create("lvm1 pv_write", 1024)))
|
||||
return_0;
|
||||
|
||||
if (!(dl = dm_pool_alloc(mem, sizeof(*dl))))
|
||||
goto_bad;
|
||||
@@ -470,13 +441,11 @@ static int _format1_vg_setup(struct format_instance *fid, struct volume_group *v
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _format1_segtype_supported(struct format_instance *fid __attribute((unused)),
|
||||
static int _format1_segtype_supported(struct format_instance *fid __attribute((unused)),
|
||||
const struct segment_type *segtype)
|
||||
{
|
||||
if (!(segtype->flags & SEG_FORMAT1_SUPPORT)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(segtype->flags & SEG_FORMAT1_SUPPORT))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -494,19 +463,16 @@ static struct format_instance *_format1_create_instance(const struct format_type
|
||||
struct format_instance *fid;
|
||||
struct metadata_area *mda;
|
||||
|
||||
if (!(fid = dm_pool_alloc(fmt->cmd->mem, sizeof(*fid)))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!(fid = dm_pool_alloc(fmt->cmd->mem, sizeof(*fid))))
|
||||
return_NULL;
|
||||
|
||||
fid->fmt = fmt;
|
||||
list_init(&fid->metadata_areas);
|
||||
|
||||
/* Define a NULL metadata area */
|
||||
if (!(mda = dm_pool_alloc(fmt->cmd->mem, sizeof(*mda)))) {
|
||||
stack;
|
||||
dm_pool_free(fmt->cmd->mem, fid);
|
||||
return NULL;
|
||||
return_NULL;
|
||||
}
|
||||
|
||||
mda->ops = &_metadata_format1_ops;
|
||||
@@ -547,15 +513,14 @@ struct format_type *init_format(struct cmd_context *cmd)
|
||||
{
|
||||
struct format_type *fmt = dm_malloc(sizeof(*fmt));
|
||||
|
||||
if (!fmt) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!fmt)
|
||||
return_NULL;
|
||||
|
||||
fmt->cmd = cmd;
|
||||
fmt->ops = &_format1_ops;
|
||||
fmt->name = FMT_LVM1_NAME;
|
||||
fmt->alias = NULL;
|
||||
fmt->orphan_vg_name = FMT_LVM1_ORPHAN_VG_NAME;
|
||||
fmt->features = FMT_RESTRICTED_LVIDS | FMT_ORPHAN_ALLOCATABLE |
|
||||
FMT_RESTRICTED_READAHEAD;
|
||||
fmt->private = NULL;
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
#define _LVM_FORMAT1_H
|
||||
|
||||
#include "metadata.h"
|
||||
#include "lvmcache.h"
|
||||
|
||||
#define FMT_LVM1_NAME "lvm1"
|
||||
#define FMT_LVM1_ORPHAN_VG_NAME ORPHAN_VG_NAME(FMT_LVM1_NAME)
|
||||
|
||||
#ifdef LVM1_INTERNAL
|
||||
struct format_type *init_lvm1_format(struct cmd_context *cmd);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "pv_alloc.h"
|
||||
#include "display.h"
|
||||
#include "lvmcache.h"
|
||||
#include "metadata.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
@@ -61,7 +62,7 @@ int import_pv(const struct format_type *fmt, struct dm_pool *mem,
|
||||
|
||||
pv->dev = dev;
|
||||
if (!*pvd->vg_name)
|
||||
pv->vg_name = ORPHAN;
|
||||
pv->vg_name = fmt->orphan_vg_name;
|
||||
else if (!(pv->vg_name = dm_pool_strdup(mem, (char *)pvd->vg_name))) {
|
||||
log_error("Volume Group name allocation failed.");
|
||||
return 0;
|
||||
@@ -117,10 +118,8 @@ int import_pv(const struct format_type *fmt, struct dm_pool *mem,
|
||||
list_init(&pv->tags);
|
||||
list_init(&pv->segments);
|
||||
|
||||
if (!alloc_pv_segment_whole_pv(mem, pv)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!alloc_pv_segment_whole_pv(mem, pv))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -149,11 +148,9 @@ int export_pv(struct cmd_context *cmd, struct dm_pool *mem __attribute((unused))
|
||||
|
||||
memcpy(pvd->pv_uuid, pv->id.uuid, ID_LEN);
|
||||
|
||||
if (pv->vg_name) {
|
||||
if (!_check_vg_name(pv->vg_name)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (pv->vg_name && !is_orphan(pv)) {
|
||||
if (!_check_vg_name(pv->vg_name))
|
||||
return_0;
|
||||
strncpy((char *)pvd->vg_name, pv->vg_name, sizeof(pvd->vg_name));
|
||||
}
|
||||
|
||||
@@ -167,10 +164,8 @@ int export_pv(struct cmd_context *cmd, struct dm_pool *mem __attribute((unused))
|
||||
if (!*vg->system_id ||
|
||||
strncmp(vg->system_id, EXPORTED_TAG,
|
||||
sizeof(EXPORTED_TAG) - 1)) {
|
||||
if (!_system_id(cmd, (char *)pvd->system_id, EXPORTED_TAG)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!_system_id(cmd, (char *)pvd->system_id, EXPORTED_TAG))
|
||||
return_0;
|
||||
}
|
||||
if (strlen((char *)pvd->vg_name) + sizeof(EXPORTED_TAG) >
|
||||
sizeof(pvd->vg_name)) {
|
||||
@@ -184,18 +179,14 @@ int export_pv(struct cmd_context *cmd, struct dm_pool *mem __attribute((unused))
|
||||
/* Is VG being imported? */
|
||||
if (vg && !(vg->status & EXPORTED_VG) && *vg->system_id &&
|
||||
!strncmp(vg->system_id, EXPORTED_TAG, sizeof(EXPORTED_TAG) - 1)) {
|
||||
if (!_system_id(cmd, (char *)pvd->system_id, IMPORTED_TAG)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!_system_id(cmd, (char *)pvd->system_id, IMPORTED_TAG))
|
||||
return_0;
|
||||
}
|
||||
|
||||
/* Generate system_id if PV is in VG */
|
||||
if (!pvd->system_id || !*pvd->system_id)
|
||||
if (!_system_id(cmd, (char *)pvd->system_id, "")) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!_system_id(cmd, (char *)pvd->system_id, ""))
|
||||
return_0;
|
||||
|
||||
/* Update internal system_id if we changed it */
|
||||
if (vg &&
|
||||
@@ -227,20 +218,14 @@ int import_vg(struct dm_pool *mem,
|
||||
struct vg_disk *vgd = &dl->vgd;
|
||||
memcpy(vg->id.uuid, vgd->vg_uuid, ID_LEN);
|
||||
|
||||
if (!_check_vg_name((char *)dl->pvd.vg_name)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!_check_vg_name((char *)dl->pvd.vg_name))
|
||||
return_0;
|
||||
|
||||
if (!(vg->name = dm_pool_strdup(mem, (char *)dl->pvd.vg_name))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(vg->name = dm_pool_strdup(mem, (char *)dl->pvd.vg_name)))
|
||||
return_0;
|
||||
|
||||
if (!(vg->system_id = dm_pool_alloc(mem, NAME_LEN))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(vg->system_id = dm_pool_alloc(mem, NAME_LEN)))
|
||||
return_0;
|
||||
|
||||
*vg->system_id = '\0';
|
||||
|
||||
@@ -286,7 +271,7 @@ int export_vg(struct vg_disk *vgd, struct volume_group *vg)
|
||||
if (vg->status & LVM_WRITE)
|
||||
vgd->vg_access |= VG_WRITE;
|
||||
|
||||
if (vg->status & CLUSTERED)
|
||||
if (vg_is_clustered(vg))
|
||||
vgd->vg_access |= VG_CLUSTERED;
|
||||
|
||||
if (vg->status & SHARED)
|
||||
@@ -299,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;
|
||||
@@ -315,10 +300,8 @@ int import_lv(struct dm_pool *mem, struct logical_volume *lv, struct lv_disk *lv
|
||||
{
|
||||
lvid_from_lvnum(&lv->lvid, &lv->vg->id, lvd->lv_number);
|
||||
|
||||
if (!(lv->name = _create_lv_name(mem, (char *)lvd->lv_name))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(lv->name = _create_lv_name(mem, (char *)lvd->lv_name)))
|
||||
return_0;
|
||||
|
||||
lv->status |= VISIBLE_LV;
|
||||
|
||||
@@ -457,15 +440,11 @@ int import_pvs(const struct format_type *fmt, struct dm_pool *mem,
|
||||
*count = 0;
|
||||
list_iterate_items(dl, pvds) {
|
||||
if (!(pvl = dm_pool_zalloc(mem, sizeof(*pvl))) ||
|
||||
!(pvl->pv = dm_pool_alloc(mem, sizeof(*pvl->pv)))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
!(pvl->pv = dm_pool_alloc(mem, sizeof(*pvl->pv))))
|
||||
return_0;
|
||||
|
||||
if (!import_pv(fmt, mem, dl->dev, vg, pvl->pv, &dl->pvd, &dl->vgd)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!import_pv(fmt, mem, dl->dev, vg, pvl->pv, &dl->pvd, &dl->vgd))
|
||||
return_0;
|
||||
|
||||
pvl->pv->fmt = fmt;
|
||||
list_add(results, &pvl->list);
|
||||
@@ -483,17 +462,13 @@ static struct logical_volume *_add_lv(struct dm_pool *mem,
|
||||
struct logical_volume *lv;
|
||||
|
||||
if (!(ll = dm_pool_zalloc(mem, sizeof(*ll))) ||
|
||||
!(ll->lv = dm_pool_zalloc(mem, sizeof(*ll->lv)))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
!(ll->lv = dm_pool_zalloc(mem, sizeof(*ll->lv))))
|
||||
return_NULL;
|
||||
lv = ll->lv;
|
||||
lv->vg = vg;
|
||||
|
||||
if (!import_lv(mem, lv, lvd)) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!import_lv(mem, lv, lvd))
|
||||
return_NULL;
|
||||
|
||||
list_add(&vg->lvs, &ll->list);
|
||||
vg->lv_count++;
|
||||
@@ -512,10 +487,8 @@ int import_lvs(struct dm_pool *mem, struct volume_group *vg, struct list *pvds)
|
||||
lvd = &ll->lvd;
|
||||
|
||||
if (!find_lv(vg, (char *)lvd->lv_name) &&
|
||||
!_add_lv(mem, vg, lvd)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
!_add_lv(mem, vg, lvd))
|
||||
return_0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -533,49 +506,37 @@ int export_lvs(struct disk_list *dl, struct volume_group *vg,
|
||||
uint32_t lv_num;
|
||||
struct dm_hash_table *lvd_hash;
|
||||
|
||||
if (!_check_vg_name(vg->name)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!_check_vg_name(vg->name))
|
||||
return_0;
|
||||
|
||||
if (!(lvd_hash = dm_hash_create(32))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(lvd_hash = dm_hash_create(32)))
|
||||
return_0;
|
||||
|
||||
/*
|
||||
* setup the pv's extents array
|
||||
*/
|
||||
len = sizeof(struct pe_disk) * dl->pvd.pe_total;
|
||||
if (!(dl->extents = dm_pool_alloc(dl->mem, len))) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
if (!(dl->extents = dm_pool_alloc(dl->mem, len)))
|
||||
goto_out;
|
||||
memset(dl->extents, 0, len);
|
||||
|
||||
list_iterate_items(ll, &vg->lvs) {
|
||||
if (ll->lv->status & SNAPSHOT)
|
||||
continue;
|
||||
|
||||
if (!(lvdl = dm_pool_alloc(dl->mem, sizeof(*lvdl)))) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
if (!(lvdl = dm_pool_alloc(dl->mem, sizeof(*lvdl))))
|
||||
goto_out;
|
||||
|
||||
_export_lv(&lvdl->lvd, vg, ll->lv, dev_dir);
|
||||
|
||||
lv_num = lvnum_from_lvid(&ll->lv->lvid);
|
||||
lvdl->lvd.lv_number = lv_num;
|
||||
|
||||
if (!dm_hash_insert(lvd_hash, ll->lv->name, &lvdl->lvd)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
if (!dm_hash_insert(lvd_hash, ll->lv->name, &lvdl->lvd))
|
||||
goto_out;
|
||||
|
||||
if (!export_extents(dl, lv_num + 1, ll->lv, pv)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
if (!export_extents(dl, lv_num + 1, ll->lv, pv))
|
||||
goto_out;
|
||||
|
||||
if (lv_is_origin(ll->lv))
|
||||
lvdl->lvd.lv_access |= LV_SNAPSHOT_ORG;
|
||||
@@ -658,7 +619,7 @@ int import_snapshots(struct dm_pool *mem __attribute((unused)), struct volume_gr
|
||||
|
||||
/* insert the snapshot */
|
||||
if (!vg_add_snapshot(NULL, org, cow, NULL,
|
||||
org->le_count,
|
||||
org->le_count,
|
||||
lvd->lv_chunk_size)) {
|
||||
log_err("Couldn't add snapshot.");
|
||||
return 0;
|
||||
@@ -675,10 +636,8 @@ int export_uuids(struct disk_list *dl, struct volume_group *vg)
|
||||
struct pv_list *pvl;
|
||||
|
||||
list_iterate_items(pvl, &vg->pvs) {
|
||||
if (!(ul = dm_pool_alloc(dl->mem, sizeof(*ul)))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(ul = dm_pool_alloc(dl->mem, sizeof(*ul))))
|
||||
return_0;
|
||||
|
||||
memset(ul->uuid, 0, sizeof(ul->uuid));
|
||||
memcpy(ul->uuid, pvl->pv->id.uuid, ID_LEN);
|
||||
@@ -723,10 +682,8 @@ int export_vg_number(struct format_instance *fid, struct list *pvds,
|
||||
struct disk_list *dl;
|
||||
int vg_num;
|
||||
|
||||
if (!get_free_vg_number(fid, filter, vg_name, &vg_num)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!get_free_vg_number(fid, filter, vg_name, &vg_num))
|
||||
return_0;
|
||||
|
||||
list_iterate_items(dl, pvds)
|
||||
dl->vgd.vg_number = vg_num;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
@@ -118,10 +118,8 @@ static int _fill_maps(struct dm_hash_table *maps, struct volume_group *vg,
|
||||
e = dl->extents;
|
||||
|
||||
/* build an array of lv's for this pv */
|
||||
if (!_fill_lv_array(lvms, maps, dl)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!_fill_lv_array(lvms, maps, dl))
|
||||
return_0;
|
||||
|
||||
for (i = 0; i < dl->pvd.pe_total; i++) {
|
||||
lv_num = e[i].lv_num;
|
||||
@@ -189,10 +187,8 @@ static int _check_maps_are_complete(struct dm_hash_table *maps)
|
||||
for (n = dm_hash_get_first(maps); n; n = dm_hash_get_next(maps, n)) {
|
||||
lvm = (struct lv_map *) dm_hash_get_data(maps, n);
|
||||
|
||||
if (!_check_single_map(lvm)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!_check_single_map(lvm))
|
||||
return_0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -216,10 +212,8 @@ static int _read_linear(struct cmd_context *cmd, struct lv_map *lvm)
|
||||
struct lv_segment *seg;
|
||||
struct segment_type *segtype;
|
||||
|
||||
if (!(segtype = get_segtype_from_string(cmd, "striped"))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(segtype = get_segtype_from_string(cmd, "striped")))
|
||||
return_0;
|
||||
|
||||
while (le < lvm->lv->le_count) {
|
||||
len = _area_length(lvm, le);
|
||||
@@ -286,7 +280,7 @@ static int _read_stripes(struct cmd_context *cmd, struct lv_map *lvm)
|
||||
while (first_area_le < total_area_len) {
|
||||
area_len = 1;
|
||||
|
||||
/*
|
||||
/*
|
||||
* Find how many extents are contiguous in all stripes
|
||||
* and so can form part of this segment
|
||||
*/
|
||||
@@ -334,10 +328,8 @@ static int _build_all_segments(struct cmd_context *cmd, struct dm_hash_table *ma
|
||||
|
||||
for (n = dm_hash_get_first(maps); n; n = dm_hash_get_next(maps, n)) {
|
||||
lvm = (struct lv_map *) dm_hash_get_data(maps, n);
|
||||
if (!_build_segments(cmd, lvm)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!_build_segments(cmd, lvm))
|
||||
return_0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -350,10 +342,8 @@ int import_extents(struct cmd_context *cmd, struct volume_group *vg,
|
||||
struct dm_pool *scratch = dm_pool_create("lvm1 import_extents", 10 * 1024);
|
||||
struct dm_hash_table *maps;
|
||||
|
||||
if (!scratch) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!scratch)
|
||||
return_0;
|
||||
|
||||
if (!(maps = _create_lv_maps(scratch, vg))) {
|
||||
log_err("Couldn't allocate logical volume maps.");
|
||||
@@ -365,10 +355,8 @@ int import_extents(struct cmd_context *cmd, struct volume_group *vg,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!_check_maps_are_complete(maps) && !(vg->status & PARTIAL_VG)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
if (!_check_maps_are_complete(maps) && !(vg->status & PARTIAL_VG))
|
||||
goto_out;
|
||||
|
||||
if (!_build_all_segments(cmd, maps)) {
|
||||
log_err("Couldn't build extent segments.");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
@@ -122,10 +122,8 @@ int calculate_extent_count(struct physical_volume *pv, uint32_t extent_size,
|
||||
struct pv_disk *pvd = dm_malloc(sizeof(*pvd));
|
||||
uint32_t end;
|
||||
|
||||
if (!pvd) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!pvd)
|
||||
return_0;
|
||||
|
||||
/*
|
||||
* Guess how many extents will fit, bearing in mind that
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
@@ -19,7 +19,7 @@
|
||||
#include "label.h"
|
||||
#include "metadata.h"
|
||||
#include "xlate.h"
|
||||
#include "lvmcache.h"
|
||||
#include "format1.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
@@ -60,21 +60,23 @@ static int _lvm1_read(struct labeller *l, struct device *dev, void *buf,
|
||||
struct pv_disk *pvd = (struct pv_disk *) buf;
|
||||
struct vg_disk vgd;
|
||||
struct lvmcache_info *info;
|
||||
const char *vgid = NULL;
|
||||
const char *vgid = FMT_LVM1_ORPHAN_VG_NAME;
|
||||
const char *vgname = FMT_LVM1_ORPHAN_VG_NAME;
|
||||
unsigned exported = 0;
|
||||
|
||||
munge_pvd(dev, pvd);
|
||||
|
||||
if (*pvd->vg_name && read_vgd(dev, &vgd, pvd)) {
|
||||
if (*pvd->vg_name) {
|
||||
if (!read_vgd(dev, &vgd, pvd))
|
||||
return_0;
|
||||
vgid = (char *) vgd.vg_uuid;
|
||||
vgname = (char *) pvd->vg_name;
|
||||
exported = pvd->pv_status & VG_EXPORTED;
|
||||
}
|
||||
|
||||
if (!(info = lvmcache_add(l, (char *)pvd->pv_uuid, dev, (char *)pvd->vg_name, vgid,
|
||||
exported))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(info = lvmcache_add(l, (char *)pvd->pv_uuid, dev, vgname, vgid,
|
||||
exported)))
|
||||
return_0;
|
||||
*label = info->label;
|
||||
|
||||
info->device_size = xlate32(pvd->pv_size) << SECTOR_SHIFT;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
@@ -33,15 +33,11 @@ int get_free_vg_number(struct format_instance *fid, struct dev_filter *filter,
|
||||
|
||||
list_init(&all_pvs);
|
||||
|
||||
if (!mem) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!mem)
|
||||
return_0;
|
||||
|
||||
if (!read_pvs_in_vg(fid->fmt, NULL, filter, mem, &all_pvs)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
if (!read_pvs_in_vg(fid->fmt, NULL, filter, mem, &all_pvs))
|
||||
goto_out;
|
||||
|
||||
memset(numbers, 0, sizeof(numbers));
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
@@ -45,10 +45,8 @@ static int __read_pool_disk(const struct format_type *fmt, struct device *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!read_pool_label(pl, fmt->labeller, dev, buf, NULL)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!read_pool_label(pl, fmt->labeller, dev, buf, NULL))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -98,10 +96,8 @@ int read_pool_label(struct pool_list *pl, struct labeller *l,
|
||||
log_debug("Calculated uuid %s for %s", uuid, pd->pl_pool_name);
|
||||
|
||||
if (!(info = lvmcache_add(l, (char *) &pvid, dev, pd->pl_pool_name,
|
||||
(char *) &vgid, 0))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
(char *) &vgid, 0)))
|
||||
return_0;
|
||||
if (label)
|
||||
*label = info->label;
|
||||
|
||||
@@ -252,10 +248,8 @@ static int _read_vg_pds(const struct format_type *fmt, struct dm_pool *mem,
|
||||
|
||||
/* FIXME: maybe should return a different error in memory
|
||||
* allocation failure */
|
||||
if (!(tmpmem = dm_pool_create("pool read_vg", 512))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(tmpmem = dm_pool_create("pool read_vg", 512)))
|
||||
return_0;
|
||||
|
||||
list_iterate_items(info, &vginfo->infos) {
|
||||
if (info->dev &&
|
||||
@@ -354,20 +348,16 @@ struct pool_list *read_pool_disk(const struct format_type *fmt,
|
||||
{
|
||||
struct pool_list *pl;
|
||||
|
||||
if (!dev_open(dev)) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!dev_open(dev))
|
||||
return_NULL;
|
||||
|
||||
if (!(pl = dm_pool_zalloc(mem, sizeof(*pl)))) {
|
||||
log_error("Unable to allocate pool list structure");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!__read_pool_disk(fmt, dev, mem, pl, vg_name)) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!__read_pool_disk(fmt, dev, mem, pl, vg_name))
|
||||
return_NULL;
|
||||
|
||||
if (!dev_close(dev))
|
||||
stack;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
@@ -24,8 +24,6 @@
|
||||
#include "format_pool.h"
|
||||
#include "pool_label.h"
|
||||
|
||||
#define FMT_POOL_NAME "pool"
|
||||
|
||||
/* Must be called after pvs are imported */
|
||||
static struct user_subpool *_build_usp(struct list *pls, struct dm_pool *mem,
|
||||
int *sps)
|
||||
@@ -128,44 +126,32 @@ static struct volume_group *_build_vg_from_pds(struct format_instance
|
||||
list_init(&vg->lvs);
|
||||
list_init(&vg->tags);
|
||||
|
||||
if (!import_pool_vg(vg, smem, pds)) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!import_pool_vg(vg, smem, pds))
|
||||
return_NULL;
|
||||
|
||||
if (!import_pool_pvs(fid->fmt, vg, &vg->pvs, smem, pds)) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!import_pool_pvs(fid->fmt, vg, &vg->pvs, smem, pds))
|
||||
return_NULL;
|
||||
|
||||
if (!import_pool_lvs(vg, smem, pds)) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!import_pool_lvs(vg, smem, pds))
|
||||
return_NULL;
|
||||
|
||||
/*
|
||||
* I need an intermediate subpool structure that contains all the
|
||||
* relevant info for this. Then i can iterate through the subpool
|
||||
* structures for checking, and create the segments
|
||||
*/
|
||||
if (!(usp = _build_usp(pds, mem, &sp_count))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!(usp = _build_usp(pds, mem, &sp_count)))
|
||||
return_NULL;
|
||||
|
||||
/*
|
||||
* check the subpool structures - we can't handle partial VGs in
|
||||
* the pool format, so this will error out if we're missing PVs
|
||||
*/
|
||||
if (!_check_usp(vg->name, usp, sp_count)) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!_check_usp(vg->name, usp, sp_count))
|
||||
return_NULL;
|
||||
|
||||
if (!import_pool_segments(&vg->lvs, smem, usp, sp_count)) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!import_pool_segments(&vg->lvs, smem, usp, sp_count))
|
||||
return_NULL;
|
||||
|
||||
return vg;
|
||||
}
|
||||
@@ -182,25 +168,19 @@ static struct volume_group *_pool_vg_read(struct format_instance *fid,
|
||||
|
||||
/* We can safely ignore the mda passed in */
|
||||
|
||||
if (!mem) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!mem)
|
||||
return_NULL;
|
||||
|
||||
/* Strip dev_dir if present */
|
||||
vg_name = strip_dir(vg_name, fid->fmt->cmd->dev_dir);
|
||||
|
||||
/* Read all the pvs in the vg */
|
||||
if (!read_pool_pds(fid->fmt, vg_name, mem, &pds)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
if (!read_pool_pds(fid->fmt, vg_name, mem, &pds))
|
||||
goto_out;
|
||||
|
||||
/* Do the rest of the vg stuff */
|
||||
if (!(vg = _build_vg_from_pds(fid, mem, &pds))) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
if (!(vg = _build_vg_from_pds(fid, mem, &pds)))
|
||||
goto_out;
|
||||
|
||||
out:
|
||||
dm_pool_destroy(mem);
|
||||
@@ -231,30 +211,22 @@ static int _pool_pv_read(const struct format_type *fmt, const char *pv_name,
|
||||
|
||||
log_very_verbose("Reading physical volume data %s from disk", pv_name);
|
||||
|
||||
if (!mem) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!mem)
|
||||
return_0;
|
||||
|
||||
if (!(dev = dev_cache_get(pv_name, fmt->cmd->filter))) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
if (!(dev = dev_cache_get(pv_name, fmt->cmd->filter)))
|
||||
goto_out;
|
||||
|
||||
/*
|
||||
* I need to read the disk and populate a pv structure here
|
||||
* I'll probably need to abstract some of this later for the
|
||||
* vg_read code
|
||||
*/
|
||||
if (!(pl = read_pool_disk(fmt, dev, mem, NULL))) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
if (!(pl = read_pool_disk(fmt, dev, mem, NULL)))
|
||||
goto_out;
|
||||
|
||||
if (!import_pool_pv(fmt, fmt->cmd->mem, NULL, pv, pl)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
if (!import_pool_pv(fmt, fmt->cmd->mem, NULL, pv, pl))
|
||||
goto_out;
|
||||
|
||||
pv->fmt = fmt;
|
||||
|
||||
@@ -342,6 +314,7 @@ struct format_type *init_format(struct cmd_context *cmd)
|
||||
fmt->ops = &_format_pool_ops;
|
||||
fmt->name = FMT_POOL_NAME;
|
||||
fmt->alias = NULL;
|
||||
fmt->orphan_vg_name = FMT_POOL_ORPHAN_VG_NAME;
|
||||
fmt->features = 0;
|
||||
fmt->private = NULL;
|
||||
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
|
||||
#include "metadata.h"
|
||||
|
||||
#define FMT_POOL_NAME "pool"
|
||||
#define FMT_POOL_ORPHAN_VG_NAME ORPHAN_VG_NAME(FMT_POOL_NAME)
|
||||
|
||||
#ifdef POOL_INTERNAL
|
||||
struct format_type *init_pool_format(struct cmd_context *cmd);
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
@@ -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;
|
||||
@@ -91,10 +91,8 @@ int import_pool_lvs(struct volume_group *vg, struct dm_pool *mem, struct list *p
|
||||
if (lv->name)
|
||||
continue;
|
||||
|
||||
if (!(lv->name = dm_pool_strdup(mem, pl->pd.pl_pool_name))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(lv->name = dm_pool_strdup(mem, pl->pd.pl_pool_name)))
|
||||
return_0;
|
||||
|
||||
get_pool_lv_uuid(lv->lvid.id, &pl->pd);
|
||||
log_debug("Calculated lv uuid for lv %s: %s", lv->name,
|
||||
@@ -167,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;
|
||||
@@ -178,10 +177,8 @@ int import_pool_pv(const struct format_type *fmt, struct dm_pool *mem,
|
||||
list_init(&pv->tags);
|
||||
list_init(&pv->segments);
|
||||
|
||||
if (!alloc_pv_segment_whole_pv(mem, pv)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!alloc_pv_segment_whole_pv(mem, pv))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -216,12 +213,10 @@ static int _add_stripe_seg(struct dm_pool *mem,
|
||||
area_len = (usp->devs[0].blocks) / POOL_PE_SIZE;
|
||||
|
||||
if (!(segtype = get_segtype_from_string(lv->vg->cmd,
|
||||
"striped"))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
"striped")))
|
||||
return_0;
|
||||
|
||||
if (!(seg = alloc_lv_segment(mem, segtype, lv, *le_cur,
|
||||
if (!(seg = alloc_lv_segment(mem, segtype, lv, *le_cur,
|
||||
area_len * usp->num_devs, 0,
|
||||
usp->striping, NULL, usp->num_devs,
|
||||
area_len, 0, 0, 0))) {
|
||||
@@ -230,10 +225,8 @@ static int _add_stripe_seg(struct dm_pool *mem,
|
||||
}
|
||||
|
||||
for (j = 0; j < usp->num_devs; j++)
|
||||
if (!set_lv_segment_area_pv(seg, j, usp->devs[j].pv, 0)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!set_lv_segment_area_pv(seg, j, usp->devs[j].pv, 0))
|
||||
return_0;
|
||||
|
||||
/* add the subpool type to the segment tag list */
|
||||
str_list_add(mem, &seg->tags, _cvt_sptype(usp->type));
|
||||
@@ -254,10 +247,8 @@ static int _add_linear_seg(struct dm_pool *mem,
|
||||
unsigned j;
|
||||
uint32_t area_len;
|
||||
|
||||
if (!(segtype = get_segtype_from_string(lv->vg->cmd, "striped"))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(segtype = get_segtype_from_string(lv->vg->cmd, "striped")))
|
||||
return_0;
|
||||
|
||||
for (j = 0; j < usp->num_devs; j++) {
|
||||
area_len = (usp->devs[j].blocks) / POOL_PE_SIZE;
|
||||
@@ -274,10 +265,8 @@ static int _add_linear_seg(struct dm_pool *mem,
|
||||
/* add the subpool type to the segment tag list */
|
||||
str_list_add(mem, &seg->tags, _cvt_sptype(usp->type));
|
||||
|
||||
if (!set_lv_segment_area_pv(seg, 0, usp->devs[j].pv, 0)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!set_lv_segment_area_pv(seg, 0, usp->devs[j].pv, 0))
|
||||
return_0;
|
||||
list_add(&lv->segments, &seg->list);
|
||||
|
||||
*le_cur += seg->len;
|
||||
@@ -302,15 +291,11 @@ int import_pool_segments(struct list *lvs, struct dm_pool *mem,
|
||||
|
||||
for (i = 0; i < subpools; i++) {
|
||||
if (usp[i].striping) {
|
||||
if (!_add_stripe_seg(mem, &usp[i], lv, &le_cur)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!_add_stripe_seg(mem, &usp[i], lv, &le_cur))
|
||||
return_0;
|
||||
} else {
|
||||
if (!_add_linear_seg(mem, &usp[i], lv, &le_cur)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!_add_linear_seg(mem, &usp[i], lv, &le_cur))
|
||||
return_0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
@@ -113,10 +113,8 @@ static char *_join_file_to_dir(struct dm_pool *mem, const char *dir, const char
|
||||
!dm_pool_grow_object(mem, dir, strlen(dir)) ||
|
||||
!dm_pool_grow_object(mem, "/", 1) ||
|
||||
!dm_pool_grow_object(mem, name, strlen(name)) ||
|
||||
!dm_pool_grow_object(mem, "\0", 1)) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
!dm_pool_grow_object(mem, "\0", 1))
|
||||
return_NULL;
|
||||
|
||||
return dm_pool_end_object(mem);
|
||||
}
|
||||
@@ -134,10 +132,8 @@ static struct list *_scan_archive(struct dm_pool *mem,
|
||||
struct archive_file *af;
|
||||
struct list *results;
|
||||
|
||||
if (!(results = dm_pool_alloc(mem, sizeof(*results)))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!(results = dm_pool_alloc(mem, sizeof(*results))))
|
||||
return_NULL;
|
||||
|
||||
list_init(results);
|
||||
|
||||
@@ -161,10 +157,8 @@ static struct list *_scan_archive(struct dm_pool *mem,
|
||||
if (strcmp(vgname, vgname_found))
|
||||
continue;
|
||||
|
||||
if (!(path = _join_file_to_dir(mem, dir, dirent[i]->d_name))) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
if (!(path = _join_file_to_dir(mem, dir, dirent[i]->d_name)))
|
||||
goto_out;
|
||||
|
||||
/*
|
||||
* Create a new archive_file.
|
||||
@@ -255,10 +249,9 @@ int archive_vg(struct volume_group *vg,
|
||||
}
|
||||
|
||||
if (!text_vg_export_file(vg, desc, fp)) {
|
||||
stack;
|
||||
if (fclose(fp))
|
||||
log_sys_error("fclose", temp_file);
|
||||
return 0;
|
||||
return_0;
|
||||
}
|
||||
|
||||
if (lvm_fclose(fp, temp_file))
|
||||
@@ -267,10 +260,8 @@ int archive_vg(struct volume_group *vg,
|
||||
/*
|
||||
* Now we want to rename this file to <vg>_index.vg.
|
||||
*/
|
||||
if (!(archives = _scan_archive(vg->cmd->mem, vg->name, dir))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(archives = _scan_archive(vg->cmd->mem, vg->name, dir)))
|
||||
return_0;
|
||||
|
||||
if (list_empty(archives))
|
||||
ix = 0;
|
||||
@@ -343,10 +334,8 @@ int archive_list(struct cmd_context *cmd, const char *dir, const char *vgname)
|
||||
struct list *archives;
|
||||
struct archive_file *af;
|
||||
|
||||
if (!(archives = _scan_archive(cmd->mem, vgname, dir))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(archives = _scan_archive(cmd->mem, vgname, dir)))
|
||||
return_0;
|
||||
|
||||
if (list_empty(archives))
|
||||
log_print("No archives found in %s.", dir);
|
||||
@@ -379,10 +368,8 @@ int backup_list(struct cmd_context *cmd, const char *dir, const char *vgname)
|
||||
{
|
||||
struct archive_file af;
|
||||
|
||||
if (!(af.path = _join_file_to_dir(cmd->mem, dir, vgname))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(af.path = _join_file_to_dir(cmd->mem, dir, vgname)))
|
||||
return_0;
|
||||
|
||||
if (path_exists(af.path))
|
||||
_display_archive(cmd, &af);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
@@ -78,17 +78,13 @@ static char *_build_desc(struct dm_pool *mem, const char *line, int before)
|
||||
size_t len = strlen(line) + 32;
|
||||
char *buffer;
|
||||
|
||||
if (!(buffer = dm_pool_zalloc(mem, strlen(line) + 32))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!(buffer = dm_pool_zalloc(mem, strlen(line) + 32)))
|
||||
return_NULL;
|
||||
|
||||
if (snprintf(buffer, len,
|
||||
"Created %s executing '%s'",
|
||||
before ? "*before*" : "*after*", line) < 0) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
before ? "*before*" : "*after*", line) < 0)
|
||||
return_NULL;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
@@ -97,10 +93,8 @@ static int __archive(struct volume_group *vg)
|
||||
{
|
||||
char *desc;
|
||||
|
||||
if (!(desc = _build_desc(vg->cmd->mem, vg->cmd->cmd_line, 1))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(desc = _build_desc(vg->cmd->mem, vg->cmd->cmd_line, 1)))
|
||||
return_0;
|
||||
|
||||
return archive_vg(vg, vg->cmd->archive_params->dir, desc,
|
||||
vg->cmd->archive_params->keep_days,
|
||||
@@ -121,9 +115,9 @@ int archive(struct volume_group *vg)
|
||||
return 0;
|
||||
|
||||
/* Trap a read-only file system */
|
||||
if ((access(vg->cmd->archive_params->dir, R_OK | W_OK | X_OK) == -1) &&
|
||||
if ((access(vg->cmd->archive_params->dir, R_OK | W_OK | X_OK) == -1) &&
|
||||
(errno == EROFS))
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
log_verbose("Archiving volume group \"%s\" metadata (seqno %u).", vg->name,
|
||||
vg->seqno);
|
||||
@@ -196,10 +190,8 @@ static int __backup(struct volume_group *vg)
|
||||
char name[PATH_MAX];
|
||||
char *desc;
|
||||
|
||||
if (!(desc = _build_desc(vg->cmd->mem, vg->cmd->cmd_line, 0))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(desc = _build_desc(vg->cmd->mem, vg->cmd->cmd_line, 0)))
|
||||
return_0;
|
||||
|
||||
if (dm_snprintf(name, sizeof(name), "%s/%s",
|
||||
vg->cmd->backup_params->dir, vg->name) < 0) {
|
||||
@@ -227,9 +219,9 @@ int backup(struct volume_group *vg)
|
||||
return 0;
|
||||
|
||||
/* Trap a read-only file system */
|
||||
if ((access(vg->cmd->backup_params->dir, R_OK | W_OK | X_OK) == -1) &&
|
||||
if ((access(vg->cmd->backup_params->dir, R_OK | W_OK | X_OK) == -1) &&
|
||||
(errno == EROFS))
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
if (!__backup(vg)) {
|
||||
log_error("Backup of volume group %s metadata failed.",
|
||||
@@ -305,7 +297,7 @@ int backup_restore_vg(struct cmd_context *cmd, struct volume_group *vg)
|
||||
/* Add any metadata areas on the PVs */
|
||||
list_iterate_items(pvl, &vg->pvs) {
|
||||
pv = pvl->pv;
|
||||
if (!(info = info_from_pvid(pv->dev->pvid))) {
|
||||
if (!(info = info_from_pvid(pv->dev->pvid, 0))) {
|
||||
log_error("PV %s missing from cache",
|
||||
pv_dev_name(pv));
|
||||
return 0;
|
||||
@@ -324,10 +316,8 @@ int backup_restore_vg(struct cmd_context *cmd, struct volume_group *vg)
|
||||
}
|
||||
}
|
||||
|
||||
if (!vg_write(vg) || !vg_commit(vg)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!vg_write(vg) || !vg_commit(vg))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -341,10 +331,8 @@ int backup_restore_from_file(struct cmd_context *cmd, const char *vg_name,
|
||||
/*
|
||||
* Read in the volume group from the text file.
|
||||
*/
|
||||
if (!(vg = backup_read_vg(cmd, vg_name, file))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(vg = backup_read_vg(cmd, vg_name, file)))
|
||||
return_0;
|
||||
|
||||
return backup_restore_vg(cmd, vg);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
@@ -37,7 +37,7 @@ typedef int (*nl_fn) (struct formatter * f);
|
||||
* Then argument list is reset and out_with_comment_fn is called again.
|
||||
*/
|
||||
#define _out_with_comment(f, buffer, fmt, ap) \
|
||||
do { \
|
||||
do { \
|
||||
va_start(ap, fmt); \
|
||||
r = f->out_with_comment(f, buffer, fmt, ap); \
|
||||
va_end(ap); \
|
||||
@@ -135,10 +135,8 @@ static int _nl_raw(struct formatter *f)
|
||||
{
|
||||
/* If metadata doesn't fit, extend buffer */
|
||||
if ((f->data.buf.used + 2 > f->data.buf.size) &&
|
||||
(!_extend_buffer(f))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
(!_extend_buffer(f)))
|
||||
return_0;
|
||||
|
||||
*(f->data.buf.start + f->data.buf.used) = '\n';
|
||||
f->data.buf.used += 1;
|
||||
@@ -195,10 +193,8 @@ static int _out_with_comment_raw(struct formatter *f,
|
||||
|
||||
/* If metadata doesn't fit, extend buffer */
|
||||
if (n < 0 || (n + f->data.buf.used + 2 > f->data.buf.size)) {
|
||||
if (!_extend_buffer(f)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!_extend_buffer(f))
|
||||
return_0;
|
||||
return -1; /* Retry */
|
||||
}
|
||||
|
||||
@@ -300,6 +296,7 @@ int out_text(struct formatter *f, const char *fmt, ...)
|
||||
static int _print_header(struct formatter *f,
|
||||
const char *desc)
|
||||
{
|
||||
char *buf;
|
||||
time_t t;
|
||||
|
||||
t = time(NULL);
|
||||
@@ -309,7 +306,12 @@ static int _print_header(struct formatter *f,
|
||||
outf(f, FORMAT_VERSION_FIELD " = %d", FORMAT_VERSION_VALUE);
|
||||
outnl(f);
|
||||
|
||||
outf(f, "description = \"%s\"", desc);
|
||||
if (!(buf = alloca(escaped_len(desc)))) {
|
||||
log_error("temporary stack allocation for description"
|
||||
"string failed");
|
||||
return 0;
|
||||
}
|
||||
outf(f, "description = \"%s\"", escape_double_quotes(buf, desc));
|
||||
outnl(f);
|
||||
outf(f, "creation_host = \"%s\"\t# %s %s %s %s %s", _utsname.nodename,
|
||||
_utsname.sysname, _utsname.nodename, _utsname.release,
|
||||
@@ -319,30 +321,37 @@ 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];
|
||||
|
||||
if (!id_write_format(&vg->id, buffer, sizeof(buffer))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!id_write_format(&vg->id, buffer, sizeof(buffer)))
|
||||
return_0;
|
||||
|
||||
outf(f, "id = \"%s\"", buffer);
|
||||
|
||||
outf(f, "seqno = %u", vg->seqno);
|
||||
|
||||
if (!print_flags(vg->status, VG_FLAGS, buffer, sizeof(buffer))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
outf(f, "status = %s", buffer);
|
||||
if (!_print_flag_config(f, vg->status, VG_FLAGS))
|
||||
return_0;
|
||||
|
||||
if (!list_empty(&vg->tags)) {
|
||||
if (!print_tags(&vg->tags, buffer, sizeof(buffer))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!print_tags(&vg->tags, buffer, sizeof(buffer)))
|
||||
return_0;
|
||||
outf(f, "tags = %s", buffer);
|
||||
}
|
||||
|
||||
@@ -350,10 +359,8 @@ static int _print_vg(struct formatter *f, struct volume_group *vg)
|
||||
outf(f, "system_id = \"%s\"", vg->system_id);
|
||||
|
||||
if (!out_size(f, (uint64_t) vg->extent_size, "extent_size = %u",
|
||||
vg->extent_size)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
vg->extent_size))
|
||||
return_0;
|
||||
outf(f, "max_lv = %u", vg->max_lv);
|
||||
outf(f, "max_pv = %u", vg->max_pv);
|
||||
|
||||
@@ -382,6 +389,7 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
|
||||
struct pv_list *pvl;
|
||||
struct physical_volume *pv;
|
||||
char buffer[4096];
|
||||
char *buf;
|
||||
const char *name;
|
||||
|
||||
outf(f, "physical_volumes {");
|
||||
@@ -390,52 +398,45 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
|
||||
list_iterate_items(pvl, &vg->pvs) {
|
||||
pv = pvl->pv;
|
||||
|
||||
if (!(name = _get_pv_name(f, pv))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(name = _get_pv_name(f, pv)))
|
||||
return_0;
|
||||
|
||||
outnl(f);
|
||||
outf(f, "%s {", name);
|
||||
_inc_indent(f);
|
||||
|
||||
if (!id_write_format(&pv->id, buffer, sizeof(buffer))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!id_write_format(&pv->id, buffer, sizeof(buffer)))
|
||||
return_0;
|
||||
|
||||
outf(f, "id = \"%s\"", buffer);
|
||||
if (!out_hint(f, "device = \"%s\"", pv_dev_name(pv))) {
|
||||
stack;
|
||||
|
||||
if (!(buf = alloca(escaped_len(pv_dev_name(pv))))) {
|
||||
log_error("temporary stack allocation for device name"
|
||||
"string failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!out_hint(f, "device = \"%s\"",
|
||||
escape_double_quotes(buf, pv_dev_name(pv))))
|
||||
return_0;
|
||||
outnl(f);
|
||||
|
||||
if (!print_flags(pv->status, PV_FLAGS, buffer, sizeof(buffer))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
outf(f, "status = %s", buffer);
|
||||
if (!_print_flag_config(f, pv->status, PV_FLAGS))
|
||||
return_0;
|
||||
|
||||
if (!list_empty(&pv->tags)) {
|
||||
if (!print_tags(&pv->tags, buffer, sizeof(buffer))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!print_tags(&pv->tags, buffer, sizeof(buffer)))
|
||||
return_0;
|
||||
outf(f, "tags = %s", buffer);
|
||||
}
|
||||
|
||||
if (!out_size(f, pv->size, "dev_size = %" PRIu64, pv->size)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!out_size(f, pv->size, "dev_size = %" PRIu64, pv->size))
|
||||
return_0;
|
||||
|
||||
outf(f, "pe_start = %" PRIu64, pv->pe_start);
|
||||
if (!out_size(f, vg->extent_size * (uint64_t) pv->pe_count,
|
||||
"pe_count = %u", pv->pe_count)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
"pe_count = %u", pv->pe_count))
|
||||
return_0;
|
||||
|
||||
_dec_indent(f);
|
||||
outf(f, "}");
|
||||
@@ -456,27 +457,21 @@ static int _print_segment(struct formatter *f, struct volume_group *vg,
|
||||
|
||||
outf(f, "start_extent = %u", seg->le);
|
||||
if (!out_size(f, (uint64_t) seg->len * vg->extent_size,
|
||||
"extent_count = %u", seg->len)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
"extent_count = %u", seg->len))
|
||||
return_0;
|
||||
|
||||
outnl(f);
|
||||
outf(f, "type = \"%s\"", seg->segtype->name);
|
||||
|
||||
if (!list_empty(&seg->tags)) {
|
||||
if (!print_tags(&seg->tags, buffer, sizeof(buffer))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!print_tags(&seg->tags, buffer, sizeof(buffer)))
|
||||
return_0;
|
||||
outf(f, "tags = %s", buffer);
|
||||
}
|
||||
|
||||
if (seg->segtype->ops->text_export &&
|
||||
!seg->segtype->ops->text_export(seg, f)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
!seg->segtype->ops->text_export(seg, f))
|
||||
return_0;
|
||||
|
||||
_dec_indent(f);
|
||||
outf(f, "}");
|
||||
@@ -498,10 +493,8 @@ int out_areas(struct formatter *f, const struct lv_segment *seg,
|
||||
for (s = 0; s < seg->area_count; s++) {
|
||||
switch (seg_type(seg, s)) {
|
||||
case AREA_PV:
|
||||
if (!(name = _get_pv_name(f, seg_pv(seg, s)))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(name = _get_pv_name(f, seg_pv(seg, s))))
|
||||
return_0;
|
||||
|
||||
outf(f, "\"%s\", %u%s", name,
|
||||
seg_pe(seg, s),
|
||||
@@ -534,24 +527,17 @@ static int _print_lv(struct formatter *f, struct logical_volume *lv)
|
||||
_inc_indent(f);
|
||||
|
||||
/* FIXME: Write full lvid */
|
||||
if (!id_write_format(&lv->lvid.id[1], buffer, sizeof(buffer))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!id_write_format(&lv->lvid.id[1], buffer, sizeof(buffer)))
|
||||
return_0;
|
||||
|
||||
outf(f, "id = \"%s\"", buffer);
|
||||
|
||||
if (!print_flags(lv->status, LV_FLAGS, buffer, sizeof(buffer))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
outf(f, "status = %s", buffer);
|
||||
if (!_print_flag_config(f, lv->status, LV_FLAGS))
|
||||
return_0;
|
||||
|
||||
if (!list_empty(&lv->tags)) {
|
||||
if (!print_tags(&lv->tags, buffer, sizeof(buffer))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!print_tags(&lv->tags, buffer, sizeof(buffer)))
|
||||
return_0;
|
||||
outf(f, "tags = %s", buffer);
|
||||
}
|
||||
|
||||
@@ -579,10 +565,8 @@ static int _print_lv(struct formatter *f, struct logical_volume *lv)
|
||||
|
||||
seg_count = 1;
|
||||
list_iterate_items(seg, &lv->segments) {
|
||||
if (!_print_segment(f, lv->vg, seg_count++, seg)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!_print_segment(f, lv->vg, seg_count++, seg))
|
||||
return_0;
|
||||
}
|
||||
|
||||
_dec_indent(f);
|
||||
@@ -610,19 +594,15 @@ static int _print_lvs(struct formatter *f, struct volume_group *vg)
|
||||
list_iterate_items(lvl, &vg->lvs) {
|
||||
if (!(lvl->lv->status & VISIBLE_LV))
|
||||
continue;
|
||||
if (!_print_lv(f, lvl->lv)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!_print_lv(f, lvl->lv))
|
||||
return_0;
|
||||
}
|
||||
|
||||
list_iterate_items(lvl, &vg->lvs) {
|
||||
if ((lvl->lv->status & VISIBLE_LV))
|
||||
continue;
|
||||
if (!_print_lv(f, lvl->lv)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!_print_lv(f, lvl->lv))
|
||||
return_0;
|
||||
}
|
||||
|
||||
_dec_indent(f);
|
||||
@@ -671,10 +651,8 @@ static int _text_vg_export(struct formatter *f,
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
if (!_build_pv_names(f, vg)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
if (!_build_pv_names(f, vg))
|
||||
goto_out;
|
||||
|
||||
if (f->header && !_print_header(f, desc))
|
||||
goto_out;
|
||||
@@ -721,10 +699,8 @@ int text_vg_export_file(struct volume_group *vg, const char *desc, FILE *fp)
|
||||
|
||||
_init();
|
||||
|
||||
if (!(f = dm_malloc(sizeof(*f)))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(f = dm_malloc(sizeof(*f))))
|
||||
return_0;
|
||||
|
||||
memset(f, 0, sizeof(*f));
|
||||
f->data.fp = fp;
|
||||
@@ -748,10 +724,8 @@ int text_vg_export_raw(struct volume_group *vg, const char *desc, char **buf)
|
||||
|
||||
_init();
|
||||
|
||||
if (!(f = dm_malloc(sizeof(*f)))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(f = dm_malloc(sizeof(*f))))
|
||||
return_0;
|
||||
|
||||
memset(f, 0, sizeof(*f));
|
||||
|
||||
@@ -767,9 +741,8 @@ int text_vg_export_raw(struct volume_group *vg, const char *desc, char **buf)
|
||||
f->nl = &_nl_raw;
|
||||
|
||||
if (!_text_vg_export(f, vg, desc)) {
|
||||
stack;
|
||||
dm_free(f->data.buf.start);
|
||||
goto out;
|
||||
goto_out;
|
||||
}
|
||||
|
||||
r = f->data.buf.used + 1;
|
||||
@@ -780,5 +753,10 @@ int text_vg_export_raw(struct volume_group *vg, const char *desc, char **buf)
|
||||
return r;
|
||||
}
|
||||
|
||||
int export_vg_to_buffer(struct volume_group *vg, char **buf)
|
||||
{
|
||||
return text_vg_export_raw(vg, "", buf);
|
||||
}
|
||||
|
||||
#undef outf
|
||||
#undef outnl
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
@@ -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;
|
||||
|
||||
@@ -91,10 +92,8 @@ int print_flags(uint32_t status, int type, char *buffer, size_t size)
|
||||
int f, first = 1;
|
||||
struct flag *flags;
|
||||
|
||||
if (!(flags = _get_flags(type))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(flags = _get_flags(type)))
|
||||
return_0;
|
||||
|
||||
if (!emit_to_buffer(&buffer, &size, "["))
|
||||
return 0;
|
||||
@@ -103,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;
|
||||
@@ -135,10 +137,8 @@ int read_flags(uint32_t *status, int type, struct config_value *cv)
|
||||
uint32_t s = 0;
|
||||
struct flag *flags;
|
||||
|
||||
if (!(flags = _get_flags(type))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(flags = _get_flags(type)))
|
||||
return_0;
|
||||
|
||||
if (cv->type == CFG_EMPTY_ARRAY)
|
||||
goto out;
|
||||
@@ -155,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;
|
||||
}
|
||||
@@ -164,6 +164,6 @@ int read_flags(uint32_t *status, int type, struct config_value *cv)
|
||||
}
|
||||
|
||||
out:
|
||||
*status = s;
|
||||
*status |= s;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
@@ -36,9 +36,6 @@
|
||||
#include <dirent.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#define FMT_TEXT_NAME "lvm2"
|
||||
#define FMT_TEXT_ALIAS "text"
|
||||
|
||||
static struct mda_header *_raw_read_mda_header(const struct format_type *fmt,
|
||||
struct device_area *dev_area);
|
||||
|
||||
@@ -142,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;
|
||||
@@ -187,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.
|
||||
@@ -250,7 +250,7 @@ static int _pv_analyze_mda_raw (const struct format_type * fmt,
|
||||
static int _text_lv_setup(struct format_instance *fid __attribute((unused)),
|
||||
struct logical_volume *lv)
|
||||
{
|
||||
/******** FIXME Any LV size restriction?
|
||||
/******** FIXME Any LV size restriction?
|
||||
uint64_t max_size = UINT_MAX;
|
||||
|
||||
if (lv->size > max_size) {
|
||||
@@ -297,40 +297,38 @@ static struct mda_header *_raw_read_mda_header(const struct format_type *fmt,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!dev_read(dev_area->dev, dev_area->start, MDA_HEADER_SIZE, mdah)) {
|
||||
stack;
|
||||
goto error;
|
||||
}
|
||||
if (!dev_read(dev_area->dev, dev_area->start, MDA_HEADER_SIZE, mdah))
|
||||
goto_bad;
|
||||
|
||||
if (mdah->checksum_xl != xlate32(calc_crc(INITIAL_CRC, mdah->magic,
|
||||
MDA_HEADER_SIZE -
|
||||
sizeof(mdah->checksum_xl)))) {
|
||||
log_error("Incorrect metadata area header checksum");
|
||||
goto error;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
_xlate_mdah(mdah);
|
||||
|
||||
if (strncmp((char *)mdah->magic, FMTT_MAGIC, sizeof(mdah->magic))) {
|
||||
log_error("Wrong magic number in metadata area header");
|
||||
goto error;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (mdah->version != FMTT_VERSION) {
|
||||
log_error("Incompatible metadata area header version: %d",
|
||||
mdah->version);
|
||||
goto error;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (mdah->start != dev_area->start) {
|
||||
log_error("Incorrect start sector in metadata area header: %"
|
||||
PRIu64, mdah->start);
|
||||
goto error;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
return mdah;
|
||||
|
||||
error:
|
||||
bad:
|
||||
dm_pool_free(fmt->cmd->mem, mdah);
|
||||
return NULL;
|
||||
}
|
||||
@@ -348,11 +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)) {
|
||||
stack;
|
||||
dm_pool_free(fmt->cmd->mem, mdah);
|
||||
return 0;
|
||||
}
|
||||
if (!dev_write(dev, start_byte, MDA_HEADER_SIZE, mdah))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -380,19 +375,18 @@ static struct raw_locn *_find_vg_rlocn(struct device_area *dev_area,
|
||||
/* FIXME Loop through rlocns two-at-a-time. List null-terminated. */
|
||||
/* FIXME Ignore if checksum incorrect!!! */
|
||||
if (!dev_read(dev_area->dev, dev_area->start + rlocn->offset,
|
||||
sizeof(vgnamebuf), vgnamebuf)) {
|
||||
stack;
|
||||
goto error;
|
||||
}
|
||||
sizeof(vgnamebuf), vgnamebuf))
|
||||
goto_bad;
|
||||
|
||||
if (!strncmp(vgnamebuf, vgname, len = strlen(vgname)) &&
|
||||
(isspace(vgnamebuf[len]) || vgnamebuf[len] == '{')) {
|
||||
return rlocn;
|
||||
}
|
||||
|
||||
error:
|
||||
if ((info = info_from_pvid(dev_area->dev->pvid)))
|
||||
lvmcache_update_vgname_and_id(info, ORPHAN, ORPHAN, 0, NULL);
|
||||
bad:
|
||||
if ((info = info_from_pvid(dev_area->dev->pvid, 0)))
|
||||
lvmcache_update_vgname_and_id(info, FMT_TEXT_ORPHAN_VG_NAME,
|
||||
FMT_TEXT_ORPHAN_VG_NAME, 0, NULL);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -422,15 +416,11 @@ static int _raw_holds_vgname(struct format_instance *fid,
|
||||
int noprecommit = 0;
|
||||
struct mda_header *mdah;
|
||||
|
||||
if (!dev_open(dev_area->dev)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!dev_open(dev_area->dev))
|
||||
return_0;
|
||||
|
||||
if (!(mdah = _raw_read_mda_header(fid->fmt, dev_area))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(mdah = _raw_read_mda_header(fid->fmt, dev_area)))
|
||||
return_0;
|
||||
|
||||
if (_find_vg_rlocn(dev_area, mdah, vgname, &noprecommit))
|
||||
r = 1;
|
||||
@@ -453,15 +443,11 @@ static struct volume_group *_vg_read_raw_area(struct format_instance *fid,
|
||||
char *desc;
|
||||
uint32_t wrap = 0;
|
||||
|
||||
if (!dev_open(area->dev)) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!dev_open(area->dev))
|
||||
return_NULL;
|
||||
|
||||
if (!(mdah = _raw_read_mda_header(fid->fmt, area))) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
if (!(mdah = _raw_read_mda_header(fid->fmt, area)))
|
||||
goto_out;
|
||||
|
||||
if (!(rlocn = _find_vg_rlocn(area, mdah, vgname, &precommitted))) {
|
||||
log_debug("VG %s not found on %s", vgname, dev_name(area->dev));
|
||||
@@ -483,10 +469,8 @@ static struct volume_group *_vg_read_raw_area(struct format_instance *fid,
|
||||
(uint32_t) (rlocn->size - wrap),
|
||||
(off_t) (area->start + MDA_HEADER_SIZE),
|
||||
wrap, calc_crc, rlocn->checksum, &when,
|
||||
&desc))) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
&desc)))
|
||||
goto_out;
|
||||
log_debug("Read %s %smetadata (%u) from %s at %" PRIu64 " size %"
|
||||
PRIu64, vg->name, precommitted ? "pre-commit " : "",
|
||||
vg->seqno, dev_name(area->dev),
|
||||
@@ -544,15 +528,11 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
|
||||
if (!found)
|
||||
return 1;
|
||||
|
||||
if (!dev_open(mdac->area.dev)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!dev_open(mdac->area.dev))
|
||||
return_0;
|
||||
|
||||
if (!(mdah = _raw_read_mda_header(fid->fmt, &mdac->area))) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
if (!(mdah = _raw_read_mda_header(fid->fmt, &mdac->area)))
|
||||
goto_out;
|
||||
|
||||
rlocn = _find_vg_rlocn(&mdac->area, mdah, vg->name, &noprecommit);
|
||||
mdac->rlocn.offset = _next_rlocn_offset(rlocn, mdah);
|
||||
@@ -589,10 +569,8 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
|
||||
/* Write text out, circularly */
|
||||
if (!dev_write(mdac->area.dev, mdac->area.start + mdac->rlocn.offset,
|
||||
(size_t) (mdac->rlocn.size - new_wrap),
|
||||
fidtc->raw_metadata_buf)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
fidtc->raw_metadata_buf))
|
||||
goto_out;
|
||||
|
||||
if (new_wrap) {
|
||||
log_debug("Writing metadata to %s at %" PRIu64 " len %" PRIu32,
|
||||
@@ -602,11 +580,9 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
|
||||
if (!dev_write(mdac->area.dev,
|
||||
mdac->area.start + MDA_HEADER_SIZE,
|
||||
(size_t) new_wrap,
|
||||
fidtc->raw_metadata_buf +
|
||||
mdac->rlocn.size - new_wrap)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
fidtc->raw_metadata_buf +
|
||||
mdac->rlocn.size - new_wrap))
|
||||
goto_out;
|
||||
}
|
||||
|
||||
mdac->rlocn.checksum = calc_crc(INITIAL_CRC, fidtc->raw_metadata_buf,
|
||||
@@ -652,10 +628,8 @@ static int _vg_commit_raw_rlocn(struct format_instance *fid,
|
||||
if (!found)
|
||||
return 1;
|
||||
|
||||
if (!(mdah = _raw_read_mda_header(fid->fmt, &mdac->area))) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
if (!(mdah = _raw_read_mda_header(fid->fmt, &mdac->area)))
|
||||
goto_out;
|
||||
|
||||
if (!(rlocn = _find_vg_rlocn(&mdac->area, mdah, vg->name, &noprecommit))) {
|
||||
mdah->raw_locns[0].offset = 0;
|
||||
@@ -694,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;
|
||||
}
|
||||
@@ -759,15 +734,11 @@ static int _vg_remove_raw(struct format_instance *fid, struct volume_group *vg,
|
||||
int r = 0;
|
||||
int noprecommit = 0;
|
||||
|
||||
if (!dev_open(mdac->area.dev)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!dev_open(mdac->area.dev))
|
||||
return_0;
|
||||
|
||||
if (!(mdah = _raw_read_mda_header(fid->fmt, &mdac->area))) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
if (!(mdah = _raw_read_mda_header(fid->fmt, &mdac->area)))
|
||||
goto_out;
|
||||
|
||||
if (!(rlocn = _find_vg_rlocn(&mdac->area, mdah, vg->name, &noprecommit))) {
|
||||
rlocn = &mdah->raw_locns[0];
|
||||
@@ -780,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;
|
||||
}
|
||||
@@ -801,10 +773,8 @@ static struct volume_group *_vg_read_file_name(struct format_instance *fid,
|
||||
time_t when;
|
||||
char *desc;
|
||||
|
||||
if (!(vg = text_vg_import_file(fid, read_path, &when, &desc))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!(vg = text_vg_import_file(fid, read_path, &when, &desc)))
|
||||
return_NULL;
|
||||
|
||||
/*
|
||||
* Currently you can only have a single volume group per
|
||||
@@ -1038,7 +1008,7 @@ static int _scan_file(const struct format_type *fmt)
|
||||
if ((vg = _vg_read_file_name(fid, vgname,
|
||||
path)))
|
||||
/* FIXME Store creation host in vg */
|
||||
lvmcache_update_vg(vg);
|
||||
lvmcache_update_vg(vg, 0);
|
||||
}
|
||||
|
||||
if (closedir(d))
|
||||
@@ -1065,10 +1035,8 @@ const char *vgname_from_mda(const struct format_type *fmt,
|
||||
if (mda_free_sectors)
|
||||
*mda_free_sectors = ((dev_area->size - MDA_HEADER_SIZE) / 2) >> SECTOR_SHIFT;
|
||||
|
||||
if (!dev_open(dev_area->dev)) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!dev_open(dev_area->dev))
|
||||
return_NULL;
|
||||
|
||||
if (!(mdah = _raw_read_mda_header(fmt, dev_area)))
|
||||
goto_out;
|
||||
@@ -1114,20 +1082,18 @@ const char *vgname_from_mda(const struct format_type *fmt,
|
||||
|
||||
/* Ignore this entry if the characters aren't permissible */
|
||||
if (!validate_name(vgname)) {
|
||||
stack;
|
||||
vgname = NULL;
|
||||
goto out;
|
||||
goto_out;
|
||||
}
|
||||
|
||||
if (!id_write_format(vgid, uuid, sizeof(uuid))) {
|
||||
stack;
|
||||
vgname = NULL;
|
||||
goto out;
|
||||
goto_out;
|
||||
}
|
||||
|
||||
log_debug("%s: Found metadata at %" PRIu64 " size %" PRIu64
|
||||
" (in area at %" PRIu64 " size %" PRIu64
|
||||
") for %s (%s)",
|
||||
") for %s (%s)",
|
||||
dev_name(dev_area->dev), dev_area->start + rlocn->offset,
|
||||
rlocn->size, dev_area->start, dev_area->size, vgname, uuid);
|
||||
|
||||
@@ -1170,7 +1136,7 @@ static int _scan_raw(const struct format_type *fmt)
|
||||
NULL, NULL))) {
|
||||
if ((vg = _vg_read_raw_area(&fid, vgname,
|
||||
&rl->dev_area, 0)))
|
||||
lvmcache_update_vg(vg);
|
||||
lvmcache_update_vg(vg, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1328,10 +1294,8 @@ static int _text_pv_write(const struct format_type *fmt, struct physical_volume
|
||||
/* FIXME Test mode don't update cache? */
|
||||
|
||||
if (!(info = lvmcache_add(fmt->labeller, (char *) &pv->id, pv->dev,
|
||||
ORPHAN, NULL, 0))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
FMT_TEXT_ORPHAN_VG_NAME, NULL, 0)))
|
||||
return_0;
|
||||
label = info->label;
|
||||
|
||||
if (label_sector != -1)
|
||||
@@ -1367,7 +1331,7 @@ static int _text_pv_write(const struct format_type *fmt, struct physical_volume
|
||||
else
|
||||
list_init(&info->das);
|
||||
|
||||
/* Set pe_start to first aligned sector after any metadata
|
||||
/* Set pe_start to first aligned sector after any metadata
|
||||
* areas that begin before pe_start */
|
||||
pv->pe_start = pe_align();
|
||||
list_iterate_items(mda, &info->mdas) {
|
||||
@@ -1384,15 +1348,11 @@ static int _text_pv_write(const struct format_type *fmt, struct physical_volume
|
||||
}
|
||||
}
|
||||
if (!add_da
|
||||
(NULL, &info->das, pv->pe_start << SECTOR_SHIFT, UINT64_C(0))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
(NULL, &info->das, pv->pe_start << SECTOR_SHIFT, UINT64_C(0)))
|
||||
return_0;
|
||||
|
||||
if (!dev_open(pv->dev)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!dev_open(pv->dev))
|
||||
return_0;
|
||||
|
||||
list_iterate_items(mda, &info->mdas) {
|
||||
mdac = mda->metadata_locn;
|
||||
@@ -1400,20 +1360,20 @@ static int _text_pv_write(const struct format_type *fmt, struct physical_volume
|
||||
mdah->size = mdac->area.size;
|
||||
if (!_raw_write_mda_header(fmt, mdac->area.dev,
|
||||
mdac->area.start, mdah)) {
|
||||
stack;
|
||||
if (!dev_close(pv->dev))
|
||||
stack;
|
||||
return 0;
|
||||
return_0;
|
||||
}
|
||||
}
|
||||
|
||||
label_write(pv->dev, label);
|
||||
|
||||
if (!dev_close(pv->dev)) {
|
||||
stack;
|
||||
return 0;
|
||||
if (!label_write(pv->dev, label)) {
|
||||
dev_close(pv->dev);
|
||||
return_0;
|
||||
}
|
||||
|
||||
if (!dev_close(pv->dev))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1439,6 +1399,55 @@ static int _add_raw(struct list *raw_list, struct device_area *dev_area)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _get_pv_if_in_vg(struct lvmcache_info *info,
|
||||
struct physical_volume *pv)
|
||||
{
|
||||
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))
|
||||
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(info->fmt->cmd, 2);
|
||||
|
||||
if (_get_pv_if_in_vg(info, pv))
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Orphan */
|
||||
pv->dev = info->dev;
|
||||
pv->fmt = info->fmt;
|
||||
pv->size = info->device_size >> SECTOR_SHIFT;
|
||||
pv->vg_name = FMT_TEXT_ORPHAN_VG_NAME;
|
||||
memcpy(&pv->id, &info->dev->pvid, sizeof(pv->id));
|
||||
|
||||
/* 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(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)
|
||||
{
|
||||
@@ -1447,57 +1456,16 @@ static int _text_pv_read(const struct format_type *fmt, const char *pv_name,
|
||||
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))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
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)))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
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)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Perform full scan (just the first time) and try again */
|
||||
if (!memlock() && !full_scan_done()) {
|
||||
lvmcache_label_scan(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)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Orphan */
|
||||
pv->dev = info->dev;
|
||||
pv->fmt = info->fmt;
|
||||
pv->size = info->device_size >> SECTOR_SHIFT;
|
||||
pv->vg_name = ORPHAN;
|
||||
memcpy(&pv->id, &info->dev->pvid, sizeof(pv->id));
|
||||
|
||||
/* 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));
|
||||
if (!_populate_pv_fields(info, pv))
|
||||
return 0;
|
||||
}
|
||||
|
||||
list_iterate_items(da, &info->das)
|
||||
pv->pe_start = da->disk_locn.offset >> SECTOR_SHIFT;
|
||||
|
||||
if (!mdas)
|
||||
return 1;
|
||||
@@ -1610,7 +1578,7 @@ static int _text_pv_setup(const struct format_type *fmt,
|
||||
/* If new vg, add any further mdas on this PV to the fid's mda list */
|
||||
if (vg) {
|
||||
/* Iterate through all mdas on this PV */
|
||||
if ((info = info_from_pvid(pv->dev->pvid))) {
|
||||
if ((info = info_from_pvid(pv->dev->pvid, 0))) {
|
||||
pvmdas = &info->mdas;
|
||||
list_iterate_items(mda, pvmdas) {
|
||||
mda_count++;
|
||||
@@ -1642,16 +1610,12 @@ static int _text_pv_setup(const struct format_type *fmt,
|
||||
continue;
|
||||
|
||||
if (!(mda_new = dm_pool_alloc(fmt->cmd->mem,
|
||||
sizeof(*mda_new)))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
sizeof(*mda_new))))
|
||||
return_0;
|
||||
|
||||
if (!(mdac_new = dm_pool_alloc(fmt->cmd->mem,
|
||||
sizeof(*mdac_new)))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
sizeof(*mdac_new))))
|
||||
return_0;
|
||||
/* FIXME multiple dev_areas inside area */
|
||||
memcpy(mda_new, mda, sizeof(*mda));
|
||||
memcpy(mdac_new, mdac, sizeof(*mdac));
|
||||
@@ -1687,11 +1651,8 @@ static int _text_pv_setup(const struct format_type *fmt,
|
||||
if (extent_count)
|
||||
pe_end = pe_start + extent_count * extent_size - 1;
|
||||
if (!_mda_setup(fmt, pe_start, pe_end, pvmetadatacopies,
|
||||
pvmetadatasize, mdas, pv, vg)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
pvmetadatasize, mdas, pv, vg))
|
||||
return_0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -1732,10 +1693,8 @@ static struct format_instance *_text_create_text_instance(const struct format_ty
|
||||
list_init(&fid->metadata_areas);
|
||||
|
||||
if (!vgname) {
|
||||
if (!(mda = dm_pool_alloc(fmt->cmd->mem, sizeof(*mda)))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!(mda = dm_pool_alloc(fmt->cmd->mem, sizeof(*mda))))
|
||||
return_NULL;
|
||||
mda->ops = &_metadata_text_file_backup_ops;
|
||||
mda->metadata_locn = context;
|
||||
list_add(&fid->metadata_areas, &mda->list);
|
||||
@@ -1751,10 +1710,8 @@ static struct format_instance *_text_create_text_instance(const struct format_ty
|
||||
}
|
||||
|
||||
context = create_text_context(fmt->cmd, path, NULL);
|
||||
if (!(mda = dm_pool_alloc(fmt->cmd->mem, sizeof(*mda)))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!(mda = dm_pool_alloc(fmt->cmd->mem, sizeof(*mda))))
|
||||
return_NULL;
|
||||
mda->ops = &_metadata_text_file_ops;
|
||||
mda->metadata_locn = context;
|
||||
list_add(&fid->metadata_areas, &mda->list);
|
||||
@@ -1767,15 +1724,11 @@ static struct format_instance *_text_create_text_instance(const struct format_ty
|
||||
if (!_raw_holds_vgname(fid, &rl->dev_area, vgname))
|
||||
continue;
|
||||
|
||||
if (!(mda = dm_pool_alloc(fmt->cmd->mem, sizeof(*mda)))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!(mda = dm_pool_alloc(fmt->cmd->mem, sizeof(*mda))))
|
||||
return_NULL;
|
||||
|
||||
if (!(mdac = dm_pool_alloc(fmt->cmd->mem, sizeof(*mdac)))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!(mdac = dm_pool_alloc(fmt->cmd->mem, sizeof(*mdac))))
|
||||
return_NULL;
|
||||
mda->metadata_locn = mdac;
|
||||
/* FIXME Allow multiple dev_areas inside area */
|
||||
memcpy(&mdac->area, &rl->dev_area, sizeof(mdac->area));
|
||||
@@ -1786,10 +1739,8 @@ static struct format_instance *_text_create_text_instance(const struct format_ty
|
||||
|
||||
/* Scan PVs in VG for any further MDAs */
|
||||
lvmcache_label_scan(fmt->cmd, 0);
|
||||
if (!(vginfo = vginfo_from_vgname(vgname, vgid))) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
if (!(vginfo = vginfo_from_vgname(vgname, vgid)))
|
||||
goto_out;
|
||||
list_iterate_items(info, &vginfo->infos) {
|
||||
mdas = &info->mdas;
|
||||
list_iterate_items(mda, mdas) {
|
||||
@@ -1798,16 +1749,12 @@ static struct format_instance *_text_create_text_instance(const struct format_ty
|
||||
|
||||
/* FIXME Check it holds this VG */
|
||||
if (!(mda_new = dm_pool_alloc(fmt->cmd->mem,
|
||||
sizeof(*mda_new)))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
sizeof(*mda_new))))
|
||||
return_NULL;
|
||||
|
||||
if (!(mdac_new = dm_pool_alloc(fmt->cmd->mem,
|
||||
sizeof(*mdac_new)))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
sizeof(*mdac_new))))
|
||||
return_NULL;
|
||||
/* FIXME multiple dev_areas inside area */
|
||||
memcpy(mda_new, mda, sizeof(*mda));
|
||||
memcpy(mdac_new, mdac, sizeof(*mdac));
|
||||
@@ -1834,33 +1781,26 @@ void *create_text_context(struct cmd_context *cmd, const char *path,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(tc = dm_pool_alloc(cmd->mem, sizeof(*tc)))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!(tc = dm_pool_alloc(cmd->mem, sizeof(*tc))))
|
||||
return_NULL;
|
||||
|
||||
if (!(tc->path_live = dm_pool_strdup(cmd->mem, path))) {
|
||||
stack;
|
||||
goto no_mem;
|
||||
}
|
||||
if (!(tc->path_live = dm_pool_strdup(cmd->mem, path)))
|
||||
goto_bad;
|
||||
|
||||
if (!(tc->path_edit = dm_pool_alloc(cmd->mem, strlen(path) + 5)))
|
||||
goto_bad;
|
||||
|
||||
if (!(tc->path_edit = dm_pool_alloc(cmd->mem, strlen(path) + 5))) {
|
||||
stack;
|
||||
goto no_mem;
|
||||
}
|
||||
sprintf(tc->path_edit, "%s.tmp", path);
|
||||
|
||||
if (!desc)
|
||||
desc = "";
|
||||
|
||||
if (!(tc->desc = dm_pool_strdup(cmd->mem, desc))) {
|
||||
stack;
|
||||
goto no_mem;
|
||||
}
|
||||
if (!(tc->desc = dm_pool_strdup(cmd->mem, desc)))
|
||||
goto_bad;
|
||||
|
||||
return (void *) tc;
|
||||
|
||||
no_mem:
|
||||
bad:
|
||||
dm_pool_free(cmd->mem, tc);
|
||||
|
||||
log_err("Couldn't allocate text format context object.");
|
||||
@@ -1956,15 +1896,14 @@ struct format_type *create_text_format(struct cmd_context *cmd)
|
||||
struct config_value *cv;
|
||||
struct mda_lists *mda_lists;
|
||||
|
||||
if (!(fmt = dm_malloc(sizeof(*fmt)))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!(fmt = dm_malloc(sizeof(*fmt))))
|
||||
return_NULL;
|
||||
|
||||
fmt->cmd = cmd;
|
||||
fmt->ops = &_text_handler;
|
||||
fmt->name = FMT_TEXT_NAME;
|
||||
fmt->alias = FMT_TEXT_ALIAS;
|
||||
fmt->orphan_vg_name = ORPHAN_VG_NAME(FMT_TEXT_NAME);
|
||||
fmt->features = FMT_SEGMENTS | FMT_MDAS | FMT_TAGS | FMT_PRECOMMIT |
|
||||
FMT_UNLIMITED_VOLS | FMT_RESIZE_PV |
|
||||
FMT_UNLIMITED_STRIPESIZE;
|
||||
|
||||
@@ -19,6 +19,10 @@
|
||||
#include "lvm-types.h"
|
||||
#include "metadata.h"
|
||||
|
||||
#define FMT_TEXT_NAME "lvm2"
|
||||
#define FMT_TEXT_ALIAS "text"
|
||||
#define FMT_TEXT_ORPHAN_VG_NAME ORPHAN_VG_NAME(FMT_TEXT_NAME)
|
||||
|
||||
/*
|
||||
* Archives a vg config. 'retain_days' is the minimum number of
|
||||
* days that an archive file must be held for. 'min_archives' is
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@@ -23,6 +23,18 @@
|
||||
/* FIXME Use tidier inclusion method */
|
||||
static struct text_vg_version_ops *(_text_vsn_list[2]);
|
||||
|
||||
static int _text_import_initialised = 0;
|
||||
|
||||
static void _init_text_import()
|
||||
{
|
||||
if (_text_import_initialised)
|
||||
return;
|
||||
|
||||
_text_vsn_list[0] = text_vg_vsn1_init();
|
||||
_text_vsn_list[1] = NULL;
|
||||
_text_import_initialised = 1;
|
||||
}
|
||||
|
||||
const char *text_vgname_import(const struct format_type *fmt,
|
||||
struct device *dev,
|
||||
off_t offset, uint32_t size,
|
||||
@@ -35,13 +47,7 @@ const char *text_vgname_import(const struct format_type *fmt,
|
||||
struct text_vg_version_ops **vsn;
|
||||
const char *vgname = NULL;
|
||||
|
||||
static int _text_import_initialised = 0;
|
||||
|
||||
if (!_text_import_initialised) {
|
||||
_text_vsn_list[0] = text_vg_vsn1_init();
|
||||
_text_vsn_list[1] = NULL;
|
||||
_text_import_initialised = 1;
|
||||
}
|
||||
_init_text_import();
|
||||
|
||||
if (!(cft = create_config_tree(NULL, 0)))
|
||||
return_NULL;
|
||||
@@ -51,7 +57,7 @@ const char *text_vgname_import(const struct format_type *fmt,
|
||||
offset2, size2, checksum_fn, checksum)))
|
||||
goto_out;
|
||||
|
||||
/*
|
||||
/*
|
||||
* Find a set of version functions that can read this file
|
||||
*/
|
||||
for (vsn = &_text_vsn_list[0]; *vsn; vsn++) {
|
||||
@@ -83,13 +89,7 @@ struct volume_group *text_vg_import_fd(struct format_instance *fid,
|
||||
struct config_tree *cft;
|
||||
struct text_vg_version_ops **vsn;
|
||||
|
||||
static int _text_vg_import_initialised = 0;
|
||||
|
||||
if (!_text_vg_import_initialised) {
|
||||
_text_vsn_list[0] = text_vg_vsn1_init();
|
||||
_text_vsn_list[1] = NULL;
|
||||
_text_vg_import_initialised = 1;
|
||||
}
|
||||
_init_text_import();
|
||||
|
||||
*desc = NULL;
|
||||
*when = 0;
|
||||
@@ -104,17 +104,15 @@ struct volume_group *text_vg_import_fd(struct format_instance *fid,
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* Find a set of version functions that can read this file
|
||||
*/
|
||||
for (vsn = &_text_vsn_list[0]; *vsn; vsn++) {
|
||||
if (!(*vsn)->check_version(cft))
|
||||
continue;
|
||||
|
||||
if (!(vg = (*vsn)->read_vg(fid, cft))) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
if (!(vg = (*vsn)->read_vg(fid, cft)))
|
||||
goto_out;
|
||||
|
||||
(*vsn)->read_desc(fid->fmt->cmd->mem, cft, when, desc);
|
||||
break;
|
||||
@@ -132,3 +130,27 @@ struct volume_group *text_vg_import_file(struct format_instance *fid,
|
||||
return text_vg_import_fd(fid, file, NULL, (off_t)0, 0, (off_t)0, 0, NULL, 0,
|
||||
when, desc);
|
||||
}
|
||||
|
||||
struct volume_group *import_vg_from_buffer(char *buf,
|
||||
struct format_instance *fid)
|
||||
{
|
||||
struct volume_group *vg = NULL;
|
||||
struct config_tree *cft;
|
||||
struct text_vg_version_ops **vsn;
|
||||
|
||||
_init_text_import();
|
||||
|
||||
if (!(cft = create_config_tree_from_string(fid->fmt->cmd, buf)))
|
||||
return_NULL;
|
||||
|
||||
for (vsn = &_text_vsn_list[0]; *vsn; vsn++) {
|
||||
if (!(*vsn)->check_version(cft))
|
||||
continue;
|
||||
if (!(vg = (*vsn)->read_vg(fid, cft)))
|
||||
stack;
|
||||
break;
|
||||
}
|
||||
|
||||
destroy_config_tree(cft);
|
||||
return vg;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
@@ -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)),
|
||||
@@ -136,10 +161,8 @@ static int _read_pv(struct format_instance *fid, struct dm_pool *mem,
|
||||
uint64_t size;
|
||||
|
||||
if (!(pvl = dm_pool_zalloc(mem, sizeof(*pvl))) ||
|
||||
!(pvl->pv = dm_pool_zalloc(mem, sizeof(*pvl->pv)))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
!(pvl->pv = dm_pool_zalloc(mem, sizeof(*pvl->pv))))
|
||||
return_0;
|
||||
|
||||
pv = pvl->pv;
|
||||
|
||||
@@ -147,10 +170,8 @@ static int _read_pv(struct format_instance *fid, struct dm_pool *mem,
|
||||
* Add the pv to the pv hash for quick lookup when we read
|
||||
* the lv segments.
|
||||
*/
|
||||
if (!dm_hash_insert(pv_hash, pvn->key, pv)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!dm_hash_insert(pv_hash, pvn->key, pv))
|
||||
return_0;
|
||||
|
||||
if (!(pvn = pvn->child)) {
|
||||
log_error("Empty pv section.");
|
||||
@@ -180,19 +201,12 @@ static int _read_pv(struct format_instance *fid, struct dm_pool *mem,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(pv->vg_name = dm_pool_strdup(mem, vg->name))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(pv->vg_name = dm_pool_strdup(mem, vg->name)))
|
||||
return_0;
|
||||
|
||||
memcpy(&pv->vgid, &vg->id, sizeof(vg->id));
|
||||
|
||||
if (!(cn = find_config_node(pvn, "status"))) {
|
||||
log_error("Couldn't find status flags for physical volume.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -231,30 +245,28 @@ static int _read_pv(struct format_instance *fid, struct dm_pool *mem,
|
||||
pv->pe_alloc_count = 0;
|
||||
pv->fmt = fid->fmt;
|
||||
|
||||
/* Fix up pv size if missing or impossibly large */
|
||||
if ((!pv->size || pv->size > (1ULL << 62)) && pv->dev) {
|
||||
if (!dev_get_size(pv->dev, &pv->size)) {
|
||||
log_error("%s: Couldn't get size.", pv_dev_name(pv));
|
||||
return 0;
|
||||
}
|
||||
log_verbose("Fixing up missing size (%s) "
|
||||
"for PV %s", display_size(fid->fmt->cmd, pv->size),
|
||||
pv_dev_name(pv));
|
||||
if (vg) {
|
||||
size = pv->pe_count * (uint64_t) vg->extent_size +
|
||||
pv->pe_start;
|
||||
if (size > pv->size)
|
||||
log_error("WARNING: Physical Volume %s is too "
|
||||
"large for underlying device",
|
||||
pv_dev_name(pv));
|
||||
}
|
||||
}
|
||||
|
||||
if (!alloc_pv_segment_whole_pv(mem, pv)) {
|
||||
stack;
|
||||
return 0;
|
||||
/* Fix up pv size if missing or impossibly large */
|
||||
if ((!pv->size || pv->size > (1ULL << 62)) && pv->dev) {
|
||||
if (!dev_get_size(pv->dev, &pv->size)) {
|
||||
log_error("%s: Couldn't get size.", pv_dev_name(pv));
|
||||
return 0;
|
||||
}
|
||||
log_verbose("Fixing up missing size (%s) "
|
||||
"for PV %s", display_size(fid->fmt->cmd, pv->size),
|
||||
pv_dev_name(pv));
|
||||
if (vg) {
|
||||
size = pv->pe_count * (uint64_t) vg->extent_size +
|
||||
pv->pe_start;
|
||||
if (size > pv->size)
|
||||
log_error("WARNING: Physical Volume %s is too "
|
||||
"large for underlying device",
|
||||
pv_dev_name(pv));
|
||||
}
|
||||
}
|
||||
|
||||
if (!alloc_pv_segment_whole_pv(mem, pv))
|
||||
return_0;
|
||||
|
||||
vg->pv_count++;
|
||||
list_add(&vg->pvs, &pvl->list);
|
||||
|
||||
@@ -316,16 +328,12 @@ static int _read_segment(struct dm_pool *mem, struct volume_group *vg,
|
||||
segtype_str = cv->v.str;
|
||||
}
|
||||
|
||||
if (!(segtype = get_segtype_from_string(vg->cmd, segtype_str))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(segtype = get_segtype_from_string(vg->cmd, segtype_str)))
|
||||
return_0;
|
||||
|
||||
if (segtype->ops->text_import_area_count &&
|
||||
!segtype->ops->text_import_area_count(sn, &area_count)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
!segtype->ops->text_import_area_count(sn, &area_count))
|
||||
return_0;
|
||||
|
||||
if (!(seg = alloc_lv_segment(mem, segtype, lv, start_extent,
|
||||
extent_count, 0, 0, NULL, area_count,
|
||||
@@ -335,10 +343,8 @@ static int _read_segment(struct dm_pool *mem, struct volume_group *vg,
|
||||
}
|
||||
|
||||
if (seg->segtype->ops->text_import &&
|
||||
!seg->segtype->ops->text_import(seg, sn, pv_hash)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
!seg->segtype->ops->text_import(seg, sn, pv_hash))
|
||||
return_0;
|
||||
|
||||
/* Optional tags */
|
||||
if ((cn = find_config_node(sn, "tags")) &&
|
||||
@@ -403,10 +409,8 @@ int text_import_areas(struct lv_segment *seg, const struct config_node *sn,
|
||||
|
||||
/* FIXME Cope if LV not yet read in */
|
||||
if ((pv = dm_hash_lookup(pv_hash, cv->v.str))) {
|
||||
if (!set_lv_segment_area_pv(seg, s, pv, (uint32_t) cv->next->v.i)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!set_lv_segment_area_pv(seg, s, pv, (uint32_t) cv->next->v.i))
|
||||
return_0;
|
||||
} else if ((lv1 = find_lv(seg->lv->vg, cv->v.str))) {
|
||||
if (!set_lv_segment_area_lv(seg, s, lv1,
|
||||
(uint32_t) cv->next->v.i,
|
||||
@@ -447,10 +451,8 @@ static int _read_segments(struct dm_pool *mem, struct volume_group *vg,
|
||||
* All sub-sections are assumed to be segments.
|
||||
*/
|
||||
if (!sn->v) {
|
||||
if (!_read_segment(mem, vg, lv, sn, pv_hash)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!_read_segment(mem, vg, lv, sn, pv_hash))
|
||||
return_0;
|
||||
|
||||
count++;
|
||||
}
|
||||
@@ -475,18 +477,14 @@ static int _read_segments(struct dm_pool *mem, struct volume_group *vg,
|
||||
/*
|
||||
* Check there are no gaps or overlaps in the lv.
|
||||
*/
|
||||
if (!check_lv_segments(lv, 0)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!check_lv_segments(lv, 0))
|
||||
return_0;
|
||||
|
||||
/*
|
||||
* Merge segments in case someones been editing things by hand.
|
||||
*/
|
||||
if (!lv_merge_segments(lv)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!lv_merge_segments(lv))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -502,30 +500,22 @@ static int _read_lvnames(struct format_instance *fid __attribute((unused)),
|
||||
struct config_node *cn;
|
||||
|
||||
if (!(lvl = dm_pool_zalloc(mem, sizeof(*lvl))) ||
|
||||
!(lvl->lv = dm_pool_zalloc(mem, sizeof(*lvl->lv)))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
!(lvl->lv = dm_pool_zalloc(mem, sizeof(*lvl->lv))))
|
||||
return_0;
|
||||
|
||||
lv = lvl->lv;
|
||||
|
||||
if (!(lv->name = dm_pool_strdup(mem, lvn->key))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(lv->name = dm_pool_strdup(mem, lvn->key)))
|
||||
return_0;
|
||||
|
||||
if (!(lvn = lvn->child)) {
|
||||
log_error("Empty logical volume section.");
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -538,10 +528,8 @@ static int _read_lvnames(struct format_instance *fid __attribute((unused)),
|
||||
}
|
||||
|
||||
lv->alloc = get_alloc_from_string(cv->v.str);
|
||||
if (lv->alloc == ALLOC_INVALID) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (lv->alloc == ALLOC_INVALID)
|
||||
return_0;
|
||||
}
|
||||
|
||||
if (!_read_int32(lvn, "read_ahead", &lv->read_ahead))
|
||||
@@ -552,7 +540,7 @@ static int _read_lvnames(struct format_instance *fid __attribute((unused)),
|
||||
case 0:
|
||||
lv->read_ahead = DM_READ_AHEAD_AUTO;
|
||||
break;
|
||||
case -1:
|
||||
case (uint32_t) -1:
|
||||
lv->read_ahead = DM_READ_AHEAD_NONE;
|
||||
break;
|
||||
default:
|
||||
@@ -611,10 +599,8 @@ static int _read_lvsegs(struct format_instance *fid __attribute((unused)),
|
||||
|
||||
memcpy(&lv->lvid.id[0], &lv->vg->id, sizeof(lv->lvid.id[0]));
|
||||
|
||||
if (!_read_segments(mem, vg, lv, lvn, pv_hash)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!_read_segments(mem, vg, lv, lvn, pv_hash))
|
||||
return_0;
|
||||
|
||||
lv->size = (uint64_t) lv->le_count * (uint64_t) vg->extent_size;
|
||||
|
||||
@@ -664,10 +650,8 @@ static int _read_sections(struct format_instance *fid,
|
||||
}
|
||||
|
||||
for (n = n->child; n; n = n->sib) {
|
||||
if (!fn(fid, mem, vg, n, vgn, pv_hash)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!fn(fid, mem, vg, n, vgn, pv_hash))
|
||||
return_0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -689,10 +673,8 @@ static struct volume_group *_read_vg(struct format_instance *fid,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(vg = dm_pool_zalloc(mem, sizeof(*vg)))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!(vg = dm_pool_zalloc(mem, sizeof(*vg))))
|
||||
return_NULL;
|
||||
vg->cmd = fid->fmt->cmd;
|
||||
|
||||
/* FIXME Determine format type from file contents */
|
||||
@@ -726,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;
|
||||
}
|
||||
@@ -770,10 +746,8 @@ static struct volume_group *_read_vg(struct format_instance *fid,
|
||||
}
|
||||
|
||||
vg->alloc = get_alloc_from_string(cv->v.str);
|
||||
if (vg->alloc == ALLOC_INVALID) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (vg->alloc == ALLOC_INVALID)
|
||||
return_0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -862,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;
|
||||
@@ -870,7 +844,7 @@ static const char *_read_vgname(const struct format_type *fmt,
|
||||
old_suppress = log_suppress(2);
|
||||
*creation_host = dm_pool_strdup(mem,
|
||||
find_config_str(cft->root,
|
||||
"creation_host", ""));
|
||||
"creation_host", ""));
|
||||
log_suppress(old_suppress);
|
||||
|
||||
/* skip any top-level values */
|
||||
@@ -891,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
@@ -24,30 +24,22 @@ int print_tags(struct list *tags, char *buffer, size_t size)
|
||||
struct str_list *sl;
|
||||
int first = 1;
|
||||
|
||||
if (!emit_to_buffer(&buffer, &size, "[")) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!emit_to_buffer(&buffer, &size, "["))
|
||||
return_0;
|
||||
|
||||
list_iterate_items(sl, tags) {
|
||||
if (!first) {
|
||||
if (!emit_to_buffer(&buffer, &size, ", ")) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!emit_to_buffer(&buffer, &size, ", "))
|
||||
return_0;
|
||||
} else
|
||||
first = 0;
|
||||
|
||||
if (!emit_to_buffer(&buffer, &size, "\"%s\"", sl->str)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!emit_to_buffer(&buffer, &size, "\"%s\"", sl->str))
|
||||
return_0;
|
||||
}
|
||||
|
||||
if (!emit_to_buffer(&buffer, &size, "]")) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!emit_to_buffer(&buffer, &size, "]"))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -63,10 +55,8 @@ int read_tags(struct dm_pool *mem, struct list *tags, struct config_value *cv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!str_list_add(mem, tags, dm_pool_strdup(mem, cv->v.str))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!str_list_add(mem, tags, dm_pool_strdup(mem, cv->v.str)))
|
||||
return_0;
|
||||
|
||||
cv = cv->next;
|
||||
}
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
#ifndef _LVM_TEXT_EXPORT_H
|
||||
#define _LVM_TEXT_EXPORT_H
|
||||
|
||||
#define outf(args...) do {if (!out_text(args)) {stack; return 0;}} while (0)
|
||||
#define outnl(f) do {if (!f->nl(f)) {stack; return 0;}} while (0)
|
||||
#define outf(args...) do {if (!out_text(args)) return_0;} while (0)
|
||||
#define outnl(f) do {if (!f->nl(f)) return_0;} while (0)
|
||||
|
||||
struct formatter;
|
||||
struct lv_segment;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
@@ -207,7 +207,9 @@ static int _text_read(struct labeller *l, struct device *dev, void *buf,
|
||||
|
||||
pvhdr = (struct pv_header *) ((void *) buf + xlate32(lh->offset_xl));
|
||||
|
||||
if (!(info = lvmcache_add(l, (char *)pvhdr->pv_uuid, dev, NULL, NULL, 0)))
|
||||
if (!(info = lvmcache_add(l, (char *)pvhdr->pv_uuid, dev,
|
||||
FMT_TEXT_ORPHAN_VG_NAME,
|
||||
FMT_TEXT_ORPHAN_VG_NAME, 0)))
|
||||
return_0;
|
||||
*label = info->label;
|
||||
|
||||
@@ -239,7 +241,7 @@ static int _text_read(struct labeller *l, struct device *dev, void *buf,
|
||||
|
||||
list_iterate_items(mda, &info->mdas) {
|
||||
mdac = (struct mda_context *) mda->metadata_locn;
|
||||
if ((vgname = vgname_from_mda(info->fmt, &mdac->area,
|
||||
if ((vgname = vgname_from_mda(info->fmt, &mdac->area,
|
||||
&vgid, &vgstatus, &creation_host,
|
||||
&mdac->free_sectors)) &&
|
||||
!lvmcache_update_vgname_and_id(info, 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;
|
||||
}
|
||||
@@ -86,10 +86,8 @@ int label_register_handler(const char *name, struct labeller *handler)
|
||||
{
|
||||
struct labeller_i *li;
|
||||
|
||||
if (!(li = _alloc_li(name, handler))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(li = _alloc_li(name, handler)))
|
||||
return_0;
|
||||
|
||||
list_add(&_labellers, &li->list);
|
||||
return 1;
|
||||
@@ -145,7 +143,7 @@ static struct labeller *_find_labeller(struct device *dev, char *buf,
|
||||
continue;
|
||||
}
|
||||
if (calc_crc(INITIAL_CRC, &lh->offset_xl, LABEL_SIZE -
|
||||
((void *) &lh->offset_xl - (void *) lh)) !=
|
||||
((uintptr_t) &lh->offset_xl - (uintptr_t) lh)) !=
|
||||
xlate32(lh->crc_xl)) {
|
||||
log_info("Label checksum incorrect on %s - "
|
||||
"ignoring", dev_name(dev));
|
||||
@@ -179,8 +177,9 @@ static struct labeller *_find_labeller(struct device *dev, char *buf,
|
||||
|
||||
out:
|
||||
if (!found) {
|
||||
if ((info = info_from_pvid(dev->pvid)))
|
||||
lvmcache_update_vgname_and_id(info, ORPHAN, ORPHAN,
|
||||
if ((info = info_from_pvid(dev->pvid, 0)))
|
||||
lvmcache_update_vgname_and_id(info, info->fmt->orphan_vg_name,
|
||||
info->fmt->orphan_vg_name,
|
||||
0, NULL);
|
||||
log_very_verbose("%s: No label detected", dev_name(dev));
|
||||
}
|
||||
@@ -203,10 +202,8 @@ int label_remove(struct device *dev)
|
||||
|
||||
log_very_verbose("Scanning for labels to wipe from %s", dev_name(dev));
|
||||
|
||||
if (!dev_open(dev)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!dev_open(dev))
|
||||
return_0;
|
||||
|
||||
/*
|
||||
* We flush the device just in case someone is stupid
|
||||
@@ -260,7 +257,6 @@ int label_remove(struct device *dev)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* FIXME Avoid repeated re-reading if cache lock held */
|
||||
int label_read(struct device *dev, struct label **result,
|
||||
uint64_t scan_sector)
|
||||
{
|
||||
@@ -270,18 +266,25 @@ int label_read(struct device *dev, struct label **result,
|
||||
struct lvmcache_info *info;
|
||||
int r = 0;
|
||||
|
||||
if ((info = info_from_pvid(dev->pvid, 1))) {
|
||||
log_debug("Using cached label for %s", dev_name(dev));
|
||||
*result = info->label;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!dev_open(dev)) {
|
||||
stack;
|
||||
|
||||
if ((info = info_from_pvid(dev->pvid)))
|
||||
lvmcache_update_vgname_and_id(info, ORPHAN, ORPHAN,
|
||||
if ((info = info_from_pvid(dev->pvid, 0)))
|
||||
lvmcache_update_vgname_and_id(info, info->fmt->orphan_vg_name,
|
||||
info->fmt->orphan_vg_name,
|
||||
0, NULL);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -317,18 +320,14 @@ int label_write(struct device *dev, struct label *label)
|
||||
lh->sector_xl = xlate64(label->sector);
|
||||
lh->offset_xl = xlate32(sizeof(*lh));
|
||||
|
||||
if (!(label->labeller->ops->write)(label, buf)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(label->labeller->ops->write)(label, buf))
|
||||
return_0;
|
||||
|
||||
lh->crc_xl = xlate32(calc_crc(INITIAL_CRC, &lh->offset_xl, LABEL_SIZE -
|
||||
((void *) &lh->offset_xl - (void *) lh)));
|
||||
((uintptr_t) &lh->offset_xl - (uintptr_t) lh)));
|
||||
|
||||
if (!dev_open(dev)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!dev_open(dev))
|
||||
return_0;
|
||||
|
||||
log_info("%s: Writing label to sector %" PRIu64, dev_name(dev),
|
||||
label->sector);
|
||||
@@ -353,15 +352,16 @@ int label_verify(struct device *dev)
|
||||
int r = 0;
|
||||
|
||||
if (!dev_open(dev)) {
|
||||
if ((info = info_from_pvid(dev->pvid)))
|
||||
lvmcache_update_vgname_and_id(info, ORPHAN, ORPHAN,
|
||||
if ((info = info_from_pvid(dev->pvid, 0)))
|
||||
lvmcache_update_vgname_and_id(info, info->fmt->orphan_vg_name,
|
||||
info->fmt->orphan_vg_name,
|
||||
0, NULL);
|
||||
|
||||
return_0;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
||||
@@ -104,8 +104,8 @@ static int _send_request(char *inbuf, int inlen, char **retbuf)
|
||||
/* Send it to CLVMD */
|
||||
rewrite:
|
||||
if ( (err = write(_clvmd_sock, inbuf, inlen)) != inlen) {
|
||||
if (err == -1 && errno == EINTR)
|
||||
goto rewrite;
|
||||
if (err == -1 && errno == EINTR)
|
||||
goto rewrite;
|
||||
log_error("Error writing data to clvmd: %s", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
@@ -113,8 +113,8 @@ static int _send_request(char *inbuf, int inlen, char **retbuf)
|
||||
/* Get the response */
|
||||
reread:
|
||||
if ((len = read(_clvmd_sock, outbuf, sizeof(struct clvm_header))) < 0) {
|
||||
if (errno == EINTR)
|
||||
goto reread;
|
||||
if (errno == EINTR)
|
||||
goto reread;
|
||||
log_error("Error reading data from clvmd: %s", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
@@ -330,7 +330,7 @@ static int _lock_for_cluster(unsigned char cmd, uint32_t flags, const char *name
|
||||
* locks are cluster-wide.
|
||||
* Also, if the lock is exclusive it makes no sense to try to
|
||||
* acquire it on all nodes, so just do that on the local node too.
|
||||
* One exception, is that P_ locks /do/ get distributed across
|
||||
* One exception, is that P_ locks /do/ get distributed across
|
||||
* the cluster because they might have side-effects.
|
||||
*/
|
||||
if (strncmp(name, "P_", 2) &&
|
||||
@@ -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,18 +437,20 @@ 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);
|
||||
}
|
||||
|
||||
log_very_verbose("Locking %s %s %s %s%s%s%s (0x%x)", lock_scope, lockname,
|
||||
lock_type,
|
||||
flags & LCK_NONBLOCK ? "" : "B",
|
||||
flags & LCK_HOLD ? "H" : "",
|
||||
flags & LCK_LOCAL ? "L" : "",
|
||||
flags & LCK_CLUSTER_VG ? "C" : "",
|
||||
flags & LCK_NONBLOCK ? "" : "B",
|
||||
flags & LCK_HOLD ? "H" : "",
|
||||
flags & LCK_LOCAL ? "L" : "",
|
||||
flags & LCK_CLUSTER_VG ? "C" : "",
|
||||
flags);
|
||||
|
||||
/* Send a message to the cluster manager */
|
||||
@@ -479,7 +480,7 @@ void reset_locking(void)
|
||||
|
||||
_clvmd_sock = _open_local_sock();
|
||||
if (_clvmd_sock == -1)
|
||||
stack;
|
||||
stack;
|
||||
}
|
||||
|
||||
#ifdef CLUSTER_LOCKING_INTERNAL
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
@@ -73,10 +73,8 @@ int init_external_locking(struct locking_type *locking, struct cmd_context *cmd)
|
||||
libname = find_config_tree_str(cmd, "global/locking_library",
|
||||
DEFAULT_LOCKING_LIB);
|
||||
|
||||
if (!(_locking_lib = load_shared_library(cmd, libname, "locking", 1))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(_locking_lib = load_shared_library(cmd, libname, "locking", 1)))
|
||||
return_0;
|
||||
|
||||
/* Get the functions we need */
|
||||
if (!(_init_fn = dlsym(_locking_lib, "locking_init")) ||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
@@ -210,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
|
||||
@@ -221,17 +226,7 @@ static int _file_lock_resource(struct cmd_context *cmd, const char *resource,
|
||||
"%s/V_%s", _lock_dir, resource);
|
||||
|
||||
if (!_lock_file(lockfile, flags))
|
||||
return 0;
|
||||
|
||||
switch (flags & LCK_TYPE_MASK) {
|
||||
case LCK_UNLOCK:
|
||||
lvmcache_unlock_vgname(resource);
|
||||
break;
|
||||
default:
|
||||
lvmcache_lock_vgname(resource,
|
||||
(flags & LCK_TYPE_MASK) ==
|
||||
LCK_READ);
|
||||
}
|
||||
return_0;
|
||||
break;
|
||||
case LCK_LV:
|
||||
switch (flags & LCK_TYPE_MASK) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "toolcontext.h"
|
||||
#include "memlock.h"
|
||||
#include "defaults.h"
|
||||
#include "lvmcache.h"
|
||||
|
||||
#include <signal.h>
|
||||
#include <sys/stat.h>
|
||||
@@ -253,7 +254,7 @@ int init_locking(int type, struct cmd_context *cmd)
|
||||
}
|
||||
|
||||
if ((type == 2 || type == 3) &&
|
||||
find_config_tree_int(cmd, "locking/fallback_to_local_locking",
|
||||
find_config_tree_int(cmd, "locking/fallback_to_local_locking",
|
||||
DEFAULT_FALLBACK_TO_LOCAL_LOCKING)) {
|
||||
log_warn("WARNING: Falling back to local file-based locking.");
|
||||
log_warn("Volume Groups with the clustered attribute will "
|
||||
@@ -291,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);
|
||||
@@ -315,22 +320,40 @@ int check_lvm1_vg_inactive(struct cmd_context *cmd, const char *vgname)
|
||||
*/
|
||||
static int _lock_vol(struct cmd_context *cmd, const char *resource, uint32_t flags)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
_block_signals(flags);
|
||||
_lock_memory(flags);
|
||||
|
||||
assert(resource);
|
||||
|
||||
if (!(_locking.lock_resource(cmd, resource, flags))) {
|
||||
_unlock_memory(flags);
|
||||
_unblock_signals();
|
||||
if (!*resource) {
|
||||
log_error("Internal error: Use of P_orphans is deprecated.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
_update_vg_lock_count(flags);
|
||||
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 &&
|
||||
!(flags & LCK_CACHE)) {
|
||||
if ((flags & LCK_TYPE_MASK) == LCK_UNLOCK)
|
||||
lvmcache_unlock_vgname(resource);
|
||||
else
|
||||
lvmcache_lock_vgname(resource, (flags & LCK_TYPE_MASK)
|
||||
== LCK_READ);
|
||||
}
|
||||
|
||||
_update_vg_lock_count(flags);
|
||||
}
|
||||
|
||||
_unlock_memory(flags);
|
||||
_unblock_signals();
|
||||
|
||||
return 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int lock_vol(struct cmd_context *cmd, const char *vol, uint32_t flags)
|
||||
@@ -361,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;
|
||||
@@ -404,19 +431,23 @@ int suspend_lvs(struct cmd_context *cmd, struct list *lvs)
|
||||
}
|
||||
|
||||
/* Lock a list of LVs */
|
||||
int activate_lvs_excl(struct cmd_context *cmd, struct list *lvs)
|
||||
int activate_lvs(struct cmd_context *cmd, struct list *lvs, unsigned exclusive)
|
||||
{
|
||||
struct list *lvh;
|
||||
struct lv_list *lvl;
|
||||
|
||||
list_iterate_items(lvl, lvs) {
|
||||
if (!activate_lv_excl(cmd, lvl->lv)) {
|
||||
if (!exclusive) {
|
||||
if (!activate_lv(cmd, lvl->lv)) {
|
||||
log_error("Failed to activate %s", lvl->lv->name);
|
||||
return 0;
|
||||
}
|
||||
} else if (!activate_lv_excl(cmd, lvl->lv)) {
|
||||
log_error("Failed to activate %s", lvl->lv->name);
|
||||
list_uniterate(lvh, lvs, &lvl->list) {
|
||||
lvl = list_item(lvh, struct lv_list);
|
||||
activate_lv(cmd, lvl->lv);
|
||||
}
|
||||
|
||||
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)
|
||||
@@ -99,7 +110,7 @@ int check_lvm1_vg_inactive(struct cmd_context *cmd, const char *vgname);
|
||||
#define LCK_LV_DEACTIVATE (LCK_LV | LCK_NULL | LCK_NONBLOCK)
|
||||
|
||||
#define LCK_LV_CLUSTERED(lv) \
|
||||
(((lv)->vg->status & CLUSTERED) ? LCK_CLUSTER_VG : 0)
|
||||
(vg_is_clustered((lv)->vg) ? LCK_CLUSTER_VG : 0)
|
||||
|
||||
#define lock_lv_vol(cmd, lv, flags) \
|
||||
lock_vol(cmd, (lv)->lvid.s, flags | LCK_LV_CLUSTERED(lv))
|
||||
@@ -116,11 +127,13 @@ 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);
|
||||
int resume_lvs(struct cmd_context *cmd, struct list *lvs);
|
||||
int activate_lvs_excl(struct cmd_context *cmd, struct list *lvs);
|
||||
int activate_lvs(struct cmd_context *cmd, struct list *lvs, unsigned exclusive);
|
||||
|
||||
/* Interrupt handling */
|
||||
void sigint_clear(void);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
@@ -18,7 +18,6 @@
|
||||
#include "locking_types.h"
|
||||
#include "lvm-string.h"
|
||||
#include "activate.h"
|
||||
#include "lvmcache.h"
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
@@ -41,15 +40,6 @@ static int _no_lock_resource(struct cmd_context *cmd, const char *resource,
|
||||
{
|
||||
switch (flags & LCK_SCOPE_MASK) {
|
||||
case LCK_VG:
|
||||
switch (flags & LCK_TYPE_MASK) {
|
||||
case LCK_UNLOCK:
|
||||
lvmcache_unlock_vgname(resource);
|
||||
break;
|
||||
default:
|
||||
lvmcache_lock_vgname(resource,
|
||||
(flags & LCK_TYPE_MASK) ==
|
||||
LCK_READ);
|
||||
}
|
||||
break;
|
||||
case LCK_LV:
|
||||
switch (flags & LCK_TYPE_MASK) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
@@ -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;
|
||||
|
||||
@@ -215,12 +216,18 @@ void init_cmd_name(int status)
|
||||
|
||||
void set_cmd_name(const char *cmd)
|
||||
{
|
||||
if (!_log_cmd_name)
|
||||
return;
|
||||
strncpy(_cmd_name, cmd, sizeof(_cmd_name));
|
||||
_cmd_name[sizeof(_cmd_name) - 1] = '\0';
|
||||
}
|
||||
|
||||
static const char *_command_name()
|
||||
{
|
||||
if (!_log_cmd_name)
|
||||
return "";
|
||||
|
||||
return _cmd_name;
|
||||
}
|
||||
|
||||
void init_msg_prefix(const char *prefix)
|
||||
{
|
||||
strncpy(_msg_prefix, prefix, sizeof(_msg_prefix));
|
||||
@@ -232,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;
|
||||
@@ -316,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) {
|
||||
@@ -352,7 +372,7 @@ void print_log(int level, const char *file, int line, const char *format, ...)
|
||||
_verbose_level <= _LOG_DEBUG)
|
||||
break;
|
||||
if (_verbose_level >= _LOG_DEBUG) {
|
||||
fprintf(stderr, "%s%s%s", locn, _cmd_name,
|
||||
fprintf(stderr, "%s%s%s", locn, _command_name(),
|
||||
_msg_prefix);
|
||||
if (_indent)
|
||||
fprintf(stderr, " ");
|
||||
@@ -363,7 +383,7 @@ void print_log(int level, const char *file, int line, const char *format, ...)
|
||||
|
||||
case _LOG_INFO:
|
||||
if (_verbose_level >= _LOG_INFO) {
|
||||
fprintf(stderr, "%s%s%s", locn, _cmd_name,
|
||||
fprintf(stderr, "%s%s%s", locn, _command_name(),
|
||||
_msg_prefix);
|
||||
if (_indent)
|
||||
fprintf(stderr, " ");
|
||||
@@ -373,7 +393,7 @@ void print_log(int level, const char *file, int line, const char *format, ...)
|
||||
break;
|
||||
case _LOG_NOTICE:
|
||||
if (_verbose_level >= _LOG_NOTICE) {
|
||||
fprintf(stderr, "%s%s%s", locn, _cmd_name,
|
||||
fprintf(stderr, "%s%s%s", locn, _command_name(),
|
||||
_msg_prefix);
|
||||
if (_indent)
|
||||
fprintf(stderr, " ");
|
||||
@@ -383,14 +403,15 @@ void print_log(int level, const char *file, int line, const char *format, ...)
|
||||
break;
|
||||
case _LOG_WARN:
|
||||
if (_verbose_level >= _LOG_WARN) {
|
||||
fprintf(use_stderr ? stderr : stdout, "%s%s", _cmd_name, _msg_prefix);
|
||||
fprintf(use_stderr ? stderr : stdout, "%s%s",
|
||||
_command_name(), _msg_prefix);
|
||||
vfprintf(use_stderr ? stderr : stdout, trformat, ap);
|
||||
fputc('\n', use_stderr ? stderr : stdout);
|
||||
}
|
||||
break;
|
||||
case _LOG_ERR:
|
||||
if (_verbose_level >= _LOG_ERR) {
|
||||
fprintf(stderr, "%s%s%s", locn, _cmd_name,
|
||||
fprintf(stderr, "%s%s%s", locn, _command_name(),
|
||||
_msg_prefix);
|
||||
vfprintf(stderr, trformat, ap);
|
||||
fputc('\n', stderr);
|
||||
@@ -399,7 +420,7 @@ void print_log(int level, const char *file, int line, const char *format, ...)
|
||||
case _LOG_FATAL:
|
||||
default:
|
||||
if (_verbose_level >= _LOG_FATAL) {
|
||||
fprintf(stderr, "%s%s%s", locn, _cmd_name,
|
||||
fprintf(stderr, "%s%s%s", locn, _command_name(),
|
||||
_msg_prefix);
|
||||
vfprintf(stderr, trformat, ap);
|
||||
fputc('\n', stderr);
|
||||
@@ -413,7 +434,7 @@ void print_log(int level, const char *file, int line, const char *format, ...)
|
||||
return;
|
||||
|
||||
if (_log_to_file && (_log_while_suspended || !memlock())) {
|
||||
fprintf(_log_file, "%s:%d %s%s", file, line, _cmd_name,
|
||||
fprintf(_log_file, "%s:%d %s%s", file, line, _command_name(),
|
||||
_msg_prefix);
|
||||
|
||||
va_start(ap, format);
|
||||
@@ -436,7 +457,7 @@ void print_log(int level, const char *file, int line, const char *format, ...)
|
||||
memset(&buf, ' ', sizeof(buf));
|
||||
bufused = 0;
|
||||
if ((n = dm_snprintf(buf, sizeof(buf) - bufused - 1,
|
||||
"%s:%d %s%s", file, line, _cmd_name,
|
||||
"%s:%d %s%s", file, line, _command_name(),
|
||||
_msg_prefix)) == -1)
|
||||
goto done;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -178,15 +178,12 @@ struct lv_segment *alloc_lv_segment(struct dm_pool *mem,
|
||||
struct lv_segment *seg;
|
||||
uint32_t areas_sz = area_count * sizeof(*seg->areas);
|
||||
|
||||
if (!(seg = dm_pool_zalloc(mem, sizeof(*seg)))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!(seg = dm_pool_zalloc(mem, sizeof(*seg))))
|
||||
return_NULL;
|
||||
|
||||
if (!(seg->areas = dm_pool_zalloc(mem, areas_sz))) {
|
||||
dm_pool_free(mem, seg);
|
||||
stack;
|
||||
return NULL;
|
||||
return_NULL;
|
||||
}
|
||||
|
||||
if (!segtype) {
|
||||
@@ -290,10 +287,8 @@ int move_lv_segment_area(struct lv_segment *seg_to, uint32_t area_to,
|
||||
seg_from->area_len);
|
||||
release_lv_segment_area(seg_to, area_to, seg_to->area_len);
|
||||
|
||||
if (!set_lv_segment_area_pv(seg_to, area_to, pv, pe)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!set_lv_segment_area_pv(seg_to, area_to, pv, pe))
|
||||
return_0;
|
||||
|
||||
break;
|
||||
|
||||
@@ -326,10 +321,8 @@ int set_lv_segment_area_pv(struct lv_segment *seg, uint32_t area_num,
|
||||
seg->areas[area_num].type = AREA_PV;
|
||||
|
||||
if (!(seg_pvseg(seg, area_num) =
|
||||
assign_peg_to_lvseg(pv, pe, seg->area_len, seg, area_num))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
assign_peg_to_lvseg(pv, pe, seg->area_len, seg, area_num)))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -365,10 +358,8 @@ static int _lv_segment_add_areas(struct logical_volume *lv,
|
||||
struct lv_segment_area *newareas;
|
||||
uint32_t areas_sz = new_area_count * sizeof(*newareas);
|
||||
|
||||
if (!(newareas = dm_pool_zalloc(lv->vg->cmd->mem, areas_sz))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(newareas = dm_pool_zalloc(lv->vg->cmd->mem, areas_sz)))
|
||||
return_0;
|
||||
|
||||
memcpy(newareas, seg->areas, seg->area_count * sizeof(*seg->areas));
|
||||
|
||||
@@ -423,19 +414,15 @@ static int _lv_reduce(struct logical_volume *lv, uint32_t extents, int delete)
|
||||
if (seg->len <= count) {
|
||||
/* remove this segment completely */
|
||||
/* FIXME Check this is safe */
|
||||
if (seg->log_lv && !lv_remove(seg->log_lv)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (seg->log_lv && !lv_remove(seg->log_lv))
|
||||
return_0;
|
||||
list_del(&seg->list);
|
||||
reduction = seg->len;
|
||||
} else
|
||||
reduction = count;
|
||||
|
||||
if (!_lv_segment_reduce(seg, reduction)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!_lv_segment_reduce(seg, reduction))
|
||||
return_0;
|
||||
count -= reduction;
|
||||
}
|
||||
|
||||
@@ -447,19 +434,16 @@ static int _lv_reduce(struct logical_volume *lv, uint32_t extents, int delete)
|
||||
|
||||
/* Remove the LV if it is now empty */
|
||||
if (!lv->le_count) {
|
||||
if (!(lvl = find_lv_in_vg(lv->vg, lv->name))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(lvl = find_lv_in_vg(lv->vg, lv->name)))
|
||||
return_0;
|
||||
|
||||
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)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
!lv->vg->fid->fmt->ops->lv_setup(lv->vg->fid, lv))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -504,10 +488,8 @@ int lv_reduce(struct logical_volume *lv, uint32_t extents)
|
||||
int lv_remove(struct logical_volume *lv)
|
||||
{
|
||||
|
||||
if (!lv_reduce(lv, lv->le_count)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!lv_reduce(lv, lv->le_count))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -684,12 +666,9 @@ static int _setup_alloced_segment(struct logical_volume *lv, uint32_t status,
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (s = 0; s < area_count; s++) {
|
||||
if (!set_lv_segment_area_pv(seg, s, aa[s].pv, aa[s].pe)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
for (s = 0; s < area_count; s++)
|
||||
if (!set_lv_segment_area_pv(seg, s, aa[s].pv, aa[s].pe))
|
||||
return_0;
|
||||
|
||||
list_add(&lv->segments, &seg->list);
|
||||
|
||||
@@ -717,10 +696,8 @@ static int _setup_alloced_segments(struct logical_volume *lv,
|
||||
list_iterate_items(aa, &alloced_areas[0]) {
|
||||
if (!_setup_alloced_segment(lv, status, area_count,
|
||||
stripe_size, segtype, aa,
|
||||
region_size, log_lv)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
region_size, log_lv))
|
||||
return_0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -1142,10 +1119,8 @@ static int _find_parallel_space(struct alloc_handle *ah, alloc_policy_t alloc,
|
||||
allocated,
|
||||
(ah->log_count && !ah->log_area.len) ?
|
||||
*(areas + ix_offset + ix - 1) :
|
||||
NULL)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
NULL))
|
||||
return_0;
|
||||
|
||||
} while (!contiguous && *allocated != needed && can_split);
|
||||
|
||||
@@ -1187,10 +1162,8 @@ static int _allocate(struct alloc_handle *ah,
|
||||
/*
|
||||
* Build the sets of available areas on the pv's.
|
||||
*/
|
||||
if (!(pvms = create_pv_maps(ah->mem, vg, allocatable_pvs))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(pvms = create_pv_maps(ah->mem, vg, allocatable_pvs)))
|
||||
return_0;
|
||||
|
||||
if (!_log_parallel_areas(ah->mem, ah->parallel_areas))
|
||||
stack;
|
||||
@@ -1315,9 +1288,8 @@ struct alloc_handle *allocate_extents(struct volume_group *vg,
|
||||
if (!segtype_is_virtual(segtype) &&
|
||||
!_allocate(ah, vg, lv, (lv ? lv->le_count : 0) + extents,
|
||||
1, allocatable_pvs)) {
|
||||
stack;
|
||||
alloc_destroy(ah);
|
||||
return NULL;
|
||||
return_NULL;
|
||||
}
|
||||
|
||||
return ah;
|
||||
@@ -1348,10 +1320,8 @@ int lv_add_segment(struct alloc_handle *ah,
|
||||
if (!_setup_alloced_segments(lv, &ah->alloced_areas[first_area],
|
||||
num_areas, status,
|
||||
stripe_size, segtype,
|
||||
region_size, log_lv)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
region_size, log_lv))
|
||||
return_0;
|
||||
|
||||
if ((segtype->flags & SEG_CAN_SPLIT) && !lv_merge_segments(lv)) {
|
||||
log_err("Couldn't merge segments after extending "
|
||||
@@ -1360,10 +1330,8 @@ int lv_add_segment(struct alloc_handle *ah,
|
||||
}
|
||||
|
||||
if (lv->vg->fid->fmt->ops->lv_setup &&
|
||||
!lv->vg->fid->fmt->ops->lv_setup(lv->vg->fid, lv)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
!lv->vg->fid->fmt->ops->lv_setup(lv->vg->fid, lv))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -1615,10 +1583,8 @@ int lv_extend(struct logical_volume *lv,
|
||||
|
||||
if (mirrors < 2) {
|
||||
if (!lv_add_segment(ah, 0, ah->area_count, lv, segtype, stripe_size,
|
||||
status, 0, NULL)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
status, 0, NULL))
|
||||
goto_out;
|
||||
} else {
|
||||
if (!_lv_extend_mirror(ah, lv, extents, 0))
|
||||
return_0;
|
||||
@@ -1714,8 +1680,8 @@ static int _rename_cb(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
*/
|
||||
static int _for_each_sub_lv(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
int (*func)(struct cmd_context *cmd,
|
||||
struct logical_volume *lv,
|
||||
void *data),
|
||||
struct logical_volume *lv,
|
||||
void *data),
|
||||
void *data)
|
||||
{
|
||||
struct lv_segment *seg;
|
||||
@@ -1890,10 +1856,9 @@ struct logical_volume *lv_create_empty(const char *name,
|
||||
lv->lvid = *lvid;
|
||||
|
||||
if (fi->fmt->ops->lv_setup && !fi->fmt->ops->lv_setup(fi, lv)) {
|
||||
stack;
|
||||
if (ll)
|
||||
dm_pool_free(cmd->mem, ll);
|
||||
return NULL;
|
||||
return_NULL;
|
||||
}
|
||||
|
||||
if (!import)
|
||||
@@ -1911,8 +1876,7 @@ static int _add_pvs(struct cmd_context *cmd, struct pv_segment *peg,
|
||||
struct pv_list *pvl;
|
||||
|
||||
/* Don't add again if it's already on list. */
|
||||
list_iterate_items(pvl, &spvs->pvs)
|
||||
if (pvl->pv == peg->pv)
|
||||
if (find_pv_in_pv_list(&spvs->pvs, peg->pv))
|
||||
return 1;
|
||||
|
||||
if (!(pvl = dm_pool_alloc(cmd->mem, sizeof(*pvl)))) {
|
||||
@@ -1960,10 +1924,8 @@ struct list *build_parallel_areas_from_lv(struct cmd_context *cmd,
|
||||
/* Find next segment end */
|
||||
/* FIXME Unnecessary nesting! */
|
||||
if (!_for_each_pv(cmd, lv, current_le, spvs->len, &spvs->len,
|
||||
0, 0, -1, 0, _add_pvs, (void *) spvs)) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
0, 0, -1, 0, _add_pvs, (void *) spvs))
|
||||
return_NULL;
|
||||
|
||||
current_le = spvs->le + spvs->len;
|
||||
} while (current_le < lv->le_count);
|
||||
@@ -2022,7 +1984,7 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
* 1) Clustered VG, and some remote nodes have the LV active
|
||||
* 2) Non-clustered VG, but LV active locally
|
||||
*/
|
||||
if ((vg_status(vg) & CLUSTERED) && !activate_lv_excl(cmd, lv) &&
|
||||
if (vg_is_clustered(vg) && !activate_lv_excl(cmd, lv) &&
|
||||
(force == PROMPT)) {
|
||||
if (yes_no_prompt("Logical volume \"%s\" is active on other "
|
||||
"cluster nodes. Really remove? [y/n]: ",
|
||||
@@ -2055,10 +2017,8 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
if (lv_is_cow(lv)) {
|
||||
origin = origin_from_cow(lv);
|
||||
log_verbose("Removing snapshot %s", lv->name);
|
||||
if (!vg_remove_snapshot(lv)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!vg_remove_snapshot(lv))
|
||||
return_0;
|
||||
}
|
||||
|
||||
log_verbose("Releasing logical volume \"%s\"", lv->name);
|
||||
@@ -2088,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.
|
||||
@@ -2348,6 +2329,9 @@ int remove_layer_from_lv(struct logical_volume *lv,
|
||||
parent->le_count != layer_lv->le_count)
|
||||
return_0;
|
||||
|
||||
if (!lv_empty(parent))
|
||||
return_0;
|
||||
|
||||
if (!_move_lv_segments(parent, layer_lv, 0, 0))
|
||||
return_0;
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
/*
|
||||
* Attempt to merge two adjacent segments.
|
||||
* Currently only supports striped segments on AREA_PV.
|
||||
* Returns success if successful, in which case 'first'
|
||||
* Returns success if successful, in which case 'first'
|
||||
* gets adjusted to contain both areas.
|
||||
*/
|
||||
static int _merge(struct lv_segment *first, struct lv_segment *second)
|
||||
@@ -76,7 +76,7 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)
|
||||
r = 0;
|
||||
}
|
||||
|
||||
area_multiplier = segtype_is_striped(seg->segtype) ?
|
||||
area_multiplier = segtype_is_striped(seg->segtype) ?
|
||||
seg->area_count : 1;
|
||||
|
||||
if (seg->area_len * area_multiplier != seg->len) {
|
||||
@@ -224,6 +224,20 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)
|
||||
seg->le + seg->len - 1, seg_found);
|
||||
r = 0;
|
||||
}
|
||||
|
||||
seg_found = 0;
|
||||
list_iterate_items(seg2, &seg->lv->segments)
|
||||
if (sl->seg == seg2) {
|
||||
seg_found++;
|
||||
break;
|
||||
}
|
||||
if (!seg_found) {
|
||||
log_error("LV segment %s:%" PRIu32 "-%" PRIu32
|
||||
"is incorrectly listed as being used by LV %s",
|
||||
seg->lv->name, seg->le, seg->le + seg->len - 1,
|
||||
lv->name);
|
||||
r = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (le != lv->le_count) {
|
||||
@@ -305,10 +319,8 @@ static int _lv_split_segment(struct logical_volume *lv, struct lv_segment *seg,
|
||||
seg->area_len,
|
||||
seg_pvseg(seg, s)->len -
|
||||
seg->area_len,
|
||||
split_seg, s))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
split_seg, s)))
|
||||
return_0;
|
||||
log_debug("Split %s:%u[%u] at %u: %s PE %u", lv->name,
|
||||
seg->le, s, le,
|
||||
dev_name(seg_dev(seg, s)),
|
||||
@@ -344,15 +356,11 @@ int lv_split_segment(struct logical_volume *lv, uint32_t le)
|
||||
if (le == seg->le)
|
||||
return 1;
|
||||
|
||||
if (!_lv_split_segment(lv, seg, le)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!_lv_split_segment(lv, seg, le))
|
||||
return_0;
|
||||
|
||||
if (!vg_validate(lv->vg)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!vg_validate(lv->vg))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -133,6 +133,7 @@ struct format_type {
|
||||
struct labeller *labeller;
|
||||
const char *name;
|
||||
const char *alias;
|
||||
const char *orphan_vg_name;
|
||||
uint32_t features;
|
||||
void *library;
|
||||
void *private;
|
||||
@@ -150,6 +151,8 @@ struct pv_segment {
|
||||
uint32_t lv_area; /* Index to area in LV segment */
|
||||
};
|
||||
|
||||
#define pvseg_is_allocated(pvseg) ((pvseg)->lvseg)
|
||||
|
||||
struct physical_volume {
|
||||
struct id id;
|
||||
struct device *dev;
|
||||
@@ -199,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;
|
||||
@@ -317,7 +336,7 @@ int pv_write(struct cmd_context *cmd, struct physical_volume *pv,
|
||||
struct list *mdas, int64_t label_sector);
|
||||
int is_pv(pv_t *pv);
|
||||
int is_orphan_vg(const char *vg_name);
|
||||
int is_orphan(pv_t *pv);
|
||||
int is_orphan(const pv_t *pv);
|
||||
int vgs_are_compatible(struct cmd_context *cmd,
|
||||
struct volume_group *vg_from,
|
||||
struct volume_group *vg_to);
|
||||
@@ -328,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,
|
||||
@@ -397,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);
|
||||
|
||||
@@ -427,14 +449,18 @@ struct logical_volume *insert_layer_for_lv(struct cmd_context *cmd,
|
||||
const char *layer_suffix);
|
||||
|
||||
/* Find a PV within a given VG */
|
||||
struct pv_list *find_pv_in_vg(struct volume_group *vg, const char *pv_name);
|
||||
pv_t *find_pv_in_vg_by_uuid(struct volume_group *vg, struct id *id);
|
||||
struct pv_list *find_pv_in_vg(const struct volume_group *vg,
|
||||
const char *pv_name);
|
||||
pv_t *find_pv_in_vg_by_uuid(const struct volume_group *vg,
|
||||
const struct id *id);
|
||||
|
||||
/* Find an LV within a given VG */
|
||||
struct lv_list *find_lv_in_vg(struct volume_group *vg, const char *lv_name);
|
||||
struct lv_list *find_lv_in_vg(const struct volume_group *vg,
|
||||
const char *lv_name);
|
||||
|
||||
/* FIXME Merge these functions with ones above */
|
||||
struct logical_volume *find_lv(struct volume_group *vg, const char *lv_name);
|
||||
struct logical_volume *find_lv(const struct volume_group *vg,
|
||||
const char *lv_name);
|
||||
struct physical_volume *find_pv_by_name(struct cmd_context *cmd,
|
||||
const char *pv_name);
|
||||
|
||||
@@ -506,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);
|
||||
@@ -537,6 +564,7 @@ uint32_t pv_pe_count(const pv_t *pv);
|
||||
uint32_t pv_pe_alloc_count(const pv_t *pv);
|
||||
|
||||
uint32_t vg_status(const vg_t *vg);
|
||||
#define vg_is_clustered(vg) (vg_status((vg)) & CLUSTERED)
|
||||
|
||||
struct vgcreate_params {
|
||||
char *vg_name;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
@@ -36,9 +36,9 @@
|
||||
#define pv_field(handle, field) \
|
||||
(((const struct physical_volume *)(handle))->field)
|
||||
|
||||
static struct physical_volume *_pv_read(struct cmd_context *cmd,
|
||||
static struct physical_volume *_pv_read(struct cmd_context *cmd,
|
||||
const char *pv_name,
|
||||
struct list *mdas,
|
||||
struct list *mdas,
|
||||
uint64_t *label_sector,
|
||||
int warnings);
|
||||
|
||||
@@ -51,17 +51,18 @@ static struct physical_volume *_pv_create(const struct format_type *fmt,
|
||||
int pvmetadatacopies,
|
||||
uint64_t pvmetadatasize, struct list *mdas);
|
||||
|
||||
static int _pv_write(struct cmd_context *cmd __attribute((unused)),
|
||||
static int _pv_write(struct cmd_context *cmd __attribute((unused)),
|
||||
struct physical_volume *pv,
|
||||
struct list *mdas, int64_t label_sector);
|
||||
|
||||
static struct physical_volume *_find_pv_by_name(struct cmd_context *cmd,
|
||||
const char *pv_name);
|
||||
|
||||
static struct pv_list *_find_pv_in_vg(struct volume_group *vg, const char *pv_name);
|
||||
static struct pv_list *_find_pv_in_vg(const struct volume_group *vg,
|
||||
const char *pv_name);
|
||||
|
||||
static struct physical_volume *_find_pv_in_vg_by_uuid(struct volume_group *vg,
|
||||
struct id *id);
|
||||
static struct physical_volume *_find_pv_in_vg_by_uuid(const struct volume_group *vg,
|
||||
const struct id *id);
|
||||
|
||||
unsigned long pe_align(void)
|
||||
{
|
||||
@@ -154,10 +155,8 @@ int add_pv_to_vg(struct volume_group *vg, const char *pv_name,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!alloc_pv_segment_whole_pv(mem, pv)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!alloc_pv_segment_whole_pv(mem, pv))
|
||||
return_0;
|
||||
|
||||
pvl->pv = pv;
|
||||
list_add(&vg->pvs, &pvl->list);
|
||||
@@ -189,10 +188,8 @@ static int _copy_pv(struct physical_volume *pv_to,
|
||||
}
|
||||
|
||||
if (!peg_dup(pv_to->fmt->cmd->mem, &pv_to->segments,
|
||||
&pv_from->segments)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
&pv_from->segments))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -217,10 +214,8 @@ int get_pv_from_vg_by_id(const struct format_type *fmt, const char *vg_name,
|
||||
|
||||
list_iterate_items(pvl, &vg->pvs) {
|
||||
if (id_equal(&pvl->pv->id, (const struct id *) pvid)) {
|
||||
if (!_copy_pv(pv, pvl->pv)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!_copy_pv(pv, pvl->pv))
|
||||
return_0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -301,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;
|
||||
}
|
||||
@@ -362,7 +360,7 @@ int vg_remove_single(struct cmd_context *cmd, const char *vg_name,
|
||||
pv = pvl->pv;
|
||||
log_verbose("Removing physical volume \"%s\" from "
|
||||
"volume group \"%s\"", pv_dev_name(pv), vg_name);
|
||||
pv->vg_name = ORPHAN;
|
||||
pv->vg_name = vg->fid->fmt->orphan_vg_name;
|
||||
pv->status = ALLOCATABLE_PV;
|
||||
|
||||
if (!dev_get_size(pv_dev(pv), &pv->size)) {
|
||||
@@ -475,10 +473,8 @@ struct volume_group *vg_create(struct cmd_context *cmd, const char *vg_name,
|
||||
int consistent = 0;
|
||||
int old_partial;
|
||||
|
||||
if (!(vg = dm_pool_zalloc(mem, sizeof(*vg)))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!(vg = dm_pool_zalloc(mem, sizeof(*vg))))
|
||||
return_NULL;
|
||||
|
||||
/* is this vg name already in use ? */
|
||||
old_partial = partial_mode();
|
||||
@@ -499,10 +495,8 @@ struct volume_group *vg_create(struct cmd_context *cmd, const char *vg_name,
|
||||
|
||||
vg->cmd = cmd;
|
||||
|
||||
if (!(vg->name = dm_pool_strdup(mem, vg_name))) {
|
||||
stack;
|
||||
goto bad;
|
||||
}
|
||||
if (!(vg->name = dm_pool_strdup(mem, vg_name)))
|
||||
goto_bad;
|
||||
|
||||
vg->seqno = 0;
|
||||
|
||||
@@ -595,22 +589,16 @@ int vg_change_pesize(struct cmd_context *cmd __attribute((unused)),
|
||||
vg->extent_size = new_size;
|
||||
|
||||
if (vg->fid->fmt->ops->vg_setup &&
|
||||
!vg->fid->fmt->ops->vg_setup(vg->fid, vg)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
!vg->fid->fmt->ops->vg_setup(vg->fid, vg))
|
||||
return_0;
|
||||
|
||||
if (!_recalc_extents(&vg->extent_count, vg->name, "", old_size,
|
||||
new_size)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
new_size))
|
||||
return_0;
|
||||
|
||||
if (!_recalc_extents(&vg->free_count, vg->name, " free space",
|
||||
old_size, new_size)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
old_size, new_size))
|
||||
return_0;
|
||||
|
||||
/* foreach PV */
|
||||
list_iterate_items(pvl, &vg->pvs) {
|
||||
@@ -618,34 +606,26 @@ int vg_change_pesize(struct cmd_context *cmd __attribute((unused)),
|
||||
|
||||
pv->pe_size = new_size;
|
||||
if (!_recalc_extents(&pv->pe_count, pv_dev_name(pv), "",
|
||||
old_size, new_size)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
old_size, new_size))
|
||||
return_0;
|
||||
|
||||
if (!_recalc_extents(&pv->pe_alloc_count, pv_dev_name(pv),
|
||||
" allocated space", old_size, new_size)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
" allocated space", old_size, new_size))
|
||||
return_0;
|
||||
|
||||
/* foreach free PV Segment */
|
||||
list_iterate_items(pvseg, &pv->segments) {
|
||||
if (pvseg->lvseg)
|
||||
if (pvseg_is_allocated(pvseg))
|
||||
continue;
|
||||
|
||||
if (!_recalc_extents(&pvseg->pe, pv_dev_name(pv),
|
||||
" PV segment start", old_size,
|
||||
new_size)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
new_size))
|
||||
return_0;
|
||||
if (!_recalc_extents(&pvseg->len, pv_dev_name(pv),
|
||||
" PV segment length", old_size,
|
||||
new_size)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
new_size))
|
||||
return_0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -654,39 +634,29 @@ int vg_change_pesize(struct cmd_context *cmd __attribute((unused)),
|
||||
lv = lvl->lv;
|
||||
|
||||
if (!_recalc_extents(&lv->le_count, lv->name, "", old_size,
|
||||
new_size)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
new_size))
|
||||
return_0;
|
||||
|
||||
list_iterate_items(seg, &lv->segments) {
|
||||
if (!_recalc_extents(&seg->le, lv->name,
|
||||
" segment start", old_size,
|
||||
new_size)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
new_size))
|
||||
return_0;
|
||||
|
||||
if (!_recalc_extents(&seg->len, lv->name,
|
||||
" segment length", old_size,
|
||||
new_size)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
new_size))
|
||||
return_0;
|
||||
|
||||
if (!_recalc_extents(&seg->area_len, lv->name,
|
||||
" area length", old_size,
|
||||
new_size)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
new_size))
|
||||
return_0;
|
||||
|
||||
if (!_recalc_extents(&seg->extents_copied, lv->name,
|
||||
" extents moved", old_size,
|
||||
new_size)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
new_size))
|
||||
return_0;
|
||||
|
||||
/* foreach area */
|
||||
for (s = 0; s < seg->area_count; s++) {
|
||||
@@ -696,27 +666,21 @@ int vg_change_pesize(struct cmd_context *cmd __attribute((unused)),
|
||||
(&seg_pe(seg, s),
|
||||
lv->name,
|
||||
" pvseg start", old_size,
|
||||
new_size)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
new_size))
|
||||
return_0;
|
||||
if (!_recalc_extents
|
||||
(&seg_pvseg(seg, s)->len,
|
||||
lv->name,
|
||||
" pvseg length", old_size,
|
||||
new_size)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
new_size))
|
||||
return_0;
|
||||
break;
|
||||
case AREA_LV:
|
||||
if (!_recalc_extents
|
||||
(&seg_le(seg, s), lv->name,
|
||||
" area start", old_size,
|
||||
new_size)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
new_size))
|
||||
return_0;
|
||||
break;
|
||||
case AREA_UNASSIGNED:
|
||||
log_error("Unassigned area %u found in "
|
||||
@@ -731,6 +695,10 @@ int vg_change_pesize(struct cmd_context *cmd __attribute((unused)),
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Separate metadata areas after splitting a VG.
|
||||
* Also accepts orphan VG as destination (for vgreduce).
|
||||
*/
|
||||
int vg_split_mdas(struct cmd_context *cmd __attribute((unused)),
|
||||
struct volume_group *vg_from, struct volume_group *vg_to)
|
||||
{
|
||||
@@ -748,12 +716,15 @@ int vg_split_mdas(struct cmd_context *cmd __attribute((unused)),
|
||||
}
|
||||
|
||||
if (!mda->ops->mda_in_vg(vg_from->fid, vg_from, mda)) {
|
||||
list_del(&mda->list);
|
||||
list_add(mdas_to, &mda->list);
|
||||
if (is_orphan_vg(vg_to->name))
|
||||
list_del(&mda->list);
|
||||
else
|
||||
list_move(mdas_to, &mda->list);
|
||||
}
|
||||
}
|
||||
|
||||
if (list_empty(mdas_from) || list_empty(mdas_to))
|
||||
if (list_empty(mdas_from) ||
|
||||
(!is_orphan_vg(vg_to->name) && list_empty(mdas_to)))
|
||||
return common_mda;
|
||||
|
||||
return 1;
|
||||
@@ -779,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,
|
||||
@@ -788,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,
|
||||
@@ -804,10 +775,8 @@ static struct physical_volume *_alloc_pv(struct dm_pool *mem)
|
||||
{
|
||||
struct physical_volume *pv = dm_pool_zalloc(mem, sizeof(*pv));
|
||||
|
||||
if (!pv) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!pv)
|
||||
return_NULL;
|
||||
|
||||
if (!(pv->vg_name = dm_pool_zalloc(mem, NAME_LEN))) {
|
||||
dm_pool_free(mem, pv);
|
||||
@@ -875,6 +844,7 @@ static struct physical_volume *_pv_create(const struct format_type *fmt,
|
||||
}
|
||||
|
||||
pv->fmt = fmt;
|
||||
pv->vg_name = fmt->orphan_vg_name;
|
||||
|
||||
if (!fmt->ops->pv_setup(fmt, pe_start, existing_extent_count,
|
||||
existing_extent_size,
|
||||
@@ -892,12 +862,14 @@ static struct physical_volume *_pv_create(const struct format_type *fmt,
|
||||
}
|
||||
|
||||
/* FIXME: liblvm todo - make into function that returns handle */
|
||||
struct pv_list *find_pv_in_vg(struct volume_group *vg, const char *pv_name)
|
||||
struct pv_list *find_pv_in_vg(const struct volume_group *vg,
|
||||
const char *pv_name)
|
||||
{
|
||||
return _find_pv_in_vg(vg, pv_name);
|
||||
}
|
||||
|
||||
static struct pv_list *_find_pv_in_vg(struct volume_group *vg, const char *pv_name)
|
||||
static struct pv_list *_find_pv_in_vg(const struct volume_group *vg,
|
||||
const char *pv_name)
|
||||
{
|
||||
struct pv_list *pvl;
|
||||
|
||||
@@ -908,6 +880,18 @@ static struct pv_list *_find_pv_in_vg(struct volume_group *vg, const char *pv_na
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct pv_list *find_pv_in_pv_list(const struct list *pl,
|
||||
const struct physical_volume *pv)
|
||||
{
|
||||
struct pv_list *pvl;
|
||||
|
||||
list_iterate_items(pvl, pl)
|
||||
if (pvl->pv == pv)
|
||||
return pvl;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int pv_is_in_vg(struct volume_group *vg, struct physical_volume *pv)
|
||||
{
|
||||
struct pv_list *pvl;
|
||||
@@ -931,14 +915,15 @@ int pv_is_in_vg(struct volume_group *vg, struct physical_volume *pv)
|
||||
* Note
|
||||
* FIXME - liblvm todo - make into function that takes VG handle
|
||||
*/
|
||||
pv_t *find_pv_in_vg_by_uuid(struct volume_group *vg, struct id *id)
|
||||
pv_t *find_pv_in_vg_by_uuid(const struct volume_group *vg,
|
||||
const struct id *id)
|
||||
{
|
||||
return _find_pv_in_vg_by_uuid(vg, id);
|
||||
}
|
||||
|
||||
|
||||
static struct physical_volume *_find_pv_in_vg_by_uuid(struct volume_group *vg,
|
||||
struct id *id)
|
||||
static struct physical_volume *_find_pv_in_vg_by_uuid(const struct volume_group *vg,
|
||||
const struct id *id)
|
||||
{
|
||||
struct pv_list *pvl;
|
||||
|
||||
@@ -949,7 +934,8 @@ static struct physical_volume *_find_pv_in_vg_by_uuid(struct volume_group *vg,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct lv_list *find_lv_in_vg(struct volume_group *vg, const char *lv_name)
|
||||
struct lv_list *find_lv_in_vg(const struct volume_group *vg,
|
||||
const char *lv_name)
|
||||
{
|
||||
struct lv_list *lvl;
|
||||
const char *ptr;
|
||||
@@ -967,6 +953,18 @@ struct lv_list *find_lv_in_vg(struct volume_group *vg, const char *lv_name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct lv_list *find_lv_in_lv_list(const struct list *ll,
|
||||
const struct logical_volume *lv)
|
||||
{
|
||||
struct lv_list *lvl;
|
||||
|
||||
list_iterate_items(lvl, ll)
|
||||
if (lvl->lv == lv)
|
||||
return lvl;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct lv_list *find_lv_in_vg_by_lvid(struct volume_group *vg,
|
||||
const union lvid *lvid)
|
||||
{
|
||||
@@ -979,7 +977,8 @@ struct lv_list *find_lv_in_vg_by_lvid(struct volume_group *vg,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct logical_volume *find_lv(struct volume_group *vg, const char *lv_name)
|
||||
struct logical_volume *find_lv(const struct volume_group *vg,
|
||||
const char *lv_name)
|
||||
{
|
||||
struct lv_list *lvl = find_lv_in_vg(vg, lv_name);
|
||||
return lvl ? lvl->lv : NULL;
|
||||
@@ -1074,10 +1073,8 @@ int vg_remove(struct volume_group *vg)
|
||||
/* Remove each copy of the metadata */
|
||||
list_iterate_items(mda, &vg->fid->metadata_areas) {
|
||||
if (mda->ops->vg_remove &&
|
||||
!mda->ops->vg_remove(vg->fid, vg, mda)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
!mda->ops->vg_remove(vg->fid, vg, mda))
|
||||
return_0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -1132,7 +1129,7 @@ int vgs_are_compatible(struct cmd_context *cmd __attribute((unused)),
|
||||
}
|
||||
|
||||
/* Clustering attribute must be the same */
|
||||
if ((vg_to->status & CLUSTERED) != (vg_from->status & CLUSTERED)) {
|
||||
if (vg_is_clustered(vg_to) != vg_is_clustered(vg_from)) {
|
||||
log_error("Clustered attribute differs for \"%s\" and \"%s\"",
|
||||
vg_to->name, vg_from->name);
|
||||
return 0;
|
||||
@@ -1183,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 */
|
||||
|
||||
@@ -1216,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)
|
||||
@@ -1248,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;
|
||||
}
|
||||
|
||||
@@ -1260,10 +1274,8 @@ int vg_write(struct volume_group *vg)
|
||||
struct list *mdah;
|
||||
struct metadata_area *mda;
|
||||
|
||||
if (!vg_validate(vg)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!vg_validate(vg))
|
||||
return_0;
|
||||
|
||||
if (vg->status & PARTIAL_VG) {
|
||||
log_error("Cannot change metadata for partial volume group %s",
|
||||
@@ -1276,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 */
|
||||
@@ -1335,6 +1352,12 @@ int vg_commit(struct volume_group *vg)
|
||||
int cache_updated = 0;
|
||||
int failed = 0;
|
||||
|
||||
if (!vgname_is_locked(vg->name)) {
|
||||
log_error("Internal error: Attempt to write new VG metadata "
|
||||
"without locking %s", vg->name);
|
||||
return cache_updated;
|
||||
}
|
||||
|
||||
/* Commit to each copy of the metadata area */
|
||||
list_iterate_items(mda, &vg->fid->metadata_areas) {
|
||||
failed = 0;
|
||||
@@ -1345,11 +1368,16 @@ int vg_commit(struct volume_group *vg)
|
||||
}
|
||||
/* Update cache first time we succeed */
|
||||
if (!failed && !cache_updated) {
|
||||
lvmcache_update_vg(vg);
|
||||
lvmcache_update_vg(vg, 0);
|
||||
cache_updated = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
@@ -1366,11 +1394,16 @@ 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;
|
||||
}
|
||||
|
||||
/* Make orphan PVs look like a VG */
|
||||
static struct volume_group *_vg_read_orphans(struct cmd_context *cmd)
|
||||
static struct volume_group *_vg_read_orphans(struct cmd_context *cmd,
|
||||
const char *orphan_vgname)
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
struct lvmcache_info *info;
|
||||
@@ -1378,10 +1411,10 @@ static struct volume_group *_vg_read_orphans(struct cmd_context *cmd)
|
||||
struct volume_group *vg;
|
||||
struct physical_volume *pv;
|
||||
|
||||
if (!(vginfo = vginfo_from_vgname(ORPHAN, NULL))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
lvmcache_label_scan(cmd, 0);
|
||||
|
||||
if (!(vginfo = vginfo_from_vgname(orphan_vgname, NULL)))
|
||||
return_NULL;
|
||||
|
||||
if (!(vg = dm_pool_zalloc(cmd->mem, sizeof(*vg)))) {
|
||||
log_error("vg allocation failed");
|
||||
@@ -1391,11 +1424,20 @@ static struct volume_group *_vg_read_orphans(struct cmd_context *cmd)
|
||||
list_init(&vg->lvs);
|
||||
list_init(&vg->tags);
|
||||
vg->cmd = cmd;
|
||||
if (!(vg->name = dm_pool_strdup(cmd->mem, ORPHAN))) {
|
||||
if (!(vg->name = dm_pool_strdup(cmd->mem, orphan_vgname))) {
|
||||
log_error("vg name allocation failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* create format instance with appropriate metadata area */
|
||||
if (!(vg->fid = vginfo->fmt->ops->create_instance(vginfo->fmt,
|
||||
orphan_vgname, NULL,
|
||||
NULL))) {
|
||||
log_error("Failed to create format instance");
|
||||
dm_pool_free(cmd->mem, vg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
list_iterate_items(info, &vginfo->infos) {
|
||||
if (!(pv = _pv_read(cmd, dev_name(info->dev), NULL, NULL, 1))) {
|
||||
continue;
|
||||
@@ -1440,23 +1482,27 @@ static int _update_pv_list(struct list *all_pvs, struct volume_group *vg)
|
||||
* inconsistent metadata on disk (i.e. the VG write lock is held).
|
||||
* This guarantees only consistent metadata is returned unless PARTIAL_VG.
|
||||
* If consistent is 0, caller must check whether consistent == 1 on return
|
||||
* and take appropriate action if it isn't (e.g. abort; get write lock
|
||||
* and take appropriate action if it isn't (e.g. abort; get write lock
|
||||
* 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,
|
||||
const char *vgid,
|
||||
int *consistent, int precommitted)
|
||||
int *consistent, unsigned precommitted)
|
||||
{
|
||||
struct format_instance *fid;
|
||||
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 use_precommitted = precommitted;
|
||||
int inconsistent_pvs = 0;
|
||||
unsigned use_precommitted = precommitted;
|
||||
struct list *pvids;
|
||||
struct pv_list *pvl, *pvl2;
|
||||
struct list all_pvs;
|
||||
@@ -1469,7 +1515,12 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
|
||||
return NULL;
|
||||
}
|
||||
*consistent = 1;
|
||||
return _vg_read_orphans(cmd);
|
||||
return _vg_read_orphans(cmd, vgname);
|
||||
}
|
||||
|
||||
if ((correct_vg = lvmcache_get_vg(vgid, precommitted))) {
|
||||
*consistent = 1;
|
||||
return correct_vg;
|
||||
}
|
||||
|
||||
/* Find the vgname in the cache */
|
||||
@@ -1477,33 +1528,31 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
|
||||
if (!(fmt = fmt_from_vgname(vgname, vgid))) {
|
||||
lvmcache_label_scan(cmd, 0);
|
||||
if (!(fmt = fmt_from_vgname(vgname, vgid))) {
|
||||
if (memlock()) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (memlock())
|
||||
return_NULL;
|
||||
lvmcache_label_scan(cmd, 2);
|
||||
if (!(fmt = fmt_from_vgname(vgname, vgid))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!(fmt = fmt_from_vgname(vgname, vgid)))
|
||||
return_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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))) {
|
||||
stack;
|
||||
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 &&
|
||||
@@ -1527,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);
|
||||
@@ -1551,15 +1638,11 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
|
||||
if (!correct_vg) {
|
||||
inconsistent = 0;
|
||||
|
||||
if (memlock()) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (memlock())
|
||||
return_NULL;
|
||||
lvmcache_label_scan(cmd, 2);
|
||||
if (!(fmt = fmt_from_vgname(vgname, vgid))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!(fmt = fmt_from_vgname(vgname, vgid)))
|
||||
return_NULL;
|
||||
|
||||
if (precommitted && !(fmt->features & FMT_PRECOMMIT))
|
||||
use_precommitted = 0;
|
||||
@@ -1605,13 +1688,11 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
|
||||
}
|
||||
|
||||
/* Give up looking */
|
||||
if (!correct_vg) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!correct_vg)
|
||||
return_NULL;
|
||||
}
|
||||
|
||||
lvmcache_update_vg(correct_vg);
|
||||
lvmcache_update_vg(correct_vg, use_precommitted);
|
||||
|
||||
if (inconsistent) {
|
||||
/* FIXME Test should be if we're *using* precommitted metadata not if we were searching for it */
|
||||
@@ -1709,13 +1790,13 @@ struct volume_group *vg_read(struct cmd_context *cmd, const char *vgname,
|
||||
return vg;
|
||||
}
|
||||
|
||||
/* This is only called by lv_from_lvid, which is only called from
|
||||
* activate.c so we know the appropriate VG lock is already held and
|
||||
/* This is only called by lv_from_lvid, which is only called from
|
||||
* activate.c so we know the appropriate VG lock is already held and
|
||||
* the vg_read is therefore safe.
|
||||
*/
|
||||
static struct volume_group *_vg_read_by_vgid(struct cmd_context *cmd,
|
||||
const char *vgid,
|
||||
int precommitted)
|
||||
unsigned precommitted)
|
||||
{
|
||||
const char *vgname;
|
||||
struct list *vgnames;
|
||||
@@ -1727,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;
|
||||
}
|
||||
@@ -1748,7 +1829,7 @@ static struct volume_group *_vg_read_by_vgid(struct cmd_context *cmd,
|
||||
/* FIXME Disabled vgrenames while active for now because we aren't
|
||||
* allowed to do a full scan here any more. */
|
||||
|
||||
// The slow way - full scan required to cope with vgrename
|
||||
// The slow way - full scan required to cope with vgrename
|
||||
if (!(vgnames = get_vgs(cmd, 2))) {
|
||||
log_error("vg_read_by_vgid: get_vgs failed");
|
||||
return NULL;
|
||||
@@ -1757,7 +1838,7 @@ static struct volume_group *_vg_read_by_vgid(struct cmd_context *cmd,
|
||||
list_iterate_items(strl, vgnames) {
|
||||
vgname = strl->str;
|
||||
if (!vgname || is_orphan_vg(vgname))
|
||||
continue; // FIXME Unnecessary?
|
||||
continue; // FIXME Unnecessary?
|
||||
consistent = 0;
|
||||
if ((vg = _vg_read(cmd, vgname, vgid, &consistent,
|
||||
precommitted)) &&
|
||||
@@ -1776,7 +1857,7 @@ static struct volume_group *_vg_read_by_vgid(struct cmd_context *cmd,
|
||||
|
||||
/* Only called by activate.c */
|
||||
struct logical_volume *lv_from_lvid(struct cmd_context *cmd, const char *lvid_s,
|
||||
int precommitted)
|
||||
unsigned precommitted)
|
||||
{
|
||||
struct lv_list *lvl;
|
||||
struct volume_group *vg;
|
||||
@@ -1826,9 +1907,9 @@ struct physical_volume *pv_read(struct cmd_context *cmd, const char *pv_name,
|
||||
}
|
||||
|
||||
/* FIXME Use label functions instead of PV functions */
|
||||
static struct physical_volume *_pv_read(struct cmd_context *cmd,
|
||||
static struct physical_volume *_pv_read(struct cmd_context *cmd,
|
||||
const char *pv_name,
|
||||
struct list *mdas,
|
||||
struct list *mdas,
|
||||
uint64_t *label_sector,
|
||||
int warnings)
|
||||
{
|
||||
@@ -1837,10 +1918,8 @@ static struct physical_volume *_pv_read(struct cmd_context *cmd,
|
||||
struct lvmcache_info *info;
|
||||
struct device *dev;
|
||||
|
||||
if (!(dev = dev_cache_get(pv_name, cmd->filter))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!(dev = dev_cache_get(pv_name, cmd->filter)))
|
||||
return_NULL;
|
||||
|
||||
if (!(label_read(dev, &label, UINT64_C(0)))) {
|
||||
if (warnings)
|
||||
@@ -1871,10 +1950,8 @@ static struct physical_volume *_pv_read(struct cmd_context *cmd,
|
||||
if (!pv->size)
|
||||
return NULL;
|
||||
|
||||
if (!alloc_pv_segment_whole_pv(cmd->mem, pv)) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!alloc_pv_segment_whole_pv(cmd->mem, pv))
|
||||
return_NULL;
|
||||
|
||||
return pv;
|
||||
}
|
||||
@@ -1893,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;
|
||||
@@ -1981,7 +2058,7 @@ int pv_write(struct cmd_context *cmd __attribute((unused)),
|
||||
return _pv_write(cmd, pv, mdas, label_sector);
|
||||
}
|
||||
|
||||
static int _pv_write(struct cmd_context *cmd __attribute((unused)),
|
||||
static int _pv_write(struct cmd_context *cmd __attribute((unused)),
|
||||
struct physical_volume *pv,
|
||||
struct list *mdas, int64_t label_sector)
|
||||
{
|
||||
@@ -1996,10 +2073,8 @@ static int _pv_write(struct cmd_context *cmd __attribute((unused)),
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!pv->fmt->ops->pv_write(pv->fmt, pv, mdas, label_sector)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!pv->fmt->ops->pv_write(pv->fmt, pv, mdas, label_sector))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -2008,7 +2083,7 @@ int pv_write_orphan(struct cmd_context *cmd, struct physical_volume *pv)
|
||||
{
|
||||
const char *old_vg_name = pv->vg_name;
|
||||
|
||||
pv->vg_name = ORPHAN;
|
||||
pv->vg_name = cmd->fmt->orphan_vg_name;
|
||||
pv->status = ALLOCATABLE_PV;
|
||||
|
||||
if (!dev_get_size(pv->dev, &pv->size)) {
|
||||
@@ -2032,14 +2107,14 @@ int pv_write_orphan(struct cmd_context *cmd, struct physical_volume *pv)
|
||||
*/
|
||||
int is_orphan_vg(const char *vg_name)
|
||||
{
|
||||
return (!strcmp(vg_name, ORPHAN) ? 1 : 0);
|
||||
return (vg_name && vg_name[0] == ORPHAN_PREFIX[0]) ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* is_orphan - Determine whether a pv is an orphan based on its vg_name
|
||||
* @pv: handle to the physical volume
|
||||
*/
|
||||
int is_orphan(pv_t *pv)
|
||||
int is_orphan(const pv_t *pv)
|
||||
{
|
||||
return is_orphan_vg(pv_field(pv, vg_name));
|
||||
}
|
||||
@@ -2109,7 +2184,7 @@ int pv_analyze(struct cmd_context *cmd, const char *pv_name,
|
||||
int vg_check_status(const struct volume_group *vg, uint32_t status)
|
||||
{
|
||||
if ((status & CLUSTERED) &&
|
||||
(vg->status & CLUSTERED) && !locking_is_clustered() &&
|
||||
(vg_is_clustered(vg)) && !locking_is_clustered() &&
|
||||
!lockingfailed()) {
|
||||
log_error("Skipping clustered volume group %s", vg->name);
|
||||
return 0;
|
||||
@@ -2247,7 +2322,6 @@ uint32_t vg_status(const vg_t *vg)
|
||||
return vg->status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* pv_by_path - Given a device path return a PV handle if it is a PV
|
||||
* @cmd - handle to the LVM command instance
|
||||
|
||||
@@ -257,6 +257,9 @@ int get_pv_from_vg_by_id(const struct format_type *fmt, const char *vg_name,
|
||||
struct lv_list *find_lv_in_vg_by_lvid(struct volume_group *vg,
|
||||
const union lvid *lvid);
|
||||
|
||||
struct lv_list *find_lv_in_lv_list(const struct list *ll,
|
||||
const struct logical_volume *lv);
|
||||
|
||||
/* Return the VG that contains a given LV (based on path given in lv_name) */
|
||||
/* or environment var */
|
||||
struct volume_group *find_vg_with_lv(const char *lv_name);
|
||||
@@ -264,11 +267,14 @@ struct volume_group *find_vg_with_lv(const char *lv_name);
|
||||
/* Find LV with given lvid (used during activation) */
|
||||
struct logical_volume *lv_from_lvid(struct cmd_context *cmd,
|
||||
const char *lvid_s,
|
||||
int precommitted);
|
||||
unsigned precommitted);
|
||||
|
||||
/* FIXME Merge these functions with ones above */
|
||||
struct physical_volume *find_pv(struct volume_group *vg, struct device *dev);
|
||||
|
||||
struct pv_list *find_pv_in_pv_list(const struct list *pl,
|
||||
const struct physical_volume *pv);
|
||||
|
||||
/* Find LV segment containing given LE */
|
||||
struct lv_segment *find_seg_by_le(const struct logical_volume *lv, uint32_t le);
|
||||
|
||||
@@ -306,6 +312,13 @@ int add_seg_to_segs_using_this_lv(struct logical_volume *lv, struct lv_segment *
|
||||
int remove_seg_from_segs_using_this_lv(struct logical_volume *lv, struct lv_segment *seg);
|
||||
struct lv_segment *get_only_segment_using_this_lv(struct logical_volume *lv);
|
||||
|
||||
/*
|
||||
* For internal metadata caching.
|
||||
*/
|
||||
int export_vg_to_buffer(struct volume_group *vg, char **buf);
|
||||
struct volume_group *import_vg_from_buffer(char *buf,
|
||||
struct format_instance *fid);
|
||||
|
||||
/*
|
||||
* Mirroring functions
|
||||
*/
|
||||
|
||||
@@ -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) 2003-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@@ -33,8 +33,8 @@
|
||||
#define MIRROR_DISK_VERSION 2
|
||||
|
||||
/* These are the flags that represent the mirror failure restoration policies */
|
||||
#define MIRROR_REMOVE 0
|
||||
#define MIRROR_ALLOCATE 1
|
||||
#define MIRROR_REMOVE 0
|
||||
#define MIRROR_ALLOCATE 1
|
||||
#define MIRROR_ALLOCATE_ANYWHERE 2
|
||||
|
||||
/*
|
||||
@@ -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)
|
||||
@@ -504,6 +550,8 @@ static int _remove_mirror_images(struct logical_volume *lv,
|
||||
* to remove the layer. */
|
||||
if (new_area_count == 1 && !is_temporary_mirror_layer(lv)) {
|
||||
lv1 = seg_lv(mirrored_seg, 0);
|
||||
lv1->status &= ~MIRROR_IMAGE;
|
||||
lv1->status |= VISIBLE_LV;
|
||||
detached_log_lv = detach_mirror_log(mirrored_seg);
|
||||
if (!remove_layer_from_lv(lv, lv1))
|
||||
return_0;
|
||||
@@ -550,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;
|
||||
@@ -1002,10 +1061,8 @@ struct logical_volume *find_pvmove_lv_from_pvname(struct cmd_context *cmd,
|
||||
{
|
||||
struct physical_volume *pv;
|
||||
|
||||
if (!(pv = find_pv_by_name(cmd, name))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!(pv = find_pv_by_name(cmd, name)))
|
||||
return_NULL;
|
||||
|
||||
return find_pvmove_lv(vg, pv->dev, lv_type);
|
||||
}
|
||||
@@ -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);
|
||||
@@ -1184,7 +1254,7 @@ static struct logical_volume *_create_mirror_log(struct logical_volume *lv,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (dm_snprintf(log_name, len, "%s%s", lv->name, suffix) < 0) {
|
||||
if (dm_snprintf(log_name, len, "%s%s", lv_name, suffix) < 0) {
|
||||
log_error("log_name allocation failed.");
|
||||
return NULL;
|
||||
}
|
||||
@@ -1209,7 +1279,9 @@ static struct logical_volume *_set_up_mirror_log(struct cmd_context *cmd,
|
||||
int in_sync)
|
||||
{
|
||||
struct logical_volume *log_lv;
|
||||
const char *suffix;
|
||||
const char *suffix, *c;
|
||||
char *lv_name;
|
||||
size_t len;
|
||||
struct lv_segment *seg;
|
||||
|
||||
init_mirror_in_sync(in_sync);
|
||||
@@ -1219,15 +1291,34 @@ static struct logical_volume *_set_up_mirror_log(struct cmd_context *cmd,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Check if the log is for temporary sync layer. */
|
||||
/* Mirror log name is lv_name + suffix, determined as the following:
|
||||
* 1. suffix is:
|
||||
* o "_mlog" for the original mirror LV.
|
||||
* o "_mlogtmp_%d" for temporary mirror LV,
|
||||
* 2. lv_name is:
|
||||
* o lv->name, if the log is temporary
|
||||
* o otherwise, the top-level LV name
|
||||
*/
|
||||
seg = first_seg(lv);
|
||||
if (seg_type(seg, 0) == AREA_LV &&
|
||||
strstr(seg_lv(seg, 0)->name, MIRROR_SYNC_LAYER))
|
||||
strstr(seg_lv(seg, 0)->name, MIRROR_SYNC_LAYER)) {
|
||||
lv_name = lv->name;
|
||||
suffix = "_mlogtmp_%d";
|
||||
else
|
||||
} else if ((c = strstr(lv->name, MIRROR_SYNC_LAYER))) {
|
||||
len = c - lv->name + 1;
|
||||
if (!(lv_name = alloca(len)) ||
|
||||
!dm_snprintf(lv_name, len, "%s", lv->name)) {
|
||||
log_error("mirror log name allocation failed");
|
||||
return 0;
|
||||
}
|
||||
suffix = "_mlog";
|
||||
} else {
|
||||
lv_name = lv->name;
|
||||
suffix = "_mlog";
|
||||
}
|
||||
|
||||
if (!(log_lv = _create_mirror_log(lv, ah, alloc, lv->name, suffix))) {
|
||||
if (!(log_lv = _create_mirror_log(lv, ah, alloc,
|
||||
(const char *) lv_name, suffix))) {
|
||||
log_error("Failed to create mirror log.");
|
||||
return NULL;
|
||||
}
|
||||
@@ -1248,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;
|
||||
@@ -1261,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;
|
||||
|
||||
@@ -1279,7 +1381,7 @@ int add_mirror_log(struct cmd_context *cmd,
|
||||
return_0;
|
||||
|
||||
if (activation() && segtype->ops->target_present &&
|
||||
!segtype->ops->target_present(NULL)) {
|
||||
!segtype->ops->target_present(NULL, NULL)) {
|
||||
log_error("%s: Required device-mapper target(s) not "
|
||||
"detected in your kernel", segtype->name);
|
||||
return 0;
|
||||
@@ -1323,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");
|
||||
@@ -1395,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.");
|
||||
|
||||
|
||||
@@ -53,10 +53,8 @@ int alloc_pv_segment_whole_pv(struct dm_pool *mem, struct physical_volume *pv)
|
||||
return 1;
|
||||
|
||||
/* FIXME Cope with holes in PVs */
|
||||
if (!(peg = _alloc_pv_segment(mem, pv, 0, pv->pe_count, NULL, 0))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(peg = _alloc_pv_segment(mem, pv, 0, pv->pe_count, NULL, 0)))
|
||||
return_0;
|
||||
|
||||
list_add(&pv->segments, &peg->list);
|
||||
|
||||
@@ -72,10 +70,8 @@ int peg_dup(struct dm_pool *mem, struct list *peg_new, struct list *peg_old)
|
||||
list_iterate_items(pego, peg_old) {
|
||||
if (!(peg = _alloc_pv_segment(mem, pego->pv, pego->pe,
|
||||
pego->len, pego->lvseg,
|
||||
pego->lv_area))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
pego->lv_area)))
|
||||
return_0;
|
||||
list_add(peg_new, &peg->list);
|
||||
}
|
||||
|
||||
@@ -93,10 +89,8 @@ static int _pv_split_segment(struct physical_volume *pv, struct pv_segment *peg,
|
||||
|
||||
if (!(peg_new = _alloc_pv_segment(pv->fmt->cmd->mem, peg->pv, pe,
|
||||
peg->len + peg->pe - pe,
|
||||
NULL, 0))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
NULL, 0)))
|
||||
return_0;
|
||||
|
||||
peg->len = peg->len - peg_new->len;
|
||||
|
||||
@@ -130,10 +124,8 @@ int pv_split_segment(struct physical_volume *pv, uint32_t pe)
|
||||
if (pe == peg->pe)
|
||||
return 1;
|
||||
|
||||
if (!_pv_split_segment(pv, peg, pe)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!_pv_split_segment(pv, peg, pe))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -154,11 +146,9 @@ struct pv_segment *assign_peg_to_lvseg(struct physical_volume *pv,
|
||||
if (!pv)
|
||||
return &null_pv_segment;
|
||||
|
||||
if (!pv_split_segment(pv, pe) ||
|
||||
!pv_split_segment(pv, pe + area_len)) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!pv_split_segment(pv, pe) ||
|
||||
!pv_split_segment(pv, pe + area_len))
|
||||
return_NULL;
|
||||
|
||||
if (!(peg = find_peg_by_pe(pv, pe))) {
|
||||
log_error("Missing PV segment on %s at %u.",
|
||||
@@ -196,10 +186,8 @@ int release_pv_segment(struct pv_segment *peg, uint32_t area_reduction)
|
||||
}
|
||||
|
||||
if (!pv_split_segment(peg->pv, peg->pe + peg->lvseg->area_len -
|
||||
area_reduction)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
area_reduction))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -245,7 +233,7 @@ uint32_t pv_list_extents_free(const struct list *pvh)
|
||||
list_iterate_items(pvl, pvh) {
|
||||
list_iterate_items(per, pvl->pe_ranges) {
|
||||
list_iterate_items(pvseg, &pvl->pv->segments) {
|
||||
if (!pvseg->lvseg) /* free space */
|
||||
if (!pvseg_is_allocated(pvseg))
|
||||
extents += _overlap_pe(pvseg, per);
|
||||
}
|
||||
}
|
||||
@@ -371,10 +359,8 @@ static int _reduce_pv(struct physical_volume *pv, struct volume_group *vg, uint3
|
||||
}
|
||||
}
|
||||
|
||||
if (!pv_split_segment(pv, new_pe_count)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!pv_split_segment(pv, new_pe_count))
|
||||
return_0;
|
||||
|
||||
list_iterate_items_safe(peg, pegt, &pv->segments) {
|
||||
if (peg->pe + peg->len > new_pe_count)
|
||||
|
||||
@@ -40,10 +40,8 @@ static int _create_single_area(struct dm_pool *mem, struct pv_map *pvm,
|
||||
{
|
||||
struct pv_area *pva;
|
||||
|
||||
if (!(pva = dm_pool_zalloc(mem, sizeof(*pva)))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(pva = dm_pool_zalloc(mem, sizeof(*pva))))
|
||||
return_0;
|
||||
|
||||
log_debug("Allowing allocation on %s start PE %" PRIu32 " length %"
|
||||
PRIu32, pv_dev_name(pvm->pv), start, length);
|
||||
@@ -58,7 +56,7 @@ static int _create_single_area(struct dm_pool *mem, struct pv_map *pvm,
|
||||
static int _create_alloc_areas_for_pv(struct dm_pool *mem, struct pv_map *pvm,
|
||||
uint32_t start, uint32_t count)
|
||||
{
|
||||
struct pv_segment *peg;
|
||||
struct pv_segment *peg;
|
||||
uint32_t pe, end, area_len;
|
||||
|
||||
/* Only select extents from start to end inclusive */
|
||||
@@ -69,7 +67,7 @@ static int _create_alloc_areas_for_pv(struct dm_pool *mem, struct pv_map *pvm,
|
||||
pe = start;
|
||||
|
||||
/* Walk through complete ordered list of device segments */
|
||||
list_iterate_items(peg, &pvm->pv->segments) {
|
||||
list_iterate_items(peg, &pvm->pv->segments) {
|
||||
/* pe holds the next extent we want to check */
|
||||
|
||||
/* Beyond the range we're interested in? */
|
||||
@@ -88,14 +86,12 @@ static int _create_alloc_areas_for_pv(struct dm_pool *mem, struct pv_map *pvm,
|
||||
area_len = (end >= peg->pe + peg->len - 1) ?
|
||||
peg->len - (pe - peg->pe) : end - pe + 1;
|
||||
|
||||
if (!_create_single_area(mem, pvm, pe, area_len)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!_create_single_area(mem, pvm, pe, area_len))
|
||||
return_0;
|
||||
|
||||
next:
|
||||
pe = peg->pe + peg->len;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -108,20 +104,16 @@ static int _create_all_areas_for_pv(struct dm_pool *mem, struct pv_map *pvm,
|
||||
if (!pe_ranges) {
|
||||
/* Use whole PV */
|
||||
if (!_create_alloc_areas_for_pv(mem, pvm, UINT32_C(0),
|
||||
pvm->pv->pe_count)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
pvm->pv->pe_count))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
list_iterate_items(aa, pe_ranges) {
|
||||
if (!_create_alloc_areas_for_pv(mem, pvm, aa->start,
|
||||
aa->count)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
aa->count))
|
||||
return_0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -145,20 +137,16 @@ static int _create_maps(struct dm_pool *mem, struct list *pvs, struct list *pvms
|
||||
}
|
||||
|
||||
if (!pvm) {
|
||||
if (!(pvm = dm_pool_zalloc(mem, sizeof(*pvm)))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(pvm = dm_pool_zalloc(mem, sizeof(*pvm))))
|
||||
return_0;
|
||||
|
||||
pvm->pv = pvl->pv;
|
||||
list_init(&pvm->areas);
|
||||
list_add(pvms, &pvm->list);
|
||||
}
|
||||
|
||||
if (!_create_all_areas_for_pv(mem, pvm, pvl->pe_ranges)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!_create_all_areas_for_pv(mem, pvm, pvl->pe_ranges))
|
||||
return_0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user