mirror of
git://sourceware.org/git/lvm2.git
synced 2025-10-23 23:33:15 +03:00
Compare commits
392 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
181ea9a381 | ||
|
|
76b8f2854e | ||
|
|
320e5198f9 | ||
|
|
e522539e2d | ||
|
|
7c996b83d2 | ||
|
|
3dd354d7aa | ||
|
|
f4ad6e2157 | ||
|
|
8b170dc2bf | ||
|
|
dcb9d779bf | ||
|
|
80f736d670 | ||
|
|
8502c6da3c | ||
|
|
b131449422 | ||
|
|
6eebc4a620 | ||
|
|
4661ab1179 | ||
|
|
86046445ed | ||
|
|
baea9bf944 | ||
|
|
0951ee9e63 | ||
|
|
5492528287 | ||
|
|
14dbd220c2 | ||
|
|
babc890c59 | ||
|
|
6f7b47ff40 | ||
|
|
3991f03202 | ||
|
|
27271d5da7 | ||
|
|
627312e1de | ||
|
|
bfc9550e4e | ||
|
|
2b9c21268b | ||
|
|
3dce4ed6f1 | ||
|
|
0f16c2ea87 | ||
|
|
9a635f0686 | ||
|
|
6a0d4b2baa | ||
|
|
ac017098ad | ||
|
|
98fef2640d | ||
|
|
8bb66e133a | ||
|
|
68a582901d | ||
|
|
c094f4c06e | ||
|
|
f7ca545544 | ||
|
|
69b4716894 | ||
|
|
7e44dcc5bf | ||
|
|
ab9843e183 | ||
|
|
01af706ade | ||
|
|
9ebdb08e99 | ||
|
|
a74ffe25d9 | ||
|
|
7f95e27707 | ||
|
|
1facf5bba3 | ||
|
|
03d77009eb | ||
|
|
8afd6812b5 | ||
|
|
ec9ad78fcf | ||
|
|
6f4e93dc90 | ||
|
|
a38e43862d | ||
|
|
39294bb037 | ||
|
|
edc5e59b78 | ||
|
|
c00fd9fd37 | ||
|
|
b3e621dd9f | ||
|
|
6e8c49b978 | ||
|
|
398d57133d | ||
|
|
16521a6feb | ||
|
|
3ca0b37a3e | ||
|
|
cf2ec1229d | ||
|
|
fe9b1e5f9b | ||
|
|
f5b96ddf01 | ||
|
|
2fe076fb27 | ||
|
|
99249cff04 | ||
|
|
0cdf7b0613 | ||
|
|
90bcf4f157 | ||
|
|
03c3ec4e12 | ||
|
|
ca9bb20d64 | ||
|
|
c6bc078fd9 | ||
|
|
2f4bd6e52c | ||
|
|
2affe53727 | ||
|
|
09654d7dd8 | ||
|
|
90a4e37815 | ||
|
|
60889c0c79 | ||
|
|
20f3408d96 | ||
|
|
e9d86789db | ||
|
|
5152b7c66c | ||
|
|
c494c4e12c | ||
|
|
54d58ccb7e | ||
|
|
714a77bfbe | ||
|
|
d48f8bf5cc | ||
|
|
99d97754a6 | ||
|
|
b9d437de2a | ||
|
|
11403f2019 | ||
|
|
1ca102d639 | ||
|
|
339ba55111 | ||
|
|
14ae59885a | ||
|
|
e3ef54f99b | ||
|
|
001901f9a9 | ||
|
|
6a98f60e2e | ||
|
|
6f2e24c47d | ||
|
|
aafa368923 | ||
|
|
eb783cab4c | ||
|
|
6533aa865a | ||
|
|
f1a1e1bc07 | ||
|
|
953f4838dd | ||
|
|
130b892d34 | ||
|
|
6ad525c77e | ||
|
|
d0ca74ad27 | ||
|
|
9806f69b4d | ||
|
|
34d9b5e3d7 | ||
|
|
3bf5189d86 | ||
|
|
12e5b0681b | ||
|
|
8c0285d608 | ||
|
|
36558fa3b8 | ||
|
|
235f940cde | ||
|
|
803d61fcbc | ||
|
|
ffbd7d8de4 | ||
|
|
4ed924d7c7 | ||
|
|
798dc9948b | ||
|
|
13515f7ee4 | ||
|
|
ef80824c26 | ||
|
|
c8503fd65e | ||
|
|
b3c454fb1c | ||
|
|
1d7723e873 | ||
|
|
77100b2365 | ||
|
|
259a788134 | ||
|
|
39511455cb | ||
|
|
b04c16178e | ||
|
|
49a959c06e | ||
|
|
096a8932b4 | ||
|
|
e39e66df93 | ||
|
|
513633f49a | ||
|
|
eb3740daaf | ||
|
|
f7947b148a | ||
|
|
9a2a702f3f | ||
|
|
c65d95bf29 | ||
|
|
753a5edc4f | ||
|
|
0b3f853c2d | ||
|
|
3527fcf1d5 | ||
|
|
4544a89c7a | ||
|
|
ffeae9005e | ||
|
|
47217bcfb7 | ||
|
|
80ff58b57a | ||
|
|
d15dd368f1 | ||
|
|
8a2ec32bd8 | ||
|
|
410496ed52 | ||
|
|
b7b07552e5 | ||
|
|
44486e80d9 | ||
|
|
7890c527d8 | ||
|
|
2c82ab79a7 | ||
|
|
e3ebe5fc53 | ||
|
|
0ac430892e | ||
|
|
a7739c942c | ||
|
|
24581482d0 | ||
|
|
0571c3b453 | ||
|
|
73e7f5a0b0 | ||
|
|
20c0adb961 | ||
|
|
a01e03562f | ||
|
|
d184ed0130 | ||
|
|
089e1c2aee | ||
|
|
ebab0e91ee | ||
|
|
858a2b1b88 | ||
|
|
02bd59827c | ||
|
|
4991428510 | ||
|
|
3b245f5dc1 | ||
|
|
c9c81da901 | ||
|
|
4919cdc3fb | ||
|
|
e90e1f577d | ||
|
|
afd4284403 | ||
|
|
150b350d31 | ||
|
|
2818520bd1 | ||
|
|
2819952292 | ||
|
|
5af71af51c | ||
|
|
07a55b51df | ||
|
|
66dd68b49d | ||
|
|
9812657777 | ||
|
|
0b09312fc6 | ||
|
|
d0a7ac6b74 | ||
|
|
ff9a238fbd | ||
|
|
359fffa5f1 | ||
|
|
5bf92ced1a | ||
|
|
340bcc7b45 | ||
|
|
ef03742bd4 | ||
|
|
20431ec16d | ||
|
|
becba8157b | ||
|
|
51fd3bb0eb | ||
|
|
4bbd3acb4e | ||
|
|
3bc930ea7b | ||
|
|
d1b26f8e86 | ||
|
|
fdf15caaff | ||
|
|
c7b4a53c0b | ||
|
|
af78dc0308 | ||
|
|
5ad39493c4 | ||
|
|
61f597b408 | ||
|
|
2162825240 | ||
|
|
2b780e70d1 | ||
|
|
a3823f818e | ||
|
|
1f7c47bcaf | ||
|
|
ec53c365a2 | ||
|
|
793ad1f2d4 | ||
|
|
9bc733b76c | ||
|
|
21b28f0217 | ||
|
|
d3e23caa52 | ||
|
|
9e7518de67 | ||
|
|
679f0047aa | ||
|
|
d77d5ce14b | ||
|
|
33ec22a2af | ||
|
|
353053225f | ||
|
|
b7f3d6f7f7 | ||
|
|
e34577499d | ||
|
|
4cf8960c0c | ||
|
|
1f93ea0675 | ||
|
|
25b705c3a8 | ||
|
|
0725588731 | ||
|
|
fc5c61cc8b | ||
|
|
ac282e63c6 | ||
|
|
c3941941ce | ||
|
|
46cdd53323 | ||
|
|
3ff3e302c3 | ||
|
|
f2ceecf95c | ||
|
|
9314c7c881 | ||
|
|
54abb2c572 | ||
|
|
8fa3bdd025 | ||
|
|
5e7a308528 | ||
|
|
7952177786 | ||
|
|
9afbe49c84 | ||
|
|
9f06ba2db3 | ||
|
|
fe55bfddcf | ||
|
|
c0842e6444 | ||
|
|
3fed20d06a | ||
|
|
5e8f2e2c04 | ||
|
|
e4df99ea84 | ||
|
|
b3276f5f11 | ||
|
|
32667ca256 | ||
|
|
bed122a170 | ||
|
|
14adc9b875 | ||
|
|
a8778bbc5a | ||
|
|
a54e641f44 | ||
|
|
5c99efe87a | ||
|
|
7da1d731ff | ||
|
|
af9828e819 | ||
|
|
7a27136142 | ||
|
|
012ad2d423 | ||
|
|
ef3bdbf4da | ||
|
|
b3bb698f7b | ||
|
|
1ed5d1e4c1 | ||
|
|
bdee01a03d | ||
|
|
458f7376d7 | ||
|
|
cb3a00e027 | ||
|
|
482eb1f3fb | ||
|
|
6e0f638f5e | ||
|
|
bab349047d | ||
|
|
28ea6b8de8 | ||
|
|
9d51bbdae8 | ||
|
|
d622f79533 | ||
|
|
04c8515ad1 | ||
|
|
53bc4251d1 | ||
|
|
a5a751f02f | ||
|
|
66ed5f82c4 | ||
|
|
c802a9e6aa | ||
|
|
880f210946 | ||
|
|
4f9f7eb6a6 | ||
|
|
f910c4a8e7 | ||
|
|
529686d965 | ||
|
|
84dfd1536f | ||
|
|
85dedc324c | ||
|
|
d639237411 | ||
|
|
449aaf75f1 | ||
|
|
b1fda66caa | ||
|
|
66a8e90fd9 | ||
|
|
37b487d191 | ||
|
|
6c59fe3577 | ||
|
|
1cbb70c992 | ||
|
|
e06b39f882 | ||
|
|
2602b1493e | ||
|
|
989d14502d | ||
|
|
f78a550282 | ||
|
|
54a1abb284 | ||
|
|
97b492a8e2 | ||
|
|
0873bd14a9 | ||
|
|
eff6ba429a | ||
|
|
8c18064be4 | ||
|
|
44a1ac0cf3 | ||
|
|
28dc8d88dd | ||
|
|
2c0c2b64ba | ||
|
|
bd3e0f5248 | ||
|
|
cd52d98938 | ||
|
|
894c70e7f8 | ||
|
|
51d70c2edd | ||
|
|
7d4b355240 | ||
|
|
3b56193b98 | ||
|
|
b16045b57d | ||
|
|
9e8b0fca5b | ||
|
|
35cf1b3b5b | ||
|
|
83f788af57 | ||
|
|
2ffe378d3f | ||
|
|
38b33a4a5e | ||
|
|
60bf9ed0a0 | ||
|
|
16adf4de1b | ||
|
|
80de983023 | ||
|
|
8703ca623f | ||
|
|
286253a73f | ||
|
|
bd806a41df | ||
|
|
b89c4e9002 | ||
|
|
6dbf31c0c3 | ||
|
|
060c45d8a1 | ||
|
|
33d3e82e4d | ||
|
|
4bb074514d | ||
|
|
e3f8892003 | ||
|
|
9d00ad5f18 | ||
|
|
dae4344850 | ||
|
|
aa7f3fabe2 | ||
|
|
f93434a8ce | ||
|
|
25dee56be9 | ||
|
|
ce9a3f3797 | ||
|
|
11e384920a | ||
|
|
a0a1f1e536 | ||
|
|
3b3d0ea9eb | ||
|
|
2f4d78286d | ||
|
|
677dc6f985 | ||
|
|
d52057e732 | ||
|
|
fa2a1cb1fb | ||
|
|
19a0fb04ad | ||
|
|
947352f2fe | ||
|
|
adcbedb686 | ||
|
|
7732f92acd | ||
|
|
ad8a001688 | ||
|
|
9121eada08 | ||
|
|
49bd4d25a2 | ||
|
|
d80b4129c6 | ||
|
|
7edb4172d5 | ||
|
|
c3a4677990 | ||
|
|
5cbb893a3b | ||
|
|
f28a2a432b | ||
|
|
03b75a2d27 | ||
|
|
859fe69083 | ||
|
|
f6f2205ddb | ||
|
|
0f9a03ef61 | ||
|
|
9aa417c084 | ||
|
|
7b70952f5d | ||
|
|
edd3d07b49 | ||
|
|
5293d0a4ec | ||
|
|
3c8c7beae1 | ||
|
|
9c3ba9fdcd | ||
|
|
fb1748fb0f | ||
|
|
0a109fbd03 | ||
|
|
5cf64db74e | ||
|
|
488cc94f36 | ||
|
|
e15846bf79 | ||
|
|
752bd00674 | ||
|
|
7fadfcbe32 | ||
|
|
41141e75bb | ||
|
|
50f641e627 | ||
|
|
c7883fd093 | ||
|
|
4fcb24b2b1 | ||
|
|
5003557935 | ||
|
|
bdf1ba84da | ||
|
|
b0b4def983 | ||
|
|
cc184bbe9e | ||
|
|
ad30c830aa | ||
|
|
1d791a8af4 | ||
|
|
e63c51cd97 | ||
|
|
f202e32908 | ||
|
|
26e1a08e82 | ||
|
|
4d5119d435 | ||
|
|
75e34ea62e | ||
|
|
0a183d6274 | ||
|
|
21d8060aea | ||
|
|
9cbe906f60 | ||
|
|
8ce4137399 | ||
|
|
5f8a139347 | ||
|
|
9bb009a3fe | ||
|
|
726d65923f | ||
|
|
8a6be4cb2d | ||
|
|
10b06beb8e | ||
|
|
81318c7968 | ||
|
|
47a2c1c6e5 | ||
|
|
39cee65c6b | ||
|
|
8582ec724e | ||
|
|
b0139682e8 | ||
|
|
d39c475a6d | ||
|
|
48f38354c6 | ||
|
|
cd5a920ed5 | ||
|
|
71bc1f378d | ||
|
|
0ee6c31cff | ||
|
|
af89a9971e | ||
|
|
c718a8ef72 | ||
|
|
8c8ad0faf0 | ||
|
|
314d5bbb7f | ||
|
|
102255757a | ||
|
|
914067a0d0 | ||
|
|
06e3ae2536 | ||
|
|
7f9b252556 | ||
|
|
3d700e243f | ||
|
|
bcfc78ce11 | ||
|
|
09241765d5 | ||
|
|
671c83c265 | ||
|
|
772d28b766 | ||
|
|
c26fcea58d | ||
|
|
1e5e26dbff | ||
|
|
742fc54864 | ||
|
|
49738f43c0 | ||
|
|
9f85f61010 |
2
BUGS
2
BUGS
@@ -1,2 +0,0 @@
|
||||
Snapshots under 2.4.18 can deadlock due to a bug in the VM system.
|
||||
2.4.19-pre8 is fine.
|
||||
0
CONTRIBUTORS
Normal file
0
CONTRIBUTORS
Normal file
49
Makefile.in
49
Makefile.in
@@ -1,35 +1,52 @@
|
||||
#
|
||||
# Copyright (C) 2001 Sistina Software
|
||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This LVM library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Library General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2 of the License, or (at your option) any later version.
|
||||
# This file is part of the LVM2.
|
||||
#
|
||||
# This LVM library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Library General Public License for more details.
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU Library General Public
|
||||
# License along with this LVM library; if not, write to the Free
|
||||
# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
# MA 02111-1307, USA
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
SUBDIRS = include man lib tools
|
||||
SUBDIRS = doc include man
|
||||
|
||||
ifeq ("@INTL@", "yes")
|
||||
SUBDIRS += po
|
||||
endif
|
||||
|
||||
SUBDIRS += lib tools daemons
|
||||
|
||||
ifeq ($(MAKECMDGOALS),distclean)
|
||||
SUBDIRS += lib/format1 \
|
||||
SUBDIRS += daemons/clvmd \
|
||||
lib/format1 \
|
||||
lib/format_pool \
|
||||
lib/locking \
|
||||
lib/mirror \
|
||||
lib/snapshot \
|
||||
po \
|
||||
test/mm test/device test/format1 test/regex test/filters
|
||||
endif
|
||||
|
||||
include make.tmpl
|
||||
|
||||
daemons: lib
|
||||
lib: include
|
||||
tools: include lib
|
||||
tools: lib
|
||||
po: tools daemons
|
||||
|
||||
ifeq ("@INTL@", "yes")
|
||||
lib.pofile: include.pofile
|
||||
tools.pofile: lib.pofile
|
||||
daemons.pofile: lib.pofile
|
||||
po.pofile: tools.pofile daemons.pofile
|
||||
pofile: po.pofile
|
||||
endif
|
||||
|
||||
|
||||
20
README
20
README
@@ -1,25 +1,23 @@
|
||||
This directory contains a beta release of LVM2, the new version of
|
||||
the userland LVM tools designed for the new device-mapper for
|
||||
the Linux kernel.
|
||||
This directory contains LVM2, the new version of the userland LVM
|
||||
tools designed for the new device-mapper for the Linux kernel.
|
||||
|
||||
The device-mapper needs to be installed before compiling these LVM2 tools.
|
||||
|
||||
For more information about LVM2 read the WHATS_NEW file.
|
||||
Installation instructions are in INSTALL.
|
||||
|
||||
This is beta-quality software, released for testing purposes only.
|
||||
There is no warranty - see COPYING and COPYING.LIB.
|
||||
|
||||
Tarballs are available from:
|
||||
ftp://ftp.sistina.com/pub/LVM2/tools/
|
||||
ftp://ftp.sistina.com/pub/LVM2/device-mapper/
|
||||
ftp://sources.redhat.com/pub/lvm2/
|
||||
ftp://sources.redhat.com/pub/dm/
|
||||
|
||||
To access the CVS tree use:
|
||||
cvs -d :pserver:cvs@tech.sistina.com:/data/cvs login
|
||||
CVS password: cvs1
|
||||
cvs -d :pserver:cvs@tech.sistina.com:/data/cvs checkout LVM2
|
||||
cvs -d :pserver:cvs@sources.redhat.com:/cvs/lvm2 login
|
||||
CVS password: cvs
|
||||
cvs -d :pserver:cvs@sources.redhat.com:/cvs/lvm2 co LVM2
|
||||
|
||||
Mailing list for discussion/bug reports etc.
|
||||
lvm-devel@sistina.com
|
||||
Subscribe from http://lists.sistina.com/mailman/listinfo/lvm-devel
|
||||
linux-lvm@redhat.com
|
||||
Subscribe from https://www.redhat.com/mailman/listinfo/linux-lvm
|
||||
|
||||
|
||||
284
WHATS_NEW
284
WHATS_NEW
@@ -1,3 +1,286 @@
|
||||
Version 2.00.34 -
|
||||
==================================
|
||||
Adjust RHEL4 clvmd init script priority.
|
||||
|
||||
Version 2.00.33 - 7th January 2005
|
||||
==================================
|
||||
pvcreate wipes first 4 sectors unless given --zero n.
|
||||
gulm clvmd now uses new ccsd key names.
|
||||
gulm clvmd now doesn't ignore the first node in cluster.conf
|
||||
Improve clvmd failure message if it's already running.
|
||||
Allow user to kill clvmd during initialisation.
|
||||
Fix off-by-one error in cluster_locking that could cause read hangs.
|
||||
|
||||
Version 2.00.32 - 22nd December 2004
|
||||
====================================
|
||||
Drop static/dl restriction for now.
|
||||
Fix an error fprintf.
|
||||
Fix vgdisplay -s. Breaks (undocumented) lvs/pvs/vgs -s instead for now.
|
||||
Fix device reference counting on re-opens.
|
||||
Ignore sysfs symlinks when DT_UNKNOWN.
|
||||
Add clvmd init script for RHEL4.
|
||||
Skip devices that are too small to be PVs.
|
||||
Fix pvchange -x segfault with lvm2-format orphan.
|
||||
Cope with empty msdos partition tables.
|
||||
Add CONTRIBUTORS file.
|
||||
|
||||
Version 2.00.31 - 12th December 2004
|
||||
====================================
|
||||
Reopen RO file descriptors RW if necessary.
|
||||
|
||||
Version 2.00.30 - 10th December 2004
|
||||
====================================
|
||||
Additional device-handling debug messages.
|
||||
Additional verbosity level -vvvv includes line numbers and backtraces.
|
||||
Verbose messages now go to stderr not stdout.
|
||||
Close any stray file descriptors before starting.
|
||||
Refine partitionable checks for certain device types.
|
||||
Allow devices/types to override built-ins.
|
||||
Fix lvreduce man page .i->.I
|
||||
Fix vgsplit man page title.
|
||||
Fix clvmd man makefile.
|
||||
Extend dev_open logging.
|
||||
Make clvmd_fix_conf.sh UNDOable.
|
||||
|
||||
Version 2.00.29 - 27th November 2004
|
||||
====================================
|
||||
xlate compilation fix.
|
||||
|
||||
Version 2.00.28 - 27th November 2004
|
||||
====================================
|
||||
Fix partition table & md signature detection.
|
||||
Minor configure/makefile tidy.
|
||||
Export version.h from tools for clvmd.
|
||||
|
||||
Version 2.00.27 - 24th November 2004
|
||||
====================================
|
||||
Trap large memory allocation requests.
|
||||
Fix to partition table detection code.
|
||||
Improve filter debug mesgs.
|
||||
Make clvmd_fix_conf.sh UNDOable
|
||||
|
||||
Version 2.00.26 - 23rd November 2004
|
||||
====================================
|
||||
Improve pool debugging stats.
|
||||
Detect partition table signature.
|
||||
pvcreate wipes md superblocks. (With --uuid or --restorefile it prompts.)
|
||||
Separate out md superblock detection code.
|
||||
Prevent snapshot origin resizing.
|
||||
Improve a vgremove error message.
|
||||
Update some man pages.
|
||||
Allow y/n with -ae args (exclusive activation).
|
||||
Fixes to lvcreate vgname parsing.
|
||||
Fix dm_name string size calculation.
|
||||
Improve clvmd error reporting during startup.
|
||||
Make clvmd cope with large gaps in node numbers IDs.
|
||||
Make clvmd initialisation cope better with debugging output.
|
||||
Tidy clvmd socket callbacks so all work happens outside main loop.
|
||||
clvmd -V now displays lvm version too.
|
||||
Add optional gulm build for clvmd
|
||||
|
||||
Version 2.00.25 - 29th September 2004
|
||||
=====================================
|
||||
Fix return code from rm_link for vgmknodes.
|
||||
Make clvmd LV hash table thread-safe.
|
||||
Fix clvmd locking so it will lock out multiple users on the same node.
|
||||
Fix clvmd VG locking to it can cope with multiple VG locks.
|
||||
Remove spurious trailing dot in lvreduce man page.
|
||||
Fix vgremove locking.
|
||||
|
||||
Version 2.00.24 - 16th September 2004
|
||||
=====================================
|
||||
Fix pool_empty so it really does empty the memory pool.
|
||||
Rename old segtypes files to segtype.
|
||||
Some fixes to memory debugging code.
|
||||
Exclude internal commands formats & segtypes from install.
|
||||
|
||||
Version 2.00.23 - 15th September 2004
|
||||
=====================================
|
||||
Export dm name build & split functions.
|
||||
Use O_NOATIME on devices if available.
|
||||
Write log message when each segtype/format gets initialised.
|
||||
New commands 'segtypes' and 'formats'.
|
||||
Suppress pvmove abort message in test mode.
|
||||
Improve pvcreate/remove device not found error message.
|
||||
Allow pvmove to move data within the same PV.
|
||||
Describe how pvmove works on man page.
|
||||
Test for incompatible format/segtype combinations in lv_extend.
|
||||
Fix lvchange example on man page.
|
||||
|
||||
Version 2.00.22 - 3rd September 2004
|
||||
====================================
|
||||
Fix /dev/vgname perms.
|
||||
Restructure xlate.h.
|
||||
Add clvmd man page.
|
||||
|
||||
Version 2.00.21 - 19th August 2004
|
||||
==================================
|
||||
Update cnxman-socket.h from cman.
|
||||
Recognise iseries/vd devices.
|
||||
Use 'make install_cluster' to install cluster extensions only.
|
||||
Cope with DT_UNKNOWN in sysfs.
|
||||
Fix extents_moved metadata size comment.
|
||||
Remove duplicate line in pvremove help text.
|
||||
Support variable mirror region size.
|
||||
Support PE ranges in pvmove source PV.
|
||||
Fixes to as-yet-unused LV segment splitting code.
|
||||
Change alloc_areas to pe_ranges and allow suppression of availability checks.
|
||||
Add dev_size column to pvs.
|
||||
Add report columns for in-kernel device number.
|
||||
|
||||
Version 2.00.20 - 3 July 2004
|
||||
=============================
|
||||
More autoconf fixes.
|
||||
Fix device number handling for 2.6 kernels.
|
||||
|
||||
Version 2.00.19 - 29 June 2004
|
||||
==============================
|
||||
Reduce severity of setlocale failure message.
|
||||
Recognise argv[0] "initrd-lvm" (pld-linux).
|
||||
Make -O2 configurable.
|
||||
Added --disable-selinux to configure script.
|
||||
LD_FLAGS->LDFLAGS & LD_DEPS->LDDEPS in configure script.
|
||||
Add init_debug to clvmd.
|
||||
|
||||
Version 2.00.18 - 24 June 2004
|
||||
==============================
|
||||
Fix vgchange activation.
|
||||
Add cluster support.
|
||||
|
||||
Version 2.00.17 - 20 June 2004
|
||||
==============================
|
||||
configure --enable-fsadm to try out fsadm. fsadm is not tested yet.
|
||||
Display all filtered devices, not just PVs, with pvs -a.
|
||||
Fix sync_dir() when no / in filename
|
||||
vgcfgbackup -f accepts template with %s for VG name.
|
||||
Extend hash functions to handle non-null-terminated data.
|
||||
Add local activation support.
|
||||
Tidy relative paths in makefile includes.
|
||||
fsadm support for fsck and resizing - needs testing.
|
||||
Add read-only GFS pool support.
|
||||
Add lvm2create_initrd script from http://poochiereds.net/svn/lvm2/
|
||||
Fix rounding of large diplayed sizes.
|
||||
Suppress decimal point when using units of sectors/bytes.
|
||||
Additional kernel target checks before pvmove & snapshot creation.
|
||||
Add i2o_block.
|
||||
|
||||
Version 2.00.16 - 24 May 2004
|
||||
=============================
|
||||
Set area_count within alloc_lv_segment.
|
||||
Remove error labels from lvresize.
|
||||
Fix a pvs error path.
|
||||
xxchange -ae for exclusive activation.
|
||||
Don't return non-zero status if there aren't any volume groups.
|
||||
Add --alloc argument to tools.
|
||||
Rename allocation policies to contiguous, normal, anywhere, inherit.
|
||||
nextfree becomes normal; anywhere isn't implemented yet.
|
||||
LV inherits allocation policy from VG. Defaults: LV - inherit; VG - normal
|
||||
Additional status character added to vgs to indicate allocation policy.
|
||||
Add reset_fn to external_locking.
|
||||
Ensure presence of virtual targets before attempting activating.
|
||||
Attempt to fix resizing of snapshot origins.
|
||||
Restructure lvresize, bringing it closer to lvcreate.
|
||||
A quick sanity check on vg_disk struct when read in. More checks needed.
|
||||
Only include visible LVs in active/open counts.
|
||||
Add virtual segment types, zero and error. A large sparse device can be
|
||||
constructed as a writeable snapshot of a large zero segment.
|
||||
Add --type to lvcreate/resize.
|
||||
Push lv_create & alloc policy up to tool level.
|
||||
Fix pvdisplay return code.
|
||||
Detect invalid LV names in arg lists.
|
||||
Reporting uses line-at-a-time output.
|
||||
lvm2 format sets unlimited_vols format flag.
|
||||
Internal-only metadata flag support.
|
||||
Basic checking for presence of device-mapper targets.
|
||||
Separate out polldaemon.
|
||||
Revise internal locking semantics.
|
||||
Move find_pv_by_name to library.
|
||||
Rename move->copy.
|
||||
Add devices to segments report.
|
||||
Begin separating out segment code. There's a lot of change here.
|
||||
Compress any (obsolete) long LVM1 pvids encountered.
|
||||
Support for tagged config files.
|
||||
Don't abort operations if selinux present but disabled.
|
||||
Fix typo in configure which left HAVE_LIBDL unset.
|
||||
|
||||
Version 2.00.15 - 19 Apr 2004
|
||||
=============================
|
||||
configure --with-owner= --with-group= to avoid -o and -g args to 'install'
|
||||
|
||||
Version 2.00.14 - 16 Apr 2004
|
||||
=============================
|
||||
Use 64-bit file functions by default.
|
||||
|
||||
Version 2.00.13 - 16 Apr 2004
|
||||
=============================
|
||||
Set devices/md_component_detection = 1 to ignore devices containing md
|
||||
superblocks. [Luca Berra]
|
||||
Ignore error setting selinux file context if fs doesn't support it.
|
||||
|
||||
Version 2.00.12 - 14 Apr 2004
|
||||
=============================
|
||||
Install a default lvm.conf into /etc/lvm if there isn't one already.
|
||||
Allow different installation dir for lvm.static (configure --staticdir=)
|
||||
Fix inverted selinux error check.
|
||||
Recognise power2 in /proc/devices.
|
||||
Fix counting in lvs_in_vg_opened. [It ignored devices open more than once.]
|
||||
|
||||
Version 2.00.11 - 8 Apr 2004
|
||||
============================
|
||||
Set fallback_to_lvm1 in lvm.conf (or configure --enable-lvm1_fallback)
|
||||
to run lvm1 binaries if running a 2.4 kernel without device-mapper.
|
||||
|
||||
Version 2.00.10 - 7 Apr 2004
|
||||
============================
|
||||
More fixes for static build.
|
||||
Add basic selinux support.
|
||||
Fix sysfs detection.
|
||||
|
||||
Version 2.00.09 - 31 Mar 2004
|
||||
=============================
|
||||
Update copyright notices for Red Hat.
|
||||
Fix vgmknodes to remove dud /dev/mapper entries. (libdevmapper update reqd).
|
||||
Add LVM1-style colon output to vgdisplay.
|
||||
lvchange --refresh to reload active LVs.
|
||||
Add string display to memory leak dump.
|
||||
Add locking flags & memlock option.
|
||||
Add list_versions to library.
|
||||
Ignore open hidden LVs when checking if deactivation is OK.
|
||||
Suppress move percentage when device inactive.
|
||||
Add lv_info_by_lvid.
|
||||
Various tidy-ups to the build process.
|
||||
Rebaseline internal verbose level.
|
||||
Add --nolocking option for read operations if locking is failing.
|
||||
Add option to compile into a library.
|
||||
When compiled without libdevmapper, only print warning message once.
|
||||
Fix lvreduce PV extent calculations.
|
||||
Fix DESTDIR to work with configure path overrides.
|
||||
Always use / as config file separator & rename internal config file variables.
|
||||
Add support for tagging PV/VG/LVs and hosts.
|
||||
Fix rare bug in recognition of long cmdline argument forms.
|
||||
Add basic internationalisation infrastructure.
|
||||
Don't recurse symlinked dirs such as /dev/fd on 2.6 kernels.
|
||||
Update autoconf files.
|
||||
Add sysfs block device filtering for 2.6 kernels.
|
||||
Update refs for move to sources.redhat.com.
|
||||
|
||||
Friday 14th November 2003
|
||||
=========================
|
||||
Some bug fixes & minor enhancements, including:
|
||||
Backwards compatibility with LVM1 metadata improved.
|
||||
Missing man pages written.
|
||||
Tool error codes made more consistent.
|
||||
vgmknodes written.
|
||||
O_DIRECT can be turned off if it doesn't work in your kernel.
|
||||
dumpconfig to display the active configuration file
|
||||
|
||||
You need to update libdevmapper before using 'vgmknodes' or 'vgscan --mknodes'.
|
||||
If your root filesystem is on an LV, you should run one of those two
|
||||
commands to fix up the special files in /dev in your real root filesystem
|
||||
after finishing with your initrd. Also, remember you can use
|
||||
'vgchange --ignorelockingfailure' on your initrd if the tool fails because
|
||||
it can't write a lock file to a read-only filesystem.
|
||||
|
||||
Wednesday 30th April 2003
|
||||
=========================
|
||||
A pvmove implementation is now available for the new metadata format.
|
||||
@@ -25,6 +308,7 @@ to provide us with diagnostic information:
|
||||
log {
|
||||
file="/tmp/lvm2.log"
|
||||
level=7
|
||||
activation=1
|
||||
}
|
||||
|
||||
You should schedule regular backups of your configuration file and
|
||||
|
||||
90
WHATS_NEW_DM
Normal file
90
WHATS_NEW_DM
Normal file
@@ -0,0 +1,90 @@
|
||||
Version 1.01.00 -
|
||||
============================
|
||||
Add dm_task_no_open_count() to skip getting open_count.
|
||||
|
||||
Version 1.00.21 - 7 Jan 2005
|
||||
============================
|
||||
Fix /proc/devices parsing.
|
||||
|
||||
Version 1.00.20 - 6 Jan 2005
|
||||
============================
|
||||
Attempt to fix /dev/mapper/control transparently if it's wrong.
|
||||
Configuration-time option for setting uid/gid/mode for /dev/mapper nodes.
|
||||
Update kernel patches for 2.4.27/2.4.28-pre-4 (includes minor fixes).
|
||||
Add --noheadings columns option for colon-separated dmsetup output.
|
||||
Support device referencing by uuid or major/minor.
|
||||
Warn if kernel data didn't fit in buffer.
|
||||
Fix a printf.
|
||||
|
||||
Version 1.00.19 - 3 July 2004
|
||||
=============================
|
||||
More autoconf fixes.
|
||||
Fix a dmsetup newline.
|
||||
Fix device number handling for 2.6 kernels.
|
||||
|
||||
Version 1.00.18 - 20 Jun 2004
|
||||
=============================
|
||||
Fix a uuid free in libdm-iface.
|
||||
Fix a targets string size calc in driver.
|
||||
Add -c to dmsetup for column-based output.
|
||||
Add target message-passing ioctl.
|
||||
|
||||
Version 1.00.17 - 17 Apr 2004
|
||||
=============================
|
||||
configure --with-owner= --with-group= to avoid -o and -g args to 'install'
|
||||
Fix library selinux linking.
|
||||
|
||||
Version 1.00.16 - 16 Apr 2004
|
||||
=============================
|
||||
Ignore error setting selinux file context if fs doesn't support it.
|
||||
|
||||
Version 1.00.15 - 7 Apr 2004
|
||||
============================
|
||||
Fix status overflow check in kernel patches.
|
||||
|
||||
Version 1.00.14 - 6 Apr 2004
|
||||
============================
|
||||
Fix static selinux build.
|
||||
|
||||
Version 1.00.13 - 6 Apr 2004
|
||||
============================
|
||||
Add some basic selinux support.
|
||||
|
||||
Version 1.00.12 - 6 Apr 2004
|
||||
============================
|
||||
Fix dmsetup.static install.
|
||||
|
||||
Version 1.00.11 - 5 Apr 2004
|
||||
============================
|
||||
configure --enable-static_link does static build in addition to dynamic.
|
||||
Moved Makefile library targets definition into template.
|
||||
|
||||
Version 1.00.10 - 2 Apr 2004
|
||||
============================
|
||||
Fix DESTDIR handling.
|
||||
Static build installs to dmsetup.static.
|
||||
Basic support for internationalisation.
|
||||
Minor Makefile tidy-ups/fixes.
|
||||
|
||||
Version 1.00.09 - 31 Mar 2004
|
||||
=============================
|
||||
Update copyright notices to Red Hat.
|
||||
Move full mknodes functionality from dmsetup into libdevmapper.
|
||||
Avoid sscanf %as for uClibc compatibility.
|
||||
Cope if DM_LIST_VERSIONS is not defined.
|
||||
Add DM_LIST_VERSIONS functionality to kernel patches.
|
||||
Generate new kernel patches for 2.4.26-rc1.
|
||||
|
||||
Version 1.00.08 - 27 Feb 2004
|
||||
=============================
|
||||
Added 'dmsetup targets'.
|
||||
Added event_nr support to 'dmsetup wait'.
|
||||
Updated dmsetup man page.
|
||||
Allow logging function to be reset to use internal one.
|
||||
Bring log macros in line with LVM2 ones.
|
||||
Added 'make install_static_lib' which installs libdevmapper.a.
|
||||
Made configure/makefiles closer to LVM2 versions.
|
||||
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.
|
||||
|
||||
519
autoconf/config.guess
vendored
519
autoconf/config.guess
vendored
@@ -1,9 +1,9 @@
|
||||
#! /bin/sh
|
||||
# Attempt to guess a canonical system name.
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
|
||||
# Free Software Foundation, Inc.
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
||||
# 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
|
||||
|
||||
timestamp='2001-09-04'
|
||||
timestamp='2003-06-17'
|
||||
|
||||
# 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
|
||||
@@ -24,8 +24,9 @@ timestamp='2001-09-04'
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# Written by Per Bothner <bothner@cygnus.com>.
|
||||
# Please send patches to <config-patches@gnu.org>.
|
||||
# Originally written by Per Bothner <per@bothner.com>.
|
||||
# Please send patches to <config-patches@gnu.org>. Submit a context
|
||||
# diff and a properly formatted ChangeLog entry.
|
||||
#
|
||||
# This script attempts to guess a canonical system name similar to
|
||||
# config.sub. If it succeeds, it prints the system name on stdout, and
|
||||
@@ -87,30 +88,42 @@ if test $# != 0; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
trap 'exit 1' 1 2 15
|
||||
|
||||
dummy=dummy-$$
|
||||
trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15
|
||||
# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
|
||||
# compiler to aid in system detection is discouraged as it requires
|
||||
# temporary files to be created and, as you can see below, it is a
|
||||
# headache to deal with in a portable fashion.
|
||||
|
||||
# CC_FOR_BUILD -- compiler used by this script.
|
||||
# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
|
||||
# use `HOST_CC' if defined, but it is deprecated.
|
||||
|
||||
set_cc_for_build='case $CC_FOR_BUILD,$HOST_CC,$CC in
|
||||
,,) echo "int dummy(){}" > $dummy.c ;
|
||||
for c in cc gcc c89 ; do
|
||||
($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ;
|
||||
if test $? = 0 ; then
|
||||
# Portable tmp directory creation inspired by the Autoconf team.
|
||||
|
||||
set_cc_for_build='
|
||||
trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
|
||||
trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
|
||||
: ${TMPDIR=/tmp} ;
|
||||
{ tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
|
||||
{ test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
|
||||
{ tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
|
||||
{ echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
|
||||
dummy=$tmp/dummy ;
|
||||
tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
|
||||
case $CC_FOR_BUILD,$HOST_CC,$CC in
|
||||
,,) echo "int x;" > $dummy.c ;
|
||||
for c in cc gcc c89 c99 ; do
|
||||
if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
|
||||
CC_FOR_BUILD="$c"; break ;
|
||||
fi ;
|
||||
done ;
|
||||
rm -f $dummy.c $dummy.o $dummy.rel ;
|
||||
if test x"$CC_FOR_BUILD" = x ; then
|
||||
CC_FOR_BUILD=no_compiler_found ;
|
||||
fi
|
||||
;;
|
||||
,,*) CC_FOR_BUILD=$CC ;;
|
||||
,*,*) CC_FOR_BUILD=$HOST_CC ;;
|
||||
esac'
|
||||
esac ;'
|
||||
|
||||
# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
|
||||
# (ghazi@noc.rutgers.edu 1994-08-24)
|
||||
@@ -127,29 +140,30 @@ UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
|
||||
|
||||
case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
*:NetBSD:*:*)
|
||||
# Netbsd (nbsd) targets should (where applicable) match one or
|
||||
# NetBSD (nbsd) targets should (where applicable) match one or
|
||||
# more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
|
||||
# *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
|
||||
# switched to ELF, *-*-netbsd* would select the old
|
||||
# object file format. This provides both forward
|
||||
# compatibility and a consistent mechanism for selecting the
|
||||
# object file format.
|
||||
# Determine the machine/vendor (is the vendor relevant).
|
||||
case "${UNAME_MACHINE}" in
|
||||
amiga) machine=m68k-unknown ;;
|
||||
arm32) machine=arm-unknown ;;
|
||||
atari*) machine=m68k-atari ;;
|
||||
sun3*) machine=m68k-sun ;;
|
||||
mac68k) machine=m68k-apple ;;
|
||||
macppc) machine=powerpc-apple ;;
|
||||
hp3[0-9][05]) machine=m68k-hp ;;
|
||||
ibmrt|romp-ibm) machine=romp-ibm ;;
|
||||
*) machine=${UNAME_MACHINE}-unknown ;;
|
||||
#
|
||||
# Note: NetBSD doesn't particularly care about the vendor
|
||||
# portion of the name. We always set it to "unknown".
|
||||
sysctl="sysctl -n hw.machine_arch"
|
||||
UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
|
||||
/usr/sbin/$sysctl 2>/dev/null || echo unknown)`
|
||||
case "${UNAME_MACHINE_ARCH}" in
|
||||
armeb) machine=armeb-unknown ;;
|
||||
arm*) machine=arm-unknown ;;
|
||||
sh3el) machine=shl-unknown ;;
|
||||
sh3eb) machine=sh-unknown ;;
|
||||
*) machine=${UNAME_MACHINE_ARCH}-unknown ;;
|
||||
esac
|
||||
# The Operating System including object format, if it has switched
|
||||
# to ELF recently, or will in the future.
|
||||
case "${UNAME_MACHINE}" in
|
||||
i386|sparc|amiga|arm*|hp300|mvme68k|vax|atari|luna68k|mac68k|news68k|next68k|pc532|sun3*|x68k)
|
||||
case "${UNAME_MACHINE_ARCH}" in
|
||||
arm*|i386|m68k|ns32k|sh3*|sparc|vax)
|
||||
eval $set_cc_for_build
|
||||
if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
|
||||
| grep __ELF__ >/dev/null
|
||||
@@ -166,75 +180,112 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
;;
|
||||
esac
|
||||
# The OS release
|
||||
# Debian GNU/NetBSD machines have a different userland, and
|
||||
# thus, need a distinct triplet. However, they do not need
|
||||
# kernel version information, so it can be replaced with a
|
||||
# suitable tag, in the style of linux-gnu.
|
||||
case "${UNAME_VERSION}" in
|
||||
Debian*)
|
||||
release='-gnu'
|
||||
;;
|
||||
*)
|
||||
release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
|
||||
;;
|
||||
esac
|
||||
# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
|
||||
# contains redundant information, the shorter form:
|
||||
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
|
||||
echo "${machine}-${os}${release}"
|
||||
exit 0 ;;
|
||||
amiga:OpenBSD:*:*)
|
||||
echo m68k-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
arc:OpenBSD:*:*)
|
||||
echo mipsel-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
hp300:OpenBSD:*:*)
|
||||
echo m68k-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
mac68k:OpenBSD:*:*)
|
||||
echo m68k-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
macppc:OpenBSD:*:*)
|
||||
echo powerpc-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
mvme68k:OpenBSD:*:*)
|
||||
echo m68k-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
mvme88k:OpenBSD:*:*)
|
||||
echo m88k-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
mvmeppc:OpenBSD:*:*)
|
||||
echo powerpc-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
pmax:OpenBSD:*:*)
|
||||
echo mipsel-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
sgi:OpenBSD:*:*)
|
||||
echo mipseb-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
sun3:OpenBSD:*:*)
|
||||
echo m68k-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
wgrisc:OpenBSD:*:*)
|
||||
echo mipsel-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
*:OpenBSD:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
alpha:OSF1:*:*)
|
||||
if test $UNAME_RELEASE = "V4.0"; then
|
||||
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
|
||||
fi
|
||||
# According to Compaq, /usr/sbin/psrinfo has been available on
|
||||
# OSF/1 and Tru64 systems produced since 1995. I hope that
|
||||
# covers most systems running today. This code pipes the CPU
|
||||
# types through head -n 1, so we only detect the type of CPU 0.
|
||||
ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
|
||||
case "$ALPHA_CPU_TYPE" in
|
||||
"EV4 (21064)")
|
||||
UNAME_MACHINE="alpha" ;;
|
||||
"EV4.5 (21064)")
|
||||
UNAME_MACHINE="alpha" ;;
|
||||
"LCA4 (21066/21068)")
|
||||
UNAME_MACHINE="alpha" ;;
|
||||
"EV5 (21164)")
|
||||
UNAME_MACHINE="alphaev5" ;;
|
||||
"EV5.6 (21164A)")
|
||||
UNAME_MACHINE="alphaev56" ;;
|
||||
"EV5.6 (21164PC)")
|
||||
UNAME_MACHINE="alphapca56" ;;
|
||||
"EV5.7 (21164PC)")
|
||||
UNAME_MACHINE="alphapca57" ;;
|
||||
"EV6 (21264)")
|
||||
UNAME_MACHINE="alphaev6" ;;
|
||||
"EV6.7 (21264A)")
|
||||
UNAME_MACHINE="alphaev67" ;;
|
||||
"EV6.8CB (21264C)")
|
||||
UNAME_MACHINE="alphaev68" ;;
|
||||
"EV6.8AL (21264B)")
|
||||
UNAME_MACHINE="alphaev68" ;;
|
||||
"EV6.8CX (21264D)")
|
||||
UNAME_MACHINE="alphaev68" ;;
|
||||
"EV6.9A (21264/EV69A)")
|
||||
UNAME_MACHINE="alphaev69" ;;
|
||||
"EV7 (21364)")
|
||||
UNAME_MACHINE="alphaev7" ;;
|
||||
"EV7.9 (21364A)")
|
||||
UNAME_MACHINE="alphaev79" ;;
|
||||
esac
|
||||
# A Vn.n version is a released version.
|
||||
# A Tn.n version is a released field test version.
|
||||
# A Xn.n version is an unreleased experimental baselevel.
|
||||
# 1.2 uses "1.2" for uname -r.
|
||||
cat <<EOF >$dummy.s
|
||||
.data
|
||||
\$Lformat:
|
||||
.byte 37,100,45,37,120,10,0 # "%d-%x\n"
|
||||
|
||||
.text
|
||||
.globl main
|
||||
.align 4
|
||||
.ent main
|
||||
main:
|
||||
.frame \$30,16,\$26,0
|
||||
ldgp \$29,0(\$27)
|
||||
.prologue 1
|
||||
.long 0x47e03d80 # implver \$0
|
||||
lda \$2,-1
|
||||
.long 0x47e20c21 # amask \$2,\$1
|
||||
lda \$16,\$Lformat
|
||||
mov \$0,\$17
|
||||
not \$1,\$18
|
||||
jsr \$26,printf
|
||||
ldgp \$29,0(\$26)
|
||||
mov 0,\$16
|
||||
jsr \$26,exit
|
||||
.end main
|
||||
EOF
|
||||
eval $set_cc_for_build
|
||||
$CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null
|
||||
if test "$?" = 0 ; then
|
||||
case `./$dummy` in
|
||||
0-0)
|
||||
UNAME_MACHINE="alpha"
|
||||
;;
|
||||
1-0)
|
||||
UNAME_MACHINE="alphaev5"
|
||||
;;
|
||||
1-1)
|
||||
UNAME_MACHINE="alphaev56"
|
||||
;;
|
||||
1-101)
|
||||
UNAME_MACHINE="alphapca56"
|
||||
;;
|
||||
2-303)
|
||||
UNAME_MACHINE="alphaev6"
|
||||
;;
|
||||
2-307)
|
||||
UNAME_MACHINE="alphaev67"
|
||||
;;
|
||||
2-1307)
|
||||
UNAME_MACHINE="alphaev68"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
rm -f $dummy.s $dummy
|
||||
echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
|
||||
exit 0 ;;
|
||||
Alpha*:OpenVMS:*:*)
|
||||
echo alpha-hp-vms
|
||||
exit 0 ;;
|
||||
Alpha\ *:Windows_NT*:*)
|
||||
# How do we know it's Interix rather than the generic POSIX subsystem?
|
||||
# Should we change UNAME_MACHINE based on the output of uname instead
|
||||
@@ -247,29 +298,11 @@ EOF
|
||||
Amiga*:UNIX_System_V:4.0:*)
|
||||
echo m68k-unknown-sysv4
|
||||
exit 0;;
|
||||
amiga:OpenBSD:*:*)
|
||||
echo m68k-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
*:[Aa]miga[Oo][Ss]:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-amigaos
|
||||
exit 0 ;;
|
||||
arc64:OpenBSD:*:*)
|
||||
echo mips64el-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
arc:OpenBSD:*:*)
|
||||
echo mipsel-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
hkmips:OpenBSD:*:*)
|
||||
echo mips-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
pmax:OpenBSD:*:*)
|
||||
echo mipsel-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
sgi:OpenBSD:*:*)
|
||||
echo mips-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
wgrisc:OpenBSD:*:*)
|
||||
echo mipsel-unknown-openbsd${UNAME_RELEASE}
|
||||
*:[Mm]orph[Oo][Ss]:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-morphos
|
||||
exit 0 ;;
|
||||
*:OS/390:*:*)
|
||||
echo i370-ibm-openedition
|
||||
@@ -291,6 +324,13 @@ EOF
|
||||
NILE*:*:*:dcosx)
|
||||
echo pyramid-pyramid-svr4
|
||||
exit 0 ;;
|
||||
DRS?6000:unix:4.0:6*)
|
||||
echo sparc-icl-nx6
|
||||
exit 0 ;;
|
||||
DRS?6000:UNIX_SV:4.2*:7*)
|
||||
case `/usr/bin/uname -p` in
|
||||
sparc) echo sparc-icl-nx7 && exit 0 ;;
|
||||
esac ;;
|
||||
sun4H:SunOS:5.*:*)
|
||||
echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
|
||||
exit 0 ;;
|
||||
@@ -319,7 +359,7 @@ EOF
|
||||
echo m68k-sun-sunos${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
sun*:*:4.2BSD:*)
|
||||
UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
|
||||
UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
|
||||
test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
|
||||
case "`/bin/arch`" in
|
||||
sun3)
|
||||
@@ -333,12 +373,6 @@ EOF
|
||||
aushp:SunOS:*:*)
|
||||
echo sparc-auspex-sunos${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
sparc*:NetBSD:*)
|
||||
echo `uname -p`-unknown-netbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
atari*:OpenBSD:*:*)
|
||||
echo m68k-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
# The situation for MiNT is a little confusing. The machine name
|
||||
# can be virtually everything (everything which is not
|
||||
# "atarist" or "atariste" at least should have a processor
|
||||
@@ -365,18 +399,6 @@ EOF
|
||||
*:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
|
||||
echo m68k-unknown-mint${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
sun3*:OpenBSD:*:*)
|
||||
echo m68k-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
mac68k:OpenBSD:*:*)
|
||||
echo m68k-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
mvme68k:OpenBSD:*:*)
|
||||
echo m68k-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
mvme88k:OpenBSD:*:*)
|
||||
echo m88k-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
powerpc:machten:*:*)
|
||||
echo powerpc-apple-machten${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
@@ -415,15 +437,20 @@ EOF
|
||||
exit (-1);
|
||||
}
|
||||
EOF
|
||||
$CC_FOR_BUILD $dummy.c -o $dummy \
|
||||
&& ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
|
||||
&& rm -f $dummy.c $dummy && exit 0
|
||||
rm -f $dummy.c $dummy
|
||||
$CC_FOR_BUILD -o $dummy $dummy.c \
|
||||
&& $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
|
||||
&& exit 0
|
||||
echo mips-mips-riscos${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
Motorola:PowerMAX_OS:*:*)
|
||||
echo powerpc-motorola-powermax
|
||||
exit 0 ;;
|
||||
Motorola:*:4.3:PL8-*)
|
||||
echo powerpc-harris-powermax
|
||||
exit 0 ;;
|
||||
Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
|
||||
echo powerpc-harris-powermax
|
||||
exit 0 ;;
|
||||
Night_Hawk:Power_UNIX:*:*)
|
||||
echo powerpc-harris-powerunix
|
||||
exit 0 ;;
|
||||
@@ -496,8 +523,7 @@ EOF
|
||||
exit(0);
|
||||
}
|
||||
EOF
|
||||
$CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0
|
||||
rm -f $dummy.c $dummy
|
||||
$CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
|
||||
echo rs6000-ibm-aix3.2.5
|
||||
elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
|
||||
echo rs6000-ibm-aix3.2.4
|
||||
@@ -506,7 +532,7 @@ EOF
|
||||
fi
|
||||
exit 0 ;;
|
||||
*:AIX:*:[45])
|
||||
IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'`
|
||||
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
|
||||
else
|
||||
@@ -546,8 +572,6 @@ EOF
|
||||
9000/31? ) HP_ARCH=m68000 ;;
|
||||
9000/[34]?? ) HP_ARCH=m68k ;;
|
||||
9000/[678][0-9][0-9])
|
||||
case "${HPUX_REV}" in
|
||||
11.[0-9][0-9])
|
||||
if [ -x /usr/bin/getconf ]; then
|
||||
sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
|
||||
sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
|
||||
@@ -558,10 +582,10 @@ EOF
|
||||
case "${sc_kernel_bits}" in
|
||||
32) HP_ARCH="hppa2.0n" ;;
|
||||
64) HP_ARCH="hppa2.0w" ;;
|
||||
'') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
|
||||
esac ;;
|
||||
esac
|
||||
fi ;;
|
||||
esac
|
||||
fi
|
||||
if [ "${HP_ARCH}" = "" ]; then
|
||||
eval $set_cc_for_build
|
||||
sed 's/^ //' << EOF >$dummy.c
|
||||
@@ -597,11 +621,21 @@ EOF
|
||||
exit (0);
|
||||
}
|
||||
EOF
|
||||
(CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null ) && HP_ARCH=`./$dummy`
|
||||
if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi
|
||||
rm -f $dummy.c $dummy
|
||||
(CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
|
||||
test -z "$HP_ARCH" && HP_ARCH=hppa
|
||||
fi ;;
|
||||
esac
|
||||
if [ ${HP_ARCH} = "hppa2.0w" ]
|
||||
then
|
||||
# avoid double evaluation of $set_cc_for_build
|
||||
test -n "$CC_FOR_BUILD" || eval $set_cc_for_build
|
||||
if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null
|
||||
then
|
||||
HP_ARCH="hppa2.0w"
|
||||
else
|
||||
HP_ARCH="hppa64"
|
||||
fi
|
||||
fi
|
||||
echo ${HP_ARCH}-hp-hpux${HPUX_REV}
|
||||
exit 0 ;;
|
||||
ia64:HP-UX:*:*)
|
||||
@@ -635,8 +669,7 @@ EOF
|
||||
exit (0);
|
||||
}
|
||||
EOF
|
||||
$CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0
|
||||
rm -f $dummy.c $dummy
|
||||
$CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
|
||||
echo unknown-hitachi-hiuxwe2
|
||||
exit 0 ;;
|
||||
9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
|
||||
@@ -664,9 +697,6 @@ EOF
|
||||
parisc*:Lites*:*:*)
|
||||
echo hppa1.1-hp-lites
|
||||
exit 0 ;;
|
||||
hppa*:OpenBSD:*:*)
|
||||
echo hppa-unknown-openbsd
|
||||
exit 0 ;;
|
||||
C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
|
||||
echo c1-convex-bsd
|
||||
exit 0 ;;
|
||||
@@ -685,9 +715,6 @@ EOF
|
||||
C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
|
||||
echo c4-convex-bsd
|
||||
exit 0 ;;
|
||||
CRAY*X-MP:*:*:*)
|
||||
echo xmp-cray-unicos
|
||||
exit 0 ;;
|
||||
CRAY*Y-MP:*:*:*)
|
||||
echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
|
||||
exit 0 ;;
|
||||
@@ -700,17 +727,14 @@ EOF
|
||||
CRAY*TS:*:*:*)
|
||||
echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
|
||||
exit 0 ;;
|
||||
CRAY*T3D:*:*:*)
|
||||
echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
|
||||
exit 0 ;;
|
||||
CRAY*T3E:*:*:*)
|
||||
echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
|
||||
exit 0 ;;
|
||||
CRAY*SV1:*:*:*)
|
||||
echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
|
||||
exit 0 ;;
|
||||
CRAY-2:*:*:*)
|
||||
echo cray2-cray-unicos
|
||||
*:UNICOS/mp:*:*)
|
||||
echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
|
||||
exit 0 ;;
|
||||
F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
|
||||
FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
|
||||
@@ -718,9 +742,6 @@ EOF
|
||||
FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
|
||||
echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
|
||||
exit 0 ;;
|
||||
hp300:OpenBSD:*:*)
|
||||
echo m68k-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
|
||||
echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
@@ -730,11 +751,19 @@ EOF
|
||||
*:BSD/OS:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
*:FreeBSD:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
|
||||
exit 0 ;;
|
||||
*:OpenBSD:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
|
||||
*:FreeBSD:*:*|*:GNU/FreeBSD:*:*)
|
||||
# Determine whether the default compiler uses glibc.
|
||||
eval $set_cc_for_build
|
||||
sed 's/^ //' << EOF >$dummy.c
|
||||
#include <features.h>
|
||||
#if __GLIBC__ >= 2
|
||||
LIBC=gnu
|
||||
#else
|
||||
LIBC=
|
||||
#endif
|
||||
EOF
|
||||
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
|
||||
echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC}
|
||||
exit 0 ;;
|
||||
i*:CYGWIN*:*)
|
||||
echo ${UNAME_MACHINE}-pc-cygwin
|
||||
@@ -745,11 +774,17 @@ EOF
|
||||
i*:PW*:*)
|
||||
echo ${UNAME_MACHINE}-pc-pw32
|
||||
exit 0 ;;
|
||||
x86:Interix*:[34]*)
|
||||
echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//'
|
||||
exit 0 ;;
|
||||
[345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
|
||||
echo i${UNAME_MACHINE}-pc-mks
|
||||
exit 0 ;;
|
||||
i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
|
||||
# How do we know it's Interix rather than the generic POSIX subsystem?
|
||||
# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
|
||||
# UNAME_MACHINE based on the output of uname instead of i386?
|
||||
echo i386-pc-interix
|
||||
echo i586-pc-interix
|
||||
exit 0 ;;
|
||||
i*:UWIN*:*)
|
||||
echo ${UNAME_MACHINE}-pc-uwin
|
||||
@@ -769,17 +804,52 @@ EOF
|
||||
arm*:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
exit 0 ;;
|
||||
cris:Linux:*:*)
|
||||
echo cris-axis-linux-gnu
|
||||
exit 0 ;;
|
||||
ia64:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
exit 0 ;;
|
||||
m68*:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
exit 0 ;;
|
||||
mips:Linux:*:*)
|
||||
case `sed -n '/^byte/s/^.*: \(.*\) endian/\1/p' < /proc/cpuinfo` in
|
||||
big) echo mips-unknown-linux-gnu && exit 0 ;;
|
||||
little) echo mipsel-unknown-linux-gnu && exit 0 ;;
|
||||
esac
|
||||
eval $set_cc_for_build
|
||||
sed 's/^ //' << EOF >$dummy.c
|
||||
#undef CPU
|
||||
#undef mips
|
||||
#undef mipsel
|
||||
#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
|
||||
CPU=mipsel
|
||||
#else
|
||||
#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
|
||||
CPU=mips
|
||||
#else
|
||||
CPU=
|
||||
#endif
|
||||
#endif
|
||||
EOF
|
||||
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
|
||||
test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
|
||||
;;
|
||||
mips64:Linux:*:*)
|
||||
eval $set_cc_for_build
|
||||
sed 's/^ //' << EOF >$dummy.c
|
||||
#undef CPU
|
||||
#undef mips64
|
||||
#undef mips64el
|
||||
#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
|
||||
CPU=mips64el
|
||||
#else
|
||||
#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
|
||||
CPU=mips64
|
||||
#else
|
||||
CPU=
|
||||
#endif
|
||||
#endif
|
||||
EOF
|
||||
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
|
||||
test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
|
||||
;;
|
||||
ppc:Linux:*:*)
|
||||
echo powerpc-unknown-linux-gnu
|
||||
@@ -815,6 +885,9 @@ EOF
|
||||
s390:Linux:*:* | s390x:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-ibm-linux
|
||||
exit 0 ;;
|
||||
sh64*:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
exit 0 ;;
|
||||
sh*:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
exit 0 ;;
|
||||
@@ -828,7 +901,8 @@ EOF
|
||||
# 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
|
||||
# problems with other programs or directories called `ld' in the path.
|
||||
ld_supported_targets=`cd /; ld --help 2>&1 \
|
||||
# Set LC_ALL=C to ensure ld outputs messages in English.
|
||||
ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
|
||||
| sed -ne '/supported targets:/!d
|
||||
s/[ ][ ]*/ /g
|
||||
s/.*supported targets: *//
|
||||
@@ -852,32 +926,28 @@ EOF
|
||||
esac
|
||||
# Determine whether the default compiler is a.out or elf
|
||||
eval $set_cc_for_build
|
||||
cat >$dummy.c <<EOF
|
||||
#include <features.h>
|
||||
#ifdef __cplusplus
|
||||
#include <stdio.h> /* for printf() prototype */
|
||||
int main (int argc, char *argv[]) {
|
||||
#else
|
||||
int main (argc, argv) int argc; char *argv[]; {
|
||||
#endif
|
||||
#ifdef __ELF__
|
||||
# ifdef __GLIBC__
|
||||
# if __GLIBC__ >= 2
|
||||
printf ("%s-pc-linux-gnu\n", argv[1]);
|
||||
# else
|
||||
printf ("%s-pc-linux-gnulibc1\n", argv[1]);
|
||||
# endif
|
||||
# else
|
||||
printf ("%s-pc-linux-gnulibc1\n", argv[1]);
|
||||
# endif
|
||||
#else
|
||||
printf ("%s-pc-linux-gnuaout\n", argv[1]);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
sed 's/^ //' << EOF >$dummy.c
|
||||
#include <features.h>
|
||||
#ifdef __ELF__
|
||||
# ifdef __GLIBC__
|
||||
# if __GLIBC__ >= 2
|
||||
LIBC=gnu
|
||||
# else
|
||||
LIBC=gnulibc1
|
||||
# endif
|
||||
# else
|
||||
LIBC=gnulibc1
|
||||
# endif
|
||||
#else
|
||||
#ifdef __INTEL_COMPILER
|
||||
LIBC=gnu
|
||||
#else
|
||||
LIBC=gnuaout
|
||||
#endif
|
||||
#endif
|
||||
EOF
|
||||
$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm -f $dummy.c $dummy && exit 0
|
||||
rm -f $dummy.c $dummy
|
||||
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
|
||||
test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0
|
||||
test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
|
||||
;;
|
||||
i*86:DYNIX/ptx:4*:*)
|
||||
@@ -894,6 +964,23 @@ EOF
|
||||
# Use sysv4.2uw... so that sysv4* matches it.
|
||||
echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
|
||||
exit 0 ;;
|
||||
i*86:OS/2:*:*)
|
||||
# If we were able to find `uname', then EMX Unix compatibility
|
||||
# is probably installed.
|
||||
echo ${UNAME_MACHINE}-pc-os2-emx
|
||||
exit 0 ;;
|
||||
i*86:XTS-300:*:STOP)
|
||||
echo ${UNAME_MACHINE}-unknown-stop
|
||||
exit 0 ;;
|
||||
i*86:atheos:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-atheos
|
||||
exit 0 ;;
|
||||
i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
|
||||
echo i386-unknown-lynxos${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
i*86:*DOS:*:*)
|
||||
echo ${UNAME_MACHINE}-pc-msdosdjgpp
|
||||
exit 0 ;;
|
||||
i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
|
||||
UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
|
||||
if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
|
||||
@@ -915,22 +1002,19 @@ EOF
|
||||
UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
|
||||
echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
|
||||
elif /bin/uname -X 2>/dev/null >/dev/null ; then
|
||||
UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
|
||||
(/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
|
||||
(/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
|
||||
UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
|
||||
(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
|
||||
(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
|
||||
&& UNAME_MACHINE=i586
|
||||
(/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \
|
||||
(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
|
||||
&& UNAME_MACHINE=i686
|
||||
(/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \
|
||||
(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
|
||||
&& UNAME_MACHINE=i686
|
||||
echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
|
||||
else
|
||||
echo ${UNAME_MACHINE}-pc-sysv32
|
||||
fi
|
||||
exit 0 ;;
|
||||
i*86:*DOS:*:*)
|
||||
echo ${UNAME_MACHINE}-pc-msdosdjgpp
|
||||
exit 0 ;;
|
||||
pc:*:*:*)
|
||||
# Left here for compatibility:
|
||||
# uname -m prints for DJGPP always 'pc', but it prints nothing about
|
||||
@@ -954,9 +1038,15 @@ EOF
|
||||
# "miniframe"
|
||||
echo m68010-convergent-sysv
|
||||
exit 0 ;;
|
||||
mc68k:UNIX:SYSTEM5:3.51m)
|
||||
echo m68k-convergent-sysv
|
||||
exit 0 ;;
|
||||
M680?0:D-NIX:5.3:*)
|
||||
echo m68k-diab-dnix
|
||||
exit 0 ;;
|
||||
M68*:*:R3V[567]*:*)
|
||||
test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
|
||||
3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0)
|
||||
3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0)
|
||||
OS_REL=''
|
||||
test -r /etc/.relid \
|
||||
&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
|
||||
@@ -973,9 +1063,6 @@ EOF
|
||||
mc68030:UNIX_System_V:4.*:*)
|
||||
echo m68k-atari-sysv4
|
||||
exit 0 ;;
|
||||
i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
|
||||
echo i386-unknown-lynxos${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
TSUNAMI:LynxOS:2.*:*)
|
||||
echo sparc-unknown-lynxos${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
@@ -1047,6 +1134,9 @@ EOF
|
||||
SX-5:SUPER-UX:*:*)
|
||||
echo sx5-nec-superux${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
SX-6:SUPER-UX:*:*)
|
||||
echo sx6-nec-superux${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
Power*:Rhapsody:*:*)
|
||||
echo powerpc-apple-rhapsody${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
@@ -1054,18 +1144,24 @@ EOF
|
||||
echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
*:Darwin:*:*)
|
||||
echo `uname -p`-apple-darwin${UNAME_RELEASE}
|
||||
case `uname -p` in
|
||||
*86) UNAME_PROCESSOR=i686 ;;
|
||||
powerpc) UNAME_PROCESSOR=powerpc ;;
|
||||
esac
|
||||
echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
*:procnto*:*:* | *:QNX:[0123456789]*:*)
|
||||
if test "${UNAME_MACHINE}" = "x86pc"; then
|
||||
UNAME_PROCESSOR=`uname -p`
|
||||
if test "$UNAME_PROCESSOR" = "x86"; then
|
||||
UNAME_PROCESSOR=i386
|
||||
UNAME_MACHINE=pc
|
||||
fi
|
||||
echo `uname -p`-${UNAME_MACHINE}-nto-qnx
|
||||
echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
*:QNX:*:4*)
|
||||
echo i386-pc-qnx
|
||||
exit 0 ;;
|
||||
NSR-[KW]:NONSTOP_KERNEL:*:*)
|
||||
NSR-[DGKLNPTVW]:NONSTOP_KERNEL:*:*)
|
||||
echo nsr-tandem-nsk${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
*:NonStop-UX:*:*)
|
||||
@@ -1088,11 +1184,6 @@ EOF
|
||||
fi
|
||||
echo ${UNAME_MACHINE}-unknown-plan9
|
||||
exit 0 ;;
|
||||
i*86:OS/2:*:*)
|
||||
# If we were able to find `uname', then EMX Unix compatibility
|
||||
# is probably installed.
|
||||
echo ${UNAME_MACHINE}-pc-os2-emx
|
||||
exit 0 ;;
|
||||
*:TOPS-10:*:*)
|
||||
echo pdp10-unknown-tops10
|
||||
exit 0 ;;
|
||||
@@ -1111,11 +1202,8 @@ EOF
|
||||
*:ITS:*:*)
|
||||
echo pdp10-unknown-its
|
||||
exit 0 ;;
|
||||
i*86:XTS-300:*:STOP)
|
||||
echo ${UNAME_MACHINE}-unknown-stop
|
||||
exit 0 ;;
|
||||
i*86:atheos:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-atheos
|
||||
SEI:*:*:SEIUX)
|
||||
echo mips-sei-seiux${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
esac
|
||||
|
||||
@@ -1237,8 +1325,7 @@ main ()
|
||||
}
|
||||
EOF
|
||||
|
||||
$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $dummy.c $dummy && exit 0
|
||||
rm -f $dummy.c $dummy
|
||||
$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0
|
||||
|
||||
# Apollos put the system type in the environment.
|
||||
|
||||
|
||||
269
autoconf/config.sub
vendored
269
autoconf/config.sub
vendored
@@ -1,9 +1,9 @@
|
||||
#! /bin/sh
|
||||
# Configuration validation subroutine script.
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
|
||||
# Free Software Foundation, Inc.
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
||||
# 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
|
||||
|
||||
timestamp='2001-09-07'
|
||||
timestamp='2003-06-17'
|
||||
|
||||
# This file is (in principle) common to ALL GNU software.
|
||||
# The presence of a machine in this file suggests that SOME GNU software
|
||||
@@ -29,7 +29,8 @@ timestamp='2001-09-07'
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# Please send patches to <config-patches@gnu.org>.
|
||||
# Please send patches to <config-patches@gnu.org>. Submit a context
|
||||
# diff and a properly formatted ChangeLog entry.
|
||||
#
|
||||
# Configuration subroutine to validate and canonicalize a configuration type.
|
||||
# Supply the specified configuration type as an argument.
|
||||
@@ -117,7 +118,7 @@ esac
|
||||
# Here we must recognize all the valid KERNEL-OS combinations.
|
||||
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
|
||||
case $maybe_os in
|
||||
nto-qnx* | linux-gnu* | storm-chaos* | os2-emx* | windows32-*)
|
||||
nto-qnx* | linux-gnu* | freebsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
|
||||
os=-$maybe_os
|
||||
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
|
||||
;;
|
||||
@@ -226,32 +227,44 @@ case $basic_machine in
|
||||
1750a | 580 \
|
||||
| a29k \
|
||||
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
|
||||
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
|
||||
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
|
||||
| c4x | clipper \
|
||||
| d10v | d30v | dsp16xx \
|
||||
| fr30 \
|
||||
| d10v | d30v | dlx | dsp16xx \
|
||||
| fr30 | frv \
|
||||
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
|
||||
| i370 | i860 | i960 | ia64 \
|
||||
| ip2k \
|
||||
| m32r | m68000 | m68k | m88k | mcore \
|
||||
| mips16 | mips64 | mips64el | mips64orion | mips64orionel \
|
||||
| mips64vr4100 | mips64vr4100el | mips64vr4300 \
|
||||
| mips64vr4300el | mips64vr5000 | mips64vr5000el \
|
||||
| mipsbe | mipseb | mipsel | mipsle | mipstx39 | mipstx39el \
|
||||
| mipsisa32 \
|
||||
| mips | mipsbe | mipseb | mipsel | mipsle \
|
||||
| mips16 \
|
||||
| mips64 | mips64el \
|
||||
| mips64vr | mips64vrel \
|
||||
| mips64orion | mips64orionel \
|
||||
| mips64vr4100 | mips64vr4100el \
|
||||
| mips64vr4300 | mips64vr4300el \
|
||||
| mips64vr5000 | mips64vr5000el \
|
||||
| mipsisa32 | mipsisa32el \
|
||||
| mipsisa32r2 | mipsisa32r2el \
|
||||
| mipsisa64 | mipsisa64el \
|
||||
| mipsisa64sb1 | mipsisa64sb1el \
|
||||
| mipsisa64sr71k | mipsisa64sr71kel \
|
||||
| mipstx39 | mipstx39el \
|
||||
| mn10200 | mn10300 \
|
||||
| msp430 \
|
||||
| ns16k | ns32k \
|
||||
| openrisc \
|
||||
| openrisc | or32 \
|
||||
| pdp10 | pdp11 | pj | pjl \
|
||||
| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
|
||||
| pyramid \
|
||||
| s390 | s390x \
|
||||
| sh | sh[34] | sh[34]eb | shbe | shle \
|
||||
| sparc | sparc64 | sparclet | sparclite | sparcv9 | sparcv9b \
|
||||
| stormy16 | strongarm \
|
||||
| tahoe | thumb | tic80 | tron \
|
||||
| v850 \
|
||||
| sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
|
||||
| sh64 | sh64le \
|
||||
| sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \
|
||||
| strongarm \
|
||||
| tahoe | thumb | tic4x | tic80 | tron \
|
||||
| v850 | v850e \
|
||||
| we32k \
|
||||
| x86 | xscale \
|
||||
| x86 | xscale | xstormy16 | xtensa \
|
||||
| z8k)
|
||||
basic_machine=$basic_machine-unknown
|
||||
;;
|
||||
@@ -278,38 +291,55 @@ case $basic_machine in
|
||||
580-* \
|
||||
| a29k-* \
|
||||
| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
|
||||
| alphapca5[67]-* | arc-* \
|
||||
| arm-* | armbe-* | armle-* | armv*-* \
|
||||
| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
|
||||
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
|
||||
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
|
||||
| avr-* \
|
||||
| bs2000-* \
|
||||
| c[123]* | c30-* | [cjt]90-* | c54x-* \
|
||||
| clipper-* | cray2-* | cydra-* \
|
||||
| d10v-* | d30v-* \
|
||||
| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
|
||||
| clipper-* | cydra-* \
|
||||
| d10v-* | d30v-* | dlx-* \
|
||||
| elxsi-* \
|
||||
| f30[01]-* | f700-* | fr30-* | fx80-* \
|
||||
| f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
|
||||
| h8300-* | h8500-* \
|
||||
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
|
||||
| i*86-* | i860-* | i960-* | ia64-* \
|
||||
| ip2k-* \
|
||||
| m32r-* \
|
||||
| m68000-* | m680[01234]0-* | m68360-* | m683?2-* | m68k-* \
|
||||
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
|
||||
| m88110-* | m88k-* | mcore-* \
|
||||
| mips-* | mips16-* | mips64-* | mips64el-* | mips64orion-* \
|
||||
| mips64orionel-* | mips64vr4100-* | mips64vr4100el-* \
|
||||
| mips64vr4300-* | mips64vr4300el-* | mipsbe-* | mipseb-* \
|
||||
| mipsle-* | mipsel-* | mipstx39-* | mipstx39el-* \
|
||||
| none-* | np1-* | ns16k-* | ns32k-* \
|
||||
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
|
||||
| mips16-* \
|
||||
| mips64-* | mips64el-* \
|
||||
| mips64vr-* | mips64vrel-* \
|
||||
| mips64orion-* | mips64orionel-* \
|
||||
| mips64vr4100-* | mips64vr4100el-* \
|
||||
| mips64vr4300-* | mips64vr4300el-* \
|
||||
| mips64vr5000-* | mips64vr5000el-* \
|
||||
| mipsisa32-* | mipsisa32el-* \
|
||||
| mipsisa32r2-* | mipsisa32r2el-* \
|
||||
| mipsisa64-* | mipsisa64el-* \
|
||||
| mipsisa64sb1-* | mipsisa64sb1el-* \
|
||||
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
|
||||
| mipstx39-* | mipstx39el-* \
|
||||
| msp430-* \
|
||||
| none-* | np1-* | nv1-* | ns16k-* | ns32k-* \
|
||||
| orion-* \
|
||||
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
|
||||
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
|
||||
| pyramid-* \
|
||||
| romp-* | rs6000-* \
|
||||
| s390-* | s390x-* \
|
||||
| sh-* | sh[34]-* | sh[34]eb-* | shbe-* | shle-* \
|
||||
| sparc-* | sparc64-* | sparc86x-* | sparclite-* \
|
||||
| sparcv9-* | sparcv9b-* | stormy16-* | strongarm-* | sv1-* \
|
||||
| t3e-* | tahoe-* | thumb-* | tic30-* | tic54x-* | tic80-* | tron-* \
|
||||
| v850-* | vax-* \
|
||||
| sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \
|
||||
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
|
||||
| sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
|
||||
| sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
|
||||
| tahoe-* | thumb-* \
|
||||
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
|
||||
| tron-* \
|
||||
| v850-* | v850e-* | vax-* \
|
||||
| we32k-* \
|
||||
| x86-* | x86_64-* | xmp-* | xps100-* | xscale-* \
|
||||
| x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
|
||||
| xtensa-* \
|
||||
| ymp-* \
|
||||
| z8k-*)
|
||||
;;
|
||||
@@ -343,6 +373,9 @@ case $basic_machine in
|
||||
basic_machine=a29k-none
|
||||
os=-bsd
|
||||
;;
|
||||
amd64)
|
||||
basic_machine=x86_64-pc
|
||||
;;
|
||||
amdahl)
|
||||
basic_machine=580-amdahl
|
||||
os=-sysv
|
||||
@@ -374,6 +407,10 @@ case $basic_machine in
|
||||
basic_machine=ns32k-sequent
|
||||
os=-dynix
|
||||
;;
|
||||
c90)
|
||||
basic_machine=c90-cray
|
||||
os=-unicos
|
||||
;;
|
||||
convex-c1)
|
||||
basic_machine=c1-convex
|
||||
os=-bsd
|
||||
@@ -394,16 +431,8 @@ case $basic_machine in
|
||||
basic_machine=c38-convex
|
||||
os=-bsd
|
||||
;;
|
||||
cray | ymp)
|
||||
basic_machine=ymp-cray
|
||||
os=-unicos
|
||||
;;
|
||||
cray2)
|
||||
basic_machine=cray2-cray
|
||||
os=-unicos
|
||||
;;
|
||||
[cjt]90)
|
||||
basic_machine=${basic_machine}-cray
|
||||
cray | j90)
|
||||
basic_machine=j90-cray
|
||||
os=-unicos
|
||||
;;
|
||||
crds | unos)
|
||||
@@ -418,6 +447,14 @@ case $basic_machine in
|
||||
decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
|
||||
basic_machine=mips-dec
|
||||
;;
|
||||
decsystem10* | dec10*)
|
||||
basic_machine=pdp10-dec
|
||||
os=-tops10
|
||||
;;
|
||||
decsystem20* | dec20*)
|
||||
basic_machine=pdp10-dec
|
||||
os=-tops20
|
||||
;;
|
||||
delta | 3300 | motorola-3300 | motorola-delta \
|
||||
| 3300-motorola | delta-motorola)
|
||||
basic_machine=m68k-motorola
|
||||
@@ -598,14 +635,6 @@ case $basic_machine in
|
||||
basic_machine=m68k-atari
|
||||
os=-mint
|
||||
;;
|
||||
mipsel*-linux*)
|
||||
basic_machine=mipsel-unknown
|
||||
os=-linux-gnu
|
||||
;;
|
||||
mips*-linux*)
|
||||
basic_machine=mips-unknown
|
||||
os=-linux-gnu
|
||||
;;
|
||||
mips3*-*)
|
||||
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
|
||||
;;
|
||||
@@ -620,6 +649,10 @@ case $basic_machine in
|
||||
basic_machine=m68k-rom68k
|
||||
os=-coff
|
||||
;;
|
||||
morphos)
|
||||
basic_machine=powerpc-unknown
|
||||
os=-morphos
|
||||
;;
|
||||
msdos)
|
||||
basic_machine=i386-pc
|
||||
os=-msdos
|
||||
@@ -692,6 +725,10 @@ case $basic_machine in
|
||||
np1)
|
||||
basic_machine=np1-gould
|
||||
;;
|
||||
nv1)
|
||||
basic_machine=nv1-cray
|
||||
os=-unicosmp
|
||||
;;
|
||||
nsr-tandem)
|
||||
basic_machine=nsr-tandem
|
||||
;;
|
||||
@@ -699,6 +736,10 @@ case $basic_machine in
|
||||
basic_machine=hppa1.1-oki
|
||||
os=-proelf
|
||||
;;
|
||||
or32 | or32-*)
|
||||
basic_machine=or32-unknown
|
||||
os=-coff
|
||||
;;
|
||||
OSE68000 | ose68000)
|
||||
basic_machine=m68000-ericsson
|
||||
os=-ose
|
||||
@@ -724,24 +765,30 @@ case $basic_machine in
|
||||
pc532 | pc532-*)
|
||||
basic_machine=ns32k-pc532
|
||||
;;
|
||||
pentium | p5 | k5 | k6 | nexgen)
|
||||
pentium | p5 | k5 | k6 | nexgen | viac3)
|
||||
basic_machine=i586-pc
|
||||
;;
|
||||
pentiumpro | p6 | 6x86 | athlon)
|
||||
pentiumpro | p6 | 6x86 | athlon | athlon_*)
|
||||
basic_machine=i686-pc
|
||||
;;
|
||||
pentiumii | pentium2)
|
||||
pentiumii | pentium2 | pentiumiii | pentium3)
|
||||
basic_machine=i686-pc
|
||||
;;
|
||||
pentium-* | p5-* | k5-* | k6-* | nexgen-*)
|
||||
pentium4)
|
||||
basic_machine=i786-pc
|
||||
;;
|
||||
pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
|
||||
basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
pentiumpro-* | p6-* | 6x86-* | athlon-*)
|
||||
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
pentiumii-* | pentium2-*)
|
||||
pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
|
||||
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
pentium4-*)
|
||||
basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
pn)
|
||||
basic_machine=pn-gould
|
||||
;;
|
||||
@@ -784,10 +831,26 @@ case $basic_machine in
|
||||
rtpc | rtpc-*)
|
||||
basic_machine=romp-ibm
|
||||
;;
|
||||
s390 | s390-*)
|
||||
basic_machine=s390-ibm
|
||||
;;
|
||||
s390x | s390x-*)
|
||||
basic_machine=s390x-ibm
|
||||
;;
|
||||
sa29200)
|
||||
basic_machine=a29k-amd
|
||||
os=-udi
|
||||
;;
|
||||
sb1)
|
||||
basic_machine=mipsisa64sb1-unknown
|
||||
;;
|
||||
sb1el)
|
||||
basic_machine=mipsisa64sb1el-unknown
|
||||
;;
|
||||
sei)
|
||||
basic_machine=mips-sei
|
||||
os=-seiux
|
||||
;;
|
||||
sequent)
|
||||
basic_machine=i386-sequent
|
||||
;;
|
||||
@@ -795,7 +858,10 @@ case $basic_machine in
|
||||
basic_machine=sh-hitachi
|
||||
os=-hms
|
||||
;;
|
||||
sparclite-wrs)
|
||||
sh64)
|
||||
basic_machine=sh64-unknown
|
||||
;;
|
||||
sparclite-wrs | simso-wrs)
|
||||
basic_machine=sparclite-wrs
|
||||
os=-vxworks
|
||||
;;
|
||||
@@ -862,19 +928,35 @@ case $basic_machine in
|
||||
os=-dynix
|
||||
;;
|
||||
t3e)
|
||||
basic_machine=t3e-cray
|
||||
basic_machine=alphaev5-cray
|
||||
os=-unicos
|
||||
;;
|
||||
t90)
|
||||
basic_machine=t90-cray
|
||||
os=-unicos
|
||||
;;
|
||||
tic54x | c54x*)
|
||||
basic_machine=tic54x-unknown
|
||||
os=-coff
|
||||
;;
|
||||
tic55x | c55x*)
|
||||
basic_machine=tic55x-unknown
|
||||
os=-coff
|
||||
;;
|
||||
tic6x | c6x*)
|
||||
basic_machine=tic6x-unknown
|
||||
os=-coff
|
||||
;;
|
||||
tx39)
|
||||
basic_machine=mipstx39-unknown
|
||||
;;
|
||||
tx39el)
|
||||
basic_machine=mipstx39el-unknown
|
||||
;;
|
||||
toad1)
|
||||
basic_machine=pdp10-xkl
|
||||
os=-tops20
|
||||
;;
|
||||
tower | tower-32)
|
||||
basic_machine=m68k-ncr
|
||||
;;
|
||||
@@ -921,17 +1003,13 @@ case $basic_machine in
|
||||
basic_machine=hppa1.1-winbond
|
||||
os=-proelf
|
||||
;;
|
||||
windows32)
|
||||
basic_machine=i386-pc
|
||||
os=-windows32-msvcrt
|
||||
;;
|
||||
xmp)
|
||||
basic_machine=xmp-cray
|
||||
os=-unicos
|
||||
;;
|
||||
xps | xps100)
|
||||
basic_machine=xps100-honeywell
|
||||
;;
|
||||
ymp)
|
||||
basic_machine=ymp-cray
|
||||
os=-unicos
|
||||
;;
|
||||
z8k-*-coff)
|
||||
basic_machine=z8k-unknown
|
||||
os=-sim
|
||||
@@ -952,13 +1030,6 @@ case $basic_machine in
|
||||
op60c)
|
||||
basic_machine=hppa1.1-oki
|
||||
;;
|
||||
mips)
|
||||
if [ x$os = x-linux-gnu ]; then
|
||||
basic_machine=mips-unknown
|
||||
else
|
||||
basic_machine=mips-mips
|
||||
fi
|
||||
;;
|
||||
romp)
|
||||
basic_machine=romp-ibm
|
||||
;;
|
||||
@@ -978,9 +1049,12 @@ case $basic_machine in
|
||||
we32k)
|
||||
basic_machine=we32k-att
|
||||
;;
|
||||
sh3 | sh4 | sh3eb | sh4eb)
|
||||
sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele)
|
||||
basic_machine=sh-unknown
|
||||
;;
|
||||
sh64)
|
||||
basic_machine=sh64-unknown
|
||||
;;
|
||||
sparc | sparcv9 | sparcv9b)
|
||||
basic_machine=sparc-sun
|
||||
;;
|
||||
@@ -999,10 +1073,6 @@ case $basic_machine in
|
||||
pmac | pmac-mpw)
|
||||
basic_machine=powerpc-apple
|
||||
;;
|
||||
c4x*)
|
||||
basic_machine=c4x-none
|
||||
os=-coff
|
||||
;;
|
||||
*-unknown)
|
||||
# Make sure to match an already-canonicalized machine name.
|
||||
;;
|
||||
@@ -1065,10 +1135,12 @@ case $os in
|
||||
| -chorusos* | -chorusrdb* \
|
||||
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
|
||||
| -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
|
||||
| -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \
|
||||
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
|
||||
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
|
||||
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
|
||||
| -os2* | -vos*)
|
||||
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
|
||||
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
|
||||
| -powermax* | -dnix* | -nx6 | -nx7 | -sei*)
|
||||
# Remember, each alternative MUST END IN *, to match a version number.
|
||||
;;
|
||||
-qnx*)
|
||||
@@ -1080,8 +1152,10 @@ case $os in
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
-nto-qnx*)
|
||||
;;
|
||||
-nto*)
|
||||
os=-nto-qnx
|
||||
os=`echo $os | sed -e 's|nto|nto-qnx|'`
|
||||
;;
|
||||
-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
|
||||
| -windows* | -osx | -abug | -netware* | -os9* | -beos* \
|
||||
@@ -1120,12 +1194,18 @@ case $os in
|
||||
-acis*)
|
||||
os=-aos
|
||||
;;
|
||||
-atheos*)
|
||||
os=-atheos
|
||||
;;
|
||||
-386bsd)
|
||||
os=-bsd
|
||||
;;
|
||||
-ctix* | -uts*)
|
||||
os=-sysv
|
||||
;;
|
||||
-nova*)
|
||||
os=-rtmk-nova
|
||||
;;
|
||||
-ns2 )
|
||||
os=-nextstep2
|
||||
;;
|
||||
@@ -1169,6 +1249,12 @@ case $os in
|
||||
-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
|
||||
os=-mint
|
||||
;;
|
||||
-aros*)
|
||||
os=-aros
|
||||
;;
|
||||
-kaos*)
|
||||
os=-kaos
|
||||
;;
|
||||
-none)
|
||||
;;
|
||||
*)
|
||||
@@ -1200,6 +1286,10 @@ case $basic_machine in
|
||||
arm*-semi)
|
||||
os=-aout
|
||||
;;
|
||||
c4x-* | tic4x-*)
|
||||
os=-coff
|
||||
;;
|
||||
# This must come before the *-dec entry.
|
||||
pdp10-*)
|
||||
os=-tops20
|
||||
;;
|
||||
@@ -1230,6 +1320,9 @@ case $basic_machine in
|
||||
mips*-*)
|
||||
os=-elf
|
||||
;;
|
||||
or32-*)
|
||||
os=-coff
|
||||
;;
|
||||
*-tti) # must be before sparc entry or we get the wrong os.
|
||||
os=-sysv3
|
||||
;;
|
||||
@@ -1377,7 +1470,7 @@ case $basic_machine in
|
||||
-ptx*)
|
||||
vendor=sequent
|
||||
;;
|
||||
-vxsim* | -vxworks*)
|
||||
-vxsim* | -vxworks* | -windiss*)
|
||||
vendor=wrs
|
||||
;;
|
||||
-aux*)
|
||||
|
||||
@@ -1,19 +1,38 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# install - install a program, script, or datafile
|
||||
# This comes from X11R5 (mit/util/scripts/install.sh).
|
||||
|
||||
scriptversion=2003-06-13.21
|
||||
|
||||
# This originates from X11R5 (mit/util/scripts/install.sh), which was
|
||||
# later released in X11R6 (xc/config/util/install.sh) with the
|
||||
# following copyright and license.
|
||||
#
|
||||
# Copyright 1991 by the Massachusetts Institute of Technology
|
||||
# Copyright (C) 1994 X Consortium
|
||||
#
|
||||
# Permission to use, copy, modify, distribute, and sell this software and its
|
||||
# documentation for any purpose is hereby granted without fee, provided that
|
||||
# the above copyright notice appear in all copies and that both that
|
||||
# copyright notice and this permission notice appear in supporting
|
||||
# documentation, and that the name of M.I.T. not be used in advertising or
|
||||
# publicity pertaining to distribution of the software without specific,
|
||||
# written prior permission. M.I.T. makes no representations about the
|
||||
# suitability of this software for any purpose. It is provided "as is"
|
||||
# without express or implied warranty.
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to
|
||||
# deal in the Software without restriction, including without limitation the
|
||||
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
# sell copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
|
||||
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# Except as contained in this notice, the name of the X Consortium shall not
|
||||
# be used in advertising or otherwise to promote the sale, use or other deal-
|
||||
# ings in this Software without prior written authorization from the X Consor-
|
||||
# tium.
|
||||
#
|
||||
#
|
||||
# FSF changes to this file are in the public domain.
|
||||
#
|
||||
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||
# `make' implicit rules from creating a file called install from it
|
||||
@@ -23,13 +42,11 @@
|
||||
# from scratch. It can only install one file at a time, a restriction
|
||||
# shared with many OS's install programs.
|
||||
|
||||
|
||||
# set DOITPROG to echo to test this script
|
||||
|
||||
# Don't use :- since 4.3BSD and earlier shells don't like it.
|
||||
doit="${DOITPROG-}"
|
||||
|
||||
|
||||
# put in absolute paths if you don't have them in your path; or use env. vars.
|
||||
|
||||
mvprog="${MVPROG-mv}"
|
||||
@@ -41,22 +58,48 @@ stripprog="${STRIPPROG-strip}"
|
||||
rmprog="${RMPROG-rm}"
|
||||
mkdirprog="${MKDIRPROG-mkdir}"
|
||||
|
||||
transformbasename=""
|
||||
transform_arg=""
|
||||
transformbasename=
|
||||
transform_arg=
|
||||
instcmd="$mvprog"
|
||||
chmodcmd="$chmodprog 0755"
|
||||
chowncmd=""
|
||||
chgrpcmd=""
|
||||
stripcmd=""
|
||||
chowncmd=
|
||||
chgrpcmd=
|
||||
stripcmd=
|
||||
rmcmd="$rmprog -f"
|
||||
mvcmd="$mvprog"
|
||||
src=""
|
||||
dst=""
|
||||
dir_arg=""
|
||||
src=
|
||||
dst=
|
||||
dir_arg=
|
||||
|
||||
while [ x"$1" != x ]; do
|
||||
usage="Usage: $0 [OPTION]... SRCFILE DSTFILE
|
||||
or: $0 -d DIR1 DIR2...
|
||||
|
||||
In the first form, install SRCFILE to DSTFILE, removing SRCFILE by default.
|
||||
In the second, create the directory path DIR.
|
||||
|
||||
Options:
|
||||
-b=TRANSFORMBASENAME
|
||||
-c copy source (using $cpprog) instead of moving (using $mvprog).
|
||||
-d create directories instead of installing files.
|
||||
-g GROUP $chgrp installed files to GROUP.
|
||||
-m MODE $chmod installed files to MODE.
|
||||
-o USER $chown installed files to USER.
|
||||
-s strip installed files (using $stripprog).
|
||||
-t=TRANSFORM
|
||||
--help display this help and exit.
|
||||
--version display version info and exit.
|
||||
|
||||
Environment variables override the default commands:
|
||||
CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
|
||||
"
|
||||
|
||||
while test -n "$1"; do
|
||||
case $1 in
|
||||
-c) instcmd="$cpprog"
|
||||
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-c) instcmd=$cpprog
|
||||
shift
|
||||
continue;;
|
||||
|
||||
@@ -64,6 +107,13 @@ while [ x"$1" != x ]; do
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
--help) echo "$usage"; exit 0;;
|
||||
|
||||
-m) chmodcmd="$chmodprog $2"
|
||||
shift
|
||||
shift
|
||||
@@ -74,12 +124,7 @@ while [ x"$1" != x ]; do
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-s) stripcmd="$stripprog"
|
||||
-s) stripcmd=$stripprog
|
||||
shift
|
||||
continue;;
|
||||
|
||||
@@ -87,12 +132,9 @@ while [ x"$1" != x ]; do
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
|
||||
shift
|
||||
continue;;
|
||||
--version) echo "$0 $scriptversion"; exit 0;;
|
||||
|
||||
*) if [ x"$src" = x ]
|
||||
then
|
||||
*) if test -z "$src"; then
|
||||
src=$1
|
||||
else
|
||||
# this colon is to work around a 386BSD /bin/sh bug
|
||||
@@ -104,148 +146,141 @@ while [ x"$1" != x ]; do
|
||||
esac
|
||||
done
|
||||
|
||||
if [ x"$src" = x ]
|
||||
then
|
||||
echo "install: no input file specified"
|
||||
if test -z "$src"; then
|
||||
echo "$0: no input file specified." >&2
|
||||
exit 1
|
||||
else
|
||||
true
|
||||
fi
|
||||
|
||||
if [ x"$dir_arg" != x ]; then
|
||||
if test -n "$dir_arg"; then
|
||||
dst=$src
|
||||
src=""
|
||||
src=
|
||||
|
||||
if [ -d $dst ]; then
|
||||
if test -d "$dst"; then
|
||||
instcmd=:
|
||||
chmodcmd=""
|
||||
chmodcmd=
|
||||
else
|
||||
instcmd=mkdir
|
||||
instcmd=$mkdirprog
|
||||
fi
|
||||
else
|
||||
|
||||
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
|
||||
if [ -f $src -o -d $src ]
|
||||
then
|
||||
true
|
||||
else
|
||||
echo "install: $src does not exist"
|
||||
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
if test ! -f "$src" && test ! -d "$src"; then
|
||||
echo "$0: $src does not exist." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ x"$dst" = x ]
|
||||
then
|
||||
echo "install: no destination specified"
|
||||
if test -z "$dst"; then
|
||||
echo "$0: no destination specified." >&2
|
||||
exit 1
|
||||
else
|
||||
true
|
||||
fi
|
||||
|
||||
# If destination is a directory, append the input filename; if your system
|
||||
# does not like double slashes in filenames, you may need to add some logic
|
||||
|
||||
if [ -d $dst ]
|
||||
then
|
||||
dst="$dst"/`basename $src`
|
||||
else
|
||||
true
|
||||
# If destination is a directory, append the input filename; won't work
|
||||
# if double slashes aren't ignored.
|
||||
if test -d "$dst"; then
|
||||
dst=$dst/`basename "$src"`
|
||||
fi
|
||||
fi
|
||||
|
||||
## this sed command emulates the dirname command
|
||||
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
|
||||
dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
|
||||
|
||||
# Make sure that the destination directory exists.
|
||||
# this part is taken from Noah Friedman's mkinstalldirs script
|
||||
# (this part is taken from Noah Friedman's mkinstalldirs script.)
|
||||
|
||||
# Skip lots of stat calls in the usual case.
|
||||
if [ ! -d "$dstdir" ]; then
|
||||
defaultIFS='
|
||||
'
|
||||
IFS="${IFS-${defaultIFS}}"
|
||||
if test ! -d "$dstdir"; then
|
||||
defaultIFS='
|
||||
'
|
||||
IFS="${IFS-$defaultIFS}"
|
||||
|
||||
oIFS="${IFS}"
|
||||
# Some sh's can't handle IFS=/ for some reason.
|
||||
IFS='%'
|
||||
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
|
||||
IFS="${oIFS}"
|
||||
oIFS=$IFS
|
||||
# Some sh's can't handle IFS=/ for some reason.
|
||||
IFS='%'
|
||||
set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
|
||||
IFS=$oIFS
|
||||
|
||||
pathcomp=''
|
||||
pathcomp=
|
||||
|
||||
while [ $# -ne 0 ] ; do
|
||||
pathcomp="${pathcomp}${1}"
|
||||
while test $# -ne 0 ; do
|
||||
pathcomp=$pathcomp$1
|
||||
shift
|
||||
|
||||
if [ ! -d "${pathcomp}" ] ;
|
||||
then
|
||||
$mkdirprog "${pathcomp}"
|
||||
else
|
||||
true
|
||||
fi
|
||||
|
||||
pathcomp="${pathcomp}/"
|
||||
done
|
||||
test -d "$pathcomp" || $mkdirprog "$pathcomp"
|
||||
pathcomp=$pathcomp/
|
||||
done
|
||||
fi
|
||||
|
||||
if [ x"$dir_arg" != x ]
|
||||
then
|
||||
$doit $instcmd $dst &&
|
||||
if test -n "$dir_arg"; then
|
||||
$doit $instcmd "$dst" \
|
||||
&& { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
|
||||
&& { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
|
||||
&& { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
|
||||
&& { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
|
||||
|
||||
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
|
||||
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
|
||||
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
|
||||
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
|
||||
else
|
||||
|
||||
# If we're going to rename the final executable, determine the name now.
|
||||
|
||||
if [ x"$transformarg" = x ]
|
||||
then
|
||||
dstfile=`basename $dst`
|
||||
# If we're going to rename the final executable, determine the name now.
|
||||
if test -z "$transformarg"; then
|
||||
dstfile=`basename "$dst"`
|
||||
else
|
||||
dstfile=`basename $dst $transformbasename |
|
||||
sed $transformarg`$transformbasename
|
||||
dstfile=`basename "$dst" $transformbasename \
|
||||
| sed $transformarg`$transformbasename
|
||||
fi
|
||||
|
||||
# don't allow the sed command to completely eliminate the filename
|
||||
# don't allow the sed command to completely eliminate the filename.
|
||||
test -z "$dstfile" && dstfile=`basename "$dst"`
|
||||
|
||||
if [ x"$dstfile" = x ]
|
||||
then
|
||||
dstfile=`basename $dst`
|
||||
# Make a couple of temp file names in the proper directory.
|
||||
dsttmp=$dstdir/_inst.$$_
|
||||
rmtmp=$dstdir/_rm.$$_
|
||||
|
||||
# Trap to clean up those temp files at exit.
|
||||
trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0
|
||||
trap '(exit $?); exit' 1 2 13 15
|
||||
|
||||
# Move or copy the file name to the temp name
|
||||
$doit $instcmd "$src" "$dsttmp" &&
|
||||
|
||||
# and set any options; do chmod last to preserve setuid bits.
|
||||
#
|
||||
# If any of these fail, we abort the whole thing. If we want to
|
||||
# ignore errors from any of these, just make sure not to ignore
|
||||
# errors from the above "$doit $instcmd $src $dsttmp" command.
|
||||
#
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
|
||||
&& { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
|
||||
&& { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
|
||||
&& { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
|
||||
|
||||
# Now remove or move aside any old file at destination location. We
|
||||
# try this two ways since rm can't unlink itself on some systems and
|
||||
# the destination file might be busy for other reasons. In this case,
|
||||
# the final cleanup might fail but the new file should still install
|
||||
# successfully.
|
||||
{
|
||||
if test -f "$dstdir/$dstfile"; then
|
||||
$doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
|
||||
|| $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
|
||||
|| {
|
||||
echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
|
||||
(exit 1); exit
|
||||
}
|
||||
else
|
||||
true
|
||||
:
|
||||
fi
|
||||
} &&
|
||||
|
||||
# Make a temp file name in the proper directory.
|
||||
|
||||
dsttmp=$dstdir/#inst.$$#
|
||||
|
||||
# Move or copy the file name to the temp name
|
||||
|
||||
$doit $instcmd $src $dsttmp &&
|
||||
|
||||
trap "rm -f ${dsttmp}" 0 &&
|
||||
|
||||
# and set any options; do chmod last to preserve setuid bits
|
||||
|
||||
# If any of these fail, we abort the whole thing. If we want to
|
||||
# ignore errors from any of these, just make sure not to ignore
|
||||
# errors from the above "$doit $instcmd $src $dsttmp" command.
|
||||
|
||||
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
|
||||
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
|
||||
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
|
||||
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
|
||||
$doit $rmcmd -f $dstdir/$dstfile &&
|
||||
$doit $mvcmd $dsttmp $dstdir/$dstfile
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
$doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
|
||||
fi &&
|
||||
|
||||
# The final little trick to "correctly" pass the exit status to the exit trap.
|
||||
{
|
||||
(exit 0); exit
|
||||
}
|
||||
|
||||
exit 0
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-end: "$"
|
||||
# End:
|
||||
|
||||
507
configure.in
507
configure.in
@@ -1,30 +1,64 @@
|
||||
################################################################################
|
||||
##
|
||||
## Copyright 1999-2000 Sistina Software, Inc.
|
||||
## Copyright (C) 2000-2004 Sistina Software, Inc. All rights reserved.
|
||||
## Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
##
|
||||
## This is free software released under the GNU General Public License.
|
||||
## There is no warranty for this software. See the file COPYING for
|
||||
## details.
|
||||
## This file is part of the LVM2.
|
||||
##
|
||||
## See the file CONTRIBUTORS for a list of contributors.
|
||||
## This copyrighted material is made available to anyone wishing to use,
|
||||
## modify, copy, or redistribute it subject to the terms and conditions
|
||||
## of the GNU General Public License v.2.
|
||||
##
|
||||
## This file is maintained by:
|
||||
## AJ Lewis <lewis@sistina.com>
|
||||
##
|
||||
## File name: configure.in
|
||||
##
|
||||
## Description: Input file for autoconf. Generates the configure script
|
||||
## that tries to keep everything nice and portable. It also
|
||||
## simplifies distribution package building considerably.
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, write to the Free Software Foundation,
|
||||
## Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
################################################################################
|
||||
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
AC_PREREQ(2.53)
|
||||
################################################################################
|
||||
dnl -- Process this file with autoconf to produce a configure script.
|
||||
AC_INIT(lib/device/dev-cache.h)
|
||||
|
||||
dnl setup the directory where autoconf has auxilary files
|
||||
################################################################################
|
||||
dnl -- Setup the directory where autoconf has auxilary files
|
||||
AC_CONFIG_AUX_DIR(autoconf)
|
||||
|
||||
dnl Checks for programs.
|
||||
################################################################################
|
||||
dnl -- Get system type
|
||||
AC_CANONICAL_SYSTEM
|
||||
|
||||
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"
|
||||
SOFLAG="-shared"
|
||||
DEVMAPPER=yes
|
||||
ODIRECT=yes
|
||||
SELINUX=yes
|
||||
CLUSTER=internal
|
||||
FSADM=no ;;
|
||||
darwin*)
|
||||
CFLAGS="$CFLAGS -no-cpp-precomp -fno-common"
|
||||
COPTIMISE_FLAG="-O2"
|
||||
CLDFLAGS="$CLDFLAGS"
|
||||
CLDWHOLEARCHIVE="-all_load"
|
||||
CLDNOWHOLEARCHIVE=
|
||||
LDDEPS="$LDDEPS"
|
||||
LDFLAGS="$LDFLAGS"
|
||||
SOFLAG="-dynamiclib"
|
||||
DEVMAPPER=no
|
||||
ODIRECT=no
|
||||
SELINUX=no
|
||||
CLUSTER=none
|
||||
FSADM=no ;;
|
||||
esac
|
||||
|
||||
################################################################################
|
||||
dnl -- Checks for programs.
|
||||
AC_PROG_AWK
|
||||
AC_PROG_CC
|
||||
AC_PROG_INSTALL
|
||||
@@ -32,99 +66,310 @@ AC_PROG_LN_S
|
||||
AC_PROG_MAKE_SET
|
||||
AC_PROG_RANLIB
|
||||
|
||||
dnl Checks for header files.
|
||||
################################################################################
|
||||
dnl -- Checks for header files.
|
||||
AC_HEADER_DIRENT
|
||||
AC_HEADER_STDC
|
||||
AC_CHECK_HEADERS(fcntl.h malloc.h sys/ioctl.h unistd.h)
|
||||
AC_HEADER_SYS_WAIT
|
||||
AC_HEADER_TIME
|
||||
|
||||
dnl Checks for typedefs, structures, and compiler characteristics.
|
||||
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))
|
||||
|
||||
case "$host_os" in
|
||||
linux*)
|
||||
AC_CHECK_HEADERS(asm/byteorder.h linux/fs.h malloc.h,,AC_MSG_ERROR(bailing out)) ;;
|
||||
darwin*)
|
||||
AC_CHECK_HEADERS(machine/endian.h sys/disk.h,,AC_MSG_ERROR(bailing out)) ;;
|
||||
esac
|
||||
|
||||
################################################################################
|
||||
dnl -- Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_C_CONST
|
||||
AC_C_INLINE
|
||||
AC_TYPE_OFF_T
|
||||
AC_TYPE_PID_T
|
||||
AC_TYPE_SIZE_T
|
||||
AC_TYPE_MODE_T
|
||||
AC_STRUCT_ST_RDEV
|
||||
AC_HEADER_TIME
|
||||
AC_STRUCT_TM
|
||||
|
||||
dnl Get system type
|
||||
AC_CANONICAL_SYSTEM
|
||||
################################################################################
|
||||
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_FUNC_ALLOCA
|
||||
AC_FUNC_CLOSEDIR_VOID
|
||||
AC_FUNC_FORK
|
||||
AC_FUNC_LSTAT
|
||||
AC_FUNC_MALLOC
|
||||
AC_FUNC_MEMCMP
|
||||
AC_FUNC_MMAP
|
||||
AC_FUNC_STAT
|
||||
AC_FUNC_STRTOD
|
||||
|
||||
case "$host_os" in
|
||||
linux*)
|
||||
CFLAGS= ;;
|
||||
esac
|
||||
|
||||
dnl -- prefix is /usr by default, the exec_prefix default is setup later
|
||||
################################################################################
|
||||
dnl -- Prefix is /usr by default, the exec_prefix default is setup later
|
||||
AC_PREFIX_DEFAULT(/usr)
|
||||
|
||||
dnl -- setup the ownership of the files
|
||||
################################################################################
|
||||
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 ],
|
||||
[ OWNER="$withval" ],
|
||||
[ OWNER="root" ])
|
||||
[ OWNER="$withval" ])
|
||||
AC_MSG_RESULT($OWNER)
|
||||
|
||||
dnl -- setup the group ownership of the files
|
||||
if test x$OWNER != x; then
|
||||
OWNER="-o $OWNER"
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
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 ],
|
||||
[ GROUP="$withval" ],
|
||||
[ GROUP="root" ])
|
||||
[ GROUP="$withval" ])
|
||||
AC_MSG_RESULT($GROUP)
|
||||
|
||||
if test x$GROUP != x; then
|
||||
GROUP="-g $GROUP"
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- LVM1 tool fallback option
|
||||
AC_MSG_CHECKING(whether to enable lvm1 fallback)
|
||||
AC_ARG_ENABLE(lvm1_fallback, [ --enable-lvm1_fallback Use this to fall back and use LVM1 binaries if
|
||||
device-mapper is missing from the kernel], LVM1_FALLBACK=$enableval, LVM1_FALLBACK=no)
|
||||
AC_MSG_RESULT($LVM1_FALLBACK)
|
||||
|
||||
if test x$LVM1_FALLBACK = xyes; then
|
||||
CFLAGS="$CFLAGS -DLVM1_FALLBACK"
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- format1 inclusion type
|
||||
AC_MSG_CHECKING(whether to include support for lvm1 metadata)
|
||||
AC_ARG_WITH(lvm1,
|
||||
[ --with-lvm1=TYPE LVM1 metadata support: internal/shared/none
|
||||
[TYPE=internal] ],
|
||||
[ LVM1="$withval" ],
|
||||
[ LVM1="internal" ])
|
||||
AC_MSG_RESULT($LVM1)
|
||||
|
||||
if [[ "x$LVM1" != xnone -a "x$LVM1" != xinternal -a "x$LVM1" != xshared ]];
|
||||
then AC_MSG_ERROR(
|
||||
--with-lvm1 parameter invalid
|
||||
)
|
||||
exit
|
||||
fi;
|
||||
|
||||
if test x$LVM1 = xinternal; then
|
||||
CFLAGS="$CFLAGS -DLVM1_INTERNAL"
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(jobs, [ --enable-jobs=NUM Number of jobs to run simultaneously], JOBS=-j$enableval, JOBS=-j2)
|
||||
################################################################################
|
||||
dnl -- format_pool inclusion type
|
||||
AC_MSG_CHECKING(whether to include support for GFS pool metadata)
|
||||
AC_ARG_WITH(pool,
|
||||
[ --with-pool=TYPE GFS pool read-only support: internal/shared/none
|
||||
[TYPE=internal] ],
|
||||
[ POOL="$withval" ],
|
||||
[ POOL="internal" ])
|
||||
AC_MSG_RESULT($POOL)
|
||||
|
||||
dnl Enables staticly linked tools
|
||||
AC_ARG_ENABLE(static_link, [ --enable-static_link Use this to link the tools to the liblvm library
|
||||
if [[ "x$POOL" != xnone -a "x$POOL" != xinternal -a "x$POOL" != xshared ]];
|
||||
then AC_MSG_ERROR(
|
||||
--with-pool parameter invalid
|
||||
)
|
||||
fi;
|
||||
|
||||
if test x$POOL = xinternal; then
|
||||
CFLAGS="$CFLAGS -DPOOL_INTERNAL"
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- cluster_locking inclusion type
|
||||
AC_MSG_CHECKING(whether to include support for cluster locking)
|
||||
AC_ARG_WITH(cluster,
|
||||
[ --with-cluster=TYPE Cluster LVM locking support: internal/shared/none
|
||||
[TYPE=internal] ],
|
||||
[ CLUSTER="$withval" ])
|
||||
AC_MSG_RESULT($CLUSTER)
|
||||
|
||||
if [[ "x$CLUSTER" != xnone -a "x$CLUSTER" != xinternal -a "x$CLUSTER" != xshared ]];
|
||||
then AC_MSG_ERROR(
|
||||
--with-cluster parameter invalid
|
||||
)
|
||||
fi;
|
||||
|
||||
if test x$CLUSTER = xinternal; then
|
||||
CFLAGS="$CFLAGS -DCLUSTER_LOCKING_INTERNAL"
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- snapshots inclusion type
|
||||
AC_MSG_CHECKING(whether to include snapshots)
|
||||
AC_ARG_WITH(snapshots,
|
||||
[ --with-snapshots=TYPE Snapshot support: internal/shared/none
|
||||
[TYPE=internal] ],
|
||||
[ SNAPSHOTS="$withval" ],
|
||||
[ SNAPSHOTS="internal" ])
|
||||
AC_MSG_RESULT($SNAPSHOTS)
|
||||
|
||||
if [[ "x$SNAPSHOTS" != xnone -a "x$SNAPSHOTS" != xinternal -a "x$SNAPSHOTS" != xshared ]];
|
||||
then AC_MSG_ERROR(
|
||||
--with-snapshots parameter invalid
|
||||
)
|
||||
fi;
|
||||
|
||||
if test x$SNAPSHOTS = xinternal; then
|
||||
CFLAGS="$CFLAGS -DSNAPSHOT_INTERNAL"
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- mirrors inclusion type
|
||||
AC_MSG_CHECKING(whether to include mirrors)
|
||||
AC_ARG_WITH(mirrors,
|
||||
[ --with-mirrors=TYPE Mirror support: internal/shared/none
|
||||
[TYPE=internal] ],
|
||||
[ MIRRORS="$withval" ],
|
||||
[ MIRRORS="internal" ])
|
||||
AC_MSG_RESULT($MIRRORS)
|
||||
|
||||
if [[ "x$MIRRORS" != xnone -a "x$MIRRORS" != xinternal -a "x$MIRRORS" != xshared ]];
|
||||
then AC_MSG_ERROR(
|
||||
--with-mirrors parameter invalid
|
||||
)
|
||||
fi;
|
||||
|
||||
if test x$MIRRORS = xinternal; then
|
||||
CFLAGS="$CFLAGS -DMIRRORED_INTERNAL"
|
||||
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
|
||||
AC_ARG_ENABLE(readline, [ --enable-readline Enable readline support], \
|
||||
################################################################################
|
||||
dnl -- Enable readline
|
||||
AC_MSG_CHECKING(whether to enable readline)
|
||||
AC_ARG_ENABLE(readline, [ --enable-readline Enable readline support],
|
||||
READLINE=$enableval, READLINE=no)
|
||||
AC_MSG_RESULT($READLINE)
|
||||
|
||||
if test x$READLINE = xyes; then
|
||||
CFLAGS="$CFLAGS -DREADLINE_SUPPORT"
|
||||
fi
|
||||
|
||||
dnl Enable Debugging
|
||||
AC_ARG_ENABLE(debug, [ --enable-debug Enable debugging], \
|
||||
DEBUG=yes, DEBUG=no)
|
||||
################################################################################
|
||||
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 devmapper
|
||||
AC_ARG_ENABLE(devmapper, [ --disable-devmapper Disable device-mapper interaction], \
|
||||
DEVMAPPER=no, DEVMAPPER=yes)
|
||||
################################################################################
|
||||
dnl -- Build cluster LVM daemon
|
||||
AC_MSG_CHECKING(whether to build cluster LVM daemon)
|
||||
AC_ARG_WITH(clvmd,
|
||||
[ --with-clvmd=TYPE Build cluster LVM Daemon: cman/gulm/none
|
||||
[TYPE=none] ],
|
||||
[ CLVMD="$withval" ],
|
||||
[ CLVMD="none" ])
|
||||
if test x$CLVMD = xyes; then
|
||||
CLVMD=cman
|
||||
fi
|
||||
AC_MSG_RESULT($CLVMD)
|
||||
|
||||
dnl -- If clvmd enabled without cluster locking, automagically include it
|
||||
if test x$CLVMD != xnone && test x$CLUSTER = xnone; then
|
||||
CLUSTER=internal
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Enable debugging
|
||||
AC_MSG_CHECKING(whether to enable debugging)
|
||||
AC_ARG_ENABLE(debug, [ --enable-debug Enable debugging],
|
||||
DEBUG=$enableval, DEBUG=no)
|
||||
AC_MSG_RESULT($DEBUG)
|
||||
|
||||
dnl -- Normally turn off optimisation for debug builds
|
||||
if test x$DEBUG = xyes; then
|
||||
COPTIMISE_FLAG=
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Override optimisation
|
||||
AC_MSG_CHECKING(for C optimisation flag)
|
||||
AC_ARG_WITH(optimisation,
|
||||
[ --with-optimisation=OPT C optimisation flag [OPT=-O2] ],
|
||||
[ COPTIMISE_FLAG="$withval" ])
|
||||
AC_MSG_RESULT($COPTIMISE_FLAG)
|
||||
|
||||
################################################################################
|
||||
dnl -- Disable devmapper
|
||||
AC_MSG_CHECKING(whether to use device-mapper)
|
||||
AC_ARG_ENABLE(devmapper, [ --disable-devmapper Disable device-mapper interaction],
|
||||
DEVMAPPER=$enableval)
|
||||
AC_MSG_RESULT($DEVMAPPER)
|
||||
|
||||
if test x$DEVMAPPER = xyes; then
|
||||
CFLAGS="$CFLAGS -DDEVMAPPER_SUPPORT"
|
||||
fi
|
||||
|
||||
dnl Mess with default exec_prefix
|
||||
################################################################################
|
||||
dnl -- Disable O_DIRECT
|
||||
AC_MSG_CHECKING(whether to enable O_DIRECT)
|
||||
AC_ARG_ENABLE(o_direct, [ --disable-o_direct Disable O_DIRECT],
|
||||
ODIRECT=$enableval)
|
||||
AC_MSG_RESULT($ODIRECT)
|
||||
|
||||
if test x$ODIRECT = xyes; then
|
||||
CFLAGS="$CFLAGS -DO_DIRECT_SUPPORT"
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Enable cmdlib
|
||||
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)
|
||||
|
||||
if test x$CMDLIB = xyes; then
|
||||
CFLAGS="$CFLAGS -DCMDLIB"
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Enable fsadm
|
||||
AC_MSG_CHECKING(whether to build fsadm)
|
||||
AC_ARG_ENABLE(fsadm, [ --enable-fsadm Enable fsadm],
|
||||
FSADM=$enableval)
|
||||
AC_MSG_RESULT($FSADM)
|
||||
|
||||
################################################################################
|
||||
dnl -- Mess with default exec_prefix
|
||||
if [[ "x$exec_prefix" = xNONE -a "x$prefix" = xNONE ]];
|
||||
then exec_prefix="";
|
||||
fi;
|
||||
|
||||
dnl Checks for library functions.
|
||||
################################################################################
|
||||
dnl -- Checks for library functions.
|
||||
AC_PROG_GCC_TRADITIONAL
|
||||
AC_TYPE_SIGNAL
|
||||
AC_FUNC_VPRINTF
|
||||
AC_CHECK_FUNCS(mkdir rmdir uname)
|
||||
AC_CHECK_FUNCS(mkdir rmdir uname,,AC_MSG_ERROR(bailing out))
|
||||
|
||||
dnl check for termcap (Shamelessly copied from parted 1.4.17)
|
||||
################################################################################
|
||||
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(
|
||||
@@ -137,22 +382,51 @@ 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.
|
||||
)
|
||||
exit
|
||||
)
|
||||
fi
|
||||
|
||||
dnl Check for dlopen
|
||||
################################################################################
|
||||
dnl -- Check for dlopen
|
||||
AC_CHECK_LIB(dl, dlopen, HAVE_LIBDL=yes, HAVE_LIBDL=no)
|
||||
|
||||
if test x$HAVE_LIBDL = xyes; then
|
||||
if [[ "x$HAVE_LIBDL" = xyes ]]; then
|
||||
CFLAGS="$CFLAGS -DHAVE_LIBDL"
|
||||
LIBS="-ldl $LIBS"
|
||||
else
|
||||
HAVE_LIBDL=no
|
||||
fi
|
||||
|
||||
dnl Check for getopt
|
||||
################################################################################
|
||||
dnl -- Check for shared/static conflicts
|
||||
if [[ \( "x$LVM1" = xshared -o "x$POOL" = xshared -o "x$CLUSTER" = xshared \
|
||||
-o "x$SNAPSHOTS" = xshared -o "x$MIRRORS" = xshared \
|
||||
\) -a "x$STATIC_LINK" = xyes ]];
|
||||
then AC_MSG_ERROR(
|
||||
Features cannot be 'shared' when building statically
|
||||
)
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Check for is_selinux_enabled
|
||||
if test x$SELINUX = xyes; then
|
||||
AC_MSG_CHECKING(for is_selinux_enabled function)
|
||||
AC_CHECK_LIB(selinux, is_selinux_enabled, HAVE_SELINUX=yes, HAVE_SELINUX=no)
|
||||
AC_MSG_RESULT($HAVE_SELINUX)
|
||||
|
||||
if test x$HAVE_SELINUX = xyes; then
|
||||
CFLAGS="$CFLAGS -DHAVE_SELINUX"
|
||||
LIBS="-lselinux $LIBS"
|
||||
else
|
||||
AC_MSG_WARN(Disabling selinux)
|
||||
fi
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Check for getopt
|
||||
AC_CHECK_HEADERS(getopt.h, CFLAGS="$CFLAGS -DHAVE_GETOPTLONG")
|
||||
|
||||
dnl Check for readline (Shamelessly copied from parted 1.4.17)
|
||||
################################################################################
|
||||
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(
|
||||
@@ -163,43 +437,158 @@ 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).
|
||||
)
|
||||
exit
|
||||
)
|
||||
AC_CHECK_FUNC(rl_completion_matches, CFLAGS="$CFLAGS -DHAVE_RL_COMPLETION_MATCHES")
|
||||
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Internationalisation stuff
|
||||
AC_MSG_CHECKING(whether to enable internationalisation)
|
||||
AC_ARG_ENABLE(nls, [ --enable-nls Enable Native Language Support],
|
||||
INTL=$enableval, INTL=no)
|
||||
AC_MSG_RESULT($INTL)
|
||||
|
||||
if test x$INTL = xyes; then
|
||||
INTL_PACKAGE="lvm2"
|
||||
AC_PATH_PROG(MSGFMT, msgfmt)
|
||||
if [[ "x$MSGFMT" == x ]];
|
||||
then AC_MSG_ERROR(
|
||||
msgfmt not found in path $PATH
|
||||
)
|
||||
fi;
|
||||
|
||||
AC_ARG_WITH(localedir,
|
||||
[ --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' ])
|
||||
|
||||
AC_ARG_WITH(staticdir,
|
||||
[ --with-staticdir=DIR Static binary in DIR [EXEC_PREFIX/sbin]],
|
||||
[ STATICDIR="$withval" ],
|
||||
[ STATICDIR='${exec_prefix}/sbin' ])
|
||||
|
||||
################################################################################
|
||||
dnl -- Ensure additional headers required
|
||||
if test x$READLINE = xyes; then
|
||||
AC_CHECK_HEADERS(readline/readline.h readline/history.h,,AC_MSG_ERROR(bailing out))
|
||||
fi
|
||||
|
||||
if test x$CLVMD = xyes; then
|
||||
AC_CHECK_HEADERS(mntent.h netdb.h netinet/in.h pthread.h search.h sys/mount.h sys/socket.h sys/uio.h sys/un.h utmpx.h,,AC_MSG_ERROR(bailing out))
|
||||
AC_CHECK_FUNCS(dup2 getmntent memmove select socket,,AC_MSG_ERROR(bailing out))
|
||||
AC_FUNC_GETMNTENT
|
||||
# AC_FUNC_REALLOC
|
||||
AC_FUNC_SELECT_ARGTYPES
|
||||
fi
|
||||
|
||||
if test x$FSADM = xyes; then
|
||||
AC_CHECK_HEADERS(fstab.h sys/mount.h sys/vfs.h,,AC_MSG_ERROR(bailing out))
|
||||
AC_CHECK_FUNCS(memmove,,AC_MSG_ERROR(bailing out))
|
||||
fi
|
||||
|
||||
if test x$CLUSTER != xnone; then
|
||||
AC_CHECK_HEADERS(sys/socket.h sys/un.h,,AC_MSG_ERROR(bailing out))
|
||||
AC_CHECK_FUNCS(socket,,AC_MSG_ERROR(bailing out))
|
||||
fi
|
||||
|
||||
if test x$HAVE_LIBDL = xyes; then
|
||||
AC_CHECK_HEADERS(dlfcn.h,,AC_MSG_ERROR(bailing out))
|
||||
fi
|
||||
|
||||
if test x$INTL = xyes; then
|
||||
AC_CHECK_HEADERS(libintl.h,,AC_MSG_ERROR(bailing out))
|
||||
fi
|
||||
|
||||
if test x$DEVMAPPER = xyes; then
|
||||
AC_CHECK_HEADERS(libdevmapper.h,,AC_MSG_ERROR(bailing out))
|
||||
fi
|
||||
|
||||
if test x$HAVE_SELINUX = xyes; then
|
||||
AC_CHECK_HEADERS(selinux/selinux.h,,AC_MSG_ERROR(bailing out))
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
if test "-f VERSION"; then
|
||||
LVM_VERSION="\"`cat VERSION`\""
|
||||
else
|
||||
LVM_VERSION="Unknown"
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
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(CFLAGS)
|
||||
AC_SUBST(COPTIMISE_FLAG)
|
||||
AC_SUBST(CLDFLAGS)
|
||||
AC_SUBST(CLDWHOLEARCHIVE)
|
||||
AC_SUBST(CLDNOWHOLEARCHIVE)
|
||||
AC_SUBST(LDDEPS)
|
||||
AC_SUBST(LDFLAGS)
|
||||
AC_SUBST(SOFLAG)
|
||||
AC_SUBST(LIBS)
|
||||
AC_SUBST(LVM_VERSION)
|
||||
AC_SUBST(LVM1_FALLBACK)
|
||||
AC_SUBST(DEBUG)
|
||||
AC_SUBST(DEVMAPPER)
|
||||
AC_SUBST(HAVE_LIBDL)
|
||||
dnl First and last lines should not contain files to generate in order to
|
||||
dnl keep utility scripts running properly
|
||||
AC_SUBST(HAVE_SELINUX)
|
||||
AC_SUBST(CMDLIB)
|
||||
AC_SUBST(MSGFMT)
|
||||
AC_SUBST(LOCALEDIR)
|
||||
AC_SUBST(CONFDIR)
|
||||
AC_SUBST(STATICDIR)
|
||||
AC_SUBST(INTL_PACKAGE)
|
||||
AC_SUBST(INTL)
|
||||
AC_SUBST(CLVMD)
|
||||
AC_SUBST(CLUSTER)
|
||||
AC_SUBST(FSADM)
|
||||
|
||||
################################################################################
|
||||
dnl -- First and last lines should not contain files to generate in order to
|
||||
dnl -- keep utility scripts running properly
|
||||
AC_OUTPUT( \
|
||||
Makefile \
|
||||
make.tmpl \
|
||||
daemons/Makefile \
|
||||
daemons/clvmd/Makefile \
|
||||
doc/Makefile \
|
||||
include/Makefile \
|
||||
lib/Makefile \
|
||||
lib/format1/Makefile \
|
||||
lib/format_pool/Makefile \
|
||||
lib/locking/Makefile \
|
||||
lib/mirror/Makefile \
|
||||
lib/snapshot/Makefile \
|
||||
man/Makefile \
|
||||
po/Makefile \
|
||||
tools/Makefile \
|
||||
tools/version.h \
|
||||
tools/fsadm/Makefile \
|
||||
test/mm/Makefile \
|
||||
test/device/Makefile \
|
||||
test/format1/Makefile \
|
||||
test/regex/Makefile \
|
||||
test/filters/Makefile \
|
||||
)
|
||||
|
||||
if test x$ODIRECT != xyes; then
|
||||
AC_MSG_WARN(Warning: O_DIRECT disabled: low-memory pvmove may lock up)
|
||||
fi
|
||||
|
||||
if test x$FSADM == xyes; then
|
||||
AC_MSG_WARN(fsadm support is untested)
|
||||
fi
|
||||
|
||||
23
daemons/Makefile.in
Normal file
23
daemons/Makefile.in
Normal file
@@ -0,0 +1,23 @@
|
||||
#
|
||||
# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of the LVM2.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
ifneq ("@CLVMD@", "none")
|
||||
SUBDIRS = clvmd
|
||||
endif
|
||||
|
||||
include $(top_srcdir)/make.tmpl
|
||||
|
||||
59
daemons/clvmd/Makefile.in
Normal file
59
daemons/clvmd/Makefile.in
Normal file
@@ -0,0 +1,59 @@
|
||||
#
|
||||
# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of the LVM2.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
SOURCES = \
|
||||
clvmd-command.c \
|
||||
clvmd.c \
|
||||
libclvm.c \
|
||||
lvm-functions.c \
|
||||
system-lv.c
|
||||
|
||||
ifeq ("@CLVMD@", "gulm")
|
||||
SOURCES += clvmd-gulm.c tcp-comms.c
|
||||
LMLIBS += -lccs -lgulm
|
||||
CFLAGS += -DUSE_GULM
|
||||
endif
|
||||
|
||||
ifeq ("@CLVMD@", "cman")
|
||||
SOURCES += clvmd-cman.c
|
||||
LMLIBS += -ldlm
|
||||
endif
|
||||
|
||||
TARGETS = \
|
||||
clvmd
|
||||
|
||||
include $(top_srcdir)/make.tmpl
|
||||
|
||||
CFLAGS += -D_REENTRANT -fno-strict-aliasing
|
||||
LIBS += -ldevmapper -llvm -lpthread
|
||||
|
||||
INSTALL_TARGETS = \
|
||||
install_clvmd
|
||||
|
||||
clvmd: $(OBJECTS) $(top_srcdir)/lib/liblvm.a
|
||||
$(CC) -o clvmd $(OBJECTS) $(LDFLAGS) $(LVMLIBS) $(LMLIBS) $(LIBS)
|
||||
|
||||
.PHONY: install_clvmd
|
||||
|
||||
install_clvmd: $(TARGETS)
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) clvmd \
|
||||
$(sbindir)/clvmd
|
||||
|
||||
install: $(INSTALL_TARGETS)
|
||||
|
||||
install_cluster: $(INSTALL_TARGETS)
|
||||
|
||||
65
daemons/clvmd/clvm.h
Normal file
65
daemons/clvmd/clvm.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Definitions for CLVMD server and clients */
|
||||
|
||||
/*
|
||||
* The protocol spoken over the cluster and across the local socket.
|
||||
*/
|
||||
|
||||
#ifndef _CLVM_H
|
||||
#define _CLVM_H
|
||||
|
||||
struct clvm_header {
|
||||
uint8_t cmd; /* See below */
|
||||
uint8_t flags; /* See below */
|
||||
uint16_t xid; /* Transaction ID */
|
||||
uint32_t clientid; /* Only used in Daemon->Daemon comms */
|
||||
int32_t status; /* For replies, whether request succeeded */
|
||||
uint32_t arglen; /* Length of argument below.
|
||||
If >1500 then it will be passed
|
||||
around the cluster in the system LV */
|
||||
char node[1]; /* Actually a NUL-terminated string, node name.
|
||||
If this is empty then the command is
|
||||
forwarded to all cluster nodes unless
|
||||
FLAG_LOCAL is also set. */
|
||||
char args[1]; /* Arguments for the command follow the
|
||||
node name, This member is only
|
||||
valid if the node name is empty */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Flags */
|
||||
#define CLVMD_FLAG_LOCAL 1 /* Only do this on the local node */
|
||||
#define CLVMD_FLAG_SYSTEMLV 2 /* Data in system LV under my node name */
|
||||
|
||||
/* Name of the local socket to communicate between libclvm and clvmd */
|
||||
//static const char CLVMD_SOCKNAME[]="/var/run/clvmd";
|
||||
static const char CLVMD_SOCKNAME[] = "\0clvmd";
|
||||
|
||||
/* Internal commands & replies */
|
||||
#define CLVMD_CMD_REPLY 1
|
||||
#define CLVMD_CMD_VERSION 2 /* Send version around cluster when we start */
|
||||
#define CLVMD_CMD_GOAWAY 3 /* Die if received this - we are running
|
||||
an incompatible version */
|
||||
#define CLVMD_CMD_TEST 4 /* Just for mucking about */
|
||||
|
||||
#define CLVMD_CMD_LOCK 30
|
||||
#define CLVMD_CMD_UNLOCK 31
|
||||
|
||||
/* Lock/Unlock commands */
|
||||
#define CLVMD_CMD_LOCK_LV 50
|
||||
#define CLVMD_CMD_LOCK_VG 51
|
||||
|
||||
#endif
|
||||
507
daemons/clvmd/clvmd-cman.c
Normal file
507
daemons/clvmd/clvmd-cman.c
Normal file
@@ -0,0 +1,507 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* CMAN communication layer for clvmd.
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <syslog.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "clvmd-comms.h"
|
||||
#include "clvm.h"
|
||||
#include "libdlm.h"
|
||||
#include "log.h"
|
||||
#include "clvmd.h"
|
||||
#include "lvm-functions.h"
|
||||
|
||||
#define LOCKSPACE_NAME "clvmd"
|
||||
|
||||
static int cluster_sock;
|
||||
static int num_nodes;
|
||||
static struct cl_cluster_node *nodes = NULL;
|
||||
static int count_nodes; /* size of allocated nodes array */
|
||||
static int max_updown_nodes = 50; /* Current size of the allocated array */
|
||||
/* Node up/down status, indexed by nodeid */
|
||||
static int *node_updown = NULL;
|
||||
static dlm_lshandle_t *lockspace;
|
||||
|
||||
static void count_clvmds_running(void);
|
||||
static void get_members(void);
|
||||
static int nodeid_from_csid(char *csid);
|
||||
static int name_from_nodeid(int nodeid, char *name);
|
||||
|
||||
struct lock_wait {
|
||||
pthread_cond_t cond;
|
||||
pthread_mutex_t mutex;
|
||||
struct dlm_lksb lksb;
|
||||
};
|
||||
|
||||
int init_cluster()
|
||||
{
|
||||
struct sockaddr_cl saddr;
|
||||
int port = CLUSTER_PORT_CLVMD;
|
||||
|
||||
/* Open the cluster communication socket */
|
||||
cluster_sock = socket(AF_CLUSTER, SOCK_DGRAM, CLPROTO_CLIENT);
|
||||
if (cluster_sock == -1) {
|
||||
syslog(LOG_ERR, "Can't open cluster manager socket: %m");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Bind to our port number on the cluster.
|
||||
Writes to this will block if the cluster loses quorum */
|
||||
saddr.scl_family = AF_CLUSTER;
|
||||
saddr.scl_port = port;
|
||||
|
||||
if (bind
|
||||
(cluster_sock, (struct sockaddr *) &saddr,
|
||||
sizeof(struct sockaddr_cl))) {
|
||||
syslog(LOG_ERR, "Can't bind cluster socket: %m");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Get the cluster members list */
|
||||
get_members();
|
||||
count_clvmds_running();
|
||||
|
||||
/* Create a lockspace for LV & VG locks to live in */
|
||||
lockspace = dlm_create_lockspace(LOCKSPACE_NAME, 0600);
|
||||
if (!lockspace) {
|
||||
syslog(LOG_ERR, "Unable to create lockspace for CLVM: %m");
|
||||
return -1;
|
||||
}
|
||||
dlm_ls_pthread_init(lockspace);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_main_cluster_fd()
|
||||
{
|
||||
return cluster_sock;
|
||||
}
|
||||
|
||||
int get_num_nodes()
|
||||
{
|
||||
return num_nodes;
|
||||
}
|
||||
|
||||
/* send_message with the fd check removed */
|
||||
int cluster_send_message(void *buf, int msglen, char *csid, const char *errtext)
|
||||
{
|
||||
struct iovec iov[2];
|
||||
struct msghdr msg;
|
||||
struct sockaddr_cl saddr;
|
||||
int len = 0;
|
||||
|
||||
msg.msg_control = NULL;
|
||||
msg.msg_controllen = 0;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_iov = iov;
|
||||
msg.msg_flags = 0;
|
||||
iov[0].iov_len = msglen;
|
||||
iov[0].iov_base = buf;
|
||||
|
||||
saddr.scl_family = AF_CLUSTER;
|
||||
saddr.scl_port = CLUSTER_PORT_CLVMD;
|
||||
if (csid) {
|
||||
msg.msg_name = &saddr;
|
||||
msg.msg_namelen = sizeof(saddr);
|
||||
memcpy(&saddr.scl_nodeid, csid, MAX_CSID_LEN);
|
||||
} else { /* Cluster broadcast */
|
||||
|
||||
msg.msg_name = NULL;
|
||||
msg.msg_namelen = 0;
|
||||
}
|
||||
|
||||
do {
|
||||
len = sendmsg(cluster_sock, &msg, 0);
|
||||
if (len < 0 && errno != EAGAIN)
|
||||
log_error(errtext);
|
||||
|
||||
} while (len == -1 && errno == EAGAIN);
|
||||
return len;
|
||||
}
|
||||
|
||||
void get_our_csid(char *csid)
|
||||
{
|
||||
int i;
|
||||
memset(csid, 0, MAX_CSID_LEN);
|
||||
|
||||
for (i = 0; i < num_nodes; i++) {
|
||||
if (nodes[i].us)
|
||||
memcpy(csid, &nodes[i].node_id, MAX_CSID_LEN);
|
||||
}
|
||||
}
|
||||
|
||||
/* Call a callback routine for each node that known (down mean not running a clvmd) */
|
||||
int cluster_do_node_callback(struct local_client *client,
|
||||
void (*callback) (struct local_client *, char *,
|
||||
int))
|
||||
{
|
||||
int i;
|
||||
int somedown = 0;
|
||||
|
||||
for (i = 0; i < get_num_nodes(); i++) {
|
||||
callback(client, (char *)&nodes[i].node_id, node_updown[nodes[i].node_id]);
|
||||
if (!node_updown[nodes[i].node_id])
|
||||
somedown = -1;
|
||||
}
|
||||
return somedown;
|
||||
}
|
||||
|
||||
/* Process OOB message from the cluster socket,
|
||||
this currently just means that a node has stopped listening on our port */
|
||||
static void process_oob_msg(char *buf, int len, int nodeid)
|
||||
{
|
||||
char namebuf[256];
|
||||
switch (buf[0]) {
|
||||
case CLUSTER_OOB_MSG_PORTCLOSED:
|
||||
name_from_nodeid(nodeid, namebuf);
|
||||
log_notice("clvmd on node %s has died\n", namebuf);
|
||||
DEBUGLOG("Got OOB message, removing node %s\n", namebuf);
|
||||
|
||||
node_updown[nodeid] = 0;
|
||||
break;
|
||||
|
||||
case CLUSTER_OOB_MSG_STATECHANGE:
|
||||
DEBUGLOG("Got OOB message, Cluster state change\n");
|
||||
get_members();
|
||||
break;
|
||||
default:
|
||||
/* ERROR */
|
||||
DEBUGLOG("Got unknown OOB message: %d\n", buf[0]);
|
||||
}
|
||||
}
|
||||
|
||||
int cluster_fd_callback(struct local_client *client, char *buf, int len, char *csid,
|
||||
struct local_client **new_client)
|
||||
{
|
||||
struct iovec iov[2];
|
||||
struct msghdr msg;
|
||||
struct sockaddr_cl saddr;
|
||||
|
||||
/* We never return a new client */
|
||||
*new_client = NULL;
|
||||
|
||||
msg.msg_control = NULL;
|
||||
msg.msg_controllen = 0;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_iov = iov;
|
||||
msg.msg_name = &saddr;
|
||||
msg.msg_flags = 0;
|
||||
msg.msg_namelen = sizeof(saddr);
|
||||
iov[0].iov_len = len;
|
||||
iov[0].iov_base = buf;
|
||||
|
||||
len = recvmsg(cluster_sock, &msg, MSG_OOB | O_NONBLOCK);
|
||||
if (len < 0 && errno == EAGAIN)
|
||||
return len;
|
||||
|
||||
DEBUGLOG("Read on cluster socket, len = %d\n", len);
|
||||
|
||||
/* A real error */
|
||||
if (len < 0) {
|
||||
log_error("read error on cluster socket: %m");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* EOF - we have left the cluster */
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
/* Is it OOB? probably a node gone down */
|
||||
if (msg.msg_flags & MSG_OOB) {
|
||||
process_oob_msg(iov[0].iov_base, len, saddr.scl_nodeid);
|
||||
|
||||
/* Tell the upper layer to ignore this message */
|
||||
len = -1;
|
||||
errno = EAGAIN;
|
||||
}
|
||||
else {
|
||||
memcpy(csid, &saddr.scl_nodeid, sizeof(saddr.scl_nodeid));
|
||||
/* Send it back to clvmd */
|
||||
process_message(client, buf, len, csid);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
void add_up_node(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;
|
||||
DEBUGLOG("Added new node %d to updown list\n", nodeid);
|
||||
}
|
||||
|
||||
void cluster_closedown()
|
||||
{
|
||||
unlock_all();
|
||||
dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
|
||||
close(cluster_sock);
|
||||
}
|
||||
|
||||
static int is_listening(int nodeid)
|
||||
{
|
||||
struct cl_listen_request rq;
|
||||
int status;
|
||||
|
||||
rq.port = CLUSTER_PORT_CLVMD;
|
||||
rq.nodeid = nodeid;
|
||||
|
||||
do {
|
||||
status = ioctl(cluster_sock, SIOCCLUSTER_ISLISTENING, &rq);
|
||||
if (status < 0 && errno == EBUSY) { /* Don't busywait */
|
||||
sleep(1);
|
||||
errno = EBUSY; /* In case sleep trashes it */
|
||||
}
|
||||
}
|
||||
while (status < 0 && errno == EBUSY);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Populate the list of CLVMDs running.
|
||||
called only at startup time */
|
||||
void count_clvmds_running(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_nodes; i++) {
|
||||
node_updown[nodes[i].node_id] = is_listening(nodes[i].node_id);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get a list of active cluster members */
|
||||
static void get_members()
|
||||
{
|
||||
struct cl_cluster_nodelist nodelist;
|
||||
|
||||
num_nodes = ioctl(cluster_sock, SIOCCLUSTER_GETMEMBERS, 0);
|
||||
if (num_nodes == -1) {
|
||||
log_error("Unable to get node count");
|
||||
} else {
|
||||
/* Not enough room for new nodes list ? */
|
||||
if (num_nodes > count_nodes && nodes) {
|
||||
free(nodes);
|
||||
nodes = NULL;
|
||||
}
|
||||
|
||||
if (nodes == NULL) {
|
||||
count_nodes = num_nodes + 10; /* Overallocate a little */
|
||||
nodes = malloc(count_nodes * sizeof(struct cl_cluster_node));
|
||||
if (!nodes) {
|
||||
log_error("Unable to allocate nodes array\n");
|
||||
exit(5);
|
||||
}
|
||||
}
|
||||
nodelist.max_members = count_nodes;
|
||||
nodelist.nodes = nodes;
|
||||
|
||||
num_nodes = ioctl(cluster_sock, SIOCCLUSTER_GETMEMBERS, &nodelist);
|
||||
if (num_nodes <= 0) {
|
||||
log_error("Unable to get node details");
|
||||
exit(6);
|
||||
}
|
||||
|
||||
/* Sanity check struct */
|
||||
if (nodes[0].size != sizeof(struct cl_cluster_node)) {
|
||||
log_error
|
||||
("sizeof(cl_cluster_node) does not match size returned from the kernel: aborting\n");
|
||||
exit(10);
|
||||
}
|
||||
|
||||
if (node_updown == NULL) {
|
||||
node_updown =
|
||||
(int *) malloc(sizeof(int) *
|
||||
max(num_nodes, max_updown_nodes));
|
||||
memset(node_updown, 0,
|
||||
sizeof(int) * max(num_nodes, max_updown_nodes));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert a node name to a CSID */
|
||||
int csid_from_name(char *csid, char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_nodes; i++) {
|
||||
if (strcmp(name, nodes[i].name) == 0) {
|
||||
memcpy(csid, &nodes[i].node_id, MAX_CSID_LEN);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Convert a CSID to a node name */
|
||||
int name_from_csid(char *csid, char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_nodes; i++) {
|
||||
if (memcmp(csid, &nodes[i].node_id, MAX_CSID_LEN) == 0) {
|
||||
strcpy(name, nodes[i].name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* Who?? */
|
||||
strcpy(name, "Unknown");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Convert a node ID to a node name */
|
||||
int name_from_nodeid(int nodeid, char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_nodes; i++) {
|
||||
if (nodeid == nodes[i].node_id) {
|
||||
strcpy(name, nodes[i].name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* Who?? */
|
||||
strcpy(name, "Unknown");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Convert a CSID to a node ID */
|
||||
static int nodeid_from_csid(char *csid)
|
||||
{
|
||||
int nodeid;
|
||||
|
||||
memcpy(&nodeid, csid, MAX_CSID_LEN);
|
||||
|
||||
return nodeid;
|
||||
}
|
||||
|
||||
int is_quorate()
|
||||
{
|
||||
return ioctl(cluster_sock, SIOCCLUSTER_ISQUORATE, 0);
|
||||
}
|
||||
|
||||
static void sync_ast_routine(void *arg)
|
||||
{
|
||||
struct lock_wait *lwait = arg;
|
||||
|
||||
pthread_mutex_lock(&lwait->mutex);
|
||||
pthread_cond_signal(&lwait->cond);
|
||||
pthread_mutex_unlock(&lwait->mutex);
|
||||
}
|
||||
|
||||
int sync_lock(const char *resource, int mode, int flags, int *lockid)
|
||||
{
|
||||
int status;
|
||||
struct lock_wait lwait;
|
||||
|
||||
if (!lockid) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
DEBUGLOG("sync_lock: '%s' mode:%d flags=%d\n", resource,mode,flags);
|
||||
/* Conversions need the lockid in the LKSB */
|
||||
if (flags & LKF_CONVERT)
|
||||
lwait.lksb.sb_lkid = *lockid;
|
||||
|
||||
pthread_cond_init(&lwait.cond, NULL);
|
||||
pthread_mutex_init(&lwait.mutex, NULL);
|
||||
pthread_mutex_lock(&lwait.mutex);
|
||||
|
||||
status = dlm_ls_lock(lockspace,
|
||||
mode,
|
||||
&lwait.lksb,
|
||||
flags,
|
||||
resource,
|
||||
strlen(resource),
|
||||
0, sync_ast_routine, &lwait, NULL, NULL);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/* Wait for it to complete */
|
||||
pthread_cond_wait(&lwait.cond, &lwait.mutex);
|
||||
pthread_mutex_unlock(&lwait.mutex);
|
||||
|
||||
*lockid = lwait.lksb.sb_lkid;
|
||||
|
||||
errno = lwait.lksb.sb_status;
|
||||
DEBUGLOG("sync_lock: returning lkid %x\n", *lockid);
|
||||
if (lwait.lksb.sb_status)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sync_unlock(const char *resource /* UNUSED */, int lockid)
|
||||
{
|
||||
int status;
|
||||
struct lock_wait lwait;
|
||||
|
||||
DEBUGLOG("sync_unlock: '%s' lkid:%x\n", resource, lockid);
|
||||
|
||||
pthread_cond_init(&lwait.cond, NULL);
|
||||
pthread_mutex_init(&lwait.mutex, NULL);
|
||||
pthread_mutex_lock(&lwait.mutex);
|
||||
|
||||
status = dlm_ls_unlock(lockspace, lockid, 0, &lwait.lksb, &lwait);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/* Wait for it to complete */
|
||||
pthread_cond_wait(&lwait.cond, &lwait.mutex);
|
||||
pthread_mutex_unlock(&lwait.mutex);
|
||||
|
||||
errno = lwait.lksb.sb_status;
|
||||
if (lwait.lksb.sb_status != EUNLOCK)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
|
||||
}
|
||||
285
daemons/clvmd/clvmd-command.c
Normal file
285
daemons/clvmd/clvmd-command.c
Normal file
@@ -0,0 +1,285 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
CLVMD Cluster LVM daemon command processor.
|
||||
|
||||
To add commands to the daemon simply add a processor in do_command and return
|
||||
and messages back in buf and the length in *retlen. The initial value of
|
||||
buflen is the maximum size of the buffer. if buf is not large enough then it
|
||||
may be reallocated by the functions in here to a suitable size bearing in
|
||||
mind that anything larger than the passed-in size will have to be returned
|
||||
using the system LV and so performance will suffer.
|
||||
|
||||
The status return will be negated and passed back to the originating node.
|
||||
|
||||
pre- and post- command routines are called only on the local node. The
|
||||
purpose is primarily to get and release locks, though the pre- routine should
|
||||
also do any other local setups required by the command (if any) and can
|
||||
return a failure code that prevents the command from being distributed around
|
||||
the cluster
|
||||
|
||||
The pre- and post- routines are run in their own thread so can block as long
|
||||
they like, do_command is run in the main clvmd thread so should not block for
|
||||
too long. If the pre-command returns an error code (!=0) then the command
|
||||
will not be propogated around the cluster but the post-command WILL be called
|
||||
|
||||
Also note that the pre and post routine are *always* called on the local
|
||||
node, even if the command to be executed was only requested to run on a
|
||||
remote node. It may peek inside the client structure to check the status of
|
||||
the command.
|
||||
|
||||
The clients of the daemon must, naturally, understand the return messages and
|
||||
codes.
|
||||
|
||||
Routines in here may only READ the values in the client structure passed in
|
||||
apart from client->private which they are free to do what they like with.
|
||||
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "list.h"
|
||||
#include "hash.h"
|
||||
#include "locking.h"
|
||||
#include "log.h"
|
||||
#include "lvm-functions.h"
|
||||
#include "clvmd-comms.h"
|
||||
#include "clvm.h"
|
||||
#include "clvmd.h"
|
||||
#include "libdlm.h"
|
||||
|
||||
/* This is where all the real work happens:
|
||||
NOTE: client will be NULL when this is executed on a remote node */
|
||||
int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
|
||||
char **buf, int buflen, int *retlen)
|
||||
{
|
||||
char *args = msg->node + strlen(msg->node) + 1;
|
||||
int arglen = msglen - sizeof(struct clvm_header) - strlen(msg->node);
|
||||
int status = 0;
|
||||
char *lockname;
|
||||
struct utsname nodeinfo;
|
||||
unsigned char lock_cmd;
|
||||
unsigned char lock_flags;
|
||||
|
||||
/* Do the command */
|
||||
switch (msg->cmd) {
|
||||
/* Just a test message */
|
||||
case CLVMD_CMD_TEST:
|
||||
if (arglen > buflen) {
|
||||
buflen = arglen + 200;
|
||||
*buf = realloc(*buf, buflen);
|
||||
}
|
||||
uname(&nodeinfo);
|
||||
*retlen = 1 + snprintf(*buf, buflen, "TEST from %s: %s v%s",
|
||||
nodeinfo.nodename, args,
|
||||
nodeinfo.release);
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_LOCK_VG:
|
||||
/* Check to see if the VG is in use by LVM1 */
|
||||
status = do_check_lvm1(&args[2]);
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_LOCK_LV:
|
||||
/* This is the biggie */
|
||||
lock_cmd = args[0];
|
||||
lock_flags = args[1];
|
||||
lockname = &args[2];
|
||||
status = do_lock_lv(lock_cmd, lock_flags, lockname);
|
||||
/* Replace EIO with something less scary */
|
||||
if (status == EIO) {
|
||||
*retlen =
|
||||
1 + snprintf(*buf, buflen,
|
||||
"Internal lvm error, check syslog");
|
||||
return EIO;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Won't get here because command is validated in pre_command */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check the status of the command and return the error text */
|
||||
if (status) {
|
||||
*retlen = 1 + snprintf(*buf, buflen, strerror(status));
|
||||
}
|
||||
|
||||
return status;
|
||||
|
||||
}
|
||||
|
||||
static int lock_vg(struct local_client *client)
|
||||
{
|
||||
struct hash_table *lock_hash;
|
||||
struct clvm_header *header =
|
||||
(struct clvm_header *) client->bits.localsock.cmd;
|
||||
unsigned char lock_cmd;
|
||||
unsigned char lock_flags;
|
||||
char *args = header->node + strlen(header->node) + 1;
|
||||
int lkid;
|
||||
int status = 0;
|
||||
char *lockname;
|
||||
|
||||
/* Keep a track of VG locks in our own hash table. In current
|
||||
practice there should only ever be more than two VGs locked
|
||||
if a user tries to merge lots of them at once */
|
||||
if (client->bits.localsock.private) {
|
||||
lock_hash = (struct hash_table *)client->bits.localsock.private;
|
||||
}
|
||||
else {
|
||||
lock_hash = hash_create(3);
|
||||
if (!lock_hash)
|
||||
return ENOMEM;
|
||||
client->bits.localsock.private = (void *)lock_hash;
|
||||
}
|
||||
|
||||
lock_cmd = args[0];
|
||||
lock_flags = args[1];
|
||||
lockname = &args[2];
|
||||
DEBUGLOG("doing PRE command LOCK_VG '%s' at %x (client=%p)\n", lockname, lock_cmd, client);
|
||||
|
||||
if (lock_cmd == LCK_UNLOCK) {
|
||||
|
||||
lkid = (int)(long)hash_lookup(lock_hash, lockname);
|
||||
if (lkid == 0)
|
||||
return EINVAL;
|
||||
|
||||
status = sync_unlock(lockname, lkid);
|
||||
if (status)
|
||||
status = errno;
|
||||
else
|
||||
hash_remove(lock_hash, lockname);
|
||||
}
|
||||
else {
|
||||
|
||||
status = sync_lock(lockname, (int)lock_cmd, (int)lock_flags, &lkid);
|
||||
if (status)
|
||||
status = errno;
|
||||
else
|
||||
hash_insert(lock_hash, lockname, (void *)lkid);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/* Pre-command is a good place to get locks that are needed only for the duration
|
||||
of the commands around the cluster (don't forget to free them in post-command),
|
||||
and to sanity check the command arguments */
|
||||
int do_pre_command(struct local_client *client)
|
||||
{
|
||||
struct clvm_header *header =
|
||||
(struct clvm_header *) client->bits.localsock.cmd;
|
||||
unsigned char lock_cmd;
|
||||
unsigned char lock_flags;
|
||||
char *args = header->node + strlen(header->node) + 1;
|
||||
int lockid;
|
||||
int status = 0;
|
||||
char *lockname;
|
||||
|
||||
switch (header->cmd) {
|
||||
case CLVMD_CMD_TEST:
|
||||
status = sync_lock("CLVMD_TEST", LKM_EXMODE, 0, &lockid);
|
||||
client->bits.localsock.private = (void *) lockid;
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_LOCK_VG:
|
||||
status = lock_vg(client);
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_LOCK_LV:
|
||||
lock_cmd = args[0];
|
||||
lock_flags = args[1];
|
||||
lockname = &args[2];
|
||||
status = pre_lock_lv(lock_cmd, lock_flags, lockname);
|
||||
break;
|
||||
|
||||
default:
|
||||
log_error("Unknown command %d received\n", header->cmd);
|
||||
status = EINVAL;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Note that the post-command routine is called even if the pre-command or the real command
|
||||
failed */
|
||||
int do_post_command(struct local_client *client)
|
||||
{
|
||||
struct clvm_header *header =
|
||||
(struct clvm_header *) client->bits.localsock.cmd;
|
||||
int status = 0;
|
||||
unsigned char lock_cmd;
|
||||
unsigned char lock_flags;
|
||||
char *args = header->node + strlen(header->node) + 1;
|
||||
char *lockname;
|
||||
|
||||
switch (header->cmd) {
|
||||
case CLVMD_CMD_TEST:
|
||||
status =
|
||||
sync_unlock("CLVMD_TEST", (int) (long) client->bits.localsock.private);
|
||||
client->bits.localsock.private = 0;
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_LOCK_VG:
|
||||
/* Nothing to do here */
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_LOCK_LV:
|
||||
lock_cmd = args[0];
|
||||
lock_flags = args[1];
|
||||
lockname = &args[2];
|
||||
status = post_lock_lv(lock_cmd, lock_flags, lockname);
|
||||
break;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/* Called when the client is about to be deleted */
|
||||
void cmd_client_cleanup(struct local_client *client)
|
||||
{
|
||||
if (client->bits.localsock.private) {
|
||||
|
||||
struct hash_node *v;
|
||||
struct hash_table *lock_hash =
|
||||
(struct hash_table *)client->bits.localsock.private;
|
||||
|
||||
hash_iterate(v, lock_hash) {
|
||||
int lkid = (int)(long)hash_get_data(lock_hash, v);
|
||||
|
||||
DEBUGLOG("cleanup: Unlocking lkid %x\n", lkid);
|
||||
sync_unlock("DUMMY", lkid);
|
||||
}
|
||||
|
||||
hash_destroy(lock_hash);
|
||||
client->bits.localsock.private = 0;
|
||||
}
|
||||
}
|
||||
55
daemons/clvmd/clvmd-comms.h
Normal file
55
daemons/clvmd/clvmd-comms.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Abstraction layer for clvmd cluster communications
|
||||
*/
|
||||
|
||||
#ifndef _CLVMD_COMMS_H
|
||||
#define _CLVMD_COMMS_H
|
||||
|
||||
struct local_client;
|
||||
|
||||
extern int cluster_send_message(void *buf, int msglen, char *csid,
|
||||
const char *errtext);
|
||||
extern int name_from_csid(char *csid, char *name);
|
||||
extern int csid_from_name(char *csid, char *name);
|
||||
extern int get_num_nodes(void);
|
||||
extern int cluster_fd_callback(struct local_client *fd, char *buf, int len,
|
||||
char *csid, struct local_client **new_client);
|
||||
extern int init_cluster(void);
|
||||
extern int get_main_cluster_fd(void); /* gets accept FD or cman cluster socket */
|
||||
extern int cluster_do_node_callback(struct local_client *client,
|
||||
void (*callback) (struct local_client *,
|
||||
char *csid, int node_up));
|
||||
extern int is_quorate(void);
|
||||
|
||||
extern void get_our_csid(char *csid);
|
||||
extern void add_up_node(char *csid);
|
||||
extern void cluster_closedown(void);
|
||||
|
||||
extern int sync_lock(const char *resource, int mode, int flags, int *lockid);
|
||||
extern int sync_unlock(const char *resource, int lockid);
|
||||
|
||||
#ifdef USE_GULM
|
||||
#include "tcp-comms.h"
|
||||
#else
|
||||
/* cman */
|
||||
#include "cnxman-socket.h"
|
||||
#define MAX_CSID_LEN 4
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
908
daemons/clvmd/clvmd-gulm.c
Normal file
908
daemons/clvmd/clvmd-gulm.c
Normal file
@@ -0,0 +1,908 @@
|
||||
/******************************************************************************
|
||||
*******************************************************************************
|
||||
**
|
||||
** Copyright (C) Sistina Software, Inc. 2002-2003 All rights reserved.
|
||||
**
|
||||
*******************************************************************************
|
||||
******************************************************************************/
|
||||
|
||||
/* This provides the interface between clvmd and gulm as the cluster
|
||||
* and lock manager.
|
||||
*
|
||||
* It also provides the "liblm" functions too as it's hard (and pointless)
|
||||
* to seperate them out when using gulm.
|
||||
*
|
||||
* What it does /not/ provide is the communications between clvmd daemons
|
||||
* on the cluster nodes. That is done in tcp-comms.c
|
||||
*/
|
||||
|
||||
|
||||
#include <pthread.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <utmpx.h>
|
||||
#include <syslog.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "ccs.h"
|
||||
#include "list.h"
|
||||
#include "locking.h"
|
||||
#include "log.h"
|
||||
#include "clvm.h"
|
||||
#include "clvmd-comms.h"
|
||||
#include "clvmd.h"
|
||||
#include "hash.h"
|
||||
#include "clvmd-gulm.h"
|
||||
#include "libgulm.h"
|
||||
#include "hash.h"
|
||||
|
||||
/* Hash list of nodes in the cluster */
|
||||
static struct hash_table *node_hash;
|
||||
|
||||
/* hash list of outstanding lock requests */
|
||||
static struct hash_table *lock_hash;
|
||||
|
||||
/* Copy of the current core state */
|
||||
static uint8_t current_corestate;
|
||||
|
||||
/* Number of active nodes */
|
||||
static int num_nodes;
|
||||
|
||||
static char *cluster_name;
|
||||
|
||||
static pthread_mutex_t lock_start_mutex;
|
||||
static volatile int lock_start_flag;
|
||||
|
||||
struct node_info
|
||||
{
|
||||
enum {NODE_UNKNOWN, NODE_DOWN, NODE_UP, NODE_CLVMD} state;
|
||||
char name[MAX_CLUSTER_MEMBER_NAME_LEN];
|
||||
};
|
||||
|
||||
struct lock_wait
|
||||
{
|
||||
pthread_cond_t cond;
|
||||
pthread_mutex_t mutex;
|
||||
int status;
|
||||
};
|
||||
|
||||
/* Forward */
|
||||
static int read_from_core_sock(struct local_client *client, char *buf, int len, char *csid,
|
||||
struct local_client **new_client);
|
||||
static int read_from_lock_sock(struct local_client *client, char *buf, int len, char *csid,
|
||||
struct local_client **new_client);
|
||||
static int get_all_cluster_nodes(void);
|
||||
|
||||
/* In tcp-comms.c */
|
||||
extern struct hash_table *sock_hash;
|
||||
|
||||
static int add_internal_client(int fd, fd_callback_t callback)
|
||||
{
|
||||
struct local_client *client;
|
||||
|
||||
DEBUGLOG("Add_internal_client, fd = %d\n", fd);
|
||||
|
||||
/* Add a GULM file descriptor it to the main loop */
|
||||
client = malloc(sizeof(struct local_client));
|
||||
if (!client)
|
||||
{
|
||||
DEBUGLOG("malloc failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(client, 0, sizeof(struct local_client));
|
||||
client->fd = fd;
|
||||
client->type = CLUSTER_INTERNAL;
|
||||
client->callback = callback;
|
||||
add_client(client);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Gulm library handle */
|
||||
static gulm_interface_p gulm_if;
|
||||
static lg_core_callbacks_t core_callbacks;
|
||||
static lg_lockspace_callbacks_t lock_callbacks;
|
||||
|
||||
static void badsig_handler(int sig)
|
||||
{
|
||||
DEBUGLOG("got sig %d\n", sig);
|
||||
cluster_closedown();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static void sighup_handler(int sig)
|
||||
{
|
||||
DEBUGLOG("got SIGHUP\n");
|
||||
|
||||
/* Re-read CCS node list */
|
||||
get_all_cluster_nodes();
|
||||
}
|
||||
|
||||
int init_cluster()
|
||||
{
|
||||
int status;
|
||||
int ccs_h;
|
||||
int port = 0;
|
||||
char *portstr;
|
||||
|
||||
/* Get cluster name from CCS */
|
||||
ccs_h = ccs_force_connect(NULL, 0);
|
||||
if (ccs_h < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "Cannot login in to CCSD server\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ccs_get(ccs_h, "//cluster/@name", &cluster_name);
|
||||
DEBUGLOG("got cluster name %s\n", cluster_name);
|
||||
|
||||
if (!ccs_get(ccs_h, "//cluster/clvm/@port", &portstr))
|
||||
{
|
||||
port = atoi(portstr);
|
||||
free(portstr);
|
||||
DEBUGLOG("got port number %d\n", port);
|
||||
|
||||
if (port <= 0 && port >= 65536)
|
||||
port = 0;
|
||||
}
|
||||
|
||||
ccs_disconnect(ccs_h);
|
||||
|
||||
/* Block locking until we are logged in */
|
||||
pthread_mutex_init(&lock_start_mutex, NULL);
|
||||
pthread_mutex_lock(&lock_start_mutex);
|
||||
lock_start_flag = 1;
|
||||
|
||||
node_hash = hash_create(100);
|
||||
lock_hash = hash_create(10);
|
||||
|
||||
/* Get all nodes from CCS */
|
||||
if (get_all_cluster_nodes())
|
||||
return -1;
|
||||
|
||||
/* Initialise GULM library */
|
||||
status = lg_initialize(&gulm_if, cluster_name, "clvmd");
|
||||
if (status)
|
||||
{
|
||||
DEBUGLOG("lg_initialize failed: %d\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Connect to core - we are not "important" :-) */
|
||||
status = lg_core_login(gulm_if, 0);
|
||||
if (status)
|
||||
{
|
||||
DEBUGLOG("lg_core_login failed: %d\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Initialise the inter-node comms */
|
||||
status = init_comms(port);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/* Add core FD to the list */
|
||||
status = add_internal_client(lg_core_selector(gulm_if), read_from_core_sock);
|
||||
if (status)
|
||||
{
|
||||
DEBUGLOG("can't allocate client space\n");
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Connect to the lock server */
|
||||
if (lg_lock_login(gulm_if, "CLVM"))
|
||||
{
|
||||
syslog(LOG_ERR, "Cannot login in to LOCK server\n");
|
||||
DEBUGLOG("Cannot login in to LOCK server\n");
|
||||
exit(88);
|
||||
}
|
||||
|
||||
/* Add lockspace FD to the list */
|
||||
status = add_internal_client(lg_lock_selector(gulm_if), read_from_lock_sock);
|
||||
if (status)
|
||||
{
|
||||
DEBUGLOG("can't allocate client space\n");
|
||||
exit(status);
|
||||
}
|
||||
|
||||
/* Request a list of nodes, we can;t really do anything until
|
||||
this comes back */
|
||||
status = lg_core_nodelist(gulm_if);
|
||||
if (status)
|
||||
{
|
||||
DEBUGLOG("lg_core_nodelist failed: %d\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* So I can kill it without taking GULM down too */
|
||||
signal(SIGINT, badsig_handler);
|
||||
signal(SIGTERM, badsig_handler);
|
||||
|
||||
/* Re-read the node list on SIGHUP */
|
||||
signal(SIGHUP, sighup_handler);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cluster_closedown()
|
||||
{
|
||||
DEBUGLOG("cluster_closedown\n");
|
||||
lg_lock_logout(gulm_if);
|
||||
lg_core_logout(gulm_if);
|
||||
lg_release(gulm_if);
|
||||
}
|
||||
|
||||
/* Expire locks for a named node, or us */
|
||||
#define GIO_KEY_SIZE 46
|
||||
static void drop_expired_locks(char *nodename)
|
||||
{
|
||||
struct utsname nodeinfo;
|
||||
uint8_t mask[GIO_KEY_SIZE];
|
||||
|
||||
memset(mask, 0xff, GIO_KEY_SIZE);
|
||||
|
||||
if (!nodename)
|
||||
{
|
||||
uname(&nodeinfo);
|
||||
nodename = nodeinfo.nodename;
|
||||
}
|
||||
|
||||
if (lg_lock_drop_exp(gulm_if, nodename, mask, GIO_KEY_SIZE))
|
||||
{
|
||||
DEBUGLOG("Error calling lg_lock_drop_exp()\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int read_from_core_sock(struct local_client *client, char *buf, int len, char *csid,
|
||||
struct local_client **new_client)
|
||||
{
|
||||
int status;
|
||||
|
||||
*new_client = NULL;
|
||||
status = lg_core_handle_messages(gulm_if, &core_callbacks, NULL);
|
||||
return status<0 ? status : 1;
|
||||
}
|
||||
|
||||
static int read_from_lock_sock(struct local_client *client, char *buf, int len, char *csid,
|
||||
struct local_client **new_client)
|
||||
{
|
||||
int status;
|
||||
|
||||
*new_client = NULL;
|
||||
status = lg_lock_handle_messages(gulm_if, &lock_callbacks, NULL);
|
||||
return status<0 ? status : 1;
|
||||
}
|
||||
|
||||
|
||||
/* CORE callback routines */
|
||||
static int core_login_reply(void *misc, uint64_t gen, uint32_t error, uint32_t rank, uint8_t corestate)
|
||||
{
|
||||
DEBUGLOG("CORE Got a Login reply. gen:%lld err:%d rank:%d corestate:%d\n",
|
||||
gen, error, rank, corestate);
|
||||
|
||||
if (error)
|
||||
exit(error);
|
||||
|
||||
current_corestate = corestate;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void set_node_state(struct node_info *ninfo, char *csid, uint8_t nodestate)
|
||||
{
|
||||
if (nodestate == lg_core_Logged_in)
|
||||
{
|
||||
/* Don't clobber NODE_CLVMD state */
|
||||
if (ninfo->state != NODE_CLVMD)
|
||||
{
|
||||
if (ninfo->state == NODE_UNKNOWN ||
|
||||
ninfo->state == NODE_DOWN)
|
||||
num_nodes++;
|
||||
|
||||
ninfo->state = NODE_UP;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nodestate == lg_core_Expired ||
|
||||
nodestate == lg_core_Fenced ||
|
||||
nodestate == lg_core_Logged_out)
|
||||
{
|
||||
if (ninfo->state != NODE_DOWN)
|
||||
num_nodes--;
|
||||
ninfo->state = NODE_DOWN;
|
||||
tcp_remove_client(csid);
|
||||
}
|
||||
}
|
||||
DEBUGLOG("set_node_state, '%s' state = %d, num_nodes=%d\n",
|
||||
ninfo->name, ninfo->state, num_nodes);
|
||||
}
|
||||
|
||||
static struct node_info *add_or_set_node(char *name, struct in6_addr *ip, uint8_t state)
|
||||
{
|
||||
struct node_info *ninfo;
|
||||
|
||||
ninfo = hash_lookup_binary(node_hash, (char *)ip, MAX_CSID_LEN);
|
||||
if (!ninfo)
|
||||
{
|
||||
/* If we can't find that node then re-read the config file in case it
|
||||
was added after we were started */
|
||||
DEBUGLOG("Node %s not found, re-reading config file\n", name);
|
||||
get_all_cluster_nodes();
|
||||
|
||||
/* Now try again */
|
||||
ninfo = hash_lookup_binary(node_hash, (char *)ip, MAX_CSID_LEN);
|
||||
if (!ninfo)
|
||||
{
|
||||
DEBUGLOG("Ignoring node %s, not part of the SAN cluster\n", name);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
set_node_state(ninfo, (char *)&ip, state);
|
||||
|
||||
return ninfo;
|
||||
}
|
||||
|
||||
static int core_nodelist(void *misc, lglcb_t type, char *name, struct in6_addr *ip, uint8_t state)
|
||||
{
|
||||
DEBUGLOG("CORE nodelist\n");
|
||||
|
||||
if (type == lglcb_start)
|
||||
{
|
||||
DEBUGLOG("Got Nodelist, start\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (type == lglcb_item)
|
||||
{
|
||||
DEBUGLOG("Got nodelist, item: %s, %#x\n", name, state);
|
||||
|
||||
add_or_set_node(name, ip, state);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (type == lglcb_stop)
|
||||
{
|
||||
char ourcsid[MAX_CSID_LEN];
|
||||
|
||||
DEBUGLOG("Got Nodelist, stop\n");
|
||||
clvmd_cluster_init_completed();
|
||||
|
||||
/* Mark ourself as up */
|
||||
get_our_csid(ourcsid);
|
||||
add_up_node(ourcsid);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUGLOG("Unknown lglcb_t %#x\n", type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int core_statechange(void *misc, uint8_t corestate, uint8_t quorate, struct in6_addr *masterip, char *mastername)
|
||||
{
|
||||
DEBUGLOG("CORE Got statechange corestate:%#x mastername:%s\n",
|
||||
corestate, mastername);
|
||||
|
||||
current_corestate = corestate;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int core_nodechange(void *misc, char *nodename, struct in6_addr *nodeip, uint8_t nodestate)
|
||||
{
|
||||
struct node_info *ninfo;
|
||||
|
||||
DEBUGLOG("CORE node change, name=%s, state = %d\n", nodename, nodestate);
|
||||
|
||||
/* If we don't get nodeip here, try a lookup by name */
|
||||
if (!nodeip)
|
||||
csid_from_name((char *)nodeip, nodename);
|
||||
if (!nodeip)
|
||||
return 0;
|
||||
|
||||
ninfo = add_or_set_node(nodename, nodeip, nodestate);
|
||||
if (!ninfo)
|
||||
return 0;
|
||||
|
||||
/* Check if we need to drop any expired locks */
|
||||
if (ninfo->state == NODE_DOWN)
|
||||
{
|
||||
drop_expired_locks(nodename);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int core_error(void *misc, uint32_t err)
|
||||
{
|
||||
DEBUGLOG("CORE error: %d\n", err);
|
||||
// Not sure what happens here
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* LOCK callback routines */
|
||||
static int lock_login_reply(void *misc, uint32_t error, uint8_t which)
|
||||
{
|
||||
DEBUGLOG("LOCK Got a Login reply. err:%d which:%d\n",
|
||||
error, which);
|
||||
|
||||
if (error)
|
||||
exit(error);
|
||||
|
||||
/* Drop any expired locks for us that might be hanging around */
|
||||
drop_expired_locks(NULL);
|
||||
|
||||
/* Enable locking operations in other threads */
|
||||
if (lock_start_flag)
|
||||
{
|
||||
lock_start_flag = 0;
|
||||
pthread_mutex_unlock(&lock_start_mutex);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lock_lock_state(void *misc, uint8_t *key, uint16_t keylen,
|
||||
uint64_t subid, uint64_t start, uint64_t stop,
|
||||
uint8_t state, uint32_t flags, uint32_t error,
|
||||
uint8_t *LVB, uint16_t LVBlen)
|
||||
{
|
||||
struct lock_wait *lwait;
|
||||
|
||||
DEBUGLOG("LOCK lock state: %s, error = %d\n", key, error);
|
||||
|
||||
lwait = hash_lookup(lock_hash, key);
|
||||
if (!lwait)
|
||||
{
|
||||
DEBUGLOG("Can't find hash entry for resource %s\n", key);
|
||||
return 0;
|
||||
}
|
||||
lwait->status = error;
|
||||
pthread_mutex_lock(&lwait->mutex);
|
||||
pthread_cond_signal(&lwait->cond);
|
||||
pthread_mutex_unlock(&lwait->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int lock_error(void *misc, uint32_t err)
|
||||
{
|
||||
DEBUGLOG("LOCK error: %d\n", err);
|
||||
// Not sure what happens here
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* CORE callbacks */
|
||||
static lg_core_callbacks_t core_callbacks = {
|
||||
.login_reply = core_login_reply,
|
||||
.nodelist = core_nodelist,
|
||||
.statechange = core_statechange,
|
||||
.nodechange = core_nodechange,
|
||||
.error = core_error,
|
||||
};
|
||||
|
||||
/* LOCK callbacks */
|
||||
static lg_lockspace_callbacks_t lock_callbacks = {
|
||||
.login_reply = lock_login_reply,
|
||||
.lock_state = lock_lock_state,
|
||||
.error = lock_error,
|
||||
};
|
||||
|
||||
/* Allow tcp-comms to loop round the list of active nodes */
|
||||
int get_next_node_csid(void **context, char *csid)
|
||||
{
|
||||
struct node_info *ninfo = NULL;
|
||||
|
||||
/* First node */
|
||||
if (!*context)
|
||||
{
|
||||
*context = hash_get_first(node_hash);
|
||||
}
|
||||
else
|
||||
{
|
||||
*context = hash_get_next(node_hash, *context);
|
||||
}
|
||||
if (*context)
|
||||
ninfo = hash_get_data(node_hash, *context);
|
||||
|
||||
/* Find a node that is UP */
|
||||
while (*context && ninfo->state == NODE_DOWN)
|
||||
{
|
||||
*context = hash_get_next(node_hash, *context);
|
||||
if (*context)
|
||||
{
|
||||
ninfo = hash_get_data(node_hash, *context);
|
||||
}
|
||||
}
|
||||
|
||||
if (!*context || ninfo->state == NODE_DOWN)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(csid, hash_get_key(node_hash, *context), MAX_CSID_LEN);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int name_from_csid(char *csid, char *name)
|
||||
{
|
||||
struct node_info *ninfo;
|
||||
|
||||
ninfo = hash_lookup_binary(node_hash, csid, MAX_CSID_LEN);
|
||||
if (!ninfo)
|
||||
{
|
||||
sprintf(name, "UNKNOWN %s", print_csid(csid));
|
||||
return -1;
|
||||
}
|
||||
|
||||
strcpy(name, ninfo->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int csid_from_name(char *csid, char *name)
|
||||
{
|
||||
struct hash_node *hn;
|
||||
struct node_info *ninfo;
|
||||
|
||||
hash_iterate(hn, node_hash)
|
||||
{
|
||||
ninfo = hash_get_data(node_hash, hn);
|
||||
if (strcmp(ninfo->name, name) == 0)
|
||||
{
|
||||
memcpy(csid, hash_get_key(node_hash, hn), MAX_CSID_LEN);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int get_num_nodes()
|
||||
{
|
||||
DEBUGLOG("num_nodes = %d\n", num_nodes);
|
||||
return num_nodes;
|
||||
}
|
||||
|
||||
/* Node is now known to be running a clvmd */
|
||||
void add_up_node(char *csid)
|
||||
{
|
||||
struct node_info *ninfo;
|
||||
|
||||
ninfo = hash_lookup_binary(node_hash, csid, MAX_CSID_LEN);
|
||||
if (!ninfo)
|
||||
return;
|
||||
|
||||
ninfo->state = NODE_CLVMD;
|
||||
return;
|
||||
|
||||
}
|
||||
/* Node is now known to be NOT running a clvmd */
|
||||
void add_down_node(char *csid)
|
||||
{
|
||||
struct node_info *ninfo;
|
||||
|
||||
ninfo = hash_lookup_binary(node_hash, csid, MAX_CSID_LEN);
|
||||
if (!ninfo)
|
||||
return;
|
||||
|
||||
/* Only set it to UP if it was previously known to be
|
||||
running clvmd - gulm may set it DOWN quite soon */
|
||||
if (ninfo->state == NODE_CLVMD)
|
||||
ninfo->state = NODE_UP;
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
/* Call a callback for each node, so the caller knows whether it's up or down */
|
||||
int cluster_do_node_callback(struct local_client *master_client,
|
||||
void (*callback)(struct local_client *, char *csid, int node_up))
|
||||
{
|
||||
struct hash_node *hn;
|
||||
struct node_info *ninfo;
|
||||
|
||||
hash_iterate(hn, node_hash)
|
||||
{
|
||||
char csid[MAX_CSID_LEN];
|
||||
struct local_client *client;
|
||||
|
||||
ninfo = hash_get_data(node_hash, hn);
|
||||
memcpy(csid, hash_get_key(node_hash, hn), MAX_CSID_LEN);
|
||||
|
||||
DEBUGLOG("down_callback. node %s, state = %d\n", ninfo->name, ninfo->state);
|
||||
|
||||
client = hash_lookup_binary(sock_hash, csid, MAX_CSID_LEN);
|
||||
if (client)
|
||||
callback(master_client, csid, ninfo->state == NODE_CLVMD);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Convert gulm error codes to unix errno numbers */
|
||||
static int gulm_to_errno(int gulm_ret)
|
||||
{
|
||||
switch (gulm_ret)
|
||||
{
|
||||
case lg_err_TryFailed:
|
||||
errno = EAGAIN;
|
||||
break;
|
||||
|
||||
case lg_err_AlreadyPend:
|
||||
errno = EBUSY;
|
||||
|
||||
/* More?? */
|
||||
default:
|
||||
errno = EINVAL;
|
||||
}
|
||||
|
||||
return gulm_ret ? -1 : 0;
|
||||
}
|
||||
|
||||
/* Real locking */
|
||||
static int _lock_resource(char *resource, int mode, int flags, int *lockid)
|
||||
{
|
||||
int status;
|
||||
struct lock_wait lwait;
|
||||
|
||||
/* Wait until the lock module is ready */
|
||||
if (lock_start_flag)
|
||||
{
|
||||
pthread_mutex_lock(&lock_start_mutex);
|
||||
pthread_mutex_unlock(&lock_start_mutex);
|
||||
}
|
||||
|
||||
pthread_cond_init(&lwait.cond, NULL);
|
||||
pthread_mutex_init(&lwait.mutex, NULL);
|
||||
pthread_mutex_lock(&lwait.mutex);
|
||||
|
||||
/* This needs to be converted from DLM/LVM2 value for GULM */
|
||||
if (flags == LCK_NONBLOCK) flags = lg_lock_flag_Try;
|
||||
|
||||
hash_insert(lock_hash, resource, &lwait);
|
||||
DEBUGLOG("lock_resource '%s', flags=%d, mode=%d\n", resource, flags, mode);
|
||||
|
||||
status = lg_lock_state_req(gulm_if, resource, strlen(resource)+1,
|
||||
0, 0, 0,
|
||||
mode, flags, NULL, 0);
|
||||
if (status)
|
||||
{
|
||||
DEBUGLOG("lg_lock_state returned %d\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Wait for it to complete */
|
||||
pthread_cond_wait(&lwait.cond, &lwait.mutex);
|
||||
pthread_mutex_unlock(&lwait.mutex);
|
||||
|
||||
hash_remove(lock_hash, resource);
|
||||
DEBUGLOG("lock-resource returning %d\n", lwait.status);
|
||||
|
||||
return gulm_to_errno(lwait.status);
|
||||
}
|
||||
|
||||
|
||||
static int _unlock_resource(char *resource, int lockid)
|
||||
{
|
||||
int status;
|
||||
struct lock_wait lwait;
|
||||
|
||||
pthread_cond_init(&lwait.cond, NULL);
|
||||
pthread_mutex_init(&lwait.mutex, NULL);
|
||||
pthread_mutex_lock(&lwait.mutex);
|
||||
|
||||
hash_insert(lock_hash, resource, &lwait);
|
||||
|
||||
DEBUGLOG("unlock_resource %s\n", resource);
|
||||
status = lg_lock_state_req(gulm_if, resource, strlen(resource)+1,
|
||||
0, 0, 0,
|
||||
lg_lock_state_Unlock, 0, NULL, 0);
|
||||
|
||||
if (status)
|
||||
{
|
||||
DEBUGLOG("lg_lock_state(unlock) returned %d\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Wait for it to complete */
|
||||
|
||||
pthread_cond_wait(&lwait.cond, &lwait.mutex);
|
||||
pthread_mutex_unlock(&lwait.mutex);
|
||||
|
||||
hash_remove(lock_hash, resource);
|
||||
|
||||
return gulm_to_errno(lwait.status);
|
||||
}
|
||||
|
||||
|
||||
/* These two locking functions MUST be called in a seperate thread from
|
||||
the clvmd main loop because they expect to be woken up by it.
|
||||
|
||||
These are abstractions around the real locking functions (above)
|
||||
as we need to emulate the DLM's EX/PW/CW interaction with GULM using
|
||||
two locks.
|
||||
To aid unlocking, we store the lock mode in the lockid (as GULM
|
||||
doesn't use this).
|
||||
*/
|
||||
int sync_lock(const char *resource, int mode, int flags, int *lockid)
|
||||
{
|
||||
int status;
|
||||
char lock1[strlen(resource)+3];
|
||||
char lock2[strlen(resource)+3];
|
||||
|
||||
snprintf(lock1, sizeof(lock1), "%s-1", resource);
|
||||
snprintf(lock2, sizeof(lock2), "%s-2", resource);
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case LCK_EXCL:
|
||||
status = _lock_resource(lock1, lg_lock_state_Exclusive, flags, lockid);
|
||||
if (status)
|
||||
goto out;
|
||||
|
||||
/* If we can't get this lock then bail out */
|
||||
status = _lock_resource(lock2, lg_lock_state_Exclusive, LCK_NONBLOCK, lockid);
|
||||
if (status == lg_err_TryFailed)
|
||||
{
|
||||
_unlock_resource(lock1, *lockid);
|
||||
status = -1;
|
||||
errno = EAGAIN;
|
||||
}
|
||||
break;
|
||||
|
||||
case LCK_READ:
|
||||
status = _lock_resource(lock1, lg_lock_state_Shared, flags, lockid);
|
||||
break;
|
||||
|
||||
case LCK_WRITE:
|
||||
status = _lock_resource(lock2, lg_lock_state_Exclusive, flags, lockid);
|
||||
break;
|
||||
|
||||
default:
|
||||
status = -1;
|
||||
errno = EINVAL;
|
||||
break;
|
||||
}
|
||||
out:
|
||||
*lockid = mode;
|
||||
return status;
|
||||
}
|
||||
|
||||
int sync_unlock(const char *resource, int lockid)
|
||||
{
|
||||
int status = 0;
|
||||
char lock1[strlen(resource)+3];
|
||||
char lock2[strlen(resource)+3];
|
||||
|
||||
snprintf(lock1, sizeof(lock1), "%s-1", resource);
|
||||
snprintf(lock2, sizeof(lock2), "%s-2", resource);
|
||||
|
||||
/* The held lock mode is in the lock id */
|
||||
assert(lockid == LCK_EXCL ||
|
||||
lockid == LCK_READ ||
|
||||
lockid == LCK_WRITE);
|
||||
|
||||
switch (lockid)
|
||||
{
|
||||
case LCK_EXCL:
|
||||
status = _unlock_resource(lock1, lockid);
|
||||
if (status)
|
||||
goto out;
|
||||
status = _unlock_resource(lock2, lockid);
|
||||
break;
|
||||
|
||||
case LCK_READ:
|
||||
status = _unlock_resource(lock1, lockid);
|
||||
break;
|
||||
|
||||
case LCK_WRITE:
|
||||
status = _unlock_resource(lock2, lockid);
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
return status;
|
||||
}
|
||||
|
||||
int is_quorate()
|
||||
{
|
||||
if (current_corestate == lg_core_Slave ||
|
||||
current_corestate == lg_core_Master ||
|
||||
current_corestate == lg_core_Client)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get all the cluster node names & IPs from CCS and
|
||||
add them to our node list so we know who to talk to.
|
||||
Called when we start up and if we get sent SIGHUP.
|
||||
*/
|
||||
static int get_all_cluster_nodes()
|
||||
{
|
||||
int ctree;
|
||||
char *nodename;
|
||||
int error;
|
||||
int i;
|
||||
|
||||
/* Open the config file */
|
||||
ctree = ccs_force_connect(NULL, 1);
|
||||
if (ctree < 0)
|
||||
{
|
||||
log_error("Error connecting to CCS");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i=1;;i++)
|
||||
{
|
||||
char nodekey[256];
|
||||
char nodeip[MAX_CSID_LEN];
|
||||
int clvmflag = 1;
|
||||
char *clvmflagstr;
|
||||
char key[256];
|
||||
|
||||
sprintf(nodekey, "//cluster/clusternodes/clusternode[%d]/@name", i);
|
||||
error = ccs_get(ctree, nodekey, &nodename);
|
||||
if (error)
|
||||
break;
|
||||
|
||||
sprintf(key, "//cluster/clusternodes/clusternode[@name=\"%s\"]/clvm", nodename);
|
||||
if (!ccs_get(ctree, key, &clvmflagstr))
|
||||
{
|
||||
clvmflag = atoi(clvmflagstr);
|
||||
free(clvmflagstr);
|
||||
}
|
||||
|
||||
DEBUGLOG("Got node %s from ccs(clvmflag = %d)\n", nodename, clvmflag);
|
||||
if ((get_ip_address(nodename, nodeip) == 0) && clvmflag)
|
||||
{
|
||||
struct node_info *ninfo;
|
||||
|
||||
/* If it's not in the list, then add it */
|
||||
ninfo = hash_lookup_binary(node_hash, nodeip, MAX_CSID_LEN);
|
||||
if (!ninfo)
|
||||
{
|
||||
ninfo = malloc(sizeof(struct node_info));
|
||||
if (!ninfo)
|
||||
{
|
||||
syslog(LOG_ERR, "Cannot alloc memory for node info\n");
|
||||
ccs_disconnect(ctree);
|
||||
return -1;
|
||||
}
|
||||
strcpy(ninfo->name, nodename);
|
||||
|
||||
ninfo->state = NODE_DOWN;
|
||||
hash_insert_binary(node_hash, nodeip, MAX_CSID_LEN, ninfo);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUGLOG("node %s has clvm disabled\n", nodename);
|
||||
}
|
||||
free(nodename);
|
||||
}
|
||||
|
||||
/* Finished with config file */
|
||||
ccs_disconnect(ctree);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
9
daemons/clvmd/clvmd-gulm.h
Normal file
9
daemons/clvmd/clvmd-gulm.h
Normal file
@@ -0,0 +1,9 @@
|
||||
|
||||
|
||||
|
||||
extern int get_next_node_csid(void **context, char *csid);
|
||||
extern void add_down_node(char *csid);
|
||||
extern int gulm_fd(void);
|
||||
extern int get_ip_address(char *node, char *addr);
|
||||
extern void tcp_remove_client(char *csid);
|
||||
extern int alloc_client(int fd, char *csid, struct local_client **new_client);
|
||||
1747
daemons/clvmd/clvmd.c
Normal file
1747
daemons/clvmd/clvmd.c
Normal file
File diff suppressed because it is too large
Load Diff
119
daemons/clvmd/clvmd.h
Normal file
119
daemons/clvmd/clvmd.h
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _CLVMD_H
|
||||
#define _CLVMD_H
|
||||
|
||||
#define CLVMD_MAJOR_VERSION 0
|
||||
#define CLVMD_MINOR_VERSION 2
|
||||
#define CLVMD_PATCH_VERSION 1
|
||||
|
||||
/* Name of the cluster LVM admin lock */
|
||||
#define ADMIN_LOCK_NAME "CLVMD_ADMIN"
|
||||
|
||||
/* Default time (in seconds) we will wait for all remote commands to execute
|
||||
before declaring them dead */
|
||||
#define DEFAULT_CMD_TIMEOUT 60
|
||||
|
||||
/* One of these for each reply we get from command execution on a node */
|
||||
struct node_reply {
|
||||
char node[MAX_CLUSTER_MEMBER_NAME_LEN];
|
||||
char *replymsg;
|
||||
int status;
|
||||
struct node_reply *next;
|
||||
};
|
||||
|
||||
/*
|
||||
* These exist for the use of local sockets only when we are
|
||||
* collecting responses from all cluster nodes
|
||||
*/
|
||||
struct localsock_bits {
|
||||
struct node_reply *replies;
|
||||
int num_replies;
|
||||
int expected_replies;
|
||||
time_t sent_time; /* So we can check for timeouts */
|
||||
int in_progress; /* Only execute one cmd at a time per client */
|
||||
int sent_out; /* Flag to indicate that a command was sent
|
||||
to remote nodes */
|
||||
void *private; /* Private area for command processor use */
|
||||
void *cmd; /* Whole command as passed down local socket */
|
||||
int cmd_len; /* Length of above */
|
||||
int pipe; /* Pipe to send PRE completion status down */
|
||||
int finished; /* Flag to tell subthread to exit */
|
||||
int all_success; /* Set to 0 if any node (or the pre_command)
|
||||
failed */
|
||||
struct local_client *pipe_client;
|
||||
pthread_t threadid;
|
||||
enum { PRE_COMMAND, POST_COMMAND, QUIT } state;
|
||||
pthread_mutex_t mutex; /* Main thread and worker synchronisation */
|
||||
pthread_cond_t cond;
|
||||
|
||||
pthread_mutex_t reply_mutex; /* Protect reply structure */
|
||||
};
|
||||
|
||||
/* Entries for PIPE clients */
|
||||
struct pipe_bits {
|
||||
struct local_client *client; /* Actual (localsock) client */
|
||||
pthread_t threadid; /* Our own copy of the thread id */
|
||||
};
|
||||
|
||||
/* Entries for Network socket clients */
|
||||
struct netsock_bits {
|
||||
void *private;
|
||||
int flags;
|
||||
};
|
||||
|
||||
typedef int (*fd_callback_t) (struct local_client * fd, char *buf, int len,
|
||||
char *csid, struct local_client ** new_client);
|
||||
|
||||
/* One of these for each fd we are listening on */
|
||||
struct local_client {
|
||||
int fd;
|
||||
enum { CLUSTER_MAIN_SOCK, CLUSTER_DATA_SOCK, LOCAL_RENDEZVOUS,
|
||||
LOCAL_SOCK, THREAD_PIPE, CLUSTER_INTERNAL } type;
|
||||
struct local_client *next;
|
||||
unsigned short xid;
|
||||
fd_callback_t callback;
|
||||
|
||||
union {
|
||||
struct localsock_bits localsock;
|
||||
struct pipe_bits pipe;
|
||||
struct netsock_bits net;
|
||||
} bits;
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DEBUGLOG(fmt, args...) fprintf(stderr, "CLVMD[%d]: %ld ", getpid(), time(NULL) ); fprintf(stderr, fmt, ## args)
|
||||
#else
|
||||
#define DEBUGLOG(fmt, args...)
|
||||
#endif
|
||||
|
||||
#ifndef max
|
||||
#define max(a,b) ((a)>(b)?(a):(b))
|
||||
#endif
|
||||
|
||||
/* The real command processor is in clvmd-command.c */
|
||||
extern int do_command(struct local_client *client, struct clvm_header *msg,
|
||||
int msglen, char **buf, int buflen, int *retlen);
|
||||
|
||||
/* Pre and post command routines are called only on the local node */
|
||||
extern int do_pre_command(struct local_client *client);
|
||||
extern int do_post_command(struct local_client *client);
|
||||
extern void cmd_client_cleanup(struct local_client *client);
|
||||
extern int add_client(struct local_client *new_client);
|
||||
|
||||
extern void clvmd_cluster_init_completed(void);
|
||||
extern void process_message(struct local_client *client, char *buf, int len, char *csid);
|
||||
#endif
|
||||
226
daemons/clvmd/cnxman-socket.h
Normal file
226
daemons/clvmd/cnxman-socket.h
Normal file
@@ -0,0 +1,226 @@
|
||||
/******************************************************************************
|
||||
*******************************************************************************
|
||||
**
|
||||
** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
|
||||
** Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
**
|
||||
** This copyrighted material is made available to anyone wishing to use,
|
||||
** modify, copy, or redistribute it subject to the terms and conditions
|
||||
** of the GNU General Public License v.2.
|
||||
**
|
||||
*******************************************************************************
|
||||
******************************************************************************/
|
||||
|
||||
/* CMAN socket interface header,
|
||||
may be include by user or kernel code */
|
||||
|
||||
#ifndef __CNXMAN_SOCKET_H
|
||||
#define __CNXMAN_SOCKET_H
|
||||
|
||||
/* A currently unused number. TIPC also uses this number and you're unlikely
|
||||
to be using both.
|
||||
*/
|
||||
#define AF_CLUSTER 30
|
||||
#define PF_CLUSTER AF_CLUSTER
|
||||
|
||||
/* Protocol(socket) types */
|
||||
#define CLPROTO_MASTER 2
|
||||
#define CLPROTO_CLIENT 3
|
||||
|
||||
/* ioctls -- should register these properly */
|
||||
#define SIOCCLUSTER_NOTIFY _IOW('x', 0x01, int)
|
||||
#define SIOCCLUSTER_REMOVENOTIFY _IO( 'x', 0x02)
|
||||
#define SIOCCLUSTER_GETMEMBERS _IOR('x', 0x03, struct cl_cluster_nodelist)
|
||||
#define SIOCCLUSTER_SETEXPECTED_VOTES _IOW('x', 0x04, int)
|
||||
#define SIOCCLUSTER_ISQUORATE _IO( 'x', 0x05)
|
||||
#define SIOCCLUSTER_ISLISTENING _IOW('x', 0x06, struct cl_listen_request)
|
||||
#define SIOCCLUSTER_GETALLMEMBERS _IOR('x', 0x07, struct cl_cluster_nodelist)
|
||||
#define SIOCCLUSTER_SET_VOTES _IOW('x', 0x08, int)
|
||||
#define SIOCCLUSTER_GET_VERSION _IOR('x', 0x09, struct cl_version)
|
||||
#define SIOCCLUSTER_SET_VERSION _IOW('x', 0x0a, struct cl_version)
|
||||
#define SIOCCLUSTER_ISACTIVE _IO( 'x', 0x0b)
|
||||
#define SIOCCLUSTER_KILLNODE _IOW('x', 0x0c, int)
|
||||
#define SIOCCLUSTER_GET_JOINCOUNT _IO( 'x', 0x0d)
|
||||
#define SIOCCLUSTER_SERVICE_REGISTER _IOW('x', 0x0e, char)
|
||||
#define SIOCCLUSTER_SERVICE_UNREGISTER _IO('x', 0x0f)
|
||||
#define SIOCCLUSTER_SERVICE_JOIN _IO( 'x', 0x10)
|
||||
#define SIOCCLUSTER_SERVICE_LEAVE _IO( 'x', 0x20)
|
||||
#define SIOCCLUSTER_SERVICE_SETSIGNAL _IOW('x', 0x30, int)
|
||||
#define SIOCCLUSTER_SERVICE_STARTDONE _IOW('x', 0x40, unsigned int)
|
||||
#define SIOCCLUSTER_SERVICE_GETEVENT _IOR('x', 0x50, struct cl_service_event)
|
||||
#define SIOCCLUSTER_SERVICE_GETMEMBERS _IOR('x', 0x60, struct cl_cluster_nodelist)
|
||||
#define SIOCCLUSTER_SERVICE_GLOBALID _IOR('x', 0x70, uint32_t)
|
||||
#define SIOCCLUSTER_SERVICE_SETLEVEL _IOR('x', 0x80, int)
|
||||
#define SIOCCLUSTER_GETNODE _IOWR('x', 0x90, struct cl_cluster_node)
|
||||
#define SIOCCLUSTER_BARRIER _IOW('x', 0x0a0, struct cl_barrier_info)
|
||||
|
||||
/* These were setsockopts */
|
||||
#define SIOCCLUSTER_PASS_SOCKET _IOW('x', 0x0b0, struct cl_passed_sock)
|
||||
#define SIOCCLUSTER_SET_NODENAME _IOW('x', 0x0b1, char *)
|
||||
#define SIOCCLUSTER_SET_NODEID _IOW('x', 0x0b2, int)
|
||||
#define SIOCCLUSTER_JOIN_CLUSTER _IOW('x', 0x0b3, struct cl_join_cluster_info)
|
||||
#define SIOCCLUSTER_LEAVE_CLUSTER _IOW('x', 0x0b4, int)
|
||||
|
||||
|
||||
/* Maximum size of a cluster message */
|
||||
#define MAX_CLUSTER_MESSAGE 1500
|
||||
#define MAX_CLUSTER_MEMBER_NAME_LEN 255
|
||||
#define MAX_BARRIER_NAME_LEN 33
|
||||
#define MAX_SA_ADDR_LEN 12
|
||||
#define MAX_CLUSTER_NAME_LEN 16
|
||||
|
||||
/* Well-known cluster port numbers */
|
||||
#define CLUSTER_PORT_MEMBERSHIP 1 /* Mustn't block during cluster
|
||||
* transitions! */
|
||||
#define CLUSTER_PORT_SERVICES 2
|
||||
#define CLUSTER_PORT_SYSMAN 10 /* Remote execution daemon */
|
||||
#define CLUSTER_PORT_CLVMD 11 /* Cluster LVM daemon */
|
||||
#define CLUSTER_PORT_SLM 12 /* LVM SLM (simple lock manager) */
|
||||
|
||||
/* Port numbers above this will be blocked when the cluster is inquorate or in
|
||||
* transition */
|
||||
#define HIGH_PROTECTED_PORT 9
|
||||
|
||||
/* Reasons for leaving the cluster */
|
||||
#define CLUSTER_LEAVEFLAG_DOWN 0 /* Normal shutdown */
|
||||
#define CLUSTER_LEAVEFLAG_KILLED 1
|
||||
#define CLUSTER_LEAVEFLAG_PANIC 2
|
||||
#define CLUSTER_LEAVEFLAG_REMOVED 3 /* This one can reduce quorum */
|
||||
#define CLUSTER_LEAVEFLAG_REJECTED 4 /* Not allowed into the cluster in the
|
||||
* first place */
|
||||
#define CLUSTER_LEAVEFLAG_INCONSISTENT 5 /* Our view of the cluster is
|
||||
* in a minority */
|
||||
#define CLUSTER_LEAVEFLAG_DEAD 6 /* Discovered to be dead */
|
||||
#define CLUSTER_LEAVEFLAG_FORCE 0x10 /* Forced by command-line */
|
||||
|
||||
/* OOB messages sent to a local socket */
|
||||
#define CLUSTER_OOB_MSG_PORTCLOSED 1
|
||||
#define CLUSTER_OOB_MSG_STATECHANGE 2
|
||||
#define CLUSTER_OOB_MSG_SERVICEEVENT 3
|
||||
|
||||
/* Sendmsg flags, these are above the normal sendmsg flags so they don't
|
||||
* interfere */
|
||||
#define MSG_NOACK 0x010000 /* Don't need an ACK for this message */
|
||||
#define MSG_QUEUE 0x020000 /* Queue the message for sending later */
|
||||
#define MSG_MULTICAST 0x080000 /* Message was sent to all nodes in the cluster
|
||||
*/
|
||||
#define MSG_ALLINT 0x100000 /* Send out of all interfaces */
|
||||
#define MSG_REPLYEXP 0x200000 /* Reply is expected */
|
||||
|
||||
typedef enum { NODESTATE_REMOTEMEMBER, NODESTATE_JOINING, NODESTATE_MEMBER,
|
||||
NODESTATE_DEAD } nodestate_t;
|
||||
|
||||
|
||||
struct sockaddr_cl {
|
||||
unsigned short scl_family;
|
||||
unsigned char scl_flags;
|
||||
unsigned char scl_port;
|
||||
int scl_nodeid;
|
||||
};
|
||||
|
||||
/*
|
||||
* This is how we pass the multicast & receive sockets into kernel space.
|
||||
*/
|
||||
struct cl_passed_sock {
|
||||
int fd; /* FD of master socket to do multicast on */
|
||||
int number; /* Socket number, to match up recvonly & bcast
|
||||
* sockets */
|
||||
int multicast; /* Is it multicast or receive ? */
|
||||
};
|
||||
|
||||
/* Cluster configuration info passed when we join the cluster */
|
||||
struct cl_join_cluster_info {
|
||||
unsigned char votes;
|
||||
unsigned int expected_votes;
|
||||
unsigned int two_node;
|
||||
unsigned int config_version;
|
||||
|
||||
char cluster_name[17];
|
||||
};
|
||||
|
||||
|
||||
/* This is the structure, per node, returned from the membership ioctl */
|
||||
struct cl_cluster_node {
|
||||
unsigned int size;
|
||||
unsigned int node_id;
|
||||
unsigned int us;
|
||||
unsigned int leave_reason;
|
||||
unsigned int incarnation;
|
||||
nodestate_t state;
|
||||
char name[MAX_CLUSTER_MEMBER_NAME_LEN];
|
||||
unsigned char votes;
|
||||
};
|
||||
|
||||
/* The struct passed to the membership ioctls */
|
||||
struct cl_cluster_nodelist {
|
||||
uint32_t max_members;
|
||||
struct cl_cluster_node *nodes;
|
||||
};
|
||||
|
||||
/* Structure passed to SIOCCLUSTER_ISLISTENING */
|
||||
struct cl_listen_request {
|
||||
unsigned char port;
|
||||
int nodeid;
|
||||
};
|
||||
|
||||
/* A Cluster PORTCLOSED message - received by a local user as an OOB message */
|
||||
struct cl_portclosed_oob {
|
||||
unsigned char cmd; /* CLUSTER_OOB_MSG_PORTCLOSED */
|
||||
unsigned char port;
|
||||
};
|
||||
|
||||
/* Get all version numbers or set the config version */
|
||||
struct cl_version {
|
||||
unsigned int major;
|
||||
unsigned int minor;
|
||||
unsigned int patch;
|
||||
unsigned int config;
|
||||
};
|
||||
|
||||
/* structure passed to barrier ioctls */
|
||||
struct cl_barrier_info {
|
||||
char cmd;
|
||||
char name[MAX_BARRIER_NAME_LEN];
|
||||
unsigned int flags;
|
||||
unsigned long arg;
|
||||
};
|
||||
|
||||
typedef enum { SERVICE_EVENT_STOP, SERVICE_EVENT_START, SERVICE_EVENT_FINISH,
|
||||
SERVICE_EVENT_LEAVEDONE } service_event_t;
|
||||
|
||||
typedef enum { SERVICE_START_FAILED, SERVICE_START_JOIN, SERVICE_START_LEAVE }
|
||||
service_start_t;
|
||||
|
||||
struct cl_service_event {
|
||||
service_event_t type;
|
||||
service_start_t start_type;
|
||||
unsigned int event_id;
|
||||
unsigned int last_stop;
|
||||
unsigned int last_start;
|
||||
unsigned int last_finish;
|
||||
unsigned int node_count;
|
||||
};
|
||||
|
||||
|
||||
/* Commands to the barrier ioctl */
|
||||
#define BARRIER_IOCTL_REGISTER 1
|
||||
#define BARRIER_IOCTL_CHANGE 2
|
||||
#define BARRIER_IOCTL_DELETE 3
|
||||
#define BARRIER_IOCTL_WAIT 4
|
||||
|
||||
/* Attributes of a barrier - bitmask */
|
||||
#define BARRIER_ATTR_AUTODELETE 1
|
||||
#define BARRIER_ATTR_MULTISTEP 2
|
||||
#define BARRIER_ATTR_MANUAL 4
|
||||
#define BARRIER_ATTR_ENABLED 8
|
||||
#define BARRIER_ATTR_CALLBACK 16
|
||||
|
||||
/* Attribute setting commands */
|
||||
#define BARRIER_SETATTR_AUTODELETE 1
|
||||
#define BARRIER_SETATTR_MULTISTEP 2
|
||||
#define BARRIER_SETATTR_ENABLED 3
|
||||
#define BARRIER_SETATTR_NODES 4
|
||||
#define BARRIER_SETATTR_CALLBACK 5
|
||||
#define BARRIER_SETATTR_TIMEOUT 6
|
||||
|
||||
#endif
|
||||
446
daemons/clvmd/libclvm.c
Normal file
446
daemons/clvmd/libclvm.c
Normal file
@@ -0,0 +1,446 @@
|
||||
/*
|
||||
* Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* library functions for Cluster LVM Daemon */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <syslog.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <search.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "clvm.h"
|
||||
#include "libclvm.h"
|
||||
|
||||
/* CLVM in hex! */
|
||||
#define LVM_SIGNATURE 0x434C564D
|
||||
|
||||
#define MAX_CLUSTER_MEMBER_NAME_LEN 255
|
||||
|
||||
/* NOTE: the LVMD uses the socket FD as the client ID, this means
|
||||
that any client that calls fork() will inherit the context of
|
||||
it's parent. */
|
||||
static int clvmd_sock = -1;
|
||||
|
||||
static int open_local_sock(void)
|
||||
{
|
||||
int local_socket;
|
||||
struct sockaddr_un sockaddr;
|
||||
|
||||
/* Open local socket */
|
||||
local_socket = socket(PF_UNIX, SOCK_STREAM, 0);
|
||||
if (local_socket < 0) {
|
||||
perror("Can't create local socket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fcntl(local_socket, F_SETFD, !FD_CLOEXEC);
|
||||
|
||||
strcpy(sockaddr.sun_path, CLVMD_SOCKNAME);
|
||||
sockaddr.sun_family = AF_UNIX;
|
||||
if (connect
|
||||
(local_socket, (struct sockaddr *) &sockaddr, sizeof(sockaddr))) {
|
||||
int saved_errno = errno;
|
||||
|
||||
close(local_socket);
|
||||
|
||||
errno = saved_errno;
|
||||
return -1;
|
||||
}
|
||||
return local_socket;
|
||||
}
|
||||
|
||||
/* Send a request and return the status */
|
||||
static int send_request(char *inbuf, int inlen, char **retbuf)
|
||||
{
|
||||
char outbuf[PIPE_BUF];
|
||||
struct clvm_header *outheader = (struct clvm_header *) outbuf;
|
||||
int len;
|
||||
int off;
|
||||
fd_set fds;
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(clvmd_sock, &fds);
|
||||
|
||||
/* Send it to CLVMD */
|
||||
if (write(clvmd_sock, inbuf, inlen) != inlen) {
|
||||
perror("Error writing to CLVMD");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Get the response */
|
||||
if ((len = read(clvmd_sock, outbuf, sizeof(struct clvm_header))) < 0) {
|
||||
perror("Error reading CLVMD");
|
||||
return -1;
|
||||
}
|
||||
if (len == 0) {
|
||||
fprintf(stderr, "EOF reading CLVMD");
|
||||
errno = ENOTCONN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Allocate buffer */
|
||||
*retbuf = malloc(len + outheader->arglen);
|
||||
if (!*retbuf) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Copy the header */
|
||||
memcpy(*retbuf, outbuf, len);
|
||||
outheader = (struct clvm_header *) *retbuf;
|
||||
|
||||
/* Read the returned values */
|
||||
off = 1; /* we've already read the first byte */
|
||||
|
||||
while (off < outheader->arglen && len > 0) {
|
||||
len = read(clvmd_sock, outheader->args + off, PIPE_BUF);
|
||||
if (len > 0)
|
||||
off += len;
|
||||
}
|
||||
|
||||
/* Was it an error ? */
|
||||
if (outheader->status < 0) {
|
||||
errno = -outheader->status;
|
||||
return -2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Build the structure header and parse-out wildcard node names */
|
||||
static void build_header(struct clvm_header *head, int cmd, const char *node,
|
||||
void *data, int len)
|
||||
{
|
||||
head->cmd = cmd;
|
||||
head->status = 0;
|
||||
head->flags = 0;
|
||||
head->clientid = 0;
|
||||
head->arglen = len;
|
||||
if (node) {
|
||||
/* Allow a couple of special node names:
|
||||
"*" for all nodes,
|
||||
"." for the local node only
|
||||
*/
|
||||
if (strcmp(node, "*") == 0) {
|
||||
head->node[0] = '\0';
|
||||
} else if (strcmp(node, ".") == 0) {
|
||||
head->node[0] = '\0';
|
||||
head->flags = CLVMD_FLAG_LOCAL;
|
||||
} else {
|
||||
strcpy(head->node, node);
|
||||
}
|
||||
} else {
|
||||
head->node[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/* Send a message to a(or all) node(s) in the cluster */
|
||||
int lvm_cluster_write(char cmd, char *node, void *data, int len)
|
||||
{
|
||||
char outbuf[sizeof(struct clvm_header) + len + strlen(node) + 1];
|
||||
char *retbuf = NULL;
|
||||
int status;
|
||||
struct clvm_header *head = (struct clvm_header *) outbuf;
|
||||
|
||||
if (clvmd_sock == -1)
|
||||
clvmd_sock = open_local_sock();
|
||||
if (clvmd_sock == -1)
|
||||
return -1;
|
||||
|
||||
build_header(head, cmd, node, data, len);
|
||||
memcpy(head->node + strlen(head->node) + 1, data, len);
|
||||
|
||||
status =
|
||||
send_request(outbuf,
|
||||
sizeof(struct clvm_header) + strlen(head->node) + len,
|
||||
&retbuf);
|
||||
if (retbuf)
|
||||
free(retbuf);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* API: Send a message to a(or all) node(s) in the cluster
|
||||
and wait for replies */
|
||||
int lvm_cluster_request(char cmd, const char *node, void *data, int len,
|
||||
lvm_response_t ** response, int *num)
|
||||
{
|
||||
char outbuf[sizeof(struct clvm_header) + len + strlen(node) + 1];
|
||||
int *outptr;
|
||||
char *inptr;
|
||||
char *retbuf = NULL;
|
||||
int status;
|
||||
int i;
|
||||
int num_responses = 0;
|
||||
struct clvm_header *head = (struct clvm_header *) outbuf;
|
||||
lvm_response_t *rarray;
|
||||
|
||||
*num = 0;
|
||||
|
||||
if (clvmd_sock == -1)
|
||||
clvmd_sock = open_local_sock();
|
||||
if (clvmd_sock == -1)
|
||||
return -1;
|
||||
|
||||
build_header(head, cmd, node, data, len);
|
||||
memcpy(head->node + strlen(head->node) + 1, data, len);
|
||||
|
||||
status =
|
||||
send_request(outbuf,
|
||||
sizeof(struct clvm_header) + strlen(head->node) + len,
|
||||
&retbuf);
|
||||
if (status == 0 || status == -2) {
|
||||
/* Count the number of responses we got */
|
||||
head = (struct clvm_header *) retbuf;
|
||||
inptr = head->args;
|
||||
while (inptr[0]) {
|
||||
num_responses++;
|
||||
inptr += strlen(inptr) + 1;
|
||||
inptr += sizeof(int);
|
||||
inptr += strlen(inptr) + 1;
|
||||
}
|
||||
|
||||
/* Allocate response array. With an extra pair of INTs on the front to sanity
|
||||
check the pointer when we are given it back to free */
|
||||
outptr =
|
||||
malloc(sizeof(lvm_response_t) * num_responses +
|
||||
sizeof(int) * 2);
|
||||
if (!outptr) {
|
||||
if (retbuf)
|
||||
free(retbuf);
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*response = (lvm_response_t *) (outptr + 2);
|
||||
outptr[0] = LVM_SIGNATURE;
|
||||
outptr[1] = num_responses;
|
||||
rarray = *response;
|
||||
|
||||
/* Unpack the response into an lvm_response_t array */
|
||||
inptr = head->args;
|
||||
i = 0;
|
||||
while (inptr[0]) {
|
||||
strcpy(rarray[i].node, inptr);
|
||||
inptr += strlen(inptr) + 1;
|
||||
|
||||
rarray[i].status = *(int *) inptr;
|
||||
inptr += sizeof(int);
|
||||
|
||||
rarray[i].response = malloc(strlen(inptr) + 1);
|
||||
if (rarray[i].response == NULL) {
|
||||
/* Free up everything else and return error */
|
||||
int j;
|
||||
for (j = 0; j < i; j++)
|
||||
free(rarray[i].response);
|
||||
free(outptr);
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
strcpy(rarray[i].response, inptr);
|
||||
rarray[i].len = strlen(inptr);
|
||||
inptr += strlen(inptr) + 1;
|
||||
i++;
|
||||
}
|
||||
*num = num_responses;
|
||||
*response = rarray;
|
||||
}
|
||||
|
||||
if (retbuf)
|
||||
free(retbuf);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* API: Free reply array */
|
||||
int lvm_cluster_free_request(lvm_response_t * response)
|
||||
{
|
||||
int *ptr = (int *) response - 2;
|
||||
int i;
|
||||
int num;
|
||||
|
||||
/* Check it's ours to free */
|
||||
if (response == NULL || *ptr != LVM_SIGNATURE) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
num = ptr[1];
|
||||
for (i = 0; i < num; i++) {
|
||||
free(response[i].response);
|
||||
}
|
||||
free(ptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* These are a "higher-level" API providing black-box lock/unlock
|
||||
functions for cluster LVM...maybe */
|
||||
|
||||
/* Set by lock(), used by unlock() */
|
||||
static int num_responses;
|
||||
static lvm_response_t *response;
|
||||
|
||||
int lvm_lock_for_cluster(char scope, char *name, int verbosity)
|
||||
{
|
||||
int status;
|
||||
int i;
|
||||
char *args;
|
||||
int len;
|
||||
|
||||
if (name) {
|
||||
len = strlen(name) + 2;
|
||||
args = alloca(len);
|
||||
strcpy(args + 1, name);
|
||||
} else {
|
||||
len = 2;
|
||||
args = alloca(len);
|
||||
args[1] = '\0';
|
||||
}
|
||||
args[0] = scope;
|
||||
|
||||
status = lvm_cluster_request(CLVMD_CMD_LOCK,
|
||||
"", args, len, &response, &num_responses);
|
||||
|
||||
/* If any nodes were down then display them and return an error */
|
||||
for (i = 0; i < num_responses; i++) {
|
||||
if (response[i].status == -EHOSTDOWN) {
|
||||
if (verbosity)
|
||||
fprintf(stderr,
|
||||
"clvmd not running on node %s\n",
|
||||
response[i].node);
|
||||
status = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* If there was an error then free the memory now as the caller won't
|
||||
want to do the unlock */
|
||||
if (status) {
|
||||
int saved_errno = errno;
|
||||
lvm_cluster_free_request(response);
|
||||
num_responses = 0;
|
||||
errno = saved_errno;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
int lvm_unlock_for_cluster(char scope, char *name, int verbosity)
|
||||
{
|
||||
int status;
|
||||
int i;
|
||||
int len;
|
||||
int failed;
|
||||
int num_unlock_responses;
|
||||
char *args;
|
||||
lvm_response_t *unlock_response;
|
||||
|
||||
/* We failed - this should not have been called */
|
||||
if (num_responses == 0)
|
||||
return 0;
|
||||
|
||||
if (name) {
|
||||
len = strlen(name) + 2;
|
||||
args = alloca(len);
|
||||
strcpy(args + 1, name);
|
||||
} else {
|
||||
len = 2;
|
||||
args = alloca(len);
|
||||
args[1] = '\0';
|
||||
}
|
||||
args[0] = scope;
|
||||
|
||||
/* See if it failed anywhere */
|
||||
failed = 0;
|
||||
for (i = 0; i < num_responses; i++) {
|
||||
if (response[i].status != 0)
|
||||
failed++;
|
||||
}
|
||||
|
||||
/* If it failed on any nodes then we only unlock on
|
||||
the nodes that succeeded */
|
||||
if (failed) {
|
||||
for (i = 0; i < num_responses; i++) {
|
||||
/* Unlock the ones that succeeded */
|
||||
if (response[i].status == 0) {
|
||||
status = lvm_cluster_request(CLVMD_CMD_UNLOCK,
|
||||
response[i].node,
|
||||
args, len,
|
||||
&unlock_response,
|
||||
&num_unlock_responses);
|
||||
if (status) {
|
||||
if (verbosity)
|
||||
fprintf(stderr,
|
||||
"cluster command to node %s failed: %s\n",
|
||||
response[i].node,
|
||||
strerror(errno));
|
||||
} else if (unlock_response[0].status != 0) {
|
||||
if (verbosity > 1)
|
||||
fprintf(stderr,
|
||||
"unlock on node %s failed: %s\n",
|
||||
response[i].node,
|
||||
strerror(unlock_response
|
||||
[0].status));
|
||||
}
|
||||
lvm_cluster_free_request(unlock_response);
|
||||
} else {
|
||||
if (verbosity)
|
||||
fprintf(stderr,
|
||||
"command on node %s failed: '%s' - will be left locked\n",
|
||||
response[i].node,
|
||||
strerror(response[i].status));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* All OK, we can do a full cluster unlock */
|
||||
status = lvm_cluster_request(CLVMD_CMD_UNLOCK,
|
||||
"",
|
||||
args, len,
|
||||
&unlock_response,
|
||||
&num_unlock_responses);
|
||||
if (status) {
|
||||
if (verbosity > 1)
|
||||
fprintf(stderr, "cluster command failed: %s\n",
|
||||
strerror(errno));
|
||||
} else {
|
||||
for (i = 0; i < num_unlock_responses; i++) {
|
||||
if (unlock_response[i].status != 0) {
|
||||
if (verbosity > 1)
|
||||
fprintf(stderr,
|
||||
"unlock on node %s failed: %s\n",
|
||||
response[i].node,
|
||||
strerror(unlock_response
|
||||
[0].status));
|
||||
}
|
||||
}
|
||||
}
|
||||
lvm_cluster_free_request(unlock_response);
|
||||
}
|
||||
lvm_cluster_free_request(response);
|
||||
|
||||
return 0;
|
||||
}
|
||||
36
daemons/clvmd/libclvm.h
Normal file
36
daemons/clvmd/libclvm.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LIBCLVM_H
|
||||
#define _LIBCLVM_H
|
||||
|
||||
typedef struct lvm_response {
|
||||
char node[255];
|
||||
char *response;
|
||||
int status;
|
||||
int len;
|
||||
|
||||
} lvm_response_t;
|
||||
|
||||
extern int lvm_cluster_request(char cmd, const char *node, void *data, int len,
|
||||
lvm_response_t ** response, int *num);
|
||||
extern int lvm_cluster_write(char cmd, char *node, void *data, int len);
|
||||
extern int lvm_cluster_free_request(lvm_response_t * response);
|
||||
|
||||
/* The "high-level" API */
|
||||
extern int lvm_lock_for_cluster(char scope, char *name, int verbosity);
|
||||
extern int lvm_unlock_for_cluster(char scope, char *name, int verbosity);
|
||||
|
||||
#endif
|
||||
463
daemons/clvmd/lvm-functions.c
Normal file
463
daemons/clvmd/lvm-functions.c
Normal file
@@ -0,0 +1,463 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <syslog.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "libdlm.h"
|
||||
#include "clvm.h"
|
||||
#include "clvmd-comms.h"
|
||||
#include "clvmd.h"
|
||||
#include "lvm-functions.h"
|
||||
|
||||
/* LVM2 headers */
|
||||
#include "toolcontext.h"
|
||||
#include "log.h"
|
||||
#include "activate.h"
|
||||
#include "hash.h"
|
||||
#include "locking.h"
|
||||
|
||||
static struct cmd_context *cmd = NULL;
|
||||
static struct hash_table *lv_hash = NULL;
|
||||
static pthread_mutex_t lv_hash_lock;
|
||||
|
||||
struct lv_info {
|
||||
int lock_id;
|
||||
int lock_mode;
|
||||
};
|
||||
|
||||
/* Return the mode a lock is currently held at (or -1 if not held) */
|
||||
static int get_current_lock(char *resource)
|
||||
{
|
||||
struct lv_info *lvi;
|
||||
|
||||
pthread_mutex_lock(&lv_hash_lock);
|
||||
lvi = hash_lookup(lv_hash, resource);
|
||||
pthread_mutex_unlock(&lv_hash_lock);
|
||||
if (lvi) {
|
||||
return lvi->lock_mode;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Called at shutdown to tidy the lockspace */
|
||||
void unlock_all()
|
||||
{
|
||||
struct hash_node *v;
|
||||
|
||||
pthread_mutex_lock(&lv_hash_lock);
|
||||
hash_iterate(v, lv_hash) {
|
||||
struct lv_info *lvi = hash_get_data(lv_hash, v);
|
||||
|
||||
sync_unlock(hash_get_key(lv_hash, v), lvi->lock_id);
|
||||
}
|
||||
pthread_mutex_unlock(&lv_hash_lock);
|
||||
}
|
||||
|
||||
/* Gets a real lock and keeps the info in the hash table */
|
||||
int hold_lock(char *resource, int mode, int flags)
|
||||
{
|
||||
int status;
|
||||
int saved_errno;
|
||||
struct lv_info *lvi;
|
||||
|
||||
flags &= LKF_NOQUEUE; /* Only LKF_NOQUEUE is valid here */
|
||||
|
||||
pthread_mutex_lock(&lv_hash_lock);
|
||||
lvi = hash_lookup(lv_hash, resource);
|
||||
pthread_mutex_unlock(&lv_hash_lock);
|
||||
if (lvi) {
|
||||
/* Already exists - convert it */
|
||||
status =
|
||||
sync_lock(resource, mode, LKF_CONVERT | flags,
|
||||
&lvi->lock_id);
|
||||
saved_errno = errno;
|
||||
if (!status)
|
||||
lvi->lock_mode = mode;
|
||||
|
||||
if (status) {
|
||||
DEBUGLOG("hold_lock. convert to %d failed: %s\n", mode,
|
||||
strerror(errno));
|
||||
}
|
||||
errno = saved_errno;
|
||||
} else {
|
||||
lvi = malloc(sizeof(struct lv_info));
|
||||
if (!lvi)
|
||||
return -1;
|
||||
|
||||
lvi->lock_mode = mode;
|
||||
status = sync_lock(resource, mode, flags, &lvi->lock_id);
|
||||
saved_errno = errno;
|
||||
if (status) {
|
||||
free(lvi);
|
||||
DEBUGLOG("hold_lock. lock at %d failed: %s\n", mode,
|
||||
strerror(errno));
|
||||
} else {
|
||||
pthread_mutex_lock(&lv_hash_lock);
|
||||
hash_insert(lv_hash, resource, lvi);
|
||||
pthread_mutex_unlock(&lv_hash_lock);
|
||||
}
|
||||
errno = saved_errno;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Unlock and remove it from the hash table */
|
||||
int hold_unlock(char *resource)
|
||||
{
|
||||
struct lv_info *lvi;
|
||||
int status;
|
||||
int saved_errno;
|
||||
|
||||
pthread_mutex_lock(&lv_hash_lock);
|
||||
lvi = hash_lookup(lv_hash, resource);
|
||||
pthread_mutex_unlock(&lv_hash_lock);
|
||||
if (!lvi) {
|
||||
DEBUGLOG("hold_unlock, lock not already held\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
status = sync_unlock(resource, lvi->lock_id);
|
||||
saved_errno = errno;
|
||||
if (!status) {
|
||||
pthread_mutex_lock(&lv_hash_lock);
|
||||
hash_remove(lv_hash, resource);
|
||||
pthread_mutex_unlock(&lv_hash_lock);
|
||||
free(lvi);
|
||||
} else {
|
||||
DEBUGLOG("hold_unlock. unlock failed(%d): %s\n", status,
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
errno = saved_errno;
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Watch the return codes here.
|
||||
liblvm API functions return 1(true) for success, 0(false) for failure and don't set errno.
|
||||
libdlm API functions return 0 for success, -1 for failure and do set errno.
|
||||
These functions here return 0 for success or >0 for failure (where the retcode is errno)
|
||||
*/
|
||||
|
||||
/* Activate LV exclusive or non-exclusive */
|
||||
static int do_activate_lv(char *resource, int mode)
|
||||
{
|
||||
int oldmode;
|
||||
int status;
|
||||
int activate_lv;
|
||||
struct lvinfo lvi;
|
||||
|
||||
/* Is it already open ? */
|
||||
oldmode = get_current_lock(resource);
|
||||
if (oldmode == mode) {
|
||||
return 0; /* Nothing to do */
|
||||
}
|
||||
|
||||
/* Does the config file want us to activate this LV ? */
|
||||
if (!lv_activation_filter(cmd, resource, &activate_lv))
|
||||
return EIO;
|
||||
|
||||
if (!activate_lv)
|
||||
return 0; /* Success, we did nothing! */
|
||||
|
||||
/* Do we need to activate exclusively? */
|
||||
if (activate_lv == 2)
|
||||
mode = LKM_EXMODE;
|
||||
|
||||
/* OK, try to get the lock */
|
||||
status = hold_lock(resource, mode, LKF_NOQUEUE);
|
||||
if (status)
|
||||
return errno;
|
||||
|
||||
/* If it's suspended then resume it */
|
||||
if (!lv_info_by_lvid(cmd, resource, &lvi))
|
||||
return EIO;
|
||||
|
||||
if (lvi.suspended)
|
||||
if (!lv_resume(cmd, resource))
|
||||
return EIO;
|
||||
|
||||
/* Now activate it */
|
||||
if (!lv_activate(cmd, resource))
|
||||
return EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Resume the LV if it was active */
|
||||
static int do_resume_lv(char *resource)
|
||||
{
|
||||
int oldmode;
|
||||
|
||||
/* Is it open ? */
|
||||
oldmode = get_current_lock(resource);
|
||||
if (oldmode == -1) {
|
||||
DEBUGLOG("do_deactivate_lock, lock not already held\n");
|
||||
return 0; /* We don't need to do anything */
|
||||
}
|
||||
|
||||
if (!lv_resume_if_active(cmd, resource))
|
||||
return EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Suspend the device if active */
|
||||
static int do_suspend_lv(char *resource)
|
||||
{
|
||||
int oldmode;
|
||||
struct lvinfo lvi;
|
||||
|
||||
/* Is it open ? */
|
||||
oldmode = get_current_lock(resource);
|
||||
if (oldmode == -1) {
|
||||
DEBUGLOG("do_suspend_lv, lock held at %d\n", oldmode);
|
||||
return 0; /* Not active, so it's OK */
|
||||
}
|
||||
|
||||
/* Only suspend it if it exists */
|
||||
if (!lv_info_by_lvid(cmd, resource, &lvi))
|
||||
return EIO;
|
||||
|
||||
if (lvi.exists) {
|
||||
if (!lv_suspend_if_active(cmd, resource)) {
|
||||
return EIO;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_deactivate_lv(char *resource)
|
||||
{
|
||||
int oldmode;
|
||||
int status;
|
||||
|
||||
/* Is it open ? */
|
||||
oldmode = get_current_lock(resource);
|
||||
if (oldmode == -1) {
|
||||
DEBUGLOG("do_deactivate_lock, lock not already held\n");
|
||||
return 0; /* We don't need to do anything */
|
||||
}
|
||||
|
||||
if (!lv_deactivate(cmd, resource))
|
||||
return EIO;
|
||||
|
||||
status = hold_unlock(resource);
|
||||
if (status)
|
||||
return errno;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This is the LOCK_LV part that happens on all nodes in the cluster -
|
||||
it is responsible for the interaction with device-mapper and LVM */
|
||||
int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
DEBUGLOG("do_lock_lv: resource '%s', cmd = 0x%x, flags = %d\n",
|
||||
resource, command, lock_flags);
|
||||
|
||||
if (!cmd->config_valid || config_files_changed(cmd)) {
|
||||
/* Reinitialise various settings inc. logging, filters */
|
||||
if (!refresh_toolcontext(cmd)) {
|
||||
log_error("Updated config file invalid. Aborting.");
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
switch (command) {
|
||||
case LCK_LV_EXCLUSIVE:
|
||||
status = do_activate_lv(resource, LKM_EXMODE);
|
||||
break;
|
||||
|
||||
case LCK_LV_SUSPEND:
|
||||
status = do_suspend_lv(resource);
|
||||
break;
|
||||
|
||||
case LCK_UNLOCK:
|
||||
case LCK_LV_RESUME: /* if active */
|
||||
status = do_resume_lv(resource);
|
||||
break;
|
||||
|
||||
case LCK_LV_ACTIVATE:
|
||||
status = do_activate_lv(resource, LKM_CRMODE);
|
||||
break;
|
||||
|
||||
case LCK_LV_DEACTIVATE:
|
||||
status = do_deactivate_lv(resource);
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUGLOG("Invalid LV command 0x%x\n", command);
|
||||
status = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
/* clean the pool for another command */
|
||||
pool_empty(cmd->mem);
|
||||
|
||||
DEBUGLOG("Command return is %d\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Functions to do on the local node only BEFORE the cluster-wide stuff above happens */
|
||||
int pre_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
|
||||
{
|
||||
/* Nearly all the stuff happens cluster-wide. Apart from SUSPEND. Here we get the
|
||||
lock out on this node (because we are the node modifying the metadata)
|
||||
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);
|
||||
|
||||
if (hold_lock(resource, LKM_PWMODE, LKF_NOQUEUE))
|
||||
return errno;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Functions to do on the local node only AFTER the cluster-wide stuff above happens */
|
||||
int post_lock_lv(unsigned char command, unsigned char lock_flags,
|
||||
char *resource)
|
||||
{
|
||||
/* Opposite of above, done on resume after a metadata update */
|
||||
if (command == LCK_LV_RESUME) {
|
||||
int oldmode;
|
||||
|
||||
DEBUGLOG
|
||||
("post_lock_lv: resource '%s', cmd = 0x%x, flags = %d\n",
|
||||
resource, command, lock_flags);
|
||||
|
||||
/* If the lock state is PW then restore it to what it was */
|
||||
oldmode = get_current_lock(resource);
|
||||
if (oldmode == LKM_PWMODE) {
|
||||
struct lvinfo lvi;
|
||||
|
||||
if (!lv_info_by_lvid(cmd, resource, &lvi))
|
||||
return EIO;
|
||||
|
||||
if (lvi.exists) {
|
||||
if (hold_lock(resource, LKM_CRMODE, 0))
|
||||
return errno;
|
||||
} else {
|
||||
if (hold_unlock(resource))
|
||||
return errno;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check if a VG is un use by LVM1 so we don't stomp on it */
|
||||
int do_check_lvm1(char *vgname)
|
||||
{
|
||||
int status;
|
||||
|
||||
status = check_lvm1_vg_inactive(cmd, vgname);
|
||||
|
||||
return status == 1 ? 0 : EBUSY;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ideally, clvmd should be started before any LVs are active
|
||||
* but this may not be the case...
|
||||
* I suppose this also comes in handy if clvmd crashes, not that it would!
|
||||
*/
|
||||
static void *get_initial_state()
|
||||
{
|
||||
char lv[64], vg[64], flags[25];
|
||||
char uuid[65];
|
||||
char line[255];
|
||||
FILE *lvs =
|
||||
popen
|
||||
("/sbin/lvm lvs --nolocking --noheadings -o vg_uuid,lv_uuid,lv_attr",
|
||||
"r");
|
||||
|
||||
if (!lvs)
|
||||
return NULL;
|
||||
|
||||
while (fgets(line, sizeof(line), lvs)) {
|
||||
if (sscanf(line, "%s %s %s\n", vg, lv, flags) == 3) {
|
||||
|
||||
/* States: s:suspended a:active S:dropped snapshot I:invalid snapshot */
|
||||
if (strlen(vg) == 38 && /* is is a valid UUID ? */
|
||||
(flags[4] == 'a' || flags[4] == 's')) { /* is it active or suspended? */
|
||||
/* Convert hyphen-separated UUIDs into one */
|
||||
memcpy(&uuid[0], &vg[0], 6);
|
||||
memcpy(&uuid[6], &vg[7], 4);
|
||||
memcpy(&uuid[10], &vg[12], 4);
|
||||
memcpy(&uuid[14], &vg[17], 4);
|
||||
memcpy(&uuid[18], &vg[22], 4);
|
||||
memcpy(&uuid[22], &vg[27], 4);
|
||||
memcpy(&uuid[26], &vg[32], 6);
|
||||
memcpy(&uuid[32], &lv[0], 6);
|
||||
memcpy(&uuid[38], &lv[7], 4);
|
||||
memcpy(&uuid[42], &lv[12], 4);
|
||||
memcpy(&uuid[46], &lv[17], 4);
|
||||
memcpy(&uuid[50], &lv[22], 4);
|
||||
memcpy(&uuid[54], &lv[27], 4);
|
||||
memcpy(&uuid[58], &lv[32], 6);
|
||||
uuid[64] = '\0';
|
||||
|
||||
DEBUGLOG("getting initial lock for %s\n", uuid);
|
||||
hold_lock(uuid, LKM_CRMODE, LKF_NOQUEUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(lvs);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void init_lvhash()
|
||||
{
|
||||
/* Create hash table for keeping LV locks & status */
|
||||
lv_hash = hash_create(100);
|
||||
pthread_mutex_init(&lv_hash_lock, NULL);
|
||||
}
|
||||
|
||||
/* Called to initialise the LVM context of the daemon */
|
||||
int init_lvm(void)
|
||||
{
|
||||
if (!(cmd = create_toolcontext(NULL))) {
|
||||
log_error("Failed to allocate command context");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Use LOG_DAEMON for syslog messages instead of LOG_USER */
|
||||
init_syslog(LOG_DAEMON);
|
||||
init_debug(_LOG_ERR);
|
||||
|
||||
get_initial_state();
|
||||
|
||||
return 1;
|
||||
}
|
||||
35
daemons/clvmd/lvm-functions.h
Normal file
35
daemons/clvmd/lvm-functions.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Functions in lvm-functions.c */
|
||||
|
||||
#ifndef _LVM_FUNCTIONS_H
|
||||
#define _LVM_FUNCTIONS_H
|
||||
|
||||
extern int pre_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
|
||||
char *resource);
|
||||
extern int do_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
|
||||
char *resource);
|
||||
extern int post_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
|
||||
char *resource);
|
||||
extern int do_check_lvm1(char *vgname);
|
||||
extern int init_lvm(void);
|
||||
extern void init_lvhash(void);
|
||||
|
||||
extern int hold_unlock(char *resource);
|
||||
extern int hold_lock(char *resource, int mode, int flags);
|
||||
extern void unlock_all(void);
|
||||
|
||||
#endif
|
||||
369
daemons/clvmd/system-lv.c
Normal file
369
daemons/clvmd/system-lv.c
Normal file
@@ -0,0 +1,369 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Routines dealing with the System LV */
|
||||
|
||||
#include <pthread.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <syslog.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <mntent.h>
|
||||
|
||||
#include "libdlm.h"
|
||||
#include "log.h"
|
||||
#include "list.h"
|
||||
#include "locking.h"
|
||||
#include "system-lv.h"
|
||||
#include "clvmd-comms.h"
|
||||
#ifdef HAVE_CCS
|
||||
#include "ccs.h"
|
||||
#endif
|
||||
|
||||
#define SYSTEM_LV_FILESYSTEM "ext2"
|
||||
#define SYSTEM_LV_MOUNTPOINT "/tmp/.clvmd-XXXXXX"
|
||||
|
||||
extern char *config_filename(void);
|
||||
|
||||
static char system_lv_name[PATH_MAX] = { '\0' };
|
||||
static char mount_point[PATH_MAX] = { '\0' };
|
||||
static int mounted = 0;
|
||||
static int mounted_rw = 0;
|
||||
static int lockid;
|
||||
static const char *lock_name = "CLVM_SYSTEM_LV";
|
||||
|
||||
/* Look in /proc/mounts or (as a last resort) /etc/mtab to
|
||||
see if the system-lv is mounted. If it is mounted and we
|
||||
think it's not then abort because we don't have the right
|
||||
lock status and we don't know what other processes are doing with it.
|
||||
|
||||
Returns 1 for mounted, 0 for not mounted so it matches the condition
|
||||
of the "mounted" static variable above.
|
||||
*/
|
||||
static int is_really_mounted(void)
|
||||
{
|
||||
FILE *mountfile;
|
||||
struct mntent *ment;
|
||||
|
||||
mountfile = setmntent("/proc/mounts", "r");
|
||||
if (!mountfile) {
|
||||
mountfile = setmntent("/etc/mtab", "r");
|
||||
if (!mountfile) {
|
||||
log_error("Unable to open /proc/mounts or /etc/mtab");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Look for system LV name in the file */
|
||||
do {
|
||||
ment = getmntent(mountfile);
|
||||
if (ment) {
|
||||
if (strcmp(ment->mnt_fsname, system_lv_name) == 0) {
|
||||
endmntent(mountfile);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (ment);
|
||||
|
||||
endmntent(mountfile);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get the system LV name from the config file */
|
||||
static int find_system_lv(void)
|
||||
{
|
||||
if (system_lv_name[0] == '\0') {
|
||||
#ifdef HAVE_CCS
|
||||
int error;
|
||||
ccs_node_t *ctree;
|
||||
|
||||
/* Read the cluster config file */
|
||||
/* Open the config file */
|
||||
error = open_ccs_file(&ctree, "clvm.ccs");
|
||||
if (error) {
|
||||
perror("reading config file");
|
||||
return -1;
|
||||
}
|
||||
|
||||
strcpy(system_lv_name, find_ccs_str(ctree,
|
||||
"cluster/systemlv", '/',
|
||||
"/dev/vg/system_lv"));
|
||||
|
||||
/* Finished with config file */
|
||||
close_ccs_file(ctree);
|
||||
#else
|
||||
if (getenv("CLVMD_SYSTEM_LV"))
|
||||
strcpy(system_lv_name, getenv("CLVMD_SYSTEM_LV"));
|
||||
else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* See if it has been mounted outside our control */
|
||||
if (is_really_mounted() != mounted) {
|
||||
log_error
|
||||
("The system LV state has been mounted/umounted outside the control of clvmd\n"
|
||||
"it cannot not be used for cluster communications until this is fixed.\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* No prizes */
|
||||
int system_lv_umount(void)
|
||||
{
|
||||
if (!mounted)
|
||||
return 0;
|
||||
|
||||
if (umount(mount_point) < 0) {
|
||||
log_error("umount of system LV (%s) failed: %m\n",
|
||||
system_lv_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sync_unlock(lock_name, lockid);
|
||||
mounted = 0;
|
||||
|
||||
/* Remove the mount point */
|
||||
rmdir(mount_point);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int system_lv_mount(int readwrite)
|
||||
{
|
||||
int status;
|
||||
int saved_errno;
|
||||
int fd;
|
||||
|
||||
if (find_system_lv()) {
|
||||
errno = EBUSY;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Is it already mounted suitably? */
|
||||
if (mounted) {
|
||||
if (!readwrite || (readwrite && mounted_rw)) {
|
||||
return 0;
|
||||
} else {
|
||||
/* Mounted RO and we need RW */
|
||||
if (system_lv_umount() < 0)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Randomize the mount point */
|
||||
strcpy(mount_point, SYSTEM_LV_MOUNTPOINT);
|
||||
fd = mkstemp(mount_point);
|
||||
if (fd < 0) {
|
||||
log_error("mkstemp for system LV mount point failed: %m\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Race condition here but there's no mkstemp for directories */
|
||||
close(fd);
|
||||
unlink(mount_point);
|
||||
mkdir(mount_point, 0600);
|
||||
|
||||
/* Make sure we have a system-lv lock */
|
||||
status =
|
||||
sync_lock(lock_name, (readwrite) ? LKM_EXMODE : LKM_CRMODE, 0,
|
||||
&lockid);
|
||||
if (status < 0)
|
||||
return -1;
|
||||
|
||||
/* Mount it */
|
||||
if (mount(system_lv_name, mount_point, SYSTEM_LV_FILESYSTEM,
|
||||
MS_MGC_VAL | MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_SYNCHRONOUS
|
||||
| (readwrite ? 0 : MS_RDONLY), NULL) < 0) {
|
||||
/* mount(2) returns EINVAL if the volume has no FS on it. So, if we want to
|
||||
write to it we try to make a filesystem in it and retry the mount */
|
||||
if (errno == EINVAL && readwrite) {
|
||||
char cmd[256];
|
||||
|
||||
log_error("Attempting mkfs on system LV device %s\n",
|
||||
system_lv_name);
|
||||
snprintf(cmd, sizeof(cmd), "/sbin/mkfs -t %s %s",
|
||||
SYSTEM_LV_FILESYSTEM, system_lv_name);
|
||||
system(cmd);
|
||||
|
||||
if (mount
|
||||
(system_lv_name, mount_point, SYSTEM_LV_FILESYSTEM,
|
||||
MS_MGC_VAL | MS_NOSUID | MS_NODEV | MS_NOEXEC |
|
||||
MS_SYNCHRONOUS | (readwrite ? 0 : MS_RDONLY),
|
||||
NULL) == 0)
|
||||
goto mounted;
|
||||
}
|
||||
|
||||
saved_errno = errno;
|
||||
log_error("mount of system LV (%s, %s, %s) failed: %m\n",
|
||||
system_lv_name, mount_point, SYSTEM_LV_FILESYSTEM);
|
||||
sync_unlock(lock_name, lockid);
|
||||
errno = saved_errno;
|
||||
return -1;
|
||||
}
|
||||
|
||||
mounted:
|
||||
/* Set the internal flags */
|
||||
mounted = 1;
|
||||
mounted_rw = readwrite;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Erase *all* files in the root directory of the system LV.
|
||||
This *MUST* be called with an appropriate lock held!
|
||||
The LV is left mounted RW because it is assumed that the
|
||||
caller wants to write something here after clearing some space */
|
||||
int system_lv_eraseall(void)
|
||||
{
|
||||
DIR *dir;
|
||||
struct dirent *ent;
|
||||
char fname[PATH_MAX];
|
||||
|
||||
/* Must be mounted R/W */
|
||||
system_lv_mount(1);
|
||||
|
||||
dir = opendir(mount_point);
|
||||
if (!dir)
|
||||
return -1;
|
||||
|
||||
while ((ent = readdir(dir))) {
|
||||
struct stat st;
|
||||
snprintf(fname, sizeof(fname), "%s/%s", mount_point,
|
||||
ent->d_name);
|
||||
|
||||
if (stat(fname, &st)) {
|
||||
if (S_ISREG(st.st_mode))
|
||||
unlink(fname);
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This is a "high-level" routine - it mounts the system LV, writes
|
||||
the data into a file named after this node and then umounts the LV
|
||||
again */
|
||||
int system_lv_write_data(char *data, ssize_t len)
|
||||
{
|
||||
struct utsname nodeinfo;
|
||||
char fname[PATH_MAX];
|
||||
int outfile;
|
||||
ssize_t thiswrite;
|
||||
ssize_t written;
|
||||
|
||||
if (system_lv_mount(1))
|
||||
return -1;
|
||||
|
||||
/* Build the file name we are goingto use. */
|
||||
uname(&nodeinfo);
|
||||
snprintf(fname, sizeof(fname), "%s/%s", mount_point, nodeinfo.nodename);
|
||||
|
||||
/* Open the file for output */
|
||||
outfile = open(fname, O_RDWR | O_CREAT | O_TRUNC, 0600);
|
||||
if (outfile < 0) {
|
||||
int saved_errno = errno;
|
||||
system_lv_umount();
|
||||
errno = saved_errno;
|
||||
return -1;
|
||||
}
|
||||
|
||||
written = 0;
|
||||
do {
|
||||
thiswrite = write(outfile, data + written, len - written);
|
||||
if (thiswrite > 0)
|
||||
written += thiswrite;
|
||||
|
||||
} while (written < len && thiswrite > 0);
|
||||
|
||||
close(outfile);
|
||||
|
||||
system_lv_umount();
|
||||
return (thiswrite < 0) ? -1 : 0;
|
||||
}
|
||||
|
||||
/* This is a "high-level" routine - it mounts the system LV, reads
|
||||
the data from a named file and then umounts the LV
|
||||
again */
|
||||
int system_lv_read_data(char *fname_base, char *data, ssize_t *len)
|
||||
{
|
||||
char fname[PATH_MAX];
|
||||
int outfile;
|
||||
struct stat st;
|
||||
ssize_t filesize;
|
||||
ssize_t thisread;
|
||||
ssize_t readbytes;
|
||||
|
||||
if (system_lv_mount(0))
|
||||
return -1;
|
||||
|
||||
/* Build the file name we are going to use. */
|
||||
snprintf(fname, sizeof(fname), "%s/%s", mount_point, fname_base);
|
||||
|
||||
/* Get the file size and stuff. Actually we only need the file size but
|
||||
this will also check that the file exists */
|
||||
if (stat(fname, &st) < 0) {
|
||||
int saved_errno = errno;
|
||||
|
||||
log_error("stat of file %s on system LV failed: %m\n", fname);
|
||||
system_lv_umount();
|
||||
errno = saved_errno;
|
||||
return -1;
|
||||
}
|
||||
filesize = st.st_size;
|
||||
|
||||
outfile = open(fname, O_RDONLY);
|
||||
if (outfile < 0) {
|
||||
int saved_errno = errno;
|
||||
|
||||
log_error("open of file %s on system LV failed: %m\n", fname);
|
||||
system_lv_umount();
|
||||
errno = saved_errno;
|
||||
return -1;
|
||||
}
|
||||
|
||||
readbytes = 0;
|
||||
do {
|
||||
thisread =
|
||||
read(outfile, data + readbytes, filesize - readbytes);
|
||||
if (thisread > 0)
|
||||
readbytes += thisread;
|
||||
|
||||
} while (readbytes < filesize && thisread > 0);
|
||||
|
||||
close(outfile);
|
||||
|
||||
system_lv_umount();
|
||||
|
||||
*len = readbytes;
|
||||
return (thisread < 0) ? -1 : 0;
|
||||
}
|
||||
30
daemons/clvmd/system-lv.h
Normal file
30
daemons/clvmd/system-lv.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _CLVM_SYSTEM_LV_H
|
||||
#define _CLVM_SYSTEM_LV_H
|
||||
|
||||
/* Prototypes for System-LV functions */
|
||||
|
||||
/* "low-level" functions */
|
||||
extern int system_lv_umount(void);
|
||||
extern int system_lv_mount(int readwrite);
|
||||
extern int system_lv_eraseall(void);
|
||||
|
||||
/* "high-level" functions */
|
||||
extern int system_lv_write_data(char *data, ssize_t len);
|
||||
extern int system_lv_read_data(char *fname_base, char *data, ssize_t *len);
|
||||
|
||||
#endif
|
||||
444
daemons/clvmd/tcp-comms.c
Normal file
444
daemons/clvmd/tcp-comms.c
Normal file
@@ -0,0 +1,444 @@
|
||||
/******************************************************************************
|
||||
*******************************************************************************
|
||||
**
|
||||
** Copyright (C) Sistina Software, Inc. 2002-2003 All rights reserved.
|
||||
**
|
||||
*******************************************************************************
|
||||
******************************************************************************/
|
||||
|
||||
/* This provides the inter-clvmd communications for a system without CMAN.
|
||||
There is a listening TCP socket which accepts new connections in the
|
||||
normal way.
|
||||
It can also make outgoing connnections to the other clvmd nodes.
|
||||
*/
|
||||
|
||||
|
||||
#include <pthread.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <syslog.h>
|
||||
#include <netdb.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "clvm.h"
|
||||
#include "clvmd-comms.h"
|
||||
#include "clvmd.h"
|
||||
#include "clvmd-gulm.h"
|
||||
#include "hash.h"
|
||||
|
||||
#define DEFAULT_TCP_PORT 21064
|
||||
|
||||
static int listen_fd = -1;
|
||||
static int tcp_port;
|
||||
struct hash_table *sock_hash;
|
||||
|
||||
static int get_our_ip_address(char *addr, int *family);
|
||||
static int read_from_tcpsock(struct local_client *fd, char *buf, int len, char *csid,
|
||||
struct local_client **new_client);
|
||||
|
||||
/* Called by init_cluster() to open up the listening socket */
|
||||
int init_comms(unsigned short port)
|
||||
{
|
||||
struct sockaddr_in6 addr;
|
||||
|
||||
sock_hash = hash_create(100);
|
||||
tcp_port = port ? port : DEFAULT_TCP_PORT;
|
||||
|
||||
listen_fd = socket(AF_INET6, SOCK_STREAM, 0);
|
||||
|
||||
if (listen_fd < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
int one = 1;
|
||||
setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(int));
|
||||
}
|
||||
|
||||
memset(&addr, 0, sizeof(addr)); // Bind to INADDR_ANY
|
||||
addr.sin6_family = AF_INET6;
|
||||
addr.sin6_port = htons(tcp_port);
|
||||
|
||||
if (bind(listen_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
|
||||
{
|
||||
DEBUGLOG("Can't bind to port: %s\n", strerror(errno));
|
||||
syslog(LOG_ERR, "Can't bind to port %d, is clvmd already running ?", tcp_port);
|
||||
close(listen_fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
listen(listen_fd, 5);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tcp_remove_client(char *csid)
|
||||
{
|
||||
struct local_client *client;
|
||||
DEBUGLOG("tcp_remove_client\n");
|
||||
|
||||
/* Don't actually close the socket here - that's the
|
||||
job of clvmd.c whch will do the job when it notices the
|
||||
other end has gone. We just need to remove the client(s) from
|
||||
the hash table so we don't try to use it for sending any more */
|
||||
client = hash_lookup_binary(sock_hash, csid, MAX_CSID_LEN);
|
||||
if (client)
|
||||
{
|
||||
hash_remove_binary(sock_hash, csid, MAX_CSID_LEN);
|
||||
}
|
||||
|
||||
/* Look for a mangled one too */
|
||||
csid[0] ^= 0x80;
|
||||
|
||||
client = hash_lookup_binary(sock_hash, csid, MAX_CSID_LEN);
|
||||
if (client)
|
||||
{
|
||||
hash_remove_binary(sock_hash, csid, MAX_CSID_LEN);
|
||||
}
|
||||
|
||||
/* Put it back as we found it */
|
||||
csid[0] ^= 0x80;
|
||||
}
|
||||
|
||||
int alloc_client(int fd, char *csid, struct local_client **new_client)
|
||||
{
|
||||
struct local_client *client;
|
||||
|
||||
DEBUGLOG("alloc_client %d csid = %s\n", fd, print_csid(csid));
|
||||
|
||||
/* Create a local_client and return it */
|
||||
client = malloc(sizeof(struct local_client));
|
||||
if (!client)
|
||||
{
|
||||
DEBUGLOG("malloc failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(client, 0, sizeof(struct local_client));
|
||||
client->fd = fd;
|
||||
client->type = CLUSTER_DATA_SOCK;
|
||||
client->callback = read_from_tcpsock;
|
||||
if (new_client)
|
||||
*new_client = client;
|
||||
|
||||
/* Add to our list of node sockets */
|
||||
if (hash_lookup_binary(sock_hash, csid, MAX_CSID_LEN))
|
||||
{
|
||||
DEBUGLOG("alloc_client mangling CSID for second connection\n");
|
||||
/* This is a duplicate connection but we can't close it because
|
||||
the other end may already have started sending.
|
||||
So, we mangle the IP address and keep it, all sending will
|
||||
go out of the main FD
|
||||
*/
|
||||
csid[0] ^= 0x80;
|
||||
client->bits.net.flags = 1; /* indicate mangled CSID */
|
||||
|
||||
/* If it still exists then kill the connection as we should only
|
||||
ever have one incoming connection from each node */
|
||||
if (hash_lookup_binary(sock_hash, csid, MAX_CSID_LEN))
|
||||
{
|
||||
DEBUGLOG("Multiple incoming connections from node\n");
|
||||
syslog(LOG_ERR, " Bogus incoming connection from %d.%d.%d.%d\n", csid[0],csid[1],csid[2],csid[3]);
|
||||
|
||||
free(client);
|
||||
errno = ECONNREFUSED;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
hash_insert_binary(sock_hash, csid, MAX_CSID_LEN, client);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_main_cluster_fd()
|
||||
{
|
||||
return listen_fd;
|
||||
}
|
||||
|
||||
|
||||
/* Read on main comms (listen) socket, accept it */
|
||||
int cluster_fd_callback(struct local_client *fd, char *buf, int len, char *csid,
|
||||
struct local_client **new_client)
|
||||
{
|
||||
int newfd;
|
||||
struct sockaddr_in6 addr;
|
||||
socklen_t addrlen = sizeof(addr);
|
||||
int status;
|
||||
char name[MAX_CLUSTER_MEMBER_NAME_LEN];
|
||||
|
||||
DEBUGLOG("cluster_fd_callback\n");
|
||||
*new_client = NULL;
|
||||
newfd = accept(listen_fd, (struct sockaddr *)&addr, &addrlen);
|
||||
|
||||
DEBUGLOG("cluster_fd_callback, newfd=%d (errno=%d)\n", newfd, errno);
|
||||
if (!newfd)
|
||||
{
|
||||
syslog(LOG_ERR, "error in accept: %m");
|
||||
errno = EAGAIN;
|
||||
return -1; /* Don't return an error or clvmd will close the listening FD */
|
||||
}
|
||||
|
||||
/* Check that the client is a member of the cluster
|
||||
and reject if not.
|
||||
*/
|
||||
if (name_from_csid((char *)&addr.sin6_addr, name) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "Got connect from non-cluster node %s\n",
|
||||
print_csid((char *)&addr.sin6_addr));
|
||||
DEBUGLOG("Got connect from non-cluster node %s\n",
|
||||
print_csid((char *)&addr.sin6_addr));
|
||||
close(newfd);
|
||||
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
status = alloc_client(newfd, (char *)&addr.sin6_addr, new_client);
|
||||
if (status)
|
||||
{
|
||||
DEBUGLOG("cluster_fd_callback, alloc_client failed, status = %d\n", status);
|
||||
close(newfd);
|
||||
/* See above... */
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
DEBUGLOG("cluster_fd_callback, returning %d, %p\n", newfd, *new_client);
|
||||
return newfd;
|
||||
}
|
||||
|
||||
|
||||
static int read_from_tcpsock(struct local_client *client, char *buf, int len, char *csid,
|
||||
struct local_client **new_client)
|
||||
{
|
||||
struct sockaddr_in6 addr;
|
||||
socklen_t slen = sizeof(addr);
|
||||
int status;
|
||||
|
||||
DEBUGLOG("read_from_tcpsock fd %d\n", client->fd);
|
||||
*new_client = NULL;
|
||||
|
||||
/* Get "csid" */
|
||||
getpeername(client->fd, (struct sockaddr *)&addr, &slen);
|
||||
memcpy(csid, &addr.sin6_addr, MAX_CSID_LEN);
|
||||
|
||||
status = read(client->fd, buf, len);
|
||||
|
||||
DEBUGLOG("read_from_tcpsock, status = %d(errno = %d)\n", status, errno);
|
||||
|
||||
/* Remove it from the hash table if there's an error, clvmd will
|
||||
remove the socket from its lists and free the client struct */
|
||||
if (status == 0 ||
|
||||
(status < 0 && errno != EAGAIN && errno != EINTR))
|
||||
{
|
||||
char remcsid[MAX_CSID_LEN];
|
||||
|
||||
memcpy(remcsid, csid, MAX_CSID_LEN);
|
||||
close(client->fd);
|
||||
|
||||
/* If the csid was mangled, then make sure we remove the right entry */
|
||||
if (client->bits.net.flags)
|
||||
remcsid[0] ^= 0x80;
|
||||
hash_remove_binary(sock_hash, remcsid, MAX_CSID_LEN);
|
||||
|
||||
/* Tell cluster manager layer */
|
||||
add_down_node(remcsid);
|
||||
}
|
||||
else {
|
||||
/* Send it back to clvmd */
|
||||
process_message(client, buf, len, csid);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static int connect_csid(char *csid, struct local_client **newclient)
|
||||
{
|
||||
int fd;
|
||||
struct sockaddr_in6 addr;
|
||||
int status;
|
||||
|
||||
DEBUGLOG("Connecting socket\n");
|
||||
fd = socket(PF_INET6, SOCK_STREAM, 0);
|
||||
|
||||
if (fd < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "Unable to create new socket: %m");
|
||||
return -1;
|
||||
}
|
||||
|
||||
addr.sin6_family = AF_INET6;
|
||||
memcpy(&addr.sin6_addr, csid, MAX_CSID_LEN);
|
||||
addr.sin6_port = htons(tcp_port);
|
||||
|
||||
DEBUGLOG("Connecting socket %d\n", fd);
|
||||
if (connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in6)) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "Unable to connect to remote node: %m");
|
||||
DEBUGLOG("Unable to connect to remote node: %s\n", strerror(errno));
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
status = alloc_client(fd, csid, newclient);
|
||||
if (status)
|
||||
close(fd);
|
||||
else
|
||||
add_client(*newclient);
|
||||
|
||||
/* If we can connect to it, it must be running a clvmd */
|
||||
add_up_node(csid);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Send a message to a known CSID */
|
||||
static int tcp_send_message(void *buf, int msglen, unsigned char *csid, const char *errtext)
|
||||
{
|
||||
int status;
|
||||
struct local_client *client;
|
||||
char ourcsid[MAX_CSID_LEN];
|
||||
|
||||
assert(csid);
|
||||
|
||||
DEBUGLOG("tcp_send_message, csid = %s, msglen = %d\n", print_csid(csid), msglen);
|
||||
|
||||
/* Don't connect to ourself */
|
||||
get_our_csid(ourcsid);
|
||||
if (memcmp(csid, ourcsid, MAX_CSID_LEN) == 0)
|
||||
return msglen;
|
||||
|
||||
client = hash_lookup_binary(sock_hash, csid, MAX_CSID_LEN);
|
||||
if (!client)
|
||||
{
|
||||
status = connect_csid(csid, &client);
|
||||
if (status)
|
||||
return -1;
|
||||
}
|
||||
DEBUGLOG("tcp_send_message, fd = %d\n", client->fd);
|
||||
|
||||
return write(client->fd, buf, msglen);
|
||||
}
|
||||
|
||||
|
||||
int cluster_send_message(void *buf, int msglen, char *csid, const char *errtext)
|
||||
{
|
||||
int status=0;
|
||||
|
||||
DEBUGLOG("cluster send message, csid = %p, msglen = %d\n", csid, msglen);
|
||||
|
||||
/* If csid is NULL then send to all known (not just connected) nodes */
|
||||
if (!csid)
|
||||
{
|
||||
void *context = NULL;
|
||||
char loop_csid[MAX_CSID_LEN];
|
||||
|
||||
/* Loop round all gulm-known nodes */
|
||||
while (get_next_node_csid(&context, loop_csid))
|
||||
{
|
||||
status = tcp_send_message(buf, msglen, loop_csid, errtext);
|
||||
if (status == 0 ||
|
||||
(status < 0 && (errno == EAGAIN || errno == EINTR)))
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
status = tcp_send_message(buf, msglen, csid, errtext);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/* To get our own IP address we get the locally bound address of the
|
||||
socket that's talking to GULM in the assumption(eek) that it will
|
||||
be on the "right" network in a multi-homed system */
|
||||
static int get_our_ip_address(char *addr, int *family)
|
||||
{
|
||||
struct utsname info;
|
||||
|
||||
uname(&info);
|
||||
get_ip_address(info.nodename, addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Public version of above for those that don't care what protocol
|
||||
we're using */
|
||||
void get_our_csid(char *csid)
|
||||
{
|
||||
static char our_csid[MAX_CSID_LEN];
|
||||
static int got_csid = 0;
|
||||
|
||||
if (!got_csid)
|
||||
{
|
||||
int family;
|
||||
|
||||
memset(our_csid, 0, sizeof(our_csid));
|
||||
if (get_our_ip_address(our_csid, &family))
|
||||
{
|
||||
got_csid = 1;
|
||||
}
|
||||
}
|
||||
memcpy(csid, our_csid, MAX_CSID_LEN);
|
||||
}
|
||||
|
||||
static void map_v4_to_v6(struct in_addr *ip4, struct in6_addr *ip6)
|
||||
{
|
||||
ip6->s6_addr32[0] = 0;
|
||||
ip6->s6_addr32[1] = 0;
|
||||
ip6->s6_addr32[2] = htonl(0xffff);
|
||||
ip6->s6_addr32[3] = ip4->s_addr;
|
||||
}
|
||||
|
||||
/* Get someone else's IP address from DNS */
|
||||
int get_ip_address(char *node, char *addr)
|
||||
{
|
||||
struct hostent *he;
|
||||
|
||||
memset(addr, 0, MAX_CSID_LEN);
|
||||
|
||||
// TODO: what do we do about multi-homed hosts ???
|
||||
// CCSs ip_interfaces solved this but some bugger removed it.
|
||||
|
||||
/* Try IPv6 first. The man page for gethostbyname implies that
|
||||
it will lookup ip6 & ip4 names, but it seems not to */
|
||||
he = gethostbyname2(node, AF_INET6);
|
||||
if (he)
|
||||
{
|
||||
memcpy(addr, he->h_addr_list[0],
|
||||
he->h_length);
|
||||
}
|
||||
else
|
||||
{
|
||||
he = gethostbyname2(node, AF_INET);
|
||||
if (!he)
|
||||
return -1;
|
||||
map_v4_to_v6((struct in_addr *)he->h_addr_list[0], (struct in6_addr *)addr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *print_csid(char *csid)
|
||||
{
|
||||
static char buf[128];
|
||||
int *icsid = (int *)csid;
|
||||
|
||||
sprintf(buf, "[%x.%x.%x.%x]",
|
||||
icsid[0],icsid[1],icsid[2],icsid[3]);
|
||||
|
||||
return buf;
|
||||
}
|
||||
8
daemons/clvmd/tcp-comms.h
Normal file
8
daemons/clvmd/tcp-comms.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#include <netinet/in.h>
|
||||
|
||||
#define MAX_CLUSTER_MESSAGE 1600
|
||||
#define MAX_CSID_LEN sizeof(struct in6_addr)
|
||||
#define MAX_CLUSTER_MEMBER_NAME_LEN 128
|
||||
|
||||
extern int init_comms(unsigned short);
|
||||
extern char *print_csid(char *);
|
||||
29
doc/Makefile.in
Normal file
29
doc/Makefile.in
Normal file
@@ -0,0 +1,29 @@
|
||||
#
|
||||
# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of the LVM2.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
CONFSRC=example.conf
|
||||
CONFDEST=lvm.conf
|
||||
|
||||
include $(top_srcdir)/make.tmpl
|
||||
|
||||
install:
|
||||
@if [ ! -e $(confdir)/$(CONFDEST) ]; then \
|
||||
echo "Installing $(CONFSRC) as $(confdir)/$(CONFDEST)"; \
|
||||
@INSTALL@ -D $(OWNER) $(GROUP) -m 644 $(CONFSRC) \
|
||||
$(confdir)/$(CONFDEST); \
|
||||
fi
|
||||
|
||||
@@ -27,8 +27,11 @@ devices {
|
||||
# the device will be accepted or rejected (ignored). Devices that
|
||||
# don't match any patterns are accepted.
|
||||
|
||||
# If using RAID md devices as physical volumes, you should
|
||||
# set up a filter here to reject the constituent devices.
|
||||
# Be careful if there there are symbolic links or multiple filesystem
|
||||
# entries for the same device as each name is checked separately against
|
||||
# the list of patterns. The effect is that if any name matches any 'a'
|
||||
# pattern, the device is accepted; otherwise if any name matches any 'r'
|
||||
# pattern it is rejected; otherwise it is accepted.
|
||||
|
||||
# Remember to run vgscan after you change this parameter to ensure
|
||||
# that the cache file gets regenerated (see below).
|
||||
@@ -57,10 +60,21 @@ devices {
|
||||
# You can turn off writing this cache file by setting this to 0.
|
||||
write_cache_state = 1
|
||||
|
||||
# An advanced setting.
|
||||
# Advanced settings.
|
||||
|
||||
# List of pairs of additional acceptable block device types found
|
||||
# in /proc/devices with maximum (non-zero) number of partitions.
|
||||
# types = [ "fd", 16 ]
|
||||
|
||||
# If sysfs is mounted (2.6 kernels) restrict device scanning to
|
||||
# the block devices it believes are valid.
|
||||
# 1 enables; 0 disables.
|
||||
sysfs_scan = 1
|
||||
|
||||
# By default, LVM2 will ignore devices used as components of
|
||||
# software RAID (md) devices by looking for md superblocks.
|
||||
# 1 enables; 0 disables.
|
||||
md_component_detection = 1
|
||||
}
|
||||
|
||||
# This section that allows you to configure the nature of the
|
||||
@@ -171,6 +185,16 @@ global {
|
||||
# setting this to 0 should suppress the error messages.
|
||||
activation = 1
|
||||
|
||||
# If we can't communicate with device-mapper, should we try running
|
||||
# the LVM1 tools?
|
||||
# This option only applies to 2.4 kernels and is provided to help you
|
||||
# switch between device-mapper kernels and LVM1 kernels.
|
||||
# The LVM1 tools need to be installed with .lvm1 suffices
|
||||
# e.g. vgscan.lvm1 and they will stop working after you start using
|
||||
# the new lvm2 on-disk metadata format.
|
||||
# The default value is set when the tools are built.
|
||||
# fallback_to_lvm1 = 0
|
||||
|
||||
# The default metadata format that commands should use - "lvm1" or "lvm2".
|
||||
# The command line override is -M1 or -M2.
|
||||
# Defaults to "lvm1" if compiled in, else "lvm2".
|
||||
@@ -215,6 +239,14 @@ activation {
|
||||
|
||||
# Nice value used while devices suspended
|
||||
process_priority = -18
|
||||
|
||||
# If volume_list is defined, each LV is only activated if there is a
|
||||
# match against the list.
|
||||
# "vgname" and "vgname/lvname" are matched exactly.
|
||||
# "@tag" matches any tag set in the LV or VG.
|
||||
# "@*" matches if any tag defined on the host is also set in the LV or VG
|
||||
#
|
||||
# volume_list = [ "vg1", "vg2/lvol1", "@tag1", "@*" ]
|
||||
}
|
||||
|
||||
|
||||
|
||||
47
doc/example_cmdlib.c
Normal file
47
doc/example_cmdlib.c
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lvm2cmd.h"
|
||||
|
||||
/* All output gets passed to this function line-by-line */
|
||||
void test_log_fn(int level, const char *file, int line, const char *format)
|
||||
{
|
||||
/* Extract and process output here rather than printing it */
|
||||
|
||||
if (level != 4)
|
||||
return;
|
||||
|
||||
printf("%s\n", format);
|
||||
return;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
void *handle;
|
||||
int r;
|
||||
|
||||
lvm2_log_fn(test_log_fn);
|
||||
|
||||
handle = lvm2_init();
|
||||
|
||||
lvm2_log_level(handle, 1);
|
||||
r = lvm2_run(handle, "vgs --noheadings vg1");
|
||||
|
||||
/* More commands here */
|
||||
|
||||
lvm2_exit(handle);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
165
doc/tagging.txt
Normal file
165
doc/tagging.txt
Normal file
@@ -0,0 +1,165 @@
|
||||
Tagging aims
|
||||
============
|
||||
1) Ability to attach an unordered list of tags to LVM metadata objects.
|
||||
2) Ability to add or remove tags easily.
|
||||
3) Ability to select LVM objects for processing according to presence/absence
|
||||
of specific tags.
|
||||
4) Ability to control through the config file which VGs/LVs are activated
|
||||
on different machines using names or tags.
|
||||
5) Ability to overlay settings from different config files e.g. override
|
||||
some settings in a global config file locally.
|
||||
|
||||
Clarifications
|
||||
==============
|
||||
1) Tag character set: A-Za-z0-9_+.-
|
||||
Can't start with hyphen & max length is 128 (NAME_LEN).
|
||||
2) LVM object types that can be tagged:
|
||||
VG, LV, LV segment
|
||||
PV - tags are stored in VG metadata so disappear when PV becomes orphaned
|
||||
Snapshots can't be tagged, but their origin may be.
|
||||
3) A tag can be used in place of any command line LVM object reference that
|
||||
accepts (a) a list of objects; or (b) a single object as long as the
|
||||
tag expands to a single object. This is not supported everywhere yet.
|
||||
Duplicate arguments in a list after argument expansion may get removed
|
||||
retaining the first copy of each argument.
|
||||
4) Wherever there may be ambiguity of argument type, a tag must be prefixed
|
||||
by '@'; elsewhere an '@' prefix is optional.
|
||||
5) LVM1 objects cannot be tagged, as the disk format doesn't support it.
|
||||
6) Tags can be added or removed with --addtag or --deltag.
|
||||
|
||||
Config file Extensions
|
||||
======================
|
||||
To define host tags in config file:
|
||||
|
||||
tags {
|
||||
# Set a tag with the hostname
|
||||
hosttags = 1
|
||||
|
||||
tag1 { }
|
||||
|
||||
tag2 {
|
||||
# If no exact match, tag is not set.
|
||||
host_list = [ "hostname", "dbase" ]
|
||||
}
|
||||
}
|
||||
|
||||
Activation config file example
|
||||
==============================
|
||||
activation {
|
||||
volume_list = [ "vg1/lvol0", "@database" ]
|
||||
}
|
||||
|
||||
Matches against vgname, vgname/lvname or @tag set in *metadata*.
|
||||
@* matches exactly against *any* tag set on the host.
|
||||
The VG or LV only gets activated if a metadata tag matches.
|
||||
The default if there is no match is not to activate.
|
||||
If volume_list is not present and any tags are defined on the host
|
||||
then it only activates if a host tag matches a metadata tag.
|
||||
If volume_list is not present and no tags are defined on the host
|
||||
then it does activate.
|
||||
|
||||
Multiple config files
|
||||
=====================
|
||||
(a) lvm.conf
|
||||
(b) lvm_<host_tag>.conf
|
||||
|
||||
At startup, load lvm.conf.
|
||||
Process tag settings.
|
||||
If any host tags were defined, load lvm_tag.conf for each tag, if present.
|
||||
|
||||
When searching for a specific config file entry, search order is (b)
|
||||
then (a), stopping at the first match.
|
||||
Within (b) use reverse order tags got set, so file for last tag set is
|
||||
searched first.
|
||||
New tags set in (b) *do* trigger additional config file loads.
|
||||
|
||||
Usage Examples
|
||||
==============
|
||||
1) Simple activation control via metadata with static config files
|
||||
|
||||
lvm.conf: (Identical on every machine - global settings)
|
||||
tags {
|
||||
hostname_tags = 1
|
||||
}
|
||||
|
||||
From any machine in the cluster, add db1 to the list of machines that
|
||||
activate vg1/lvol2:
|
||||
|
||||
lvchange --tag @db1 vg1/lvol2
|
||||
(followed by lvchange -ay to actually activate it)
|
||||
|
||||
|
||||
2) Multiple hosts.
|
||||
|
||||
Activate vg1 only on the database hosts, db1 and db2.
|
||||
Activate vg2 only on the fileserver host fs1.
|
||||
Activate nothing initially on the fileserver backup host fsb1, but be
|
||||
prepared for it to take over from fs1.
|
||||
|
||||
Option (i) - centralised admin, static configuration replicated between hosts
|
||||
# Add @database tag to vg1's metadata
|
||||
vgchange --tag @database vg1
|
||||
|
||||
# Add @fileserver tag to vg2's metadata
|
||||
vgchange --tag @fileserver vg2
|
||||
|
||||
lvm.conf: (Identical on every machine)
|
||||
tags {
|
||||
database {
|
||||
host_list = [ "db1", "db2" ]
|
||||
}
|
||||
fileserver {
|
||||
host_list = [ "fs1" ]
|
||||
}
|
||||
fileserverbackup {
|
||||
host_list = [ "fsb1" ]
|
||||
}
|
||||
}
|
||||
|
||||
activation {
|
||||
# Only activate if host has a tag that matches a metadata tag
|
||||
volume_list = [ "@*" ]
|
||||
}
|
||||
|
||||
In the event of the fileserver host going down, vg2 can be brought up
|
||||
on fsb1 by running *on any node* 'vgchange --tag @fileserverbackup vg2'
|
||||
followed by 'vgchange -ay vg2'
|
||||
|
||||
|
||||
Option (ii) - localised admin & configuation
|
||||
(i.e. each host holds *locally* which classes of volumes to activate)
|
||||
# Add @database tag to vg1's metadata
|
||||
vgchange --tag @database vg1
|
||||
|
||||
# Add @fileserver tag to vg2's metadata
|
||||
vgchange --tag @fileserver vg2
|
||||
|
||||
lvm.conf: (Identical on every machine - global settings)
|
||||
tags {
|
||||
hosttags = 1
|
||||
}
|
||||
|
||||
lvm_db1.conf: (only needs to be on db1 - could be symlink to lvm_db.conf)
|
||||
activation {
|
||||
volume_list = [ "@database" ]
|
||||
}
|
||||
|
||||
lvm_db2.conf: (only needs to be on db2 - could be symlink to lvm_db.conf)
|
||||
activation {
|
||||
volume_list = [ "@database" ]
|
||||
}
|
||||
|
||||
lvm_fs1.conf: (only needs to be on fs1 - could be symlink to lvm_fs.conf)
|
||||
activation {
|
||||
volume_list = [ "@fileserver" ]
|
||||
}
|
||||
|
||||
If fileserver goes down, to bring a spare machine fsb1 in as fileserver,
|
||||
create lvm_fsb1.conf on fsb1 (or symlink to lvm_fs.conf):
|
||||
|
||||
activation {
|
||||
volume_list = [ "@fileserver" ]
|
||||
}
|
||||
|
||||
and run 'vgchange -ay vg2' or 'vgchange -ay @fileserver'
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
../daemons/clvmd/clvm.h
|
||||
../lib/activate/activate.h
|
||||
../lib/activate/targets.h
|
||||
../lib/cache/lvmcache.h
|
||||
../lib/commands/errors.h
|
||||
../lib/commands/toolcontext.h
|
||||
@@ -9,29 +11,40 @@
|
||||
../lib/datastruct/hash.h
|
||||
../lib/datastruct/list.h
|
||||
../lib/datastruct/lvm-types.h
|
||||
../lib/datastruct/str_list.h
|
||||
../lib/device/dev-cache.h
|
||||
../lib/device/device.h
|
||||
../lib/display/display.h
|
||||
../lib/filters/filter-composite.h
|
||||
../lib/filters/filter-md.h
|
||||
../lib/filters/filter-persistent.h
|
||||
../lib/filters/filter-regex.h
|
||||
../lib/filters/filter-sysfs.h
|
||||
../lib/filters/filter.h
|
||||
../lib/format1/format1.h
|
||||
../lib/format1/lvm1-label.h
|
||||
../lib/format_pool/format_pool.h
|
||||
../lib/format_text/format-text.h
|
||||
../lib/format_text/text_export.h
|
||||
../lib/format_text/text_import.h
|
||||
../lib/label/label.h
|
||||
../lib/locking/locking.h
|
||||
../lib/log/log.h
|
||||
../lib/metadata/lv_alloc.h
|
||||
../lib/metadata/metadata.h
|
||||
../lib/metadata/segtype.h
|
||||
../lib/mm/dbg_malloc.h
|
||||
../lib/mm/memlock.h
|
||||
../lib/mm/pool.h
|
||||
../lib/mm/xlate.h
|
||||
../lib/misc/crc.h
|
||||
../lib/misc/intl.h
|
||||
../lib/misc/lib.h
|
||||
../lib/misc/lvm-file.h
|
||||
../lib/misc/lvm-string.h
|
||||
../lib/misc/selinux.h
|
||||
../lib/misc/sharedlib.h
|
||||
../lib/regex/matcher.h
|
||||
../lib/report/report.h
|
||||
../lib/uuid/uuid.h
|
||||
../po/pogen.h
|
||||
../tools/version.h
|
||||
|
||||
@@ -1,20 +1,16 @@
|
||||
#
|
||||
# Copyright (C) 2001 Sistina Software
|
||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This LVM library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Library General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2 of the License, or (at your option) any later version.
|
||||
# This file is part of the LVM2.
|
||||
#
|
||||
# This LVM library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Library General Public License for more details.
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU Library General Public
|
||||
# License along with this LVM library; if not, write to the Free
|
||||
# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
# MA 02111-1307, USA
|
||||
# You should have received a copy of the GNU 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
|
||||
|
||||
SHELL = /bin/sh
|
||||
|
||||
@@ -24,6 +20,8 @@ VPATH = @srcdir@
|
||||
|
||||
LN_S = @LN_S@
|
||||
|
||||
.PHONY: clean distclean all install pofile install_cluster
|
||||
|
||||
all: .symlinks_created
|
||||
|
||||
.symlinks_created: .symlinks
|
||||
@@ -35,9 +33,11 @@ distclean:
|
||||
find . -maxdepth 1 -type l -exec $(RM) \{\} \;
|
||||
$(RM) Makefile .include_symlinks .symlinks_created
|
||||
|
||||
pofile: all
|
||||
|
||||
clean:
|
||||
|
||||
install:
|
||||
|
||||
.PHONY: clean distclean all install
|
||||
install_cluster:
|
||||
|
||||
|
||||
@@ -1,8 +1,16 @@
|
||||
#
|
||||
# Copyright (C) 2001 Sistina Software (UK) Limited
|
||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is released under the GPL.
|
||||
# This file is part of the LVM2.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
@@ -12,7 +20,19 @@ ifeq ("@LVM1@", "shared")
|
||||
SUBDIRS = format1
|
||||
endif
|
||||
|
||||
SOURCES=\
|
||||
ifeq ("@POOL@", "shared")
|
||||
SUBDIRS += format_pool
|
||||
endif
|
||||
|
||||
ifeq ("@SNAPSHOTS@", "shared")
|
||||
SUBDIRS += snapshot
|
||||
endif
|
||||
|
||||
ifeq ("@MIRRORS@", "shared")
|
||||
SUBDIRS += mirror
|
||||
endif
|
||||
|
||||
SOURCES =\
|
||||
activate/activate.c \
|
||||
cache/lvmcache.c \
|
||||
commands/toolcontext.c \
|
||||
@@ -20,13 +40,18 @@ SOURCES=\
|
||||
datastruct/bitset.c \
|
||||
datastruct/btree.c \
|
||||
datastruct/hash.c \
|
||||
datastruct/str_list.c \
|
||||
device/dev-cache.c \
|
||||
device/dev-io.c \
|
||||
device/dev-md.c \
|
||||
device/device.c \
|
||||
display/display.c \
|
||||
error/errseg.c \
|
||||
filters/filter-composite.c \
|
||||
filters/filter-persistent.c \
|
||||
filters/filter-regex.c \
|
||||
filters/filter-sysfs.c \
|
||||
filters/filter-md.c \
|
||||
filters/filter.c \
|
||||
format_text/archive.c \
|
||||
format_text/export.c \
|
||||
@@ -34,6 +59,7 @@ SOURCES=\
|
||||
format_text/format-text.c \
|
||||
format_text/import.c \
|
||||
format_text/import_vsn1.c \
|
||||
format_text/tags.c \
|
||||
format_text/text_label.c \
|
||||
label/label.c \
|
||||
locking/file_locking.c \
|
||||
@@ -45,20 +71,24 @@ SOURCES=\
|
||||
metadata/metadata.c \
|
||||
metadata/mirror.c \
|
||||
metadata/pv_map.c \
|
||||
metadata/segtype.c \
|
||||
metadata/snapshot_manip.c \
|
||||
misc/crc.c \
|
||||
misc/lvm-file.c \
|
||||
misc/lvm-string.c \
|
||||
mm/dbg_malloc.c \
|
||||
mm/memlock.c \
|
||||
mm/pool.c \
|
||||
regex/matcher.c \
|
||||
regex/parse_rx.c \
|
||||
regex/ttree.c \
|
||||
report/report.c \
|
||||
uuid/uuid.c
|
||||
striped/striped.c \
|
||||
uuid/uuid.c \
|
||||
zero/zero.c
|
||||
|
||||
ifeq ("@LVM1@", "internal")
|
||||
SOURCES+=\
|
||||
SOURCES +=\
|
||||
format1/disk-rep.c \
|
||||
format1/format1.c \
|
||||
format1/import-export.c \
|
||||
@@ -68,29 +98,49 @@ ifeq ("@LVM1@", "internal")
|
||||
format1/vg_number.c
|
||||
endif
|
||||
|
||||
ifeq ("@DEBUG@", "yes")
|
||||
SOURCES+=\
|
||||
mm/dbg_malloc.c
|
||||
ifeq ("@POOL@", "internal")
|
||||
SOURCES +=\
|
||||
format_pool/disk_rep.c \
|
||||
format_pool/format_pool.c \
|
||||
format_pool/import_export.c \
|
||||
format_pool/pool_label.c
|
||||
endif
|
||||
|
||||
ifeq ("@CLUSTER@", "internal")
|
||||
SOURCES += locking/cluster_locking.c
|
||||
endif
|
||||
|
||||
ifeq ("@CLUSTER@", "shared")
|
||||
SUBDIRS += locking
|
||||
endif
|
||||
|
||||
ifeq ("@SNAPSHOTS@", "internal")
|
||||
SOURCES += snapshot/snapshot.c
|
||||
endif
|
||||
|
||||
ifeq ("@MIRRORS@", "internal")
|
||||
SOURCES += mirror/mirrored.c
|
||||
endif
|
||||
|
||||
ifeq ("@DEVMAPPER@", "yes")
|
||||
SOURCES+=\
|
||||
SOURCES +=\
|
||||
activate/dev_manager.c \
|
||||
activate/fs.c
|
||||
endif
|
||||
|
||||
ifeq ("@HAVE_LIBDL@", "yes")
|
||||
SOURCES+=\
|
||||
SOURCES +=\
|
||||
locking/external_locking.c \
|
||||
misc/sharedlib.c
|
||||
endif
|
||||
|
||||
TARGETS=liblvm.a
|
||||
ifeq ("@HAVE_SELINUX@", "yes")
|
||||
SOURCES += misc/selinux.c
|
||||
endif
|
||||
|
||||
include ../make.tmpl
|
||||
LIB_STATIC = liblvm.a
|
||||
|
||||
liblvm.a: $(OBJECTS)
|
||||
$(RM) $@
|
||||
$(AR) r $@ $(OBJECTS)
|
||||
$(RANLIB) $@
|
||||
$(SUBDIRS): $(LIB_STATIC)
|
||||
|
||||
include $(top_srcdir)/make.tmpl
|
||||
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -10,10 +19,13 @@
|
||||
#include "memlock.h"
|
||||
#include "display.h"
|
||||
#include "fs.h"
|
||||
#include "lvm-file.h"
|
||||
#include "lvm-string.h"
|
||||
#include "pool.h"
|
||||
#include "toolcontext.h"
|
||||
#include "dev_manager.h"
|
||||
#include "str_list.h"
|
||||
#include "config.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <fcntl.h>
|
||||
@@ -21,12 +33,34 @@
|
||||
|
||||
#define _skip(fmt, args...) log_very_verbose("Skipping: " fmt , ## args)
|
||||
|
||||
int lvm1_present(struct cmd_context *cmd)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
|
||||
if (lvm_snprintf(path, sizeof(path), "%s/lvm/global", cmd->proc_dir)
|
||||
< 0) {
|
||||
log_error("LVM1 proc global snprintf failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (path_exists(path))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef DEVMAPPER_SUPPORT
|
||||
void set_activation(int act)
|
||||
{
|
||||
if (act)
|
||||
static int warned = 0;
|
||||
|
||||
if (warned || !act)
|
||||
return;
|
||||
|
||||
log_error("Compiled without libdevmapper support. "
|
||||
"Can't enable activation.");
|
||||
|
||||
warned = 1;
|
||||
}
|
||||
int activation(void)
|
||||
{
|
||||
@@ -40,10 +74,19 @@ int driver_version(char *version, size_t size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int target_present(const char *target_name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int lv_info(const struct logical_volume *lv, struct lvinfo *info)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
|
||||
struct lvinfo *info)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int lv_snapshot_percent(struct logical_volume *lv, float *percent)
|
||||
{
|
||||
return 0;
|
||||
@@ -61,10 +104,18 @@ int lvs_in_vg_opened(struct volume_group *vg)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int lv_suspend(struct cmd_context *cmd, const char *lvid_s)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
int lv_resume(struct cmd_context *cmd, const char *lvid_s)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s)
|
||||
{
|
||||
return 1;
|
||||
@@ -73,10 +124,25 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s,
|
||||
int *activate_lv)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
int lv_activate(struct cmd_context *cmd, const char *lvid_s)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void activation_exit(void)
|
||||
{
|
||||
return;
|
||||
@@ -105,6 +171,86 @@ int activation(void)
|
||||
return _activation;
|
||||
}
|
||||
|
||||
static int _passes_activation_filter(struct cmd_context *cmd,
|
||||
struct logical_volume *lv)
|
||||
{
|
||||
const struct config_node *cn;
|
||||
struct config_value *cv;
|
||||
char *str;
|
||||
char path[PATH_MAX];
|
||||
|
||||
if (!(cn = find_config_node(cmd->cft->root, "activation/volume_list"))) {
|
||||
/* If no host tags defined, activate */
|
||||
if (list_empty(&cmd->tags))
|
||||
return 1;
|
||||
|
||||
/* If any host tag matches any LV or VG tag, activate */
|
||||
if (str_list_match_list(&cmd->tags, &lv->tags) ||
|
||||
str_list_match_list(&cmd->tags, &lv->vg->tags))
|
||||
return 1;
|
||||
|
||||
/* Don't activate */
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (cv = cn->v; cv; cv = cv->next) {
|
||||
if (cv->type != CFG_STRING) {
|
||||
log_error("Ignoring invalid string in config file "
|
||||
"activation/volume_list");
|
||||
continue;
|
||||
}
|
||||
str = cv->v.str;
|
||||
if (!*str) {
|
||||
log_error("Ignoring empty string in config file "
|
||||
"activation/volume_list");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Tag? */
|
||||
if (*str == '@') {
|
||||
str++;
|
||||
if (!*str) {
|
||||
log_error("Ignoring empty tag in config file "
|
||||
"activation/volume_list");
|
||||
continue;
|
||||
}
|
||||
/* If any host tag matches any LV or VG tag, activate */
|
||||
if (!strcmp(str, "*")) {
|
||||
if (str_list_match_list(&cmd->tags, &lv->tags)
|
||||
|| str_list_match_list(&cmd->tags,
|
||||
&lv->vg->tags))
|
||||
return 1;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
/* If supplied tag matches LV or VG tag, activate */
|
||||
if (str_list_match_item(&lv->tags, str) ||
|
||||
str_list_match_item(&lv->vg->tags, str))
|
||||
return 1;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
if (!index(str, '/')) {
|
||||
/* vgname supplied */
|
||||
if (!strcmp(str, lv->vg->name))
|
||||
return 1;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
/* vgname/lvname */
|
||||
if (lvm_snprintf(path, sizeof(path), "%s/%s", lv->vg->name,
|
||||
lv->name) < 0) {
|
||||
log_error("lvm_snprintf error from %s/%s", lv->vg->name,
|
||||
lv->name);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(path, str))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int library_version(char *version, size_t size)
|
||||
{
|
||||
if (!activation())
|
||||
@@ -143,10 +289,51 @@ int driver_version(char *version, size_t size)
|
||||
return r;
|
||||
}
|
||||
|
||||
int target_present(const char *target_name)
|
||||
{
|
||||
int r = 0;
|
||||
struct dm_task *dmt;
|
||||
struct dm_versions *target, *last_target;
|
||||
|
||||
if (!activation())
|
||||
return 0;
|
||||
|
||||
log_very_verbose("Getting target version for %s", target_name);
|
||||
if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dm_task_run(dmt)) {
|
||||
log_debug("Failed to get %s target version", target_name);
|
||||
/* Assume this was because LIST_VERSIONS isn't supported */
|
||||
return 1;
|
||||
}
|
||||
|
||||
target = dm_task_get_versions(dmt);
|
||||
|
||||
do {
|
||||
last_target = target;
|
||||
|
||||
if (!strcmp(target_name, target->name)) {
|
||||
r = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
target = (void *) target + target->next;
|
||||
} while (last_target != target);
|
||||
|
||||
out:
|
||||
dm_task_destroy(dmt);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns 1 if info structure populated, else 0 on failure.
|
||||
*/
|
||||
int lv_info(const struct logical_volume *lv, struct lvinfo *info)
|
||||
static int _lv_info(const struct logical_volume *lv, int mknodes,
|
||||
struct lvinfo *info)
|
||||
{
|
||||
int r;
|
||||
struct dev_manager *dm;
|
||||
@@ -155,12 +342,12 @@ int lv_info(const struct logical_volume *lv, struct lvinfo *info)
|
||||
if (!activation())
|
||||
return 0;
|
||||
|
||||
if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cf))) {
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(r = dev_manager_info(dm, lv, &dminfo)))
|
||||
if (!(r = dev_manager_info(dm, lv, mknodes, &dminfo)))
|
||||
stack;
|
||||
|
||||
info->exists = dminfo.exists;
|
||||
@@ -174,6 +361,22 @@ int lv_info(const struct logical_volume *lv, struct lvinfo *info)
|
||||
return r;
|
||||
}
|
||||
|
||||
int lv_info(const struct logical_volume *lv, struct lvinfo *info)
|
||||
{
|
||||
return _lv_info(lv, 0, info);
|
||||
}
|
||||
|
||||
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
|
||||
struct lvinfo *info)
|
||||
{
|
||||
struct logical_volume *lv;
|
||||
|
||||
if (!(lv = lv_from_lvid(cmd, lvid_s)))
|
||||
return 0;
|
||||
|
||||
return _lv_info(lv, 0, info);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns 1 if percent set, else 0 on failure.
|
||||
*/
|
||||
@@ -185,7 +388,7 @@ int lv_snapshot_percent(struct logical_volume *lv, float *percent)
|
||||
if (!activation())
|
||||
return 0;
|
||||
|
||||
if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cf))) {
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -204,11 +407,20 @@ int lv_mirror_percent(struct logical_volume *lv, int wait, float *percent,
|
||||
{
|
||||
int r;
|
||||
struct dev_manager *dm;
|
||||
struct lvinfo info;
|
||||
|
||||
if (!activation())
|
||||
return 0;
|
||||
|
||||
if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cf))) {
|
||||
if (!lv_info(lv, &info)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!info.exists)
|
||||
return 0;
|
||||
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -246,12 +458,12 @@ static int _lv_open_count(struct logical_volume *lv)
|
||||
}
|
||||
|
||||
/* FIXME Need to detect and handle an lv rename */
|
||||
static int _lv_activate(struct logical_volume *lv)
|
||||
static int _lv_activate_lv(struct logical_volume *lv)
|
||||
{
|
||||
int r;
|
||||
struct dev_manager *dm;
|
||||
|
||||
if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cf))) {
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -268,7 +480,7 @@ static int _lv_deactivate(struct logical_volume *lv)
|
||||
int r;
|
||||
struct dev_manager *dm;
|
||||
|
||||
if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cf))) {
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -280,12 +492,12 @@ static int _lv_deactivate(struct logical_volume *lv)
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _lv_suspend(struct logical_volume *lv)
|
||||
static int _lv_suspend_lv(struct logical_volume *lv)
|
||||
{
|
||||
int r;
|
||||
struct dev_manager *dm;
|
||||
|
||||
if (!(dm = dev_manager_create(lv->vg->name, lv->vg->cmd->cf))) {
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -298,7 +510,7 @@ static int _lv_suspend(struct logical_volume *lv)
|
||||
}
|
||||
|
||||
/*
|
||||
* These two functions return the number of LVs in the state,
|
||||
* These two functions return the number of visible LVs in the state,
|
||||
* or -1 on error.
|
||||
*/
|
||||
int lvs_in_vg_activated(struct volume_group *vg)
|
||||
@@ -312,6 +524,7 @@ int lvs_in_vg_activated(struct volume_group *vg)
|
||||
|
||||
list_iterate(lvh, &vg->lvs) {
|
||||
lv = list_item(lvh, struct lv_list)->lv;
|
||||
if (lv->status & VISIBLE_LV)
|
||||
count += (_lv_active(lv) == 1);
|
||||
}
|
||||
|
||||
@@ -329,14 +542,15 @@ int lvs_in_vg_opened(struct volume_group *vg)
|
||||
|
||||
list_iterate(lvh, &vg->lvs) {
|
||||
lv = list_item(lvh, struct lv_list)->lv;
|
||||
count += (_lv_open_count(lv) == 1);
|
||||
if (lv->status & VISIBLE_LV)
|
||||
count += (_lv_open_count(lv) > 0);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/* These return success if the device is not active */
|
||||
int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s)
|
||||
static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
|
||||
int error_if_not_suspended)
|
||||
{
|
||||
struct logical_volume *lv;
|
||||
struct lvinfo info;
|
||||
@@ -358,10 +572,10 @@ int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s)
|
||||
}
|
||||
|
||||
if (!info.exists || info.suspended)
|
||||
return 1;
|
||||
return error_if_not_suspended ? 0 : 1;
|
||||
|
||||
memlock_inc();
|
||||
if (!_lv_suspend(lv)) {
|
||||
if (!_lv_suspend_lv(lv)) {
|
||||
memlock_dec();
|
||||
fs_unlock();
|
||||
return 0;
|
||||
@@ -370,7 +584,19 @@ int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s)
|
||||
/* Returns success if the device is not active */
|
||||
int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s)
|
||||
{
|
||||
return _lv_suspend(cmd, lvid_s, 0);
|
||||
}
|
||||
|
||||
int lv_suspend(struct cmd_context *cmd, const char *lvid_s)
|
||||
{
|
||||
return _lv_suspend(cmd, lvid_s, 1);
|
||||
}
|
||||
|
||||
static int _lv_resume(struct cmd_context *cmd, const char *lvid_s,
|
||||
int error_if_not_active)
|
||||
{
|
||||
struct logical_volume *lv;
|
||||
struct lvinfo info;
|
||||
@@ -392,9 +618,9 @@ int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s)
|
||||
}
|
||||
|
||||
if (!info.exists || !info.suspended)
|
||||
return 1;
|
||||
return error_if_not_active ? 0 : 1;
|
||||
|
||||
if (!_lv_activate(lv))
|
||||
if (!_lv_activate_lv(lv))
|
||||
return 0;
|
||||
|
||||
memlock_dec();
|
||||
@@ -403,6 +629,17 @@ int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Returns success if the device is not active */
|
||||
int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s)
|
||||
{
|
||||
return _lv_resume(cmd, lvid_s, 0);
|
||||
}
|
||||
|
||||
int lv_resume(struct cmd_context *cmd, const char *lvid_s)
|
||||
{
|
||||
return _lv_resume(cmd, lvid_s, 1);
|
||||
}
|
||||
|
||||
int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
|
||||
{
|
||||
struct logical_volume *lv;
|
||||
@@ -428,6 +665,12 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
|
||||
if (!info.exists)
|
||||
return 1;
|
||||
|
||||
if (info.open_count && (lv->status & VISIBLE_LV)) {
|
||||
log_error("LV %s/%s in use: not removing", lv->vg->name,
|
||||
lv->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memlock_inc();
|
||||
r = _lv_deactivate(lv);
|
||||
memlock_dec();
|
||||
@@ -436,7 +679,31 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
|
||||
return r;
|
||||
}
|
||||
|
||||
int lv_activate(struct cmd_context *cmd, const char *lvid_s)
|
||||
/* Test if LV passes filter */
|
||||
int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s,
|
||||
int *activate_lv)
|
||||
{
|
||||
struct logical_volume *lv;
|
||||
|
||||
if (!activation())
|
||||
goto activate;
|
||||
|
||||
if (!(lv = lv_from_lvid(cmd, lvid_s)))
|
||||
return 0;
|
||||
|
||||
if (!_passes_activation_filter(cmd, lv)) {
|
||||
log_verbose("Not activating %s/%s due to config file settings",
|
||||
lv->vg->name, lv->name);
|
||||
*activate_lv = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
activate:
|
||||
*activate_lv = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _lv_activate(struct cmd_context *cmd, const char *lvid_s, int filter)
|
||||
{
|
||||
struct logical_volume *lv;
|
||||
struct lvinfo info;
|
||||
@@ -448,6 +715,12 @@ int lv_activate(struct cmd_context *cmd, const char *lvid_s)
|
||||
if (!(lv = lv_from_lvid(cmd, lvid_s)))
|
||||
return 0;
|
||||
|
||||
if (filter && !_passes_activation_filter(cmd, lv)) {
|
||||
log_verbose("Not activating %s/%s due to config file settings",
|
||||
lv->vg->name, lv->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (test_mode()) {
|
||||
_skip("Activating '%s'.", lv->name);
|
||||
return 1;
|
||||
@@ -462,13 +735,51 @@ int lv_activate(struct cmd_context *cmd, const char *lvid_s)
|
||||
return 1;
|
||||
|
||||
memlock_inc();
|
||||
r = _lv_activate(lv);
|
||||
r = _lv_activate_lv(lv);
|
||||
memlock_dec();
|
||||
fs_unlock();
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Activate LV */
|
||||
int lv_activate(struct cmd_context *cmd, const char *lvid_s)
|
||||
{
|
||||
return _lv_activate(cmd, lvid_s, 0);
|
||||
}
|
||||
|
||||
/* Activate LV only if it passes filter */
|
||||
int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s)
|
||||
{
|
||||
return _lv_activate(cmd, lvid_s, 1);
|
||||
}
|
||||
|
||||
int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
|
||||
{
|
||||
struct lvinfo info;
|
||||
int r = 1;
|
||||
|
||||
if (!lv) {
|
||||
r = dev_manager_mknodes();
|
||||
fs_unlock();
|
||||
return r;
|
||||
}
|
||||
|
||||
if (!_lv_info(lv, 1, &info)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (info.exists)
|
||||
r = dev_manager_lv_mknodes(lv);
|
||||
else
|
||||
r = dev_manager_lv_rmnodes(lv);
|
||||
|
||||
fs_unlock();
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void activation_exit(void)
|
||||
{
|
||||
dev_manager_exit();
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef LVM_ACTIVATE_H
|
||||
@@ -27,18 +36,35 @@ int activation(void);
|
||||
|
||||
int driver_version(char *version, size_t size);
|
||||
int library_version(char *version, size_t size);
|
||||
int lvm1_present(struct cmd_context *cmd);
|
||||
|
||||
int target_present(const char *target_name);
|
||||
|
||||
void activation_exit(void);
|
||||
|
||||
int lv_suspend(struct cmd_context *cmd, const char *lvid_s);
|
||||
int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s);
|
||||
int lv_resume(struct cmd_context *cmd, const char *lvid_s);
|
||||
int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s);
|
||||
int lv_activate(struct cmd_context *cmd, const char *lvid_s);
|
||||
int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s);
|
||||
int lv_deactivate(struct cmd_context *cmd, const char *lvid_s);
|
||||
|
||||
int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv);
|
||||
|
||||
/*
|
||||
* Returns 1 if info structure has been populated, else 0.
|
||||
*/
|
||||
int lv_info(const struct logical_volume *lv, struct lvinfo *info);
|
||||
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
|
||||
struct lvinfo *info);
|
||||
|
||||
/*
|
||||
* Returns 1 if activate_lv has been set: 1 = activate; 0 = don't.
|
||||
*/
|
||||
int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s,
|
||||
int *activate_lv);
|
||||
|
||||
/*
|
||||
* Returns 1 if percent has been set, else 0.
|
||||
*/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,23 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2002 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_DEV_MANAGER_H
|
||||
#define _LVM_DEV_MANAGER_H
|
||||
|
||||
#include "metadata.h"
|
||||
#include "config.h"
|
||||
|
||||
struct logical_volume;
|
||||
struct cmd_context;
|
||||
struct dev_manager;
|
||||
struct dm_info;
|
||||
|
||||
/*
|
||||
* Constructor and destructor.
|
||||
*/
|
||||
struct dev_manager *dev_manager_create(const char *vg_name,
|
||||
struct config_tree *cf);
|
||||
struct dev_manager *dev_manager_create(struct cmd_context *cmd,
|
||||
const char *vg_name);
|
||||
void dev_manager_destroy(struct dev_manager *dm);
|
||||
void dev_manager_exit(void);
|
||||
|
||||
@@ -28,7 +36,7 @@ void dev_manager_exit(void);
|
||||
* unsuspended until the snapshot is also created.)
|
||||
*/
|
||||
int dev_manager_info(struct dev_manager *dm, const struct logical_volume *lv,
|
||||
struct dm_info *info);
|
||||
int mknodes, struct dm_info *info);
|
||||
int dev_manager_snapshot_percent(struct dev_manager *dm,
|
||||
struct logical_volume *lv, float *percent);
|
||||
int dev_manager_mirror_percent(struct dev_manager *dm,
|
||||
@@ -38,6 +46,10 @@ int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv);
|
||||
int dev_manager_activate(struct dev_manager *dm, struct logical_volume *lv);
|
||||
int dev_manager_deactivate(struct dev_manager *dm, struct logical_volume *lv);
|
||||
|
||||
int dev_manager_lv_mknodes(const struct logical_volume *lv);
|
||||
int dev_manager_lv_rmnodes(const struct logical_volume *lv);
|
||||
int dev_manager_mknodes(void);
|
||||
|
||||
/*
|
||||
* Put the desired changes into effect.
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -11,6 +20,10 @@
|
||||
#include "lvm-file.h"
|
||||
#include "memlock.h"
|
||||
|
||||
#ifdef HAVE_SELINUX
|
||||
# include "selinux.h"
|
||||
#endif
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
@@ -33,7 +46,7 @@ static int _mk_dir(const char *dev_dir, const char *vg_name)
|
||||
return 1;
|
||||
|
||||
log_very_verbose("Creating directory %s", vg_path);
|
||||
if (mkdir(vg_path, 0555)) {
|
||||
if (mkdir(vg_path, 0777)) {
|
||||
log_sys_error("mkdir", vg_path);
|
||||
return 0;
|
||||
}
|
||||
@@ -52,10 +65,10 @@ static int _rm_dir(const char *dev_dir, const char *vg_name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (is_empty_dir(vg_path)) {
|
||||
log_very_verbose("Removing directory %s", vg_path);
|
||||
|
||||
if (is_empty_dir(vg_path))
|
||||
rmdir(vg_path);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -166,6 +179,13 @@ static int _mk_link(const char *dev_dir, const char *vg_name,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_SELINUX
|
||||
if (!set_selinux_context(lv_path)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -182,6 +202,8 @@ static int _rm_link(const char *dev_dir, const char *vg_name,
|
||||
}
|
||||
|
||||
if (lstat(lv_path, &buf) || !S_ISLNK(buf.st_mode)) {
|
||||
if (errno == ENOENT)
|
||||
return 1;
|
||||
log_error("%s not symbolic link - not removing", lv_path);
|
||||
return 0;
|
||||
}
|
||||
@@ -309,13 +331,13 @@ static int _fs_op(fs_op_t type, const char *dev_dir, const char *vg_name,
|
||||
return _do_fs_op(type, dev_dir, vg_name, lv_name, dev, old_lv_name);
|
||||
}
|
||||
|
||||
int fs_add_lv(struct logical_volume *lv, const char *dev)
|
||||
int fs_add_lv(const struct logical_volume *lv, const char *dev)
|
||||
{
|
||||
return _fs_op(FS_ADD, lv->vg->cmd->dev_dir, lv->vg->name, lv->name,
|
||||
dev, "");
|
||||
}
|
||||
|
||||
int fs_del_lv(struct logical_volume *lv)
|
||||
int fs_del_lv(const struct logical_volume *lv)
|
||||
{
|
||||
return _fs_op(FS_DEL, lv->vg->cmd->dev_dir, lv->vg->name, lv->name,
|
||||
"", "");
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_FS_H
|
||||
@@ -14,8 +23,8 @@
|
||||
* up the volume group directory in /dev and the
|
||||
* symbolic links to the dm device.
|
||||
*/
|
||||
int fs_add_lv(struct logical_volume *lv, const char *dev);
|
||||
int fs_del_lv(struct logical_volume *lv);
|
||||
int fs_add_lv(const struct logical_volume *lv, const char *dev);
|
||||
int fs_del_lv(const struct logical_volume *lv);
|
||||
int fs_rename_lv(struct logical_volume *lv,
|
||||
const char *dev, const char *old_name);
|
||||
void fs_unlock(void);
|
||||
|
||||
25
lib/activate/targets.h
Normal file
25
lib/activate/targets.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_TARGETS_H
|
||||
#define _LVM_TARGETS_H
|
||||
|
||||
struct dev_manager;
|
||||
struct lv_segment;
|
||||
|
||||
int compose_areas_line(struct dev_manager *dm, struct lv_segment *seg, char *params, size_t paramsize, int *pos,
|
||||
int start_area, int areas);
|
||||
|
||||
#endif
|
||||
35
lib/cache/lvmcache.c
vendored
35
lib/cache/lvmcache.c
vendored
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -13,6 +22,7 @@
|
||||
#include "metadata.h"
|
||||
#include "filter.h"
|
||||
#include "memlock.h"
|
||||
#include "str_list.h"
|
||||
|
||||
static struct hash_table *_pvid_hash = NULL;
|
||||
static struct hash_table *_vgid_hash = NULL;
|
||||
@@ -207,31 +217,22 @@ int lvmcache_label_scan(struct cmd_context *cmd, int full_scan)
|
||||
|
||||
struct list *lvmcache_get_vgnames(struct cmd_context *cmd, int full_scan)
|
||||
{
|
||||
struct list *vgih, *vgnames;
|
||||
struct str_list *sl;
|
||||
struct list *vgnames;
|
||||
struct lvmcache_vginfo *vgi;
|
||||
|
||||
lvmcache_label_scan(cmd, full_scan);
|
||||
|
||||
if (!(vgnames = pool_alloc(cmd->mem, sizeof(struct list)))) {
|
||||
if (!(vgnames = str_list_create(cmd->mem))) {
|
||||
log_error("vgnames list allocation failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
list_init(vgnames);
|
||||
|
||||
list_iterate(vgih, &_vginfos) {
|
||||
if (!(sl = pool_alloc(cmd->mem, sizeof(*sl)))) {
|
||||
list_iterate_items(vgi, &_vginfos) {
|
||||
if (!str_list_add(cmd->mem, vgnames,
|
||||
pool_strdup(cmd->mem, vgi->vgname))) {
|
||||
log_error("strlist allocation failed");
|
||||
return NULL;
|
||||
}
|
||||
if (!(sl->str = pool_strdup(cmd->mem,
|
||||
list_item(vgih,
|
||||
struct lvmcache_vginfo)->
|
||||
vgname))) {
|
||||
log_error("vgname allocation failed");
|
||||
return NULL;
|
||||
}
|
||||
list_add(vgnames, &sl->list);
|
||||
}
|
||||
|
||||
return vgnames;
|
||||
|
||||
18
lib/cache/lvmcache.h
vendored
18
lib/cache/lvmcache.h
vendored
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -11,7 +20,6 @@
|
||||
#include "dev-cache.h"
|
||||
#include "uuid.h"
|
||||
#include "label.h"
|
||||
#include "metadata.h"
|
||||
|
||||
#define ORPHAN ""
|
||||
|
||||
@@ -21,6 +29,10 @@
|
||||
/* LVM specific per-volume info */
|
||||
/* Eventual replacement for struct physical_volume perhaps? */
|
||||
|
||||
struct cmd_context;
|
||||
struct format_type;
|
||||
struct volume_group;
|
||||
|
||||
struct lvmcache_vginfo {
|
||||
struct list list; /* Join these vginfos together */
|
||||
struct list infos; /* List head for lvmcache_infos */
|
||||
|
||||
@@ -1,15 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_ERRORS_H
|
||||
#define _LVM_ERRORS_H
|
||||
|
||||
#define EINVALID_CMD_LINE 1
|
||||
#define ENO_SUCH_CMD 3
|
||||
#define ECMD_PROCESSED 4
|
||||
#define ECMD_PROCESSED 1
|
||||
#define ENO_SUCH_CMD 2
|
||||
#define EINVALID_CMD_LINE 3
|
||||
#define ECMD_FAILED 5
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -14,13 +23,18 @@
|
||||
#include "activate.h"
|
||||
#include "filter.h"
|
||||
#include "filter-composite.h"
|
||||
#include "filter-md.h"
|
||||
#include "filter-persistent.h"
|
||||
#include "filter-regex.h"
|
||||
#include "filter-sysfs.h"
|
||||
#include "label.h"
|
||||
#include "lvm-file.h"
|
||||
#include "format-text.h"
|
||||
#include "display.h"
|
||||
#include "memlock.h"
|
||||
#include "str_list.h"
|
||||
#include "segtype.h"
|
||||
#include "lvmcache.h"
|
||||
|
||||
#ifdef HAVE_LIBDL
|
||||
#include "sharedlib.h"
|
||||
@@ -30,8 +44,13 @@
|
||||
#include "format1.h"
|
||||
#endif
|
||||
|
||||
#ifdef POOL_INTERNAL
|
||||
#include "format_pool.h"
|
||||
#endif
|
||||
|
||||
#include <locale.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <syslog.h>
|
||||
#include <time.h>
|
||||
|
||||
@@ -67,7 +86,7 @@ static void _init_logging(struct cmd_context *cmd)
|
||||
|
||||
/* Syslog */
|
||||
cmd->default_settings.syslog =
|
||||
find_config_int(cmd->cf->root, "log/syslog", '/', DEFAULT_SYSLOG);
|
||||
find_config_int(cmd->cft->root, "log/syslog", DEFAULT_SYSLOG);
|
||||
if (cmd->default_settings.syslog != 1)
|
||||
fin_syslog();
|
||||
|
||||
@@ -76,47 +95,50 @@ static void _init_logging(struct cmd_context *cmd)
|
||||
|
||||
/* Debug level for log file output */
|
||||
cmd->default_settings.debug =
|
||||
find_config_int(cmd->cf->root, "log/level", '/', DEFAULT_LOGLEVEL);
|
||||
find_config_int(cmd->cft->root, "log/level", DEFAULT_LOGLEVEL);
|
||||
init_debug(cmd->default_settings.debug);
|
||||
|
||||
/* Verbose level for tty output */
|
||||
cmd->default_settings.verbose =
|
||||
find_config_int(cmd->cf->root, "log/verbose", '/', DEFAULT_VERBOSE);
|
||||
init_verbose(cmd->default_settings.verbose);
|
||||
find_config_int(cmd->cft->root, "log/verbose", DEFAULT_VERBOSE);
|
||||
init_verbose(cmd->default_settings.verbose + VERBOSE_BASE_LEVEL);
|
||||
|
||||
/* Log message formatting */
|
||||
init_indent(find_config_int(cmd->cf->root, "log/indent", '/',
|
||||
init_indent(find_config_int(cmd->cft->root, "log/indent",
|
||||
DEFAULT_INDENT));
|
||||
|
||||
cmd->default_settings.msg_prefix = find_config_str(cmd->cf->root,
|
||||
"log/prefix", '/',
|
||||
cmd->default_settings.msg_prefix = find_config_str(cmd->cft->root,
|
||||
"log/prefix",
|
||||
DEFAULT_MSG_PREFIX);
|
||||
init_msg_prefix(cmd->default_settings.msg_prefix);
|
||||
|
||||
cmd->default_settings.cmd_name = find_config_int(cmd->cf->root,
|
||||
cmd->default_settings.cmd_name = find_config_int(cmd->cft->root,
|
||||
"log/command_names",
|
||||
'/', DEFAULT_CMD_NAME);
|
||||
DEFAULT_CMD_NAME);
|
||||
init_cmd_name(cmd->default_settings.cmd_name);
|
||||
|
||||
/* Test mode */
|
||||
cmd->default_settings.test =
|
||||
find_config_int(cmd->cf->root, "global/test", '/', 0);
|
||||
find_config_int(cmd->cft->root, "global/test", 0);
|
||||
|
||||
/* Settings for logging to file */
|
||||
if (find_config_int(cmd->cf->root, "log/overwrite", '/',
|
||||
DEFAULT_OVERWRITE))
|
||||
if (find_config_int(cmd->cft->root, "log/overwrite", DEFAULT_OVERWRITE))
|
||||
append = 0;
|
||||
|
||||
log_file = find_config_str(cmd->cf->root, "log/file", '/', 0);
|
||||
if (log_file)
|
||||
init_log_file(log_file, append);
|
||||
log_file = find_config_str(cmd->cft->root, "log/file", 0);
|
||||
|
||||
log_file = find_config_str(cmd->cf->root, "log/activate_file", '/', 0);
|
||||
if (log_file) {
|
||||
release_log_memory();
|
||||
fin_log();
|
||||
init_log_file(log_file, append);
|
||||
}
|
||||
|
||||
log_file = find_config_str(cmd->cft->root, "log/activate_file", 0);
|
||||
if (log_file)
|
||||
init_log_direct(log_file, append);
|
||||
|
||||
init_log_while_suspended(find_config_int(cmd->cf->root,
|
||||
"log/activation", '/', 0));
|
||||
init_log_while_suspended(find_config_int(cmd->cft->root,
|
||||
"log/activation", 0));
|
||||
|
||||
t = time(NULL);
|
||||
log_verbose("Logging initialised at %s", ctime(&t));
|
||||
@@ -132,8 +154,8 @@ static int _process_config(struct cmd_context *cmd)
|
||||
mode_t old_umask;
|
||||
|
||||
/* umask */
|
||||
cmd->default_settings.umask = find_config_int(cmd->cf->root,
|
||||
"global/umask", '/',
|
||||
cmd->default_settings.umask = find_config_int(cmd->cft->root,
|
||||
"global/umask",
|
||||
DEFAULT_UMASK);
|
||||
|
||||
if ((old_umask = umask((mode_t) cmd->default_settings.umask)) !=
|
||||
@@ -142,8 +164,8 @@ static int _process_config(struct cmd_context *cmd)
|
||||
|
||||
/* dev dir */
|
||||
if (lvm_snprintf(cmd->dev_dir, sizeof(cmd->dev_dir), "%s/",
|
||||
find_config_str(cmd->cf->root, "devices/dir",
|
||||
'/', DEFAULT_DEV_DIR)) < 0) {
|
||||
find_config_str(cmd->cft->root, "devices/dir",
|
||||
DEFAULT_DEV_DIR)) < 0) {
|
||||
log_error("Device directory given in config file too long");
|
||||
return 0;
|
||||
}
|
||||
@@ -153,27 +175,25 @@ static int _process_config(struct cmd_context *cmd)
|
||||
|
||||
/* proc dir */
|
||||
if (lvm_snprintf(cmd->proc_dir, sizeof(cmd->proc_dir), "%s",
|
||||
find_config_str(cmd->cf->root, "global/proc",
|
||||
'/', DEFAULT_PROC_DIR)) < 0) {
|
||||
find_config_str(cmd->cft->root, "global/proc",
|
||||
DEFAULT_PROC_DIR)) < 0) {
|
||||
log_error("Device directory given in config file too long");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* activation? */
|
||||
cmd->default_settings.activation = find_config_int(cmd->cf->root,
|
||||
cmd->default_settings.activation = find_config_int(cmd->cft->root,
|
||||
"global/activation",
|
||||
'/',
|
||||
DEFAULT_ACTIVATION);
|
||||
set_activation(cmd->default_settings.activation);
|
||||
|
||||
cmd->default_settings.suffix = find_config_int(cmd->cf->root,
|
||||
cmd->default_settings.suffix = find_config_int(cmd->cft->root,
|
||||
"global/suffix",
|
||||
'/', DEFAULT_SUFFIX);
|
||||
DEFAULT_SUFFIX);
|
||||
|
||||
if (!(cmd->default_settings.unit_factor =
|
||||
units_to_bytes(find_config_str(cmd->cf->root,
|
||||
units_to_bytes(find_config_str(cmd->cft->root,
|
||||
"global/units",
|
||||
'/',
|
||||
DEFAULT_UNITS),
|
||||
&cmd->default_settings.unit_type))) {
|
||||
log_error("Invalid units specification");
|
||||
@@ -183,57 +203,266 @@ static int _process_config(struct cmd_context *cmd)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Find and read config file */
|
||||
static int _init_config(struct cmd_context *cmd)
|
||||
static int _set_tag(struct cmd_context *cmd, const char *tag)
|
||||
{
|
||||
struct stat info;
|
||||
char config_file[PATH_MAX] = "";
|
||||
log_very_verbose("Setting host tag: %s", pool_strdup(cmd->libmem, tag));
|
||||
|
||||
if (!(cmd->cf = create_config_tree())) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* No config file if LVM_SYSTEM_DIR is empty */
|
||||
if (!*cmd->sys_dir)
|
||||
return 1;
|
||||
|
||||
if (lvm_snprintf(config_file, sizeof(config_file),
|
||||
"%s/lvm.conf", cmd->sys_dir) < 0) {
|
||||
log_error("LVM_SYSTEM_DIR was too long");
|
||||
destroy_config_tree(cmd->cf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Is there a config file? */
|
||||
if (stat(config_file, &info) == -1) {
|
||||
if (errno == ENOENT)
|
||||
return 1;
|
||||
log_sys_error("stat", config_file);
|
||||
destroy_config_tree(cmd->cf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!read_config_file(cmd->cf, config_file)) {
|
||||
log_error("Failed to load config file %s", config_file);
|
||||
destroy_config_tree(cmd->cf);
|
||||
if (!str_list_add(cmd->libmem, &cmd->tags, tag)) {
|
||||
log_error("_set_tag: str_list_add %s failed", tag);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _init_dev_cache(struct cmd_context *cmd)
|
||||
static int _check_host_filters(struct cmd_context *cmd, struct config_node *hn,
|
||||
int *passes)
|
||||
{
|
||||
struct config_node *cn;
|
||||
struct config_value *cv;
|
||||
|
||||
*passes = 1;
|
||||
|
||||
for (cn = hn; cn; cn = cn->sib) {
|
||||
if (!cn->v)
|
||||
continue;
|
||||
if (!strcmp(cn->key, "host_list")) {
|
||||
*passes = 0;
|
||||
if (cn->v->type == CFG_EMPTY_ARRAY)
|
||||
continue;
|
||||
for (cv = cn->v; cv; cv = cv->next) {
|
||||
if (cv->type != CFG_STRING) {
|
||||
log_error("Invalid hostname string "
|
||||
"for tag %s", cn->key);
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp(cv->v.str, cmd->hostname)) {
|
||||
*passes = 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!strcmp(cn->key, "host_filter")) {
|
||||
log_error("host_filter not supported yet");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _init_tags(struct cmd_context *cmd, struct config_tree *cft)
|
||||
{
|
||||
const struct config_node *tn, *cn;
|
||||
const char *tag;
|
||||
int passes;
|
||||
|
||||
if (!(tn = find_config_node(cft->root, "tags")) || !tn->child)
|
||||
return 1;
|
||||
|
||||
/* NB hosttags 0 when already 1 intentionally does not delete the tag */
|
||||
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;
|
||||
}
|
||||
cmd->hosttags = 1;
|
||||
}
|
||||
|
||||
for (cn = tn->child; cn; cn = cn->sib) {
|
||||
if (cn->v)
|
||||
continue;
|
||||
tag = cn->key;
|
||||
if (*tag == '@')
|
||||
tag++;
|
||||
if (!validate_name(tag)) {
|
||||
log_error("Invalid tag in config file: %s", cn->key);
|
||||
return 0;
|
||||
}
|
||||
if (cn->child) {
|
||||
passes = 0;
|
||||
if (!_check_host_filters(cmd, cn->child, &passes)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!passes)
|
||||
continue;
|
||||
}
|
||||
if (!_set_tag(cmd, tag)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _load_config_file(struct cmd_context *cmd, const char *tag)
|
||||
{
|
||||
char config_file[PATH_MAX] = "";
|
||||
const char *filler = "";
|
||||
struct stat info;
|
||||
struct config_tree_list *cfl;
|
||||
|
||||
if (*tag)
|
||||
filler = "_";
|
||||
|
||||
if (lvm_snprintf(config_file, sizeof(config_file), "%s/lvm%s%s.conf",
|
||||
cmd->sys_dir, filler, tag) < 0) {
|
||||
log_error("LVM_SYSTEM_DIR or tag was too long");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(cfl = pool_alloc(cmd->libmem, sizeof(*cfl)))) {
|
||||
log_error("config_tree_list allocation failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(cfl->cft = create_config_tree(config_file))) {
|
||||
log_error("config_tree allocation failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Is there a config file? */
|
||||
if (stat(config_file, &info) == -1) {
|
||||
if (errno == ENOENT) {
|
||||
list_add(&cmd->config_files, &cfl->list);
|
||||
goto out;
|
||||
}
|
||||
log_sys_error("stat", config_file);
|
||||
destroy_config_tree(cfl->cft);
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_very_verbose("Loading config file: %s", config_file);
|
||||
if (!read_config_file(cfl->cft)) {
|
||||
log_error("Failed to load config file %s", config_file);
|
||||
destroy_config_tree(cfl->cft);
|
||||
return 0;
|
||||
}
|
||||
|
||||
list_add(&cmd->config_files, &cfl->list);
|
||||
|
||||
out:
|
||||
if (*tag)
|
||||
_init_tags(cmd, cfl->cft);
|
||||
else
|
||||
/* Use temporary copy of lvm.conf while loading other files */
|
||||
cmd->cft = cfl->cft;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Find and read first config file */
|
||||
static int _init_lvm_conf(struct cmd_context *cmd)
|
||||
{
|
||||
/* No config file if LVM_SYSTEM_DIR is empty */
|
||||
if (!*cmd->sys_dir) {
|
||||
if (!(cmd->cft = create_config_tree(NULL))) {
|
||||
log_error("Failed to create config tree");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!_load_config_file(cmd, "")) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Read any additional config files */
|
||||
static int _init_tag_configs(struct cmd_context *cmd)
|
||||
{
|
||||
struct str_list *sl;
|
||||
|
||||
/* Tag list may grow while inside this loop */
|
||||
list_iterate_items(sl, &cmd->tags) {
|
||||
if (!_load_config_file(cmd, sl->str)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _merge_config_files(struct cmd_context *cmd)
|
||||
{
|
||||
struct config_tree_list *cfl;
|
||||
|
||||
/* Replace temporary duplicate copy of lvm.conf */
|
||||
if (cmd->cft->root) {
|
||||
if (!(cmd->cft = create_config_tree(NULL))) {
|
||||
log_error("Failed to create config tree");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _destroy_tags(struct cmd_context *cmd)
|
||||
{
|
||||
struct list *slh, *slht;
|
||||
|
||||
list_iterate_safe(slh, slht, &cmd->tags) {
|
||||
list_del(slh);
|
||||
}
|
||||
}
|
||||
|
||||
int config_files_changed(struct cmd_context *cmd)
|
||||
{
|
||||
struct config_tree_list *cfl;
|
||||
|
||||
list_iterate_items(cfl, &cmd->config_files) {
|
||||
if (config_file_changed(cfl->cft))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _destroy_tag_configs(struct cmd_context *cmd)
|
||||
{
|
||||
struct config_tree_list *cfl;
|
||||
|
||||
if (cmd->cft && cmd->cft->root) {
|
||||
destroy_config_tree(cmd->cft);
|
||||
cmd->cft = NULL;
|
||||
}
|
||||
|
||||
list_iterate_items(cfl, &cmd->config_files) {
|
||||
destroy_config_tree(cfl->cft);
|
||||
}
|
||||
|
||||
list_init(&cmd->config_files);
|
||||
}
|
||||
|
||||
static int _init_dev_cache(struct cmd_context *cmd)
|
||||
{
|
||||
const struct config_node *cn;
|
||||
struct config_value *cv;
|
||||
|
||||
if (!dev_cache_init()) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(cn = find_config_node(cmd->cf->root, "devices/scan", '/'))) {
|
||||
if (!(cn = find_config_node(cmd->cft->root, "devices/scan"))) {
|
||||
if (!dev_cache_add_dir("/dev")) {
|
||||
log_error("Failed to add /dev to internal "
|
||||
"device cache");
|
||||
@@ -261,33 +490,61 @@ static int _init_dev_cache(struct cmd_context *cmd)
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define MAX_FILTERS 4
|
||||
|
||||
static struct dev_filter *_init_filter_components(struct cmd_context *cmd)
|
||||
{
|
||||
struct config_node *cn;
|
||||
struct dev_filter *f1, *f2, *f3;
|
||||
unsigned nr_filt = 0;
|
||||
const struct config_node *cn;
|
||||
struct dev_filter *filters[MAX_FILTERS];
|
||||
|
||||
cn = find_config_node(cmd->cf->root, "devices/types", '/');
|
||||
memset(filters, 0, sizeof(filters));
|
||||
|
||||
if (!(f2 = lvm_type_filter_create(cmd->proc_dir, cn)))
|
||||
return NULL;
|
||||
/*
|
||||
* Filters listed in order: top one gets applied first.
|
||||
* Failure to initialise some filters is not fatal.
|
||||
* Update MAX_FILTERS definition above when adding new filters.
|
||||
*/
|
||||
|
||||
if (!(cn = find_config_node(cmd->cf->root, "devices/filter", '/'))) {
|
||||
log_debug("devices/filter not found in config file: no regex "
|
||||
"filter installed");
|
||||
return f2;
|
||||
/*
|
||||
* sysfs filter. Only available on 2.6 kernels. Non-critical.
|
||||
* Listed first because it's very efficient at eliminating
|
||||
* unavailable devices.
|
||||
*/
|
||||
if (find_config_bool(cmd->cft->root, "devices/sysfs_scan",
|
||||
DEFAULT_SYSFS_SCAN)) {
|
||||
if ((filters[nr_filt] = sysfs_filter_create(cmd->proc_dir)))
|
||||
nr_filt++;
|
||||
}
|
||||
|
||||
if (!(f1 = regex_filter_create(cn->v))) {
|
||||
/* regex filter. Optional. */
|
||||
if (!(cn = find_config_node(cmd->cft->root, "devices/filter")))
|
||||
log_very_verbose("devices/filter not found in config file: "
|
||||
"no regex filter installed");
|
||||
|
||||
else if (!(filters[nr_filt++] = regex_filter_create(cn->v))) {
|
||||
log_error("Failed to create regex device filter");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(f3 = composite_filter_create(2, f1, f2))) {
|
||||
log_error("Failed to create composite device filter");
|
||||
/* device type filter. Required. */
|
||||
cn = find_config_node(cmd->cft->root, "devices/types");
|
||||
if (!(filters[nr_filt++] = lvm_type_filter_create(cmd->proc_dir, cn))) {
|
||||
log_error("Failed to create lvm type filter");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return f3;
|
||||
/* md component filter. Optional, non-critical. */
|
||||
if (find_config_bool(cmd->cft->root, "devices/md_component_detection",
|
||||
DEFAULT_MD_COMPONENT_DETECTION)) {
|
||||
init_md_filtering(1);
|
||||
if ((filters[nr_filt] = md_filter_create()))
|
||||
nr_filt++;
|
||||
}
|
||||
|
||||
/* Only build a composite filter if we really need it. */
|
||||
return (nr_filt == 1) ?
|
||||
filters[0] : composite_filter_create(nr_filt, filters);
|
||||
}
|
||||
|
||||
static int _init_filters(struct cmd_context *cmd)
|
||||
@@ -309,22 +566,22 @@ static int _init_filters(struct cmd_context *cmd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
dev_cache =
|
||||
find_config_str(cmd->cf->root, "devices/cache", '/', cache_file);
|
||||
dev_cache = find_config_str(cmd->cft->root, "devices/cache",
|
||||
cache_file);
|
||||
if (!(f4 = persistent_filter_create(f3, dev_cache))) {
|
||||
log_error("Failed to create persistent device filter");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Should we ever dump persistent filter state? */
|
||||
if (find_config_int(cmd->cf->root, "devices/write_cache_state", '/', 1))
|
||||
if (find_config_int(cmd->cft->root, "devices/write_cache_state", 1))
|
||||
cmd->dump_filter = 1;
|
||||
|
||||
if (!*cmd->sys_dir)
|
||||
cmd->dump_filter = 0;
|
||||
|
||||
if (!stat(dev_cache, &st) &&
|
||||
(st.st_mtime > config_file_timestamp(cmd->cf)) &&
|
||||
(st.st_mtime > config_file_timestamp(cmd->cft)) &&
|
||||
!persistent_filter_load(f4))
|
||||
log_verbose("Failed to load existing device cache from %s",
|
||||
dev_cache);
|
||||
@@ -342,7 +599,7 @@ static int _init_formats(struct cmd_context *cmd)
|
||||
struct list *fmth;
|
||||
|
||||
#ifdef HAVE_LIBDL
|
||||
struct config_node *cn;
|
||||
const struct config_node *cn;
|
||||
#endif
|
||||
|
||||
label_init();
|
||||
@@ -354,10 +611,16 @@ static int _init_formats(struct cmd_context *cmd)
|
||||
list_add(&cmd->formats, &fmt->list);
|
||||
#endif
|
||||
|
||||
#ifdef POOL_INTERNAL
|
||||
if (!(fmt = init_pool_format(cmd)))
|
||||
return 0;
|
||||
fmt->library = NULL;
|
||||
list_add(&cmd->formats, &fmt->list);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBDL
|
||||
/* Load any formats in shared libs */
|
||||
if ((cn = find_config_node(cmd->cf->root, "global/format_libraries",
|
||||
'/'))) {
|
||||
if ((cn = find_config_node(cmd->cft->root, "global/format_libraries"))) {
|
||||
|
||||
struct config_value *cv;
|
||||
struct format_type *(*init_format_fn) (struct cmd_context *);
|
||||
@@ -369,7 +632,7 @@ static int _init_formats(struct cmd_context *cmd)
|
||||
"global/format_libraries");
|
||||
return 0;
|
||||
}
|
||||
if (!(lib = load_shared_library(cmd->cf, cv->v.str,
|
||||
if (!(lib = load_shared_library(cmd->cft, cv->v.str,
|
||||
"format"))) {
|
||||
stack;
|
||||
return 0;
|
||||
@@ -397,7 +660,7 @@ static int _init_formats(struct cmd_context *cmd)
|
||||
|
||||
cmd->fmt_backup = fmt;
|
||||
|
||||
format = find_config_str(cmd->cf->root, "global/format", '/',
|
||||
format = find_config_str(cmd->cft->root, "global/format",
|
||||
DEFAULT_FORMAT);
|
||||
|
||||
list_iterate(fmth, &cmd->formats) {
|
||||
@@ -413,6 +676,119 @@ static int _init_formats(struct cmd_context *cmd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _init_segtypes(struct cmd_context *cmd)
|
||||
{
|
||||
struct segment_type *segtype;
|
||||
|
||||
#ifdef HAVE_LIBDL
|
||||
const struct config_node *cn;
|
||||
#endif
|
||||
|
||||
if (!(segtype = init_striped_segtype(cmd)))
|
||||
return 0;
|
||||
segtype->library = NULL;
|
||||
list_add(&cmd->segtypes, &segtype->list);
|
||||
|
||||
if (!(segtype = init_zero_segtype(cmd)))
|
||||
return 0;
|
||||
segtype->library = NULL;
|
||||
list_add(&cmd->segtypes, &segtype->list);
|
||||
|
||||
if (!(segtype = init_error_segtype(cmd)))
|
||||
return 0;
|
||||
segtype->library = NULL;
|
||||
list_add(&cmd->segtypes, &segtype->list);
|
||||
|
||||
#ifdef SNAPSHOT_INTERNAL
|
||||
if (!(segtype = init_snapshot_segtype(cmd)))
|
||||
return 0;
|
||||
segtype->library = NULL;
|
||||
list_add(&cmd->segtypes, &segtype->list);
|
||||
#endif
|
||||
|
||||
#ifdef MIRRORED_INTERNAL
|
||||
if (!(segtype = init_mirrored_segtype(cmd)))
|
||||
return 0;
|
||||
segtype->library = NULL;
|
||||
list_add(&cmd->segtypes, &segtype->list);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBDL
|
||||
/* Load any formats in shared libs */
|
||||
if ((cn = find_config_node(cmd->cft->root, "global/segment_libraries"))) {
|
||||
|
||||
struct config_value *cv;
|
||||
struct segment_type *(*init_segtype_fn) (struct cmd_context *);
|
||||
void *lib;
|
||||
struct list *sgtl, *tmp;
|
||||
struct segment_type *segtype2;
|
||||
|
||||
for (cv = cn->v; cv; cv = cv->next) {
|
||||
if (cv->type != CFG_STRING) {
|
||||
log_error("Invalid string in config file: "
|
||||
"global/segment_libraries");
|
||||
return 0;
|
||||
}
|
||||
if (!(lib = load_shared_library(cmd->cft, cv->v.str,
|
||||
"segment type"))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(init_segtype_fn = dlsym(lib, "init_segtype"))) {
|
||||
log_error("Shared library %s does not contain "
|
||||
"segment type functions", cv->v.str);
|
||||
dlclose(lib);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(segtype = init_segtype_fn(cmd)))
|
||||
return 0;
|
||||
segtype->library = lib;
|
||||
list_add(&cmd->segtypes, &segtype->list);
|
||||
|
||||
list_iterate_safe(sgtl, tmp, &cmd->segtypes) {
|
||||
segtype2 = list_item(sgtl, struct segment_type);
|
||||
if (!strcmp(segtype2->name, segtype->name)) {
|
||||
log_error("Duplicate segment type %s: "
|
||||
"unloading shared library %s",
|
||||
segtype->name, cv->v.str);
|
||||
list_del(&segtype->list);
|
||||
segtype->ops->destroy(segtype);
|
||||
dlclose(lib);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _init_hostname(struct cmd_context *cmd)
|
||||
{
|
||||
struct utsname uts;
|
||||
|
||||
if (uname(&uts)) {
|
||||
log_sys_error("uname", "_init_hostname");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(cmd->hostname = pool_strdup(cmd->libmem, uts.nodename))) {
|
||||
log_error("_init_hostname: pool_strdup failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(cmd->kernel_vsn = pool_strdup(cmd->libmem, uts.release))) {
|
||||
log_error("_init_hostname: pool_strdup kernel_vsn failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Entry point */
|
||||
struct cmd_context *create_toolcontext(struct arg *the_args)
|
||||
{
|
||||
@@ -423,7 +799,11 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
|
||||
#endif
|
||||
|
||||
if (!setlocale(LC_ALL, ""))
|
||||
log_error("setlocale failed");
|
||||
log_very_verbose("setlocale failed");
|
||||
|
||||
#ifdef INTL_PACKAGE
|
||||
bindtextdomain(INTL_PACKAGE, LOCALEDIR);
|
||||
#endif
|
||||
|
||||
init_syslog(DEFAULT_LOG_FACILITY);
|
||||
|
||||
@@ -433,7 +813,11 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
|
||||
}
|
||||
memset(cmd, 0, sizeof(*cmd));
|
||||
cmd->args = the_args;
|
||||
cmd->hosttags = 0;
|
||||
list_init(&cmd->formats);
|
||||
list_init(&cmd->segtypes);
|
||||
list_init(&cmd->tags);
|
||||
list_init(&cmd->config_files);
|
||||
|
||||
strcpy(cmd->sys_dir, DEFAULT_SYS_DIR);
|
||||
|
||||
@@ -444,11 +828,28 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
|
||||
if (*cmd->sys_dir && !create_dir(cmd->sys_dir))
|
||||
goto error;
|
||||
|
||||
if (!_init_config(cmd))
|
||||
if (!(cmd->libmem = pool_create("library", 4 * 1024))) {
|
||||
log_error("Library memory pool creation failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!_init_lvm_conf(cmd))
|
||||
goto error;
|
||||
|
||||
_init_logging(cmd);
|
||||
|
||||
if (!_init_hostname(cmd))
|
||||
goto error;
|
||||
|
||||
if (!_init_tags(cmd, cmd->cft))
|
||||
goto error;
|
||||
|
||||
if (!_init_tag_configs(cmd))
|
||||
goto error;
|
||||
|
||||
if (!_merge_config_files(cmd))
|
||||
goto error;
|
||||
|
||||
if (!_process_config(cmd))
|
||||
goto error;
|
||||
|
||||
@@ -458,7 +859,7 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
|
||||
if (!_init_filters(cmd))
|
||||
goto error;
|
||||
|
||||
if (!(cmd->mem = pool_create(4 * 1024))) {
|
||||
if (!(cmd->mem = pool_create("command", 4 * 1024))) {
|
||||
log_error("Command memory pool creation failed");
|
||||
return 0;
|
||||
}
|
||||
@@ -468,8 +869,12 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
|
||||
if (!_init_formats(cmd))
|
||||
goto error;
|
||||
|
||||
if (!_init_segtypes(cmd))
|
||||
goto error;
|
||||
|
||||
cmd->current_settings = cmd->default_settings;
|
||||
|
||||
cmd->config_valid = 1;
|
||||
return cmd;
|
||||
|
||||
error:
|
||||
@@ -495,6 +900,83 @@ static void _destroy_formats(struct list *formats)
|
||||
}
|
||||
}
|
||||
|
||||
static void _destroy_segtypes(struct list *segtypes)
|
||||
{
|
||||
struct list *sgtl, *tmp;
|
||||
struct segment_type *segtype;
|
||||
void *lib;
|
||||
|
||||
list_iterate_safe(sgtl, tmp, segtypes) {
|
||||
segtype = list_item(sgtl, struct segment_type);
|
||||
list_del(&segtype->list);
|
||||
lib = segtype->library;
|
||||
segtype->ops->destroy(segtype);
|
||||
#ifdef HAVE_LIBDL
|
||||
if (lib)
|
||||
dlclose(lib);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
int refresh_toolcontext(struct cmd_context *cmd)
|
||||
{
|
||||
log_verbose("Reloading config files");
|
||||
|
||||
if (cmd->config_valid) {
|
||||
if (cmd->dump_filter)
|
||||
persistent_filter_dump(cmd->filter);
|
||||
}
|
||||
|
||||
activation_exit();
|
||||
lvmcache_destroy();
|
||||
label_exit();
|
||||
_destroy_segtypes(&cmd->segtypes);
|
||||
_destroy_formats(&cmd->formats);
|
||||
if (cmd->filter) {
|
||||
cmd->filter->destroy(cmd->filter);
|
||||
cmd->filter = NULL;
|
||||
}
|
||||
dev_cache_exit();
|
||||
_destroy_tags(cmd);
|
||||
_destroy_tag_configs(cmd);
|
||||
|
||||
cmd->config_valid = 0;
|
||||
|
||||
cmd->hosttags = 0;
|
||||
|
||||
if (!_init_lvm_conf(cmd))
|
||||
return 0;
|
||||
|
||||
_init_logging(cmd);
|
||||
|
||||
if (!_init_tags(cmd, cmd->cft))
|
||||
return 0;
|
||||
|
||||
if (!_init_tag_configs(cmd))
|
||||
return 0;
|
||||
|
||||
if (!_merge_config_files(cmd))
|
||||
return 0;
|
||||
|
||||
if (!_process_config(cmd))
|
||||
return 0;
|
||||
|
||||
if (!_init_dev_cache(cmd))
|
||||
return 0;
|
||||
|
||||
if (!_init_filters(cmd))
|
||||
return 0;
|
||||
|
||||
if (!_init_formats(cmd))
|
||||
return 0;
|
||||
|
||||
if (!_init_segtypes(cmd))
|
||||
return 0;
|
||||
|
||||
cmd->config_valid = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void destroy_toolcontext(struct cmd_context *cmd)
|
||||
{
|
||||
if (cmd->dump_filter)
|
||||
@@ -503,11 +985,14 @@ void destroy_toolcontext(struct cmd_context *cmd)
|
||||
activation_exit();
|
||||
lvmcache_destroy();
|
||||
label_exit();
|
||||
_destroy_segtypes(&cmd->segtypes);
|
||||
_destroy_formats(&cmd->formats);
|
||||
cmd->filter->destroy(cmd->filter);
|
||||
pool_destroy(cmd->mem);
|
||||
dev_cache_exit();
|
||||
destroy_config_tree(cmd->cf);
|
||||
_destroy_tags(cmd);
|
||||
_destroy_tag_configs(cmd);
|
||||
pool_destroy(cmd->libmem);
|
||||
dbg_free(cmd);
|
||||
|
||||
release_log_memory();
|
||||
|
||||
@@ -1,17 +1,23 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_TOOLCONTEXT_H
|
||||
#define _LVM_TOOLCONTEXT_H
|
||||
|
||||
#include "dev-cache.h"
|
||||
#include "config.h"
|
||||
#include "pool.h"
|
||||
#include "metadata.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
@@ -39,16 +45,21 @@ struct config_info {
|
||||
mode_t umask;
|
||||
};
|
||||
|
||||
struct config_tree;
|
||||
|
||||
/* FIXME Split into tool & library contexts */
|
||||
/* command-instance-related variables needed by library */
|
||||
struct cmd_context {
|
||||
/* format handler allocates all objects from here */
|
||||
struct pool *mem;
|
||||
struct pool *libmem; /* For permanent config data */
|
||||
struct pool *mem; /* Transient: Cleared between each command */
|
||||
|
||||
const struct format_type *fmt; /* Current format to use by default */
|
||||
struct format_type *fmt_backup; /* Format to use for backups */
|
||||
|
||||
struct list formats; /* Available formats */
|
||||
struct list segtypes; /* Available segment types */
|
||||
const char *hostname;
|
||||
const char *kernel_vsn;
|
||||
|
||||
char *cmd_line;
|
||||
struct command *command;
|
||||
@@ -58,10 +69,16 @@ struct cmd_context {
|
||||
struct dev_filter *filter;
|
||||
int dump_filter; /* Dump filter when exiting? */
|
||||
|
||||
struct config_tree *cf;
|
||||
struct list config_files;
|
||||
int config_valid;
|
||||
struct config_tree *cft;
|
||||
struct config_info default_settings;
|
||||
struct config_info current_settings;
|
||||
|
||||
/* List of defined tags */
|
||||
struct list tags;
|
||||
int hosttags;
|
||||
|
||||
char sys_dir[PATH_MAX];
|
||||
char dev_dir[PATH_MAX];
|
||||
char proc_dir[PATH_MAX];
|
||||
@@ -69,5 +86,7 @@ struct cmd_context {
|
||||
|
||||
struct cmd_context *create_toolcontext(struct arg *the_args);
|
||||
void destroy_toolcontext(struct cmd_context *cmd);
|
||||
int refresh_toolcontext(struct cmd_context *cmd);
|
||||
int config_files_changed(struct cmd_context *cmd);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -9,6 +18,8 @@
|
||||
#include "crc.h"
|
||||
#include "pool.h"
|
||||
#include "device.h"
|
||||
#include "str_list.h"
|
||||
#include "toolcontext.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
@@ -43,10 +54,11 @@ struct parser {
|
||||
};
|
||||
|
||||
struct cs {
|
||||
struct config_tree cf;
|
||||
struct config_tree cft;
|
||||
struct pool *mem;
|
||||
time_t timestamp;
|
||||
char *filename;
|
||||
int exists;
|
||||
};
|
||||
|
||||
static void _get_token(struct parser *p, int tok_prev);
|
||||
@@ -60,6 +72,8 @@ static struct config_value *_create_value(struct parser *p);
|
||||
static struct config_node *_create_node(struct parser *p);
|
||||
static char *_dup_tok(struct parser *p);
|
||||
|
||||
static const int sep = '/';
|
||||
|
||||
#define MAX_INDENT 32
|
||||
|
||||
#define match(t) do {\
|
||||
@@ -82,39 +96,41 @@ static int _tok_match(const char *str, const char *b, const char *e)
|
||||
/*
|
||||
* public interface
|
||||
*/
|
||||
struct config_tree *create_config_tree(void)
|
||||
struct config_tree *create_config_tree(const char *filename)
|
||||
{
|
||||
struct cs *c;
|
||||
struct pool *mem = pool_create(10 * 1024);
|
||||
struct pool *mem = pool_create("config", 10 * 1024);
|
||||
|
||||
if (!mem) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(c = pool_alloc(mem, sizeof(*c)))) {
|
||||
if (!(c = pool_zalloc(mem, sizeof(*c)))) {
|
||||
stack;
|
||||
pool_destroy(mem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
c->mem = mem;
|
||||
c->cf.root = (struct config_node *) NULL;
|
||||
c->cft.root = (struct config_node *) NULL;
|
||||
c->timestamp = 0;
|
||||
c->filename = NULL;
|
||||
return &c->cf;
|
||||
c->exists = 0;
|
||||
if (filename)
|
||||
c->filename = pool_strdup(c->mem, filename);
|
||||
return &c->cft;
|
||||
}
|
||||
|
||||
void destroy_config_tree(struct config_tree *cf)
|
||||
void destroy_config_tree(struct config_tree *cft)
|
||||
{
|
||||
pool_destroy(((struct cs *) cf)->mem);
|
||||
pool_destroy(((struct cs *) cft)->mem);
|
||||
}
|
||||
|
||||
int read_config_fd(struct config_tree *cf, struct device *dev,
|
||||
int read_config_fd(struct config_tree *cft, struct device *dev,
|
||||
off_t offset, size_t size, off_t offset2, size_t size2,
|
||||
checksum_fn_t checksum_fn, uint32_t checksum)
|
||||
{
|
||||
struct cs *c = (struct cs *) cf;
|
||||
struct cs *c = (struct cs *) cft;
|
||||
struct parser *p;
|
||||
int r = 0;
|
||||
int use_mmap = 1;
|
||||
@@ -172,7 +188,7 @@ int read_config_fd(struct config_tree *cf, struct device *dev,
|
||||
p->tb = p->te = p->fb;
|
||||
p->line = 1;
|
||||
_get_token(p, TOK_SECTION_E);
|
||||
if (!(cf->root = _file(p))) {
|
||||
if (!(cft->root = _file(p))) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
@@ -193,99 +209,30 @@ int read_config_fd(struct config_tree *cf, struct device *dev,
|
||||
return r;
|
||||
}
|
||||
|
||||
int read_config_file(struct config_tree *cf, const char *file)
|
||||
int read_config_file(struct config_tree *cft)
|
||||
{
|
||||
struct cs *c = (struct cs *) cf;
|
||||
struct cs *c = (struct cs *) cft;
|
||||
struct stat info;
|
||||
struct device *dev;
|
||||
int r = 1;
|
||||
|
||||
if (stat(file, &info)) {
|
||||
log_sys_error("stat", file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!S_ISREG(info.st_mode)) {
|
||||
log_error("%s is not a regular file", file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (info.st_size == 0) {
|
||||
log_verbose("%s is empty", file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!(dev = dev_create_file(file, NULL, NULL))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dev_open_flags(dev, O_RDONLY, 0, 0)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = read_config_fd(cf, dev, 0, (size_t) info.st_size, 0, 0,
|
||||
(checksum_fn_t) NULL, 0);
|
||||
|
||||
dev_close(dev);
|
||||
|
||||
c->timestamp = info.st_mtime;
|
||||
c->filename = pool_strdup(c->mem, file);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
time_t config_file_timestamp(struct config_tree *cf)
|
||||
{
|
||||
struct cs *c = (struct cs *) cf;
|
||||
|
||||
return c->timestamp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns 1 if config file reloaded
|
||||
*/
|
||||
int reload_config_file(struct config_tree **cf)
|
||||
{
|
||||
struct config_tree *new_cf;
|
||||
struct cs *c = (struct cs *) *cf;
|
||||
struct cs *new_cs;
|
||||
struct stat info;
|
||||
struct device *dev;
|
||||
int r;
|
||||
|
||||
if (!c->filename)
|
||||
return 0;
|
||||
|
||||
if (stat(c->filename, &info) == -1) {
|
||||
if (errno == ENOENT)
|
||||
return 1;
|
||||
if (stat(c->filename, &info)) {
|
||||
log_sys_error("stat", c->filename);
|
||||
log_error("Failed to reload configuration file");
|
||||
c->exists = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!S_ISREG(info.st_mode)) {
|
||||
log_error("Configuration file %s is not a regular file",
|
||||
c->filename);
|
||||
log_error("%s is not a regular file", c->filename);
|
||||
c->exists = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Unchanged? */
|
||||
if (c->timestamp == info.st_mtime)
|
||||
return 0;
|
||||
|
||||
log_verbose("Detected config file change: Reloading %s", c->filename);
|
||||
c->exists = 1;
|
||||
|
||||
if (info.st_size == 0) {
|
||||
log_verbose("Config file reload: %s is empty", c->filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(new_cf = create_config_tree())) {
|
||||
log_error("Allocation of new config_tree failed");
|
||||
return 0;
|
||||
log_verbose("%s is empty", c->filename);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!(dev = dev_create_file(c->filename, NULL, NULL))) {
|
||||
@@ -298,22 +245,63 @@ int reload_config_file(struct config_tree **cf)
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = read_config_fd(new_cf, dev, 0, (size_t) info.st_size,
|
||||
0, 0, (checksum_fn_t) NULL, 0);
|
||||
r = read_config_fd(cft, dev, 0, (size_t) info.st_size, 0, 0,
|
||||
(checksum_fn_t) NULL, 0);
|
||||
|
||||
dev_close(dev);
|
||||
|
||||
if (r) {
|
||||
new_cs = (struct cs *) new_cf;
|
||||
new_cs->filename = pool_strdup(new_cs->mem, c->filename);
|
||||
new_cs->timestamp = info.st_mtime;
|
||||
destroy_config_tree(*cf);
|
||||
*cf = new_cf;
|
||||
}
|
||||
c->timestamp = info.st_mtime;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
time_t config_file_timestamp(struct config_tree *cft)
|
||||
{
|
||||
struct cs *c = (struct cs *) cft;
|
||||
|
||||
return c->timestamp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return 1 if config files ought to be reloaded
|
||||
*/
|
||||
int config_file_changed(struct config_tree *cft)
|
||||
{
|
||||
struct cs *c = (struct cs *) cft;
|
||||
struct stat info;
|
||||
|
||||
if (!c->filename)
|
||||
return 0;
|
||||
|
||||
if (stat(c->filename, &info) == -1) {
|
||||
/* Ignore a deleted config file: still use original data */
|
||||
if (errno == ENOENT) {
|
||||
if (!c->exists)
|
||||
return 0;
|
||||
log_very_verbose("Config file %s has disappeared!",
|
||||
c->filename);
|
||||
goto reload;
|
||||
}
|
||||
log_sys_error("stat", c->filename);
|
||||
log_error("Failed to reload configuration files");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!S_ISREG(info.st_mode)) {
|
||||
log_error("Configuration file %s is not a regular file",
|
||||
c->filename);
|
||||
goto reload;
|
||||
}
|
||||
|
||||
/* Unchanged? */
|
||||
if (c->timestamp == info.st_mtime)
|
||||
return 0;
|
||||
|
||||
reload:
|
||||
log_verbose("Detected config file change to %s", c->filename);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _write_value(FILE *fp, struct config_value *v)
|
||||
{
|
||||
switch (v->type) {
|
||||
@@ -382,20 +370,28 @@ static int _write_config(struct config_node *n, FILE *fp, int level)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int write_config_file(struct config_tree *cf, const char *file)
|
||||
int write_config_file(struct config_tree *cft, const char *file)
|
||||
{
|
||||
int r = 1;
|
||||
FILE *fp = fopen(file, "w");
|
||||
if (!fp) {
|
||||
FILE *fp;
|
||||
|
||||
if (!file) {
|
||||
fp = stdout;
|
||||
file = "stdout";
|
||||
} else if (!(fp = fopen(file, "w"))) {
|
||||
log_sys_error("open", file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!_write_config(cf->root, fp, 0)) {
|
||||
stack;
|
||||
log_verbose("Dumping configuration to %s", file);
|
||||
if (!_write_config(cft->root, fp, 0)) {
|
||||
log_error("Failure while writing configuration");
|
||||
r = 0;
|
||||
}
|
||||
|
||||
if (fp != stdout)
|
||||
fclose(fp);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -502,7 +498,7 @@ static struct config_value *_value(struct parser *p)
|
||||
|
||||
static struct config_value *_type(struct parser *p)
|
||||
{
|
||||
/* [0-9]+ | [0-9]*\.[0-9]* | ".*" */
|
||||
/* [+-]{0,1}[0-9]+ | [0-9]*\.[0-9]* | ".*" */
|
||||
struct config_value *v = _create_value(p);
|
||||
|
||||
if (!v)
|
||||
@@ -637,6 +633,8 @@ static void _get_token(struct parser *p, int tok_prev)
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
case '+':
|
||||
case '-':
|
||||
if (values_allowed) {
|
||||
p->te++;
|
||||
while ((p->te != p->fe) && (*p->te)) {
|
||||
@@ -718,8 +716,8 @@ static char *_dup_tok(struct parser *p)
|
||||
/*
|
||||
* utility functions
|
||||
*/
|
||||
struct config_node *find_config_node(struct config_node *cn,
|
||||
const char *path, const int sep)
|
||||
struct config_node *find_config_node(const struct config_node *cn,
|
||||
const char *path)
|
||||
{
|
||||
const char *e;
|
||||
|
||||
@@ -747,13 +745,13 @@ struct config_node *find_config_node(struct config_node *cn,
|
||||
path = e;
|
||||
}
|
||||
|
||||
return cn;
|
||||
return (struct config_node *) cn;
|
||||
}
|
||||
|
||||
const char *find_config_str(struct config_node *cn,
|
||||
const char *path, const int sep, const char *fail)
|
||||
const char *find_config_str(const struct config_node *cn,
|
||||
const char *path, const char *fail)
|
||||
{
|
||||
struct config_node *n = find_config_node(cn, path, sep);
|
||||
const struct config_node *n = find_config_node(cn, path);
|
||||
|
||||
if (n && n->v->type == CFG_STRING) {
|
||||
if (*n->v->v.str)
|
||||
@@ -767,10 +765,9 @@ const char *find_config_str(struct config_node *cn,
|
||||
return fail;
|
||||
}
|
||||
|
||||
int find_config_int(struct config_node *cn, const char *path,
|
||||
const int sep, int fail)
|
||||
int find_config_int(const struct config_node *cn, const char *path, int fail)
|
||||
{
|
||||
struct config_node *n = find_config_node(cn, path, sep);
|
||||
const struct config_node *n = find_config_node(cn, path);
|
||||
|
||||
if (n && n->v->type == CFG_INT) {
|
||||
log_very_verbose("Setting %s to %d", path, n->v->v.i);
|
||||
@@ -782,10 +779,10 @@ int find_config_int(struct config_node *cn, const char *path,
|
||||
return fail;
|
||||
}
|
||||
|
||||
float find_config_float(struct config_node *cn, const char *path,
|
||||
const int sep, float fail)
|
||||
float find_config_float(const struct config_node *cn, const char *path,
|
||||
float fail)
|
||||
{
|
||||
struct config_node *n = find_config_node(cn, path, sep);
|
||||
const struct config_node *n = find_config_node(cn, path);
|
||||
|
||||
if (n && n->v->type == CFG_FLOAT) {
|
||||
log_very_verbose("Setting %s to %f", path, n->v->v.r);
|
||||
@@ -825,10 +822,9 @@ static int _str_to_bool(const char *str, int fail)
|
||||
return fail;
|
||||
}
|
||||
|
||||
int find_config_bool(struct config_node *cn, const char *path,
|
||||
const int sep, int fail)
|
||||
int find_config_bool(const struct config_node *cn, const char *path, int fail)
|
||||
{
|
||||
struct config_node *n = find_config_node(cn, path, sep);
|
||||
const struct config_node *n = find_config_node(cn, path);
|
||||
struct config_value *v;
|
||||
|
||||
if (!n)
|
||||
@@ -847,12 +843,12 @@ int find_config_bool(struct config_node *cn, const char *path,
|
||||
return fail;
|
||||
}
|
||||
|
||||
int get_config_uint32(struct config_node *cn, const char *path,
|
||||
const int sep, uint32_t *result)
|
||||
int get_config_uint32(const struct config_node *cn, const char *path,
|
||||
uint32_t *result)
|
||||
{
|
||||
struct config_node *n;
|
||||
const struct config_node *n;
|
||||
|
||||
n = find_config_node(cn, path, sep);
|
||||
n = find_config_node(cn, path);
|
||||
|
||||
if (!n || !n->v || n->v->type != CFG_INT)
|
||||
return 0;
|
||||
@@ -861,12 +857,12 @@ int get_config_uint32(struct config_node *cn, const char *path,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int get_config_uint64(struct config_node *cn, const char *path,
|
||||
const int sep, uint64_t *result)
|
||||
int get_config_uint64(const struct config_node *cn, const char *path,
|
||||
uint64_t *result)
|
||||
{
|
||||
struct config_node *n;
|
||||
const struct config_node *n;
|
||||
|
||||
n = find_config_node(cn, path, sep);
|
||||
n = find_config_node(cn, path);
|
||||
|
||||
if (!n || !n->v || n->v->type != CFG_INT)
|
||||
return 0;
|
||||
@@ -876,12 +872,12 @@ int get_config_uint64(struct config_node *cn, const char *path,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int get_config_str(struct config_node *cn, const char *path,
|
||||
const int sep, char **result)
|
||||
int get_config_str(const struct config_node *cn, const char *path,
|
||||
char **result)
|
||||
{
|
||||
struct config_node *n;
|
||||
const struct config_node *n;
|
||||
|
||||
n = find_config_node(cn, path, sep);
|
||||
n = find_config_node(cn, path);
|
||||
|
||||
if (!n || !n->v || n->v->type != CFG_STRING)
|
||||
return 0;
|
||||
@@ -889,3 +885,115 @@ int get_config_str(struct config_node *cn, const char *path,
|
||||
*result = n->v->v.str;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Insert cn2 after cn1 */
|
||||
static void _insert_config_node(struct config_node **cn1,
|
||||
struct config_node *cn2)
|
||||
{
|
||||
if (!*cn1) {
|
||||
*cn1 = cn2;
|
||||
cn2->sib = NULL;
|
||||
} else {
|
||||
cn2->sib = (*cn1)->sib;
|
||||
(*cn1)->sib = cn2;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Merge section cn2 into section cn1 (which has the same name)
|
||||
* overwriting any existing cn1 nodes with matching names.
|
||||
*/
|
||||
static void _merge_section(struct config_node *cn1, struct config_node *cn2)
|
||||
{
|
||||
struct config_node *cn, *nextn, *oldn;
|
||||
struct config_value *cv;
|
||||
|
||||
for (cn = cn2->child; cn; cn = nextn) {
|
||||
nextn = cn->sib;
|
||||
|
||||
/* Skip "tags" */
|
||||
if (!strcmp(cn->key, "tags"))
|
||||
continue;
|
||||
|
||||
/* Subsection? */
|
||||
if (!cn->v)
|
||||
/* Ignore - we don't have any of these yet */
|
||||
continue;
|
||||
/* Not already present? */
|
||||
if (!(oldn = find_config_node(cn1->child, cn->key))) {
|
||||
_insert_config_node(&cn1->child, cn);
|
||||
continue;
|
||||
}
|
||||
/* Merge certain value lists */
|
||||
if ((!strcmp(cn1->key, "activation") &&
|
||||
!strcmp(cn->key, "volume_list")) ||
|
||||
(!strcmp(cn1->key, "devices") &&
|
||||
(!strcmp(cn->key, "filter") || !strcmp(cn->key, "types")))) {
|
||||
cv = cn->v;
|
||||
while (cv->next)
|
||||
cv = cv->next;
|
||||
cv->next = oldn->v;
|
||||
}
|
||||
|
||||
/* Replace values */
|
||||
oldn->v = cn->v;
|
||||
}
|
||||
}
|
||||
|
||||
static int _match_host_tags(struct list *tags, struct config_node *tn)
|
||||
{
|
||||
struct config_value *tv;
|
||||
const char *str;
|
||||
|
||||
for (tv = tn->v; tv; tv = tv->next) {
|
||||
if (tv->type != CFG_STRING)
|
||||
continue;
|
||||
str = tv->v.str;
|
||||
if (*str == '@')
|
||||
str++;
|
||||
if (!*str)
|
||||
continue;
|
||||
if (str_list_match_item(tags, str))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Destructively merge a new config tree into an existing one */
|
||||
int merge_config_tree(struct cmd_context *cmd, struct config_tree *cft,
|
||||
struct config_tree *newdata)
|
||||
{
|
||||
struct config_node *root = cft->root;
|
||||
struct config_node *cn, *nextn, *oldn, *tn, *cn2;
|
||||
|
||||
for (cn = newdata->root; cn; cn = nextn) {
|
||||
nextn = cn->sib;
|
||||
/* Ignore tags section */
|
||||
if (!strcmp(cn->key, "tags"))
|
||||
continue;
|
||||
/* If there's a tags node, skip if host tags don't match */
|
||||
if ((tn = find_config_node(cn->child, "tags"))) {
|
||||
if (!_match_host_tags(&cmd->tags, tn))
|
||||
continue;
|
||||
}
|
||||
if (!(oldn = find_config_node(root, cn->key))) {
|
||||
_insert_config_node(&cft->root, cn);
|
||||
/* Remove any "tags" nodes */
|
||||
for (cn2 = cn->child; cn2; cn2 = cn2->sib) {
|
||||
if (!strcmp(cn2->key, "tags")) {
|
||||
cn->child = cn2->sib;
|
||||
continue;
|
||||
}
|
||||
if (cn2->sib && !strcmp(cn2->sib->key, "tags")) {
|
||||
cn2->sib = cn2->sib->sib;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
_merge_section(oldn, cn);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,23 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_CONFIG_H
|
||||
#define _LVM_CONFIG_H
|
||||
|
||||
#include "device.h"
|
||||
struct device;
|
||||
struct cmd_context;
|
||||
|
||||
enum {
|
||||
CFG_STRING,
|
||||
@@ -36,46 +46,51 @@ struct config_tree {
|
||||
struct config_node *root;
|
||||
};
|
||||
|
||||
struct config_tree *create_config_tree(void);
|
||||
void destroy_config_tree(struct config_tree *cf);
|
||||
struct config_tree_list {
|
||||
struct list list;
|
||||
struct config_tree *cft;
|
||||
};
|
||||
|
||||
struct config_tree *create_config_tree(const char *filename);
|
||||
void destroy_config_tree(struct config_tree *cft);
|
||||
|
||||
typedef uint32_t (*checksum_fn_t) (uint32_t initial, void *buf, uint32_t size);
|
||||
|
||||
int read_config_fd(struct config_tree *cf, struct device *dev,
|
||||
int read_config_fd(struct config_tree *cft, struct device *dev,
|
||||
off_t offset, size_t size, off_t offset2, size_t size2,
|
||||
checksum_fn_t checksum_fn, uint32_t checksum);
|
||||
|
||||
int read_config_file(struct config_tree *cf, const char *file);
|
||||
int write_config_file(struct config_tree *cf, const char *file);
|
||||
int reload_config_file(struct config_tree **cf);
|
||||
time_t config_file_timestamp(struct config_tree *cf);
|
||||
int read_config_file(struct config_tree *cft);
|
||||
int write_config_file(struct config_tree *cft, const char *file);
|
||||
time_t config_file_timestamp(struct config_tree *cft);
|
||||
int config_file_changed(struct config_tree *cft);
|
||||
int merge_config_tree(struct cmd_context *cmd, struct config_tree *cft,
|
||||
struct config_tree *newdata);
|
||||
|
||||
struct config_node *find_config_node(struct config_node *cn,
|
||||
const char *path, const int separator);
|
||||
struct config_node *find_config_node(const struct config_node *cn,
|
||||
const char *path);
|
||||
|
||||
const char *find_config_str(struct config_node *cn,
|
||||
const char *path, const int sep, const char *fail);
|
||||
const char *find_config_str(const struct config_node *cn, const char *path,
|
||||
const char *fail);
|
||||
|
||||
int find_config_int(struct config_node *cn, const char *path,
|
||||
const int sep, int fail);
|
||||
int find_config_int(const struct config_node *cn, const char *path, int fail);
|
||||
|
||||
float find_config_float(struct config_node *cn, const char *path,
|
||||
const int sep, float fail);
|
||||
float find_config_float(const struct config_node *cn, const char *path,
|
||||
float fail);
|
||||
|
||||
/*
|
||||
* Understands (0, ~0), (y, n), (yes, no), (on,
|
||||
* off), (true, false).
|
||||
*/
|
||||
int find_config_bool(struct config_node *cn, const char *path,
|
||||
const int sep, int fail);
|
||||
int find_config_bool(const struct config_node *cn, const char *path, int fail);
|
||||
|
||||
int get_config_uint32(struct config_node *cn, const char *path,
|
||||
const int sep, uint32_t *result);
|
||||
int get_config_uint32(const struct config_node *cn, const char *path,
|
||||
uint32_t *result);
|
||||
|
||||
int get_config_uint64(struct config_node *cn, const char *path,
|
||||
const int sep, uint64_t *result);
|
||||
int get_config_uint64(const struct config_node *cn, const char *path,
|
||||
uint64_t *result);
|
||||
|
||||
int get_config_str(struct config_node *cn, const char *path,
|
||||
const int sep, char **result);
|
||||
int get_config_str(const struct config_node *cn, const char *path,
|
||||
char **result);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the GPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_DEFAULTS_H
|
||||
@@ -19,12 +28,20 @@
|
||||
#define DEFAULT_SYS_DIR "/etc/lvm"
|
||||
#define DEFAULT_DEV_DIR "/dev"
|
||||
#define DEFAULT_PROC_DIR "/proc"
|
||||
#define DEFAULT_SYSFS_SCAN 1
|
||||
#define DEFAULT_MD_COMPONENT_DETECTION 1
|
||||
|
||||
#define DEFAULT_LOCK_DIR "/var/lock/lvm"
|
||||
#define DEFAULT_LOCKING_LIB "lvm2_locking.so"
|
||||
|
||||
#define DEFAULT_UMASK 0077
|
||||
|
||||
#ifdef LVM1_FALLBACK
|
||||
# define DEFAULT_FALLBACK_TO_LVM1 1
|
||||
#else
|
||||
# define DEFAULT_FALLBACK_TO_LVM1 0
|
||||
#endif
|
||||
|
||||
#ifdef LVM1_SUPPORT
|
||||
# define DEFAULT_FORMAT "lvm1"
|
||||
#else
|
||||
@@ -50,6 +67,7 @@
|
||||
#define DEFAULT_INDENT 1
|
||||
#define DEFAULT_UNITS "h"
|
||||
#define DEFAULT_SUFFIX 1
|
||||
#define DEFAULT_HOSTTAGS 0
|
||||
|
||||
#ifdef DEVMAPPER_SUPPORT
|
||||
# define DEFAULT_ACTIVATION 1
|
||||
@@ -73,14 +91,14 @@
|
||||
#define DEFAULT_REP_HEADINGS 1
|
||||
#define DEFAULT_REP_SEPARATOR " "
|
||||
|
||||
#define DEFAULT_LVS_COLS "lv_name,vg_name,lv_attr,lv_size,origin,snap_percent,move_pv,move_percent"
|
||||
#define DEFAULT_LVS_COLS "lv_name,vg_name,lv_attr,lv_size,origin,snap_percent,move_pv,copy_percent"
|
||||
#define DEFAULT_VGS_COLS "vg_name,pv_count,lv_count,snap_count,vg_attr,vg_size,vg_free"
|
||||
#define DEFAULT_PVS_COLS "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free"
|
||||
#define DEFAULT_SEGS_COLS "lv_name,vg_name,lv_attr,stripes,segtype,seg_size"
|
||||
|
||||
#define DEFAULT_LVS_COLS_VERB "lv_name,vg_name,seg_count,lv_attr,lv_size,lv_major,lv_minor,origin,snap_percent,move_pv,move_percent,lv_uuid"
|
||||
#define DEFAULT_LVS_COLS_VERB "lv_name,vg_name,seg_count,lv_attr,lv_size,lv_major,lv_minor,lv_kernel_major,lv_kernel_minor,origin,snap_percent,move_pv,copy_percent,lv_uuid"
|
||||
#define DEFAULT_VGS_COLS_VERB "vg_name,vg_attr,vg_extent_size,pv_count,lv_count,snap_count,vg_size,vg_free,vg_uuid"
|
||||
#define DEFAULT_PVS_COLS_VERB "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pv_uuid"
|
||||
#define DEFAULT_PVS_COLS_VERB "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,dev_size,pv_uuid"
|
||||
#define DEFAULT_SEGS_COLS_VERB "lv_name,vg_name,lv_attr,seg_start,seg_size,stripes,segtype,stripesize,chunksize"
|
||||
|
||||
#define DEFAULT_LVS_SORT "vg_name,lv_name"
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the GPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_BITSET_H
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the GPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_BTREE_H
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -10,7 +19,8 @@
|
||||
struct hash_node {
|
||||
struct hash_node *next;
|
||||
void *data;
|
||||
char key[1];
|
||||
int keylen;
|
||||
char key[0];
|
||||
};
|
||||
|
||||
struct hash_table {
|
||||
@@ -47,22 +57,23 @@ static unsigned char _nums[] = {
|
||||
209
|
||||
};
|
||||
|
||||
static struct hash_node *_create_node(const char *str)
|
||||
static struct hash_node *_create_node(const char *str, int len)
|
||||
{
|
||||
/* remember sizeof(n) includes an extra char from key[1],
|
||||
so not adding 1 to the strlen as you would expect */
|
||||
struct hash_node *n = dbg_malloc(sizeof(*n) + strlen(str));
|
||||
struct hash_node *n = dbg_malloc(sizeof(*n) + len);
|
||||
|
||||
if (n)
|
||||
strcpy(n->key, str);
|
||||
if (n) {
|
||||
memcpy(n->key, str, len);
|
||||
n->keylen = len;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static unsigned _hash(const char *str)
|
||||
static unsigned _hash(const char *str, uint32_t len)
|
||||
{
|
||||
unsigned long h = 0, g;
|
||||
while (*str) {
|
||||
unsigned long h = 0, g, i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
h <<= 4;
|
||||
h += _nums[(int) *str++];
|
||||
g = h & ((unsigned long) 0xf << 16u);
|
||||
@@ -71,6 +82,7 @@ static unsigned _hash(const char *str)
|
||||
h ^= g >> 5u;
|
||||
}
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
@@ -125,32 +137,35 @@ void hash_destroy(struct hash_table *t)
|
||||
dbg_free(t);
|
||||
}
|
||||
|
||||
static inline struct hash_node **_find(struct hash_table *t, const char *key)
|
||||
static inline struct hash_node **_find(struct hash_table *t, const char *key,
|
||||
uint32_t len)
|
||||
{
|
||||
unsigned h = _hash(key) & (t->num_slots - 1);
|
||||
unsigned h = _hash(key, len) & (t->num_slots - 1);
|
||||
struct hash_node **c;
|
||||
|
||||
for (c = &t->slots[h]; *c; c = &((*c)->next))
|
||||
if (!strcmp(key, (*c)->key))
|
||||
if (!memcmp(key, (*c)->key, len))
|
||||
break;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
void *hash_lookup(struct hash_table *t, const char *key)
|
||||
void *hash_lookup_binary(struct hash_table *t, const char *key,
|
||||
uint32_t len)
|
||||
{
|
||||
struct hash_node **c = _find(t, key);
|
||||
struct hash_node **c = _find(t, key, len);
|
||||
return *c ? (*c)->data : 0;
|
||||
}
|
||||
|
||||
int hash_insert(struct hash_table *t, const char *key, void *data)
|
||||
int hash_insert_binary(struct hash_table *t, const char *key,
|
||||
uint32_t len, void *data)
|
||||
{
|
||||
struct hash_node **c = _find(t, key);
|
||||
struct hash_node **c = _find(t, key, len);
|
||||
|
||||
if (*c)
|
||||
(*c)->data = data;
|
||||
else {
|
||||
struct hash_node *n = _create_node(key);
|
||||
struct hash_node *n = _create_node(key, len);
|
||||
|
||||
if (!n)
|
||||
return 0;
|
||||
@@ -164,9 +179,10 @@ int hash_insert(struct hash_table *t, const char *key, void *data)
|
||||
return 1;
|
||||
}
|
||||
|
||||
void hash_remove(struct hash_table *t, const char *key)
|
||||
void hash_remove_binary(struct hash_table *t, const char *key,
|
||||
uint32_t len)
|
||||
{
|
||||
struct hash_node **c = _find(t, key);
|
||||
struct hash_node **c = _find(t, key, len);
|
||||
|
||||
if (*c) {
|
||||
struct hash_node *old = *c;
|
||||
@@ -176,6 +192,21 @@ void hash_remove(struct hash_table *t, const char *key)
|
||||
}
|
||||
}
|
||||
|
||||
void *hash_lookup(struct hash_table *t, const char *key)
|
||||
{
|
||||
return hash_lookup_binary(t, key, strlen(key) + 1);
|
||||
}
|
||||
|
||||
int hash_insert(struct hash_table *t, const char *key, void *data)
|
||||
{
|
||||
return hash_insert_binary(t, key, strlen(key) + 1, data);
|
||||
}
|
||||
|
||||
void hash_remove(struct hash_table *t, const char *key)
|
||||
{
|
||||
hash_remove_binary(t, key, strlen(key) + 1);
|
||||
}
|
||||
|
||||
unsigned hash_get_num_entries(struct hash_table *t)
|
||||
{
|
||||
return t->num_nodes;
|
||||
@@ -226,6 +257,6 @@ struct hash_node *hash_get_first(struct hash_table *t)
|
||||
|
||||
struct hash_node *hash_get_next(struct hash_table *t, struct hash_node *n)
|
||||
{
|
||||
unsigned h = _hash(n->key) & (t->num_slots - 1);
|
||||
unsigned h = _hash(n->key, n->keylen) & (t->num_slots - 1);
|
||||
return n->next ? n->next : _next_slot(t, h + 1);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the GPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_HASH_H
|
||||
@@ -17,10 +26,14 @@ void hash_destroy(struct hash_table *t);
|
||||
void hash_wipe(struct hash_table *t);
|
||||
|
||||
void *hash_lookup(struct hash_table *t, const char *key);
|
||||
void *hash_lookup_fixed(struct hash_table *t, const char *key, uint32_t len);
|
||||
int hash_insert(struct hash_table *t, const char *key, void *data);
|
||||
void hash_remove(struct hash_table *t, const char *key);
|
||||
|
||||
void *hash_lookup_binary(struct hash_table *t, const char *key, uint32_t len);
|
||||
int hash_insert_binary(struct hash_table *t, const char *key, uint32_t len,
|
||||
void *data);
|
||||
void hash_remove_binary(struct hash_table *t, const char *key, uint32_t len);
|
||||
|
||||
unsigned hash_get_num_entries(struct hash_table *t);
|
||||
void hash_iter(struct hash_table *t, iterate_fn f);
|
||||
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_LIST_H
|
||||
@@ -63,26 +72,6 @@ static inline struct list *list_next(struct list *head, struct list *elem)
|
||||
return (list_end(head, elem) ? NULL : elem->n);
|
||||
}
|
||||
|
||||
#define list_iterate(v, head) \
|
||||
for (v = (head)->n; v != head; v = v->n)
|
||||
|
||||
#define list_uniterate(v, head, start) \
|
||||
for (v = (start)->p; v != head; v = v->p)
|
||||
|
||||
#define list_iterate_safe(v, t, head) \
|
||||
for (v = (head)->n, t = v->n; v != head; v = t, t = v->n)
|
||||
|
||||
static inline unsigned int list_size(const struct list *head)
|
||||
{
|
||||
unsigned int s = 0;
|
||||
const struct list *v;
|
||||
|
||||
list_iterate(v, head)
|
||||
s++;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
#define list_item(v, t) \
|
||||
((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->list))
|
||||
|
||||
@@ -96,4 +85,28 @@ static inline unsigned int list_size(const struct list *head)
|
||||
/* Given a known element in a known structure, locate the list head */
|
||||
#define list_head(v, t, e) struct_field(v, t, e, list)
|
||||
|
||||
#define list_iterate(v, head) \
|
||||
for (v = (head)->n; v != head; v = v->n)
|
||||
|
||||
#define list_uniterate(v, head, start) \
|
||||
for (v = (start)->p; v != head; v = v->p)
|
||||
|
||||
#define list_iterate_safe(v, t, head) \
|
||||
for (v = (head)->n, t = v->n; v != head; v = t, t = v->n)
|
||||
|
||||
#define list_iterate_items(v, head) \
|
||||
for (v = list_item((head)->n, typeof(*v)); &v->list != (head); \
|
||||
v = list_item(v->list.n, typeof(*v)))
|
||||
|
||||
static inline unsigned int list_size(const struct list *head)
|
||||
{
|
||||
unsigned int s = 0;
|
||||
const struct list *v;
|
||||
|
||||
list_iterate(v, head)
|
||||
s++;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the GPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_TYPES_H
|
||||
|
||||
128
lib/datastruct/str_list.c
Normal file
128
lib/datastruct/str_list.c
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
#include "str_list.h"
|
||||
|
||||
struct list *str_list_create(struct pool *mem)
|
||||
{
|
||||
struct list *sl;
|
||||
|
||||
if (!(sl = pool_alloc(mem, sizeof(struct list)))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
list_init(sl);
|
||||
|
||||
return sl;
|
||||
}
|
||||
|
||||
int str_list_add(struct pool *mem, struct list *sll, const char *str)
|
||||
{
|
||||
struct str_list *sln;
|
||||
|
||||
if (!str) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Already in list? */
|
||||
if (str_list_match_item(sll, str))
|
||||
return 1;
|
||||
|
||||
if (!(sln = pool_alloc(mem, sizeof(*sln)))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
sln->str = str;
|
||||
list_add(sll, &sln->list);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int str_list_del(struct list *sll, const char *str)
|
||||
{
|
||||
struct list *slh, *slht;
|
||||
|
||||
list_iterate_safe(slh, slht, sll) {
|
||||
if (!strcmp(str, list_item(slh, struct str_list)->str))
|
||||
list_del(slh);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int str_list_dup(struct pool *mem, struct list *sllnew, struct list *sllold)
|
||||
{
|
||||
struct str_list *sl;
|
||||
|
||||
list_init(sllnew);
|
||||
|
||||
list_iterate_items(sl, sllold) {
|
||||
if (!str_list_add(mem, sllnew, strdup(sl->str))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Is item on list?
|
||||
*/
|
||||
int str_list_match_item(struct list *sll, const char *str)
|
||||
{
|
||||
struct str_list *sl;
|
||||
|
||||
list_iterate_items(sl, sll)
|
||||
if (!strcmp(str, sl->str))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Is at least one item on both lists?
|
||||
*/
|
||||
int str_list_match_list(struct list *sll, struct list *sll2)
|
||||
{
|
||||
struct str_list *sl;
|
||||
|
||||
list_iterate_items(sl, sll)
|
||||
if (str_list_match_item(sll2, sl->str))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do both lists contain the same set of items?
|
||||
*/
|
||||
int str_list_lists_equal(struct list *sll, struct list *sll2)
|
||||
{
|
||||
struct str_list *sl;
|
||||
|
||||
if (list_size(sll) != list_size(sll2))
|
||||
return 0;
|
||||
|
||||
list_iterate_items(sl, sll)
|
||||
if (!str_list_match_item(sll2, sl->str))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
29
lib/datastruct/str_list.h
Normal file
29
lib/datastruct/str_list.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_STR_LIST_H
|
||||
#define _LVM_STR_LIST_H
|
||||
|
||||
#include "pool.h"
|
||||
|
||||
struct list *str_list_create(struct pool *mem);
|
||||
int str_list_add(struct pool *mem, struct list *sll, const char *str);
|
||||
int str_list_del(struct list *sll, const char *str);
|
||||
int str_list_match_item(struct list *sll, const char *str);
|
||||
int str_list_match_list(struct list *sll, struct list *sll2);
|
||||
int str_list_lists_equal(struct list *sll, struct list *sll2);
|
||||
int str_list_dup(struct pool *mem, struct list *sllnew, struct list *sllold);
|
||||
|
||||
#endif
|
||||
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -73,6 +82,7 @@ struct device *dev_create_file(const char *filename, struct device *dev,
|
||||
dev->dev = 0;
|
||||
dev->fd = -1;
|
||||
dev->open_count = 0;
|
||||
dev->block_size = -1;
|
||||
memset(dev->pvid, 0, sizeof(dev->pvid));
|
||||
list_init(&dev->open_list);
|
||||
|
||||
@@ -92,6 +102,7 @@ static struct device *_dev_create(dev_t d)
|
||||
dev->dev = d;
|
||||
dev->fd = -1;
|
||||
dev->open_count = 0;
|
||||
dev->block_size = -1;
|
||||
dev->end = UINT64_C(0);
|
||||
memset(dev->pvid, 0, sizeof(dev->pvid));
|
||||
list_init(&dev->open_list);
|
||||
@@ -313,6 +324,17 @@ static int _insert(const char *path, int rec)
|
||||
}
|
||||
|
||||
if (S_ISDIR(info.st_mode)) { /* add a directory */
|
||||
/* check it's not a symbolic link */
|
||||
if (lstat(path, &info) < 0) {
|
||||
log_sys_very_verbose("lstat", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (S_ISLNK(info.st_mode)) {
|
||||
log_debug("%s: Symbolic link to directory", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rec)
|
||||
r = _insert_dir(path);
|
||||
|
||||
@@ -367,7 +389,7 @@ int dev_cache_init(void)
|
||||
{
|
||||
_cache.names = NULL;
|
||||
|
||||
if (!(_cache.mem = pool_create(10 * 1024))) {
|
||||
if (!(_cache.mem = pool_create("dev_cache", 10 * 1024))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -406,11 +428,22 @@ static inline void _check_for_open_devices(void)
|
||||
|
||||
void dev_cache_exit(void)
|
||||
{
|
||||
if (_cache.names)
|
||||
_check_for_open_devices();
|
||||
|
||||
if (_cache.mem) {
|
||||
pool_destroy(_cache.mem);
|
||||
if (_cache.names)
|
||||
_cache.mem = NULL;
|
||||
}
|
||||
|
||||
if (_cache.names) {
|
||||
hash_destroy(_cache.names);
|
||||
_cache.names = NULL;
|
||||
}
|
||||
|
||||
_cache.devices = NULL;
|
||||
_cache.has_scanned = 0;
|
||||
list_init(&_cache.dirs);
|
||||
}
|
||||
|
||||
int dev_cache_add_dir(const char *path)
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the GPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_DEV_CACHE_H
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -10,6 +19,7 @@
|
||||
#include "metadata.h"
|
||||
#include "lvmcache.h"
|
||||
#include "memlock.h"
|
||||
#include "locking.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <sys/stat.h>
|
||||
@@ -23,6 +33,9 @@
|
||||
# undef WUNTRACED /* Avoid redefinition */
|
||||
# include <linux/fs.h> /* For block ioctl definitions */
|
||||
# define BLKSIZE_SHIFT SECTOR_SHIFT
|
||||
# ifndef BLKGETSIZE64 /* fs.h out-of-date */
|
||||
# define BLKGETSIZE64 _IOR(0x12, 114, size_t)
|
||||
# endif /* BLKGETSIZE64 */
|
||||
#else
|
||||
# include <sys/disk.h>
|
||||
# define BLKBSZGET DKIOCGETBLOCKSIZE
|
||||
@@ -30,15 +43,13 @@
|
||||
# define BLKGETSIZE64 DKIOCGETBLOCKCOUNT
|
||||
# define BLKFLSBUF DKIOCSYNCHRONIZECACHE
|
||||
# define BLKSIZE_SHIFT 0
|
||||
# ifndef O_DIRECT
|
||||
# define O_DIRECT 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* FIXME Use _llseek for 64-bit
|
||||
_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo, loff_t *, res, uint, wh);
|
||||
if (_llseek((unsigned) fd, (ulong) (offset >> 32), (ulong) (offset & 0xFFFFFFFF), &pos, SEEK_SET) < 0) {
|
||||
*/
|
||||
#ifdef O_DIRECT_SUPPORT
|
||||
# ifndef O_DIRECT
|
||||
# error O_DIRECT support configured but O_DIRECT definition not found in headers
|
||||
# endif
|
||||
#endif
|
||||
|
||||
static LIST_INIT(_open_devices);
|
||||
|
||||
@@ -70,7 +81,9 @@ static int _io(struct device_area *where, void *buffer, int should_write)
|
||||
}
|
||||
|
||||
if (lseek(fd, (off_t) where->start, SEEK_SET) < 0) {
|
||||
log_sys_error("lseek", dev_name(where->dev));
|
||||
log_error("%s: lseek %" PRIu64 " failed: %s",
|
||||
dev_name(where->dev), (uint64_t) where->start,
|
||||
strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -81,6 +94,14 @@ static int _io(struct device_area *where, void *buffer, int should_write)
|
||||
read(fd, buffer, (size_t) where->size - total);
|
||||
while ((n < 0) && ((errno == EINTR) || (errno == EAGAIN)));
|
||||
|
||||
if (n < 0)
|
||||
log_error("%s: %s failed after %" PRIu64 " of %" PRIu64
|
||||
" at %" PRIu64 ": %s", dev_name(where->dev),
|
||||
should_write ? "write" : "read",
|
||||
(uint64_t) total,
|
||||
(uint64_t) where->size,
|
||||
(uint64_t) where->start, strerror(errno));
|
||||
|
||||
if (n <= 0)
|
||||
break;
|
||||
|
||||
@@ -103,14 +124,18 @@ static int _io(struct device_area *where, void *buffer, int should_write)
|
||||
*/
|
||||
static int _get_block_size(struct device *dev, unsigned int *size)
|
||||
{
|
||||
int s;
|
||||
const char *name = dev_name(dev);
|
||||
|
||||
if (ioctl(dev_fd(dev), BLKBSZGET, &s) < 0) {
|
||||
log_sys_error("ioctl BLKBSZGET", dev_name(dev));
|
||||
if ((dev->block_size == -1)) {
|
||||
if (ioctl(dev_fd(dev), BLKBSZGET, &dev->block_size) < 0) {
|
||||
log_sys_error("ioctl BLKBSZGET", name);
|
||||
return 0;
|
||||
}
|
||||
log_debug("%s: block size is %u bytes", name, dev->block_size);
|
||||
}
|
||||
|
||||
*size = (unsigned int) dev->block_size;
|
||||
|
||||
*size = (unsigned int) s;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -151,7 +176,7 @@ static int _aligned_io(struct device_area *where, void *buffer,
|
||||
}
|
||||
|
||||
if (!block_size)
|
||||
block_size = SECTOR_SIZE * 2;
|
||||
block_size = getpagesize();
|
||||
|
||||
_widen_region(block_size, where, &widened);
|
||||
|
||||
@@ -201,12 +226,11 @@ static int _aligned_io(struct device_area *where, void *buffer,
|
||||
* Public functions
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
int dev_get_size(struct device *dev, uint64_t *size)
|
||||
int dev_get_size(const struct device *dev, uint64_t *size)
|
||||
{
|
||||
int fd;
|
||||
const char *name = dev_name(dev);
|
||||
|
||||
log_very_verbose("Getting size of %s", name);
|
||||
if ((fd = open(name, O_RDONLY)) < 0) {
|
||||
log_sys_error("open", name);
|
||||
return 0;
|
||||
@@ -214,22 +238,27 @@ int dev_get_size(struct device *dev, uint64_t *size)
|
||||
|
||||
if (ioctl(fd, BLKGETSIZE64, size) < 0) {
|
||||
log_sys_error("ioctl BLKGETSIZE64", name);
|
||||
close(fd);
|
||||
if (close(fd))
|
||||
log_sys_error("close", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*size >>= BLKSIZE_SHIFT; /* Convert to sectors */
|
||||
close(fd);
|
||||
if (close(fd))
|
||||
log_sys_error("close", name);
|
||||
|
||||
log_very_verbose("%s: size is %" PRIu64 " sectors", name, *size);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* FIXME Unused
|
||||
int dev_get_sectsize(struct device *dev, uint32_t *size)
|
||||
{
|
||||
int fd;
|
||||
int s;
|
||||
const char *name = dev_name(dev);
|
||||
|
||||
log_very_verbose("Getting size of %s", name);
|
||||
if ((fd = open(name, O_RDONLY)) < 0) {
|
||||
log_sys_error("open", name);
|
||||
return 0;
|
||||
@@ -243,8 +272,12 @@ int dev_get_sectsize(struct device *dev, uint32_t *size)
|
||||
|
||||
close(fd);
|
||||
*size = (uint32_t) s;
|
||||
|
||||
log_very_verbose("%s: sector size is %" PRIu32 " bytes", name, *size);
|
||||
|
||||
return 1;
|
||||
}
|
||||
*/
|
||||
|
||||
void dev_flush(struct device *dev)
|
||||
{
|
||||
@@ -263,10 +296,22 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
|
||||
const char *name;
|
||||
|
||||
if (dev->fd >= 0) {
|
||||
if ((dev->flags & DEV_OPENED_RW) ||
|
||||
((flags & O_ACCMODE) != O_RDWR)) {
|
||||
dev->open_count++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (dev->open_count) {
|
||||
/* FIXME Ensure we never get here */
|
||||
log_debug("WARNING: %s already opened read-only",
|
||||
dev_name(dev));
|
||||
dev->open_count++;
|
||||
}
|
||||
|
||||
dev_close_immediate(dev);
|
||||
}
|
||||
|
||||
if (memlock())
|
||||
log_error("WARNING: dev_open(%s) called while suspended",
|
||||
dev_name(dev));
|
||||
@@ -284,49 +329,69 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef O_DIRECT_SUPPORT
|
||||
if (direct)
|
||||
flags |= O_DIRECT;
|
||||
#endif
|
||||
|
||||
#ifdef O_NOATIME
|
||||
/* Don't update atime on device inodes */
|
||||
if (!(dev->flags & DEV_REGULAR))
|
||||
flags |= O_NOATIME;
|
||||
#endif
|
||||
|
||||
if ((dev->fd = open(name, flags, 0777)) < 0) {
|
||||
log_sys_error("open", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dev->open_count = 1;
|
||||
dev->open_count++;
|
||||
dev->flags &= ~DEV_ACCESSED_W;
|
||||
if ((flags & O_ACCMODE) == O_RDWR)
|
||||
dev->flags |= DEV_OPENED_RW;
|
||||
else
|
||||
dev->flags &= ~DEV_OPENED_RW;
|
||||
|
||||
if (!(dev->flags & DEV_REGULAR) &&
|
||||
((fstat(dev->fd, &buf) < 0) || (buf.st_rdev != dev->dev))) {
|
||||
log_error("%s: fstat failed: Has device name changed?", name);
|
||||
dev_close(dev);
|
||||
dev->fd = -1;
|
||||
dev_close_immediate(dev);
|
||||
dev->open_count = 0;
|
||||
return 0;
|
||||
}
|
||||
#if !O_DIRECT
|
||||
|
||||
#ifndef O_DIRECT_SUPPORT
|
||||
if (!(dev->flags & DEV_REGULAR))
|
||||
dev_flush(dev);
|
||||
#endif
|
||||
|
||||
if ((flags & O_CREAT) && !(flags & O_TRUNC)) {
|
||||
if ((flags & O_CREAT) && !(flags & O_TRUNC))
|
||||
dev->end = lseek(dev->fd, (off_t) 0, SEEK_END);
|
||||
}
|
||||
|
||||
list_add(&_open_devices, &dev->open_list);
|
||||
log_debug("Opened %s", dev_name(dev));
|
||||
|
||||
log_debug("Opened %s %s", dev_name(dev),
|
||||
dev->flags & DEV_OPENED_RW ? "RW" : "RO");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int dev_open_quiet(struct device *dev)
|
||||
{
|
||||
/* FIXME Open O_RDONLY if vg read lock? */
|
||||
return dev_open_flags(dev, O_RDWR, 1, 1);
|
||||
int flags;
|
||||
|
||||
flags = vg_write_lock_held() ? O_RDWR : O_RDONLY;
|
||||
|
||||
return dev_open_flags(dev, flags, 1, 1);
|
||||
}
|
||||
|
||||
int dev_open(struct device *dev)
|
||||
{
|
||||
/* FIXME Open O_RDONLY if vg read lock? */
|
||||
return dev_open_flags(dev, O_RDWR, 1, 0);
|
||||
int flags;
|
||||
|
||||
flags = vg_write_lock_held() ? O_RDWR : O_RDONLY;
|
||||
|
||||
return dev_open_flags(dev, flags, 1, 0);
|
||||
}
|
||||
|
||||
static void _close(struct device *dev)
|
||||
@@ -334,6 +399,7 @@ static void _close(struct device *dev)
|
||||
if (close(dev->fd))
|
||||
log_sys_error("close", dev_name(dev));
|
||||
dev->fd = -1;
|
||||
dev->block_size = -1;
|
||||
list_del(&dev->open_list);
|
||||
|
||||
log_debug("Closed %s", dev_name(dev));
|
||||
@@ -346,25 +412,39 @@ static void _close(struct device *dev)
|
||||
}
|
||||
}
|
||||
|
||||
int dev_close(struct device *dev)
|
||||
static int _dev_close(struct device *dev, int immediate)
|
||||
{
|
||||
if (dev->fd < 0) {
|
||||
log_error("Attempt to close device '%s' "
|
||||
"which is not open.", dev_name(dev));
|
||||
return 0;
|
||||
}
|
||||
#if !O_DIRECT
|
||||
|
||||
#ifndef O_DIRECT_SUPPORT
|
||||
if (dev->flags & DEV_ACCESSED_W)
|
||||
dev_flush(dev);
|
||||
#endif
|
||||
|
||||
if (dev->open_count > 0)
|
||||
dev->open_count--;
|
||||
|
||||
/* FIXME lookup device in cache to get vgname and see if it's locked? */
|
||||
if (--dev->open_count < 1 && !vgs_locked())
|
||||
if (immediate || (dev->open_count < 1 && !vgs_locked()))
|
||||
_close(dev);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int dev_close(struct device *dev)
|
||||
{
|
||||
return _dev_close(dev, 0);
|
||||
}
|
||||
|
||||
int dev_close_immediate(struct device *dev)
|
||||
{
|
||||
return _dev_close(dev, 1);
|
||||
}
|
||||
|
||||
void dev_close_all(void)
|
||||
{
|
||||
struct list *doh, *doht;
|
||||
@@ -381,8 +461,10 @@ int dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer)
|
||||
{
|
||||
struct device_area where;
|
||||
|
||||
if (!dev->open_count)
|
||||
if (!dev->open_count) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
where.dev = dev;
|
||||
where.start = offset;
|
||||
@@ -400,13 +482,15 @@ int dev_append(struct device *dev, size_t len, void *buffer)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (!dev->open_count)
|
||||
if (!dev->open_count) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = dev_write(dev, dev->end, len, buffer);
|
||||
dev->end += (uint64_t) len;
|
||||
|
||||
#if !O_DIRECT
|
||||
#ifndef O_DIRECT_SUPPORT
|
||||
dev_flush(dev);
|
||||
#endif
|
||||
return r;
|
||||
@@ -416,8 +500,10 @@ int dev_write(struct device *dev, uint64_t offset, size_t len, void *buffer)
|
||||
{
|
||||
struct device_area where;
|
||||
|
||||
if (!dev->open_count)
|
||||
if (!dev->open_count) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
where.dev = dev;
|
||||
where.start = offset;
|
||||
@@ -455,6 +541,8 @@ int dev_zero(struct device *dev, uint64_t offset, size_t len)
|
||||
len -= s;
|
||||
if (!len)
|
||||
break;
|
||||
|
||||
offset += s;
|
||||
}
|
||||
|
||||
dev->flags |= DEV_ACCESSED_W;
|
||||
@@ -462,6 +550,5 @@ int dev_zero(struct device *dev, uint64_t offset, size_t len)
|
||||
if (!dev_close(dev))
|
||||
stack;
|
||||
|
||||
/* FIXME: Always display error */
|
||||
return (len == 0);
|
||||
}
|
||||
|
||||
69
lib/device/dev-md.c
Normal file
69
lib/device/dev-md.c
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (C) 2004 Luca Berra
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU 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 "metadata.h"
|
||||
#include "xlate.h"
|
||||
|
||||
/* Lifted from <linux/raid/md_p.h> because of difficulty including it */
|
||||
|
||||
#define MD_SB_MAGIC 0xa92b4efc
|
||||
#define MD_RESERVED_BYTES (64 * 1024)
|
||||
#define MD_RESERVED_SECTORS (MD_RESERVED_BYTES / 512)
|
||||
#define MD_NEW_SIZE_SECTORS(x) ((x & ~(MD_RESERVED_SECTORS - 1)) \
|
||||
- MD_RESERVED_SECTORS)
|
||||
|
||||
/*
|
||||
* Returns -1 on error
|
||||
*/
|
||||
int dev_is_md(struct device *dev, uint64_t *sb)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
#ifdef linux
|
||||
|
||||
uint64_t size, sb_offset;
|
||||
uint32_t md_magic;
|
||||
|
||||
if (!dev_get_size(dev, &size)) {
|
||||
stack;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (size < MD_RESERVED_SECTORS * 2)
|
||||
return 0;
|
||||
|
||||
if (!dev_open(dev)) {
|
||||
stack;
|
||||
return -1;
|
||||
}
|
||||
|
||||
sb_offset = MD_NEW_SIZE_SECTORS(size) << SECTOR_SHIFT;
|
||||
|
||||
/* Check if it is an md component device. */
|
||||
if (dev_read(dev, sb_offset, sizeof(uint32_t), &md_magic) &&
|
||||
(md_magic == xlate32(MD_SB_MAGIC))) {
|
||||
if (sb)
|
||||
*sb = sb_offset;
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
if (!dev_close(dev))
|
||||
stack;
|
||||
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1,22 +1,105 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This LVM library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This LVM library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this LVM library; if not, write to the Free
|
||||
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
* MA 02111-1307, USA
|
||||
* You should have received a copy of the GNU 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 "lvm-types.h"
|
||||
#include "device.h"
|
||||
#include "metadata.h"
|
||||
#include "filter.h"
|
||||
#include "xlate.h"
|
||||
|
||||
/* See linux/genhd.h and fs/partitions/msdos */
|
||||
|
||||
#define PART_MAGIC 0xAA55
|
||||
#define PART_MAGIC_OFFSET UINT64_C(0x1FE)
|
||||
#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;
|
||||
} __attribute__((packed));
|
||||
|
||||
static int _is_partitionable(struct device *dev)
|
||||
{
|
||||
int parts = max_partitions(MAJOR(dev->dev));
|
||||
|
||||
if ((parts <= 1) || (MINOR(dev->dev) % parts))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _has_partition_table(struct device *dev)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned p;
|
||||
uint8_t buf[SECTOR_SIZE];
|
||||
uint16_t *part_magic;
|
||||
struct partition *part;
|
||||
|
||||
if (!dev_open(dev)) {
|
||||
stack;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!dev_read(dev, 0, sizeof(buf), &buf)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* FIXME Check for other types of partition table too */
|
||||
|
||||
/* Check for msdos partition table */
|
||||
part_magic = (uint16_t *)(buf + PART_MAGIC_OFFSET);
|
||||
if ((*part_magic == xlate16(PART_MAGIC))) {
|
||||
part = (struct partition *) (buf + PART_OFFSET);
|
||||
for (p = 0; p < 4; p++, part++) {
|
||||
/* Table is invalid if boot indicator not 0 or 0x80 */
|
||||
if ((part->boot_ind & 0x7f)) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
/* Must have at least one non-empty partition */
|
||||
if (part->nr_sects)
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
if (!dev_close(dev))
|
||||
stack;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int is_partitioned_dev(struct device *dev)
|
||||
{
|
||||
if (!_is_partitionable(dev))
|
||||
return 0;
|
||||
|
||||
return _has_partition_table(dev);
|
||||
}
|
||||
|
||||
#if 0
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
@@ -31,24 +114,13 @@
|
||||
#include <linux/major.h>
|
||||
#include <linux/genhd.h>
|
||||
|
||||
#include "dbg_malloc.h"
|
||||
#include "log.h"
|
||||
#include "dev-cache.h"
|
||||
#include "metadata.h"
|
||||
#include "device.h"
|
||||
|
||||
int _get_partition_type(struct dev_filter *filter, struct device *d);
|
||||
|
||||
#define MINOR_PART(dm, d) (MINOR((d)->dev) % dev_max_partitions(dm, (d)->dev))
|
||||
#define MINOR_PART(dev) (MINOR((dev)->dev) % max_partitions(MINOR((dev)->dev)))
|
||||
|
||||
int is_whole_disk(struct dev_filter *filter, struct device *d)
|
||||
int is_extended_partition(struct device *d)
|
||||
{
|
||||
return (MINOR_PART(dm, d)) ? 0 : 1;
|
||||
}
|
||||
|
||||
int is_extended_partition(struct dev_mgr *dm, struct device *d)
|
||||
{
|
||||
return (MINOR_PART(dm, d) > 4) ? 1 : 0;
|
||||
return (MINOR_PART(d) > 4) ? 1 : 0;
|
||||
}
|
||||
|
||||
struct device *dev_primary(struct dev_mgr *dm, struct device *d)
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the GPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_DEVICE_H
|
||||
@@ -13,6 +22,7 @@
|
||||
#define DEV_ACCESSED_W 0x00000001 /* Device written to? */
|
||||
#define DEV_REGULAR 0x00000002 /* Regular file? */
|
||||
#define DEV_ALLOCED 0x00000004 /* dbg_malloc used */
|
||||
#define DEV_OPENED_RW 0x00000008 /* Opened RW */
|
||||
|
||||
/*
|
||||
* All devices in LVM will be represented by one of these.
|
||||
@@ -25,6 +35,7 @@ struct device {
|
||||
/* private */
|
||||
int fd;
|
||||
int open_count;
|
||||
int block_size;
|
||||
uint32_t flags;
|
||||
uint64_t end;
|
||||
struct list open_list;
|
||||
@@ -46,7 +57,7 @@ struct device_area {
|
||||
/*
|
||||
* All io should use these routines.
|
||||
*/
|
||||
int dev_get_size(struct device *dev, uint64_t *size);
|
||||
int dev_get_size(const struct device *dev, uint64_t *size);
|
||||
int dev_get_sectsize(struct device *dev, uint32_t *size);
|
||||
|
||||
/* Use quiet version if device number could change e.g. when opening LV */
|
||||
@@ -54,6 +65,7 @@ int dev_open(struct device *dev);
|
||||
int dev_open_quiet(struct device *dev);
|
||||
int dev_open_flags(struct device *dev, int flags, int append, int quiet);
|
||||
int dev_close(struct device *dev);
|
||||
int dev_close_immediate(struct device *dev);
|
||||
void dev_close_all(void);
|
||||
|
||||
static inline int dev_fd(struct device *dev)
|
||||
@@ -79,15 +91,14 @@ static inline const char *dev_name(const struct device *dev)
|
||||
/* Return a valid device name from the alias list; NULL otherwise */
|
||||
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); */
|
||||
|
||||
/*
|
||||
static inline int is_lvm_partition(const char *name)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
*/
|
||||
int is_partitioned_dev(struct device *dev);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,21 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This LVM library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This LVM library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this LVM library; if not, write to the Free
|
||||
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
* MA 02111-1307, USA
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -23,6 +18,7 @@
|
||||
#include "display.h"
|
||||
#include "activate.h"
|
||||
#include "toolcontext.h"
|
||||
#include "segtype.h"
|
||||
|
||||
#define SIZE_BUF 128
|
||||
|
||||
@@ -31,23 +27,13 @@ static struct {
|
||||
const char *str;
|
||||
} _policies[] = {
|
||||
{
|
||||
ALLOC_NEXT_FREE, "next free"}, {
|
||||
ALLOC_CONTIGUOUS, "contiguous"}, {
|
||||
ALLOC_DEFAULT, "next free (default)"}
|
||||
};
|
||||
|
||||
static struct {
|
||||
segment_type_t segtype;
|
||||
const char *str;
|
||||
} _segtypes[] = {
|
||||
{
|
||||
SEG_STRIPED, "striped"}, {
|
||||
SEG_MIRRORED, "mirror"}, {
|
||||
SEG_SNAPSHOT, "snapshot"}
|
||||
ALLOC_NORMAL, "normal"}, {
|
||||
ALLOC_ANYWHERE, "anywhere"}, {
|
||||
ALLOC_INHERIT, "inherit"}
|
||||
};
|
||||
|
||||
static int _num_policies = sizeof(_policies) / sizeof(*_policies);
|
||||
static int _num_segtypes = sizeof(_segtypes) / sizeof(*_segtypes);
|
||||
|
||||
uint64_t units_to_bytes(const char *units, char *unit_type)
|
||||
{
|
||||
@@ -129,17 +115,6 @@ const char *get_alloc_string(alloc_policy_t alloc)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *get_segtype_string(segment_type_t segtype)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < _num_segtypes; i++)
|
||||
if (_segtypes[i].segtype == segtype)
|
||||
return _segtypes[i].str;
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
alloc_policy_t get_alloc_from_string(const char *str)
|
||||
{
|
||||
int i;
|
||||
@@ -148,26 +123,19 @@ alloc_policy_t get_alloc_from_string(const char *str)
|
||||
if (!strcmp(_policies[i].str, str))
|
||||
return _policies[i].alloc;
|
||||
|
||||
log_error("Unrecognised allocation policy - using default");
|
||||
return ALLOC_DEFAULT;
|
||||
}
|
||||
|
||||
segment_type_t get_segtype_from_string(const char *str)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < _num_segtypes; i++)
|
||||
if (!strcmp(_segtypes[i].str, str))
|
||||
return _segtypes[i].segtype;
|
||||
|
||||
log_error("Unrecognised segment type - using default (striped)");
|
||||
return SEG_STRIPED;
|
||||
/* Special case for old metadata */
|
||||
if(!strcmp("next free", str))
|
||||
return ALLOC_NORMAL;
|
||||
|
||||
log_error("Unrecognised allocation policy %s", str);
|
||||
return ALLOC_INVALID;
|
||||
}
|
||||
|
||||
/* Size supplied in sectors */
|
||||
const char *display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl)
|
||||
{
|
||||
int s;
|
||||
int suffix = 1;
|
||||
int suffix = 1, precision;
|
||||
uint64_t byte = UINT64_C(0);
|
||||
uint64_t units = UINT64_C(1024);
|
||||
char *size_buf = NULL;
|
||||
@@ -202,8 +170,9 @@ const char *display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl)
|
||||
|
||||
if (s < 8) {
|
||||
byte = cmd->current_settings.unit_factor;
|
||||
size *= UINT64_C(1024);
|
||||
size *= UINT64_C(512);
|
||||
} else {
|
||||
size /= 2;
|
||||
suffix = 1;
|
||||
if (cmd->current_settings.unit_type == 'H')
|
||||
units = UINT64_C(1000);
|
||||
@@ -215,8 +184,18 @@ const char *display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl)
|
||||
s++, byte /= units;
|
||||
}
|
||||
|
||||
snprintf(size_buf, SIZE_BUF - 1, "%.2f%s", (float) size / byte,
|
||||
suffix ? size_str[s][sl] : "");
|
||||
/* FIXME Make precision configurable */
|
||||
switch(toupper((int) cmd->current_settings.unit_type)) {
|
||||
case 'B':
|
||||
case 'S':
|
||||
precision = 0;
|
||||
break;
|
||||
default:
|
||||
precision = 2;
|
||||
}
|
||||
|
||||
snprintf(size_buf, SIZE_BUF - 1, "%.*f%s", precision,
|
||||
(double) size / byte, suffix ? size_str[s][sl] : "");
|
||||
|
||||
return size_buf;
|
||||
}
|
||||
@@ -269,17 +248,17 @@ void pvdisplay_full(struct cmd_context *cmd, struct physical_volume *pv,
|
||||
log_print("VG Name %s%s", pv->vg_name,
|
||||
pv->status & EXPORTED_VG ? " (exported)" : "");
|
||||
|
||||
size = display_size(cmd, (uint64_t) pv->size / 2, SIZE_SHORT);
|
||||
size = display_size(cmd, (uint64_t) pv->size, SIZE_SHORT);
|
||||
if (pv->pe_size && pv->pe_count) {
|
||||
|
||||
/******** FIXME display LVM on-disk data size
|
||||
size2 = display_size(pv->size / 2, SIZE_SHORT);
|
||||
size2 = display_size(pv->size, SIZE_SHORT);
|
||||
********/
|
||||
|
||||
log_print("PV Size %s" " / not usable %s", /* [LVM: %s]", */
|
||||
size, display_size(cmd,
|
||||
(pv->size -
|
||||
pv->pe_count * pv->pe_size) / 2,
|
||||
size,
|
||||
display_size(cmd, (pv->size -
|
||||
pv->pe_count * pv->pe_size),
|
||||
SIZE_SHORT));
|
||||
|
||||
} else
|
||||
@@ -391,8 +370,7 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
snap_active = lv_snapshot_percent(snap->cow,
|
||||
&snap_percent);
|
||||
if (!snap_active || snap_percent < 0 ||
|
||||
snap_percent >= 100)
|
||||
snap_active = 0;
|
||||
snap_percent >= 100) snap_active = 0;
|
||||
log_print(" %s%s/%s [%s]",
|
||||
lv->vg->cmd->dev_dir, lv->vg->name,
|
||||
snap->cow->name,
|
||||
@@ -424,7 +402,7 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
|
||||
log_print("LV Size %s",
|
||||
display_size(cmd,
|
||||
snap ? snap->origin->size / 2 : lv->size / 2,
|
||||
snap ? snap->origin->size : lv->size,
|
||||
SIZE_SHORT));
|
||||
|
||||
log_print("Current LE %u",
|
||||
@@ -445,11 +423,11 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
snap_percent = 100;
|
||||
|
||||
log_print("Snapshot chunk size %s",
|
||||
display_size(cmd, (uint64_t) snap->chunk_size / 2,
|
||||
display_size(cmd, (uint64_t) snap->chunk_size,
|
||||
SIZE_SHORT));
|
||||
|
||||
/*
|
||||
size = display_size(lv->size / 2, SIZE_SHORT);
|
||||
size = display_size(lv->size, SIZE_SHORT);
|
||||
sscanf(size, "%f", &fsize);
|
||||
fused = fsize * snap_percent / 100;
|
||||
*/
|
||||
@@ -483,7 +461,7 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _display_stripe(struct lv_segment *seg, uint32_t s, const char *pre)
|
||||
void display_stripe(const struct lv_segment *seg, uint32_t s, const char *pre)
|
||||
{
|
||||
switch (seg->area[s].type) {
|
||||
case AREA_PV:
|
||||
@@ -511,52 +489,18 @@ static void _display_stripe(struct lv_segment *seg, uint32_t s, const char *pre)
|
||||
|
||||
int lvdisplay_segments(struct logical_volume *lv)
|
||||
{
|
||||
uint32_t s;
|
||||
struct list *segh;
|
||||
struct lv_segment *seg;
|
||||
|
||||
log_print("--- Segments ---");
|
||||
|
||||
list_iterate(segh, &lv->segments) {
|
||||
seg = list_item(segh, struct lv_segment);
|
||||
|
||||
list_iterate_items(seg, &lv->segments) {
|
||||
log_print("Logical extent %u to %u:",
|
||||
seg->le, seg->le + seg->len - 1);
|
||||
|
||||
if (seg->type == SEG_STRIPED && seg->area_count == 1)
|
||||
log_print(" Type\t\tlinear");
|
||||
else
|
||||
log_print(" Type\t\t%s",
|
||||
get_segtype_string(seg->type));
|
||||
log_print(" Type\t\t%s", seg->segtype->ops->name(seg));
|
||||
|
||||
switch (seg->type) {
|
||||
case SEG_STRIPED:
|
||||
if (seg->area_count == 1)
|
||||
_display_stripe(seg, 0, " ");
|
||||
else {
|
||||
log_print(" Stripes\t\t%u", seg->area_count);
|
||||
log_print(" Stripe size\t\t%u KB",
|
||||
seg->stripe_size / 2);
|
||||
|
||||
for (s = 0; s < seg->area_count; s++) {
|
||||
log_print(" Stripe %d:", s);
|
||||
_display_stripe(seg, s, " ");
|
||||
}
|
||||
}
|
||||
log_print(" ");
|
||||
break;
|
||||
case SEG_SNAPSHOT:
|
||||
break;
|
||||
case SEG_MIRRORED:
|
||||
log_print(" Mirrors\t\t%u", seg->area_count);
|
||||
log_print(" Mirror size\t\t%u", seg->area_len);
|
||||
log_print(" Mirror original:");
|
||||
_display_stripe(seg, 0, " ");
|
||||
log_print(" Mirror destination:");
|
||||
_display_stripe(seg, 1, " ");
|
||||
log_print(" ");
|
||||
break;
|
||||
}
|
||||
if (seg->segtype->ops->display)
|
||||
seg->segtype->ops->display(seg);
|
||||
}
|
||||
|
||||
log_print(" ");
|
||||
@@ -610,7 +554,7 @@ void vgdisplay_full(struct volume_group *vg)
|
||||
log_print("Open LV %u", lvs_in_vg_opened(vg));
|
||||
/****** FIXME Max LV Size
|
||||
log_print ( "MAX LV Size %s",
|
||||
( s1 = display_size ( LVM_LV_SIZE_MAX(vg) / 2, SIZE_SHORT)));
|
||||
( s1 = display_size ( LVM_LV_SIZE_MAX(vg), SIZE_SHORT)));
|
||||
free ( s1);
|
||||
*********/
|
||||
log_print("Max PV %u", vg->max_pv);
|
||||
@@ -619,32 +563,25 @@ void vgdisplay_full(struct volume_group *vg)
|
||||
|
||||
log_print("VG Size %s",
|
||||
display_size(vg->cmd,
|
||||
(uint64_t) vg->extent_count * (vg->extent_size /
|
||||
2), SIZE_SHORT));
|
||||
(uint64_t) vg->extent_count * vg->extent_size,
|
||||
SIZE_SHORT));
|
||||
|
||||
log_print("PE Size %s",
|
||||
display_size(vg->cmd, (uint64_t) vg->extent_size / 2,
|
||||
display_size(vg->cmd, (uint64_t) vg->extent_size,
|
||||
SIZE_SHORT));
|
||||
|
||||
log_print("Total PE %u", vg->extent_count);
|
||||
|
||||
log_print("Alloc PE / Size %u / %s",
|
||||
vg->extent_count - vg->free_count, display_size(vg->cmd,
|
||||
((uint64_t)
|
||||
vg->
|
||||
extent_count
|
||||
-
|
||||
vg->
|
||||
free_count) *
|
||||
(vg->
|
||||
extent_size /
|
||||
2),
|
||||
SIZE_SHORT));
|
||||
vg->extent_count - vg->free_count,
|
||||
display_size(vg->cmd,
|
||||
((uint64_t) vg->extent_count - vg->free_count) *
|
||||
vg->extent_size, SIZE_SHORT));
|
||||
|
||||
log_print("Free PE / Size %u / %s", vg->free_count,
|
||||
display_size(vg->cmd,
|
||||
(uint64_t) vg->free_count * (vg->extent_size /
|
||||
2), SIZE_SHORT));
|
||||
(uint64_t) vg->free_count * vg->extent_size,
|
||||
SIZE_SHORT));
|
||||
|
||||
if (!id_write_format(&vg->id, uuid, sizeof(uuid))) {
|
||||
stack;
|
||||
@@ -659,6 +596,53 @@ void vgdisplay_full(struct volume_group *vg)
|
||||
|
||||
void vgdisplay_colons(struct volume_group *vg)
|
||||
{
|
||||
uint32_t active_pvs;
|
||||
const char *access;
|
||||
char uuid[64];
|
||||
|
||||
if (vg->status & PARTIAL_VG)
|
||||
active_pvs = list_size(&vg->pvs);
|
||||
else
|
||||
active_pvs = vg->pv_count;
|
||||
|
||||
switch (vg->status & (LVM_READ | LVM_WRITE)) {
|
||||
case LVM_READ | LVM_WRITE:
|
||||
access = "r/w";
|
||||
break;
|
||||
case LVM_READ:
|
||||
access = "r";
|
||||
break;
|
||||
case LVM_WRITE:
|
||||
access = "w";
|
||||
break;
|
||||
default:
|
||||
access = "";
|
||||
}
|
||||
|
||||
if (!id_write_format(&vg->id, uuid, sizeof(uuid))) {
|
||||
stack;
|
||||
return;
|
||||
}
|
||||
|
||||
log_print("%s:%s:%d:-1:%u:%u:%u:-1:%u:%u:%u:%" PRIu64 ":%" PRIu32
|
||||
":%u:%u:%u:%s",
|
||||
vg->name,
|
||||
access,
|
||||
vg->status,
|
||||
/* internal volume group number; obsolete */
|
||||
vg->max_lv,
|
||||
vg->lv_count,
|
||||
lvs_in_vg_opened(vg),
|
||||
/* FIXME: maximum logical volume size */
|
||||
vg->max_pv,
|
||||
vg->pv_count,
|
||||
active_pvs,
|
||||
(uint64_t) vg->extent_count * (vg->extent_size / 2),
|
||||
vg->extent_size / 2,
|
||||
vg->extent_count,
|
||||
vg->extent_count - vg->free_count,
|
||||
vg->free_count,
|
||||
uuid[0] ? uuid : "none");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -666,15 +650,34 @@ void vgdisplay_short(struct volume_group *vg)
|
||||
{
|
||||
log_print("\"%s\" %-9s [%-9s used / %s free]", vg->name,
|
||||
/********* FIXME if "open" print "/used" else print "/idle"??? ******/
|
||||
display_size(vg->cmd, (uint64_t) vg->extent_count *
|
||||
vg->extent_size / 2, SIZE_SHORT),
|
||||
display_size(vg->cmd,
|
||||
(uint64_t) vg->extent_count * vg->extent_size,
|
||||
SIZE_SHORT),
|
||||
display_size(vg->cmd,
|
||||
((uint64_t) vg->extent_count -
|
||||
vg->free_count) * vg->extent_size / 2,
|
||||
SIZE_SHORT), display_size(vg->cmd,
|
||||
(uint64_t) vg->
|
||||
free_count *
|
||||
vg->extent_size / 2,
|
||||
vg->free_count) * vg->extent_size,
|
||||
SIZE_SHORT),
|
||||
display_size(vg->cmd,
|
||||
(uint64_t) vg->free_count * vg->extent_size,
|
||||
SIZE_SHORT));
|
||||
return;
|
||||
}
|
||||
|
||||
void display_formats(struct cmd_context *cmd)
|
||||
{
|
||||
struct format_type *fmt;
|
||||
|
||||
list_iterate_items(fmt, &cmd->formats) {
|
||||
log_print("%s", fmt->name);
|
||||
}
|
||||
}
|
||||
|
||||
void display_segtypes(struct cmd_context *cmd)
|
||||
{
|
||||
struct segment_type *segtype;
|
||||
|
||||
list_iterate_items(segtype, &cmd->segtypes) {
|
||||
log_print("%s", segtype->name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,21 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This LVM library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This LVM library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this LVM library; if not, write to the Free
|
||||
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
* MA 02111-1307, USA
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_DISPLAY_H
|
||||
@@ -32,6 +27,7 @@ uint64_t units_to_bytes(const char *units, char *unit_type);
|
||||
/* Specify size in KB */
|
||||
const char *display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl);
|
||||
char *display_uuid(char *uuidstr);
|
||||
void display_stripe(const struct lv_segment *seg, uint32_t s, const char *pre);
|
||||
|
||||
void pvdisplay_colons(struct physical_volume *pv);
|
||||
void pvdisplay_full(struct cmd_context *cmd, struct physical_volume *pv,
|
||||
@@ -49,16 +45,13 @@ void vgdisplay_full(struct volume_group *vg);
|
||||
void vgdisplay_colons(struct volume_group *vg);
|
||||
void vgdisplay_short(struct volume_group *vg);
|
||||
|
||||
void display_formats(struct cmd_context *cmd);
|
||||
void display_segtypes(struct cmd_context *cmd);
|
||||
|
||||
/*
|
||||
* Allocation policy display conversion routines.
|
||||
*/
|
||||
const char *get_alloc_string(alloc_policy_t alloc);
|
||||
alloc_policy_t get_alloc_from_string(const char *str);
|
||||
|
||||
/*
|
||||
* Segment type display conversion routines.
|
||||
*/
|
||||
segment_type_t get_segtype_from_string(const char *str);
|
||||
const char *get_segtype_string(segment_type_t segtype);
|
||||
|
||||
#endif
|
||||
|
||||
103
lib/error/errseg.c
Normal file
103
lib/error/errseg.c
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
#include "pool.h"
|
||||
#include "list.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"
|
||||
|
||||
static const char *_name(const struct lv_segment *seg)
|
||||
{
|
||||
return seg->segtype->name;
|
||||
}
|
||||
|
||||
static int _merge_segments(struct lv_segment *seg1, struct lv_segment *seg2)
|
||||
{
|
||||
seg1->len += seg2->len;
|
||||
seg1->area_len += seg2->area_len;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef DEVMAPPER_SUPPORT
|
||||
static int _compose_target_line(struct dev_manager *dm, struct pool *mem,
|
||||
struct config_tree *cft, void **target_state,
|
||||
struct lv_segment *seg, char *params,
|
||||
size_t paramsize, const char **target, int *pos,
|
||||
uint32_t *pvmove_mirror_count)
|
||||
{
|
||||
/* error */
|
||||
|
||||
*target = "error";
|
||||
*params = '\0';
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _target_present(void)
|
||||
{
|
||||
static int checked = 0;
|
||||
static int present = 0;
|
||||
|
||||
if (!checked)
|
||||
present = target_present("error");
|
||||
|
||||
checked = 1;
|
||||
return present;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void _destroy(const struct segment_type *segtype)
|
||||
{
|
||||
dbg_free((void *) segtype);
|
||||
}
|
||||
|
||||
static struct segtype_handler _error_ops = {
|
||||
name:_name,
|
||||
merge_segments:_merge_segments,
|
||||
#ifdef DEVMAPPER_SUPPORT
|
||||
compose_target_line:_compose_target_line,
|
||||
target_present:_target_present,
|
||||
#endif
|
||||
destroy:_destroy,
|
||||
};
|
||||
|
||||
struct segment_type *init_error_segtype(struct cmd_context *cmd)
|
||||
{
|
||||
struct segment_type *segtype = dbg_malloc(sizeof(*segtype));
|
||||
|
||||
if (!segtype) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
segtype->cmd = cmd;
|
||||
segtype->ops = &_error_ops;
|
||||
segtype->name = "error";
|
||||
segtype->private = NULL;
|
||||
segtype->flags = SEG_CAN_SPLIT | SEG_VIRTUAL;
|
||||
|
||||
log_very_verbose("Initialised segtype: %s", segtype->name);
|
||||
|
||||
return segtype;
|
||||
}
|
||||
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -37,35 +46,32 @@ static void _destroy(struct dev_filter *f)
|
||||
dbg_free(f);
|
||||
}
|
||||
|
||||
struct dev_filter *composite_filter_create(int n, ...)
|
||||
struct dev_filter *composite_filter_create(int n, struct dev_filter **filters)
|
||||
{
|
||||
struct dev_filter **filters = dbg_malloc(sizeof(*filters) * (n + 1));
|
||||
struct dev_filter *cf;
|
||||
va_list ap;
|
||||
int i;
|
||||
struct dev_filter **filters_copy, *cft;
|
||||
|
||||
if (!filters) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(cf = dbg_malloc(sizeof(*cf)))) {
|
||||
stack;
|
||||
dbg_free(filters);
|
||||
if (!(filters_copy = dbg_malloc(sizeof(*filters) * (n + 1)))) {
|
||||
log_error("composite filters allocation failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
va_start(ap, n);
|
||||
for (i = 0; i < n; i++) {
|
||||
struct dev_filter *f = va_arg(ap, struct dev_filter *);
|
||||
filters[i] = f;
|
||||
memcpy(filters_copy, filters, sizeof(*filters) * n);
|
||||
filters_copy[n] = NULL;
|
||||
|
||||
if (!(cft = dbg_malloc(sizeof(*cft)))) {
|
||||
log_error("compsoite filters allocation failed");
|
||||
dbg_free(filters_copy);
|
||||
return NULL;
|
||||
}
|
||||
filters[i] = NULL;
|
||||
va_end(ap);
|
||||
|
||||
cf->passes_filter = _and_p;
|
||||
cf->destroy = _destroy;
|
||||
cf->private = filters;
|
||||
cft->passes_filter = _and_p;
|
||||
cft->destroy = _destroy;
|
||||
cft->private = filters_copy;
|
||||
|
||||
return cf;
|
||||
return cft;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the GPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_FILTER_COMPOSITE_H
|
||||
@@ -9,6 +18,6 @@
|
||||
|
||||
#include "dev-cache.h"
|
||||
|
||||
struct dev_filter *composite_filter_create(int n, ...);
|
||||
struct dev_filter *composite_filter_create(int n, struct dev_filter **filters);
|
||||
|
||||
#endif
|
||||
|
||||
80
lib/filters/filter-md.c
Normal file
80
lib/filters/filter-md.c
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (C) 2004 Luca Berra
|
||||
*
|
||||
* 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 "filter-md.h"
|
||||
#include "metadata.h"
|
||||
|
||||
#ifdef linux
|
||||
|
||||
/* Lifted from <linux/raid/md_p.h> because of difficulty including it */
|
||||
|
||||
#define MD_SB_MAGIC 0xa92b4efc
|
||||
#define MD_RESERVED_BYTES (64 * 1024)
|
||||
#define MD_RESERVED_SECTORS (MD_RESERVED_BYTES / 512)
|
||||
#define MD_NEW_SIZE_SECTORS(x) ((x & ~(MD_RESERVED_SECTORS - 1)) \
|
||||
- MD_RESERVED_SECTORS)
|
||||
|
||||
static int _ignore_md(struct dev_filter *f, struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!md_filtering())
|
||||
return 1;
|
||||
|
||||
ret = dev_is_md(dev, NULL);
|
||||
|
||||
if (ret == 1) {
|
||||
log_debug("%s: Skipping md component device", dev_name(dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
log_debug("%s: Skipping: error in md component detection",
|
||||
dev_name(dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _destroy(struct dev_filter *f)
|
||||
{
|
||||
dbg_free(f);
|
||||
}
|
||||
|
||||
struct dev_filter *md_filter_create(void)
|
||||
{
|
||||
struct dev_filter *f;
|
||||
|
||||
if (!(f = dbg_malloc(sizeof(*f)))) {
|
||||
log_error("md filter allocation failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
f->passes_filter = _ignore_md;
|
||||
f->destroy = _destroy;
|
||||
f->private = NULL;
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
struct dev_filter *md_filter_create(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
23
lib/filters/filter-md.h
Normal file
23
lib/filters/filter-md.h
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (C) 2004 Luca Berra
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef _LVM_FILTER_MD_H
|
||||
#define _LVM_FILTER_MD_H
|
||||
|
||||
#include "dev-cache.h"
|
||||
|
||||
struct dev_filter *md_filter_create(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -51,13 +60,13 @@ int persistent_filter_wipe(struct dev_filter *f)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _read_array(struct pfilter *pf, struct config_tree *cf,
|
||||
static int _read_array(struct pfilter *pf, struct config_tree *cft,
|
||||
const char *path, void *data)
|
||||
{
|
||||
struct config_node *cn;
|
||||
const struct config_node *cn;
|
||||
struct config_value *cv;
|
||||
|
||||
if (!(cn = find_config_node(cf->root, path, '/'))) {
|
||||
if (!(cn = find_config_node(cft->root, path))) {
|
||||
log_very_verbose("Couldn't find %s array in '%s'",
|
||||
path, pf->file);
|
||||
return 0;
|
||||
@@ -88,22 +97,22 @@ int persistent_filter_load(struct dev_filter *f)
|
||||
struct pfilter *pf = (struct pfilter *) f->private;
|
||||
|
||||
int r = 0;
|
||||
struct config_tree *cf;
|
||||
struct config_tree *cft;
|
||||
|
||||
if (!(cf = create_config_tree())) {
|
||||
if (!(cft = create_config_tree(pf->file))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!read_config_file(cf, pf->file)) {
|
||||
if (!read_config_file(cft)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
|
||||
_read_array(pf, cf, "persistent_filter_cache/valid_devices",
|
||||
_read_array(pf, cft, "persistent_filter_cache/valid_devices",
|
||||
PF_GOOD_DEVICE);
|
||||
/* We don't gain anything by holding invalid devices */
|
||||
/* _read_array(pf, cf, "persistent_filter_cache/invalid_devices",
|
||||
/* _read_array(pf, cft, "persistent_filter_cache/invalid_devices",
|
||||
PF_BAD_DEVICE); */
|
||||
|
||||
/* Did we find anything? */
|
||||
@@ -116,7 +125,7 @@ int persistent_filter_load(struct dev_filter *f)
|
||||
log_very_verbose("Loaded persistent filter cache from %s", pf->file);
|
||||
|
||||
out:
|
||||
destroy_config_tree(cf);
|
||||
destroy_config_tree(cft);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -203,13 +212,10 @@ static int _lookup_p(struct dev_filter *f, struct device *dev)
|
||||
sl = list_item(ah, struct str_list);
|
||||
hash_insert(pf->devices, sl->str, l);
|
||||
}
|
||||
}
|
||||
|
||||
if (l == PF_BAD_DEVICE) {
|
||||
} else if (l == PF_BAD_DEVICE)
|
||||
log_debug("%s: Skipping (cached)", dev_name(dev));
|
||||
return 0;
|
||||
} else
|
||||
return 1;
|
||||
|
||||
return (l == PF_BAD_DEVICE) ? 0 : 1;
|
||||
}
|
||||
|
||||
static void _destroy(struct dev_filter *f)
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the GPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_FILTER_PERSISTENT_H
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -42,7 +51,7 @@ static int _extract_pattern(struct pool *mem, const char *pat,
|
||||
pat++;
|
||||
|
||||
/*
|
||||
* get the seperator
|
||||
* get the separator
|
||||
*/
|
||||
switch (*pat) {
|
||||
case '(':
|
||||
@@ -75,7 +84,7 @@ static int _extract_pattern(struct pool *mem, const char *pat,
|
||||
*/
|
||||
ptr = r + strlen(r) - 1;
|
||||
if (*ptr != sep) {
|
||||
log_info("invalid seperator at end of regex");
|
||||
log_info("invalid separator at end of regex");
|
||||
return 0;
|
||||
}
|
||||
*ptr = '\0';
|
||||
@@ -92,7 +101,7 @@ static int _build_matcher(struct rfilter *rf, struct config_value *val)
|
||||
unsigned count = 0;
|
||||
int i, r = 0;
|
||||
|
||||
if (!(scratch = pool_create(1024))) {
|
||||
if (!(scratch = pool_create("filter matcher", 1024))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -177,6 +186,9 @@ static int _accept_p(struct dev_filter *f, struct device *dev)
|
||||
first = 0;
|
||||
}
|
||||
|
||||
if (rejected)
|
||||
log_debug("%s: Skipping (regex)", dev_name(dev));
|
||||
|
||||
/*
|
||||
* pass everything that doesn't match
|
||||
* anything.
|
||||
@@ -192,7 +204,7 @@ static void _destroy(struct dev_filter *f)
|
||||
|
||||
struct dev_filter *regex_filter_create(struct config_value *patterns)
|
||||
{
|
||||
struct pool *mem = pool_create(10 * 1024);
|
||||
struct pool *mem = pool_create("filter regex", 10 * 1024);
|
||||
struct rfilter *rf;
|
||||
struct dev_filter *f;
|
||||
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the GPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_FILTER_REGEX_H
|
||||
|
||||
306
lib/filters/filter-sysfs.c
Normal file
306
lib/filters/filter-sysfs.c
Normal file
@@ -0,0 +1,306 @@
|
||||
/*
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
#include "filter-sysfs.h"
|
||||
#include "lvm-string.h"
|
||||
#include "pool.h"
|
||||
|
||||
#ifdef linux
|
||||
|
||||
#include <dirent.h>
|
||||
|
||||
static int _locate_sysfs_blocks(const char *proc, char *path, size_t len)
|
||||
{
|
||||
char proc_mounts[PATH_MAX];
|
||||
int r = 0;
|
||||
FILE *fp;
|
||||
char *split[4], buffer[PATH_MAX + 16];
|
||||
|
||||
if (!*proc) {
|
||||
log_verbose("No proc filesystem found: skipping sysfs filter");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lvm_snprintf(proc_mounts, sizeof(proc_mounts),
|
||||
"%s/mounts", proc) < 0) {
|
||||
log_error("Failed to create /proc/mounts string");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(fp = fopen(proc_mounts, "r"))) {
|
||||
log_sys_error("fopen %s", proc_mounts);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (fgets(buffer, sizeof(buffer), fp)) {
|
||||
if (split_words(buffer, 4, split) == 4 &&
|
||||
!strcmp(split[2], "sysfs")) {
|
||||
if (lvm_snprintf(path, len, "%s/%s", split[1],
|
||||
"block") >= 0) {
|
||||
r = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return r;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------
|
||||
* We need to store a set of dev_t.
|
||||
*--------------------------------------------------------------*/
|
||||
struct entry {
|
||||
struct entry *next;
|
||||
dev_t dev;
|
||||
};
|
||||
|
||||
#define SET_BUCKETS 64
|
||||
struct dev_set {
|
||||
struct pool *mem;
|
||||
const char *sys_block;
|
||||
int initialised;
|
||||
struct entry *slots[SET_BUCKETS];
|
||||
};
|
||||
|
||||
static struct dev_set *_dev_set_create(struct pool *mem, const char *sys_block)
|
||||
{
|
||||
struct dev_set *ds;
|
||||
|
||||
if (!(ds = pool_zalloc(mem, sizeof(*ds))))
|
||||
return NULL;
|
||||
|
||||
ds->mem = mem;
|
||||
ds->sys_block = pool_strdup(mem, sys_block);
|
||||
ds->initialised = 0;
|
||||
|
||||
return ds;
|
||||
}
|
||||
|
||||
static inline unsigned _hash_dev(dev_t dev)
|
||||
{
|
||||
return (major(dev) ^ minor(dev)) & (SET_BUCKETS - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Doesn't check that the set already contains dev.
|
||||
*/
|
||||
static int _set_insert(struct dev_set *ds, dev_t dev)
|
||||
{
|
||||
struct entry *e;
|
||||
unsigned h = _hash_dev(dev);
|
||||
|
||||
if (!(e = pool_alloc(ds->mem, sizeof(*e))))
|
||||
return 0;
|
||||
|
||||
e->next = ds->slots[h];
|
||||
e->dev = dev;
|
||||
ds->slots[h] = e;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _set_lookup(struct dev_set *ds, dev_t dev)
|
||||
{
|
||||
unsigned h = _hash_dev(dev);
|
||||
struct entry *e;
|
||||
|
||||
for (e = ds->slots[h]; e; e = e->next)
|
||||
if (e->dev == dev)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------
|
||||
* filter methods
|
||||
*--------------------------------------------------------------*/
|
||||
static int _parse_dev(const char *file, FILE *fp, dev_t *result)
|
||||
{
|
||||
unsigned major, minor;
|
||||
char buffer[64];
|
||||
|
||||
if (!fgets(buffer, sizeof(buffer), fp)) {
|
||||
log_error("Empty sysfs device file: %s", file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sscanf(buffer, "%u:%u", &major, &minor) != 2) {
|
||||
log_info("sysfs device file not correct format");
|
||||
return 0;
|
||||
}
|
||||
|
||||
*result = makedev(major, minor);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _read_dev(const char *file, dev_t *result)
|
||||
{
|
||||
int r;
|
||||
FILE *fp;
|
||||
|
||||
if (!(fp = fopen(file, "r"))) {
|
||||
log_sys_error("fopen", file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = _parse_dev(file, fp, result);
|
||||
fclose(fp);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Recurse through sysfs directories, inserting any devs found.
|
||||
*/
|
||||
static int _read_devs(struct dev_set *ds, const char *dir)
|
||||
{
|
||||
struct dirent *d;
|
||||
DIR *dr;
|
||||
unsigned char dtype;
|
||||
struct stat info;
|
||||
char path[PATH_MAX];
|
||||
dev_t dev;
|
||||
int r = 1;
|
||||
|
||||
if (!(dr = opendir(dir))) {
|
||||
log_sys_error("opendir", dir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while ((d = readdir(dr))) {
|
||||
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
|
||||
continue;
|
||||
|
||||
if (lvm_snprintf(path, sizeof(path), "%s/%s", dir,
|
||||
d->d_name) < 0) {
|
||||
log_error("sysfs path name too long: %s in %s",
|
||||
d->d_name, dir);
|
||||
continue;
|
||||
}
|
||||
|
||||
dtype = d->d_type;
|
||||
|
||||
if (dtype == DT_UNKNOWN) {
|
||||
if (lstat(path, &info) >= 0) {
|
||||
if (S_ISLNK(info.st_mode))
|
||||
dtype = DT_LNK;
|
||||
else if (S_ISDIR(info.st_mode))
|
||||
dtype = DT_DIR;
|
||||
else if (S_ISREG(info.st_mode))
|
||||
dtype = DT_REG;
|
||||
}
|
||||
}
|
||||
|
||||
if (dtype == DT_DIR) {
|
||||
if (!_read_devs(ds, path)) {
|
||||
r = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((dtype == DT_REG && !strcmp(d->d_name, "dev")))
|
||||
if (!_read_dev(path, &dev) || !_set_insert(ds, dev)) {
|
||||
r = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (closedir(dr))
|
||||
log_sys_error("closedir", dir);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _init_devs(struct dev_set *ds)
|
||||
{
|
||||
if (!_read_devs(ds, ds->sys_block)) {
|
||||
ds->initialised = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ds->initialised = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int _accept_p(struct dev_filter *f, struct device *dev)
|
||||
{
|
||||
struct dev_set *ds = (struct dev_set *) f->private;
|
||||
|
||||
if (!ds->initialised)
|
||||
_init_devs(ds);
|
||||
|
||||
/* Pass through if initialisation failed */
|
||||
if (ds->initialised != 1)
|
||||
return 1;
|
||||
|
||||
if (!_set_lookup(ds, dev->dev)) {
|
||||
log_debug("%s: Skipping (sysfs)", dev_name(dev));
|
||||
return 0;
|
||||
} else
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _destroy(struct dev_filter *f)
|
||||
{
|
||||
struct dev_set *ds = (struct dev_set *) f->private;
|
||||
pool_destroy(ds->mem);
|
||||
}
|
||||
|
||||
struct dev_filter *sysfs_filter_create(const char *proc)
|
||||
{
|
||||
char sys_block[PATH_MAX];
|
||||
struct pool *mem;
|
||||
struct dev_set *ds;
|
||||
struct dev_filter *f;
|
||||
|
||||
if (!_locate_sysfs_blocks(proc, sys_block, sizeof(sys_block)))
|
||||
return NULL;
|
||||
|
||||
if (!(mem = pool_create("sysfs", 256))) {
|
||||
log_error("sysfs pool creation failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(ds = _dev_set_create(mem, sys_block))) {
|
||||
log_error("sysfs dev_set creation failed");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (!(f = pool_zalloc(mem, sizeof(*f)))) {
|
||||
stack;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
f->passes_filter = _accept_p;
|
||||
f->destroy = _destroy;
|
||||
f->private = ds;
|
||||
return f;
|
||||
|
||||
bad:
|
||||
pool_destroy(mem);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
struct dev_filter *sysfs_filter_create(const char *proc)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
23
lib/filters/filter-sysfs.h
Normal file
23
lib/filters/filter-sysfs.h
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_FILTER_SYSFS_H
|
||||
#define _LVM_FILTER_SYSFS_H
|
||||
|
||||
#include "config.h"
|
||||
#include "dev-cache.h"
|
||||
|
||||
struct dev_filter *sysfs_filter_create(const char *proc);
|
||||
|
||||
#endif
|
||||
@@ -1,21 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* lvm is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* lvm is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU CC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* 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"
|
||||
@@ -23,6 +18,7 @@
|
||||
#include "filter.h"
|
||||
#include "lvm-string.h"
|
||||
#include "config.h"
|
||||
#include "metadata.h"
|
||||
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
@@ -30,7 +26,11 @@
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
|
||||
#define NUMBER_OF_MAJORS 256
|
||||
#define NUMBER_OF_MAJORS 4096
|
||||
|
||||
/* FIXME Make this sparse */
|
||||
/* 0 means LVM won't use this major number. */
|
||||
static int _max_partitions_by_major[NUMBER_OF_MAJORS];
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
@@ -44,12 +44,19 @@ int md_major(void)
|
||||
return _md_major;
|
||||
}
|
||||
|
||||
/* This list can be supplemented with devices/types in the config file */
|
||||
/*
|
||||
* Devices are only checked for partition tables if their minor number
|
||||
* is a multiple of the number corresponding to their type below
|
||||
* i.e. this gives the granularity of whole-device minor numbers.
|
||||
* Use 1 if the device is not partitionable.
|
||||
*
|
||||
* The list can be supplemented with devices/types in the config file.
|
||||
*/
|
||||
static const device_info_t device_info[] = {
|
||||
{"ide", 16}, /* IDE disk */
|
||||
{"ide", 64}, /* IDE disk */
|
||||
{"sd", 16}, /* SCSI disk */
|
||||
{"md", 16}, /* Multiple Disk driver (SoftRAID) */
|
||||
{"loop", 16}, /* Loop device */
|
||||
{"md", 1}, /* Multiple Disk driver (SoftRAID) */
|
||||
{"loop", 1}, /* Loop device */
|
||||
{"dasd", 4}, /* DASD disk (IBM S/390, zSeries) */
|
||||
{"dac960", 8}, /* DAC960 */
|
||||
{"nbd", 16}, /* Network Block Device */
|
||||
@@ -57,35 +64,60 @@ static const device_info_t device_info[] = {
|
||||
{"cciss", 16}, /* Compaq CCISS array */
|
||||
{"ubd", 16}, /* User-mode virtual block device */
|
||||
{"ataraid", 16}, /* ATA Raid */
|
||||
{"drbd", 16}, /* Distributed Replicated Block Device */
|
||||
{"emcpower", 16}, /* EMC Powerpath */
|
||||
{"power2", 16}, /* EMC Powerpath */
|
||||
{"i2o_block", 16}, /* i2o Block Disk */
|
||||
{"iseries/vd", 8}, /* iSeries disks */
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
static int _passes_lvm_type_device_filter(struct dev_filter *f,
|
||||
struct device *dev)
|
||||
{
|
||||
int fd;
|
||||
const char *name = dev_name(dev);
|
||||
int ret = 0;
|
||||
uint64_t size;
|
||||
|
||||
/* Is this a recognised device type? */
|
||||
if (!(((int *) f->private)[MAJOR(dev->dev)])) {
|
||||
if (!_max_partitions_by_major[MAJOR(dev->dev)]) {
|
||||
log_debug("%s: Skipping: Unrecognised LVM device type %"
|
||||
PRIu64, name, (uint64_t) MAJOR(dev->dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check it's accessible */
|
||||
if ((fd = open(name, O_RDONLY)) < 0) {
|
||||
log_debug("%s: Skipping: open failed: %s", name,
|
||||
strerror(errno));
|
||||
if (!dev_open_flags(dev, O_RDONLY, 0, 0)) {
|
||||
log_debug("%s: Skipping: open failed", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
/* Check it's not too small */
|
||||
if (!dev_get_size(dev, &size)) {
|
||||
log_debug("%s: Skipping: dev_get_size failed", name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
return 1;
|
||||
if (size < PV_MIN_SIZE) {
|
||||
log_debug("%s: Skipping: Too small to hold a PV", name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (is_partitioned_dev(dev)) {
|
||||
log_debug("%s: Skipping: Partition table signature found",
|
||||
name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
out:
|
||||
dev_close(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int *_scan_proc_dev(const char *proc, struct config_node *cn)
|
||||
static int _scan_proc_dev(const char *proc, const struct config_node *cn)
|
||||
{
|
||||
char line[80];
|
||||
char proc_devices[PATH_MAX];
|
||||
@@ -95,35 +127,31 @@ static int *_scan_proc_dev(const char *proc, struct config_node *cn)
|
||||
int blocksection = 0;
|
||||
size_t dev_len = 0;
|
||||
struct config_value *cv;
|
||||
int *max_partitions_by_major;
|
||||
char *name;
|
||||
|
||||
if (!(max_partitions_by_major =
|
||||
dbg_malloc(sizeof(int) * NUMBER_OF_MAJORS))) {
|
||||
log_error("Filter failed to allocate max_partitions_by_major");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!*proc) {
|
||||
log_verbose("No proc filesystem found: using all block device "
|
||||
"types");
|
||||
for (i = 0; i < NUMBER_OF_MAJORS; i++)
|
||||
max_partitions_by_major[i] = 1;
|
||||
return max_partitions_by_major;
|
||||
_max_partitions_by_major[i] = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* All types unrecognised initially */
|
||||
memset(_max_partitions_by_major, 0, sizeof(int) * NUMBER_OF_MAJORS);
|
||||
|
||||
if (lvm_snprintf(proc_devices, sizeof(proc_devices),
|
||||
"%s/devices", proc) < 0) {
|
||||
log_error("Failed to create /proc/devices string");
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(pd = fopen(proc_devices, "r"))) {
|
||||
log_sys_error("fopen", proc_devices);
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(max_partitions_by_major, 0, sizeof(int) * NUMBER_OF_MAJORS);
|
||||
while (fgets(line, 80, pd) != NULL) {
|
||||
i = 0;
|
||||
while (line[i] == ' ' && line[i] != '\0')
|
||||
@@ -158,13 +186,13 @@ static int *_scan_proc_dev(const char *proc, struct config_node *cn)
|
||||
if (dev_len <= strlen(line + i) &&
|
||||
!strncmp(device_info[j].name, line + i, dev_len) &&
|
||||
(line_maj < NUMBER_OF_MAJORS)) {
|
||||
max_partitions_by_major[line_maj] =
|
||||
_max_partitions_by_major[line_maj] =
|
||||
device_info[j].max_partitions;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (max_partitions_by_major[line_maj] || !cn)
|
||||
if (!cn)
|
||||
continue;
|
||||
|
||||
/* Check devices/types for local variations */
|
||||
@@ -172,7 +200,7 @@ static int *_scan_proc_dev(const char *proc, struct config_node *cn)
|
||||
if (cv->type != CFG_STRING) {
|
||||
log_error("Expecting string in devices/types "
|
||||
"in config file");
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
dev_len = strlen(cv->v.str);
|
||||
name = cv->v.str;
|
||||
@@ -181,28 +209,33 @@ static int *_scan_proc_dev(const char *proc, struct config_node *cn)
|
||||
log_error("Max partition count missing for %s "
|
||||
"in devices/types in config file",
|
||||
name);
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
if (!cv->v.i) {
|
||||
log_error("Zero partition count invalid for "
|
||||
"%s in devices/types in config file",
|
||||
name);
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
if (dev_len <= strlen(line + i) &&
|
||||
!strncmp(name, line + i, dev_len) &&
|
||||
(line_maj < NUMBER_OF_MAJORS)) {
|
||||
max_partitions_by_major[line_maj] = cv->v.i;
|
||||
_max_partitions_by_major[line_maj] = cv->v.i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(pd);
|
||||
return max_partitions_by_major;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int max_partitions(int major)
|
||||
{
|
||||
return _max_partitions_by_major[major];
|
||||
}
|
||||
|
||||
struct dev_filter *lvm_type_filter_create(const char *proc,
|
||||
struct config_node *cn)
|
||||
const struct config_node *cn)
|
||||
{
|
||||
struct dev_filter *f;
|
||||
|
||||
@@ -213,8 +246,9 @@ struct dev_filter *lvm_type_filter_create(const char *proc,
|
||||
|
||||
f->passes_filter = _passes_lvm_type_device_filter;
|
||||
f->destroy = lvm_type_filter_destroy;
|
||||
f->private = NULL;
|
||||
|
||||
if (!(f->private = _scan_proc_dev(proc, cn))) {
|
||||
if (!_scan_proc_dev(proc, cn)) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
@@ -224,7 +258,6 @@ struct dev_filter *lvm_type_filter_create(const char *proc,
|
||||
|
||||
void lvm_type_filter_destroy(struct dev_filter *f)
|
||||
{
|
||||
dbg_free(f->private);
|
||||
dbg_free(f);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,21 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* lvm is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* lvm is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU CC; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_FILTER_H
|
||||
@@ -26,7 +21,9 @@
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef linux
|
||||
# include <linux/kdev_t.h>
|
||||
# define MAJOR(dev) ((dev & 0xfff00) >> 8)
|
||||
# define MINOR(dev) ((dev & 0xff) | ((dev >> 12) & 0xfff00))
|
||||
# define MKDEV(ma,mi) ((mi & 0xff) | (ma << 8) | ((mi & ~0xff) << 12))
|
||||
#else
|
||||
# define MAJOR(x) major((x))
|
||||
# define MINOR(x) minor((x))
|
||||
@@ -34,10 +31,12 @@
|
||||
#endif
|
||||
|
||||
struct dev_filter *lvm_type_filter_create(const char *proc,
|
||||
struct config_node *cn);
|
||||
const struct config_node *cn);
|
||||
|
||||
void lvm_type_filter_destroy(struct dev_filter *f);
|
||||
|
||||
int md_major(void);
|
||||
|
||||
int max_partitions(int major);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
Base {
|
||||
global:
|
||||
init_format;
|
||||
local:
|
||||
*;
|
||||
};
|
||||
|
||||
1
lib/format1/.exported_symbols
Normal file
1
lib/format1/.exported_symbols
Normal file
@@ -0,0 +1 @@
|
||||
init_format
|
||||
@@ -1,14 +1,22 @@
|
||||
#
|
||||
# Copyright (C) 2002 Sistina Software (UK) Limited.
|
||||
# Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is released under the LGPL.
|
||||
# This file is part of the LVM2.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
SOURCES=\
|
||||
SOURCES =\
|
||||
disk-rep.c \
|
||||
format1.c \
|
||||
import-export.c \
|
||||
@@ -17,15 +25,12 @@ SOURCES=\
|
||||
lvm1-label.c \
|
||||
vg_number.c
|
||||
|
||||
TARGETS=liblvm2format1.so
|
||||
LIB_SHARED = liblvm2format1.so
|
||||
|
||||
include ../../make.tmpl
|
||||
include $(top_srcdir)/make.tmpl
|
||||
|
||||
|
||||
install: libformat1.so
|
||||
$(INSTALL) -D -o $(OWNER) -g $(GROUP) -m 555 $(STRIP) $< \
|
||||
install: liblvm2format1.so
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
|
||||
$(libdir)/liblvm2format1.so.$(LIB_VERSION)
|
||||
$(LN_S) -f liblvm2format1.so.$(LIB_VERSION) $(libdir)/liblvm2format1.so
|
||||
|
||||
.PHONY: install
|
||||
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -108,6 +117,7 @@ static void _xlate_extents(struct pe_disk *extents, uint32_t count)
|
||||
static int _munge_formats(struct pv_disk *pvd)
|
||||
{
|
||||
uint32_t pe_start;
|
||||
int b, e;
|
||||
|
||||
switch (pvd->version) {
|
||||
case 1:
|
||||
@@ -125,17 +135,54 @@ static int _munge_formats(struct pv_disk *pvd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 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 (b = 0; b < ID_LEN; b++) {
|
||||
pvd->pv_uuid[b] = pvd->pv_uuid[++e - ID_LEN];
|
||||
/* FIXME Remove all invalid chars */
|
||||
if (pvd->pv_uuid[b] == '/')
|
||||
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')
|
||||
uuid_from_num(pvd->pv_uuid, pvd->pv_number);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _read_pvd(struct device *dev, struct pv_disk *pvd)
|
||||
/*
|
||||
* If exported, remove "PV_EXP" from end of VG name
|
||||
*/
|
||||
static void _munge_exported_vg(struct pv_disk *pvd)
|
||||
{
|
||||
if (!dev_read(dev, UINT64_C(0), sizeof(*pvd), pvd)) {
|
||||
log_very_verbose("Failed to read PV data from %s",
|
||||
dev_name(dev));
|
||||
return 0;
|
||||
}
|
||||
int l;
|
||||
size_t s;
|
||||
|
||||
/* Return if PV not in a VG */
|
||||
if ((!*pvd->vg_name))
|
||||
return;
|
||||
/* FIXME also check vgd->status & VG_EXPORTED? */
|
||||
|
||||
l = strlen(pvd->vg_name);
|
||||
s = sizeof(EXPORTED_TAG);
|
||||
if (!strncmp(pvd->vg_name + l - s + 1, EXPORTED_TAG, s)) {
|
||||
pvd->vg_name[l - s + 1] = '\0';
|
||||
pvd->pv_status |= VG_EXPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
int munge_pvd(struct device *dev, struct pv_disk *pvd)
|
||||
{
|
||||
_xlate_pvd(pvd);
|
||||
|
||||
if (pvd->id[0] != 'H' || pvd->id[1] != 'M') {
|
||||
@@ -150,9 +197,23 @@ static int _read_pvd(struct device *dev, struct pv_disk *pvd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If VG is exported, set VG name back to the real name */
|
||||
_munge_exported_vg(pvd);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _read_pvd(struct device *dev, struct pv_disk *pvd)
|
||||
{
|
||||
if (!dev_read(dev, UINT64_C(0), sizeof(*pvd), pvd)) {
|
||||
log_very_verbose("Failed to read PV data from %s",
|
||||
dev_name(dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return munge_pvd(dev, pvd);
|
||||
}
|
||||
|
||||
static int _read_lvd(struct device *dev, uint64_t pos, struct lv_disk *disk)
|
||||
{
|
||||
if (!dev_read(dev, pos, sizeof(*disk), disk))
|
||||
@@ -172,6 +233,13 @@ static int _read_vgd(struct disk_list *data)
|
||||
|
||||
_xlate_vgd(vgd);
|
||||
|
||||
if ((vgd->lv_max > MAX_LV) || (vgd->pv_max > MAX_PV))
|
||||
fail;
|
||||
|
||||
/* If UUID is missing, create one */
|
||||
if (vgd->vg_uuid[0] == '\0')
|
||||
uuid_from_num(vgd->vg_uuid, vgd->vg_number);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -252,26 +320,6 @@ static int _read_extents(struct disk_list *data)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If exported, remove "PV_EXP" from end of VG name
|
||||
*/
|
||||
void munge_exported_vg(struct pv_disk *pvd, struct vg_disk *vgd)
|
||||
{
|
||||
int l;
|
||||
size_t s;
|
||||
|
||||
/* Return if PV not in a VG or VG not exported */
|
||||
if ((!*pvd->vg_name) || (vgd && !(vgd->vg_status & VG_EXPORTED)))
|
||||
return;
|
||||
|
||||
l = strlen(pvd->vg_name);
|
||||
s = sizeof(EXPORTED_TAG);
|
||||
if (!strncmp(pvd->vg_name + l - s + 1, EXPORTED_TAG, s))
|
||||
pvd->vg_name[l - s + 1] = '\0';
|
||||
|
||||
pvd->pv_status |= VG_EXPORTED;
|
||||
}
|
||||
|
||||
static struct disk_list *__read_disk(const struct format_type *fmt,
|
||||
struct device *dev, struct pool *mem,
|
||||
const char *vg_name)
|
||||
@@ -295,9 +343,6 @@ static struct disk_list *__read_disk(const struct format_type *fmt,
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/* If VG is exported, set VG name back to the real name */
|
||||
munge_exported_vg(&dl->pvd, &dl->vgd);
|
||||
|
||||
if (!(info = lvmcache_add(fmt->labeller, dl->pvd.pv_uuid, dev,
|
||||
dl->pvd.vg_name, NULL)))
|
||||
stack;
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the GPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef DISK_REP_FORMAT1_H
|
||||
@@ -10,11 +19,14 @@
|
||||
#include "lvm-types.h"
|
||||
#include "metadata.h"
|
||||
#include "pool.h"
|
||||
#include "toolcontext.h"
|
||||
|
||||
#define MAX_PV 256
|
||||
#define MAX_LV 256
|
||||
#define MAX_VG 99
|
||||
|
||||
#define LVM_BLK_MAJOR 58
|
||||
|
||||
#define MAX_PV_SIZE ((uint32_t) -1) /* 2TB in sectors - 1 */
|
||||
#define MIN_PE_SIZE (8192L >> SECTOR_SHIFT) /* 8 KB in sectors */
|
||||
#define MAX_PE_SIZE (16L * 1024L * (1024L >> SECTOR_SHIFT) * 1024L)
|
||||
@@ -171,7 +183,7 @@ struct disk_list {
|
||||
*/
|
||||
int calculate_layout(struct disk_list *dl);
|
||||
int calculate_extent_count(struct physical_volume *pv, uint32_t extent_size,
|
||||
uint32_t max_extent_count);
|
||||
uint32_t max_extent_count, uint64_t pe_start);
|
||||
|
||||
/*
|
||||
* Low level io routines which read/write
|
||||
@@ -194,7 +206,8 @@ int write_disks(const struct format_type *fmt, struct list *pvds);
|
||||
int import_pv(struct pool *mem, struct device *dev,
|
||||
struct volume_group *vg,
|
||||
struct physical_volume *pv, struct pv_disk *pvd);
|
||||
int export_pv(struct pool *mem, struct volume_group *vg,
|
||||
int export_pv(struct cmd_context *cmd, struct pool *mem,
|
||||
struct volume_group *vg,
|
||||
struct pv_disk *pvd, struct physical_volume *pv);
|
||||
|
||||
int import_vg(struct pool *mem,
|
||||
@@ -203,7 +216,7 @@ int export_vg(struct vg_disk *vgd, struct volume_group *vg);
|
||||
|
||||
int import_lv(struct pool *mem, struct logical_volume *lv, struct lv_disk *lvd);
|
||||
|
||||
int import_extents(struct pool *mem, struct volume_group *vg,
|
||||
int import_extents(struct cmd_context *cmd, struct volume_group *vg,
|
||||
struct list *pvds);
|
||||
int export_extents(struct disk_list *dl, uint32_t lv_num,
|
||||
struct logical_volume *lv, struct physical_volume *pv);
|
||||
@@ -224,7 +237,7 @@ int export_uuids(struct disk_list *dl, struct volume_group *vg);
|
||||
void export_numbers(struct list *pvds, struct volume_group *vg);
|
||||
|
||||
void export_pv_act(struct list *pvds);
|
||||
void munge_exported_vg(struct pv_disk *pvd, struct vg_disk *vgd);
|
||||
int munge_pvd(struct device *dev, struct pv_disk *pvd);
|
||||
|
||||
/* blech */
|
||||
int get_free_vg_number(struct format_instance *fid, struct dev_filter *filter,
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -15,6 +24,9 @@
|
||||
#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)
|
||||
@@ -64,6 +76,35 @@ static int _check_vgs(struct list *pvs, int *partial)
|
||||
else if (memcmp(&first->vgd, &dl->vgd, sizeof(first->vgd))) {
|
||||
log_error("VG data differs between PVs %s and %s",
|
||||
dev_name(first->dev), dev_name(dl->dev));
|
||||
log_debug("VG data on %s: %s %s %" PRIu32 " %" PRIu32
|
||||
" %" PRIu32 " %" PRIu32 " %" PRIu32 " %"
|
||||
PRIu32 " %" PRIu32 " %" PRIu32 " %" PRIu32
|
||||
" %" PRIu32 " %" PRIu32 " %" PRIu32 " %"
|
||||
PRIu32 " %" PRIu32 " %" PRIu32,
|
||||
dev_name(first->dev), first->vgd.vg_uuid,
|
||||
first->vgd.vg_name_dummy,
|
||||
first->vgd.vg_number, first->vgd.vg_access,
|
||||
first->vgd.vg_status, first->vgd.lv_max,
|
||||
first->vgd.lv_cur, first->vgd.lv_open,
|
||||
first->vgd.pv_max, first->vgd.pv_cur,
|
||||
first->vgd.pv_act, first->vgd.dummy,
|
||||
first->vgd.vgda, first->vgd.pe_size,
|
||||
first->vgd.pe_total, first->vgd.pe_allocated,
|
||||
first->vgd.pvg_total);
|
||||
log_debug("VG data on %s: %s %s %" PRIu32 " %" PRIu32
|
||||
" %" PRIu32 " %" PRIu32 " %" PRIu32 " %"
|
||||
PRIu32 " %" PRIu32 " %" PRIu32 " %" PRIu32
|
||||
" %" PRIu32 " %" PRIu32 " %" PRIu32 " %"
|
||||
PRIu32 " %" PRIu32 " %" PRIu32,
|
||||
dev_name(dl->dev), dl->vgd.vg_uuid,
|
||||
dl->vgd.vg_name_dummy, dl->vgd.vg_number,
|
||||
dl->vgd.vg_access, dl->vgd.vg_status,
|
||||
dl->vgd.lv_max, dl->vgd.lv_cur,
|
||||
dl->vgd.lv_open, dl->vgd.pv_max,
|
||||
dl->vgd.pv_cur, dl->vgd.pv_act, dl->vgd.dummy,
|
||||
dl->vgd.vgda, dl->vgd.pe_size,
|
||||
dl->vgd.pe_total, dl->vgd.pe_allocated,
|
||||
dl->vgd.pvg_total);
|
||||
list_del(pvh);
|
||||
if (partial_mode()) {
|
||||
*partial = 1;
|
||||
@@ -75,9 +116,9 @@ static int _check_vgs(struct list *pvs, int *partial)
|
||||
}
|
||||
|
||||
/* On entry to fn, list known to be non-empty */
|
||||
if (pv_count != dl->vgd.pv_cur) {
|
||||
if (pv_count != first->vgd.pv_cur) {
|
||||
log_error("%d PV(s) found for VG %s: expected %d",
|
||||
pv_count, dl->pvd.vg_name, dl->vgd.pv_cur);
|
||||
pv_count, first->pvd.vg_name, first->vgd.pv_cur);
|
||||
if (!partial_mode())
|
||||
return 0;
|
||||
*partial = 1;
|
||||
@@ -108,6 +149,7 @@ static struct volume_group *_build_vg(struct format_instance *fid,
|
||||
list_init(&vg->pvs);
|
||||
list_init(&vg->lvs);
|
||||
list_init(&vg->snapshots);
|
||||
list_init(&vg->tags);
|
||||
|
||||
if (!_check_vgs(pvs, &partial))
|
||||
goto bad;
|
||||
@@ -123,7 +165,7 @@ static struct volume_group *_build_vg(struct format_instance *fid,
|
||||
if (!import_lvs(mem, vg, pvs))
|
||||
goto bad;
|
||||
|
||||
if (!import_extents(mem, vg, pvs))
|
||||
if (!import_extents(fid->fmt->cmd, vg, pvs))
|
||||
goto bad;
|
||||
|
||||
if (!import_snapshots(mem, vg, pvs))
|
||||
@@ -141,7 +183,7 @@ static struct volume_group *_vg_read(struct format_instance *fid,
|
||||
const char *vg_name,
|
||||
struct metadata_area *mda)
|
||||
{
|
||||
struct pool *mem = pool_create(1024 * 10);
|
||||
struct pool *mem = pool_create("lvm1 vg_read", 1024 * 10);
|
||||
struct list pvs;
|
||||
struct volume_group *vg = NULL;
|
||||
list_init(&pvs);
|
||||
@@ -170,7 +212,8 @@ static struct volume_group *_vg_read(struct format_instance *fid,
|
||||
return vg;
|
||||
}
|
||||
|
||||
static struct disk_list *_flatten_pv(struct pool *mem, struct volume_group *vg,
|
||||
static struct disk_list *_flatten_pv(struct format_instance *fid,
|
||||
struct pool *mem, struct volume_group *vg,
|
||||
struct physical_volume *pv,
|
||||
const char *dev_dir)
|
||||
{
|
||||
@@ -187,7 +230,7 @@ static struct disk_list *_flatten_pv(struct pool *mem, struct volume_group *vg,
|
||||
list_init(&dl->uuids);
|
||||
list_init(&dl->lvds);
|
||||
|
||||
if (!export_pv(mem, vg, &dl->pvd, pv) ||
|
||||
if (!export_pv(fid->fmt->cmd, mem, vg, &dl->pvd, pv) ||
|
||||
!export_vg(&dl->vgd, vg) ||
|
||||
!export_uuids(dl, vg) ||
|
||||
!export_lvs(dl, vg, pv, dev_dir) || !calculate_layout(dl)) {
|
||||
@@ -211,7 +254,7 @@ static int _flatten_vg(struct format_instance *fid, struct pool *mem,
|
||||
list_iterate(pvh, &vg->pvs) {
|
||||
pvl = list_item(pvh, struct pv_list);
|
||||
|
||||
if (!(data = _flatten_pv(mem, vg, pvl->pv, dev_dir))) {
|
||||
if (!(data = _flatten_pv(fid, mem, vg, pvl->pv, dev_dir))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -233,7 +276,7 @@ static int _flatten_vg(struct format_instance *fid, struct pool *mem,
|
||||
static int _vg_write(struct format_instance *fid, struct volume_group *vg,
|
||||
struct metadata_area *mda)
|
||||
{
|
||||
struct pool *mem = pool_create(1024 * 10);
|
||||
struct pool *mem = pool_create("lvm1 vg_write", 1024 * 10);
|
||||
struct list pvds;
|
||||
int r = 0;
|
||||
|
||||
@@ -256,7 +299,7 @@ static int _vg_write(struct format_instance *fid, struct volume_group *vg,
|
||||
static int _pv_read(const struct format_type *fmt, const char *pv_name,
|
||||
struct physical_volume *pv, struct list *mdas)
|
||||
{
|
||||
struct pool *mem = pool_create(1024);
|
||||
struct pool *mem = pool_create("lvm1 pv_read", 1024);
|
||||
struct disk_list *dl;
|
||||
struct device *dev;
|
||||
int r = 0;
|
||||
@@ -303,7 +346,7 @@ static int _pv_setup(const struct format_type *fmt,
|
||||
pv->size--;
|
||||
if (pv->size > MAX_PV_SIZE) {
|
||||
log_error("Physical volumes cannot be bigger than %s",
|
||||
display_size(fmt->cmd, (uint64_t) MAX_PV_SIZE / 2,
|
||||
display_size(fmt->cmd, (uint64_t) MAX_PV_SIZE,
|
||||
SIZE_SHORT));
|
||||
return 0;
|
||||
}
|
||||
@@ -315,14 +358,12 @@ static int _pv_setup(const struct format_type *fmt,
|
||||
/*
|
||||
* This works out pe_start and pe_count.
|
||||
*/
|
||||
if (!calculate_extent_count(pv, extent_size, extent_count)) {
|
||||
if (!calculate_extent_count(pv, extent_size, extent_count, pe_start)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Retain existing extent locations exactly */
|
||||
/* FIXME Relax this so a non-overlapping existing pe_start can also
|
||||
* be used in place of the calculated one */
|
||||
if (((pe_start || extent_count) && (pe_start != pv->pe_start)) ||
|
||||
(extent_count && (extent_count != pv->pe_count))) {
|
||||
log_error("Metadata would overwrite physical extents");
|
||||
@@ -332,32 +373,12 @@ static int _pv_setup(const struct format_type *fmt,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static uint32_t _find_free_lvnum(struct logical_volume *lv)
|
||||
{
|
||||
int lvnum_used[MAX_LV];
|
||||
uint32_t i = 0;
|
||||
struct list *lvh;
|
||||
struct lv_list *lvl;
|
||||
|
||||
memset(&lvnum_used, 0, sizeof(lvnum_used));
|
||||
|
||||
list_iterate(lvh, &lv->vg->lvs) {
|
||||
lvl = list_item(lvh, struct lv_list);
|
||||
lvnum_used[lvnum_from_lvid(&lvl->lv->lvid)] = 1;
|
||||
}
|
||||
|
||||
while (lvnum_used[i])
|
||||
i++;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static int _lv_setup(struct format_instance *fid, struct logical_volume *lv)
|
||||
{
|
||||
uint64_t max_size = UINT_MAX;
|
||||
|
||||
if (!*lv->lvid.s)
|
||||
lvid_from_lvnum(&lv->lvid, &lv->vg->id, _find_free_lvnum(lv));
|
||||
lvid_from_lvnum(&lv->lvid, &lv->vg->id, find_free_lvnum(lv));
|
||||
|
||||
if (lv->le_count > MAX_LE_TOTAL) {
|
||||
log_error("logical volumes cannot contain more than "
|
||||
@@ -366,7 +387,7 @@ static int _lv_setup(struct format_instance *fid, struct logical_volume *lv)
|
||||
}
|
||||
if (lv->size > max_size) {
|
||||
log_error("logical volumes cannot be larger than %s",
|
||||
display_size(fid->fmt->cmd, max_size / 2,
|
||||
display_size(fid->fmt->cmd, max_size,
|
||||
SIZE_SHORT));
|
||||
return 0;
|
||||
}
|
||||
@@ -400,7 +421,7 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
|
||||
pv->pe_size = pv->pe_count = 0;
|
||||
pv->pe_start = PE_ALIGN;
|
||||
|
||||
if (!(mem = pool_create(1024))) {
|
||||
if (!(mem = pool_create("lvm1 pv_write", 1024))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -412,7 +433,7 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
|
||||
dl->mem = mem;
|
||||
dl->dev = pv->dev;
|
||||
|
||||
if (!export_pv(mem, NULL, &dl->pvd, pv)) {
|
||||
if (!export_pv(fmt->cmd, mem, NULL, &dl->pvd, pv)) {
|
||||
stack;
|
||||
goto bad;
|
||||
}
|
||||
@@ -440,20 +461,17 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
|
||||
static int _vg_setup(struct format_instance *fid, struct volume_group *vg)
|
||||
{
|
||||
/* just check max_pv and max_lv */
|
||||
if (vg->max_lv >= MAX_LV)
|
||||
if (!vg->max_lv || vg->max_lv >= MAX_LV)
|
||||
vg->max_lv = MAX_LV - 1;
|
||||
|
||||
if (vg->max_pv >= MAX_PV)
|
||||
if (!vg->max_pv || vg->max_pv >= MAX_PV)
|
||||
vg->max_pv = MAX_PV - 1;
|
||||
|
||||
if (vg->extent_size > MAX_PE_SIZE || vg->extent_size < MIN_PE_SIZE) {
|
||||
log_error("Extent size must be between %s and %s",
|
||||
display_size(fid->fmt->cmd, (uint64_t) MIN_PE_SIZE
|
||||
/ 2,
|
||||
SIZE_SHORT), display_size(fid->fmt->cmd,
|
||||
(uint64_t)
|
||||
MAX_PE_SIZE
|
||||
/ 2,
|
||||
display_size(fid->fmt->cmd, (uint64_t) MIN_PE_SIZE,
|
||||
SIZE_SHORT),
|
||||
display_size(fid->fmt->cmd, (uint64_t) MAX_PE_SIZE,
|
||||
SIZE_SHORT));
|
||||
|
||||
return 0;
|
||||
@@ -461,8 +479,8 @@ static int _vg_setup(struct format_instance *fid, struct volume_group *vg)
|
||||
|
||||
if (vg->extent_size % MIN_PE_SIZE) {
|
||||
log_error("Extent size must be multiple of %s",
|
||||
display_size(fid->fmt->cmd,
|
||||
(uint64_t) MIN_PE_SIZE / 2, SIZE_SHORT));
|
||||
display_size(fid->fmt->cmd, (uint64_t) MIN_PE_SIZE,
|
||||
SIZE_SHORT));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -475,6 +493,17 @@ static int _vg_setup(struct format_instance *fid, struct volume_group *vg)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _segtype_supported (struct format_instance *fid,
|
||||
struct segment_type *segtype)
|
||||
{
|
||||
if (!(segtype->flags & SEG_FORMAT1_SUPPORT)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct metadata_area_ops _metadata_format1_ops = {
|
||||
vg_read:_vg_read,
|
||||
vg_write:_vg_write,
|
||||
@@ -525,6 +554,7 @@ static struct format_handler _format1_ops = {
|
||||
pv_write:_pv_write,
|
||||
lv_setup:_lv_setup,
|
||||
vg_setup:_vg_setup,
|
||||
segtype_supported:_segtype_supported,
|
||||
create_instance:_create_instance,
|
||||
destroy_instance:_destroy_instance,
|
||||
destroy:_destroy,
|
||||
@@ -548,7 +578,7 @@ struct format_type *init_format(struct cmd_context *cmd)
|
||||
fmt->ops = &_format1_ops;
|
||||
fmt->name = FMT_LVM1_NAME;
|
||||
fmt->alias = NULL;
|
||||
fmt->features = 0;
|
||||
fmt->features = FMT_RESTRICTED_LVIDS | FMT_ORPHAN_ALLOCATABLE;
|
||||
fmt->private = NULL;
|
||||
|
||||
if (!(fmt->labeller = lvm1_labeller_create(fmt))) {
|
||||
@@ -561,5 +591,7 @@ struct format_type *init_format(struct cmd_context *cmd)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
log_very_verbose("Initialised format: %s", fmt->name);
|
||||
|
||||
return fmt;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the GPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_FORMAT1_H
|
||||
@@ -9,8 +18,6 @@
|
||||
|
||||
#include "metadata.h"
|
||||
|
||||
#define FMT_LVM1_NAME "lvm1"
|
||||
|
||||
#ifdef LVM1_INTERNAL
|
||||
struct format_type *init_lvm1_format(struct cmd_context *cmd);
|
||||
#endif
|
||||
|
||||
@@ -1,9 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Translates between disk and in-core formats.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -13,9 +24,10 @@
|
||||
#include "list.h"
|
||||
#include "lvm-string.h"
|
||||
#include "filter.h"
|
||||
#include "toolcontext.h"
|
||||
#include "segtype.h"
|
||||
|
||||
#include <time.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
static int _check_vg_name(const char *name)
|
||||
{
|
||||
@@ -76,20 +88,16 @@ int import_pv(struct pool *mem, struct device *dev,
|
||||
pv->pe_count = pvd->pe_total;
|
||||
pv->pe_alloc_count = pvd->pe_allocated;
|
||||
|
||||
list_init(&pv->tags);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _system_id(char *s, const char *prefix)
|
||||
static int _system_id(struct cmd_context *cmd, char *s, const char *prefix)
|
||||
{
|
||||
struct utsname uts;
|
||||
|
||||
if (uname(&uts) != 0) {
|
||||
log_sys_error("uname", "_system_id");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lvm_snprintf(s, NAME_LEN, "%s%s%lu",
|
||||
prefix, uts.nodename, time(NULL)) < 0) {
|
||||
prefix, cmd->hostname, time(NULL)) < 0) {
|
||||
log_error("Generated system_id too long");
|
||||
return 0;
|
||||
}
|
||||
@@ -97,7 +105,8 @@ static int _system_id(char *s, const char *prefix)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int export_pv(struct pool *mem, struct volume_group *vg,
|
||||
int export_pv(struct cmd_context *cmd, struct pool *mem,
|
||||
struct volume_group *vg,
|
||||
struct pv_disk *pvd, struct physical_volume *pv)
|
||||
{
|
||||
memset(pvd, 0, sizeof(*pvd));
|
||||
@@ -128,7 +137,7 @@ int export_pv(struct pool *mem, struct volume_group *vg,
|
||||
if (!*vg->system_id ||
|
||||
strncmp(vg->system_id, EXPORTED_TAG,
|
||||
sizeof(EXPORTED_TAG) - 1)) {
|
||||
if (!_system_id(pvd->system_id, EXPORTED_TAG)) {
|
||||
if (!_system_id(cmd, pvd->system_id, EXPORTED_TAG)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -145,7 +154,7 @@ int export_pv(struct pool *mem, struct volume_group *vg,
|
||||
/* 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(pvd->system_id, IMPORTED_TAG)) {
|
||||
if (!_system_id(cmd, pvd->system_id, IMPORTED_TAG)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -153,7 +162,7 @@ int export_pv(struct pool *mem, struct volume_group *vg,
|
||||
|
||||
/* Generate system_id if PV is in VG */
|
||||
if (!pvd->system_id || !*pvd->system_id)
|
||||
if (!_system_id(pvd->system_id, "")) {
|
||||
if (!_system_id(cmd, pvd->system_id, "")) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -228,6 +237,7 @@ int import_vg(struct pool *mem,
|
||||
vg->free_count = vgd->pe_total - vgd->pe_allocated;
|
||||
vg->max_lv = vgd->lv_max;
|
||||
vg->max_pv = vgd->pv_max;
|
||||
vg->alloc = ALLOC_NORMAL;
|
||||
|
||||
if (partial)
|
||||
vg->status |= PARTIAL_VG;
|
||||
@@ -307,13 +317,14 @@ int import_lv(struct pool *mem, struct logical_volume *lv, struct lv_disk *lvd)
|
||||
if (lvd->lv_allocation & LV_CONTIGUOUS)
|
||||
lv->alloc = ALLOC_CONTIGUOUS;
|
||||
else
|
||||
lv->alloc = ALLOC_NEXT_FREE;
|
||||
lv->alloc = ALLOC_NORMAL;
|
||||
|
||||
lv->read_ahead = lvd->lv_read_ahead;
|
||||
lv->size = lvd->lv_size;
|
||||
lv->le_count = lvd->lv_allocated_le;
|
||||
|
||||
list_init(&lv->segments);
|
||||
list_init(&lv->tags);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -339,6 +350,8 @@ static void _export_lv(struct lv_disk *lvd, struct volume_group *vg,
|
||||
if (lv->status & FIXED_MINOR) {
|
||||
lvd->lv_status |= LV_PERSISTENT_MINOR;
|
||||
lvd->lv_dev = MKDEV(lv->major, lv->minor);
|
||||
} else {
|
||||
lvd->lv_dev = MKDEV(LVM_BLK_MAJOR, lvnum_from_lvid(&lv->lvid));
|
||||
}
|
||||
|
||||
lvd->lv_read_ahead = lv->read_ahead;
|
||||
@@ -369,9 +382,10 @@ int export_extents(struct disk_list *dl, uint32_t lv_num,
|
||||
seg = list_item(segh, struct lv_segment);
|
||||
|
||||
for (s = 0; s < seg->area_count; s++) {
|
||||
if (seg->type != SEG_STRIPED) {
|
||||
log_error("Non-striped segment type in LV %s: "
|
||||
"unsupported by format1", lv->name);
|
||||
if (!(seg->segtype->flags & SEG_FORMAT1_SUPPORT)) {
|
||||
log_error("Segment type %s in LV %s: "
|
||||
"unsupported by format1",
|
||||
seg->segtype->name, lv->name);
|
||||
return 0;
|
||||
}
|
||||
if (seg->area[s].type != AREA_PV) {
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -9,6 +18,9 @@
|
||||
#include "hash.h"
|
||||
#include "pool.h"
|
||||
#include "disk-rep.h"
|
||||
#include "lv_alloc.h"
|
||||
#include "display.h"
|
||||
#include "segtype.h"
|
||||
|
||||
/*
|
||||
* After much thought I have decided it is easier,
|
||||
@@ -191,34 +203,24 @@ static int _check_maps_are_complete(struct hash_table *maps)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct lv_segment *_alloc_seg(struct pool *mem, uint32_t stripes)
|
||||
{
|
||||
struct lv_segment *seg;
|
||||
uint32_t len = sizeof(*seg) + (stripes * sizeof(seg->area[0]));
|
||||
|
||||
if (!(seg = pool_zalloc(mem, len))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return seg;
|
||||
}
|
||||
|
||||
static int _read_linear(struct pool *mem, struct lv_map *lvm)
|
||||
static int _read_linear(struct cmd_context *cmd, struct lv_map *lvm)
|
||||
{
|
||||
uint32_t le = 0;
|
||||
struct lv_segment *seg;
|
||||
|
||||
while (le < lvm->lv->le_count) {
|
||||
seg = _alloc_seg(mem, 1);
|
||||
seg = alloc_lv_segment(cmd->mem, 1);
|
||||
|
||||
seg->lv = lvm->lv;
|
||||
seg->type = SEG_STRIPED;
|
||||
if (!(seg->segtype = get_segtype_from_string(cmd, "striped"))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
seg->le = le;
|
||||
seg->len = 0;
|
||||
seg->area_len = 0;
|
||||
seg->stripe_size = 0;
|
||||
seg->area_count = 1;
|
||||
|
||||
seg->area[0].type = AREA_PV;
|
||||
seg->area[0].u.pv.pv = lvm->map[le].pv;
|
||||
@@ -254,13 +256,12 @@ static int _check_stripe(struct lv_map *lvm, struct lv_segment *seg,
|
||||
if ((lvm->map[le + st * len].pv != seg->area[st].u.pv.pv) ||
|
||||
(seg->area[st].u.pv.pv &&
|
||||
lvm->map[le + st * len].pe !=
|
||||
seg->area[st].u.pv.pe + seg->len))
|
||||
return 0;
|
||||
seg->area[st].u.pv.pe + seg->len)) return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _read_stripes(struct pool *mem, struct lv_map *lvm)
|
||||
static int _read_stripes(struct cmd_context *cmd, struct lv_map *lvm)
|
||||
{
|
||||
uint32_t st, le = 0, len;
|
||||
struct lv_segment *seg;
|
||||
@@ -276,15 +277,17 @@ static int _read_stripes(struct pool *mem, struct lv_map *lvm)
|
||||
len = lvm->lv->le_count / lvm->stripes;
|
||||
|
||||
while (le < len) {
|
||||
if (!(seg = _alloc_seg(mem, lvm->stripes))) {
|
||||
if (!(seg = alloc_lv_segment(cmd->mem, lvm->stripes))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
seg->lv = lvm->lv;
|
||||
seg->type = SEG_STRIPED;
|
||||
if (!(seg->segtype = get_segtype_from_string(cmd, "striped"))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
seg->stripe_size = lvm->stripe_size;
|
||||
seg->area_count = lvm->stripes;
|
||||
seg->le = seg->area_count * le;
|
||||
seg->len = 1;
|
||||
seg->area_len = 1;
|
||||
@@ -315,20 +318,20 @@ static int _read_stripes(struct pool *mem, struct lv_map *lvm)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _build_segments(struct pool *mem, struct lv_map *lvm)
|
||||
static int _build_segments(struct cmd_context *cmd, struct lv_map *lvm)
|
||||
{
|
||||
return (lvm->stripes > 1 ? _read_stripes(mem, lvm) :
|
||||
_read_linear(mem, lvm));
|
||||
return (lvm->stripes > 1 ? _read_stripes(cmd, lvm) :
|
||||
_read_linear(cmd, lvm));
|
||||
}
|
||||
|
||||
static int _build_all_segments(struct pool *mem, struct hash_table *maps)
|
||||
static int _build_all_segments(struct cmd_context *cmd, struct hash_table *maps)
|
||||
{
|
||||
struct hash_node *n;
|
||||
struct lv_map *lvm;
|
||||
|
||||
for (n = hash_get_first(maps); n; n = hash_get_next(maps, n)) {
|
||||
lvm = (struct lv_map *) hash_get_data(maps, n);
|
||||
if (!_build_segments(mem, lvm)) {
|
||||
if (!_build_segments(cmd, lvm)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -337,10 +340,11 @@ static int _build_all_segments(struct pool *mem, struct hash_table *maps)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int import_extents(struct pool *mem, struct volume_group *vg, struct list *pvds)
|
||||
int import_extents(struct cmd_context *cmd, struct volume_group *vg,
|
||||
struct list *pvds)
|
||||
{
|
||||
int r = 0;
|
||||
struct pool *scratch = pool_create(10 * 1024);
|
||||
struct pool *scratch = pool_create("lvm1 import_extents", 10 * 1024);
|
||||
struct hash_table *maps;
|
||||
|
||||
if (!scratch) {
|
||||
@@ -363,7 +367,7 @@ int import_extents(struct pool *mem, struct volume_group *vg, struct list *pvds)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!_build_all_segments(mem, maps)) {
|
||||
if (!_build_all_segments(cmd, maps)) {
|
||||
log_err("Couldn't build extent segments.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -103,9 +112,10 @@ int calculate_layout(struct disk_list *dl)
|
||||
|
||||
/*
|
||||
* The number of extents that can fit on a disk is metadata format dependant.
|
||||
* pe_start is any existing value for pe_start
|
||||
*/
|
||||
int calculate_extent_count(struct physical_volume *pv, uint32_t extent_size,
|
||||
uint32_t max_extent_count)
|
||||
uint32_t max_extent_count, uint64_t pe_start)
|
||||
{
|
||||
struct pv_disk *pvd = dbg_malloc(sizeof(*pvd));
|
||||
uint32_t end;
|
||||
@@ -138,6 +148,9 @@ int calculate_extent_count(struct physical_volume *pv, uint32_t extent_size,
|
||||
end = ((pvd->pe_on_disk.base + pvd->pe_on_disk.size +
|
||||
SECTOR_SIZE - 1) >> SECTOR_SHIFT);
|
||||
|
||||
if (pe_start && end < pe_start)
|
||||
end = pe_start;
|
||||
|
||||
pvd->pe_start = _round_up(end, PE_ALIGN);
|
||||
|
||||
} while ((pvd->pe_start + (pvd->pe_total * extent_size))
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2002 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -51,9 +60,12 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
|
||||
struct pv_disk *pvd = (struct pv_disk *) buf;
|
||||
struct lvmcache_info *info;
|
||||
|
||||
munge_exported_vg(pvd, NULL);
|
||||
if (!(info = lvmcache_add(l, pvd->pv_uuid, dev, pvd->vg_name, NULL)))
|
||||
munge_pvd(dev, pvd);
|
||||
|
||||
if (!(info = lvmcache_add(l, pvd->pv_uuid, dev, pvd->vg_name, NULL))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
*label = info->label;
|
||||
|
||||
info->device_size = xlate32(pvd->pv_size) << SECTOR_SHIFT;
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2002 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_LVM1_LABEL_H
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Sistina Software (UK) Limited.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
@@ -21,7 +30,7 @@ int get_free_vg_number(struct format_instance *fid, struct dev_filter *filter,
|
||||
struct list *pvh;
|
||||
struct list all_pvs;
|
||||
struct disk_list *dl;
|
||||
struct pool *mem = pool_create(10 * 1024);
|
||||
struct pool *mem = pool_create("lvm1 vg_number", 10 * 1024);
|
||||
int numbers[MAX_VG], i, r = 0;
|
||||
|
||||
list_init(&all_pvs);
|
||||
|
||||
1
lib/format_pool/.exported_symbols
Normal file
1
lib/format_pool/.exported_symbols
Normal file
@@ -0,0 +1 @@
|
||||
init_format
|
||||
35
lib/format_pool/Makefile.in
Normal file
35
lib/format_pool/Makefile.in
Normal file
@@ -0,0 +1,35 @@
|
||||
#
|
||||
# Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
|
||||
# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of the LVM2.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
SOURCES =\
|
||||
disk_rep.c \
|
||||
format_pool.c \
|
||||
import_export.c \
|
||||
pool_label.c
|
||||
|
||||
LIB_SHARED = liblvm2formatpool.so
|
||||
|
||||
include $(top_srcdir)/make.tmpl
|
||||
|
||||
install: liblvm2formatpool.so
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
|
||||
$(libdir)/liblvm2formatpool.so.$(LIB_VERSION)
|
||||
$(LN_S) -f liblvm2formatpool.so.$(LIB_VERSION) \
|
||||
$(libdir)/liblvm2formatpool.so
|
||||
|
||||
|
||||
385
lib/format_pool/disk_rep.c
Normal file
385
lib/format_pool/disk_rep.c
Normal file
@@ -0,0 +1,385 @@
|
||||
/*
|
||||
* Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
#include "pool.h"
|
||||
#include "label.h"
|
||||
#include "metadata.h"
|
||||
#include "lvmcache.h"
|
||||
#include "filter.h"
|
||||
#include "list.h"
|
||||
#include "xlate.h"
|
||||
|
||||
#include "disk_rep.h"
|
||||
|
||||
/* FIXME: memcpy might not be portable */
|
||||
#define CPIN_8(x, y, z) {memcpy((x), (y), (z));}
|
||||
#define CPOUT_8(x, y, z) {memcpy((y), (x), (z));}
|
||||
#define CPIN_16(x, y) {(x) = xlate16_be((y));}
|
||||
#define CPOUT_16(x, y) {(y) = xlate16_be((x));}
|
||||
#define CPIN_32(x, y) {(x) = xlate32_be((y));}
|
||||
#define CPOUT_32(x, y) {(y) = xlate32_be((x));}
|
||||
#define CPIN_64(x, y) {(x) = xlate64_be((y));}
|
||||
#define CPOUT_64(x, y) {(y) = xlate64_be((x));}
|
||||
|
||||
static int __read_pool_disk(const struct format_type *fmt, struct device *dev,
|
||||
struct pool *mem, struct pool_list *pl,
|
||||
const char *vg_name)
|
||||
{
|
||||
char buf[512];
|
||||
|
||||
/* FIXME: Need to check the cache here first */
|
||||
if (!dev_read(dev, UINT64_C(0), 512, buf)) {
|
||||
log_very_verbose("Failed to read PV data from %s",
|
||||
dev_name(dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!read_pool_label(pl, fmt->labeller, dev, buf, NULL)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _add_pl_to_list(struct list *head, struct pool_list *data)
|
||||
{
|
||||
struct list *pvdh;
|
||||
struct pool_list *pl;
|
||||
|
||||
list_iterate(pvdh, head) {
|
||||
pl = list_item(pvdh, struct pool_list);
|
||||
|
||||
if (id_equal(&data->pv_uuid, &pl->pv_uuid)) {
|
||||
char uuid[ID_LEN + 7];
|
||||
|
||||
id_write_format(&pl->pv_uuid, uuid, ID_LEN + 7);
|
||||
|
||||
if (MAJOR(data->dev->dev) != md_major()) {
|
||||
log_very_verbose("Ignoring duplicate PV %s on "
|
||||
"%s", uuid,
|
||||
dev_name(data->dev));
|
||||
return;
|
||||
}
|
||||
log_very_verbose("Duplicate PV %s - using md %s",
|
||||
uuid, dev_name(data->dev));
|
||||
list_del(pvdh);
|
||||
break;
|
||||
}
|
||||
}
|
||||
list_add(head, &data->list);
|
||||
}
|
||||
|
||||
int read_pool_label(struct pool_list *pl, struct labeller *l,
|
||||
struct device *dev, char *buf, struct label **label)
|
||||
{
|
||||
struct lvmcache_info *info;
|
||||
struct id pvid;
|
||||
struct id vgid;
|
||||
char uuid[ID_LEN + 7];
|
||||
struct pool_disk *pd = &pl->pd;
|
||||
|
||||
pool_label_in(pd, buf);
|
||||
|
||||
get_pool_pv_uuid(&pvid, pd);
|
||||
id_write_format(&pvid, uuid, ID_LEN + 7);
|
||||
log_debug("Calculated uuid %s for %s", uuid, dev_name(dev));
|
||||
|
||||
get_pool_vg_uuid(&vgid, pd);
|
||||
id_write_format(&vgid, uuid, ID_LEN + 7);
|
||||
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))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (label)
|
||||
*label = info->label;
|
||||
|
||||
info->device_size = xlate32_be(pd->pl_blocks) << SECTOR_SHIFT;
|
||||
list_init(&info->mdas);
|
||||
|
||||
info->status &= ~CACHE_INVALID;
|
||||
|
||||
pl->dev = dev;
|
||||
pl->pv = NULL;
|
||||
memcpy(&pl->pv_uuid, &pvid, sizeof(pvid));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* pool_label_out - copies a pool_label_t into a char buffer
|
||||
* @pl: ptr to a pool_label_t struct
|
||||
* @buf: ptr to raw space where label info will be copied
|
||||
*
|
||||
* This function is important because it takes care of all of
|
||||
* the endian issues when copying to disk. This way, when
|
||||
* machines of different architectures are used, they will
|
||||
* be able to interpret ondisk labels correctly. Always use
|
||||
* this function before writing to disk.
|
||||
*/
|
||||
void pool_label_out(struct pool_disk *pl, char *buf)
|
||||
{
|
||||
struct pool_disk *bufpl = (struct pool_disk *) buf;
|
||||
|
||||
CPOUT_64(pl->pl_magic, bufpl->pl_magic);
|
||||
CPOUT_64(pl->pl_pool_id, bufpl->pl_pool_id);
|
||||
CPOUT_8(pl->pl_pool_name, bufpl->pl_pool_name, POOL_NAME_SIZE);
|
||||
CPOUT_32(pl->pl_version, bufpl->pl_version);
|
||||
CPOUT_32(pl->pl_subpools, bufpl->pl_subpools);
|
||||
CPOUT_32(pl->pl_sp_id, bufpl->pl_sp_id);
|
||||
CPOUT_32(pl->pl_sp_devs, bufpl->pl_sp_devs);
|
||||
CPOUT_32(pl->pl_sp_devid, bufpl->pl_sp_devid);
|
||||
CPOUT_32(pl->pl_sp_type, bufpl->pl_sp_type);
|
||||
CPOUT_64(pl->pl_blocks, bufpl->pl_blocks);
|
||||
CPOUT_32(pl->pl_striping, bufpl->pl_striping);
|
||||
CPOUT_32(pl->pl_sp_dmepdevs, bufpl->pl_sp_dmepdevs);
|
||||
CPOUT_32(pl->pl_sp_dmepid, bufpl->pl_sp_dmepid);
|
||||
CPOUT_32(pl->pl_sp_weight, bufpl->pl_sp_weight);
|
||||
CPOUT_32(pl->pl_minor, bufpl->pl_minor);
|
||||
CPOUT_32(pl->pl_padding, bufpl->pl_padding);
|
||||
CPOUT_8(pl->pl_reserve, bufpl->pl_reserve, 184);
|
||||
}
|
||||
|
||||
/**
|
||||
* pool_label_in - copies a char buffer into a pool_label_t
|
||||
* @pl: ptr to a pool_label_t struct
|
||||
* @buf: ptr to raw space where label info is copied from
|
||||
*
|
||||
* This function is important because it takes care of all of
|
||||
* the endian issues when information from disk is about to be
|
||||
* used. This way, when machines of different architectures
|
||||
* are used, they will be able to interpret ondisk labels
|
||||
* correctly. Always use this function before using labels that
|
||||
* were read from disk.
|
||||
*/
|
||||
void pool_label_in(struct pool_disk *pl, char *buf)
|
||||
{
|
||||
struct pool_disk *bufpl = (struct pool_disk *) buf;
|
||||
|
||||
CPIN_64(pl->pl_magic, bufpl->pl_magic);
|
||||
CPIN_64(pl->pl_pool_id, bufpl->pl_pool_id);
|
||||
CPIN_8(pl->pl_pool_name, bufpl->pl_pool_name, POOL_NAME_SIZE);
|
||||
CPIN_32(pl->pl_version, bufpl->pl_version);
|
||||
CPIN_32(pl->pl_subpools, bufpl->pl_subpools);
|
||||
CPIN_32(pl->pl_sp_id, bufpl->pl_sp_id);
|
||||
CPIN_32(pl->pl_sp_devs, bufpl->pl_sp_devs);
|
||||
CPIN_32(pl->pl_sp_devid, bufpl->pl_sp_devid);
|
||||
CPIN_32(pl->pl_sp_type, bufpl->pl_sp_type);
|
||||
CPIN_64(pl->pl_blocks, bufpl->pl_blocks);
|
||||
CPIN_32(pl->pl_striping, bufpl->pl_striping);
|
||||
CPIN_32(pl->pl_sp_dmepdevs, bufpl->pl_sp_dmepdevs);
|
||||
CPIN_32(pl->pl_sp_dmepid, bufpl->pl_sp_dmepid);
|
||||
CPIN_32(pl->pl_sp_weight, bufpl->pl_sp_weight);
|
||||
CPIN_32(pl->pl_minor, bufpl->pl_minor);
|
||||
CPIN_32(pl->pl_padding, bufpl->pl_padding);
|
||||
CPIN_8(pl->pl_reserve, bufpl->pl_reserve, 184);
|
||||
}
|
||||
|
||||
static char _calc_char(unsigned int id)
|
||||
{
|
||||
/*
|
||||
* [0-9A-Za-z!#] - 64 printable chars (6-bits)
|
||||
*/
|
||||
|
||||
if (id < 10)
|
||||
return id + 48;
|
||||
if (id < 36)
|
||||
return (id - 10) + 65;
|
||||
if (id < 62)
|
||||
return (id - 36) + 97;
|
||||
if (id == 62)
|
||||
return '!';
|
||||
if (id == 63)
|
||||
return '#';
|
||||
|
||||
return '%';
|
||||
}
|
||||
|
||||
void get_pool_uuid(char *uuid, uint64_t poolid, uint32_t spid, uint32_t devid)
|
||||
{
|
||||
int i;
|
||||
unsigned shifter = 0x003F;
|
||||
|
||||
assert(ID_LEN == 32);
|
||||
memset(uuid, 0, ID_LEN);
|
||||
strcat(uuid, "POOL0000000000");
|
||||
|
||||
/* We grab the entire 64 bits (+2 that get shifted in) */
|
||||
for (i = 13; i < 24; i++) {
|
||||
uuid[i] = _calc_char(((unsigned) poolid) & shifter);
|
||||
poolid = poolid >> 6;
|
||||
}
|
||||
|
||||
/* We grab the entire 32 bits (+4 that get shifted in) */
|
||||
for (i = 24; i < 30; i++) {
|
||||
uuid[i] = _calc_char((unsigned) (spid & shifter));
|
||||
spid = spid >> 6;
|
||||
}
|
||||
|
||||
/*
|
||||
* Since we can only have 128 devices, we only worry about the
|
||||
* last 12 bits
|
||||
*/
|
||||
for (i = 30; i < 32; i++) {
|
||||
uuid[i] = _calc_char((unsigned) (devid & shifter));
|
||||
devid = devid >> 6;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int _read_vg_pds(const struct format_type *fmt, struct pool *mem,
|
||||
struct lvmcache_vginfo *vginfo, struct list *head,
|
||||
uint32_t *devcount)
|
||||
{
|
||||
|
||||
struct list *vgih = NULL;
|
||||
struct device *dev;
|
||||
struct pool_list *pl = NULL;
|
||||
struct pool *tmpmem = NULL;
|
||||
|
||||
uint32_t sp_count = 0;
|
||||
uint32_t *sp_devs = NULL;
|
||||
int i;
|
||||
|
||||
/* FIXME: maybe should return a different error in memory
|
||||
* allocation failure */
|
||||
if (!(tmpmem = pool_create("pool read_vg", 512))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
list_iterate(vgih, &vginfo->infos) {
|
||||
dev = list_item(vgih, struct lvmcache_info)->dev;
|
||||
if (dev &&
|
||||
!(pl = read_pool_disk(fmt, dev, mem, vginfo->vgname)))
|
||||
break;
|
||||
/*
|
||||
* We need to keep track of the total expected number
|
||||
* of devices per subpool
|
||||
*/
|
||||
if (!sp_count) {
|
||||
sp_count = pl->pd.pl_subpools;
|
||||
if (!(sp_devs =
|
||||
pool_zalloc(tmpmem,
|
||||
sizeof(uint32_t) * sp_count))) {
|
||||
log_error("Unable to allocate %d 32-bit uints",
|
||||
sp_count);
|
||||
pool_destroy(tmpmem);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* watch out for a pool label with a different subpool
|
||||
* count than the original - give up if it does
|
||||
*/
|
||||
if (sp_count != pl->pd.pl_subpools)
|
||||
break;
|
||||
|
||||
_add_pl_to_list(head, pl);
|
||||
|
||||
if (sp_count > pl->pd.pl_sp_id && sp_devs[pl->pd.pl_sp_id] == 0)
|
||||
sp_devs[pl->pd.pl_sp_id] = pl->pd.pl_sp_devs;
|
||||
}
|
||||
|
||||
*devcount = 0;
|
||||
for (i = 0; i < sp_count; i++) {
|
||||
*devcount += sp_devs[i];
|
||||
}
|
||||
|
||||
pool_destroy(tmpmem);
|
||||
|
||||
if (pl && *pl->pd.pl_pool_name)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int read_pool_pds(const struct format_type *fmt, const char *vg_name,
|
||||
struct pool *mem, struct list *pdhead)
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
uint32_t totaldevs;
|
||||
int full_scan = -1;
|
||||
|
||||
do {
|
||||
/*
|
||||
* If the cache scanning doesn't work, this will never work
|
||||
*/
|
||||
if (vg_name && (vginfo = vginfo_from_vgname(vg_name)) &&
|
||||
vginfo->infos.n) {
|
||||
|
||||
if (_read_vg_pds(fmt, mem, vginfo, pdhead, &totaldevs)) {
|
||||
/*
|
||||
* If we found all the devices we were
|
||||
* expecting, return success
|
||||
*/
|
||||
if (list_size(pdhead) == totaldevs)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* accept partial pool if we've done a full
|
||||
* rescan of the cache
|
||||
*/
|
||||
if (full_scan > 0)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
/* Failed */
|
||||
list_init(pdhead);
|
||||
|
||||
full_scan++;
|
||||
if (full_scan > 1) {
|
||||
log_debug("No devices for vg %s found in cache",
|
||||
vg_name);
|
||||
return 0;
|
||||
}
|
||||
lvmcache_label_scan(fmt->cmd, full_scan);
|
||||
|
||||
} while (1);
|
||||
|
||||
}
|
||||
|
||||
struct pool_list *read_pool_disk(const struct format_type *fmt,
|
||||
struct device *dev, struct pool *mem,
|
||||
const char *vg_name)
|
||||
{
|
||||
struct pool_list *pl;
|
||||
|
||||
if (!dev_open(dev)) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(pl = 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 (!dev_close(dev))
|
||||
stack;
|
||||
|
||||
return pl;
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user