mirror of
git://sourceware.org/git/lvm2.git
synced 2025-12-24 16:23:50 +03:00
Compare commits
101 Commits
dm_v1_02_0
...
old-dm_v1_
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f95dbff71f | ||
|
|
098f6830a6 | ||
|
|
d1ecebdb52 | ||
|
|
590b654251 | ||
|
|
3bf190c8ab | ||
|
|
dcca7638e0 | ||
|
|
70e45ad37b | ||
|
|
db88210289 | ||
|
|
d2e0d96cc3 | ||
|
|
3feba82ccc | ||
|
|
db924da231 | ||
|
|
fc55ae7e6d | ||
|
|
86e757a6ad | ||
|
|
4790715cd3 | ||
|
|
e7e9c60042 | ||
|
|
1c3bc52cc4 | ||
|
|
5227dff0e1 | ||
|
|
33f0b5b7c2 | ||
|
|
0a02968303 | ||
|
|
f7bf658c07 | ||
|
|
8d16a0abad | ||
|
|
c974b97ca3 | ||
|
|
b8025bfebd | ||
|
|
30323b253f | ||
|
|
535c3ede96 | ||
|
|
89fed8ca33 | ||
|
|
f43c77aaed | ||
|
|
96c676b371 | ||
|
|
113047e1a2 | ||
|
|
abed57cb53 | ||
|
|
c01a800a6b | ||
|
|
d648832a2d | ||
|
|
f06833fbd2 | ||
|
|
c561addc94 | ||
|
|
702f5f1f4c | ||
|
|
1273f179e8 | ||
|
|
5d02f60bde | ||
|
|
4cf7a108e8 | ||
|
|
42635c3938 | ||
|
|
ed43dc842b | ||
|
|
49d4db6cd2 | ||
|
|
ea80ab2cae | ||
|
|
382e808b8d | ||
|
|
846befa7e0 | ||
|
|
74dd29f843 | ||
|
|
b0473bffcb | ||
|
|
24dd9ab1a7 | ||
|
|
49d3037e87 | ||
|
|
37ad2bd4e8 | ||
|
|
7d7b332b02 | ||
|
|
ac033b8612 | ||
|
|
a7b98dfe25 | ||
|
|
7fb7c86c46 | ||
|
|
ed036598a9 | ||
|
|
160bb70cdf | ||
|
|
c2e61f3c21 | ||
|
|
18218467f3 | ||
|
|
17e298ad2a | ||
|
|
d031a374f9 | ||
|
|
55f69c98cb | ||
|
|
71f2e4306d | ||
|
|
f8af23a025 | ||
|
|
4ef55a6cd3 | ||
|
|
312f866723 | ||
|
|
0ebe1f6dec | ||
|
|
2ad92e0e6e | ||
|
|
ac8823cdcf | ||
|
|
77565f7ee4 | ||
|
|
d656d90fa8 | ||
|
|
175b3b0834 | ||
|
|
7477e6b714 | ||
|
|
cd6568db69 | ||
|
|
6aff325fb2 | ||
|
|
0d603cfe9c | ||
|
|
34a1f14a17 | ||
|
|
efe1c8a070 | ||
|
|
1575844344 | ||
|
|
221ac1c208 | ||
|
|
57442db759 | ||
|
|
5fdb3e7cd6 | ||
|
|
96f259726c | ||
|
|
4936efba5e | ||
|
|
d5a3559a2f | ||
|
|
114a1c7f52 | ||
|
|
ce5265c203 | ||
|
|
1a575d926f | ||
|
|
85c818a39e | ||
|
|
4ffa2defe4 | ||
|
|
8825157fbb | ||
|
|
966d608dc5 | ||
|
|
b808c89471 | ||
|
|
75d4e6490f | ||
|
|
a82775f544 | ||
|
|
6a22ad0171 | ||
|
|
c854e88186 | ||
|
|
d02203060c | ||
|
|
cf703b0433 | ||
|
|
c0197a72d3 | ||
|
|
e5a543e283 | ||
|
|
b8b029b7d3 | ||
|
|
370f368b1a |
21
Makefile.in
21
Makefile.in
@@ -24,8 +24,13 @@ endif
|
||||
|
||||
SUBDIRS += lib tools daemons
|
||||
|
||||
ifeq ("@DMEVENTD@", "yes")
|
||||
SUBDIRS += dmeventd
|
||||
endif
|
||||
|
||||
ifeq ($(MAKECMDGOALS),distclean)
|
||||
SUBDIRS += daemons/clvmd \
|
||||
dmeventd \
|
||||
lib/format1 \
|
||||
lib/format_pool \
|
||||
lib/locking \
|
||||
@@ -40,13 +45,25 @@ include make.tmpl
|
||||
daemons: lib
|
||||
lib: include
|
||||
tools: lib
|
||||
po: tools daemons
|
||||
dmeventd: tools
|
||||
po: tools daemons dmeventd
|
||||
|
||||
ifeq ("@INTL@", "yes")
|
||||
lib.pofile: include.pofile
|
||||
tools.pofile: lib.pofile
|
||||
daemons.pofile: lib.pofile
|
||||
po.pofile: tools.pofile daemons.pofile
|
||||
dmeventd.pofile: tools.pofile
|
||||
po.pofile: tools.pofile daemons.pofile dmeventd.pofile
|
||||
pofile: po.pofile
|
||||
endif
|
||||
|
||||
ifneq ("@CFLOW_CMD@", "")
|
||||
tools.cflow: lib.cflow
|
||||
cflow: tools.cflow
|
||||
endif
|
||||
|
||||
ifneq ("@CSCOPE_CMD@", "")
|
||||
cscope.out: tools
|
||||
@CSCOPE_CMD@ -b -R
|
||||
all: cscope.out
|
||||
endif
|
||||
|
||||
46
WHATS_NEW
46
WHATS_NEW
@@ -1,5 +1,47 @@
|
||||
Version 2.02.02
|
||||
====================================
|
||||
Version 2.02.04 -
|
||||
=================================
|
||||
Check for libsepol.
|
||||
Add some cflow & scope support.
|
||||
Separate out DEFS from CFLAGS.
|
||||
Remove inlines and use unique function names.
|
||||
|
||||
Version 2.02.03 - 14th April 2006
|
||||
=================================
|
||||
vgrename accepts vgid and exported VG.
|
||||
Add --partial to pvs.
|
||||
When choosing between identically-named VGs, also consider creation_host.
|
||||
Provide total log suppression with 2.
|
||||
Fix vgexport/vgimport to set/reset PV exported flag so pv_attr is correct.
|
||||
Add vgid to struct physical_volume and pass with vg_name to some functions.
|
||||
If two or more VGs are found with the same name, use one that is not exported.
|
||||
Whenever vgname is captured, also capture vgid and whether exported.
|
||||
Remove an incorrect unlock_vg() from process_each_lv().
|
||||
Update extent size information in vgchange and vgcreate man pages.
|
||||
Introduce origin_from_cow() and lv_is_visible().
|
||||
pvremove without -f now fails if there's no PV label.
|
||||
Support lvconvert -s.
|
||||
Suppress locking library load failure message if --ignorelockingfailure.
|
||||
Propagate partial mode around cluster.
|
||||
Fix archive file expiration.
|
||||
Fix dmeventd build.
|
||||
clvmd now uses libcman rather than cman ioctls.
|
||||
clvmd will allow new cman to shutdown on request.
|
||||
|
||||
Version 2.02.02 - 7th February 2006
|
||||
===================================
|
||||
Add %.so: %.a make template rule.
|
||||
Switchover library building to use LIB_SUFFIX.
|
||||
Only do lockfs filesystem sync when suspending snapshots.
|
||||
Always print warning if activation is disabled.
|
||||
vgreduce removes mirror images.
|
||||
Add --mirrorsonly to vgreduce.
|
||||
vgreduce replaces active LVs with error segment before removing them.
|
||||
Set block_on_error parameter if available.
|
||||
Add target_version.
|
||||
Add details to format1 'Invalid LV in extent map' error message.
|
||||
Fix lvscan snapshot full display.
|
||||
Bring lvdisplay man page example into line.
|
||||
Add mirror dmeventd library.
|
||||
Add some activation logic to remove_mirror_images().
|
||||
lvconvert can remove specified PVs from a mirror.
|
||||
lvconvert turns an existing LV into a mirror.
|
||||
|
||||
34
WHATS_NEW_DM
34
WHATS_NEW_DM
@@ -1,3 +1,37 @@
|
||||
Version 1.02.06 -
|
||||
=============================
|
||||
|
||||
Version 1.02.05 - 19 Apr 2006
|
||||
=============================
|
||||
Separate install_include target in makefiles.
|
||||
Separate out DEFS from CFLAGS.
|
||||
Support pkg-config.
|
||||
Check for libsepol.
|
||||
|
||||
Version 1.02.04 - 14 Apr 2006
|
||||
=============================
|
||||
Bring dmsetup man page up-to-date.
|
||||
Use name-based device refs if kernel doesn't support device number refs.
|
||||
Fix memory leak (struct dm_ioctl) when struct dm_task is reused.
|
||||
If _create_and_load_v4 fails part way through, revert the creation.
|
||||
dmeventd thread/fifo fixes.
|
||||
Add file & line to dm_strdup_aux().
|
||||
Add setgeometry.
|
||||
|
||||
Version 1.02.03 - 7 Feb 2006
|
||||
============================
|
||||
Add exported functions to set uid, gid and mode.
|
||||
Rename _log to dm_log and export.
|
||||
Add dm_tree_skip_lockfs.
|
||||
Fix dm_strdup debug definition.
|
||||
Fix hash function to avoid using a negative array offset.
|
||||
Don't inline _find in hash.c and tidy signed/unsigned etc.
|
||||
Fix libdevmapper.h #endif.
|
||||
Fix dmsetup version driver version.
|
||||
Add sync, nosync and block_on_error mirror log parameters.
|
||||
Add hweight32.
|
||||
Fix dmeventd build.
|
||||
|
||||
Version 1.02.02 - 2 Dec 2005
|
||||
============================
|
||||
dmeventd added.
|
||||
|
||||
237
configure
vendored
237
configure
vendored
@@ -310,7 +310,7 @@ ac_includes_default="\
|
||||
#endif"
|
||||
|
||||
ac_default_prefix=/usr
|
||||
ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os AWK CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN_S SET_MAKE RANLIB ac_ct_RANLIB CPP EGREP ALLOCA LIBOBJS POW_LIB MSGFMT MODPROBE_CMD JOBS STATIC_LINK LVM1 POOL SNAPSHOTS MIRRORS OWNER GROUP COPTIMISE_FLAG CLDFLAGS CLDWHOLEARCHIVE CLDNOWHOLEARCHIVE LDDEPS SOFLAG LVM_VERSION LVM1_FALLBACK DEBUG DEVMAPPER HAVE_LIBDL HAVE_SELINUX CMDLIB LOCALEDIR CONFDIR STATICDIR INTL_PACKAGE INTL CLVMD CLUSTER FSADM LTLIBOBJS'
|
||||
ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os AWK CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN_S SET_MAKE RANLIB ac_ct_RANLIB CFLOW_CMD CSCOPE_CMD CPP EGREP ALLOCA LIBOBJS POW_LIB MSGFMT MODPROBE_CMD JOBS STATIC_LINK LVM1 POOL SNAPSHOTS MIRRORS OWNER GROUP LVM_DEFS COPTIMISE_FLAG CLDFLAGS CLDWHOLEARCHIVE CLDNOWHOLEARCHIVE LDDEPS LIB_SUFFIX LVM_VERSION LVM1_FALLBACK DEBUG DEVMAPPER HAVE_LIBDL HAVE_SELINUX CMDLIB LOCALEDIR CONFDIR STATICDIR INTL_PACKAGE INTL CLVMD CLUSTER FSADM DMEVENTD LTLIBOBJS'
|
||||
ac_subst_files=''
|
||||
|
||||
# Initialize some variables set by options.
|
||||
@@ -858,6 +858,7 @@ Optional Features:
|
||||
--disable-o_direct Disable O_DIRECT
|
||||
--enable-cmdlib Build shared command library
|
||||
--enable-fsadm Enable fsadm
|
||||
--enable-dmeventd Enable the device-mapper event daemon
|
||||
--enable-nls Enable Native Language Support
|
||||
|
||||
Optional Packages:
|
||||
@@ -1450,7 +1451,7 @@ case "$host_os" in
|
||||
CLDNOWHOLEARCHIVE="-Wl,-no-whole-archive"
|
||||
LDDEPS="$LDDEPS .export.sym"
|
||||
LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
|
||||
SOFLAG="-shared"
|
||||
LIB_SUFFIX="so"
|
||||
DEVMAPPER=yes
|
||||
ODIRECT=yes
|
||||
SELINUX=yes
|
||||
@@ -1464,7 +1465,7 @@ case "$host_os" in
|
||||
CLDNOWHOLEARCHIVE=
|
||||
LDDEPS="$LDDEPS"
|
||||
LDFLAGS="$LDFLAGS"
|
||||
SOFLAG="-dynamiclib"
|
||||
LIB_SUFFIX="dylib"
|
||||
DEVMAPPER=yes
|
||||
ODIRECT=no
|
||||
SELINUX=no
|
||||
@@ -2642,6 +2643,84 @@ else
|
||||
RANLIB="$ac_cv_prog_RANLIB"
|
||||
fi
|
||||
|
||||
# Extract the first word of "cflow", so it can be a program name with args.
|
||||
set dummy cflow; ac_word=$2
|
||||
echo "$as_me:$LINENO: checking for $ac_word" >&5
|
||||
echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
|
||||
if test "${ac_cv_path_CFLOW_CMD+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
case $CFLOW_CMD in
|
||||
[\\/]* | ?:[\\/]*)
|
||||
ac_cv_path_CFLOW_CMD="$CFLOW_CMD" # Let the user override the test with a path.
|
||||
;;
|
||||
*)
|
||||
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
for as_dir in $PATH
|
||||
do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_path_CFLOW_CMD="$as_dir/$ac_word$ac_exec_ext"
|
||||
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
CFLOW_CMD=$ac_cv_path_CFLOW_CMD
|
||||
|
||||
if test -n "$CFLOW_CMD"; then
|
||||
echo "$as_me:$LINENO: result: $CFLOW_CMD" >&5
|
||||
echo "${ECHO_T}$CFLOW_CMD" >&6
|
||||
else
|
||||
echo "$as_me:$LINENO: result: no" >&5
|
||||
echo "${ECHO_T}no" >&6
|
||||
fi
|
||||
|
||||
# Extract the first word of "cscope", so it can be a program name with args.
|
||||
set dummy cscope; ac_word=$2
|
||||
echo "$as_me:$LINENO: checking for $ac_word" >&5
|
||||
echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
|
||||
if test "${ac_cv_path_CSCOPE_CMD+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
case $CSCOPE_CMD in
|
||||
[\\/]* | ?:[\\/]*)
|
||||
ac_cv_path_CSCOPE_CMD="$CSCOPE_CMD" # Let the user override the test with a path.
|
||||
;;
|
||||
*)
|
||||
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
for as_dir in $PATH
|
||||
do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_path_CSCOPE_CMD="$as_dir/$ac_word$ac_exec_ext"
|
||||
echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
CSCOPE_CMD=$ac_cv_path_CSCOPE_CMD
|
||||
|
||||
if test -n "$CSCOPE_CMD"; then
|
||||
echo "$as_me:$LINENO: result: $CSCOPE_CMD" >&5
|
||||
echo "${ECHO_T}$CSCOPE_CMD" >&6
|
||||
else
|
||||
echo "$as_me:$LINENO: result: no" >&5
|
||||
echo "${ECHO_T}no" >&6
|
||||
fi
|
||||
|
||||
|
||||
################################################################################
|
||||
|
||||
@@ -7148,7 +7227,7 @@ echo "$as_me:$LINENO: result: $LVM1_FALLBACK" >&5
|
||||
echo "${ECHO_T}$LVM1_FALLBACK" >&6
|
||||
|
||||
if test x$LVM1_FALLBACK = xyes; then
|
||||
CFLAGS="$CFLAGS -DLVM1_FALLBACK"
|
||||
LVM_DEFS="$LVM_DEFS -DLVM1_FALLBACK"
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
@@ -7174,7 +7253,7 @@ echo "$as_me: error: --with-lvm1 parameter invalid
|
||||
fi;
|
||||
|
||||
if test x$LVM1 = xinternal; then
|
||||
CFLAGS="$CFLAGS -DLVM1_INTERNAL"
|
||||
LVM_DEFS="$LVM_DEFS -DLVM1_INTERNAL"
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
@@ -7200,7 +7279,7 @@ echo "$as_me: error: --with-pool parameter invalid
|
||||
fi;
|
||||
|
||||
if test x$POOL = xinternal; then
|
||||
CFLAGS="$CFLAGS -DPOOL_INTERNAL"
|
||||
LVM_DEFS="$LVM_DEFS -DPOOL_INTERNAL"
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
@@ -7224,7 +7303,7 @@ echo "$as_me: error: --with-cluster parameter invalid
|
||||
fi;
|
||||
|
||||
if test x$CLUSTER = xinternal; then
|
||||
CFLAGS="$CFLAGS -DCLUSTER_LOCKING_INTERNAL"
|
||||
LVM_DEFS="$LVM_DEFS -DCLUSTER_LOCKING_INTERNAL"
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
@@ -7250,7 +7329,7 @@ echo "$as_me: error: --with-snapshots parameter invalid
|
||||
fi;
|
||||
|
||||
if test x$SNAPSHOTS = xinternal; then
|
||||
CFLAGS="$CFLAGS -DSNAPSHOT_INTERNAL"
|
||||
LVM_DEFS="$LVM_DEFS -DSNAPSHOT_INTERNAL"
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
@@ -7276,7 +7355,7 @@ echo "$as_me: error: --with-mirrors parameter invalid
|
||||
fi;
|
||||
|
||||
if test x$MIRRORS = xinternal; then
|
||||
CFLAGS="$CFLAGS -DMIRRORED_INTERNAL"
|
||||
LVM_DEFS="$LVM_DEFS -DMIRRORED_INTERNAL"
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
@@ -7306,7 +7385,7 @@ echo "$as_me:$LINENO: result: $READLINE" >&5
|
||||
echo "${ECHO_T}$READLINE" >&6
|
||||
|
||||
if test x$READLINE = xyes; then
|
||||
CFLAGS="$CFLAGS -DREADLINE_SUPPORT"
|
||||
LVM_DEFS="$LVM_DEFS -DREADLINE_SUPPORT"
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
@@ -7356,6 +7435,8 @@ echo "${ECHO_T}$DEBUG" >&6
|
||||
|
||||
if test x$DEBUG = xyes; then
|
||||
COPTIMISE_FLAG=
|
||||
else
|
||||
CSCOPE_CMD=
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
@@ -7382,7 +7463,7 @@ echo "$as_me:$LINENO: result: $DEVMAPPER" >&5
|
||||
echo "${ECHO_T}$DEVMAPPER" >&6
|
||||
|
||||
if test x$DEVMAPPER = xyes; then
|
||||
CFLAGS="$CFLAGS -DDEVMAPPER_SUPPORT"
|
||||
LVM_DEFS="$LVM_DEFS -DDEVMAPPER_SUPPORT"
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
@@ -7397,7 +7478,7 @@ echo "$as_me:$LINENO: result: $ODIRECT" >&5
|
||||
echo "${ECHO_T}$ODIRECT" >&6
|
||||
|
||||
if test x$ODIRECT = xyes; then
|
||||
CFLAGS="$CFLAGS -DO_DIRECT_SUPPORT"
|
||||
LVM_DEFS="$LVM_DEFS -DO_DIRECT_SUPPORT"
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
@@ -7414,7 +7495,7 @@ echo "$as_me:$LINENO: result: $CMDLIB" >&5
|
||||
echo "${ECHO_T}$CMDLIB" >&6
|
||||
|
||||
if test x$CMDLIB = xyes; then
|
||||
CFLAGS="$CFLAGS -DCMDLIB"
|
||||
LVM_DEFS="$LVM_DEFS -DCMDLIB"
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
@@ -7428,6 +7509,28 @@ fi;
|
||||
echo "$as_me:$LINENO: result: $FSADM" >&5
|
||||
echo "${ECHO_T}$FSADM" >&6
|
||||
|
||||
################################################################################
|
||||
echo "$as_me:$LINENO: checking whether to use dmeventd" >&5
|
||||
echo $ECHO_N "checking whether to use dmeventd... $ECHO_C" >&6
|
||||
# Check whether --enable-dmeventd or --disable-dmeventd was given.
|
||||
if test "${enable_dmeventd+set}" = set; then
|
||||
enableval="$enable_dmeventd"
|
||||
DMEVENTD=$enableval
|
||||
fi;
|
||||
echo "$as_me:$LINENO: result: $DMEVENTD" >&5
|
||||
echo "${ECHO_T}$DMEVENTD" >&6
|
||||
|
||||
if test x$DMEVENTD = xyes && test x$MIRRORS != xinternal; then
|
||||
{ { echo "$as_me:$LINENO: error: --enable-dmeventd currently requires --with-mirrors=internal
|
||||
" >&5
|
||||
echo "$as_me: error: --enable-dmeventd currently requires --with-mirrors=internal
|
||||
" >&2;}
|
||||
{ (exit 1); exit 1; }; }
|
||||
fi
|
||||
|
||||
if test x$DMEVENTD = xyes; then
|
||||
LVM_DEFS="$LVM_DEFS -DDMEVENTD"
|
||||
fi
|
||||
################################################################################
|
||||
if [ "x$exec_prefix" = xNONE -a "x$prefix" = xNONE ];
|
||||
then exec_prefix="";
|
||||
@@ -8087,7 +8190,7 @@ fi
|
||||
|
||||
|
||||
if [ "x$HAVE_LIBDL" = xyes ]; then
|
||||
CFLAGS="$CFLAGS -DHAVE_LIBDL"
|
||||
LVM_DEFS="$LVM_DEFS -DHAVE_LIBDL"
|
||||
LIBS="-ldl $LIBS"
|
||||
else
|
||||
HAVE_LIBDL=no
|
||||
@@ -8106,6 +8209,85 @@ fi
|
||||
|
||||
################################################################################
|
||||
if test x$SELINUX = xyes; then
|
||||
echo "$as_me:$LINENO: checking for sepol_check_context function" >&5
|
||||
echo $ECHO_N "checking for sepol_check_context function... $ECHO_C" >&6
|
||||
echo "$as_me:$LINENO: checking for sepol_check_context in -lsepol" >&5
|
||||
echo $ECHO_N "checking for sepol_check_context in -lsepol... $ECHO_C" >&6
|
||||
if test "${ac_cv_lib_sepol_sepol_check_context+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
ac_check_lib_save_LIBS=$LIBS
|
||||
LIBS="-lsepol $LIBS"
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any gcc2 internal prototype to avoid an error. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
/* We use char because int might match the return type of a gcc2
|
||||
builtin and then its argument prototype would still apply. */
|
||||
char sepol_check_context ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
sepol_check_context ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
rm -f conftest.$ac_objext conftest$ac_exeext
|
||||
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
|
||||
(eval $ac_link) 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } &&
|
||||
{ ac_try='test -z "$ac_c_werror_flag"
|
||||
|| test ! -s conftest.err'
|
||||
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); }; } &&
|
||||
{ ac_try='test -s conftest$ac_exeext'
|
||||
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); }; }; then
|
||||
ac_cv_lib_sepol_sepol_check_context=yes
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
ac_cv_lib_sepol_sepol_check_context=no
|
||||
fi
|
||||
rm -f conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
LIBS=$ac_check_lib_save_LIBS
|
||||
fi
|
||||
echo "$as_me:$LINENO: result: $ac_cv_lib_sepol_sepol_check_context" >&5
|
||||
echo "${ECHO_T}$ac_cv_lib_sepol_sepol_check_context" >&6
|
||||
if test $ac_cv_lib_sepol_sepol_check_context = yes; then
|
||||
HAVE_SEPOL=yes
|
||||
else
|
||||
HAVE_SEPOL=no
|
||||
fi
|
||||
|
||||
echo "$as_me:$LINENO: result: $HAVE_SEPOL" >&5
|
||||
echo "${ECHO_T}$HAVE_SEPOL" >&6
|
||||
|
||||
if test x$HAVE_SEPOL = xyes; then
|
||||
LIBS="-lsepol $LIBS"
|
||||
fi
|
||||
|
||||
echo "$as_me:$LINENO: checking for is_selinux_enabled function" >&5
|
||||
echo $ECHO_N "checking for is_selinux_enabled function... $ECHO_C" >&6
|
||||
echo "$as_me:$LINENO: checking for is_selinux_enabled in -lselinux" >&5
|
||||
@@ -8182,7 +8364,7 @@ fi
|
||||
echo "${ECHO_T}$HAVE_SELINUX" >&6
|
||||
|
||||
if test x$HAVE_SELINUX = xyes; then
|
||||
CFLAGS="$CFLAGS -DHAVE_SELINUX"
|
||||
LVM_DEFS="$LVM_DEFS -DHAVE_SELINUX"
|
||||
LIBS="-lselinux $LIBS"
|
||||
else
|
||||
{ echo "$as_me:$LINENO: WARNING: Disabling selinux" >&5
|
||||
@@ -8336,7 +8518,7 @@ if test `eval echo '${'$as_ac_Header'}'` = yes; then
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
|
||||
_ACEOF
|
||||
CFLAGS="$CFLAGS -DHAVE_GETOPTLONG"
|
||||
LVM_DEFS="$LVM_DEFS -DHAVE_GETOPTLONG"
|
||||
fi
|
||||
|
||||
done
|
||||
@@ -8526,7 +8708,7 @@ fi
|
||||
echo "$as_me:$LINENO: result: $ac_cv_func_rl_completion_matches" >&5
|
||||
echo "${ECHO_T}$ac_cv_func_rl_completion_matches" >&6
|
||||
if test $ac_cv_func_rl_completion_matches = yes; then
|
||||
CFLAGS="$CFLAGS -DHAVE_RL_COMPLETION_MATCHES"
|
||||
LVM_DEFS="$LVM_DEFS -DHAVE_RL_COMPLETION_MATCHES"
|
||||
fi
|
||||
|
||||
|
||||
@@ -10810,7 +10992,7 @@ fi
|
||||
|
||||
|
||||
if test x$MODPROBE_CMD != x; then
|
||||
CFLAGS="$CFLAGS -DMODPROBE_CMD=\\\"$MODPROBE_CMD\\\""
|
||||
LVM_DEFS="$LVM_DEFS -DMODPROBE_CMD=\\\"$MODPROBE_CMD\\\""
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
@@ -10850,13 +11032,17 @@ fi
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
################################################################################
|
||||
ac_config_files="$ac_config_files 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"
|
||||
ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile dmeventd/Makefile dmeventd/mirror/Makefile doc/Makefile include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/snapshot/Makefile man/Makefile po/Makefile tools/Makefile tools/version.h tools/fsadm/Makefile test/mm/Makefile test/device/Makefile test/format1/Makefile test/regex/Makefile test/filters/Makefile"
|
||||
cat >confcache <<\_ACEOF
|
||||
# This file is a shell script that caches the results of configure
|
||||
# tests run on this system so they can be shared between configure
|
||||
@@ -11412,6 +11598,8 @@ do
|
||||
"make.tmpl" ) CONFIG_FILES="$CONFIG_FILES make.tmpl" ;;
|
||||
"daemons/Makefile" ) CONFIG_FILES="$CONFIG_FILES daemons/Makefile" ;;
|
||||
"daemons/clvmd/Makefile" ) CONFIG_FILES="$CONFIG_FILES daemons/clvmd/Makefile" ;;
|
||||
"dmeventd/Makefile" ) CONFIG_FILES="$CONFIG_FILES dmeventd/Makefile" ;;
|
||||
"dmeventd/mirror/Makefile" ) CONFIG_FILES="$CONFIG_FILES dmeventd/mirror/Makefile" ;;
|
||||
"doc/Makefile" ) CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;;
|
||||
"include/Makefile" ) CONFIG_FILES="$CONFIG_FILES include/Makefile" ;;
|
||||
"lib/Makefile" ) CONFIG_FILES="$CONFIG_FILES lib/Makefile" ;;
|
||||
@@ -11540,6 +11728,8 @@ s,@LN_S@,$LN_S,;t t
|
||||
s,@SET_MAKE@,$SET_MAKE,;t t
|
||||
s,@RANLIB@,$RANLIB,;t t
|
||||
s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t
|
||||
s,@CFLOW_CMD@,$CFLOW_CMD,;t t
|
||||
s,@CSCOPE_CMD@,$CSCOPE_CMD,;t t
|
||||
s,@CPP@,$CPP,;t t
|
||||
s,@EGREP@,$EGREP,;t t
|
||||
s,@ALLOCA@,$ALLOCA,;t t
|
||||
@@ -11555,12 +11745,13 @@ s,@SNAPSHOTS@,$SNAPSHOTS,;t t
|
||||
s,@MIRRORS@,$MIRRORS,;t t
|
||||
s,@OWNER@,$OWNER,;t t
|
||||
s,@GROUP@,$GROUP,;t t
|
||||
s,@LVM_DEFS@,$LVM_DEFS,;t t
|
||||
s,@COPTIMISE_FLAG@,$COPTIMISE_FLAG,;t t
|
||||
s,@CLDFLAGS@,$CLDFLAGS,;t t
|
||||
s,@CLDWHOLEARCHIVE@,$CLDWHOLEARCHIVE,;t t
|
||||
s,@CLDNOWHOLEARCHIVE@,$CLDNOWHOLEARCHIVE,;t t
|
||||
s,@LDDEPS@,$LDDEPS,;t t
|
||||
s,@SOFLAG@,$SOFLAG,;t t
|
||||
s,@LIB_SUFFIX@,$LIB_SUFFIX,;t t
|
||||
s,@LVM_VERSION@,$LVM_VERSION,;t t
|
||||
s,@LVM1_FALLBACK@,$LVM1_FALLBACK,;t t
|
||||
s,@DEBUG@,$DEBUG,;t t
|
||||
@@ -11576,6 +11767,7 @@ s,@INTL@,$INTL,;t t
|
||||
s,@CLVMD@,$CLVMD,;t t
|
||||
s,@CLUSTER@,$CLUSTER,;t t
|
||||
s,@FSADM@,$FSADM,;t t
|
||||
s,@DMEVENTD@,$DMEVENTD,;t t
|
||||
s,@LTLIBOBJS@,$LTLIBOBJS,;t t
|
||||
CEOF
|
||||
|
||||
@@ -11855,3 +12047,8 @@ if test x$FSADM == xyes; then
|
||||
{ echo "$as_me:$LINENO: WARNING: fsadm support is untested" >&5
|
||||
echo "$as_me: WARNING: fsadm support is untested" >&2;}
|
||||
fi
|
||||
|
||||
if test x$DMEVENTD == xyes; then
|
||||
{ echo "$as_me:$LINENO: WARNING: dmeventd support is untested" >&5
|
||||
echo "$as_me: WARNING: dmeventd support is untested" >&2;}
|
||||
fi
|
||||
|
||||
77
configure.in
77
configure.in
@@ -35,7 +35,7 @@ case "$host_os" in
|
||||
CLDNOWHOLEARCHIVE="-Wl,-no-whole-archive"
|
||||
LDDEPS="$LDDEPS .export.sym"
|
||||
LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
|
||||
SOFLAG="-shared"
|
||||
LIB_SUFFIX="so"
|
||||
DEVMAPPER=yes
|
||||
ODIRECT=yes
|
||||
SELINUX=yes
|
||||
@@ -49,7 +49,7 @@ case "$host_os" in
|
||||
CLDNOWHOLEARCHIVE=
|
||||
LDDEPS="$LDDEPS"
|
||||
LDFLAGS="$LDFLAGS"
|
||||
SOFLAG="-dynamiclib"
|
||||
LIB_SUFFIX="dylib"
|
||||
DEVMAPPER=yes
|
||||
ODIRECT=no
|
||||
SELINUX=no
|
||||
@@ -65,6 +65,8 @@ AC_PROG_INSTALL
|
||||
AC_PROG_LN_S
|
||||
AC_PROG_MAKE_SET
|
||||
AC_PROG_RANLIB
|
||||
AC_PATH_PROG(CFLOW_CMD, cflow)
|
||||
AC_PATH_PROG(CSCOPE_CMD, cscope)
|
||||
|
||||
################################################################################
|
||||
dnl -- Checks for header files.
|
||||
@@ -150,7 +152,7 @@ AC_ARG_ENABLE(lvm1_fallback, [ --enable-lvm1_fallback Use this to fall back an
|
||||
AC_MSG_RESULT($LVM1_FALLBACK)
|
||||
|
||||
if test x$LVM1_FALLBACK = xyes; then
|
||||
CFLAGS="$CFLAGS -DLVM1_FALLBACK"
|
||||
LVM_DEFS="$LVM_DEFS -DLVM1_FALLBACK"
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
@@ -170,7 +172,7 @@ if [[ "x$LVM1" != xnone -a "x$LVM1" != xinternal -a "x$LVM1" != xshared ]];
|
||||
fi;
|
||||
|
||||
if test x$LVM1 = xinternal; then
|
||||
CFLAGS="$CFLAGS -DLVM1_INTERNAL"
|
||||
LVM_DEFS="$LVM_DEFS -DLVM1_INTERNAL"
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
@@ -190,7 +192,7 @@ if [[ "x$POOL" != xnone -a "x$POOL" != xinternal -a "x$POOL" != xshared ]];
|
||||
fi;
|
||||
|
||||
if test x$POOL = xinternal; then
|
||||
CFLAGS="$CFLAGS -DPOOL_INTERNAL"
|
||||
LVM_DEFS="$LVM_DEFS -DPOOL_INTERNAL"
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
@@ -209,7 +211,7 @@ if [[ "x$CLUSTER" != xnone -a "x$CLUSTER" != xinternal -a "x$CLUSTER" != xshared
|
||||
fi;
|
||||
|
||||
if test x$CLUSTER = xinternal; then
|
||||
CFLAGS="$CFLAGS -DCLUSTER_LOCKING_INTERNAL"
|
||||
LVM_DEFS="$LVM_DEFS -DCLUSTER_LOCKING_INTERNAL"
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
@@ -229,7 +231,7 @@ if [[ "x$SNAPSHOTS" != xnone -a "x$SNAPSHOTS" != xinternal -a "x$SNAPSHOTS" != x
|
||||
fi;
|
||||
|
||||
if test x$SNAPSHOTS = xinternal; then
|
||||
CFLAGS="$CFLAGS -DSNAPSHOT_INTERNAL"
|
||||
LVM_DEFS="$LVM_DEFS -DSNAPSHOT_INTERNAL"
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
@@ -249,7 +251,7 @@ if [[ "x$MIRRORS" != xnone -a "x$MIRRORS" != xinternal -a "x$MIRRORS" != xshared
|
||||
fi;
|
||||
|
||||
if test x$MIRRORS = xinternal; then
|
||||
CFLAGS="$CFLAGS -DMIRRORED_INTERNAL"
|
||||
LVM_DEFS="$LVM_DEFS -DMIRRORED_INTERNAL"
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
@@ -267,7 +269,7 @@ READLINE=$enableval, READLINE=no)
|
||||
AC_MSG_RESULT($READLINE)
|
||||
|
||||
if test x$READLINE = xyes; then
|
||||
CFLAGS="$CFLAGS -DREADLINE_SUPPORT"
|
||||
LVM_DEFS="$LVM_DEFS -DREADLINE_SUPPORT"
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
@@ -305,6 +307,8 @@ AC_MSG_RESULT($DEBUG)
|
||||
dnl -- Normally turn off optimisation for debug builds
|
||||
if test x$DEBUG = xyes; then
|
||||
COPTIMISE_FLAG=
|
||||
else
|
||||
CSCOPE_CMD=
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
@@ -323,7 +327,7 @@ DEVMAPPER=$enableval)
|
||||
AC_MSG_RESULT($DEVMAPPER)
|
||||
|
||||
if test x$DEVMAPPER = xyes; then
|
||||
CFLAGS="$CFLAGS -DDEVMAPPER_SUPPORT"
|
||||
LVM_DEFS="$LVM_DEFS -DDEVMAPPER_SUPPORT"
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
@@ -334,7 +338,7 @@ ODIRECT=$enableval)
|
||||
AC_MSG_RESULT($ODIRECT)
|
||||
|
||||
if test x$ODIRECT = xyes; then
|
||||
CFLAGS="$CFLAGS -DO_DIRECT_SUPPORT"
|
||||
LVM_DEFS="$LVM_DEFS -DO_DIRECT_SUPPORT"
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
@@ -345,7 +349,7 @@ CMDLIB=$enableval, CMDLIB=no)
|
||||
AC_MSG_RESULT($CMDLIB)
|
||||
|
||||
if test x$CMDLIB = xyes; then
|
||||
CFLAGS="$CFLAGS -DCMDLIB"
|
||||
LVM_DEFS="$LVM_DEFS -DCMDLIB"
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
@@ -355,6 +359,23 @@ AC_ARG_ENABLE(fsadm, [ --enable-fsadm Enable fsadm],
|
||||
FSADM=$enableval)
|
||||
AC_MSG_RESULT($FSADM)
|
||||
|
||||
################################################################################
|
||||
dnl -- enable dmeventd handling
|
||||
AC_MSG_CHECKING(whether to use dmeventd)
|
||||
AC_ARG_ENABLE(dmeventd, [ --enable-dmeventd Enable the device-mapper event daemon],
|
||||
DMEVENTD=$enableval)
|
||||
AC_MSG_RESULT($DMEVENTD)
|
||||
|
||||
dnl -- dmeventd currently requires internal mirror support
|
||||
if test x$DMEVENTD = xyes && test x$MIRRORS != xinternal; then
|
||||
AC_MSG_ERROR(
|
||||
--enable-dmeventd currently requires --with-mirrors=internal
|
||||
)
|
||||
fi
|
||||
|
||||
if test x$DMEVENTD = xyes; then
|
||||
LVM_DEFS="$LVM_DEFS -DDMEVENTD"
|
||||
fi
|
||||
################################################################################
|
||||
dnl -- Mess with default exec_prefix
|
||||
if [[ "x$exec_prefix" = xNONE -a "x$prefix" = xNONE ]];
|
||||
@@ -390,7 +411,7 @@ dnl -- Check for dlopen
|
||||
AC_CHECK_LIB(dl, dlopen, HAVE_LIBDL=yes, HAVE_LIBDL=no)
|
||||
|
||||
if [[ "x$HAVE_LIBDL" = xyes ]]; then
|
||||
CFLAGS="$CFLAGS -DHAVE_LIBDL"
|
||||
LVM_DEFS="$LVM_DEFS -DHAVE_LIBDL"
|
||||
LIBS="-ldl $LIBS"
|
||||
else
|
||||
HAVE_LIBDL=no
|
||||
@@ -407,14 +428,22 @@ Features cannot be 'shared' when building statically
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Check for is_selinux_enabled
|
||||
dnl -- Check for selinux
|
||||
if test x$SELINUX = xyes; then
|
||||
AC_MSG_CHECKING(for sepol_check_context function)
|
||||
AC_CHECK_LIB(sepol, sepol_check_context, HAVE_SEPOL=yes, HAVE_SEPOL=no)
|
||||
AC_MSG_RESULT($HAVE_SEPOL)
|
||||
|
||||
if test x$HAVE_SEPOL = xyes; then
|
||||
LIBS="-lsepol $LIBS"
|
||||
fi
|
||||
|
||||
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"
|
||||
LVM_DEFS="$LVM_DEFS -DHAVE_SELINUX"
|
||||
LIBS="-lselinux $LIBS"
|
||||
else
|
||||
AC_MSG_WARN(Disabling selinux)
|
||||
@@ -423,7 +452,7 @@ fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Check for getopt
|
||||
AC_CHECK_HEADERS(getopt.h, CFLAGS="$CFLAGS -DHAVE_GETOPTLONG")
|
||||
AC_CHECK_HEADERS(getopt.h, LVM_DEFS="$LVM_DEFS -DHAVE_GETOPTLONG")
|
||||
|
||||
################################################################################
|
||||
dnl -- Check for readline (Shamelessly copied from parted 1.4.17)
|
||||
@@ -438,7 +467,7 @@ Note: if you are using precompiled packages you will also need the development
|
||||
package as well (which may be called readline-devel or something similar).
|
||||
)
|
||||
)
|
||||
AC_CHECK_FUNC(rl_completion_matches, CFLAGS="$CFLAGS -DHAVE_RL_COMPLETION_MATCHES")
|
||||
AC_CHECK_FUNC(rl_completion_matches, LVM_DEFS="$LVM_DEFS -DHAVE_RL_COMPLETION_MATCHES")
|
||||
|
||||
fi
|
||||
|
||||
@@ -519,7 +548,7 @@ fi
|
||||
AC_PATH_PROG(MODPROBE_CMD, modprobe)
|
||||
|
||||
if test x$MODPROBE_CMD != x; then
|
||||
CFLAGS="$CFLAGS -DMODPROBE_CMD=\\\"$MODPROBE_CMD\\\""
|
||||
LVM_DEFS="$LVM_DEFS -DMODPROBE_CMD=\\\"$MODPROBE_CMD\\\""
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
@@ -539,13 +568,14 @@ AC_SUBST(MIRRORS)
|
||||
AC_SUBST(OWNER)
|
||||
AC_SUBST(GROUP)
|
||||
AC_SUBST(CFLAGS)
|
||||
AC_SUBST(LVM_DEFS)
|
||||
AC_SUBST(COPTIMISE_FLAG)
|
||||
AC_SUBST(CLDFLAGS)
|
||||
AC_SUBST(CLDWHOLEARCHIVE)
|
||||
AC_SUBST(CLDNOWHOLEARCHIVE)
|
||||
AC_SUBST(LDDEPS)
|
||||
AC_SUBST(LDFLAGS)
|
||||
AC_SUBST(SOFLAG)
|
||||
AC_SUBST(LIB_SUFFIX)
|
||||
AC_SUBST(LIBS)
|
||||
AC_SUBST(LVM_VERSION)
|
||||
AC_SUBST(LVM1_FALLBACK)
|
||||
@@ -563,6 +593,9 @@ AC_SUBST(INTL)
|
||||
AC_SUBST(CLVMD)
|
||||
AC_SUBST(CLUSTER)
|
||||
AC_SUBST(FSADM)
|
||||
AC_SUBST(DMEVENTD)
|
||||
AC_SUBST(CFLOW_CMD)
|
||||
AC_SUBST(CSCOPE_CMD)
|
||||
|
||||
################################################################################
|
||||
dnl -- First and last lines should not contain files to generate in order to
|
||||
@@ -572,6 +605,8 @@ Makefile \
|
||||
make.tmpl \
|
||||
daemons/Makefile \
|
||||
daemons/clvmd/Makefile \
|
||||
dmeventd/Makefile \
|
||||
dmeventd/mirror/Makefile \
|
||||
doc/Makefile \
|
||||
include/Makefile \
|
||||
lib/Makefile \
|
||||
@@ -599,3 +634,7 @@ fi
|
||||
if test x$FSADM == xyes; then
|
||||
AC_MSG_WARN(fsadm support is untested)
|
||||
fi
|
||||
|
||||
if test x$DMEVENTD == xyes; then
|
||||
AC_MSG_WARN(dmeventd support is untested)
|
||||
fi
|
||||
|
||||
@@ -35,28 +35,38 @@ ifeq ("@CLVMD@", "all")
|
||||
endif
|
||||
|
||||
ifeq ("@DEBUG@", "yes")
|
||||
CFLAGS += -DDEBUG
|
||||
DEFS += -DDEBUG
|
||||
endif
|
||||
|
||||
ifeq ("$(GULM)", "yes")
|
||||
SOURCES += clvmd-gulm.c tcp-comms.c
|
||||
LMLIBS += -lccs -lgulm
|
||||
CFLAGS += -DUSE_GULM
|
||||
DEFS += -DUSE_GULM
|
||||
endif
|
||||
|
||||
ifeq ("$(CMAN)", "yes")
|
||||
SOURCES += clvmd-cman.c
|
||||
LMLIBS += -ldlm
|
||||
CFLAGS += -DUSE_CMAN
|
||||
LMLIBS += -ldlm -lcman
|
||||
DEFS += -DUSE_CMAN
|
||||
endif
|
||||
|
||||
TARGETS = \
|
||||
clvmd
|
||||
|
||||
include $(top_srcdir)/make.tmpl
|
||||
LVMLIBS = -llvm -lpthread
|
||||
|
||||
CFLAGS += -D_REENTRANT -fno-strict-aliasing
|
||||
LIBS += -ldevmapper -llvm -lpthread
|
||||
ifeq ("@DMEVENTD@", "yes")
|
||||
LVMLIBS += -ldevmapper-event
|
||||
endif
|
||||
|
||||
ifeq ("@DEVMAPPER@", "yes")
|
||||
LVMLIBS += -ldevmapper
|
||||
endif
|
||||
|
||||
DEFS += -D_REENTRANT
|
||||
CFLAGS += -fno-strict-aliasing
|
||||
|
||||
include $(top_srcdir)/make.tmpl
|
||||
|
||||
INSTALL_TARGETS = \
|
||||
install_clvmd
|
||||
|
||||
@@ -46,19 +46,23 @@
|
||||
|
||||
#define LOCKSPACE_NAME "clvmd"
|
||||
|
||||
static int cluster_sock;
|
||||
static int num_nodes;
|
||||
static struct cl_cluster_node *nodes = NULL;
|
||||
static struct cman_node *nodes = NULL;
|
||||
static struct cman_node this_node;
|
||||
static int count_nodes; /* size of allocated nodes array */
|
||||
static int max_updown_nodes = 50; /* Current size of the allocated array */
|
||||
/* Node up/down status, indexed by nodeid */
|
||||
static int *node_updown = NULL;
|
||||
static dlm_lshandle_t *lockspace;
|
||||
static cman_handle_t c_handle;
|
||||
|
||||
static void count_clvmds_running(void);
|
||||
static void get_members(void);
|
||||
static int nodeid_from_csid(char *csid);
|
||||
static int name_from_nodeid(int nodeid, char *name);
|
||||
static void event_callback(cman_handle_t handle, void *private, int reason, int arg);
|
||||
static void data_callback(cman_handle_t handle, void *private,
|
||||
char *buf, int len, uint8_t port, int nodeid);
|
||||
|
||||
struct lock_wait {
|
||||
pthread_cond_t cond;
|
||||
@@ -68,30 +72,23 @@ struct lock_wait {
|
||||
|
||||
static int _init_cluster(void)
|
||||
{
|
||||
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) {
|
||||
/* Don't print an error here because we could be just probing for CMAN */
|
||||
c_handle = cman_init(NULL);
|
||||
if (!c_handle) {
|
||||
syslog(LOG_ERR, "Can't open cluster manager socket: %m");
|
||||
return -1;
|
||||
}
|
||||
/* Set Close-on-exec */
|
||||
fcntl(cluster_sock, F_SETFD, 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))) {
|
||||
if (cman_start_recv_data(c_handle, data_callback, CLUSTER_PORT_CLVMD)) {
|
||||
syslog(LOG_ERR, "Can't bind cluster socket: %m");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cman_start_notification(c_handle, event_callback)) {
|
||||
syslog(LOG_ERR, "Can't start cluster event listening");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Get the cluster members list */
|
||||
get_members();
|
||||
count_clvmds_running();
|
||||
@@ -114,63 +111,46 @@ static void _cluster_init_completed(void)
|
||||
|
||||
static int _get_main_cluster_fd()
|
||||
{
|
||||
return cluster_sock;
|
||||
return cman_get_fd(c_handle);
|
||||
}
|
||||
|
||||
static int _get_num_nodes()
|
||||
{
|
||||
return num_nodes;
|
||||
int i;
|
||||
int nnodes = 0;
|
||||
|
||||
/* return number of ACTIVE nodes */
|
||||
for (i=0; i<num_nodes; i++) {
|
||||
if (nodes[i].cn_member)
|
||||
nnodes++;
|
||||
}
|
||||
return nnodes;
|
||||
}
|
||||
|
||||
/* send_message with the fd check removed */
|
||||
static 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;
|
||||
int nodeid = 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;
|
||||
if (csid)
|
||||
memcpy(&nodeid, csid, CMAN_MAX_CSID_LEN);
|
||||
|
||||
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, CMAN_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)
|
||||
if (cman_send_data(c_handle, buf, msglen, 0, CLUSTER_PORT_CLVMD, nodeid) <= 0)
|
||||
{
|
||||
log_error(errtext);
|
||||
|
||||
} while (len == -1 && errno == EAGAIN);
|
||||
return len;
|
||||
}
|
||||
return msglen;
|
||||
}
|
||||
|
||||
static void _get_our_csid(char *csid)
|
||||
{
|
||||
int i;
|
||||
memset(csid, 0, CMAN_MAX_CSID_LEN);
|
||||
|
||||
for (i = 0; i < num_nodes; i++) {
|
||||
if (nodes[i].us)
|
||||
memcpy(csid, &nodes[i].node_id, CMAN_MAX_CSID_LEN);
|
||||
if (this_node.cn_nodeid == 0) {
|
||||
cman_get_node(c_handle, 0, &this_node);
|
||||
}
|
||||
memcpy(csid, &this_node.cn_nodeid, CMAN_MAX_CSID_LEN);
|
||||
}
|
||||
|
||||
/* Call a callback routine for each node that known (down mean not running a clvmd) */
|
||||
/* Call a callback routine for each node is that known (down means not running a clvmd) */
|
||||
static int _cluster_do_node_callback(struct local_client *client,
|
||||
void (*callback) (struct local_client *, char *,
|
||||
int))
|
||||
@@ -179,8 +159,8 @@ static int _cluster_do_node_callback(struct local_client *client,
|
||||
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])
|
||||
callback(client, (char *)&nodes[i].cn_nodeid, node_updown[nodes[i].cn_nodeid]);
|
||||
if (!node_updown[nodes[i].cn_nodeid])
|
||||
somedown = -1;
|
||||
}
|
||||
return somedown;
|
||||
@@ -188,78 +168,63 @@ static int _cluster_do_node_callback(struct local_client *client,
|
||||
|
||||
/* 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)
|
||||
static void event_callback(cman_handle_t handle, void *private, int reason, int arg)
|
||||
{
|
||||
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);
|
||||
char namebuf[MAX_CLUSTER_NAME_LEN];
|
||||
|
||||
node_updown[nodeid] = 0;
|
||||
switch (reason) {
|
||||
case CMAN_REASON_PORTCLOSED:
|
||||
name_from_nodeid(arg, namebuf);
|
||||
log_notice("clvmd on node %s has died\n", namebuf);
|
||||
DEBUGLOG("Got port closed message, removing node %s\n", namebuf);
|
||||
|
||||
node_updown[arg] = 0;
|
||||
break;
|
||||
|
||||
case CLUSTER_OOB_MSG_STATECHANGE:
|
||||
DEBUGLOG("Got OOB message, Cluster state change\n");
|
||||
case CMAN_REASON_STATECHANGE:
|
||||
DEBUGLOG("Got state change message, re-reading members list\n");
|
||||
get_members();
|
||||
break;
|
||||
|
||||
#if defined(LIBCMAN_VERSION) && LIBCMAN_VERSION >= 2
|
||||
case CMAN_REASON_PORTOPENED:
|
||||
/* Ignore this, wait for startup message from clvmd itself */
|
||||
break;
|
||||
|
||||
case CMAN_REASON_TRY_SHUTDOWN:
|
||||
DEBUGLOG("Got try shutdown, sending OK\n");
|
||||
cman_replyto_shutdown(c_handle, 1);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
/* ERROR */
|
||||
DEBUGLOG("Got unknown OOB message: %d\n", buf[0]);
|
||||
DEBUGLOG("Got unknown event callback message: %d\n", reason);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int _cluster_fd_callback(struct local_client *client, char *buf, int len, char *csid,
|
||||
static struct local_client *cman_client;
|
||||
static int _cluster_fd_callback(struct local_client *fd, char *buf, int len, char *csid,
|
||||
struct local_client **new_client)
|
||||
{
|
||||
struct iovec iov[2];
|
||||
struct msghdr msg;
|
||||
struct sockaddr_cl saddr;
|
||||
|
||||
/* Save this for data_callback */
|
||||
cman_client = fd;
|
||||
|
||||
/* 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;
|
||||
return cman_dispatch(c_handle, 0);
|
||||
}
|
||||
|
||||
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;
|
||||
static void data_callback(cman_handle_t handle, void *private,
|
||||
char *buf, int len, uint8_t port, int nodeid)
|
||||
{
|
||||
/* Ignore looped back messages */
|
||||
if (nodeid == this_node.cn_nodeid)
|
||||
return;
|
||||
process_message(cman_client, buf, len, (char *)&nodeid);
|
||||
}
|
||||
|
||||
static void _add_up_node(char *csid)
|
||||
@@ -290,19 +255,15 @@ static void _cluster_closedown()
|
||||
{
|
||||
unlock_all();
|
||||
dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
|
||||
close(cluster_sock);
|
||||
cman_finish(c_handle);
|
||||
}
|
||||
|
||||
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);
|
||||
status = cman_is_listening(c_handle, nodeid, CLUSTER_PORT_CLVMD);
|
||||
if (status < 0 && errno == EBUSY) { /* Don't busywait */
|
||||
sleep(1);
|
||||
errno = EBUSY; /* In case sleep trashes it */
|
||||
@@ -320,19 +281,22 @@ static 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);
|
||||
node_updown[nodes[i].cn_nodeid] = is_listening(nodes[i].cn_nodeid);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get a list of active cluster members */
|
||||
static void get_members()
|
||||
{
|
||||
struct cl_cluster_nodelist nodelist;
|
||||
int retnodes;
|
||||
int status;
|
||||
|
||||
num_nodes = ioctl(cluster_sock, SIOCCLUSTER_GETMEMBERS, 0);
|
||||
num_nodes = cman_get_node_count(c_handle);
|
||||
if (num_nodes == -1) {
|
||||
log_error("Unable to get node count");
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Not enough room for new nodes list ? */
|
||||
if (num_nodes > count_nodes && nodes) {
|
||||
free(nodes);
|
||||
@@ -341,28 +305,19 @@ static void get_members()
|
||||
|
||||
if (nodes == NULL) {
|
||||
count_nodes = num_nodes + 10; /* Overallocate a little */
|
||||
nodes = malloc(count_nodes * sizeof(struct cl_cluster_node));
|
||||
nodes = malloc(count_nodes * sizeof(struct cman_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) {
|
||||
status = cman_get_nodes(c_handle, count_nodes, &retnodes, nodes);
|
||||
if (status < 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) *
|
||||
@@ -371,7 +326,6 @@ static void get_members()
|
||||
sizeof(int) * max(num_nodes, max_updown_nodes));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert a node name to a CSID */
|
||||
static int _csid_from_name(char *csid, char *name)
|
||||
@@ -379,8 +333,8 @@ static 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, CMAN_MAX_CSID_LEN);
|
||||
if (strcmp(name, nodes[i].cn_name) == 0) {
|
||||
memcpy(csid, &nodes[i].cn_nodeid, CMAN_MAX_CSID_LEN);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -393,8 +347,8 @@ static int _name_from_csid(char *csid, char *name)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_nodes; i++) {
|
||||
if (memcmp(csid, &nodes[i].node_id, CMAN_MAX_CSID_LEN) == 0) {
|
||||
strcpy(name, nodes[i].name);
|
||||
if (memcmp(csid, &nodes[i].cn_nodeid, CMAN_MAX_CSID_LEN) == 0) {
|
||||
strcpy(name, nodes[i].cn_name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -409,8 +363,8 @@ static 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);
|
||||
if (nodeid == nodes[i].cn_nodeid) {
|
||||
strcpy(name, nodes[i].cn_name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -431,7 +385,7 @@ static int nodeid_from_csid(char *csid)
|
||||
|
||||
static int _is_quorate()
|
||||
{
|
||||
return ioctl(cluster_sock, SIOCCLUSTER_ISQUORATE, 0);
|
||||
return cman_is_quorate(c_handle);
|
||||
}
|
||||
|
||||
static void sync_ast_routine(void *arg)
|
||||
|
||||
@@ -56,15 +56,19 @@ struct cluster_ops *init_gulm_cluster(void);
|
||||
#endif
|
||||
|
||||
#ifdef USE_CMAN
|
||||
# include "cnxman-socket.h"
|
||||
# include <netinet/in.h>
|
||||
# include "libcman.h"
|
||||
# define CMAN_MAX_CSID_LEN 4
|
||||
# ifndef MAX_CSID_LEN
|
||||
# define MAX_CSID_LEN CMAN_MAX_CSID_LEN
|
||||
# endif
|
||||
# undef MAX_CLUSTER_MEMBER_NAME_LEN
|
||||
# define MAX_CLUSTER_MEMBER_NAME_LEN CMAN_MAX_CLUSTER_MEMBER_NAME_LEN
|
||||
# define MAX_CLUSTER_MEMBER_NAME_LEN CMAN_MAX_NODENAME_LEN
|
||||
# define CMAN_MAX_CLUSTER_MESSAGE 1500
|
||||
# define CLUSTER_PORT_CLVMD 11
|
||||
struct cluster_ops *init_cman_cluster(void);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -247,7 +247,7 @@ int main(int argc, char *argv[])
|
||||
if ((clops = init_cman_cluster())) {
|
||||
max_csid_len = CMAN_MAX_CSID_LEN;
|
||||
max_cluster_message = CMAN_MAX_CLUSTER_MESSAGE;
|
||||
max_cluster_member_name_len = CMAN_MAX_CLUSTER_MEMBER_NAME_LEN;
|
||||
max_cluster_member_name_len = CMAN_MAX_NODENAME_LEN;
|
||||
syslog(LOG_NOTICE, "Cluster LVM daemon started - connected to CMAN");
|
||||
}
|
||||
#endif
|
||||
@@ -509,6 +509,7 @@ static void main_loop(int local_sock, int cmd_timeout)
|
||||
int quorate = clops->is_quorate();
|
||||
|
||||
/* Wait on the cluster FD and all local sockets/pipes */
|
||||
local_client_head.fd = clops->get_main_cluster_fd();
|
||||
FD_ZERO(&in);
|
||||
for (thisfd = &local_client_head; thisfd != NULL;
|
||||
thisfd = thisfd->next) {
|
||||
|
||||
@@ -303,6 +303,9 @@ int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
|
||||
}
|
||||
}
|
||||
|
||||
if (lock_flags & LCK_PARTIAL_MODE)
|
||||
init_partial(1);
|
||||
|
||||
switch (command) {
|
||||
case LCK_LV_EXCLUSIVE:
|
||||
status = do_activate_lv(resource, lock_flags, LKM_EXMODE);
|
||||
@@ -331,6 +334,9 @@ int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
|
||||
break;
|
||||
}
|
||||
|
||||
if (lock_flags & LCK_PARTIAL_MODE)
|
||||
init_partial(0);
|
||||
|
||||
/* clean the pool for another command */
|
||||
dm_pool_empty(cmd->mem);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
dm_register_for_event
|
||||
dm_unregister_for_event
|
||||
dm_get_registered_device
|
||||
dm_set_event_timeout
|
||||
dm_get_event_timeout
|
||||
dm_event_register
|
||||
dm_event_unregister
|
||||
dm_event_get_registered_device
|
||||
dm_event_set_timeout
|
||||
dm_event_get_timeout
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
interface = @interface@
|
||||
|
||||
SOURCES = libdevmapper-event.c \
|
||||
dmeventd.c
|
||||
@@ -27,11 +26,12 @@ else
|
||||
LIB_SHARED = libdevmapper-event.so
|
||||
endif
|
||||
|
||||
CLDFLAGS += -ldl -ldevmapper -lpthread
|
||||
|
||||
include ../make.tmpl
|
||||
|
||||
.PHONY: install_dynamic install_static
|
||||
CLDFLAGS += -ldl -ldevmapper -lpthread
|
||||
|
||||
.PHONY: install_dynamic install_static install_include \
|
||||
install_pkgconfig
|
||||
|
||||
INSTALL_TYPE = install_dynamic
|
||||
|
||||
@@ -39,18 +39,35 @@ ifeq ("@STATIC_LINK@", "yes")
|
||||
INSTALL_TYPE += install_static
|
||||
endif
|
||||
|
||||
install: $(INSTALL_TYPE)
|
||||
ifeq ("@PKGCONFIG@", "yes")
|
||||
INSTALL_TYPE += install_pkgconfig
|
||||
endif
|
||||
|
||||
install: $(INSTALL_TYPE) install_include
|
||||
|
||||
install_include:
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 444 libdevmapper-event.h \
|
||||
$(includedir)/libdevmapper-event.h
|
||||
|
||||
install_dynamic: libdevmapper-event.$(LIB_SUFFIX)
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
|
||||
$(libdir)/libdevmapper-event.$(LIB_SUFFIX).$(LIB_VERSION)
|
||||
$(LN_S) -f libdevmapper-event.$(LIB_SUFFIX).$(LIB_VERSION) \
|
||||
$(libdir)/libdevmapper-event.$(LIB_SUFFIX)
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 444 libdevmapper-event.h \
|
||||
$(includedir)/libdevmapper-event.h
|
||||
|
||||
install_pkgconfig:
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 444 libdevmapper-event.pc \
|
||||
$(usrlibdir)/pkgconfig/devmapper-event.pc
|
||||
|
||||
install_static: libdevmapper-event.a
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
|
||||
$(libdir)/libdevmapper-event.a.$(LIB_VERSION)
|
||||
$(LN_S) -f libdevmapper-event.a.$(LIB_VERSION) $(libdir)/libdevmapper-event.a
|
||||
|
||||
.PHONY: distclean_lib distclean
|
||||
|
||||
distclean_lib:
|
||||
$(RM) libdevmapper-event.pc
|
||||
|
||||
distclean: distclean_lib
|
||||
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
@@ -45,11 +44,6 @@
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
/* FIXME Use dm library */
|
||||
#define dbg_malloc(x...) malloc(x)
|
||||
#define dbg_strdup(x...) strdup(x)
|
||||
#define dbg_free(x...) free(x)
|
||||
|
||||
/* List (un)link macros. */
|
||||
#define LINK(x, head) list_add(head, &(x)->list)
|
||||
#define LINK_DSO(dso) LINK(dso, &dso_registry)
|
||||
@@ -132,7 +126,8 @@ struct thread_status {
|
||||
struct dso_data *dso_data;/* DSO this thread accesses. */
|
||||
|
||||
char *device_path; /* Mapped device path. */
|
||||
int event_nr; /* event number */
|
||||
uint32_t event_nr; /* event number */
|
||||
int processing; /* Set when event is being processed */
|
||||
enum dm_event_type events; /* bitfield for event filter. */
|
||||
enum dm_event_type current_events;/* bitfield for occured events. */
|
||||
enum dm_event_type processed_events;/* bitfield for processed events. */
|
||||
@@ -141,6 +136,7 @@ struct thread_status {
|
||||
struct list timeout_list;
|
||||
};
|
||||
static LIST_INIT(thread_registry);
|
||||
static LIST_INIT(thread_registry_unused);
|
||||
|
||||
static int timeout_running;
|
||||
static LIST_INIT(timeout_registry);
|
||||
@@ -151,12 +147,12 @@ static pthread_cond_t timeout_cond = PTHREAD_COND_INITIALIZER;
|
||||
static struct thread_status *alloc_thread_status(struct message_data *data,
|
||||
struct dso_data *dso_data)
|
||||
{
|
||||
struct thread_status *ret = (typeof(ret)) dbg_malloc(sizeof(*ret));
|
||||
struct thread_status *ret = (typeof(ret)) dm_malloc(sizeof(*ret));
|
||||
|
||||
if (ret) {
|
||||
if (!memset(ret, 0, sizeof(*ret)) ||
|
||||
!(ret->device_path = dbg_strdup(data->device_path))) {
|
||||
dbg_free(ret);
|
||||
!(ret->device_path = dm_strdup(data->device_path))) {
|
||||
dm_free(ret);
|
||||
ret = NULL;
|
||||
} else {
|
||||
ret->dso_data = dso_data;
|
||||
@@ -171,19 +167,19 @@ static struct thread_status *alloc_thread_status(struct message_data *data,
|
||||
|
||||
static void free_thread_status(struct thread_status *thread)
|
||||
{
|
||||
dbg_free(thread->device_path);
|
||||
dbg_free(thread);
|
||||
dm_free(thread->device_path);
|
||||
dm_free(thread);
|
||||
}
|
||||
|
||||
/* Allocate/free DSO data. */
|
||||
static struct dso_data *alloc_dso_data(struct message_data *data)
|
||||
{
|
||||
struct dso_data *ret = (typeof(ret)) dbg_malloc(sizeof(*ret));
|
||||
struct dso_data *ret = (typeof(ret)) dm_malloc(sizeof(*ret));
|
||||
|
||||
if (ret) {
|
||||
if (!memset(ret, 0, sizeof(*ret)) ||
|
||||
!(ret->dso_name = dbg_strdup(data->dso_name))) {
|
||||
dbg_free(ret);
|
||||
!(ret->dso_name = dm_strdup(data->dso_name))) {
|
||||
dm_free(ret);
|
||||
ret = NULL;
|
||||
}
|
||||
}
|
||||
@@ -193,8 +189,8 @@ static struct dso_data *alloc_dso_data(struct message_data *data)
|
||||
|
||||
static void free_dso_data(struct dso_data *data)
|
||||
{
|
||||
dbg_free(data->dso_name);
|
||||
dbg_free(data);
|
||||
dm_free(data->dso_name);
|
||||
dm_free(data);
|
||||
}
|
||||
|
||||
/* FIXME: Factor out. */
|
||||
@@ -220,11 +216,11 @@ static int fetch_string(char **ptr, char **src)
|
||||
if ((p = strchr(*src, delimiter)))
|
||||
*p = 0;
|
||||
|
||||
if ((*ptr = dbg_strdup(*src))) {
|
||||
if ((*ptr = dm_strdup(*src))) {
|
||||
if ((len = strlen(*ptr)))
|
||||
*src += len;
|
||||
else {
|
||||
dbg_free(*ptr);
|
||||
dm_free(*ptr);
|
||||
*ptr = NULL;
|
||||
}
|
||||
|
||||
@@ -242,10 +238,10 @@ static int fetch_string(char **ptr, char **src)
|
||||
static void free_message(struct message_data *message_data)
|
||||
{
|
||||
if (message_data->dso_name)
|
||||
dbg_free(message_data->dso_name);
|
||||
dm_free(message_data->dso_name);
|
||||
|
||||
if (message_data->device_path)
|
||||
dbg_free(message_data->device_path);
|
||||
dm_free(message_data->device_path);
|
||||
}
|
||||
|
||||
/* Parse a register message from the client. */
|
||||
@@ -268,12 +264,12 @@ static int parse_message(struct message_data *message_data)
|
||||
* Free string representaion of events.
|
||||
* Not needed an more.
|
||||
*/
|
||||
dbg_free(message_data->events.str);
|
||||
dm_free(message_data->events.str);
|
||||
message_data->events.field = i;
|
||||
}
|
||||
if (message_data->timeout.str) {
|
||||
uint32_t secs = atoi(message_data->timeout.str);
|
||||
dbg_free(message_data->timeout.str);
|
||||
dm_free(message_data->timeout.str);
|
||||
message_data->timeout.secs = secs ? secs :
|
||||
DM_EVENT_DEFAULT_TIMEOUT;
|
||||
}
|
||||
@@ -304,10 +300,10 @@ static int storepid(int lf)
|
||||
if ((len = snprintf(pid, sizeof(pid), "%u\n", getpid())) < 0)
|
||||
return 0;
|
||||
|
||||
if (len > sizeof(pid))
|
||||
len = sizeof(pid);
|
||||
if (len > (int) sizeof(pid))
|
||||
len = (int) sizeof(pid);
|
||||
|
||||
if (write(lf, pid, len) != len)
|
||||
if (write(lf, pid, (size_t) len) != len)
|
||||
return 0;
|
||||
|
||||
fsync(lf);
|
||||
@@ -315,19 +311,29 @@ static int storepid(int lf)
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* FIXME This is unreliable: should use DM_DEVICE_INFO ioctl instead. */
|
||||
/* Check, if a device exists. */
|
||||
static int device_exists(char *device)
|
||||
{
|
||||
struct stat st_buf;
|
||||
char path2[PATH_MAX];
|
||||
|
||||
return !stat(device, &st_buf) && S_ISBLK(st_buf.st_mode);
|
||||
if (!device)
|
||||
return 0;
|
||||
|
||||
if (device[0] == '/') /* absolute path */
|
||||
return !stat(device, &st_buf) && S_ISBLK(st_buf.st_mode);
|
||||
|
||||
if (PATH_MAX <= snprintf(path2, PATH_MAX, "%s/%s", dm_dir(), device))
|
||||
return 0;
|
||||
|
||||
return !stat(path2, &st_buf) && S_ISBLK(st_buf.st_mode);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find an existing thread for a device.
|
||||
*
|
||||
* Mutex must be hold when calling this.
|
||||
* Mutex must be held when calling this.
|
||||
*/
|
||||
static struct thread_status *lookup_thread_status(struct message_data *data)
|
||||
{
|
||||
@@ -578,6 +584,8 @@ static void monitor_unregister(void *arg)
|
||||
}
|
||||
|
||||
/* Device monitoring thread. */
|
||||
static void *monitor_thread(void *arg)
|
||||
__attribute((noreturn));
|
||||
static void *monitor_thread(void *arg)
|
||||
{
|
||||
struct thread_status *thread = arg;
|
||||
@@ -585,7 +593,7 @@ static void *monitor_thread(void *arg)
|
||||
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
|
||||
pthread_cleanup_push(monitor_unregister, thread);
|
||||
|
||||
/* Wait for do_process_reques() to finish its task. */
|
||||
/* Wait for do_process_request() to finish its task. */
|
||||
lock_mutex();
|
||||
unlock_mutex();
|
||||
|
||||
@@ -593,6 +601,11 @@ static void *monitor_thread(void *arg)
|
||||
while (1) {
|
||||
thread->current_events = 0;
|
||||
|
||||
/*
|
||||
* FIXME: if unrecoverable error (ENODEV) happens,
|
||||
* we loop indefinitely. event_wait should return
|
||||
* more than 0/1.
|
||||
*/
|
||||
if (!event_wait(thread))
|
||||
continue;
|
||||
|
||||
@@ -603,12 +616,22 @@ static void *monitor_thread(void *arg)
|
||||
* the device got registered for those events AND
|
||||
* those events haven't been processed yet, call
|
||||
* the DSO's process_event() handler.
|
||||
*
|
||||
* FIXME: when does processed_events get cleared? What if
|
||||
* the same type of event happens later... after the first
|
||||
* was handled properly?
|
||||
*/
|
||||
if (thread->events &
|
||||
thread->current_events &
|
||||
~thread->processed_events) {
|
||||
lock_mutex();
|
||||
thread->processing = 1;
|
||||
unlock_mutex();
|
||||
do_process_event(thread);
|
||||
thread->processed_events |= thread->current_events;
|
||||
lock_mutex();
|
||||
thread->processing = 0;
|
||||
unlock_mutex();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -689,41 +712,27 @@ static int lookup_symbols(void *dl, struct dso_data *data)
|
||||
"unregister_device");
|
||||
}
|
||||
|
||||
/* Create a DSO file name based on its name. */
|
||||
static char *create_dso_file_name(char *dso_name)
|
||||
{
|
||||
char *ret;
|
||||
static char prefix[] = "libdmeventd";
|
||||
static char suffix[] = ".so";
|
||||
|
||||
if ((ret = dbg_malloc(strlen(prefix) +
|
||||
strlen(dso_name) +
|
||||
strlen(suffix) + 1)))
|
||||
sprintf(ret, "%s%s%s", prefix, dso_name, suffix);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Load an application specific DSO. */
|
||||
static struct dso_data *load_dso(struct message_data *data)
|
||||
{
|
||||
void *dl;
|
||||
struct dso_data *ret = NULL;
|
||||
char *dso_file;
|
||||
|
||||
if (!(dso_file = create_dso_file_name(data->dso_name)))
|
||||
return NULL;
|
||||
|
||||
if (!(dl = dlopen(dso_file, RTLD_NOW))){
|
||||
if (!(dl = dlopen(data->dso_name, RTLD_NOW))){
|
||||
log_error("%s\n", dlerror());
|
||||
goto free_dso_file;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(ret = alloc_dso_data(data)))
|
||||
goto close;
|
||||
if (!(ret = alloc_dso_data(data))) {
|
||||
dlclose(dl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(lookup_symbols(dl, ret)))
|
||||
goto free_all;
|
||||
if (!(lookup_symbols(dl, ret))) {
|
||||
free_dso_data(ret);
|
||||
dlclose(dl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Keep handle to close the library once
|
||||
@@ -736,17 +745,6 @@ static struct dso_data *load_dso(struct message_data *data)
|
||||
LINK_DSO(ret);
|
||||
unlock_mutex();
|
||||
|
||||
goto free_dso_file;
|
||||
|
||||
free_all:
|
||||
free_dso_data(ret);
|
||||
|
||||
close:
|
||||
dlclose(dl);
|
||||
|
||||
free_dso_file:
|
||||
dbg_free(dso_file);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -875,27 +873,11 @@ static int unregister_for_event(struct message_data *message_data)
|
||||
* In case there's no events to monitor on this device ->
|
||||
* unlink and terminate its monitoring thread.
|
||||
*/
|
||||
if (!thread->events)
|
||||
UNLINK_THREAD(thread);
|
||||
|
||||
unlock_mutex();
|
||||
|
||||
if (!thread->events) {
|
||||
/* turn codes negative */
|
||||
if ((ret = -terminate_thread(thread)))
|
||||
stack;
|
||||
else {
|
||||
pthread_join(thread->thread, NULL);
|
||||
free_thread_status(thread);
|
||||
lib_put(thread->dso_data);
|
||||
|
||||
lock_mutex();
|
||||
if (list_empty(&thread_registry))
|
||||
exit_dm_lib();
|
||||
unlock_mutex();
|
||||
}
|
||||
UNLINK_THREAD(thread);
|
||||
LINK(thread, &thread_registry_unused);
|
||||
}
|
||||
|
||||
unlock_mutex();
|
||||
|
||||
out:
|
||||
return ret;
|
||||
@@ -1050,20 +1032,32 @@ static int open_fifos(struct dm_event_fifos *fifos)
|
||||
|
||||
/*
|
||||
* Read message from client making sure that data is available
|
||||
* and a complete message is read.
|
||||
* and a complete message is read. Must not block indefinitely.
|
||||
*/
|
||||
static int client_read(struct dm_event_fifos *fifos, struct dm_event_daemon_message *msg)
|
||||
{
|
||||
int bytes = 0, ret = 0;
|
||||
struct timeval t;
|
||||
unsigned bytes = 0;
|
||||
int ret = 0;
|
||||
fd_set fds;
|
||||
|
||||
errno = 0;
|
||||
while (bytes < sizeof(*msg) && errno != EOF) {
|
||||
do {
|
||||
/* Watch client read FIFO for input. */
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fifos->client, &fds);
|
||||
} while (select(fifos->client+1, &fds, NULL, NULL, NULL) != 1);
|
||||
/* Watch client read FIFO for input. */
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fifos->client, &fds);
|
||||
t.tv_sec = 1;
|
||||
t.tv_usec = 0;
|
||||
ret = select(fifos->client+1, &fds, NULL, NULL, &t);
|
||||
|
||||
if (!ret && !bytes) /* nothing to read */
|
||||
return 0;
|
||||
|
||||
if (!ret) /* trying to finish read */
|
||||
continue;
|
||||
|
||||
if (ret < 0) /* error */
|
||||
return 0;
|
||||
|
||||
ret = read(fifos->client, msg, sizeof(*msg) - bytes);
|
||||
bytes += ret > 0 ? ret : 0;
|
||||
@@ -1077,7 +1071,8 @@ static int client_read(struct dm_event_fifos *fifos, struct dm_event_daemon_mess
|
||||
*/
|
||||
static int client_write(struct dm_event_fifos *fifos, struct dm_event_daemon_message *msg)
|
||||
{
|
||||
int bytes = 0, ret = 0;
|
||||
unsigned bytes = 0;
|
||||
int ret = 0;
|
||||
fd_set fds;
|
||||
|
||||
errno = 0;
|
||||
@@ -1139,7 +1134,6 @@ static int do_process_request(struct dm_event_daemon_message *msg)
|
||||
stack;
|
||||
ret = -EINVAL;
|
||||
} else {
|
||||
log_print("%s: %u \"%s\"\n", __func__, msg->opcode.cmd, message_data.msg->msg);
|
||||
ret = handle_request(msg, &message_data);
|
||||
}
|
||||
|
||||
@@ -1155,20 +1149,56 @@ static void process_request(struct dm_event_fifos *fifos)
|
||||
|
||||
/* FIXME: better error handling */
|
||||
|
||||
/* Read the request from the client. */
|
||||
if (!memset(&msg, 0, sizeof(msg)) ||
|
||||
!client_read(fifos, &msg)) {
|
||||
stack;
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
|
||||
/*
|
||||
* Read the request from the client.
|
||||
* Of course, it's tough to tell what to do when
|
||||
* we use fucking retarded return codes like
|
||||
* 0 for error.
|
||||
*/
|
||||
if (!client_read(fifos, &msg))
|
||||
return;
|
||||
}
|
||||
|
||||
msg.opcode.status = do_process_request(&msg);
|
||||
|
||||
log_print("%s: status: %s\n", __func__, strerror(-msg.opcode.status));
|
||||
if (!client_write(fifos, &msg))
|
||||
stack;
|
||||
}
|
||||
|
||||
static void cleanup_unused_threads(void)
|
||||
{
|
||||
int ret;
|
||||
struct list *l;
|
||||
struct thread_status *thread;
|
||||
|
||||
lock_mutex();
|
||||
while ((l = list_first(&thread_registry_unused))) {
|
||||
thread = list_item(l, struct thread_status);
|
||||
if (thread->processing) {
|
||||
goto out; /* cleanup on the next round */
|
||||
}
|
||||
list_del(l);
|
||||
|
||||
if (!thread->events) {
|
||||
/* turn codes negative -- should we be returning this? */
|
||||
if ((ret = -terminate_thread(thread)))
|
||||
stack;
|
||||
else {
|
||||
pthread_join(thread->thread, NULL);
|
||||
lib_put(thread->dso_data);
|
||||
free_thread_status(thread);
|
||||
}
|
||||
} else {
|
||||
log_error("thread can't be on unused list unless !thread->events");
|
||||
LINK_THREAD(thread);
|
||||
}
|
||||
|
||||
}
|
||||
out:
|
||||
unlock_mutex();
|
||||
}
|
||||
|
||||
static void sig_alarm(int signum)
|
||||
{
|
||||
pthread_testcancel();
|
||||
@@ -1261,10 +1291,27 @@ void dmeventd(void)
|
||||
/*
|
||||
* We exit when there are no more devices to watch.
|
||||
* That is, when the last unregister happens.
|
||||
*
|
||||
* We must be careful though. One of our threads which is
|
||||
* watching a device may receive an event and:
|
||||
* 1) Alter the device and unregister it
|
||||
* or
|
||||
* 2) Alter the device, unregister, [alter again,] and reregister
|
||||
*
|
||||
* We must be capable of answering a request to unregister
|
||||
* that comes from the very thread that must be unregistered.
|
||||
* Additionally, if that thread unregisters itself and it was the
|
||||
* only thread being monitored, we must also handle the case where
|
||||
* that thread may perform a register before exiting. (In other
|
||||
* words, we can not simply exit if all threads have been unregistered
|
||||
* unless all threads are done processing.
|
||||
*/
|
||||
do {
|
||||
process_request(&fifos);
|
||||
} while(!list_empty(&thread_registry));
|
||||
cleanup_unused_threads();
|
||||
} while(!list_empty(&thread_registry) || !list_empty(&thread_registry_unused));
|
||||
|
||||
exit_dm_lib();
|
||||
|
||||
#ifdef MCL_CURRENT
|
||||
munlockall();
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#define EXIT_FIFO_FAILURE 5
|
||||
#define EXIT_CHDIR_FAILURE 6
|
||||
|
||||
void dmeventd(void);
|
||||
void dmeventd(void)
|
||||
__attribute((noreturn));
|
||||
|
||||
#endif /* __DMEVENTD_DOT_H__ */
|
||||
|
||||
@@ -44,7 +44,7 @@ static char *fetch_string(char **src)
|
||||
if ((p = strchr(*src, delimiter)))
|
||||
*p = 0;
|
||||
|
||||
if ((ret = strdup(*src)))
|
||||
if ((ret = dm_strdup(*src)))
|
||||
*src += strlen(ret) + 1;
|
||||
|
||||
if (p)
|
||||
@@ -69,52 +69,80 @@ static int parse_message(struct dm_event_daemon_message *msg, char **dso_name,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Read message from daemon. */
|
||||
/*
|
||||
* daemon_read
|
||||
* @fifos
|
||||
* @msg
|
||||
*
|
||||
* Read message from daemon.
|
||||
*
|
||||
* Returns: 0 on failure, 1 on success
|
||||
*/
|
||||
static int daemon_read(struct dm_event_fifos *fifos, struct dm_event_daemon_message *msg)
|
||||
{
|
||||
int bytes = 0, ret = 0;
|
||||
unsigned bytes = 0;
|
||||
int ret = 0;
|
||||
fd_set fds;
|
||||
|
||||
memset(msg, 0, sizeof(*msg));
|
||||
errno = 0;
|
||||
/* FIXME Fix error handling. Check 'ret' before errno. EINTR? EAGAIN? */
|
||||
/* FIXME errno != EOF? RTFM! */
|
||||
while (bytes < sizeof(*msg) && errno != EOF) {
|
||||
while (bytes < sizeof(*msg)) {
|
||||
do {
|
||||
/* Watch daemon read FIFO for input. */
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fifos->server, &fds);
|
||||
/* FIXME Check for errors e.g. EBADF */
|
||||
} while (select(fifos->server+1, &fds, NULL, NULL, NULL) != 1);
|
||||
ret = select(fifos->server+1, &fds, NULL, NULL, NULL);
|
||||
if (ret < 0 && errno != EINTR) {
|
||||
/* FIXME Log error */
|
||||
return 0;
|
||||
}
|
||||
} while (ret < 1);
|
||||
|
||||
ret = read(fifos->server, msg, sizeof(*msg) - bytes);
|
||||
bytes += ret > 0 ? ret : 0;
|
||||
if (ret < 0) {
|
||||
if ((errno == EINTR) || (errno == EAGAIN))
|
||||
continue;
|
||||
else {
|
||||
/* FIXME Log error */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bytes += ret;
|
||||
}
|
||||
|
||||
// log_print("%s: \"%s\"\n", __func__, msg->msg);
|
||||
return bytes == sizeof(*msg);
|
||||
}
|
||||
|
||||
/* Write message to daemon. */
|
||||
static int daemon_write(struct dm_event_fifos *fifos, struct dm_event_daemon_message *msg)
|
||||
{
|
||||
int bytes = 0, ret = 0;
|
||||
unsigned bytes = 0;
|
||||
int ret = 0;
|
||||
fd_set fds;
|
||||
|
||||
|
||||
// log_print("%s: \"%s\"\n", __func__, msg->msg);
|
||||
errno = 0;
|
||||
/* FIXME Fix error handling. Check 'ret' before errno. EINTR? EAGAIN? */
|
||||
while (bytes < sizeof(*msg) && errno != EIO) {
|
||||
while (bytes < sizeof(*msg)) {
|
||||
do {
|
||||
/* Watch daemon write FIFO to be ready for output. */
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fifos->client, &fds);
|
||||
/* FIXME Check for errors e.g. EBADF */
|
||||
} while (select(fifos->client +1, NULL, &fds, NULL, NULL) != 1);
|
||||
ret = select(fifos->client +1, NULL, &fds, NULL, NULL);
|
||||
if ((ret < 0) && (errno != EINTR)) {
|
||||
/* FIXME Log error */
|
||||
return 0;
|
||||
}
|
||||
} while (ret < 1);
|
||||
|
||||
ret = write(fifos->client, msg, sizeof(*msg) - bytes);
|
||||
bytes += ret > 0 ? ret : 0;
|
||||
if (ret < 0) {
|
||||
if ((errno == EINTR) || (errno == EAGAIN))
|
||||
continue;
|
||||
else {
|
||||
/* fixme: log error */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bytes += ret;
|
||||
}
|
||||
|
||||
return bytes == sizeof(*msg);
|
||||
@@ -132,11 +160,11 @@ static int daemon_talk(struct dm_event_fifos *fifos, struct dm_event_daemon_mess
|
||||
*/
|
||||
msg->opcode.cmd = cmd;
|
||||
|
||||
if (sizeof(msg->msg) <= snprintf(msg->msg, sizeof(msg->msg),
|
||||
"%s %s %u %"PRIu32,
|
||||
dso_name ? dso_name : "",
|
||||
device ? device : "",
|
||||
events, timeout)) {
|
||||
if (sizeof(msg->msg) <= (unsigned) snprintf(msg->msg, sizeof(msg->msg),
|
||||
"%s %s %u %"PRIu32,
|
||||
dso_name ? dso_name : "",
|
||||
device ? device : "",
|
||||
events, timeout)) {
|
||||
stack;
|
||||
return -ENAMETOOLONG;
|
||||
}
|
||||
@@ -178,8 +206,8 @@ static void daemon_running_signal_handler(int sig)
|
||||
static int start_daemon(void)
|
||||
{
|
||||
int pid, ret=0;
|
||||
int old_mask;
|
||||
void *old_hand;
|
||||
sigset_t set, oset;
|
||||
|
||||
/* Must be able to acquire signal */
|
||||
old_hand = signal(SIGUSR1, &daemon_running_signal_handler);
|
||||
@@ -188,12 +216,11 @@ static int start_daemon(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef linux
|
||||
/* FIXME Deprecated. Try posix sigprocmask instead. */
|
||||
old_mask = siggetmask();
|
||||
old_mask &= ~sigmask(SIGUSR1);
|
||||
old_mask = sigsetmask(old_mask);
|
||||
#endif
|
||||
if (sigemptyset(&set) || sigaddset(&set, SIGUSR1)) {
|
||||
log_error("Unable to fill signal set.");
|
||||
} else if (sigprocmask(SIG_UNBLOCK, &set, &oset)) {
|
||||
log_error("Can't unblock the potentially blocked signal SIGUSR1");
|
||||
}
|
||||
|
||||
pid = fork();
|
||||
|
||||
@@ -207,7 +234,6 @@ static int start_daemon(void)
|
||||
sleep(1);
|
||||
|
||||
if (daemon_running) {
|
||||
log_print("dmeventd started.\n");
|
||||
ret = 1;
|
||||
} else {
|
||||
switch (WEXITSTATUS(status)) {
|
||||
@@ -225,6 +251,13 @@ static int start_daemon(void)
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Sometimes, a single process may perform multiple calls
|
||||
* that result in a daemon starting and exiting. If we
|
||||
* don't reset this, the second (or greater) time the daemon
|
||||
* is started will cause this logic not to work.
|
||||
*/
|
||||
daemon_running = 0;
|
||||
} else {
|
||||
signal(SIGUSR1, SIG_IGN); /* don't care about error */
|
||||
|
||||
@@ -238,9 +271,11 @@ static int start_daemon(void)
|
||||
/* FIXME What if old_hand is SIG_ERR? */
|
||||
if (signal(SIGUSR1, old_hand) == SIG_ERR)
|
||||
log_error("Unable to reset signal handler.");
|
||||
sigsetmask(old_mask);
|
||||
|
||||
return ret;
|
||||
if (sigprocmask(SIG_SETMASK, &oset, NULL))
|
||||
log_error("Unable to reset signal mask.");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Initialize client. */
|
||||
@@ -251,15 +286,15 @@ static int init_client(struct dm_event_fifos *fifos)
|
||||
|
||||
/* init fifos */
|
||||
memset(fifos, 0, sizeof(*fifos));
|
||||
fifos->client_path = DM_EVENT_FIFO_CLIENT;
|
||||
fifos->server_path = DM_EVENT_FIFO_SERVER;
|
||||
fifos->client_path = DM_EVENT_FIFO_CLIENT;
|
||||
fifos->server_path = DM_EVENT_FIFO_SERVER;
|
||||
|
||||
/* FIXME The server should be responsible for these, not the client. */
|
||||
/* Create fifos */
|
||||
if (((mkfifo(fifos->client_path, 0600) == -1) && errno != EEXIST) ||
|
||||
((mkfifo(fifos->server_path, 0600) == -1) && errno != EEXIST)) {
|
||||
log_error("%s: Failed to create a fifo.\n", __func__);
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* FIXME Warn/abort if perms are wrong - not something to fix silently. */
|
||||
@@ -296,11 +331,11 @@ static int init_client(struct dm_event_fifos *fifos)
|
||||
}
|
||||
|
||||
/* Anyone listening? If not, errno will be ENXIO */
|
||||
if ((fifos->client = open(fifos->client_path,
|
||||
while ((fifos->client = open(fifos->client_path,
|
||||
O_WRONLY | O_NONBLOCK)) < 0) {
|
||||
if (errno != ENXIO) {
|
||||
log_error("%s: open client fifo %s\n",
|
||||
__func__, fifos->client_path);
|
||||
log_error("%s: Can't open client fifo %s: %s\n",
|
||||
__func__, fifos->client_path, strerror(errno));
|
||||
close(fifos->server);
|
||||
stack;
|
||||
return 0;
|
||||
@@ -311,17 +346,6 @@ static int init_client(struct dm_event_fifos *fifos)
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* FIXME Unnecessary if daemon was started before calling this */
|
||||
/* Daemon is started, retry the open */
|
||||
fifos->client = open(fifos->client_path, O_WRONLY | O_NONBLOCK);
|
||||
if (fifos->client < 0) {
|
||||
log_error("%s: open client fifo %s\n",
|
||||
__func__, fifos->client_path);
|
||||
close(fifos->server);
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -330,7 +354,7 @@ static int init_client(struct dm_event_fifos *fifos)
|
||||
static void dtr_client(struct dm_event_fifos *fifos)
|
||||
{
|
||||
if (flock(fifos->server, LOCK_UN))
|
||||
log_error("flock unlock %s\n", fifos->server_path);
|
||||
log_error("flock unlock %s\n", fifos->server_path);
|
||||
|
||||
close(fifos->client);
|
||||
close(fifos->server);
|
||||
@@ -363,12 +387,13 @@ static int do_event(int cmd, struct dm_event_daemon_message *msg,
|
||||
struct dm_event_fifos fifos;
|
||||
|
||||
/* FIXME Start the daemon here if it's not running e.g. exclusive lock file */
|
||||
|
||||
/* FIXME Move this to separate 'dm_event_register_handler' - if no daemon here, fail */
|
||||
if (!init_client(&fifos)) {
|
||||
stack;
|
||||
return -ESRCH;
|
||||
}
|
||||
|
||||
/* FIXME Use separate 'dm_event_register_handler' function to pass in dso? */
|
||||
ret = daemon_talk(&fifos, msg, cmd, dso_name, device, events, timeout);
|
||||
|
||||
/* what is the opposite of init? */
|
||||
@@ -377,29 +402,49 @@ static int do_event(int cmd, struct dm_event_daemon_message *msg,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* FIXME remove dso_name - use handle instead */
|
||||
/* FIXME Use uuid not path! */
|
||||
/* External library interface. */
|
||||
int dm_event_register(char *dso_name, char *device_path,
|
||||
enum dm_event_type events)
|
||||
enum dm_event_type events)
|
||||
{
|
||||
int ret;
|
||||
struct dm_event_daemon_message msg;
|
||||
|
||||
if (!device_exists(device_path))
|
||||
return -ENODEV;
|
||||
if (!device_exists(device_path)) {
|
||||
log_error("%s: device not found", device_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return do_event(DM_EVENT_CMD_REGISTER_FOR_EVENT, &msg,
|
||||
dso_name, device_path, events, 0);
|
||||
if ((ret = do_event(DM_EVENT_CMD_REGISTER_FOR_EVENT, &msg,
|
||||
dso_name, device_path, events, 0)) < 0) {
|
||||
log_error("%s: event registration failed: %s", device_path,
|
||||
strerror(-ret));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int dm_event_unregister(char *dso_name, char *device_path,
|
||||
enum dm_event_type events)
|
||||
enum dm_event_type events)
|
||||
{
|
||||
int ret;
|
||||
struct dm_event_daemon_message msg;
|
||||
|
||||
if (!device_exists(device_path))
|
||||
return -ENODEV;
|
||||
if (!device_exists(device_path)) {
|
||||
log_error("%s: device not found", device_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return do_event(DM_EVENT_CMD_UNREGISTER_FOR_EVENT, &msg,
|
||||
dso_name, device_path, events, 0);
|
||||
if ((ret = do_event(DM_EVENT_CMD_UNREGISTER_FOR_EVENT, &msg,
|
||||
dso_name, device_path, events, 0)) < 0) {
|
||||
log_error("%s: event deregistration failed: %s", device_path,
|
||||
strerror(-ret));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int dm_event_get_registered_device(char **dso_name, char **device_path,
|
||||
@@ -417,9 +462,9 @@ int dm_event_get_registered_device(char **dso_name, char **device_path,
|
||||
|
||||
if (next){
|
||||
if (*dso_name)
|
||||
free(*dso_name);
|
||||
dm_free(*dso_name);
|
||||
if (*device_path)
|
||||
free(*device_path);
|
||||
dm_free(*device_path);
|
||||
*dso_name = dso_name_arg;
|
||||
*device_path = device_path_arg;
|
||||
} else {
|
||||
|
||||
@@ -82,6 +82,15 @@ enum dm_event_type {
|
||||
DM_EVENT_PATH_ERROR | DM_EVENT_ADAPTOR_ERROR)
|
||||
|
||||
/* Prototypes for event lib interface. */
|
||||
|
||||
/* FIXME Replace device with standard name/uuid/devno choice */
|
||||
/* Interface changes:
|
||||
First register a handler, passing in a unique ref for the device. */
|
||||
// int dm_event_register_handler(const char *dso_name, const char *device);
|
||||
// int dm_event_register(const char *dso_name, const char *name, const char *uuid, uint32_t major, uint32_t minor, enum dm_event_type events);
|
||||
/* Or (better?) add to task structure and use existing functions - run a task to register/unregister events - we may need to run task withe that with the new event mechanism anyway, then the dso calls just hook in.
|
||||
*/
|
||||
|
||||
/* FIXME Missing consts? */
|
||||
int dm_event_register(char *dso_name, char *device, enum dm_event_type events);
|
||||
int dm_event_unregister(char *dso_name, char *device,
|
||||
|
||||
12
daemons/dmeventd/libdevmapper-event.pc.in
Normal file
12
daemons/dmeventd/libdevmapper-event.pc.in
Normal file
@@ -0,0 +1,12 @@
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: devmapper-event
|
||||
Description: device-mapper event library
|
||||
Version: @DM_LIB_VERSION@
|
||||
Requires: devmapper
|
||||
Cflags: -I${includedir}
|
||||
Libs: -L${libdir} -ldevmapper-event
|
||||
Libs.private: -lpthread -ldl
|
||||
22
daemons/dmeventd/plugins/Makefile.in
Normal file
22
daemons/dmeventd/plugins/Makefile.in
Normal file
@@ -0,0 +1,22 @@
|
||||
#
|
||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
# Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of the LVM2.
|
||||
#
|
||||
# This 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@
|
||||
|
||||
SUBDIRS += mirror
|
||||
|
||||
include $(top_srcdir)/make.tmpl
|
||||
|
||||
3
daemons/dmeventd/plugins/mirror/.exported_symbols
Normal file
3
daemons/dmeventd/plugins/mirror/.exported_symbols
Normal file
@@ -0,0 +1,3 @@
|
||||
process_event
|
||||
register_device
|
||||
unregister_device
|
||||
36
daemons/dmeventd/plugins/mirror/Makefile.in
Normal file
36
daemons/dmeventd/plugins/mirror/Makefile.in
Normal file
@@ -0,0 +1,36 @@
|
||||
#
|
||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
# Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of the LVM2.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
INCLUDES += -I${top_srcdir}/tools
|
||||
CLDFLAGS += -L${top_srcdir}/tools -ldevmapper -llvm2cmd
|
||||
|
||||
SOURCES = dmeventd_mirror.c
|
||||
|
||||
ifeq ("@LIB_SUFFIX@","dylib")
|
||||
LIB_SHARED = libdevmapper-event-lvm2mirror.dylib
|
||||
else
|
||||
LIB_SHARED = libdevmapper-event-lvm2mirror.so
|
||||
endif
|
||||
|
||||
include $(top_srcdir)/make.tmpl
|
||||
|
||||
install: libdevmapper-event-lvm2mirror.$(LIB_SUFFIX)
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
|
||||
$(libdir)/$<.$(LIB_VERSION)
|
||||
$(LN_S) -f $<.$(LIB_VERSION) $(libdir)/$<
|
||||
|
||||
246
daemons/dmeventd/plugins/mirror/dmeventd_mirror.c
Normal file
246
daemons/dmeventd/plugins/mirror/dmeventd_mirror.c
Normal file
@@ -0,0 +1,246 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "libdevmapper.h"
|
||||
#include "libdevmapper-event.h"
|
||||
#include "lvm2cmd.h"
|
||||
#include "lvm-string.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <syslog.h> /* FIXME Replace syslog with multilog */
|
||||
|
||||
#define ME_IGNORE 0
|
||||
#define ME_INSYNC 1
|
||||
#define ME_FAILURE 2
|
||||
|
||||
/* FIXME: We may need to lock around operations to these */
|
||||
static int register_count = 0;
|
||||
static struct dm_pool *mem_pool = NULL;
|
||||
|
||||
static int _get_mirror_event(char *params)
|
||||
{
|
||||
int i, rtn = ME_INSYNC;
|
||||
int max_args = 30; /* should support at least 8-way mirrors */
|
||||
char *args[max_args];
|
||||
char *dev_status_str;
|
||||
char *log_status_str;
|
||||
char *sync_str;
|
||||
char *p;
|
||||
int log_argc, num_devs, num_failures=0;
|
||||
|
||||
if (max_args <= split_words(params, max_args, args)) {
|
||||
syslog(LOG_ERR, "Unable to split mirror parameters: Arg list too long");
|
||||
return -E2BIG;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unused: 0 409600 mirror
|
||||
* Used : 2 253:4 253:5 400/400 1 AA 3 cluster 253:3 A
|
||||
*/
|
||||
num_devs = atoi(args[0]);
|
||||
dev_status_str = args[3 + num_devs];
|
||||
log_argc = atoi(args[4 + num_devs]);
|
||||
log_status_str = args[4 + num_devs + log_argc];
|
||||
sync_str = args[1 + num_devs];
|
||||
|
||||
/* Check for bad mirror devices */
|
||||
for (i = 0; i < num_devs; i++) {
|
||||
if (dev_status_str[i] == 'D') {
|
||||
syslog(LOG_ERR, "Mirror device, %s, has failed.\n", args[i+1]);
|
||||
num_failures++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for bad log device */
|
||||
if (log_status_str[0] == 'D') {
|
||||
syslog(LOG_ERR, "Log device, %s, has failed.\n",
|
||||
args[3 + num_devs + log_argc]);
|
||||
num_failures++;
|
||||
}
|
||||
|
||||
if (num_failures) {
|
||||
rtn = ME_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
p = strstr(sync_str, "/");
|
||||
if (p) {
|
||||
p[0] = '\0';
|
||||
if (strcmp(sync_str, p+1))
|
||||
rtn = ME_IGNORE;
|
||||
p[0] = '/';
|
||||
} else {
|
||||
/*
|
||||
* How the hell did we get this?
|
||||
* Might mean all our parameters are screwed.
|
||||
*/
|
||||
syslog(LOG_ERR, "Unable to parse sync string.");
|
||||
rtn = ME_IGNORE;
|
||||
}
|
||||
out:
|
||||
return rtn;
|
||||
}
|
||||
|
||||
static void _temporary_log_fn(int level, const char *file, int line, const char *format)
|
||||
{
|
||||
return;
|
||||
syslog(LOG_DEBUG, "%s", format);
|
||||
}
|
||||
|
||||
static int _remove_failed_devices(const char *device)
|
||||
{
|
||||
int r;
|
||||
void *handle;
|
||||
int cmd_size = 256; /* FIXME Use system restriction */
|
||||
char cmd_str[cmd_size];
|
||||
char *vg = NULL, *lv = NULL, *layer = NULL;
|
||||
|
||||
if (strlen(device) > 200)
|
||||
return -ENAMETOOLONG;
|
||||
|
||||
if (!split_dm_name(mem_pool, device, &vg, &lv, &layer)) {
|
||||
syslog(LOG_ERR, "Unable to determine VG name from %s",
|
||||
device);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* FIXME Is any sanity-checking required on %s? */
|
||||
if (cmd_size <= snprintf(cmd_str, cmd_size, "vgreduce --removemissing %s", vg)) {
|
||||
/* this error should be caught above, but doesn't hurt to check again */
|
||||
syslog(LOG_ERR, "Unable to form LVM command: Device name too long");
|
||||
dm_pool_empty(mem_pool); /* FIXME: not safe with multiple threads */
|
||||
return -ENAMETOOLONG;
|
||||
}
|
||||
|
||||
lvm2_log_fn(_temporary_log_fn);
|
||||
handle = lvm2_init();
|
||||
lvm2_log_level(handle, 1);
|
||||
r = lvm2_run(handle, cmd_str);
|
||||
|
||||
dm_pool_empty(mem_pool); /* FIXME: not safe with multiple threads */
|
||||
return (r == 1)? 0: -1;
|
||||
}
|
||||
|
||||
void process_event(const char *device, enum dm_event_type event)
|
||||
{
|
||||
struct dm_task *dmt;
|
||||
void *next = NULL;
|
||||
uint64_t start, length;
|
||||
char *target_type = NULL;
|
||||
char *params;
|
||||
|
||||
/* FIXME Move inside libdevmapper */
|
||||
if (!(dmt = dm_task_create(DM_DEVICE_STATUS))) {
|
||||
syslog(LOG_ERR, "Unable to create dm_task.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!dm_task_set_name(dmt, device)) {
|
||||
syslog(LOG_ERR, "Unable to set device name.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!dm_task_run(dmt)) {
|
||||
syslog(LOG_ERR, "Unable to run task.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
do {
|
||||
next = dm_get_next_target(dmt, next, &start, &length,
|
||||
&target_type, ¶ms);
|
||||
|
||||
if (strcmp(target_type, "mirror")) {
|
||||
syslog(LOG_INFO, "%s has unmirrored portion.\n", device);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(_get_mirror_event(params)) {
|
||||
case ME_INSYNC:
|
||||
/* FIXME: all we really know is that this
|
||||
_part_ of the device is in sync
|
||||
Also, this is not an error
|
||||
*/
|
||||
syslog(LOG_NOTICE, "%s is now in-sync\n", device);
|
||||
break;
|
||||
case ME_FAILURE:
|
||||
syslog(LOG_ERR, "Device failure in %s\n", device);
|
||||
if (_remove_failed_devices(device))
|
||||
syslog(LOG_ERR, "Failed to remove faulty devices in %s\n",
|
||||
device);
|
||||
/* Should check before warning user that device is now linear
|
||||
else
|
||||
syslog(LOG_NOTICE, "%s is now a linear device.\n",
|
||||
device);
|
||||
*/
|
||||
break;
|
||||
case ME_IGNORE:
|
||||
break;
|
||||
default:
|
||||
syslog(LOG_INFO, "Unknown event received.\n");
|
||||
}
|
||||
} while (next);
|
||||
|
||||
fail:
|
||||
if (dmt)
|
||||
dm_task_destroy(dmt);
|
||||
}
|
||||
|
||||
int register_device(const char *device)
|
||||
{
|
||||
syslog(LOG_INFO, "Monitoring %s for events\n", device);
|
||||
|
||||
/*
|
||||
* Need some space for allocations. 1024 should be more
|
||||
* than enough for what we need (device mapper name splitting)
|
||||
*/
|
||||
if (!mem_pool)
|
||||
mem_pool = dm_pool_create("mirror_dso", 1024);
|
||||
|
||||
if (!mem_pool)
|
||||
return 0;
|
||||
|
||||
register_count++;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int unregister_device(const char *device)
|
||||
{
|
||||
syslog(LOG_INFO, "Stopped monitoring %s for events\n", device);
|
||||
|
||||
if (!(--register_count)) {
|
||||
dm_pool_destroy(mem_pool);
|
||||
mem_pool = NULL;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Overrides for Emacs so that we follow Linus's tabbing style.
|
||||
* Emacs will notice this stuff at the end of the file and automatically
|
||||
* adjust the settings for this buffer only. This must remain at the end
|
||||
* of the file.
|
||||
* ---------------------------------------------------------------------------
|
||||
* Local variables:
|
||||
* c-file-style: "linux"
|
||||
* End:
|
||||
*/
|
||||
22
dmeventd/Makefile.in
Normal file
22
dmeventd/Makefile.in
Normal file
@@ -0,0 +1,22 @@
|
||||
#
|
||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
# Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of the LVM2.
|
||||
#
|
||||
# This 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@
|
||||
|
||||
SUBDIRS += mirror
|
||||
|
||||
include $(top_srcdir)/make.tmpl
|
||||
|
||||
3
dmeventd/mirror/.exported_symbols
Normal file
3
dmeventd/mirror/.exported_symbols
Normal file
@@ -0,0 +1,3 @@
|
||||
process_event
|
||||
register_device
|
||||
unregister_device
|
||||
36
dmeventd/mirror/Makefile.in
Normal file
36
dmeventd/mirror/Makefile.in
Normal file
@@ -0,0 +1,36 @@
|
||||
#
|
||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
# Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of the LVM2.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
INCLUDES += -I${top_srcdir}/tools
|
||||
CLDFLAGS += -L${top_srcdir}/tools -ldevmapper -llvm2cmd
|
||||
|
||||
SOURCES = dmeventd_mirror.c
|
||||
|
||||
ifeq ("@LIB_SUFFIX@","dylib")
|
||||
LIB_SHARED = libdevmapper-event-lvm2mirror.dylib
|
||||
else
|
||||
LIB_SHARED = libdevmapper-event-lvm2mirror.so
|
||||
endif
|
||||
|
||||
include $(top_srcdir)/make.tmpl
|
||||
|
||||
install: libdevmapper-event-lvm2mirror.$(LIB_SUFFIX)
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
|
||||
$(libdir)/$<.$(LIB_VERSION)
|
||||
$(LN_S) -f $<.$(LIB_VERSION) $(libdir)/$<
|
||||
|
||||
246
dmeventd/mirror/dmeventd_mirror.c
Normal file
246
dmeventd/mirror/dmeventd_mirror.c
Normal file
@@ -0,0 +1,246 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "libdevmapper.h"
|
||||
#include "libdevmapper-event.h"
|
||||
#include "lvm2cmd.h"
|
||||
#include "lvm-string.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <syslog.h> /* FIXME Replace syslog with multilog */
|
||||
|
||||
#define ME_IGNORE 0
|
||||
#define ME_INSYNC 1
|
||||
#define ME_FAILURE 2
|
||||
|
||||
/* FIXME: We may need to lock around operations to these */
|
||||
static int register_count = 0;
|
||||
static struct dm_pool *mem_pool = NULL;
|
||||
|
||||
static int _get_mirror_event(char *params)
|
||||
{
|
||||
int i, rtn = ME_INSYNC;
|
||||
int max_args = 30; /* should support at least 8-way mirrors */
|
||||
char *args[max_args];
|
||||
char *dev_status_str;
|
||||
char *log_status_str;
|
||||
char *sync_str;
|
||||
char *p;
|
||||
int log_argc, num_devs, num_failures=0;
|
||||
|
||||
if (max_args <= split_words(params, max_args, args)) {
|
||||
syslog(LOG_ERR, "Unable to split mirror parameters: Arg list too long");
|
||||
return -E2BIG;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unused: 0 409600 mirror
|
||||
* Used : 2 253:4 253:5 400/400 1 AA 3 cluster 253:3 A
|
||||
*/
|
||||
num_devs = atoi(args[0]);
|
||||
dev_status_str = args[3 + num_devs];
|
||||
log_argc = atoi(args[4 + num_devs]);
|
||||
log_status_str = args[4 + num_devs + log_argc];
|
||||
sync_str = args[1 + num_devs];
|
||||
|
||||
/* Check for bad mirror devices */
|
||||
for (i = 0; i < num_devs; i++) {
|
||||
if (dev_status_str[i] == 'D') {
|
||||
syslog(LOG_ERR, "Mirror device, %s, has failed.\n", args[i+1]);
|
||||
num_failures++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for bad log device */
|
||||
if (log_status_str[0] == 'D') {
|
||||
syslog(LOG_ERR, "Log device, %s, has failed.\n",
|
||||
args[3 + num_devs + log_argc]);
|
||||
num_failures++;
|
||||
}
|
||||
|
||||
if (num_failures) {
|
||||
rtn = ME_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
p = strstr(sync_str, "/");
|
||||
if (p) {
|
||||
p[0] = '\0';
|
||||
if (strcmp(sync_str, p+1))
|
||||
rtn = ME_IGNORE;
|
||||
p[0] = '/';
|
||||
} else {
|
||||
/*
|
||||
* How the hell did we get this?
|
||||
* Might mean all our parameters are screwed.
|
||||
*/
|
||||
syslog(LOG_ERR, "Unable to parse sync string.");
|
||||
rtn = ME_IGNORE;
|
||||
}
|
||||
out:
|
||||
return rtn;
|
||||
}
|
||||
|
||||
static void _temporary_log_fn(int level, const char *file, int line, const char *format)
|
||||
{
|
||||
return;
|
||||
syslog(LOG_DEBUG, "%s", format);
|
||||
}
|
||||
|
||||
static int _remove_failed_devices(const char *device)
|
||||
{
|
||||
int r;
|
||||
void *handle;
|
||||
int cmd_size = 256; /* FIXME Use system restriction */
|
||||
char cmd_str[cmd_size];
|
||||
char *vg = NULL, *lv = NULL, *layer = NULL;
|
||||
|
||||
if (strlen(device) > 200)
|
||||
return -ENAMETOOLONG;
|
||||
|
||||
if (!split_dm_name(mem_pool, device, &vg, &lv, &layer)) {
|
||||
syslog(LOG_ERR, "Unable to determine VG name from %s",
|
||||
device);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* FIXME Is any sanity-checking required on %s? */
|
||||
if (cmd_size <= snprintf(cmd_str, cmd_size, "vgreduce --removemissing %s", vg)) {
|
||||
/* this error should be caught above, but doesn't hurt to check again */
|
||||
syslog(LOG_ERR, "Unable to form LVM command: Device name too long");
|
||||
dm_pool_empty(mem_pool); /* FIXME: not safe with multiple threads */
|
||||
return -ENAMETOOLONG;
|
||||
}
|
||||
|
||||
lvm2_log_fn(_temporary_log_fn);
|
||||
handle = lvm2_init();
|
||||
lvm2_log_level(handle, 1);
|
||||
r = lvm2_run(handle, cmd_str);
|
||||
|
||||
dm_pool_empty(mem_pool); /* FIXME: not safe with multiple threads */
|
||||
return (r == 1)? 0: -1;
|
||||
}
|
||||
|
||||
void process_event(const char *device, enum dm_event_type event)
|
||||
{
|
||||
struct dm_task *dmt;
|
||||
void *next = NULL;
|
||||
uint64_t start, length;
|
||||
char *target_type = NULL;
|
||||
char *params;
|
||||
|
||||
/* FIXME Move inside libdevmapper */
|
||||
if (!(dmt = dm_task_create(DM_DEVICE_STATUS))) {
|
||||
syslog(LOG_ERR, "Unable to create dm_task.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!dm_task_set_name(dmt, device)) {
|
||||
syslog(LOG_ERR, "Unable to set device name.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!dm_task_run(dmt)) {
|
||||
syslog(LOG_ERR, "Unable to run task.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
do {
|
||||
next = dm_get_next_target(dmt, next, &start, &length,
|
||||
&target_type, ¶ms);
|
||||
|
||||
if (strcmp(target_type, "mirror")) {
|
||||
syslog(LOG_INFO, "%s has unmirrored portion.\n", device);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(_get_mirror_event(params)) {
|
||||
case ME_INSYNC:
|
||||
/* FIXME: all we really know is that this
|
||||
_part_ of the device is in sync
|
||||
Also, this is not an error
|
||||
*/
|
||||
syslog(LOG_NOTICE, "%s is now in-sync\n", device);
|
||||
break;
|
||||
case ME_FAILURE:
|
||||
syslog(LOG_ERR, "Device failure in %s\n", device);
|
||||
if (_remove_failed_devices(device))
|
||||
syslog(LOG_ERR, "Failed to remove faulty devices in %s\n",
|
||||
device);
|
||||
/* Should check before warning user that device is now linear
|
||||
else
|
||||
syslog(LOG_NOTICE, "%s is now a linear device.\n",
|
||||
device);
|
||||
*/
|
||||
break;
|
||||
case ME_IGNORE:
|
||||
break;
|
||||
default:
|
||||
syslog(LOG_INFO, "Unknown event received.\n");
|
||||
}
|
||||
} while (next);
|
||||
|
||||
fail:
|
||||
if (dmt)
|
||||
dm_task_destroy(dmt);
|
||||
}
|
||||
|
||||
int register_device(const char *device)
|
||||
{
|
||||
syslog(LOG_INFO, "Monitoring %s for events\n", device);
|
||||
|
||||
/*
|
||||
* Need some space for allocations. 1024 should be more
|
||||
* than enough for what we need (device mapper name splitting)
|
||||
*/
|
||||
if (!mem_pool)
|
||||
mem_pool = dm_pool_create("mirror_dso", 1024);
|
||||
|
||||
if (!mem_pool)
|
||||
return 0;
|
||||
|
||||
register_count++;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int unregister_device(const char *device)
|
||||
{
|
||||
syslog(LOG_INFO, "Stopped monitoring %s for events\n", device);
|
||||
|
||||
if (!(--register_count)) {
|
||||
dm_pool_destroy(mem_pool);
|
||||
mem_pool = NULL;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Overrides for Emacs so that we follow Linus's tabbing style.
|
||||
* Emacs will notice this stuff at the end of the file and automatically
|
||||
* adjust the settings for this buffer only. This must remain at the end
|
||||
* of the file.
|
||||
* ---------------------------------------------------------------------------
|
||||
* Local variables:
|
||||
* c-file-style: "linux"
|
||||
* End:
|
||||
*/
|
||||
@@ -289,4 +289,9 @@ activation {
|
||||
# dirs = [ "/etc/lvm/metadata", "/mnt/disk2/lvm/metadata2" ]
|
||||
#}
|
||||
|
||||
# Event daemon
|
||||
#
|
||||
#dmeventd {
|
||||
# mirror_library = "libdevmapper-event-lvm2mirror.so"
|
||||
#}
|
||||
|
||||
|
||||
@@ -41,3 +41,5 @@ install:
|
||||
|
||||
install_cluster:
|
||||
|
||||
cflow:
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ SOURCES =\
|
||||
commands/toolcontext.c \
|
||||
config/config.c \
|
||||
datastruct/btree.c \
|
||||
datastruct/list.c \
|
||||
datastruct/str_list.c \
|
||||
device/dev-cache.c \
|
||||
device/dev-io.c \
|
||||
@@ -133,9 +134,22 @@ ifeq ("@HAVE_LIBDL@", "yes")
|
||||
misc/sharedlib.c
|
||||
endif
|
||||
|
||||
ifeq ("@DMEVENTD@", "yes")
|
||||
CLDFLAGS += -ldevmapper-event
|
||||
endif
|
||||
|
||||
LIB_STATIC = liblvm.a
|
||||
|
||||
$(SUBDIRS): $(LIB_STATIC)
|
||||
|
||||
CLEAN_TARGETS += liblvm.cflow
|
||||
|
||||
include $(top_srcdir)/make.tmpl
|
||||
|
||||
liblvm.cflow: $(SOURCES)
|
||||
set -e; (echo -n "SOURCES += "; \
|
||||
echo $(SOURCES) | \
|
||||
sed "s/^/ /;s/ / $(top_srcdir)\/lib\//g;s/$$//"; \
|
||||
) > $@
|
||||
|
||||
cflow: liblvm.cflow
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "str_list.h"
|
||||
#include "config.h"
|
||||
#include "filter.h"
|
||||
#include "segtype.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <fcntl.h>
|
||||
@@ -75,6 +76,11 @@ int driver_version(char *version, size_t size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int target_version(const char *target_name, uint32_t *maj,
|
||||
uint32_t *min, uint32_t *patchlevel)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int target_present(const char *target_name)
|
||||
{
|
||||
return 0;
|
||||
@@ -89,12 +95,12 @@ int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int lv_snapshot_percent(struct logical_volume *lv, float *percent)
|
||||
int lv_snapshot_percent(const struct logical_volume *lv, float *percent)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int lv_mirror_percent(struct logical_volume *lv, int wait, float *percent,
|
||||
uint32_t *event_nr)
|
||||
int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
int wait, float *percent, uint32_t *event_nr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -170,8 +176,8 @@ void set_activation(int act)
|
||||
log_verbose("Activation enabled. Device-mapper kernel "
|
||||
"driver will be used.");
|
||||
else
|
||||
log_verbose("Activation disabled. No device-mapper "
|
||||
"interaction will be attempted.");
|
||||
log_print("WARNING: Activation disabled. No device-mapper "
|
||||
"interaction will be attempted.");
|
||||
}
|
||||
|
||||
int activation(void)
|
||||
@@ -277,7 +283,8 @@ int driver_version(char *version, size_t size)
|
||||
return dm_driver_version(version, size);
|
||||
}
|
||||
|
||||
static int _target_present(const char *target_name)
|
||||
int target_version(const char *target_name, uint32_t *maj,
|
||||
uint32_t *min, uint32_t *patchlevel)
|
||||
{
|
||||
int r = 0;
|
||||
struct dm_task *dmt;
|
||||
@@ -300,6 +307,9 @@ static int _target_present(const char *target_name)
|
||||
|
||||
if (!strcmp(target_name, target->name)) {
|
||||
r = 1;
|
||||
*maj = target->version[0];
|
||||
*min = target->version[1];
|
||||
*patchlevel = target->version[2];
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -314,6 +324,7 @@ static int _target_present(const char *target_name)
|
||||
|
||||
int target_present(const char *target_name, int use_modprobe)
|
||||
{
|
||||
uint32_t maj, min, patchlevel;
|
||||
#ifdef MODPROBE_CMD
|
||||
char module[128];
|
||||
#endif
|
||||
@@ -323,7 +334,7 @@ int target_present(const char *target_name, int use_modprobe)
|
||||
|
||||
#ifdef MODPROBE_CMD
|
||||
if (use_modprobe) {
|
||||
if (_target_present(target_name))
|
||||
if (target_version(target_name, &maj, &min, &patchlevel))
|
||||
return 1;
|
||||
|
||||
if (lvm_snprintf(module, sizeof(module), "dm-%s", target_name)
|
||||
@@ -338,7 +349,7 @@ int target_present(const char *target_name, int use_modprobe)
|
||||
}
|
||||
#endif
|
||||
|
||||
return _target_present(target_name);
|
||||
return target_version(target_name, &maj, &min, &patchlevel);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -396,7 +407,7 @@ int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
|
||||
/*
|
||||
* Returns 1 if percent set, else 0 on failure.
|
||||
*/
|
||||
int lv_snapshot_percent(struct logical_volume *lv, float *percent)
|
||||
int lv_snapshot_percent(const struct logical_volume *lv, float *percent)
|
||||
{
|
||||
int r;
|
||||
struct dev_manager *dm;
|
||||
@@ -416,8 +427,8 @@ int lv_snapshot_percent(struct logical_volume *lv, float *percent)
|
||||
}
|
||||
|
||||
/* FIXME Merge with snapshot_percent */
|
||||
int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv, int wait, float *percent,
|
||||
uint32_t *event_nr)
|
||||
int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
int wait, float *percent, uint32_t *event_nr)
|
||||
{
|
||||
int r;
|
||||
struct dev_manager *dm;
|
||||
@@ -563,18 +574,53 @@ int lvs_in_vg_opened(struct volume_group *vg)
|
||||
return count;
|
||||
}
|
||||
|
||||
static int _register_dev_for_events(struct cmd_context *cmd,
|
||||
struct logical_volume *lv, int do_reg)
|
||||
{
|
||||
#ifdef DMEVENTD
|
||||
struct list *tmp;
|
||||
struct lv_segment *seg;
|
||||
int (*reg) (struct dm_pool *mem, struct lv_segment *,
|
||||
struct config_tree *cft, int events);
|
||||
|
||||
list_iterate(tmp, &lv->segments) {
|
||||
seg = list_item(tmp, struct lv_segment);
|
||||
|
||||
reg = NULL;
|
||||
|
||||
if (do_reg) {
|
||||
if (seg->segtype->ops->target_register_events)
|
||||
reg = seg->segtype->ops->target_register_events;
|
||||
} else if (seg->segtype->ops->target_unregister_events)
|
||||
reg = seg->segtype->ops->target_unregister_events;
|
||||
|
||||
if (reg)
|
||||
/* FIXME specify events */
|
||||
if (!reg(cmd->mem, seg, cmd->cft, 0)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
|
||||
int error_if_not_suspended)
|
||||
{
|
||||
struct logical_volume *lv;
|
||||
struct logical_volume *lv, *lv_pre;
|
||||
struct lvinfo info;
|
||||
|
||||
if (!activation())
|
||||
return 1;
|
||||
|
||||
if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
|
||||
return_0;
|
||||
|
||||
/* Use precommitted metadata if present */
|
||||
if (!(lv = lv_from_lvid(cmd, lvid_s, 1)))
|
||||
return 0;
|
||||
if (!(lv_pre = lv_from_lvid(cmd, lvid_s, 1)))
|
||||
return_0;
|
||||
|
||||
if (test_mode()) {
|
||||
_skip("Suspending '%s'.", lv->name);
|
||||
@@ -588,13 +634,16 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
|
||||
return error_if_not_suspended ? 0 : 1;
|
||||
|
||||
/* If VG was precommitted, preload devices for the LV */
|
||||
if ((lv->vg->status & PRECOMMITTED)) {
|
||||
if (!_lv_preload(lv)) {
|
||||
if ((lv_pre->vg->status & PRECOMMITTED)) {
|
||||
if (!_lv_preload(lv_pre)) {
|
||||
/* FIXME Revert preloading */
|
||||
return_0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_register_dev_for_events(cmd, lv, 0))
|
||||
stack;
|
||||
|
||||
memlock_inc();
|
||||
if (!_lv_suspend_lv(lv)) {
|
||||
memlock_dec();
|
||||
@@ -645,6 +694,9 @@ static int _lv_resume(struct cmd_context *cmd, const char *lvid_s,
|
||||
memlock_dec();
|
||||
fs_unlock();
|
||||
|
||||
if (!_register_dev_for_events(cmd, lv, 1))
|
||||
stack;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -688,6 +740,9 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!_register_dev_for_events(cmd, lv, 0))
|
||||
stack;
|
||||
|
||||
memlock_inc();
|
||||
r = _lv_deactivate(lv);
|
||||
memlock_dec();
|
||||
@@ -758,6 +813,9 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
|
||||
memlock_dec();
|
||||
fs_unlock();
|
||||
|
||||
if (!_register_dev_for_events(cmd, lv, 1))
|
||||
stack;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,8 @@ int library_version(char *version, size_t size);
|
||||
int lvm1_present(struct cmd_context *cmd);
|
||||
|
||||
int target_present(const char *target_name, int use_modprobe);
|
||||
int target_version(const char *target_name, uint32_t *maj,
|
||||
uint32_t *min, uint32_t *patchlevel);
|
||||
|
||||
void activation_exit(void);
|
||||
|
||||
@@ -68,9 +70,9 @@ int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s,
|
||||
/*
|
||||
* Returns 1 if percent has been set, else 0.
|
||||
*/
|
||||
int lv_snapshot_percent(struct logical_volume *lv, float *percent);
|
||||
int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv, int wait, float *percent,
|
||||
uint32_t *event_nr);
|
||||
int lv_snapshot_percent(const struct logical_volume *lv, float *percent);
|
||||
int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
int wait, float *percent, uint32_t *event_nr);
|
||||
|
||||
/*
|
||||
* Return number of LVs in the VG that are active.
|
||||
|
||||
@@ -85,7 +85,7 @@ char *build_dlid(struct dev_manager *dm, const char *lvid, const char *layer)
|
||||
return _build_dlid(dm->mem, lvid, layer);
|
||||
}
|
||||
|
||||
static inline int _read_only_lv(struct logical_volume *lv)
|
||||
static int _read_only_lv(struct logical_volume *lv)
|
||||
{
|
||||
return (!(lv->vg->status & LVM_WRITE) || !(lv->status & LVM_WRITE));
|
||||
}
|
||||
@@ -432,7 +432,8 @@ void dev_manager_exit(void)
|
||||
}
|
||||
|
||||
int dev_manager_snapshot_percent(struct dev_manager *dm,
|
||||
struct logical_volume *lv, float *percent)
|
||||
const struct logical_volume *lv,
|
||||
float *percent)
|
||||
{
|
||||
char *name;
|
||||
const char *dlid;
|
||||
@@ -977,6 +978,8 @@ static int _tree_action(struct dev_manager *dm, struct logical_volume *lv, actio
|
||||
goto_out;
|
||||
break;
|
||||
case SUSPEND:
|
||||
if (!lv_is_origin(lv) && !lv_is_cow(lv))
|
||||
dm_tree_skip_lockfs(root);
|
||||
if (!dm_tree_suspend_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1))
|
||||
goto_out;
|
||||
break;
|
||||
|
||||
@@ -41,7 +41,8 @@ int dev_manager_info(struct dm_pool *mem, const char *name,
|
||||
const struct logical_volume *lv,
|
||||
int mknodes, int with_open_count, struct dm_info *info);
|
||||
int dev_manager_snapshot_percent(struct dev_manager *dm,
|
||||
struct logical_volume *lv, float *percent);
|
||||
const struct logical_volume *lv,
|
||||
float *percent);
|
||||
int dev_manager_mirror_percent(struct dev_manager *dm,
|
||||
struct logical_volume *lv, int wait,
|
||||
float *percent, uint32_t *event_nr);
|
||||
|
||||
315
lib/cache/lvmcache.c
vendored
315
lib/cache/lvmcache.c
vendored
@@ -86,7 +86,8 @@ int vgs_locked(void)
|
||||
return _vgs_locked;
|
||||
}
|
||||
|
||||
struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname)
|
||||
/* If vgid supplied, require a match. */
|
||||
struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname, const char *vgid)
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
|
||||
@@ -96,10 +97,16 @@ struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname)
|
||||
if (!(vginfo = dm_hash_lookup(_vgname_hash, vgname)))
|
||||
return NULL;
|
||||
|
||||
if (vgid)
|
||||
do
|
||||
if (!strncmp(vgid, vginfo->vgid, sizeof(vginfo->vgid)))
|
||||
return vginfo;
|
||||
while ((vginfo = vginfo->next));
|
||||
|
||||
return vginfo;
|
||||
}
|
||||
|
||||
const struct format_type *fmt_from_vgname(const char *vgname)
|
||||
const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid)
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
struct lvmcache_info *info;
|
||||
@@ -107,8 +114,9 @@ const struct format_type *fmt_from_vgname(const char *vgname)
|
||||
struct list *devh, *tmp;
|
||||
struct list devs;
|
||||
struct device_list *devl;
|
||||
char vgid_found[ID_LEN + 1];
|
||||
|
||||
if (!(vginfo = vginfo_from_vgname(vgname)))
|
||||
if (!(vginfo = vginfo_from_vgname(vgname, vgid)))
|
||||
return NULL;
|
||||
|
||||
/* This function is normally called before reading metadata so
|
||||
@@ -120,6 +128,8 @@ const struct format_type *fmt_from_vgname(const char *vgname)
|
||||
list_add(&devs, &devl->list);
|
||||
}
|
||||
|
||||
memcpy(vgid_found, vginfo->vgid, sizeof(vgid_found));
|
||||
|
||||
list_iterate_safe(devh, tmp, &devs) {
|
||||
devl = list_item(devh, struct device_list);
|
||||
label_read(devl->dev, &label);
|
||||
@@ -127,6 +137,11 @@ const struct format_type *fmt_from_vgname(const char *vgname)
|
||||
dm_free(devl);
|
||||
}
|
||||
|
||||
/* If vginfo changed, caller needs to rescan */
|
||||
if (!(vginfo = vginfo_from_vgname(vgname, vgid_found)) ||
|
||||
strncmp(vginfo->vgid, vgid_found, sizeof(vgid_found)))
|
||||
return NULL;
|
||||
|
||||
return vginfo->fmt;
|
||||
}
|
||||
|
||||
@@ -148,6 +163,19 @@ struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid)
|
||||
return vginfo;
|
||||
}
|
||||
|
||||
const char *vgname_from_vgid(struct dm_pool *mem, const char *vgid)
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
|
||||
if ((vginfo = vginfo_from_vgid(vgid))) {
|
||||
if (mem)
|
||||
return dm_pool_strdup(mem, vginfo->vgname);
|
||||
return vginfo->vgname;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct lvmcache_info *info_from_pvid(const char *pvid)
|
||||
{
|
||||
struct lvmcache_info *info;
|
||||
@@ -232,10 +260,33 @@ int lvmcache_label_scan(struct cmd_context *cmd, int full_scan)
|
||||
return r;
|
||||
}
|
||||
|
||||
struct list *lvmcache_get_vgids(struct cmd_context *cmd, int full_scan)
|
||||
{
|
||||
struct list *vgids;
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
|
||||
lvmcache_label_scan(cmd, full_scan);
|
||||
|
||||
if (!(vgids = str_list_create(cmd->mem))) {
|
||||
log_error("vgids list allocation failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
list_iterate_items(vginfo, &_vginfos) {
|
||||
if (!str_list_add(cmd->mem, vgids,
|
||||
dm_pool_strdup(cmd->mem, vginfo->vgid))) {
|
||||
log_error("strlist allocation failed");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return vgids;
|
||||
}
|
||||
|
||||
struct list *lvmcache_get_vgnames(struct cmd_context *cmd, int full_scan)
|
||||
{
|
||||
struct list *vgnames;
|
||||
struct lvmcache_vginfo *vgi;
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
|
||||
lvmcache_label_scan(cmd, full_scan);
|
||||
|
||||
@@ -244,9 +295,9 @@ struct list *lvmcache_get_vgnames(struct cmd_context *cmd, int full_scan)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
list_iterate_items(vgi, &_vginfos) {
|
||||
list_iterate_items(vginfo, &_vginfos) {
|
||||
if (!str_list_add(cmd->mem, vgnames,
|
||||
dm_pool_strdup(cmd->mem, vgi->vgname))) {
|
||||
dm_pool_strdup(cmd->mem, vginfo->vgname))) {
|
||||
log_error("strlist allocation failed");
|
||||
return NULL;
|
||||
}
|
||||
@@ -297,7 +348,7 @@ struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void _drop_vginfo(struct lvmcache_info *info)
|
||||
static int _drop_vginfo(struct lvmcache_info *info)
|
||||
{
|
||||
if (!list_empty(&info->list)) {
|
||||
list_del(&info->list);
|
||||
@@ -306,8 +357,18 @@ static void _drop_vginfo(struct lvmcache_info *info)
|
||||
|
||||
if (info->vginfo && list_empty(&info->vginfo->infos)) {
|
||||
dm_hash_remove(_vgname_hash, info->vginfo->vgname);
|
||||
if (info->vginfo->next) {
|
||||
if (!dm_hash_insert(_vgname_hash, info->vginfo->vgname, info->vginfo->next)) {
|
||||
log_error("vg hash re-insertion failed: %s",
|
||||
info->vginfo->vgname);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (info->vginfo->vgname)
|
||||
dm_free(info->vginfo->vgname);
|
||||
if (info->vginfo->creation_host)
|
||||
dm_free(info->vginfo->creation_host);
|
||||
if (*info->vginfo->vgid)
|
||||
dm_hash_remove(_vgid_hash, info->vginfo->vgid);
|
||||
list_del(&info->vginfo->list);
|
||||
@@ -315,6 +376,8 @@ static void _drop_vginfo(struct lvmcache_info *info)
|
||||
}
|
||||
|
||||
info->vginfo = NULL;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Unused
|
||||
@@ -356,8 +419,10 @@ static int _lvmcache_update_vgid(struct lvmcache_info *info, const char *vgid)
|
||||
|
||||
if (info->vginfo && *info->vginfo->vgid)
|
||||
dm_hash_remove(_vgid_hash, info->vginfo->vgid);
|
||||
if (!vgid)
|
||||
if (!vgid) {
|
||||
log_debug("lvmcache: %s: clearing VGID", dev_name(info->dev));
|
||||
return 1;
|
||||
}
|
||||
|
||||
strncpy(info->vginfo->vgid, vgid, sizeof(info->vginfo->vgid));
|
||||
info->vginfo->vgid[sizeof(info->vginfo->vgid) - 1] = '\0';
|
||||
@@ -367,19 +432,110 @@ static int _lvmcache_update_vgid(struct lvmcache_info *info, const char *vgid)
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_debug("lvmcache: %s: setting %s VGID to %s", dev_name(info->dev),
|
||||
info->vginfo->vgname, info->vginfo->vgid);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname)
|
||||
static int _insert_vginfo(struct lvmcache_vginfo *new_vginfo, const char *vgid,
|
||||
uint32_t vgstatus, const char *creation_host,
|
||||
struct lvmcache_vginfo *primary_vginfo)
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
struct lvmcache_vginfo *last_vginfo = primary_vginfo;
|
||||
char uuid_primary[64], uuid_new[64];
|
||||
int use_new = 0;
|
||||
|
||||
/* Pre-existing VG takes precedence. Unexported VG takes precedence. */
|
||||
if (primary_vginfo) {
|
||||
if (!id_write_format((struct id *)vgid, uuid_new, sizeof(uuid_new)))
|
||||
return_0;
|
||||
|
||||
if (!id_write_format((struct id *)&primary_vginfo->vgid, uuid_primary,
|
||||
sizeof(uuid_primary)))
|
||||
return_0;
|
||||
|
||||
/*
|
||||
* If Primary not exported, new exported => keep
|
||||
* Else Primary exported, new not exported => change
|
||||
* Else Primary has hostname for this machine => keep
|
||||
* Else Primary has no hostname, new has one => change
|
||||
* Else New has hostname for this machine => change
|
||||
* Else Keep primary.
|
||||
*/
|
||||
if (!(primary_vginfo->status & EXPORTED_VG) &&
|
||||
(vgstatus & EXPORTED_VG))
|
||||
log_error("WARNING: Duplicate VG name %s: "
|
||||
"Existing %s takes precedence over "
|
||||
"exported %s", new_vginfo->vgname,
|
||||
uuid_primary, uuid_new);
|
||||
else if ((primary_vginfo->status & EXPORTED_VG) &&
|
||||
!(vgstatus & EXPORTED_VG)) {
|
||||
log_error("WARNING: Duplicate VG name %s: "
|
||||
"%s takes precedence over exported %s",
|
||||
new_vginfo->vgname, uuid_new,
|
||||
uuid_primary);
|
||||
use_new = 1;
|
||||
} else if (primary_vginfo->creation_host &&
|
||||
!strcmp(primary_vginfo->creation_host,
|
||||
primary_vginfo->fmt->cmd->hostname))
|
||||
log_error("WARNING: Duplicate VG name %s: "
|
||||
"Existing %s (created here) takes precedence "
|
||||
"over %s", new_vginfo->vgname, uuid_primary,
|
||||
uuid_new);
|
||||
else if (!primary_vginfo->creation_host && creation_host) {
|
||||
log_error("WARNING: Duplicate VG name %s: "
|
||||
"%s (with creation_host) takes precedence over %s",
|
||||
new_vginfo->vgname, uuid_new,
|
||||
uuid_primary);
|
||||
use_new = 1;
|
||||
} else if (creation_host &&
|
||||
!strcmp(creation_host,
|
||||
primary_vginfo->fmt->cmd->hostname)) {
|
||||
log_error("WARNING: Duplicate VG name %s: "
|
||||
"%s (created here) takes precedence over %s",
|
||||
new_vginfo->vgname, uuid_new,
|
||||
uuid_primary);
|
||||
use_new = 1;
|
||||
}
|
||||
|
||||
if (!use_new) {
|
||||
while (last_vginfo->next)
|
||||
last_vginfo = last_vginfo->next;
|
||||
last_vginfo->next = new_vginfo;
|
||||
return 1;
|
||||
}
|
||||
|
||||
dm_hash_remove(_vgname_hash, primary_vginfo->vgname);
|
||||
}
|
||||
|
||||
if (!dm_hash_insert(_vgname_hash, new_vginfo->vgname, new_vginfo)) {
|
||||
log_error("cache_update: vg hash insertion failed: %s",
|
||||
new_vginfo->vgname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (primary_vginfo)
|
||||
new_vginfo->next = primary_vginfo;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _lvmcache_update_vgname(struct lvmcache_info *info,
|
||||
const char *vgname, const char *vgid,
|
||||
uint32_t vgstatus, const char *creation_host)
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo, *primary_vginfo;
|
||||
// struct lvmcache_vginfo *old_vginfo, *next;
|
||||
|
||||
/* If vgname is NULL and we don't already have a vgname,
|
||||
* assume ORPHAN - we want every entry to have a vginfo
|
||||
* attached for scanning reasons.
|
||||
*/
|
||||
if (!vgname && !info->vginfo)
|
||||
if (!vgname && !info->vginfo) {
|
||||
vgname = ORPHAN;
|
||||
vgid = ORPHAN;
|
||||
}
|
||||
|
||||
if (!vgname || (info->vginfo && !strcmp(info->vginfo->vgname, vgname)))
|
||||
return 1;
|
||||
@@ -388,7 +544,43 @@ int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname)
|
||||
_drop_vginfo(info);
|
||||
|
||||
/* Get existing vginfo or create new one */
|
||||
if (!(vginfo = vginfo_from_vgname(vgname))) {
|
||||
if (!(vginfo = vginfo_from_vgname(vgname, vgid))) {
|
||||
/*** FIXME - vginfo ends up duplicated instead of renamed.
|
||||
// Renaming? This lookup fails.
|
||||
if ((vginfo = vginfo_from_vgid(vgid))) {
|
||||
next = vginfo->next;
|
||||
old_vginfo = vginfo_from_vgname(vginfo->vgname, NULL);
|
||||
if (old_vginfo == vginfo) {
|
||||
dm_hash_remove(_vgname_hash, old_vginfo->vgname);
|
||||
if (old_vginfo->next) {
|
||||
if (!dm_hash_insert(_vgname_hash, old_vginfo->vgname, old_vginfo->next)) {
|
||||
log_error("vg hash re-insertion failed: %s",
|
||||
old_vginfo->vgname);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} else do {
|
||||
if (old_vginfo->next == vginfo) {
|
||||
old_vginfo->next = vginfo->next;
|
||||
break;
|
||||
}
|
||||
} while ((old_vginfo = old_vginfo->next));
|
||||
vginfo->next = NULL;
|
||||
|
||||
dm_free(vginfo->vgname);
|
||||
if (!(vginfo->vgname = dm_strdup(vgname))) {
|
||||
log_error("cache vgname alloc failed for %s", vgname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Rename so can assume new name does not already exist
|
||||
if (!dm_hash_insert(_vgname_hash, vginfo->vgname, vginfo->next)) {
|
||||
log_error("vg hash re-insertion failed: %s",
|
||||
vginfo->vgname);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
***/
|
||||
if (!(vginfo = dm_malloc(sizeof(*vginfo)))) {
|
||||
log_error("lvmcache_update_vgname: list alloc failed");
|
||||
return 0;
|
||||
@@ -400,9 +592,9 @@ int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname)
|
||||
return 0;
|
||||
}
|
||||
list_init(&vginfo->infos);
|
||||
if (!dm_hash_insert(_vgname_hash, vginfo->vgname, vginfo)) {
|
||||
log_error("cache_update: vg hash insertion failed: %s",
|
||||
vginfo->vgname);
|
||||
primary_vginfo = vginfo_from_vgname(vgname, NULL);
|
||||
if (!_insert_vginfo(vginfo, vgid, vgstatus, creation_host,
|
||||
primary_vginfo)) {
|
||||
dm_free(vginfo->vgname);
|
||||
dm_free(vginfo);
|
||||
return 0;
|
||||
@@ -412,6 +604,9 @@ int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname)
|
||||
list_add(&_vginfos, &vginfo->list);
|
||||
else
|
||||
list_add_h(&_vginfos, &vginfo->list);
|
||||
/***
|
||||
}
|
||||
***/
|
||||
}
|
||||
|
||||
info->vginfo = vginfo;
|
||||
@@ -420,8 +615,59 @@ int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname)
|
||||
/* FIXME Check consistency of list! */
|
||||
vginfo->fmt = info->fmt;
|
||||
|
||||
log_debug("lvmcache: %s now %s%s", dev_name(info->dev),
|
||||
*vgname ? "in VG " : "orphaned", vgname);
|
||||
log_debug("lvmcache: %s: now %s%s%s%s%s", dev_name(info->dev),
|
||||
*vgname ? "in VG " : "orphaned", vgname,
|
||||
vginfo->vgid[0] ? " (" : "",
|
||||
vginfo->vgid[0] ? vginfo->vgid : "",
|
||||
vginfo->vgid[0] ? ")" : "");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _lvmcache_update_vgstatus(struct lvmcache_info *info, uint32_t vgstatus,
|
||||
const char *creation_host)
|
||||
{
|
||||
if (!info || !info->vginfo)
|
||||
return 1;
|
||||
|
||||
if ((info->vginfo->status & EXPORTED_VG) != (vgstatus & EXPORTED_VG))
|
||||
log_debug("lvmcache: %s: VG %s %s exported",
|
||||
dev_name(info->dev), info->vginfo->vgname,
|
||||
vgstatus & EXPORTED_VG ? "now" : "no longer");
|
||||
|
||||
info->vginfo->status = vgstatus;
|
||||
|
||||
if (!creation_host)
|
||||
return 1;
|
||||
|
||||
if (info->vginfo->creation_host && !strcmp(creation_host,
|
||||
info->vginfo->creation_host))
|
||||
return 1;
|
||||
|
||||
if (info->vginfo->creation_host)
|
||||
dm_free(info->vginfo->creation_host);
|
||||
|
||||
if (!(info->vginfo->creation_host = dm_strdup(creation_host))) {
|
||||
log_error("cache creation host alloc failed for %s",
|
||||
creation_host);
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_debug("lvmcache: %s: VG %s: Set creation host to %s.",
|
||||
dev_name(info->dev), info->vginfo->vgname, creation_host);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lvmcache_update_vgname_and_id(struct lvmcache_info *info,
|
||||
const char *vgname, const char *vgid,
|
||||
uint32_t vgstatus, const char *creation_host)
|
||||
{
|
||||
if (!_lvmcache_update_vgname(info, vgname, vgid, vgstatus,
|
||||
creation_host) ||
|
||||
!_lvmcache_update_vgid(info, vgid) ||
|
||||
!_lvmcache_update_vgstatus(info, vgstatus, creation_host))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -431,20 +677,17 @@ int lvmcache_update_vg(struct volume_group *vg)
|
||||
struct pv_list *pvl;
|
||||
struct lvmcache_info *info;
|
||||
char pvid_s[ID_LEN + 1];
|
||||
int vgid_updated = 0;
|
||||
|
||||
pvid_s[sizeof(pvid_s) - 1] = '\0';
|
||||
|
||||
list_iterate_items(pvl, &vg->pvs) {
|
||||
strncpy(pvid_s, (char *) &pvl->pv->id, sizeof(pvid_s) - 1);
|
||||
/* FIXME Could pvl->pv->dev->pvid ever be different? */
|
||||
if ((info = info_from_pvid(pvid_s))) {
|
||||
lvmcache_update_vgname(info, vg->name);
|
||||
if (!vgid_updated) {
|
||||
_lvmcache_update_vgid(info, (char *) &vg->id);
|
||||
vgid_updated = 1;
|
||||
}
|
||||
}
|
||||
if ((info = info_from_pvid(pvid_s)) &&
|
||||
!lvmcache_update_vgname_and_id(info, vg->name,
|
||||
(char *) &vg->id,
|
||||
vg->status, NULL))
|
||||
return_0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -452,7 +695,8 @@ int lvmcache_update_vg(struct volume_group *vg)
|
||||
|
||||
struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
|
||||
struct device *dev,
|
||||
const char *vgname, const char *vgid)
|
||||
const char *vgname, const char *vgid,
|
||||
uint32_t vgstatus)
|
||||
{
|
||||
struct label *label;
|
||||
struct lvmcache_info *existing, *info;
|
||||
@@ -548,7 +792,7 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!lvmcache_update_vgname(info, vgname)) {
|
||||
if (!lvmcache_update_vgname_and_id(info, vgname, vgid, vgstatus, NULL)) {
|
||||
if (!existing) {
|
||||
dm_hash_remove(_pvid_hash, pvid_s);
|
||||
strcpy(info->dev->pvid, "");
|
||||
@@ -558,10 +802,6 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_lvmcache_update_vgid(info, vgid))
|
||||
/* Non-critical */
|
||||
stack;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
@@ -576,9 +816,16 @@ static void _lvmcache_destroy_entry(struct lvmcache_info *info)
|
||||
|
||||
static void _lvmcache_destroy_vgnamelist(struct lvmcache_vginfo *vginfo)
|
||||
{
|
||||
if (vginfo->vgname)
|
||||
dm_free(vginfo->vgname);
|
||||
dm_free(vginfo);
|
||||
struct lvmcache_vginfo *next;
|
||||
|
||||
do {
|
||||
next = vginfo->next;
|
||||
if (vginfo->vgname)
|
||||
dm_free(vginfo->vgname);
|
||||
if (vginfo->creation_host)
|
||||
dm_free(vginfo->creation_host);
|
||||
dm_free(vginfo);
|
||||
} while ((vginfo = next));
|
||||
}
|
||||
|
||||
static void _lvmcache_destroy_lockname(int present)
|
||||
|
||||
22
lib/cache/lvmcache.h
vendored
22
lib/cache/lvmcache.h
vendored
@@ -33,15 +33,20 @@ struct cmd_context;
|
||||
struct format_type;
|
||||
struct volume_group;
|
||||
|
||||
/* One per VG */
|
||||
struct lvmcache_vginfo {
|
||||
struct list list; /* Join these vginfos together */
|
||||
struct list infos; /* List head for lvmcache_infos */
|
||||
const struct format_type *fmt;
|
||||
char *vgname; /* "" == orphan */
|
||||
uint32_t status;
|
||||
char vgid[ID_LEN + 1];
|
||||
char _padding[7];
|
||||
struct lvmcache_vginfo *next; /* Another VG with same name? */
|
||||
char *creation_host;
|
||||
};
|
||||
|
||||
/* One per device */
|
||||
struct lvmcache_info {
|
||||
struct list list; /* Join VG members together */
|
||||
struct list mdas; /* list head for metadata areas */
|
||||
@@ -64,21 +69,26 @@ int lvmcache_label_scan(struct cmd_context *cmd, int full_scan);
|
||||
/* Add/delete a device */
|
||||
struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
|
||||
struct device *dev,
|
||||
const char *vgname, const char *vgid);
|
||||
const char *vgname, const char *vgid,
|
||||
uint32_t vgstatus);
|
||||
void lvmcache_del(struct lvmcache_info *info);
|
||||
|
||||
/* Update things */
|
||||
int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname);
|
||||
int lvmcache_update_vgname_and_id(struct lvmcache_info *info,
|
||||
const char *vgname, const char *vgid,
|
||||
uint32_t vgstatus, const char *hostname);
|
||||
int lvmcache_update_vg(struct volume_group *vg);
|
||||
|
||||
void lvmcache_lock_vgname(const char *vgname, int read_only);
|
||||
void lvmcache_unlock_vgname(const char *vgname);
|
||||
|
||||
/* Queries */
|
||||
const struct format_type *fmt_from_vgname(const char *vgname);
|
||||
struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname);
|
||||
const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid);
|
||||
struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname,
|
||||
const char *vgid);
|
||||
struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid);
|
||||
struct lvmcache_info *info_from_pvid(const char *pvid);
|
||||
const char *vgname_from_vgid(struct dm_pool *mem, const char *vgid);
|
||||
struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid);
|
||||
int vgs_locked(void);
|
||||
int vgname_is_locked(const char *vgname);
|
||||
@@ -87,4 +97,8 @@ int vgname_is_locked(const char *vgname);
|
||||
/* Set full_scan to 1 to reread every filtered device label */
|
||||
struct list *lvmcache_get_vgnames(struct cmd_context *cmd, int full_scan);
|
||||
|
||||
/* Returns list of struct str_lists containing pool-allocated copy of vgids */
|
||||
/* Set full_scan to 1 to reread every filtered device label */
|
||||
struct list *lvmcache_get_vgids(struct cmd_context *cmd, int full_scan);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -657,7 +657,7 @@ static int _init_formats(struct cmd_context *cmd)
|
||||
return 0;
|
||||
}
|
||||
if (!(lib = load_shared_library(cmd->cft, cv->v.str,
|
||||
"format"))) {
|
||||
"format", 0))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -753,7 +753,7 @@ static int _init_segtypes(struct cmd_context *cmd)
|
||||
return 0;
|
||||
}
|
||||
if (!(lib = load_shared_library(cmd->cft, cv->v.str,
|
||||
"segment type"))) {
|
||||
"segment type", 0))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
#define DEFAULT_LOCK_DIR "/var/lock/lvm"
|
||||
#define DEFAULT_LOCKING_LIB "lvm2_locking.so"
|
||||
|
||||
#define DEFAULT_DMEVENTD_MIRROR_LIB "libdevmapper-event-lvm2mirror.so"
|
||||
|
||||
#define DEFAULT_UMASK 0077
|
||||
|
||||
#ifdef LVM1_FALLBACK
|
||||
|
||||
@@ -107,7 +107,7 @@ void *btree_get_data(struct btree_iter *it)
|
||||
return ((struct node *) it)->data;
|
||||
}
|
||||
|
||||
static inline struct node *_left(struct node *n)
|
||||
static struct node *_left(struct node *n)
|
||||
{
|
||||
while (n->l)
|
||||
n = n->l;
|
||||
|
||||
@@ -33,107 +33,61 @@ struct list {
|
||||
* The list head's next and previous pointers point back to itself.
|
||||
*/
|
||||
#define LIST_INIT(name) struct list name = { &(name), &(name) }
|
||||
static inline void list_init(struct list *head)
|
||||
{
|
||||
head->n = head->p = head;
|
||||
}
|
||||
void list_init(struct list *head);
|
||||
|
||||
/*
|
||||
* Insert an element before 'head'.
|
||||
* If 'head' is the list head, this adds an element to the end of the list.
|
||||
*/
|
||||
static inline void list_add(struct list *head, struct list *elem)
|
||||
{
|
||||
assert(head->n);
|
||||
|
||||
elem->n = head;
|
||||
elem->p = head->p;
|
||||
|
||||
head->p->n = elem;
|
||||
head->p = elem;
|
||||
}
|
||||
void list_add(struct list *head, struct list *elem);
|
||||
|
||||
/*
|
||||
* Insert an element after 'head'.
|
||||
* If 'head' is the list head, this adds an element to the front of the list.
|
||||
*/
|
||||
static inline void list_add_h(struct list *head, struct list *elem)
|
||||
{
|
||||
assert(head->n);
|
||||
|
||||
elem->n = head->n;
|
||||
elem->p = head;
|
||||
|
||||
head->n->p = elem;
|
||||
head->n = elem;
|
||||
}
|
||||
void list_add_h(struct list *head, struct list *elem);
|
||||
|
||||
/*
|
||||
* Delete an element from its list.
|
||||
* Note that this doesn't change the element itself - it may still be safe
|
||||
* to follow its pointers.
|
||||
*/
|
||||
static inline void list_del(struct list *elem)
|
||||
{
|
||||
elem->n->p = elem->p;
|
||||
elem->p->n = elem->n;
|
||||
}
|
||||
void list_del(struct list *elem);
|
||||
|
||||
/*
|
||||
* Is the list empty?
|
||||
*/
|
||||
static inline int list_empty(struct list *head)
|
||||
{
|
||||
return head->n == head;
|
||||
}
|
||||
int list_empty(struct list *head);
|
||||
|
||||
/*
|
||||
* Is this the first element of the list?
|
||||
*/
|
||||
static inline int list_start(struct list *head, struct list *elem)
|
||||
{
|
||||
return elem->p == head;
|
||||
}
|
||||
int list_start(struct list *head, struct list *elem);
|
||||
|
||||
/*
|
||||
* Is this the last element of the list?
|
||||
*/
|
||||
static inline int list_end(struct list *head, struct list *elem)
|
||||
{
|
||||
return elem->n == head;
|
||||
}
|
||||
int list_end(struct list *head, struct list *elem);
|
||||
|
||||
/*
|
||||
* Return first element of the list or NULL if empty
|
||||
*/
|
||||
static inline struct list *list_first(struct list *head)
|
||||
{
|
||||
return (list_empty(head) ? NULL : head->n);
|
||||
}
|
||||
struct list *list_first(struct list *head);
|
||||
|
||||
/*
|
||||
* Return last element of the list or NULL if empty
|
||||
*/
|
||||
static inline struct list *list_last(struct list *head)
|
||||
{
|
||||
return (list_empty(head) ? NULL : head->p);
|
||||
}
|
||||
struct list *list_last(struct list *head);
|
||||
|
||||
/*
|
||||
* Return the previous element of the list, or NULL if we've reached the start.
|
||||
*/
|
||||
static inline struct list *list_prev(struct list *head, struct list *elem)
|
||||
{
|
||||
return (list_start(head, elem) ? NULL : elem->p);
|
||||
}
|
||||
struct list *list_prev(struct list *head, struct list *elem);
|
||||
|
||||
/*
|
||||
* Return the next element of the list, or NULL if we've reached the end.
|
||||
*/
|
||||
static inline struct list *list_next(struct list *head, struct list *elem)
|
||||
{
|
||||
return (list_end(head, elem) ? NULL : elem->n);
|
||||
}
|
||||
struct list *list_next(struct list *head, struct list *elem);
|
||||
|
||||
/*
|
||||
* Given the address v of an instance of 'struct list' called 'head'
|
||||
@@ -244,15 +198,6 @@ static inline struct list *list_next(struct list *head, struct list *elem)
|
||||
/*
|
||||
* Return the number of elements in a list by walking it.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
unsigned int list_size(const struct list *head);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -479,7 +479,7 @@ static void _check_closed(struct device *dev)
|
||||
log_err("Device '%s' has been left open.", dev_name(dev));
|
||||
}
|
||||
|
||||
static inline void _check_for_open_devices(void)
|
||||
static void _check_for_open_devices(void)
|
||||
{
|
||||
dm_hash_iter(_cache.names, (dm_hash_iterate_fn) _check_closed);
|
||||
}
|
||||
@@ -664,7 +664,7 @@ void dev_iter_destroy(struct dev_iter *iter)
|
||||
dm_free(iter);
|
||||
}
|
||||
|
||||
static inline struct device *_iter_next(struct dev_iter *iter)
|
||||
static struct device *_iter_next(struct dev_iter *iter)
|
||||
{
|
||||
struct device *d = btree_get_data(iter->current);
|
||||
iter->current = btree_next(iter->current);
|
||||
@@ -682,3 +682,14 @@ struct device *dev_iter_get(struct dev_iter *iter)
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int dev_fd(struct device *dev)
|
||||
{
|
||||
return dev->fd;
|
||||
}
|
||||
|
||||
const char *dev_name(const struct device *dev)
|
||||
{
|
||||
return (dev) ? list_item(dev->aliases.n, struct str_list)->str :
|
||||
"unknown device";
|
||||
}
|
||||
|
||||
@@ -74,10 +74,8 @@ int dev_close_immediate(struct device *dev);
|
||||
void dev_close_all(void);
|
||||
int dev_test_excl(struct device *dev);
|
||||
|
||||
static inline int dev_fd(struct device *dev)
|
||||
{
|
||||
return dev->fd;
|
||||
}
|
||||
int dev_fd(struct device *dev);
|
||||
const char *dev_name(const struct device *dev);
|
||||
|
||||
int dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer);
|
||||
int dev_write(struct device *dev, uint64_t offset, size_t len, void *buffer);
|
||||
@@ -88,12 +86,6 @@ void dev_flush(struct device *dev);
|
||||
struct device *dev_create_file(const char *filename, struct device *dev,
|
||||
struct str_list *alias, int use_malloc);
|
||||
|
||||
static inline const char *dev_name(const struct device *dev)
|
||||
{
|
||||
return (dev) ? list_item(dev->aliases.n, struct str_list)->str :
|
||||
"unknown device";
|
||||
}
|
||||
|
||||
/* Return a valid device name from the alias list; NULL otherwise */
|
||||
const char *dev_name_confirmed(struct device *dev, int quiet);
|
||||
|
||||
|
||||
@@ -24,12 +24,12 @@
|
||||
#include "lvm-string.h"
|
||||
#include "activate.h"
|
||||
|
||||
static const char *_name(const struct lv_segment *seg)
|
||||
static const char *_errseg_name(const struct lv_segment *seg)
|
||||
{
|
||||
return seg->segtype->name;
|
||||
}
|
||||
|
||||
static int _merge_segments(struct lv_segment *seg1, struct lv_segment *seg2)
|
||||
static int _errseg_merge_segments(struct lv_segment *seg1, struct lv_segment *seg2)
|
||||
{
|
||||
seg1->len += seg2->len;
|
||||
seg1->area_len += seg2->area_len;
|
||||
@@ -38,7 +38,7 @@ static int _merge_segments(struct lv_segment *seg1, struct lv_segment *seg2)
|
||||
}
|
||||
|
||||
#ifdef DEVMAPPER_SUPPORT
|
||||
static int _add_target_line(struct dev_manager *dm, struct dm_pool *mem,
|
||||
static int _errseg_add_target_line(struct dev_manager *dm, struct dm_pool *mem,
|
||||
struct config_tree *cft, void **target_state,
|
||||
struct lv_segment *seg,
|
||||
struct dm_tree_node *node, uint64_t len,
|
||||
@@ -47,34 +47,34 @@ static int _add_target_line(struct dev_manager *dm, struct dm_pool *mem,
|
||||
return dm_tree_node_add_error_target(node, len);
|
||||
}
|
||||
|
||||
static int _target_present(void)
|
||||
static int _errseg_target_present(void)
|
||||
{
|
||||
static int checked = 0;
|
||||
static int present = 0;
|
||||
static int _errseg_checked = 0;
|
||||
static int _errseg_present = 0;
|
||||
|
||||
/* Reported truncated in older kernels */
|
||||
if (!checked &&
|
||||
if (!_errseg_checked &&
|
||||
(target_present("error", 0) || target_present("erro", 0)))
|
||||
present = 1;
|
||||
_errseg_present = 1;
|
||||
|
||||
checked = 1;
|
||||
return present;
|
||||
_errseg_checked = 1;
|
||||
return _errseg_present;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void _destroy(const struct segment_type *segtype)
|
||||
static void _errseg_destroy(const struct segment_type *segtype)
|
||||
{
|
||||
dm_free((void *) segtype);
|
||||
}
|
||||
|
||||
static struct segtype_handler _error_ops = {
|
||||
name:_name,
|
||||
merge_segments:_merge_segments,
|
||||
name:_errseg_name,
|
||||
merge_segments:_errseg_merge_segments,
|
||||
#ifdef DEVMAPPER_SUPPORT
|
||||
add_target_line:_add_target_line,
|
||||
target_present:_target_present,
|
||||
add_target_line:_errseg_add_target_line,
|
||||
target_present:_errseg_target_present,
|
||||
#endif
|
||||
destroy:_destroy,
|
||||
destroy:_errseg_destroy,
|
||||
};
|
||||
|
||||
struct segment_type *init_error_segtype(struct cmd_context *cmd)
|
||||
|
||||
@@ -33,7 +33,7 @@ static int _and_p(struct dev_filter *f, struct device *dev)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _destroy(struct dev_filter *f)
|
||||
static void _composite_destroy(struct dev_filter *f)
|
||||
{
|
||||
struct dev_filter **filters = (struct dev_filter **) f->private;
|
||||
|
||||
@@ -70,7 +70,7 @@ struct dev_filter *composite_filter_create(int n, struct dev_filter **filters)
|
||||
}
|
||||
|
||||
cft->passes_filter = _and_p;
|
||||
cft->destroy = _destroy;
|
||||
cft->destroy = _composite_destroy;
|
||||
cft->private = filters_copy;
|
||||
|
||||
return cft;
|
||||
|
||||
@@ -217,7 +217,7 @@ static int _lookup_p(struct dev_filter *f, struct device *dev)
|
||||
return (l == PF_BAD_DEVICE) ? 0 : 1;
|
||||
}
|
||||
|
||||
static void _destroy(struct dev_filter *f)
|
||||
static void _persistent_destroy(struct dev_filter *f)
|
||||
{
|
||||
struct pfilter *pf = (struct pfilter *) f->private;
|
||||
|
||||
@@ -258,7 +258,7 @@ struct dev_filter *persistent_filter_create(struct dev_filter *real,
|
||||
}
|
||||
|
||||
f->passes_filter = _lookup_p;
|
||||
f->destroy = _destroy;
|
||||
f->destroy = _persistent_destroy;
|
||||
f->private = pf;
|
||||
|
||||
return f;
|
||||
|
||||
@@ -191,7 +191,7 @@ static int _accept_p(struct dev_filter *f, struct device *dev)
|
||||
return !rejected;
|
||||
}
|
||||
|
||||
static void _destroy(struct dev_filter *f)
|
||||
static void _regex_destroy(struct dev_filter *f)
|
||||
{
|
||||
struct rfilter *rf = (struct rfilter *) f->private;
|
||||
dm_pool_destroy(rf->mem);
|
||||
@@ -226,7 +226,7 @@ struct dev_filter *regex_filter_create(struct config_value *patterns)
|
||||
}
|
||||
|
||||
f->passes_filter = _accept_p;
|
||||
f->destroy = _destroy;
|
||||
f->destroy = _regex_destroy;
|
||||
f->private = rf;
|
||||
return f;
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ static struct dev_set *_dev_set_create(struct dm_pool *mem, const char *sys_bloc
|
||||
return ds;
|
||||
}
|
||||
|
||||
static inline unsigned _hash_dev(dev_t dev)
|
||||
static unsigned _hash_dev(dev_t dev)
|
||||
{
|
||||
return (major(dev) ^ minor(dev)) & (SET_BUCKETS - 1);
|
||||
}
|
||||
|
||||
@@ -223,11 +223,11 @@ static int _read_lvd(struct device *dev, uint64_t pos, struct lv_disk *disk)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _read_vgd(struct disk_list *data)
|
||||
int read_vgd(struct device *dev, struct vg_disk *vgd, struct pv_disk *pvd)
|
||||
{
|
||||
struct vg_disk *vgd = &data->vgd;
|
||||
uint64_t pos = data->pvd.vg_on_disk.base;
|
||||
if (!dev_read(data->dev, pos, sizeof(*vgd), vgd))
|
||||
uint64_t pos = pvd->vg_on_disk.base;
|
||||
|
||||
if (!dev_read(dev, pos, sizeof(*vgd), vgd))
|
||||
fail;
|
||||
|
||||
_xlate_vgd(vgd);
|
||||
@@ -269,7 +269,7 @@ static int _read_uuids(struct disk_list *data)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int _check_lvd(struct lv_disk *lvd)
|
||||
static int _check_lvd(struct lv_disk *lvd)
|
||||
{
|
||||
return !(lvd->lv_name[0] == '\0');
|
||||
}
|
||||
@@ -319,13 +319,31 @@ static int _read_extents(struct disk_list *data)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void __update_lvmcache(const struct format_type *fmt,
|
||||
struct disk_list *dl,
|
||||
struct device *dev, const char *vgid,
|
||||
int exported)
|
||||
{
|
||||
struct lvmcache_info *info;
|
||||
|
||||
if (!(info = lvmcache_add(fmt->labeller, dl->pvd.pv_uuid, dev,
|
||||
dl->pvd.vg_name, vgid,
|
||||
exported ? EXPORTED_VG : 0))) {
|
||||
stack;
|
||||
return;
|
||||
}
|
||||
|
||||
info->device_size = xlate32(dl->pvd.pv_size) << SECTOR_SHIFT;
|
||||
list_init(&info->mdas);
|
||||
info->status &= ~CACHE_INVALID;
|
||||
}
|
||||
|
||||
static struct disk_list *__read_disk(const struct format_type *fmt,
|
||||
struct device *dev, struct dm_pool *mem,
|
||||
const char *vg_name)
|
||||
{
|
||||
struct disk_list *dl = dm_pool_alloc(mem, sizeof(*dl));
|
||||
struct disk_list *dl = dm_pool_zalloc(mem, sizeof(*dl));
|
||||
const char *name = dev_name(dev);
|
||||
struct lvmcache_info *info;
|
||||
|
||||
if (!dl) {
|
||||
stack;
|
||||
@@ -342,41 +360,32 @@ static struct disk_list *__read_disk(const struct format_type *fmt,
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (!(info = lvmcache_add(fmt->labeller, dl->pvd.pv_uuid, dev,
|
||||
dl->pvd.vg_name, NULL)))
|
||||
stack;
|
||||
else {
|
||||
info->device_size = xlate32(dl->pvd.pv_size) << SECTOR_SHIFT;
|
||||
list_init(&info->mdas);
|
||||
info->status &= ~CACHE_INVALID;
|
||||
}
|
||||
|
||||
/*
|
||||
* is it an orphan ?
|
||||
*/
|
||||
if (!*dl->pvd.vg_name) {
|
||||
log_very_verbose("%s is not a member of any format1 VG", name);
|
||||
|
||||
/* Update VG cache */
|
||||
/* vgcache_add(dl->pvd.vg_name, NULL, dev, fmt); */
|
||||
|
||||
__update_lvmcache(fmt, dl, dev, NULL, 0);
|
||||
return (vg_name) ? NULL : dl;
|
||||
}
|
||||
|
||||
if (!_read_vgd(dl)) {
|
||||
if (!read_vgd(dl->dev, &dl->vgd, &dl->pvd)) {
|
||||
log_error("Failed to read VG data from PV (%s)", name);
|
||||
__update_lvmcache(fmt, dl, dev, NULL, 0);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/* Update VG cache with what we found */
|
||||
/* vgcache_add(dl->pvd.vg_name, dl->vgd.vg_uuid, dev, fmt); */
|
||||
|
||||
if (vg_name && strcmp(vg_name, dl->pvd.vg_name)) {
|
||||
log_very_verbose("%s is not a member of the VG %s",
|
||||
name, vg_name);
|
||||
__update_lvmcache(fmt, dl, dev, NULL, 0);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
__update_lvmcache(fmt, dl, dev, dl->vgd.vg_uuid,
|
||||
dl->vgd.vg_status & VG_EXPORTED);
|
||||
|
||||
if (!_read_uuids(dl)) {
|
||||
log_error("Failed to read PV uuid list from %s", name);
|
||||
goto bad;
|
||||
@@ -461,7 +470,7 @@ int read_pvs_in_vg(const struct format_type *fmt, const char *vg_name,
|
||||
struct lvmcache_info *info;
|
||||
|
||||
/* Fast path if we already saw this VG and cached the list of PVs */
|
||||
if (vg_name && (vginfo = vginfo_from_vgname(vg_name)) &&
|
||||
if (vg_name && (vginfo = vginfo_from_vgname(vg_name, NULL)) &&
|
||||
vginfo->infos.n) {
|
||||
list_iterate_items(info, &vginfo->infos) {
|
||||
dev = info->dev;
|
||||
|
||||
@@ -204,7 +204,8 @@ int write_disks(const struct format_type *fmt, struct list *pvds);
|
||||
*/
|
||||
int import_pv(struct dm_pool *mem, struct device *dev,
|
||||
struct volume_group *vg,
|
||||
struct physical_volume *pv, struct pv_disk *pvd);
|
||||
struct physical_volume *pv, struct pv_disk *pvd,
|
||||
struct vg_disk *vgd);
|
||||
int export_pv(struct cmd_context *cmd, struct dm_pool *mem,
|
||||
struct volume_group *vg,
|
||||
struct pv_disk *pvd, struct physical_volume *pv);
|
||||
@@ -237,6 +238,7 @@ void export_numbers(struct list *pvds, struct volume_group *vg);
|
||||
|
||||
void export_pv_act(struct list *pvds);
|
||||
int munge_pvd(struct device *dev, struct pv_disk *pvd);
|
||||
int read_vgd(struct device *dev, struct vg_disk *vgd, struct pv_disk *pvd);
|
||||
|
||||
/* blech */
|
||||
int get_free_vg_number(struct format_instance *fid, struct dev_filter *filter,
|
||||
|
||||
@@ -173,7 +173,7 @@ static struct volume_group *_build_vg(struct format_instance *fid,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct volume_group *_vg_read(struct format_instance *fid,
|
||||
static struct volume_group *_format1_vg_read(struct format_instance *fid,
|
||||
const char *vg_name,
|
||||
struct metadata_area *mda)
|
||||
{
|
||||
@@ -264,7 +264,7 @@ static int _flatten_vg(struct format_instance *fid, struct dm_pool *mem,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _vg_write(struct format_instance *fid, struct volume_group *vg,
|
||||
static int _format1_vg_write(struct format_instance *fid, struct volume_group *vg,
|
||||
struct metadata_area *mda)
|
||||
{
|
||||
struct dm_pool *mem = dm_pool_create("lvm1 vg_write", 1024 * 10);
|
||||
@@ -287,7 +287,7 @@ static int _vg_write(struct format_instance *fid, struct volume_group *vg,
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _pv_read(const struct format_type *fmt, const char *pv_name,
|
||||
static int _format1_pv_read(const struct format_type *fmt, const char *pv_name,
|
||||
struct physical_volume *pv, struct list *mdas)
|
||||
{
|
||||
struct dm_pool *mem = dm_pool_create("lvm1 pv_read", 1024);
|
||||
@@ -312,7 +312,7 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!import_pv(fmt->cmd->mem, dl->dev, NULL, pv, &dl->pvd)) {
|
||||
if (!import_pv(fmt->cmd->mem, dl->dev, NULL, pv, &dl->pvd, &dl->vgd)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
@@ -326,7 +326,7 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _pv_setup(const struct format_type *fmt,
|
||||
static int _format1_pv_setup(const struct format_type *fmt,
|
||||
uint64_t pe_start, uint32_t extent_count,
|
||||
uint32_t extent_size,
|
||||
int pvmetadatacopies,
|
||||
@@ -364,7 +364,7 @@ static int _pv_setup(const struct format_type *fmt,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _lv_setup(struct format_instance *fid, struct logical_volume *lv)
|
||||
static int _format1_lv_setup(struct format_instance *fid, struct logical_volume *lv)
|
||||
{
|
||||
uint64_t max_size = UINT_MAX;
|
||||
|
||||
@@ -386,7 +386,7 @@ static int _lv_setup(struct format_instance *fid, struct logical_volume *lv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
|
||||
static int _format1_pv_write(const struct format_type *fmt, struct physical_volume *pv,
|
||||
struct list *mdas, int64_t sector)
|
||||
{
|
||||
struct dm_pool *mem;
|
||||
@@ -396,7 +396,7 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
|
||||
struct lvmcache_info *info;
|
||||
|
||||
if (!(info = lvmcache_add(fmt->labeller, (char *) &pv->id, pv->dev,
|
||||
pv->vg_name, NULL))) {
|
||||
pv->vg_name, NULL, 0))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -449,7 +449,7 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _vg_setup(struct format_instance *fid, struct volume_group *vg)
|
||||
static int _format1_vg_setup(struct format_instance *fid, struct volume_group *vg)
|
||||
{
|
||||
/* just check max_pv and max_lv */
|
||||
if (!vg->max_lv || vg->max_lv >= MAX_LV)
|
||||
@@ -484,7 +484,7 @@ static int _vg_setup(struct format_instance *fid, struct volume_group *vg)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _segtype_supported (struct format_instance *fid,
|
||||
static int _format1_segtype_supported(struct format_instance *fid,
|
||||
struct segment_type *segtype)
|
||||
{
|
||||
if (!(segtype->flags & SEG_FORMAT1_SUPPORT)) {
|
||||
@@ -496,12 +496,13 @@ static int _segtype_supported (struct format_instance *fid,
|
||||
}
|
||||
|
||||
static struct metadata_area_ops _metadata_format1_ops = {
|
||||
vg_read:_vg_read,
|
||||
vg_write:_vg_write,
|
||||
vg_read:_format1_vg_read,
|
||||
vg_write:_format1_vg_write,
|
||||
};
|
||||
|
||||
static struct format_instance *_create_instance(const struct format_type *fmt,
|
||||
static struct format_instance *_format1_create_instance(const struct format_type *fmt,
|
||||
const char *vgname,
|
||||
const char *vgid,
|
||||
void *private)
|
||||
{
|
||||
struct format_instance *fid;
|
||||
@@ -529,26 +530,26 @@ static struct format_instance *_create_instance(const struct format_type *fmt,
|
||||
return fid;
|
||||
}
|
||||
|
||||
static void _destroy_instance(struct format_instance *fid)
|
||||
static void _format1_destroy_instance(struct format_instance *fid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void _destroy(const struct format_type *fmt)
|
||||
static void _format1_destroy(const struct format_type *fmt)
|
||||
{
|
||||
dm_free((void *) fmt);
|
||||
}
|
||||
|
||||
static struct format_handler _format1_ops = {
|
||||
pv_read:_pv_read,
|
||||
pv_setup:_pv_setup,
|
||||
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,
|
||||
pv_read:_format1_pv_read,
|
||||
pv_setup:_format1_pv_setup,
|
||||
pv_write:_format1_pv_write,
|
||||
lv_setup:_format1_lv_setup,
|
||||
vg_setup:_format1_vg_setup,
|
||||
segtype_supported:_format1_segtype_supported,
|
||||
create_instance:_format1_create_instance,
|
||||
destroy_instance:_format1_destroy_instance,
|
||||
destroy:_format1_destroy,
|
||||
};
|
||||
|
||||
#ifdef LVM1_INTERNAL
|
||||
|
||||
@@ -49,7 +49,8 @@ static char *_create_lv_name(struct dm_pool *mem, const char *full_name)
|
||||
|
||||
int import_pv(struct dm_pool *mem, struct device *dev,
|
||||
struct volume_group *vg,
|
||||
struct physical_volume *pv, struct pv_disk *pvd)
|
||||
struct physical_volume *pv, struct pv_disk *pvd,
|
||||
struct vg_disk *vgd)
|
||||
{
|
||||
memset(pv, 0, sizeof(*pv));
|
||||
memcpy(&pv->id, pvd->pv_uuid, ID_LEN);
|
||||
@@ -60,6 +61,8 @@ int import_pv(struct dm_pool *mem, struct device *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(&pv->vgid, vgd->vg_uuid, sizeof(vg->id));
|
||||
|
||||
/* Store system_id from first PV if PV belongs to a VG */
|
||||
if (vg && !*vg->system_id)
|
||||
strncpy(vg->system_id, pvd->system_id, NAME_LEN);
|
||||
@@ -426,7 +429,7 @@ int import_pvs(const struct format_type *fmt, struct dm_pool *mem,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!import_pv(mem, dl->dev, vg, pvl->pv, &dl->pvd)) {
|
||||
if (!import_pv(mem, dl->dev, vg, pvl->pv, &dl->pvd, &dl->vgd)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -140,7 +140,12 @@ static int _fill_maps(struct dm_hash_table *maps, struct volume_group *vg,
|
||||
lvm = lvms[lv_num];
|
||||
|
||||
if (!lvm) {
|
||||
log_err("invalid lv in extent map");
|
||||
log_error("Invalid LV in extent map "
|
||||
"(PV %s, PE %" PRIu32
|
||||
", LV %" PRIu32
|
||||
", LE %" PRIu32 ")",
|
||||
dev_name(pv->dev), i,
|
||||
lv_num, e[i].le_num);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,16 +19,18 @@
|
||||
/*
|
||||
* Only works with powers of 2.
|
||||
*/
|
||||
static inline uint32_t _round_up(uint32_t n, uint32_t size)
|
||||
static uint32_t _round_up(uint32_t n, uint32_t size)
|
||||
{
|
||||
size--;
|
||||
return (n + size) & ~size;
|
||||
}
|
||||
|
||||
static inline uint32_t _div_up(uint32_t n, uint32_t size)
|
||||
/* Unused.
|
||||
static uint32_t _div_up(uint32_t n, uint32_t size)
|
||||
{
|
||||
return _round_up(n, size) / size;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
* Each chunk of metadata should be aligned to
|
||||
|
||||
@@ -30,7 +30,7 @@ static void _not_supported(const char *op)
|
||||
op);
|
||||
}
|
||||
|
||||
static int _can_handle(struct labeller *l, char *buf, uint64_t sector)
|
||||
static int _lvm1_can_handle(struct labeller *l, char *buf, uint64_t sector)
|
||||
{
|
||||
struct pv_disk *pvd = (struct pv_disk *) buf;
|
||||
uint32_t version;
|
||||
@@ -48,21 +48,30 @@ static int _can_handle(struct labeller *l, char *buf, uint64_t sector)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _write(struct label *label, char *buf)
|
||||
static int _lvm1_write(struct label *label, char *buf)
|
||||
{
|
||||
_not_supported("write");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _read(struct labeller *l, struct device *dev, char *buf,
|
||||
static int _lvm1_read(struct labeller *l, struct device *dev, char *buf,
|
||||
struct label **label)
|
||||
{
|
||||
struct pv_disk *pvd = (struct pv_disk *) buf;
|
||||
struct vg_disk vgd;
|
||||
struct lvmcache_info *info;
|
||||
const char *vgid = NULL;
|
||||
int exported = 0;
|
||||
|
||||
munge_pvd(dev, pvd);
|
||||
|
||||
if (!(info = lvmcache_add(l, pvd->pv_uuid, dev, pvd->vg_name, NULL))) {
|
||||
if (*pvd->vg_name && read_vgd(dev, &vgd, pvd)) {
|
||||
vgid = vgd.vg_uuid;
|
||||
exported = pvd->pv_status & VG_EXPORTED;
|
||||
}
|
||||
|
||||
if (!(info = lvmcache_add(l, pvd->pv_uuid, dev, pvd->vg_name, vgid,
|
||||
exported))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -76,31 +85,31 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _initialise_label(struct labeller *l, struct label *label)
|
||||
static int _lvm1_initialise_label(struct labeller *l, struct label *label)
|
||||
{
|
||||
strcpy(label->type, "LVM1");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _destroy_label(struct labeller *l, struct label *label)
|
||||
static void _lvm1_destroy_label(struct labeller *l, struct label *label)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void _destroy(struct labeller *l)
|
||||
static void _lvm1_destroy(struct labeller *l)
|
||||
{
|
||||
dm_free(l);
|
||||
}
|
||||
|
||||
struct label_ops _lvm1_ops = {
|
||||
can_handle:_can_handle,
|
||||
write:_write,
|
||||
read:_read,
|
||||
verify:_can_handle,
|
||||
initialise_label:_initialise_label,
|
||||
destroy_label:_destroy_label,
|
||||
destroy:_destroy
|
||||
can_handle:_lvm1_can_handle,
|
||||
write:_lvm1_write,
|
||||
read:_lvm1_read,
|
||||
verify:_lvm1_can_handle,
|
||||
initialise_label:_lvm1_initialise_label,
|
||||
destroy_label:_lvm1_destroy_label,
|
||||
destroy:_lvm1_destroy
|
||||
};
|
||||
|
||||
struct labeller *lvm1_labeller_create(struct format_type *fmt)
|
||||
|
||||
@@ -98,7 +98,7 @@ int read_pool_label(struct pool_list *pl, struct labeller *l,
|
||||
log_debug("Calculated uuid %s for %s", uuid, pd->pl_pool_name);
|
||||
|
||||
if (!(info = lvmcache_add(l, (char *) &pvid, dev, pd->pl_pool_name,
|
||||
(char *) &vgid))) {
|
||||
(char *) &vgid, 0))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -314,7 +314,7 @@ int read_pool_pds(const struct format_type *fmt, const char *vg_name,
|
||||
/*
|
||||
* If the cache scanning doesn't work, this will never work
|
||||
*/
|
||||
if (vg_name && (vginfo = vginfo_from_vgname(vg_name)) &&
|
||||
if (vg_name && (vginfo = vginfo_from_vgname(vg_name, NULL)) &&
|
||||
vginfo->infos.n) {
|
||||
|
||||
if (_read_vg_pds(fmt, mem, vginfo, pdhead, &totaldevs)) {
|
||||
|
||||
@@ -169,7 +169,7 @@ static struct volume_group *_build_vg_from_pds(struct format_instance
|
||||
return vg;
|
||||
}
|
||||
|
||||
static struct volume_group *_vg_read(struct format_instance *fid,
|
||||
static struct volume_group *_pool_vg_read(struct format_instance *fid,
|
||||
const char *vg_name,
|
||||
struct metadata_area *mda)
|
||||
{
|
||||
@@ -206,7 +206,7 @@ static struct volume_group *_vg_read(struct format_instance *fid,
|
||||
return vg;
|
||||
}
|
||||
|
||||
static int _pv_setup(const struct format_type *fmt,
|
||||
static int _pool_pv_setup(const struct format_type *fmt,
|
||||
uint64_t pe_start, uint32_t extent_count,
|
||||
uint32_t extent_size,
|
||||
int pvmetadatacopies,
|
||||
@@ -216,7 +216,7 @@ static int _pv_setup(const struct format_type *fmt,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _pv_read(const struct format_type *fmt, const char *pv_name,
|
||||
static int _pool_pv_read(const struct format_type *fmt, const char *pv_name,
|
||||
struct physical_volume *pv, struct list *mdas)
|
||||
{
|
||||
struct dm_pool *mem = dm_pool_create("pool pv_read", 1024);
|
||||
@@ -262,12 +262,13 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
static struct metadata_area_ops _metadata_format_pool_ops = {
|
||||
vg_read:_vg_read,
|
||||
vg_read:_pool_vg_read,
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
static struct format_instance *_create_instance(const struct format_type *fmt,
|
||||
static struct format_instance *_pool_create_instance(const struct format_type *fmt,
|
||||
const char *vgname,
|
||||
const char *vgid,
|
||||
void *private)
|
||||
{
|
||||
struct format_instance *fid;
|
||||
@@ -297,23 +298,23 @@ static struct format_instance *_create_instance(const struct format_type *fmt,
|
||||
return fid;
|
||||
}
|
||||
|
||||
static void _destroy_instance(struct format_instance *fid)
|
||||
static void _pool_destroy_instance(struct format_instance *fid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void _destroy(const struct format_type *fmt)
|
||||
static void _pool_destroy(const struct format_type *fmt)
|
||||
{
|
||||
dm_free((void *) fmt);
|
||||
}
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
static struct format_handler _format_pool_ops = {
|
||||
pv_read:_pv_read,
|
||||
pv_setup:_pv_setup,
|
||||
create_instance:_create_instance,
|
||||
destroy_instance:_destroy_instance,
|
||||
destroy:_destroy,
|
||||
pv_read:_pool_pv_read,
|
||||
pv_setup:_pool_pv_setup,
|
||||
create_instance:_pool_create_instance,
|
||||
destroy_instance:_pool_destroy_instance,
|
||||
destroy:_pool_destroy,
|
||||
};
|
||||
/* *INDENT-ON */
|
||||
|
||||
|
||||
@@ -165,6 +165,7 @@ int import_pool_pv(const struct format_type *fmt, struct dm_pool *mem,
|
||||
log_error("Unable to duplicate vg_name string");
|
||||
return 0;
|
||||
}
|
||||
memcpy(&pv->vgid, &vg->id, sizeof(vg->id));
|
||||
pv->status = 0;
|
||||
pv->size = pd->pl_blocks;
|
||||
pv->pe_size = POOL_PE_SIZE;
|
||||
|
||||
@@ -23,13 +23,13 @@
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
static void _not_supported(const char *op)
|
||||
static void _pool_not_supported(const char *op)
|
||||
{
|
||||
log_error("The '%s' operation is not supported for the pool labeller.",
|
||||
op);
|
||||
}
|
||||
|
||||
static int _can_handle(struct labeller *l, char *buf, uint64_t sector)
|
||||
static int _pool_can_handle(struct labeller *l, char *buf, uint64_t sector)
|
||||
{
|
||||
|
||||
struct pool_disk pd;
|
||||
@@ -50,13 +50,13 @@ static int _can_handle(struct labeller *l, char *buf, uint64_t sector)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _write(struct label *label, char *buf)
|
||||
static int _pool_write(struct label *label, char *buf)
|
||||
{
|
||||
_not_supported("write");
|
||||
_pool_not_supported("write");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _read(struct labeller *l, struct device *dev, char *buf,
|
||||
static int _pool_read(struct labeller *l, struct device *dev, char *buf,
|
||||
struct label **label)
|
||||
{
|
||||
struct pool_list pl;
|
||||
@@ -64,31 +64,31 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
|
||||
return read_pool_label(&pl, l, dev, buf, label);
|
||||
}
|
||||
|
||||
static int _initialise_label(struct labeller *l, struct label *label)
|
||||
static int _pool_initialise_label(struct labeller *l, struct label *label)
|
||||
{
|
||||
strcpy(label->type, "POOL");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _destroy_label(struct labeller *l, struct label *label)
|
||||
static void _pool_destroy_label(struct labeller *l, struct label *label)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static void _destroy(struct labeller *l)
|
||||
static void _label_pool_destroy(struct labeller *l)
|
||||
{
|
||||
dm_free(l);
|
||||
}
|
||||
|
||||
struct label_ops _pool_ops = {
|
||||
can_handle:_can_handle,
|
||||
write:_write,
|
||||
read:_read,
|
||||
verify:_can_handle,
|
||||
initialise_label:_initialise_label,
|
||||
destroy_label:_destroy_label,
|
||||
destroy:_destroy
|
||||
can_handle:_pool_can_handle,
|
||||
write:_pool_write,
|
||||
read:_pool_read,
|
||||
verify:_pool_can_handle,
|
||||
initialise_label:_pool_initialise_label,
|
||||
destroy_label:_pool_destroy_label,
|
||||
destroy:_label_pool_destroy
|
||||
};
|
||||
|
||||
struct labeller *pool_labeller_create(struct format_type *fmt)
|
||||
|
||||
@@ -87,7 +87,7 @@ static int _split_vg(const char *filename, char *vgname, size_t vg_size,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _insert_file(struct list *head, struct archive_file *b)
|
||||
static void _insert_archive_file(struct list *head, struct archive_file *b)
|
||||
{
|
||||
struct archive_file *bf = NULL;
|
||||
|
||||
@@ -107,7 +107,7 @@ static void _insert_file(struct list *head, struct archive_file *b)
|
||||
list_add_h(&bf->list, &b->list);
|
||||
}
|
||||
|
||||
static char *_join(struct dm_pool *mem, const char *dir, const char *name)
|
||||
static char *_join_file_to_dir(struct dm_pool *mem, const char *dir, const char *name)
|
||||
{
|
||||
if (!dm_pool_begin_object(mem, 32) ||
|
||||
!dm_pool_grow_object(mem, dir, strlen(dir)) ||
|
||||
@@ -161,7 +161,7 @@ static struct list *_scan_archive(struct dm_pool *mem,
|
||||
if (strcmp(vgname, vgname_found))
|
||||
continue;
|
||||
|
||||
if (!(path = _join(mem, dir, dirent[i]->d_name))) {
|
||||
if (!(path = _join_file_to_dir(mem, dir, dirent[i]->d_name))) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
@@ -181,7 +181,7 @@ static struct list *_scan_archive(struct dm_pool *mem,
|
||||
/*
|
||||
* Insert it to the correct part of the list.
|
||||
*/
|
||||
_insert_file(results, af);
|
||||
_insert_archive_file(results, af);
|
||||
}
|
||||
|
||||
out:
|
||||
@@ -207,8 +207,8 @@ static void _remove_expired(struct list *archives, uint32_t archives_size,
|
||||
/* Convert retain_days into the time after which we must retain */
|
||||
retain_time = time(NULL) - (time_t) retain_days *SECS_PER_DAY;
|
||||
|
||||
/* Assume list is ordered oldest first (by index) */
|
||||
list_iterate_items(bf, archives) {
|
||||
/* Assume list is ordered newest first (by index) */
|
||||
list_iterate_back_items(bf, archives) {
|
||||
/* Get the mtime of the file and unlink if too old */
|
||||
if (stat(bf->path, &sb)) {
|
||||
log_sys_error("stat", bf->path);
|
||||
@@ -311,7 +311,7 @@ static void _display_archive(struct cmd_context *cmd, struct archive_file *af)
|
||||
|
||||
if (!(context = create_text_context(cmd, af->path, NULL)) ||
|
||||
!(tf = cmd->fmt_backup->ops->create_instance(cmd->fmt_backup, NULL,
|
||||
context))) {
|
||||
NULL, context))) {
|
||||
log_error("Couldn't create text instance object.");
|
||||
return;
|
||||
}
|
||||
@@ -360,7 +360,7 @@ int backup_list(struct cmd_context *cmd, const char *dir, const char *vgname)
|
||||
{
|
||||
struct archive_file af;
|
||||
|
||||
if (!(af.path = _join(cmd->mem, dir, vgname))) {
|
||||
if (!(af.path = _join_file_to_dir(cmd->mem, dir, vgname))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -257,7 +257,7 @@ struct volume_group *backup_read_vg(struct cmd_context *cmd,
|
||||
if (!(context = create_text_context(cmd, file,
|
||||
cmd->cmd_line)) ||
|
||||
!(tf = cmd->fmt_backup->ops->create_instance(cmd->fmt_backup, NULL,
|
||||
context))) {
|
||||
NULL, context))) {
|
||||
log_error("Couldn't create text format object.");
|
||||
return NULL;
|
||||
}
|
||||
@@ -286,7 +286,7 @@ int backup_restore_vg(struct cmd_context *cmd, struct volume_group *vg)
|
||||
|
||||
/* Attempt to write out using currently active format */
|
||||
if (!(vg->fid = cmd->fmt->ops->create_instance(cmd->fmt, vg->name,
|
||||
NULL))) {
|
||||
NULL, NULL))) {
|
||||
log_error("Failed to allocate format instance");
|
||||
return 0;
|
||||
}
|
||||
@@ -365,7 +365,7 @@ int backup_to_file(const char *file, const char *desc, struct volume_group *vg)
|
||||
|
||||
if (!(context = create_text_context(cmd, file, desc)) ||
|
||||
!(tf = cmd->fmt_backup->ops->create_instance(cmd->fmt_backup, NULL,
|
||||
context))) {
|
||||
NULL, context))) {
|
||||
log_error("Couldn't create backup object.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -354,8 +354,7 @@ static int _print_vg(struct formatter *f, struct volume_group *vg)
|
||||
* Get the pv%d name from the formatters hash
|
||||
* table.
|
||||
*/
|
||||
static inline const char *_get_pv_name(struct formatter *f,
|
||||
struct physical_volume *pv)
|
||||
static const char *_get_pv_name(struct formatter *f, struct physical_volume *pv)
|
||||
{
|
||||
return (pv) ? (const char *)
|
||||
dm_hash_lookup(f->pv_names, dev_name(pv->dev)) : "Missing";
|
||||
|
||||
@@ -39,8 +39,9 @@
|
||||
#define FMT_TEXT_NAME "lvm2"
|
||||
#define FMT_TEXT_ALIAS "text"
|
||||
|
||||
static struct format_instance *_create_text_instance(const struct format_type
|
||||
static struct format_instance *_text_create_text_instance(const struct format_type
|
||||
*fmt, const char *vgname,
|
||||
const char *vgid,
|
||||
void *context);
|
||||
|
||||
struct text_fid_context {
|
||||
@@ -68,7 +69,7 @@ struct text_context {
|
||||
* NOTE: Currently there can be only one vg per text file.
|
||||
*/
|
||||
|
||||
static int _vg_setup(struct format_instance *fid, struct volume_group *vg)
|
||||
static int _text_vg_setup(struct format_instance *fid, struct volume_group *vg)
|
||||
{
|
||||
if (vg->extent_size & (vg->extent_size - 1)) {
|
||||
log_error("Extent size must be power of 2");
|
||||
@@ -78,7 +79,7 @@ static int _vg_setup(struct format_instance *fid, struct volume_group *vg)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _lv_setup(struct format_instance *fid, struct logical_volume *lv)
|
||||
static int _text_lv_setup(struct format_instance *fid, struct logical_volume *lv)
|
||||
{
|
||||
/******** FIXME Any LV size restriction?
|
||||
uint64_t max_size = UINT_MAX;
|
||||
@@ -219,7 +220,7 @@ static struct raw_locn *_find_vg_rlocn(struct device_area *dev_area,
|
||||
|
||||
error:
|
||||
if ((info = info_from_pvid(dev_area->dev->pvid)))
|
||||
lvmcache_update_vgname(info, ORPHAN);
|
||||
lvmcache_update_vgname_and_id(info, ORPHAN, ORPHAN, 0, NULL);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -858,9 +859,11 @@ static int _scan_file(const struct format_type *fmt)
|
||||
}
|
||||
|
||||
/* FIXME stat file to see if it's changed */
|
||||
fid = _create_text_instance(fmt, NULL, NULL);
|
||||
fid = _text_create_text_instance(fmt, NULL, NULL,
|
||||
NULL);
|
||||
if ((vg = _vg_read_file_name(fid, vgname,
|
||||
path)))
|
||||
/* FIXME Store creation host in vg */
|
||||
lvmcache_update_vg(vg);
|
||||
}
|
||||
|
||||
@@ -871,65 +874,92 @@ static int _scan_file(const struct format_type *fmt)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int vgname_from_mda(const struct format_type *fmt, struct device_area *dev_area,
|
||||
char *buf, uint32_t size)
|
||||
const char *vgname_from_mda(const struct format_type *fmt,
|
||||
struct device_area *dev_area, struct id *vgid,
|
||||
uint32_t *vgstatus, char **creation_host)
|
||||
{
|
||||
struct raw_locn *rlocn;
|
||||
struct mda_header *mdah;
|
||||
unsigned int len;
|
||||
int r = 0;
|
||||
uint32_t wrap = 0;
|
||||
const char *vgname = NULL;
|
||||
unsigned int len = 0;
|
||||
char buf[NAME_LEN + 1];
|
||||
|
||||
if (!dev_open(dev_area->dev)) {
|
||||
stack;
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(mdah = _raw_read_mda_header(fmt, dev_area))) {
|
||||
stack;
|
||||
if (!(mdah = _raw_read_mda_header(fmt, dev_area)))
|
||||
goto_out;
|
||||
|
||||
/* FIXME Cope with returning a list */
|
||||
rlocn = mdah->raw_locns;
|
||||
|
||||
/* Do quick check for a vgname */
|
||||
if (!dev_read(dev_area->dev, dev_area->start + rlocn->offset,
|
||||
NAME_LEN, buf))
|
||||
goto_out;
|
||||
|
||||
while (buf[len] && !isspace(buf[len]) && buf[len] != '{' &&
|
||||
len < (NAME_LEN - 1))
|
||||
len++;
|
||||
|
||||
buf[len] = '\0';
|
||||
|
||||
/* Ignore this entry if the characters aren't permissible */
|
||||
if (!validate_name(buf))
|
||||
goto_out;
|
||||
|
||||
/* We found a VG - now check the metadata */
|
||||
if (rlocn->offset + rlocn->size > mdah->size)
|
||||
wrap = (uint32_t) ((rlocn->offset + rlocn->size) - mdah->size);
|
||||
|
||||
if (wrap > rlocn->offset) {
|
||||
log_error("%s: metadata too large for circular buffer",
|
||||
dev_name(dev_area->dev));
|
||||
goto out;
|
||||
}
|
||||
|
||||
rlocn = mdah->raw_locns;
|
||||
/* FIXME 64-bit */
|
||||
if (!(vgname = text_vgname_import(fmt, dev_area->dev,
|
||||
(off_t) (dev_area->start +
|
||||
rlocn->offset),
|
||||
(uint32_t) (rlocn->size - wrap),
|
||||
(off_t) (dev_area->start +
|
||||
MDA_HEADER_SIZE),
|
||||
wrap, calc_crc, rlocn->checksum,
|
||||
vgid, vgstatus, creation_host)))
|
||||
goto_out;
|
||||
|
||||
while (rlocn->offset) {
|
||||
if (!dev_read(dev_area->dev, dev_area->start + rlocn->offset,
|
||||
size, buf)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
len = 0;
|
||||
while (buf[len] && !isspace(buf[len]) && buf[len] != '{' &&
|
||||
len < (size - 1))
|
||||
len++;
|
||||
buf[len] = '\0';
|
||||
|
||||
/* Ignore this entry if the characters aren't permissible */
|
||||
if (!validate_name(buf)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
|
||||
r = 1;
|
||||
break;
|
||||
|
||||
/* FIXME Cope with returning a list */
|
||||
rlocn++;
|
||||
/* Ignore this entry if the characters aren't permissible */
|
||||
if (!validate_name(vgname)) {
|
||||
stack;
|
||||
vgname = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
log_debug("%s: Found metadata at %" PRIu64 " size %" PRIu64
|
||||
" for %s (%s)",
|
||||
dev_name(dev_area->dev), dev_area->start + rlocn->offset,
|
||||
rlocn->size, vgname, vgid->uuid);
|
||||
|
||||
out:
|
||||
if (!dev_close(dev_area->dev))
|
||||
stack;
|
||||
|
||||
return r;
|
||||
return vgname;
|
||||
}
|
||||
|
||||
static int _scan_raw(const struct format_type *fmt)
|
||||
{
|
||||
struct raw_list *rl;
|
||||
struct list *raw_list;
|
||||
char vgnamebuf[NAME_LEN + 2];
|
||||
const char *vgname;
|
||||
struct volume_group *vg;
|
||||
struct format_instance fid;
|
||||
struct id vgid;
|
||||
uint32_t vgstatus;
|
||||
|
||||
raw_list = &((struct mda_lists *) fmt->private)->raws;
|
||||
|
||||
@@ -938,9 +968,9 @@ static int _scan_raw(const struct format_type *fmt)
|
||||
|
||||
list_iterate_items(rl, raw_list) {
|
||||
/* FIXME We're reading mdah twice here... */
|
||||
if (vgname_from_mda(fmt, &rl->dev_area, vgnamebuf,
|
||||
sizeof(vgnamebuf))) {
|
||||
if ((vg = _vg_read_raw_area(&fid, vgnamebuf,
|
||||
if ((vgname = vgname_from_mda(fmt, &rl->dev_area, &vgid, &vgstatus,
|
||||
NULL))) {
|
||||
if ((vg = _vg_read_raw_area(&fid, vgname,
|
||||
&rl->dev_area, 0)))
|
||||
lvmcache_update_vg(vg);
|
||||
}
|
||||
@@ -949,7 +979,7 @@ static int _scan_raw(const struct format_type *fmt)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _scan(const struct format_type *fmt)
|
||||
static int _text_scan(const struct format_type *fmt)
|
||||
{
|
||||
return (_scan_file(fmt) & _scan_raw(fmt));
|
||||
}
|
||||
@@ -1095,7 +1125,7 @@ static int _mda_setup(const struct format_type *fmt,
|
||||
|
||||
/* Only for orphans */
|
||||
/* Set label_sector to -1 if rewriting existing label into same sector */
|
||||
static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
|
||||
static int _text_pv_write(const struct format_type *fmt, struct physical_volume *pv,
|
||||
struct list *mdas, int64_t label_sector)
|
||||
{
|
||||
struct label *label;
|
||||
@@ -1109,7 +1139,7 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
|
||||
/* FIXME Test mode don't update cache? */
|
||||
|
||||
if (!(info = lvmcache_add(fmt->labeller, (char *) &pv->id, pv->dev,
|
||||
ORPHAN, NULL))) {
|
||||
ORPHAN, NULL, 0))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -1220,7 +1250,7 @@ static int _add_raw(struct list *raw_list, struct device_area *dev_area)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _pv_read(const struct format_type *fmt, const char *pv_name,
|
||||
static int _text_pv_read(const struct format_type *fmt, const char *pv_name,
|
||||
struct physical_volume *pv, struct list *mdas)
|
||||
{
|
||||
struct label *label;
|
||||
@@ -1245,7 +1275,7 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
|
||||
/* Have we already cached vgname? */
|
||||
if (info->vginfo && info->vginfo->vgname && *info->vginfo->vgname &&
|
||||
get_pv_from_vg_by_id(info->fmt, info->vginfo->vgname,
|
||||
info->dev->pvid, pv)) {
|
||||
info->vginfo->vgid, info->dev->pvid, pv)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1256,6 +1286,7 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
|
||||
if (info->vginfo && info->vginfo->vgname &&
|
||||
*info->vginfo->vgname &&
|
||||
get_pv_from_vg_by_id(info->fmt, info->vginfo->vgname,
|
||||
info->vginfo->vgid,
|
||||
info->dev->pvid, pv)) {
|
||||
return 1;
|
||||
}
|
||||
@@ -1301,7 +1332,7 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _destroy_instance(struct format_instance *fid)
|
||||
static void _text_destroy_instance(struct format_instance *fid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -1326,7 +1357,7 @@ static void _free_raws(struct list *raw_list)
|
||||
}
|
||||
}
|
||||
|
||||
static void _destroy(const struct format_type *fmt)
|
||||
static void _text_destroy(const struct format_type *fmt)
|
||||
{
|
||||
if (fmt->private) {
|
||||
_free_dirs(&((struct mda_lists *) fmt->private)->dirs);
|
||||
@@ -1363,7 +1394,7 @@ static struct metadata_area_ops _metadata_text_raw_ops = {
|
||||
};
|
||||
|
||||
/* pvmetadatasize in sectors */
|
||||
static int _pv_setup(const struct format_type *fmt,
|
||||
static int _text_pv_setup(const struct format_type *fmt,
|
||||
uint64_t pe_start, uint32_t extent_count,
|
||||
uint32_t extent_size,
|
||||
int pvmetadatacopies,
|
||||
@@ -1380,7 +1411,7 @@ static int _pv_setup(const struct format_type *fmt,
|
||||
/* FIXME if vg, adjust start/end of pe area to avoid mdas! */
|
||||
|
||||
/* FIXME Cope with pvchange */
|
||||
/* FIXME Merge code with _create_text_instance */
|
||||
/* FIXME Merge code with _text_create_text_instance */
|
||||
|
||||
/* If new vg, add any further mdas on this PV to the fid's mda list */
|
||||
if (vg) {
|
||||
@@ -1448,8 +1479,9 @@ static int _pv_setup(const struct format_type *fmt,
|
||||
}
|
||||
|
||||
/* NULL vgname means use only the supplied context e.g. an archive file */
|
||||
static struct format_instance *_create_text_instance(const struct format_type
|
||||
static struct format_instance *_text_create_text_instance(const struct format_type
|
||||
*fmt, const char *vgname,
|
||||
const char *vgid,
|
||||
void *context)
|
||||
{
|
||||
struct format_instance *fid;
|
||||
@@ -1535,7 +1567,7 @@ static struct format_instance *_create_text_instance(const struct format_type
|
||||
|
||||
/* Scan PVs in VG for any further MDAs */
|
||||
lvmcache_label_scan(fmt->cmd, 0);
|
||||
if (!(vginfo = vginfo_from_vgname(vgname))) {
|
||||
if (!(vginfo = vginfo_from_vgname(vgname, vgid))) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
@@ -1569,7 +1601,6 @@ static struct format_instance *_create_text_instance(const struct format_type
|
||||
|
||||
out:
|
||||
return fid;
|
||||
|
||||
}
|
||||
|
||||
void *create_text_context(struct cmd_context *cmd, const char *path,
|
||||
@@ -1618,15 +1649,15 @@ void *create_text_context(struct cmd_context *cmd, const char *path,
|
||||
}
|
||||
|
||||
static struct format_handler _text_handler = {
|
||||
scan:_scan,
|
||||
pv_read:_pv_read,
|
||||
pv_setup:_pv_setup,
|
||||
pv_write:_pv_write,
|
||||
vg_setup:_vg_setup,
|
||||
lv_setup:_lv_setup,
|
||||
create_instance:_create_text_instance,
|
||||
destroy_instance:_destroy_instance,
|
||||
destroy:_destroy
|
||||
scan:_text_scan,
|
||||
pv_read:_text_pv_read,
|
||||
pv_setup:_text_pv_setup,
|
||||
pv_write:_text_pv_write,
|
||||
vg_setup:_text_vg_setup,
|
||||
lv_setup:_text_lv_setup,
|
||||
create_instance:_text_create_text_instance,
|
||||
destroy_instance:_text_destroy_instance,
|
||||
destroy:_text_destroy
|
||||
};
|
||||
|
||||
static int _add_dir(const char *dir, struct list *dir_list)
|
||||
|
||||
@@ -54,7 +54,8 @@ int add_mda(const struct format_type *fmt, struct dm_pool *mem, struct list *mda
|
||||
struct device *dev, uint64_t start, uint64_t size);
|
||||
void del_mdas(struct list *mdas);
|
||||
|
||||
int vgname_from_mda(const struct format_type *fmt, struct device_area *dev_area,
|
||||
char *buf, uint32_t size);
|
||||
const char *vgname_from_mda(const struct format_type *fmt,
|
||||
struct device_area *dev_area, struct id *vgid,
|
||||
uint32_t *vgstatus, char **creation_host);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -47,6 +47,10 @@ struct text_vg_version_ops {
|
||||
struct config_tree * cf);
|
||||
void (*read_desc) (struct dm_pool * mem, struct config_tree * cf,
|
||||
time_t *when, char **desc);
|
||||
const char *(*read_vgname) (const struct format_type *fmt,
|
||||
struct config_tree *cft,
|
||||
struct id *vgid, uint32_t *vgstatus,
|
||||
char **creation_host);
|
||||
};
|
||||
|
||||
struct text_vg_version_ops *text_vg_vsn1_init(void);
|
||||
@@ -70,5 +74,12 @@ struct volume_group *text_vg_import_fd(struct format_instance *fid,
|
||||
checksum_fn_t checksum_fn,
|
||||
uint32_t checksum,
|
||||
time_t *when, char **desc);
|
||||
const char *text_vgname_import(const struct format_type *fmt,
|
||||
struct device *dev,
|
||||
off_t offset, uint32_t size,
|
||||
off_t offset2, uint32_t size2,
|
||||
checksum_fn_t checksum_fn, uint32_t checksum,
|
||||
struct id *vgid, uint32_t *vgstatus,
|
||||
char **creation_host);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -23,6 +23,53 @@
|
||||
/* FIXME Use tidier inclusion method */
|
||||
static struct text_vg_version_ops *(_text_vsn_list[2]);
|
||||
|
||||
const char *text_vgname_import(const struct format_type *fmt,
|
||||
struct device *dev,
|
||||
off_t offset, uint32_t size,
|
||||
off_t offset2, uint32_t size2,
|
||||
checksum_fn_t checksum_fn, uint32_t checksum,
|
||||
struct id *vgid, uint32_t *vgstatus,
|
||||
char **creation_host)
|
||||
{
|
||||
struct config_tree *cft;
|
||||
struct text_vg_version_ops **vsn;
|
||||
const char *vgname;
|
||||
|
||||
static int _text_import_initialised = 0;
|
||||
|
||||
if (!_text_import_initialised) {
|
||||
_text_vsn_list[0] = text_vg_vsn1_init();
|
||||
_text_vsn_list[1] = NULL;
|
||||
_text_import_initialised = 1;
|
||||
}
|
||||
|
||||
if (!(cft = create_config_tree(NULL)))
|
||||
goto_out;
|
||||
|
||||
if ((!dev && !read_config_file(cft)) ||
|
||||
(dev && !read_config_fd(cft, dev, offset, size,
|
||||
offset2, size2, checksum_fn, checksum)))
|
||||
goto_out;
|
||||
|
||||
/*
|
||||
* Find a set of version functions that can read this file
|
||||
*/
|
||||
for (vsn = &_text_vsn_list[0]; *vsn; vsn++) {
|
||||
if (!(*vsn)->check_version(cft))
|
||||
continue;
|
||||
|
||||
if (!(vgname = (*vsn)->read_vgname(fmt, cft, vgid, vgstatus,
|
||||
creation_host)))
|
||||
goto_out;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
destroy_config_tree(cft);
|
||||
return vgname;
|
||||
}
|
||||
|
||||
struct volume_group *text_vg_import_fd(struct format_instance *fid,
|
||||
const char *file,
|
||||
struct device *dev,
|
||||
@@ -36,12 +83,12 @@ struct volume_group *text_vg_import_fd(struct format_instance *fid,
|
||||
struct config_tree *cft;
|
||||
struct text_vg_version_ops **vsn;
|
||||
|
||||
static int _initialised = 0;
|
||||
static int _text_vg_import_initialised = 0;
|
||||
|
||||
if (!_initialised) {
|
||||
if (!_text_vg_import_initialised) {
|
||||
_text_vsn_list[0] = text_vg_vsn1_init();
|
||||
_text_vsn_list[1] = NULL;
|
||||
_initialised = 1;
|
||||
_text_vg_import_initialised = 1;
|
||||
}
|
||||
|
||||
*desc = NULL;
|
||||
|
||||
@@ -167,6 +167,8 @@ static int _read_pv(struct format_instance *fid, struct dm_pool *mem,
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(&pv->vgid, &vg->id, sizeof(vg->id));
|
||||
|
||||
if (!(cn = find_config_node(pvn, "status"))) {
|
||||
log_error("Couldn't find status flags for physical volume.");
|
||||
return 0;
|
||||
@@ -798,10 +800,59 @@ static void _read_desc(struct dm_pool *mem,
|
||||
*when = u;
|
||||
}
|
||||
|
||||
static const char *_read_vgname(const struct format_type *fmt,
|
||||
struct config_tree *cft, struct id *vgid,
|
||||
uint32_t *vgstatus, char **creation_host)
|
||||
{
|
||||
struct config_node *vgn, *cn;
|
||||
struct dm_pool *mem = fmt->cmd->mem;
|
||||
char *vgname;
|
||||
int old_suppress;
|
||||
|
||||
old_suppress = log_suppress(2);
|
||||
*creation_host = dm_pool_strdup(mem,
|
||||
find_config_str(cft->root,
|
||||
"creation_host", ""));
|
||||
log_suppress(old_suppress);
|
||||
|
||||
/* skip any top-level values */
|
||||
for (vgn = cft->root; (vgn && vgn->v); vgn = vgn->sib) ;
|
||||
|
||||
if (!vgn) {
|
||||
log_error("Couldn't find volume group in file.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(vgname = dm_pool_strdup(mem, vgn->key)))
|
||||
return_0;
|
||||
|
||||
vgn = vgn->child;
|
||||
|
||||
if (!_read_id(vgid, vgn, "id")) {
|
||||
log_error("Couldn't read uuid for volume group %s.", vgname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(cn = find_config_node(vgn, "status"))) {
|
||||
log_error("Couldn't find status flags for volume group %s.",
|
||||
vgname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(read_flags(vgstatus, VG_FLAGS, cn->v))) {
|
||||
log_error("Couldn't read status flags for volume group %s.",
|
||||
vgname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return vgname;
|
||||
}
|
||||
|
||||
static struct text_vg_version_ops _vsn1_ops = {
|
||||
check_version:_check_version,
|
||||
read_vg:_read_vg,
|
||||
read_desc:_read_desc
|
||||
read_desc:_read_desc,
|
||||
read_vgname:_read_vgname
|
||||
};
|
||||
|
||||
struct text_vg_version_ops *text_vg_vsn1_init(void)
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
static int _can_handle(struct labeller *l, char *buf, uint64_t sector)
|
||||
static int _text_can_handle(struct labeller *l, char *buf, uint64_t sector)
|
||||
{
|
||||
struct label_header *lh = (struct label_header *) buf;
|
||||
|
||||
@@ -33,7 +33,7 @@ static int _can_handle(struct labeller *l, char *buf, uint64_t sector)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _write(struct label *label, char *buf)
|
||||
static int _text_write(struct label *label, char *buf)
|
||||
{
|
||||
struct label_header *lh = (struct label_header *) buf;
|
||||
struct pv_header *pvhdr;
|
||||
@@ -179,14 +179,14 @@ void del_mdas(struct list *mdas)
|
||||
}
|
||||
}
|
||||
|
||||
static int _initialise_label(struct labeller *l, struct label *label)
|
||||
static int _text_initialise_label(struct labeller *l, struct label *label)
|
||||
{
|
||||
strncpy(label->type, LVM2_LABEL, sizeof(label->type));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _read(struct labeller *l, struct device *dev, char *buf,
|
||||
static int _text_read(struct labeller *l, struct device *dev, char *buf,
|
||||
struct label **label)
|
||||
{
|
||||
struct label_header *lh = (struct label_header *) buf;
|
||||
@@ -195,13 +195,16 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
|
||||
struct disk_locn *dlocn_xl;
|
||||
uint64_t offset;
|
||||
struct metadata_area *mda;
|
||||
char vgnamebuf[NAME_LEN + 2];
|
||||
struct id vgid;
|
||||
struct mda_context *mdac;
|
||||
const char *vgname;
|
||||
uint32_t vgstatus;
|
||||
char *creation_host;
|
||||
|
||||
pvhdr = (struct pv_header *) ((void *) buf + xlate32(lh->offset_xl));
|
||||
|
||||
if (!(info = lvmcache_add(l, pvhdr->pv_uuid, dev, NULL, NULL)))
|
||||
return 0;
|
||||
if (!(info = lvmcache_add(l, pvhdr->pv_uuid, dev, NULL, NULL, 0)))
|
||||
return_0;
|
||||
*label = info->label;
|
||||
|
||||
info->device_size = xlate64(pvhdr->device_size_xl);
|
||||
@@ -232,10 +235,12 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
|
||||
|
||||
list_iterate_items(mda, &info->mdas) {
|
||||
mdac = (struct mda_context *) mda->metadata_locn;
|
||||
if (vgname_from_mda(info->fmt, &mdac->area, vgnamebuf,
|
||||
sizeof(vgnamebuf))) {
|
||||
lvmcache_update_vgname(info, vgnamebuf);
|
||||
}
|
||||
if ((vgname = vgname_from_mda(info->fmt, &mdac->area,
|
||||
&vgid, &vgstatus, &creation_host)) &&
|
||||
!lvmcache_update_vgname_and_id(info, vgname,
|
||||
(char *) &vgid, vgstatus,
|
||||
creation_host))
|
||||
return_0;
|
||||
}
|
||||
|
||||
info->status &= ~CACHE_INVALID;
|
||||
@@ -243,7 +248,7 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _destroy_label(struct labeller *l, struct label *label)
|
||||
static void _text_destroy_label(struct labeller *l, struct label *label)
|
||||
{
|
||||
struct lvmcache_info *info = (struct lvmcache_info *) label->info;
|
||||
|
||||
@@ -253,19 +258,19 @@ static void _destroy_label(struct labeller *l, struct label *label)
|
||||
del_das(&info->das);
|
||||
}
|
||||
|
||||
static void _destroy(struct labeller *l)
|
||||
static void _fmt_text_destroy(struct labeller *l)
|
||||
{
|
||||
dm_free(l);
|
||||
}
|
||||
|
||||
struct label_ops _text_ops = {
|
||||
can_handle:_can_handle,
|
||||
write:_write,
|
||||
read:_read,
|
||||
verify:_can_handle,
|
||||
initialise_label:_initialise_label,
|
||||
destroy_label:_destroy_label,
|
||||
destroy:_destroy
|
||||
can_handle:_text_can_handle,
|
||||
write:_text_write,
|
||||
read:_text_read,
|
||||
verify:_text_can_handle,
|
||||
initialise_label:_text_initialise_label,
|
||||
destroy_label:_text_destroy_label,
|
||||
destroy:_fmt_text_destroy
|
||||
};
|
||||
|
||||
struct labeller *text_labeller_create(const struct format_type *fmt)
|
||||
|
||||
@@ -117,15 +117,6 @@ static struct labeller *_find_labeller(struct device *dev, char *buf,
|
||||
int found = 0;
|
||||
char readbuf[LABEL_SCAN_SIZE];
|
||||
|
||||
if (!dev_open(dev)) {
|
||||
stack;
|
||||
|
||||
if ((info = info_from_pvid(dev->pvid)))
|
||||
lvmcache_update_vgname(info, ORPHAN);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!dev_read(dev, UINT64_C(0), LABEL_SCAN_SIZE, readbuf)) {
|
||||
log_debug("%s: Failed to read label area", dev_name(dev));
|
||||
goto out;
|
||||
@@ -184,13 +175,11 @@ static struct labeller *_find_labeller(struct device *dev, char *buf,
|
||||
out:
|
||||
if (!found) {
|
||||
if ((info = info_from_pvid(dev->pvid)))
|
||||
lvmcache_update_vgname(info, ORPHAN);
|
||||
lvmcache_update_vgname_and_id(info, ORPHAN, ORPHAN,
|
||||
0, NULL);
|
||||
log_very_verbose("%s: No label detected", dev_name(dev));
|
||||
}
|
||||
|
||||
if (!dev_close(dev))
|
||||
stack;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -272,16 +261,29 @@ int label_read(struct device *dev, struct label **result)
|
||||
char buf[LABEL_SIZE];
|
||||
struct labeller *l;
|
||||
uint64_t sector;
|
||||
int r;
|
||||
struct lvmcache_info *info;
|
||||
int r = 0;
|
||||
|
||||
if (!(l = _find_labeller(dev, buf, §or))) {
|
||||
if (!dev_open(dev)) {
|
||||
stack;
|
||||
return 0;
|
||||
|
||||
if ((info = info_from_pvid(dev->pvid)))
|
||||
lvmcache_update_vgname_and_id(info, ORPHAN, ORPHAN,
|
||||
0, NULL);
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!(l = _find_labeller(dev, buf, §or)))
|
||||
goto_out;
|
||||
|
||||
if ((r = (l->ops->read)(l, dev, buf, result)) && result && *result)
|
||||
(*result)->sector = sector;
|
||||
|
||||
out:
|
||||
if (!dev_close(dev))
|
||||
stack;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -335,18 +337,35 @@ int label_write(struct device *dev, struct label *label)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Unused */
|
||||
int label_verify(struct device *dev)
|
||||
{
|
||||
struct labeller *l;
|
||||
char buf[LABEL_SIZE];
|
||||
uint64_t sector;
|
||||
struct lvmcache_info *info;
|
||||
int r = 0;
|
||||
|
||||
if (!(l = _find_labeller(dev, buf, §or))) {
|
||||
if (!dev_open(dev)) {
|
||||
stack;
|
||||
return 0;
|
||||
|
||||
if ((info = info_from_pvid(dev->pvid)))
|
||||
lvmcache_update_vgname_and_id(info, ORPHAN, ORPHAN,
|
||||
0, NULL);
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
return ((l->ops->verify) ? l->ops->verify(l, buf, sector) : 1);
|
||||
if (!(l = _find_labeller(dev, buf, §or)))
|
||||
goto_out;
|
||||
|
||||
r = l->ops->verify ? l->ops->verify(l, buf, sector) : 1;
|
||||
|
||||
out:
|
||||
if (!dev_close(dev))
|
||||
stack;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void label_destroy(struct label *label)
|
||||
|
||||
@@ -330,6 +330,9 @@ static int _lock_for_cluster(unsigned char cmd, unsigned int flags, char *name)
|
||||
args[0] = flags & 0x7F; /* Maskoff lock flags */
|
||||
args[1] = flags & 0xC0; /* Bitmap flags */
|
||||
|
||||
if (partial_mode())
|
||||
args[1] |= LCK_PARTIAL_MODE;
|
||||
|
||||
/*
|
||||
* VG locks are just that: locks, and have no side effects
|
||||
* so we only need to do them on the local node because all
|
||||
|
||||
@@ -72,7 +72,7 @@ int init_external_locking(struct locking_type *locking, struct config_tree *cft)
|
||||
libname = find_config_str(cft->root, "global/locking_library",
|
||||
DEFAULT_LOCKING_LIB);
|
||||
|
||||
if (!(_locking_lib = load_shared_library(cft, libname, "locking"))) {
|
||||
if (!(_locking_lib = load_shared_library(cft, libname, "locking", 1))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ void reset_locking(void)
|
||||
_unblock_signals();
|
||||
}
|
||||
|
||||
static inline void _update_vg_lock_count(int flags)
|
||||
static void _update_vg_lock_count(int flags)
|
||||
{
|
||||
if ((flags & LCK_SCOPE_MASK) != LCK_VG)
|
||||
return;
|
||||
|
||||
@@ -67,6 +67,11 @@ int check_lvm1_vg_inactive(struct cmd_context *cmd, const char *vgname);
|
||||
#define LCK_LOCAL 0x00000040 /* Don't propagate to other nodes */
|
||||
#define LCK_CLUSTER_VG 0x00000080 /* VG is clustered */
|
||||
|
||||
/*
|
||||
* Additional lock bits for cluster communication
|
||||
*/
|
||||
#define LCK_PARTIAL_MODE 0x00000001 /* Running in partial mode */
|
||||
|
||||
/*
|
||||
* Common combinations
|
||||
*/
|
||||
|
||||
@@ -90,9 +90,13 @@ void init_syslog(int facility)
|
||||
_syslog = 1;
|
||||
}
|
||||
|
||||
void log_suppress(int suppress)
|
||||
int log_suppress(int suppress)
|
||||
{
|
||||
int old_suppress = _log_suppress;
|
||||
|
||||
_log_suppress = suppress;
|
||||
|
||||
return old_suppress;
|
||||
}
|
||||
|
||||
void release_log_memory(void)
|
||||
@@ -253,6 +257,9 @@ void print_log(int level, const char *file, int line, const char *format, ...)
|
||||
const char *message;
|
||||
const char *trformat; /* Translated format string */
|
||||
|
||||
if (_log_suppress == 2)
|
||||
return;
|
||||
|
||||
trformat = _(format);
|
||||
|
||||
if (_lvm2_log_fn) {
|
||||
|
||||
@@ -86,8 +86,9 @@ int ignorelockingfailure(void);
|
||||
int lockingfailed(void);
|
||||
int security_level(void);
|
||||
|
||||
/* Suppress messages to stdout/stderr */
|
||||
void log_suppress(int suppress);
|
||||
/* Suppress messages to stdout/stderr (1) or everywhere (2) */
|
||||
/* Returns previous setting */
|
||||
int log_suppress(int suppress);
|
||||
|
||||
/* Suppress messages to syslog */
|
||||
void syslog_suppress(int suppress);
|
||||
|
||||
@@ -717,7 +717,7 @@ static int _find_parallel_space(struct alloc_handle *ah, alloc_policy_t alloc,
|
||||
next_le = (prev_lvseg ? prev_lvseg->le + prev_lvseg->len : 0) + *allocated;
|
||||
if (next_le >= spvs->le) {
|
||||
if (next_le + max_parallel > spvs->le + spvs->len)
|
||||
max_parallel = spvs->le + spvs->len - next_le;
|
||||
max_parallel = (spvs->le + spvs->len - next_le) * ah->area_multiple;
|
||||
parallel_pvs = &spvs->pvs;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -71,6 +71,8 @@ static int _add_pv_to_vg(struct format_instance *fid, struct volume_group *vg,
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(&pv->vgid, &vg->id, sizeof(vg->id));
|
||||
|
||||
/* Units of 512-byte sectors */
|
||||
pv->pe_size = vg->extent_size;
|
||||
|
||||
@@ -143,13 +145,14 @@ static int _copy_pv(struct physical_volume *pv_to,
|
||||
}
|
||||
|
||||
int get_pv_from_vg_by_id(const struct format_type *fmt, const char *vg_name,
|
||||
const char *id, struct physical_volume *pv)
|
||||
const char *vgid, const char *pvid,
|
||||
struct physical_volume *pv)
|
||||
{
|
||||
struct volume_group *vg;
|
||||
struct pv_list *pvl;
|
||||
int consistent = 0;
|
||||
|
||||
if (!(vg = vg_read(fmt->cmd, vg_name, &consistent))) {
|
||||
if (!(vg = vg_read(fmt->cmd, vg_name, vgid, &consistent))) {
|
||||
log_error("get_pv_from_vg_by_id: vg_read failed to read VG %s",
|
||||
vg_name);
|
||||
return 0;
|
||||
@@ -160,7 +163,7 @@ int get_pv_from_vg_by_id(const struct format_type *fmt, const char *vg_name,
|
||||
vg_name);
|
||||
|
||||
list_iterate_items(pvl, &vg->pvs) {
|
||||
if (id_equal(&pvl->pv->id, (const struct id *) id)) {
|
||||
if (id_equal(&pvl->pv->id, (const struct id *) pvid)) {
|
||||
if (!_copy_pv(pv, pvl->pv)) {
|
||||
stack;
|
||||
return 0;
|
||||
@@ -239,7 +242,7 @@ struct volume_group *vg_create(struct cmd_context *cmd, const char *vg_name,
|
||||
/* is this vg name already in use ? */
|
||||
old_partial = partial_mode();
|
||||
init_partial(1);
|
||||
if (vg_read(cmd, vg_name, &consistent)) {
|
||||
if (vg_read(cmd, vg_name, NULL, &consistent)) {
|
||||
log_err("A volume group called '%s' already exists.", vg_name);
|
||||
goto bad;
|
||||
}
|
||||
@@ -286,7 +289,7 @@ struct volume_group *vg_create(struct cmd_context *cmd, const char *vg_name,
|
||||
list_init(&vg->tags);
|
||||
|
||||
if (!(vg->fid = cmd->fmt->ops->create_instance(cmd->fmt, vg_name,
|
||||
NULL))) {
|
||||
NULL, NULL))) {
|
||||
log_error("Failed to create format instance");
|
||||
goto bad;
|
||||
}
|
||||
@@ -496,7 +499,7 @@ struct physical_volume *pv_create(const struct format_type *fmt,
|
||||
uint64_t pvmetadatasize, struct list *mdas)
|
||||
{
|
||||
struct dm_pool *mem = fmt->cmd->mem;
|
||||
struct physical_volume *pv = dm_pool_alloc(mem, sizeof(*pv));
|
||||
struct physical_volume *pv = dm_pool_zalloc(mem, sizeof(*pv));
|
||||
|
||||
if (!pv) {
|
||||
stack;
|
||||
@@ -862,7 +865,7 @@ static struct volume_group *_vg_read_orphans(struct cmd_context *cmd)
|
||||
struct volume_group *vg;
|
||||
struct physical_volume *pv;
|
||||
|
||||
if (!(vginfo = vginfo_from_vgname(ORPHAN))) {
|
||||
if (!(vginfo = vginfo_from_vgname(ORPHAN, NULL))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
@@ -907,6 +910,7 @@ static struct volume_group *_vg_read_orphans(struct cmd_context *cmd)
|
||||
*/
|
||||
static struct volume_group *_vg_read(struct cmd_context *cmd,
|
||||
const char *vgname,
|
||||
const char *vgid,
|
||||
int *consistent, int precommitted)
|
||||
{
|
||||
struct format_instance *fid;
|
||||
@@ -928,15 +932,15 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
|
||||
|
||||
/* Find the vgname in the cache */
|
||||
/* If it's not there we must do full scan to be completely sure */
|
||||
if (!(fmt = fmt_from_vgname(vgname))) {
|
||||
if (!(fmt = fmt_from_vgname(vgname, vgid))) {
|
||||
lvmcache_label_scan(cmd, 0);
|
||||
if (!(fmt = fmt_from_vgname(vgname))) {
|
||||
if (!(fmt = fmt_from_vgname(vgname, vgid))) {
|
||||
if (memlock()) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
lvmcache_label_scan(cmd, 2);
|
||||
if (!(fmt = fmt_from_vgname(vgname))) {
|
||||
if (!(fmt = fmt_from_vgname(vgname, vgid))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
@@ -947,7 +951,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
|
||||
use_precommitted = 0;
|
||||
|
||||
/* create format instance with appropriate metadata area */
|
||||
if (!(fid = fmt->ops->create_instance(fmt, vgname, NULL))) {
|
||||
if (!(fid = fmt->ops->create_instance(fmt, vgname, vgid, NULL))) {
|
||||
log_error("Failed to create format instance");
|
||||
return NULL;
|
||||
}
|
||||
@@ -978,7 +982,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
|
||||
inconsistent = 0;
|
||||
|
||||
lvmcache_label_scan(cmd, 2);
|
||||
if (!(fmt = fmt_from_vgname(vgname))) {
|
||||
if (!(fmt = fmt_from_vgname(vgname, vgid))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
@@ -987,7 +991,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
|
||||
use_precommitted = 0;
|
||||
|
||||
/* create format instance with appropriate metadata area */
|
||||
if (!(fid = fmt->ops->create_instance(fmt, vgname, NULL))) {
|
||||
if (!(fid = fmt->ops->create_instance(fmt, vgname, vgid, NULL))) {
|
||||
log_error("Failed to create format instance");
|
||||
return NULL;
|
||||
}
|
||||
@@ -1069,12 +1073,12 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
|
||||
}
|
||||
|
||||
struct volume_group *vg_read(struct cmd_context *cmd, const char *vgname,
|
||||
int *consistent)
|
||||
const char *vgid, int *consistent)
|
||||
{
|
||||
struct volume_group *vg;
|
||||
struct lv_list *lvl;
|
||||
|
||||
if (!(vg = _vg_read(cmd, vgname, consistent, 0)))
|
||||
if (!(vg = _vg_read(cmd, vgname, vgid, consistent, 0)))
|
||||
return NULL;
|
||||
|
||||
if (!check_pv_segments(vg)) {
|
||||
@@ -1112,7 +1116,7 @@ static struct volume_group *_vg_read_by_vgid(struct cmd_context *cmd,
|
||||
/* Is corresponding vgname already cached? */
|
||||
if ((vginfo = vginfo_from_vgid(vgid)) &&
|
||||
vginfo->vgname && *vginfo->vgname) {
|
||||
if ((vg = _vg_read(cmd, vginfo->vgname,
|
||||
if ((vg = _vg_read(cmd, vginfo->vgname, vgid,
|
||||
&consistent, precommitted)) &&
|
||||
!strncmp(vg->id.uuid, vgid, ID_LEN)) {
|
||||
if (!consistent) {
|
||||
@@ -1143,7 +1147,7 @@ static struct volume_group *_vg_read_by_vgid(struct cmd_context *cmd,
|
||||
if (!vgname || !*vgname)
|
||||
continue; // FIXME Unnecessary?
|
||||
consistent = 0;
|
||||
if ((vg = _vg_read(cmd, vgname, &consistent,
|
||||
if ((vg = _vg_read(cmd, vgname, vgid, &consistent,
|
||||
precommitted)) &&
|
||||
!strncmp(vg->id.uuid, vgid, ID_LEN)) {
|
||||
if (!consistent) {
|
||||
@@ -1245,13 +1249,18 @@ struct list *get_vgs(struct cmd_context *cmd, int full_scan)
|
||||
return lvmcache_get_vgnames(cmd, full_scan);
|
||||
}
|
||||
|
||||
struct list *get_vgids(struct cmd_context *cmd, int full_scan)
|
||||
{
|
||||
return lvmcache_get_vgids(cmd, full_scan);
|
||||
}
|
||||
|
||||
struct list *get_pvs(struct cmd_context *cmd)
|
||||
{
|
||||
struct str_list *strl;
|
||||
struct list *results;
|
||||
const char *vgname;
|
||||
const char *vgname, *vgid;
|
||||
struct list *pvh, *tmp;
|
||||
struct list *vgnames;
|
||||
struct list *vgids;
|
||||
struct volume_group *vg;
|
||||
int consistent = 0;
|
||||
int old_partial;
|
||||
@@ -1267,7 +1276,7 @@ struct list *get_pvs(struct cmd_context *cmd)
|
||||
list_init(results);
|
||||
|
||||
/* Get list of VGs */
|
||||
if (!(vgnames = get_vgs(cmd, 0))) {
|
||||
if (!(vgids = get_vgids(cmd, 0))) {
|
||||
log_error("get_pvs: get_vgs failed");
|
||||
return NULL;
|
||||
}
|
||||
@@ -1278,12 +1287,16 @@ struct list *get_pvs(struct cmd_context *cmd)
|
||||
old_pvmove = pvmove_mode();
|
||||
init_partial(1);
|
||||
init_pvmove(1);
|
||||
list_iterate_items(strl, vgnames) {
|
||||
vgname = strl->str;
|
||||
if (!vgname)
|
||||
list_iterate_items(strl, vgids) {
|
||||
vgid = strl->str;
|
||||
if (!vgid)
|
||||
continue; /* FIXME Unnecessary? */
|
||||
consistent = 0;
|
||||
if (!(vg = vg_read(cmd, vgname, &consistent))) {
|
||||
if (!(vgname = vgname_from_vgid(NULL, vgid))) {
|
||||
stack;
|
||||
continue;
|
||||
}
|
||||
if (!(vg = vg_read(cmd, vgname, vgid, &consistent))) {
|
||||
stack;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -23,9 +23,9 @@
|
||||
|
||||
#include "ctype.h"
|
||||
#include "dev-cache.h"
|
||||
#include "lvm-string.h"
|
||||
#include "uuid.h"
|
||||
|
||||
#define NAME_LEN 128
|
||||
#define MAX_STRIPES 128
|
||||
#define SECTOR_SHIFT 9L
|
||||
#define SECTOR_SIZE ( 1L << SECTOR_SHIFT )
|
||||
@@ -122,6 +122,7 @@ struct physical_volume {
|
||||
struct device *dev;
|
||||
const struct format_type *fmt;
|
||||
const char *vg_name;
|
||||
struct id vgid;
|
||||
|
||||
uint32_t status;
|
||||
uint64_t size;
|
||||
@@ -382,6 +383,7 @@ struct format_handler {
|
||||
*/
|
||||
struct format_instance *(*create_instance) (const struct format_type *
|
||||
fmt, const char *vgname,
|
||||
const char *vgid,
|
||||
void *context);
|
||||
|
||||
/*
|
||||
@@ -403,7 +405,7 @@ int vg_write(struct volume_group *vg);
|
||||
int vg_commit(struct volume_group *vg);
|
||||
int vg_revert(struct volume_group *vg);
|
||||
struct volume_group *vg_read(struct cmd_context *cmd, const char *vg_name,
|
||||
int *consistent);
|
||||
const char *vgid, int *consistent);
|
||||
struct physical_volume *pv_read(struct cmd_context *cmd, const char *pv_name,
|
||||
struct list *mdas, uint64_t *label_sector,
|
||||
int warnings);
|
||||
@@ -411,6 +413,7 @@ struct list *get_pvs(struct cmd_context *cmd);
|
||||
|
||||
/* Set full_scan to 1 to re-read every (filtered) device label */
|
||||
struct list *get_vgs(struct cmd_context *cmd, int full_scan);
|
||||
struct list *get_vgids(struct cmd_context *cmd, int full_scan);
|
||||
|
||||
int pv_write(struct cmd_context *cmd, struct physical_volume *pv,
|
||||
struct list *mdas, int64_t label_sector);
|
||||
@@ -478,7 +481,8 @@ struct pv_list *find_pv_in_vg(struct volume_group *vg, const char *pv_name);
|
||||
struct physical_volume *find_pv_in_vg_by_uuid(struct volume_group *vg,
|
||||
struct id *id);
|
||||
int get_pv_from_vg_by_id(const struct format_type *fmt, const char *vg_name,
|
||||
const char *id, struct physical_volume *pv);
|
||||
const char *vgid, const char *pvid,
|
||||
struct physical_volume *pv);
|
||||
|
||||
/* Find an LV within a given VG */
|
||||
struct lv_list *find_lv_in_vg(struct volume_group *vg, const char *lv_name);
|
||||
@@ -535,11 +539,16 @@ int lv_split_segment(struct logical_volume *lv, uint32_t le);
|
||||
*/
|
||||
int lv_is_origin(const struct logical_volume *lv);
|
||||
int lv_is_cow(const struct logical_volume *lv);
|
||||
int lv_is_visible(const struct logical_volume *lv);
|
||||
|
||||
int pv_is_in_vg(struct volume_group *vg, struct physical_volume *pv);
|
||||
|
||||
/* Given a cow LV, return return the snapshot lv_segment that uses it */
|
||||
struct lv_segment *find_cow(const struct logical_volume *lv);
|
||||
|
||||
/* Given a cow LV, return its origin */
|
||||
struct logical_volume *origin_from_cow(const struct logical_volume *lv);
|
||||
|
||||
int vg_add_snapshot(struct format_instance *fid, const char *name,
|
||||
struct logical_volume *origin, struct logical_volume *cow,
|
||||
union lvid *lvid, uint32_t extent_count,
|
||||
@@ -600,29 +609,4 @@ uint32_t find_free_lvnum(struct logical_volume *lv);
|
||||
char *generate_lv_name(struct volume_group *vg, const char *format,
|
||||
char *buffer, size_t len);
|
||||
|
||||
static inline int validate_name(const char *n)
|
||||
{
|
||||
register char c;
|
||||
register int len = 0;
|
||||
|
||||
if (!n || !*n)
|
||||
return 0;
|
||||
|
||||
/* Hyphen used as VG-LV separator - ambiguity if LV starts with it */
|
||||
if (*n == '-')
|
||||
return 0;
|
||||
|
||||
if (!strcmp(n, ".") || !strcmp(n, ".."))
|
||||
return 0;
|
||||
|
||||
while ((len++, c = *n++))
|
||||
if (!isalnum(c) && c != '.' && c != '_' && c != '-' && c != '+')
|
||||
return 0;
|
||||
|
||||
if (len > NAME_LEN)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -78,6 +78,12 @@ struct segtype_handler {
|
||||
uint64_t *total_denominator, float *percent);
|
||||
int (*target_present) (void);
|
||||
void (*destroy) (const struct segment_type * segtype);
|
||||
int (*target_register_events) (struct dm_pool *mem,
|
||||
struct lv_segment *seg,
|
||||
struct config_tree *cft, int events);
|
||||
int (*target_unregister_events) (struct dm_pool *mem,
|
||||
struct lv_segment *seg,
|
||||
struct config_tree *cft, int events);
|
||||
};
|
||||
|
||||
struct segment_type *get_segtype_from_string(struct cmd_context *cmd,
|
||||
|
||||
@@ -28,12 +28,26 @@ int lv_is_cow(const struct logical_volume *lv)
|
||||
return lv->snapshot ? 1 : 0;
|
||||
}
|
||||
|
||||
int lv_is_visible(const struct logical_volume *lv)
|
||||
{
|
||||
if (lv_is_cow(lv))
|
||||
return lv_is_visible(find_cow(lv)->lv);
|
||||
|
||||
return lv->status & VISIBLE_LV ? 1 : 0;
|
||||
}
|
||||
|
||||
/* Given a cow LV, return the snapshot lv_segment that uses it */
|
||||
struct lv_segment *find_cow(const struct logical_volume *lv)
|
||||
{
|
||||
return lv->snapshot;
|
||||
}
|
||||
|
||||
/* Given a cow LV, return its origin */
|
||||
struct logical_volume *origin_from_cow(const struct logical_volume *lv)
|
||||
{
|
||||
return lv->snapshot->origin;
|
||||
}
|
||||
|
||||
int vg_add_snapshot(struct format_instance *fid, const char *name,
|
||||
struct logical_volume *origin,
|
||||
struct logical_volume *cow, union lvid *lvid,
|
||||
|
||||
@@ -25,6 +25,13 @@
|
||||
#include "lvm-string.h"
|
||||
#include "targets.h"
|
||||
#include "activate.h"
|
||||
#include "sharedlib.h"
|
||||
|
||||
#ifdef DMEVENTD
|
||||
# include <libdevmapper-event.h>
|
||||
#endif
|
||||
|
||||
static int _block_on_error_available = 0;
|
||||
|
||||
enum {
|
||||
MIRR_DISABLED,
|
||||
@@ -36,12 +43,12 @@ struct mirror_state {
|
||||
uint32_t default_region_size;
|
||||
};
|
||||
|
||||
static const char *_name(const struct lv_segment *seg)
|
||||
static const char *_mirrored_name(const struct lv_segment *seg)
|
||||
{
|
||||
return seg->segtype->name;
|
||||
}
|
||||
|
||||
static void _display(const struct lv_segment *seg)
|
||||
static void _mirrored_display(const struct lv_segment *seg)
|
||||
{
|
||||
const char *size;
|
||||
uint32_t s;
|
||||
@@ -66,7 +73,7 @@ static void _display(const struct lv_segment *seg)
|
||||
log_print(" ");
|
||||
}
|
||||
|
||||
static int _text_import_area_count(struct config_node *sn, uint32_t *area_count)
|
||||
static int _mirrored_text_import_area_count(struct config_node *sn, uint32_t *area_count)
|
||||
{
|
||||
if (!get_config_uint32(sn, "mirror_count", area_count)) {
|
||||
log_error("Couldn't read 'mirror_count' for "
|
||||
@@ -77,7 +84,7 @@ static int _text_import_area_count(struct config_node *sn, uint32_t *area_count)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _text_import(struct lv_segment *seg, const struct config_node *sn,
|
||||
static int _mirrored_text_import(struct lv_segment *seg, const struct config_node *sn,
|
||||
struct dm_hash_table *pv_hash)
|
||||
{
|
||||
const struct config_node *cn;
|
||||
@@ -132,7 +139,7 @@ static int _text_import(struct lv_segment *seg, const struct config_node *sn,
|
||||
return text_import_areas(seg, sn, cn, pv_hash, MIRROR_IMAGE);
|
||||
}
|
||||
|
||||
static int _text_export(const struct lv_segment *seg, struct formatter *f)
|
||||
static int _mirrored_text_export(const struct lv_segment *seg, struct formatter *f)
|
||||
{
|
||||
outf(f, "mirror_count = %u", seg->area_count);
|
||||
if (seg->status & PVMOVE)
|
||||
@@ -147,7 +154,7 @@ static int _text_export(const struct lv_segment *seg, struct formatter *f)
|
||||
}
|
||||
|
||||
#ifdef DEVMAPPER_SUPPORT
|
||||
static struct mirror_state *_init_target(struct dm_pool *mem,
|
||||
static struct mirror_state *_mirrored_init_target(struct dm_pool *mem,
|
||||
struct config_tree *cft)
|
||||
{
|
||||
struct mirror_state *mirr_state;
|
||||
@@ -165,7 +172,7 @@ static struct mirror_state *_init_target(struct dm_pool *mem,
|
||||
return mirr_state;
|
||||
}
|
||||
|
||||
static int _target_percent(void **target_state, struct dm_pool *mem,
|
||||
static int _mirrored_target_percent(void **target_state, struct dm_pool *mem,
|
||||
struct config_tree *cft, struct lv_segment *seg,
|
||||
char *params, uint64_t *total_numerator,
|
||||
uint64_t *total_denominator, float *percent)
|
||||
@@ -177,7 +184,7 @@ static int _target_percent(void **target_state, struct dm_pool *mem,
|
||||
char *pos = params;
|
||||
|
||||
if (!*target_state)
|
||||
*target_state = _init_target(mem, cft);
|
||||
*target_state = _mirrored_init_target(mem, cft);
|
||||
|
||||
mirr_state = *target_state;
|
||||
|
||||
@@ -221,6 +228,7 @@ static int _add_log(struct dev_manager *dm, struct lv_segment *seg,
|
||||
{
|
||||
unsigned clustered = 0;
|
||||
char *log_dlid = NULL;
|
||||
uint32_t log_flags = 0;
|
||||
|
||||
/*
|
||||
* Use clustered mirror log for non-exclusive activation
|
||||
@@ -237,11 +245,13 @@ static int _add_log(struct dev_manager *dm, struct lv_segment *seg,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* FIXME Add sync parm? */
|
||||
return dm_tree_node_add_mirror_target_log(node, region_size, clustered, log_dlid, area_count);
|
||||
if (_block_on_error_available && !(seg->status & PVMOVE))
|
||||
log_flags |= DM_BLOCK_ON_ERROR;
|
||||
|
||||
return dm_tree_node_add_mirror_target_log(node, region_size, clustered, log_dlid, area_count, log_flags);
|
||||
}
|
||||
|
||||
static int _add_target_line(struct dev_manager *dm, struct dm_pool *mem,
|
||||
static int _mirrored_add_target_line(struct dev_manager *dm, struct dm_pool *mem,
|
||||
struct config_tree *cft, void **target_state,
|
||||
struct lv_segment *seg,
|
||||
struct dm_tree_node *node, uint64_t len,
|
||||
@@ -255,7 +265,7 @@ static int _add_target_line(struct dev_manager *dm, struct dm_pool *mem,
|
||||
int r;
|
||||
|
||||
if (!*target_state)
|
||||
*target_state = _init_target(mem, cft);
|
||||
*target_state = _mirrored_init_target(mem, cft);
|
||||
|
||||
mirr_state = *target_state;
|
||||
|
||||
@@ -312,37 +322,141 @@ static int _add_target_line(struct dev_manager *dm, struct dm_pool *mem,
|
||||
return add_areas_line(dm, seg, node, start_area, area_count);
|
||||
}
|
||||
|
||||
static int _target_present(void)
|
||||
static int _mirrored_target_present(void)
|
||||
{
|
||||
static int checked = 0;
|
||||
static int present = 0;
|
||||
static int _mirrored_checked = 0;
|
||||
static int _mirrored_present = 0;
|
||||
uint32_t maj, min, patchlevel;
|
||||
unsigned maj2, min2, patchlevel2;
|
||||
char vsn[80];
|
||||
|
||||
if (!checked)
|
||||
present = target_present("mirror", 1);
|
||||
if (!_mirrored_checked) {
|
||||
_mirrored_present = target_present("mirror", 1);
|
||||
|
||||
checked = 1;
|
||||
/*
|
||||
* block_on_error available with mirror target >= 1.1
|
||||
* or with 1.0 in RHEL4U3 driver >= 4.5
|
||||
*/
|
||||
/* FIXME Move this into libdevmapper */
|
||||
|
||||
return present;
|
||||
if (target_version("mirror", &maj, &min, &patchlevel) &&
|
||||
maj == 1 &&
|
||||
(min >= 1 ||
|
||||
(min == 0 && driver_version(vsn, sizeof(vsn)) &&
|
||||
sscanf(vsn, "%u.%u.%u", &maj2, &min2, &patchlevel2) == 3 &&
|
||||
maj2 == 4 && min2 == 5 && patchlevel2 == 0))) /* RHEL4U3 */
|
||||
_block_on_error_available = 1;
|
||||
}
|
||||
|
||||
_mirrored_checked = 1;
|
||||
|
||||
return _mirrored_present;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void _destroy(const struct segment_type *segtype)
|
||||
#ifdef DMEVENTD
|
||||
static int _setup_registration(struct dm_pool *mem, struct config_tree *cft,
|
||||
char **dso)
|
||||
{
|
||||
char *path;
|
||||
const char *libpath;
|
||||
|
||||
if (!(path = dm_pool_alloc(mem, PATH_MAX))) {
|
||||
log_error("Failed to allocate dmeventd library path.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
libpath = find_config_str(cft->root, "dmeventd/mirror_library",
|
||||
DEFAULT_DMEVENTD_MIRROR_LIB);
|
||||
|
||||
get_shared_library_path(cft, libpath, path, PATH_MAX);
|
||||
|
||||
*dso = path;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* FIXME This gets run while suspended and performs banned operations. */
|
||||
/* FIXME Merge these two functions */
|
||||
static int _target_register_events(struct dm_pool *mem,
|
||||
struct lv_segment *seg,
|
||||
struct config_tree *cft, int events)
|
||||
{
|
||||
char *dso, *name;
|
||||
struct logical_volume *lv;
|
||||
struct volume_group *vg;
|
||||
|
||||
lv = seg->lv;
|
||||
vg = lv->vg;
|
||||
|
||||
if (!_setup_registration(mem, cft, &dso)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(name = build_dm_name(mem, vg->name, lv->name, NULL)))
|
||||
return_0;
|
||||
|
||||
/* FIXME Save a returned handle here so we can unregister it later */
|
||||
if (!dm_event_register(dso, name, DM_EVENT_ALL_ERRORS))
|
||||
return_0;
|
||||
|
||||
log_info("Registered %s for events", name);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _target_unregister_events(struct dm_pool *mem,
|
||||
struct lv_segment *seg,
|
||||
struct config_tree *cft, int events)
|
||||
{
|
||||
char *dso;
|
||||
char *name;
|
||||
struct logical_volume *lv;
|
||||
struct volume_group *vg;
|
||||
|
||||
lv = seg->lv;
|
||||
vg = lv->vg;
|
||||
|
||||
/* FIXME Remove this and use handle to avoid config file race */
|
||||
if (!_setup_registration(mem, cft, &dso))
|
||||
return_0;
|
||||
|
||||
if (!(name = build_dm_name(mem, vg->name, lv->name, NULL)))
|
||||
return_0;
|
||||
|
||||
/* FIXME Use handle returned by registration function instead of dso */
|
||||
if (!dm_event_unregister(dso, name, DM_EVENT_ALL_ERRORS))
|
||||
return_0;
|
||||
|
||||
log_info("Unregistered %s for events", name);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /* DMEVENTD */
|
||||
#endif /* DEVMAPPER_SUPPORT */
|
||||
|
||||
static void _mirrored_destroy(const struct segment_type *segtype)
|
||||
{
|
||||
dm_free((void *) segtype);
|
||||
}
|
||||
|
||||
static struct segtype_handler _mirrored_ops = {
|
||||
name:_name,
|
||||
display:_display,
|
||||
text_import_area_count:_text_import_area_count,
|
||||
text_import:_text_import,
|
||||
text_export:_text_export,
|
||||
name:_mirrored_name,
|
||||
display:_mirrored_display,
|
||||
text_import_area_count:_mirrored_text_import_area_count,
|
||||
text_import:_mirrored_text_import,
|
||||
text_export:_mirrored_text_export,
|
||||
#ifdef DEVMAPPER_SUPPORT
|
||||
add_target_line:_add_target_line,
|
||||
target_percent:_target_percent,
|
||||
target_present:_target_present,
|
||||
add_target_line:_mirrored_add_target_line,
|
||||
target_percent:_mirrored_target_percent,
|
||||
target_present:_mirrored_target_present,
|
||||
#ifdef DMEVENTD
|
||||
target_register_events:_target_register_events,
|
||||
target_unregister_events:_target_unregister_events,
|
||||
#endif
|
||||
destroy:_destroy,
|
||||
#endif
|
||||
destroy:_mirrored_destroy,
|
||||
};
|
||||
|
||||
#ifdef MIRRORED_INTERNAL
|
||||
|
||||
@@ -208,3 +208,27 @@ int split_dm_name(struct dm_pool *mem, const char *dmname,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int validate_name(const char *n)
|
||||
{
|
||||
register char c;
|
||||
register int len = 0;
|
||||
|
||||
if (!n || !*n)
|
||||
return 0;
|
||||
|
||||
/* Hyphen used as VG-LV separator - ambiguity if LV starts with it */
|
||||
if (*n == '-')
|
||||
return 0;
|
||||
|
||||
if (!strcmp(n, ".") || !strcmp(n, ".."))
|
||||
return 0;
|
||||
|
||||
while ((len++, c = *n++))
|
||||
if (!isalnum(c) && c != '.' && c != '_' && c != '-' && c != '+')
|
||||
return 0;
|
||||
|
||||
if (len > NAME_LEN)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#define NAME_LEN 128
|
||||
|
||||
struct pool;
|
||||
|
||||
/*
|
||||
@@ -40,4 +42,6 @@ char *build_dm_name(struct dm_pool *mem, const char *vg,
|
||||
int split_dm_name(struct dm_pool *mem, const char *dmname,
|
||||
char **vgname, char **lvname, char **layer);
|
||||
|
||||
int validate_name(const char *n);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
#include <sys/stat.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
static void _get_library_path(struct config_tree *cft, const char *libname,
|
||||
char *path, int path_len)
|
||||
void get_shared_library_path(struct config_tree *cft, const char *libname,
|
||||
char *path, int path_len)
|
||||
{
|
||||
struct stat info;
|
||||
const char *lib_dir;
|
||||
@@ -38,17 +38,23 @@ static void _get_library_path(struct config_tree *cft, const char *libname,
|
||||
}
|
||||
|
||||
void *load_shared_library(struct config_tree *cft, const char *libname,
|
||||
const char *desc)
|
||||
const char *desc, int silent)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
void *library;
|
||||
|
||||
_get_library_path(cft, libname, path, sizeof(path));
|
||||
get_shared_library_path(cft, libname, path, sizeof(path));
|
||||
|
||||
log_very_verbose("Opening shared %s library %s", desc, path);
|
||||
|
||||
if (!(library = dlopen(path, RTLD_LAZY)))
|
||||
log_error("Unable to open external %s library %s", desc, path);
|
||||
if (!(library = dlopen(path, RTLD_LAZY))) {
|
||||
if (silent && ignorelockingfailure())
|
||||
log_verbose("Unable to open external %s library %s",
|
||||
desc, path);
|
||||
else
|
||||
log_error("Unable to open external %s library %s",
|
||||
desc, path);
|
||||
}
|
||||
|
||||
return library;
|
||||
}
|
||||
|
||||
@@ -16,5 +16,7 @@
|
||||
#include "config.h"
|
||||
#include <dlfcn.h>
|
||||
|
||||
void get_shared_library_path(struct config_tree *cft, const char *libname,
|
||||
char *path, int path_len);
|
||||
void *load_shared_library(struct config_tree *cf, const char *libname,
|
||||
const char *what);
|
||||
const char *what, int silent);
|
||||
|
||||
@@ -90,7 +90,7 @@ static void _release_memory(void)
|
||||
}
|
||||
|
||||
/* Stop memory getting swapped out */
|
||||
static void _lock_memory(void)
|
||||
static void _lock_mem(void)
|
||||
{
|
||||
#ifdef MCL_CURRENT
|
||||
if (mlockall(MCL_CURRENT | MCL_FUTURE))
|
||||
@@ -109,7 +109,7 @@ static void _lock_memory(void)
|
||||
_default_priority, strerror(errno));
|
||||
}
|
||||
|
||||
static void _unlock_memory(void)
|
||||
static void _unlock_mem(void)
|
||||
{
|
||||
#ifdef MCL_CURRENT
|
||||
if (munlockall())
|
||||
@@ -126,14 +126,14 @@ static void _unlock_memory(void)
|
||||
void memlock_inc(void)
|
||||
{
|
||||
if (!_memlock_count++)
|
||||
_lock_memory();
|
||||
_lock_mem();
|
||||
log_debug("memlock_count inc to %d", _memlock_count);
|
||||
}
|
||||
|
||||
void memlock_dec(void)
|
||||
{
|
||||
if (_memlock_count && (!--_memlock_count))
|
||||
_unlock_memory();
|
||||
_unlock_mem();
|
||||
log_debug("memlock_count dec to %d", _memlock_count);
|
||||
}
|
||||
|
||||
|
||||
@@ -166,7 +166,7 @@ static void _calc_functions(struct matcher *m)
|
||||
}
|
||||
}
|
||||
|
||||
static inline struct dfa_state *_create_dfa_state(struct dm_pool *mem)
|
||||
static struct dfa_state *_create_dfa_state(struct dm_pool *mem)
|
||||
{
|
||||
return dm_pool_zalloc(mem, sizeof(struct dfa_state));
|
||||
}
|
||||
@@ -337,8 +337,7 @@ struct matcher *matcher_create(struct dm_pool *mem, const char **patterns,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct dfa_state *_step_matcher(int c,
|
||||
struct dfa_state *cs, int *r)
|
||||
static struct dfa_state *_step_matcher(int c, struct dfa_state *cs, int *r)
|
||||
{
|
||||
if (!(cs = cs->lookup[(unsigned char) c]))
|
||||
return NULL;
|
||||
|
||||
@@ -38,7 +38,7 @@ static void _single_char(struct parse_sp *ps, unsigned int c, const char *ptr)
|
||||
* Get the next token from the regular expression.
|
||||
* Returns: 1 success, 0 end of input, -1 error.
|
||||
*/
|
||||
static int _get_token(struct parse_sp *ps)
|
||||
static int _rx_get_token(struct parse_sp *ps)
|
||||
{
|
||||
int neg = 0, range = 0;
|
||||
char c, lc = 0;
|
||||
@@ -230,17 +230,17 @@ static struct rx_node *_term(struct parse_sp *ps)
|
||||
}
|
||||
|
||||
dm_bit_copy(n->charset, ps->charset);
|
||||
_get_token(ps); /* match charset */
|
||||
_rx_get_token(ps); /* match charset */
|
||||
break;
|
||||
|
||||
case '(':
|
||||
_get_token(ps); /* match '(' */
|
||||
_rx_get_token(ps); /* match '(' */
|
||||
n = _or_term(ps);
|
||||
if (ps->type != ')') {
|
||||
log_error("missing ')' in regular expression");
|
||||
return 0;
|
||||
}
|
||||
_get_token(ps); /* match ')' */
|
||||
_rx_get_token(ps); /* match ')' */
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -280,7 +280,7 @@ static struct rx_node *_closure_term(struct parse_sp *ps)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_get_token(ps);
|
||||
_rx_get_token(ps);
|
||||
l = n;
|
||||
}
|
||||
|
||||
@@ -316,7 +316,7 @@ static struct rx_node *_or_term(struct parse_sp *ps)
|
||||
if (ps->type != '|')
|
||||
return l;
|
||||
|
||||
_get_token(ps); /* match '|' */
|
||||
_rx_get_token(ps); /* match '|' */
|
||||
|
||||
if (!(r = _or_term(ps))) {
|
||||
log_error("Badly formed 'or' expression");
|
||||
@@ -344,7 +344,7 @@ struct rx_node *rx_parse_tok(struct dm_pool *mem,
|
||||
ps->charset = dm_bitset_create(mem, 256);
|
||||
ps->cursor = begin;
|
||||
ps->rx_end = end;
|
||||
_get_token(ps); /* load the first token */
|
||||
_rx_get_token(ps); /* load the first token */
|
||||
|
||||
if (!(r = _or_term(ps))) {
|
||||
log_error("Parse error in regex");
|
||||
|
||||
@@ -59,7 +59,7 @@ void *ttree_lookup(struct ttree *tt, unsigned *key)
|
||||
return *c ? (*c)->data : NULL;
|
||||
}
|
||||
|
||||
static struct node *_node(struct dm_pool *mem, unsigned int k)
|
||||
static struct node *_tree_node(struct dm_pool *mem, unsigned int k)
|
||||
{
|
||||
struct node *n = dm_pool_zalloc(mem, sizeof(*n));
|
||||
|
||||
@@ -86,7 +86,7 @@ int ttree_insert(struct ttree *tt, unsigned int *key, void *data)
|
||||
count++;
|
||||
|
||||
while (count--) {
|
||||
if (!(*c = _node(tt->mem, k))) {
|
||||
if (!(*c = _tree_node(tt->mem, k))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -324,7 +324,6 @@ static int _lvstatus_disp(struct report_handle *rh, struct field *field,
|
||||
const struct logical_volume *lv = (const struct logical_volume *) data;
|
||||
struct lvinfo info;
|
||||
char *repstr;
|
||||
struct lv_segment *snap_seg;
|
||||
float snap_percent;
|
||||
|
||||
if (!(repstr = dm_pool_zalloc(rh->mem, 7))) {
|
||||
@@ -344,7 +343,7 @@ static int _lvstatus_disp(struct report_handle *rh, struct field *field,
|
||||
repstr[0] = 'v';
|
||||
else if (lv_is_origin(lv))
|
||||
repstr[0] = 'o';
|
||||
else if (find_cow(lv))
|
||||
else if (lv_is_cow(lv))
|
||||
repstr[0] = 's';
|
||||
else
|
||||
repstr[0] = '-';
|
||||
@@ -377,8 +376,8 @@ static int _lvstatus_disp(struct report_handle *rh, struct field *field,
|
||||
repstr[4] = 'd'; /* Inactive without table */
|
||||
|
||||
/* Snapshot dropped? */
|
||||
if (info.live_table && (snap_seg = find_cow(lv)) &&
|
||||
(!lv_snapshot_percent(snap_seg->cow, &snap_percent) ||
|
||||
if (info.live_table && lv_is_cow(lv) &&
|
||||
(!lv_snapshot_percent(lv, &snap_percent) ||
|
||||
snap_percent < 0 || snap_percent >= 100)) {
|
||||
repstr[0] = toupper(repstr[0]);
|
||||
if (info.suspended)
|
||||
@@ -491,10 +490,9 @@ static int _origin_disp(struct report_handle *rh, struct field *field,
|
||||
const void *data)
|
||||
{
|
||||
const struct logical_volume *lv = (const struct logical_volume *) data;
|
||||
struct lv_segment *snap_seg;
|
||||
|
||||
if ((snap_seg = find_cow(lv)))
|
||||
return _string_disp(rh, field, &snap_seg->origin->name);
|
||||
if (lv_is_cow(lv))
|
||||
return _string_disp(rh, field, &origin_from_cow(lv)->name);
|
||||
|
||||
field->report_string = "";
|
||||
field->sort_value = (const void *) field->report_string;
|
||||
@@ -527,8 +525,7 @@ static int _lvname_disp(struct report_handle *rh, struct field *field,
|
||||
char *repstr;
|
||||
size_t len;
|
||||
|
||||
/* FIXME Remove need for snapshot special case */
|
||||
if (lv->status & VISIBLE_LV || lv_is_cow(lv)) {
|
||||
if (lv_is_visible(lv)) {
|
||||
repstr = lv->name;
|
||||
return _string_disp(rh, field, &repstr);
|
||||
}
|
||||
@@ -667,11 +664,10 @@ static int _chunksize_disp(struct report_handle *rh, struct field *field,
|
||||
const void *data)
|
||||
{
|
||||
const struct lv_segment *seg = (const struct lv_segment *) data;
|
||||
struct lv_segment *snap_seg;
|
||||
uint64_t size;
|
||||
|
||||
if ((snap_seg = find_cow(seg->lv)))
|
||||
size = (uint64_t) snap_seg->chunk_size;
|
||||
if (lv_is_cow(seg->lv))
|
||||
size = (uint64_t) find_cow(seg->lv)->chunk_size;
|
||||
else
|
||||
size = 0;
|
||||
|
||||
@@ -840,7 +836,6 @@ static int _snpercent_disp(struct report_handle *rh, struct field *field,
|
||||
const void *data)
|
||||
{
|
||||
const struct logical_volume *lv = (const struct logical_volume *) data;
|
||||
struct lv_segment *snap_seg;
|
||||
struct lvinfo info;
|
||||
float snap_percent;
|
||||
uint64_t *sortval;
|
||||
@@ -851,16 +846,15 @@ static int _snpercent_disp(struct report_handle *rh, struct field *field,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(snap_seg = find_cow(lv)) ||
|
||||
(lv_info(lv->vg->cmd, snap_seg->cow, &info, 0) && !info.exists)) {
|
||||
if (!lv_is_cow(lv) ||
|
||||
(lv_info(lv->vg->cmd, lv, &info, 0) && !info.exists)) {
|
||||
field->report_string = "";
|
||||
*sortval = UINT64_C(0);
|
||||
field->sort_value = sortval;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!lv_snapshot_percent(snap_seg->cow, &snap_percent)
|
||||
|| snap_percent < 0) {
|
||||
if (!lv_snapshot_percent(lv, &snap_percent) || snap_percent < 0) {
|
||||
field->report_string = "100.00";
|
||||
*sortval = UINT64_C(100);
|
||||
field->sort_value = sortval;
|
||||
|
||||
@@ -21,12 +21,12 @@
|
||||
#include "config.h"
|
||||
#include "activate.h"
|
||||
|
||||
static const char *_name(const struct lv_segment *seg)
|
||||
static const char *_snap_name(const struct lv_segment *seg)
|
||||
{
|
||||
return seg->segtype->name;
|
||||
}
|
||||
|
||||
static int _text_import(struct lv_segment *seg, const struct config_node *sn,
|
||||
static int _snap_text_import(struct lv_segment *seg, const struct config_node *sn,
|
||||
struct dm_hash_table *pv_hash)
|
||||
{
|
||||
uint32_t chunk_size;
|
||||
@@ -77,7 +77,7 @@ static int _text_import(struct lv_segment *seg, const struct config_node *sn,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _text_export(const struct lv_segment *seg, struct formatter *f)
|
||||
static int _snap_text_export(const struct lv_segment *seg, struct formatter *f)
|
||||
{
|
||||
outf(f, "chunk_size = %u", seg->chunk_size);
|
||||
outf(f, "origin = \"%s\"", seg->origin->name);
|
||||
@@ -87,7 +87,7 @@ static int _text_export(const struct lv_segment *seg, struct formatter *f)
|
||||
}
|
||||
|
||||
#ifdef DEVMAPPER_SUPPORT
|
||||
static int _target_percent(void **target_state, struct dm_pool *mem,
|
||||
static int _snap_target_percent(void **target_state, struct dm_pool *mem,
|
||||
struct config_tree *cft, struct lv_segment *seg,
|
||||
char *params, uint64_t *total_numerator,
|
||||
uint64_t *total_denominator, float *percent)
|
||||
@@ -109,35 +109,35 @@ static int _target_percent(void **target_state, struct dm_pool *mem,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _target_present(void)
|
||||
static int _snap_target_present(void)
|
||||
{
|
||||
static int checked = 0;
|
||||
static int present = 0;
|
||||
static int _snap_checked = 0;
|
||||
static int _snap_present = 0;
|
||||
|
||||
if (!checked)
|
||||
present = target_present("snapshot", 1) &&
|
||||
if (!_snap_checked)
|
||||
_snap_present = target_present("snapshot", 1) &&
|
||||
target_present("snapshot-origin", 0);
|
||||
|
||||
checked = 1;
|
||||
_snap_checked = 1;
|
||||
|
||||
return present;
|
||||
return _snap_present;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void _destroy(const struct segment_type *segtype)
|
||||
static void _snap_destroy(const struct segment_type *segtype)
|
||||
{
|
||||
dm_free((void *) segtype);
|
||||
}
|
||||
|
||||
static struct segtype_handler _snapshot_ops = {
|
||||
name:_name,
|
||||
text_import:_text_import,
|
||||
text_export:_text_export,
|
||||
name:_snap_name,
|
||||
text_import:_snap_text_import,
|
||||
text_export:_snap_text_export,
|
||||
#ifdef DEVMAPPER_SUPPORT
|
||||
target_percent:_target_percent,
|
||||
target_present:_target_present,
|
||||
target_percent:_snap_target_percent,
|
||||
target_present:_snap_target_present,
|
||||
#endif
|
||||
destroy:_destroy,
|
||||
destroy:_snap_destroy,
|
||||
};
|
||||
|
||||
#ifdef SNAPSHOT_INTERNAL
|
||||
|
||||
@@ -26,12 +26,12 @@
|
||||
#include "activate.h"
|
||||
#include "pv_alloc.h"
|
||||
|
||||
static const char *_name(const struct lv_segment *seg)
|
||||
static const char *_striped_name(const struct lv_segment *seg)
|
||||
{
|
||||
return (seg->area_count == 1) ? "linear" : seg->segtype->name;
|
||||
}
|
||||
|
||||
static void _display(const struct lv_segment *seg)
|
||||
static void _striped_display(const struct lv_segment *seg)
|
||||
{
|
||||
uint32_t s;
|
||||
|
||||
@@ -49,7 +49,7 @@ static void _display(const struct lv_segment *seg)
|
||||
log_print(" ");
|
||||
}
|
||||
|
||||
static int _text_import_area_count(struct config_node *sn, uint32_t *area_count)
|
||||
static int _striped_text_import_area_count(struct config_node *sn, uint32_t *area_count)
|
||||
{
|
||||
if (!get_config_uint32(sn, "stripe_count", area_count)) {
|
||||
log_error("Couldn't read 'stripe_count' for "
|
||||
@@ -60,7 +60,7 @@ static int _text_import_area_count(struct config_node *sn, uint32_t *area_count)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _text_import(struct lv_segment *seg, const struct config_node *sn,
|
||||
static int _striped_text_import(struct lv_segment *seg, const struct config_node *sn,
|
||||
struct dm_hash_table *pv_hash)
|
||||
{
|
||||
struct config_node *cn;
|
||||
@@ -83,7 +83,7 @@ static int _text_import(struct lv_segment *seg, const struct config_node *sn,
|
||||
return text_import_areas(seg, sn, cn, pv_hash, 0);
|
||||
}
|
||||
|
||||
static int _text_export(const struct lv_segment *seg, struct formatter *f)
|
||||
static int _striped_text_export(const struct lv_segment *seg, struct formatter *f)
|
||||
{
|
||||
|
||||
outf(f, "stripe_count = %u%s", seg->area_count,
|
||||
@@ -99,7 +99,7 @@ static int _text_export(const struct lv_segment *seg, struct formatter *f)
|
||||
/*
|
||||
* Test whether two segments could be merged by the current merging code
|
||||
*/
|
||||
static int _segments_compatible(struct lv_segment *first,
|
||||
static int _striped_segments_compatible(struct lv_segment *first,
|
||||
struct lv_segment *second)
|
||||
{
|
||||
uint32_t width;
|
||||
@@ -132,11 +132,11 @@ static int _segments_compatible(struct lv_segment *first,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _merge_segments(struct lv_segment *seg1, struct lv_segment *seg2)
|
||||
static int _striped_merge_segments(struct lv_segment *seg1, struct lv_segment *seg2)
|
||||
{
|
||||
uint32_t s;
|
||||
|
||||
if (!_segments_compatible(seg1, seg2))
|
||||
if (!_striped_segments_compatible(seg1, seg2))
|
||||
return 0;
|
||||
|
||||
seg1->len += seg2->len;
|
||||
@@ -151,7 +151,7 @@ static int _merge_segments(struct lv_segment *seg1, struct lv_segment *seg2)
|
||||
}
|
||||
|
||||
#ifdef DEVMAPPER_SUPPORT
|
||||
static int _add_target_line(struct dev_manager *dm, struct dm_pool *mem,
|
||||
static int _striped_add_target_line(struct dev_manager *dm, struct dm_pool *mem,
|
||||
struct config_tree *cft, void **target_state,
|
||||
struct lv_segment *seg,
|
||||
struct dm_tree_node *node, uint64_t len,
|
||||
@@ -172,37 +172,38 @@ static int _add_target_line(struct dev_manager *dm, struct dm_pool *mem,
|
||||
return add_areas_line(dm, seg, node, 0u, seg->area_count);
|
||||
}
|
||||
|
||||
static int _target_present(void)
|
||||
static int _striped_target_present(void)
|
||||
{
|
||||
static int checked = 0;
|
||||
static int present = 0;
|
||||
static int _striped_checked = 0;
|
||||
static int _striped_present = 0;
|
||||
|
||||
if (!checked)
|
||||
present = target_present("linear", 0) &&
|
||||
if (!_striped_checked)
|
||||
_striped_present = target_present("linear", 0) &&
|
||||
target_present("striped", 0);
|
||||
|
||||
checked = 1;
|
||||
return present;
|
||||
_striped_checked = 1;
|
||||
|
||||
return _striped_present;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void _destroy(const struct segment_type *segtype)
|
||||
static void _striped_destroy(const struct segment_type *segtype)
|
||||
{
|
||||
dm_free((void *) segtype);
|
||||
}
|
||||
|
||||
static struct segtype_handler _striped_ops = {
|
||||
name:_name,
|
||||
display:_display,
|
||||
text_import_area_count:_text_import_area_count,
|
||||
text_import:_text_import,
|
||||
text_export:_text_export,
|
||||
merge_segments:_merge_segments,
|
||||
name:_striped_name,
|
||||
display:_striped_display,
|
||||
text_import_area_count:_striped_text_import_area_count,
|
||||
text_import:_striped_text_import,
|
||||
text_export:_striped_text_export,
|
||||
merge_segments:_striped_merge_segments,
|
||||
#ifdef DEVMAPPER_SUPPORT
|
||||
add_target_line:_add_target_line,
|
||||
target_present:_target_present,
|
||||
add_target_line:_striped_add_target_line,
|
||||
target_present:_striped_target_present,
|
||||
#endif
|
||||
destroy:_destroy,
|
||||
destroy:_striped_destroy,
|
||||
};
|
||||
|
||||
struct segment_type *init_striped_segtype(struct cmd_context *cmd)
|
||||
|
||||
@@ -24,12 +24,12 @@
|
||||
#include "lvm-string.h"
|
||||
#include "activate.h"
|
||||
|
||||
static const char *_name(const struct lv_segment *seg)
|
||||
static const char *_zero_name(const struct lv_segment *seg)
|
||||
{
|
||||
return seg->segtype->name;
|
||||
}
|
||||
|
||||
static int _merge_segments(struct lv_segment *seg1, struct lv_segment *seg2)
|
||||
static int _zero_merge_segments(struct lv_segment *seg1, struct lv_segment *seg2)
|
||||
{
|
||||
seg1->len += seg2->len;
|
||||
seg1->area_len += seg2->area_len;
|
||||
@@ -38,7 +38,7 @@ static int _merge_segments(struct lv_segment *seg1, struct lv_segment *seg2)
|
||||
}
|
||||
|
||||
#ifdef DEVMAPPER_SUPPORT
|
||||
static int _add_target_line(struct dev_manager *dm, struct dm_pool *mem,
|
||||
static int _zero_add_target_line(struct dev_manager *dm, struct dm_pool *mem,
|
||||
struct config_tree *cft, void **target_state,
|
||||
struct lv_segment *seg,
|
||||
struct dm_tree_node *node, uint64_t len,
|
||||
@@ -47,32 +47,33 @@ static int _add_target_line(struct dev_manager *dm, struct dm_pool *mem,
|
||||
return dm_tree_node_add_zero_target(node, len);
|
||||
}
|
||||
|
||||
static int _target_present(void)
|
||||
static int _zero_target_present(void)
|
||||
{
|
||||
static int checked = 0;
|
||||
static int present = 0;
|
||||
static int _zero_checked = 0;
|
||||
static int _zero_present = 0;
|
||||
|
||||
if (!checked)
|
||||
present = target_present("zero", 0);
|
||||
if (!_zero_checked)
|
||||
_zero_present = target_present("zero", 0);
|
||||
|
||||
checked = 1;
|
||||
return present;
|
||||
_zero_checked = 1;
|
||||
|
||||
return _zero_present;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void _destroy(const struct segment_type *segtype)
|
||||
static void _zero_destroy(const struct segment_type *segtype)
|
||||
{
|
||||
dm_free((void *) segtype);
|
||||
}
|
||||
|
||||
static struct segtype_handler _zero_ops = {
|
||||
name:_name,
|
||||
merge_segments:_merge_segments,
|
||||
name:_zero_name,
|
||||
merge_segments:_zero_merge_segments,
|
||||
#ifdef DEVMAPPER_SUPPORT
|
||||
add_target_line:_add_target_line,
|
||||
target_present:_target_present,
|
||||
add_target_line:_zero_add_target_line,
|
||||
target_present:_zero_target_present,
|
||||
#endif
|
||||
destroy:_destroy,
|
||||
destroy:_zero_destroy,
|
||||
};
|
||||
|
||||
struct segment_type *init_zero_segtype(struct cmd_context *cmd)
|
||||
|
||||
@@ -2,6 +2,7 @@ dm_lib_release
|
||||
dm_lib_exit
|
||||
dm_driver_version
|
||||
dm_get_library_version
|
||||
dm_log
|
||||
dm_log_init
|
||||
dm_log_init_verbose
|
||||
dm_task_create
|
||||
@@ -22,6 +23,9 @@ dm_task_set_major
|
||||
dm_task_set_minor
|
||||
dm_task_set_sector
|
||||
dm_task_set_message
|
||||
dm_task_set_uid
|
||||
dm_task_set_gid
|
||||
dm_task_set_mode
|
||||
dm_task_suppress_identical_reload
|
||||
dm_task_add_target
|
||||
dm_task_no_open_count
|
||||
@@ -60,11 +64,12 @@ dm_tree_node_add_striped_target
|
||||
dm_tree_node_add_mirror_target
|
||||
dm_tree_node_add_mirror_target_log
|
||||
dm_tree_node_add_target_area
|
||||
dm_tree_skip_lockfs
|
||||
dm_is_dm_major
|
||||
dm_mknodes
|
||||
dm_malloc_aux
|
||||
dm_malloc_aux_debug
|
||||
dm_strdup
|
||||
dm_strdup_aux
|
||||
dm_free_aux
|
||||
dm_realloc_aux
|
||||
dm_dump_memory_debug
|
||||
@@ -103,3 +108,4 @@ dm_hash_get_data
|
||||
dm_hash_get_first
|
||||
dm_hash_get_next
|
||||
dm_set_selinux_context
|
||||
dm_task_set_geometry
|
||||
|
||||
@@ -42,8 +42,9 @@ CFLAGS += -DDEVICE_UID=@DEVICE_UID@ -DDEVICE_GID=@DEVICE_GID@ \
|
||||
|
||||
include ../make.tmpl
|
||||
|
||||
.PHONY: install_dynamic install_static \
|
||||
install_fs install_ioctl install_ioctl_static
|
||||
.PHONY: install_dynamic install_static install_include \
|
||||
install_fs install_ioctl install_ioctl_static \
|
||||
install_pkgconfig
|
||||
|
||||
INSTALL_TYPE = install_dynamic
|
||||
|
||||
@@ -51,18 +52,22 @@ ifeq ("@STATIC_LINK@", "yes")
|
||||
INSTALL_TYPE += install_static
|
||||
endif
|
||||
|
||||
install: $(INSTALL_TYPE)
|
||||
ifeq ("@PKGCONFIG@", "yes")
|
||||
INSTALL_TYPE += install_pkgconfig
|
||||
endif
|
||||
|
||||
install: $(INSTALL_TYPE) install_include
|
||||
|
||||
install_include:
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 444 libdevmapper.h \
|
||||
$(includedir)/libdevmapper.h
|
||||
|
||||
install_dynamic: install_@interface@
|
||||
$(LN_S) -f libdevmapper.$(LIB_SUFFIX).$(LIB_VERSION) \
|
||||
$(libdir)/libdevmapper.$(LIB_SUFFIX)
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 444 libdevmapper.h \
|
||||
$(includedir)/libdevmapper.h
|
||||
|
||||
install_static: install_@interface@_static
|
||||
$(LN_S) -f libdevmapper.a.$(LIB_VERSION) $(libdir)/libdevmapper.a
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 444 libdevmapper.h \
|
||||
$(includedir)/libdevmapper.h
|
||||
|
||||
install_fs: fs/libdevmapper.$(LIB_SUFFIX)
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
|
||||
@@ -72,6 +77,10 @@ install_ioctl: ioctl/libdevmapper.$(LIB_SUFFIX)
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
|
||||
$(libdir)/libdevmapper.$(LIB_SUFFIX).$(LIB_VERSION)
|
||||
|
||||
install_pkgconfig:
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 444 libdevmapper.pc \
|
||||
$(usrlibdir)/pkgconfig/devmapper.pc
|
||||
|
||||
install_ioctl_static: ioctl/libdevmapper.a
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
|
||||
$(libdir)/libdevmapper.a.$(LIB_VERSION)
|
||||
@@ -79,7 +88,7 @@ install_ioctl_static: ioctl/libdevmapper.a
|
||||
.PHONY: distclean_lib distclean
|
||||
|
||||
distclean_lib:
|
||||
$(RM) libdm-common.h
|
||||
$(RM) libdm-common.h libdevmapper.pc
|
||||
|
||||
distclean: distclean_lib
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ void dm_bit_union(dm_bitset_t out, dm_bitset_t in1, dm_bitset_t in2)
|
||||
*/
|
||||
static inline int _test_word(uint32_t test, int bit)
|
||||
{
|
||||
while (bit < DM_BITS_PER_INT) {
|
||||
while (bit < (int) DM_BITS_PER_INT) {
|
||||
if (test & (0x1 << bit))
|
||||
return bit;
|
||||
bit++;
|
||||
@@ -73,7 +73,10 @@ int dm_bit_get_next(dm_bitset_t bs, int last_bit)
|
||||
|
||||
last_bit++; /* otherwise we'll return the same bit again */
|
||||
|
||||
while (last_bit < bs[0]) {
|
||||
/*
|
||||
* bs[0] holds number of bits
|
||||
*/
|
||||
while (last_bit < (int) bs[0]) {
|
||||
word = last_bit >> INT_SHIFT;
|
||||
test = bs[word + 1];
|
||||
bit = last_bit & (DM_BITS_PER_INT - 1);
|
||||
|
||||
@@ -18,13 +18,13 @@
|
||||
struct dm_hash_node {
|
||||
struct dm_hash_node *next;
|
||||
void *data;
|
||||
int keylen;
|
||||
unsigned keylen;
|
||||
char key[0];
|
||||
};
|
||||
|
||||
struct dm_hash_table {
|
||||
int num_nodes;
|
||||
int num_slots;
|
||||
unsigned num_nodes;
|
||||
unsigned num_slots;
|
||||
struct dm_hash_node **slots;
|
||||
};
|
||||
|
||||
@@ -56,7 +56,7 @@ static unsigned char _nums[] = {
|
||||
209
|
||||
};
|
||||
|
||||
static struct dm_hash_node *_create_node(const char *str, int len)
|
||||
static struct dm_hash_node *_create_node(const char *str, unsigned len)
|
||||
{
|
||||
struct dm_hash_node *n = dm_malloc(sizeof(*n) + len);
|
||||
|
||||
@@ -68,13 +68,14 @@ static struct dm_hash_node *_create_node(const char *str, int len)
|
||||
return n;
|
||||
}
|
||||
|
||||
static unsigned _hash(const char *str, uint32_t len)
|
||||
static unsigned long _hash(const unsigned char *str, unsigned len)
|
||||
{
|
||||
unsigned long h = 0, g, i;
|
||||
unsigned long h = 0, g;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
h <<= 4;
|
||||
h += _nums[(int) *str++];
|
||||
h += _nums[*str++];
|
||||
g = h & ((unsigned long) 0xf << 16u);
|
||||
if (g) {
|
||||
h ^= g >> 16u;
|
||||
@@ -120,7 +121,7 @@ struct dm_hash_table *dm_hash_create(unsigned size_hint)
|
||||
static void _free_nodes(struct dm_hash_table *t)
|
||||
{
|
||||
struct dm_hash_node *c, *n;
|
||||
int i;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < t->num_slots; i++)
|
||||
for (c = t->slots[i]; c; c = n) {
|
||||
@@ -136,8 +137,8 @@ void dm_hash_destroy(struct dm_hash_table *t)
|
||||
dm_free(t);
|
||||
}
|
||||
|
||||
static inline struct dm_hash_node **_find(struct dm_hash_table *t, const char *key,
|
||||
uint32_t len)
|
||||
static struct dm_hash_node **_find(struct dm_hash_table *t, const char *key,
|
||||
uint32_t len)
|
||||
{
|
||||
unsigned h = _hash(key, len) & (t->num_slots - 1);
|
||||
struct dm_hash_node **c;
|
||||
@@ -153,11 +154,12 @@ void *dm_hash_lookup_binary(struct dm_hash_table *t, const char *key,
|
||||
uint32_t len)
|
||||
{
|
||||
struct dm_hash_node **c = _find(t, key, len);
|
||||
|
||||
return *c ? (*c)->data : 0;
|
||||
}
|
||||
|
||||
int dm_hash_insert_binary(struct dm_hash_table *t, const char *key,
|
||||
uint32_t len, void *data)
|
||||
uint32_t len, void *data)
|
||||
{
|
||||
struct dm_hash_node **c = _find(t, key, len);
|
||||
|
||||
@@ -214,7 +216,7 @@ unsigned dm_hash_get_num_entries(struct dm_hash_table *t)
|
||||
void dm_hash_iter(struct dm_hash_table *t, dm_hash_iterate_fn f)
|
||||
{
|
||||
struct dm_hash_node *c;
|
||||
int i;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < t->num_slots; i++)
|
||||
for (c = t->slots[i]; c; c = c->next)
|
||||
@@ -225,7 +227,7 @@ void dm_hash_wipe(struct dm_hash_table *t)
|
||||
{
|
||||
_free_nodes(t);
|
||||
memset(t->slots, 0, sizeof(struct dm_hash_node *) * t->num_slots);
|
||||
t->num_nodes = 0;
|
||||
t->num_nodes = 0u;
|
||||
}
|
||||
|
||||
char *dm_hash_get_key(struct dm_hash_table *t, struct dm_hash_node *n)
|
||||
@@ -241,7 +243,7 @@ void *dm_hash_get_data(struct dm_hash_table *t, struct dm_hash_node *n)
|
||||
static struct dm_hash_node *_next_slot(struct dm_hash_table *t, unsigned s)
|
||||
{
|
||||
struct dm_hash_node *c = NULL;
|
||||
int i;
|
||||
unsigned i;
|
||||
|
||||
for (i = s; i < t->num_slots && !c; i++)
|
||||
c = t->slots[i];
|
||||
@@ -257,5 +259,6 @@ struct dm_hash_node *dm_hash_get_first(struct dm_hash_table *t)
|
||||
struct dm_hash_node *dm_hash_get_next(struct dm_hash_table *t, struct dm_hash_node *n)
|
||||
{
|
||||
unsigned h = _hash(n->key, n->keylen) & (t->num_slots - 1);
|
||||
|
||||
return n->next ? n->next : _next_slot(t, h + 1);
|
||||
}
|
||||
|
||||
@@ -33,107 +33,61 @@ struct list {
|
||||
* The list head's next and previous pointers point back to itself.
|
||||
*/
|
||||
#define LIST_INIT(name) struct list name = { &(name), &(name) }
|
||||
static inline void list_init(struct list *head)
|
||||
{
|
||||
head->n = head->p = head;
|
||||
}
|
||||
void list_init(struct list *head);
|
||||
|
||||
/*
|
||||
* Insert an element before 'head'.
|
||||
* If 'head' is the list head, this adds an element to the end of the list.
|
||||
*/
|
||||
static inline void list_add(struct list *head, struct list *elem)
|
||||
{
|
||||
assert(head->n);
|
||||
|
||||
elem->n = head;
|
||||
elem->p = head->p;
|
||||
|
||||
head->p->n = elem;
|
||||
head->p = elem;
|
||||
}
|
||||
void list_add(struct list *head, struct list *elem);
|
||||
|
||||
/*
|
||||
* Insert an element after 'head'.
|
||||
* If 'head' is the list head, this adds an element to the front of the list.
|
||||
*/
|
||||
static inline void list_add_h(struct list *head, struct list *elem)
|
||||
{
|
||||
assert(head->n);
|
||||
|
||||
elem->n = head->n;
|
||||
elem->p = head;
|
||||
|
||||
head->n->p = elem;
|
||||
head->n = elem;
|
||||
}
|
||||
void list_add_h(struct list *head, struct list *elem);
|
||||
|
||||
/*
|
||||
* Delete an element from its list.
|
||||
* Note that this doesn't change the element itself - it may still be safe
|
||||
* to follow its pointers.
|
||||
*/
|
||||
static inline void list_del(struct list *elem)
|
||||
{
|
||||
elem->n->p = elem->p;
|
||||
elem->p->n = elem->n;
|
||||
}
|
||||
void list_del(struct list *elem);
|
||||
|
||||
/*
|
||||
* Is the list empty?
|
||||
*/
|
||||
static inline int list_empty(struct list *head)
|
||||
{
|
||||
return head->n == head;
|
||||
}
|
||||
int list_empty(struct list *head);
|
||||
|
||||
/*
|
||||
* Is this the first element of the list?
|
||||
*/
|
||||
static inline int list_start(struct list *head, struct list *elem)
|
||||
{
|
||||
return elem->p == head;
|
||||
}
|
||||
int list_start(struct list *head, struct list *elem);
|
||||
|
||||
/*
|
||||
* Is this the last element of the list?
|
||||
*/
|
||||
static inline int list_end(struct list *head, struct list *elem)
|
||||
{
|
||||
return elem->n == head;
|
||||
}
|
||||
int list_end(struct list *head, struct list *elem);
|
||||
|
||||
/*
|
||||
* Return first element of the list or NULL if empty
|
||||
*/
|
||||
static inline struct list *list_first(struct list *head)
|
||||
{
|
||||
return (list_empty(head) ? NULL : head->n);
|
||||
}
|
||||
struct list *list_first(struct list *head);
|
||||
|
||||
/*
|
||||
* Return last element of the list or NULL if empty
|
||||
*/
|
||||
static inline struct list *list_last(struct list *head)
|
||||
{
|
||||
return (list_empty(head) ? NULL : head->p);
|
||||
}
|
||||
struct list *list_last(struct list *head);
|
||||
|
||||
/*
|
||||
* Return the previous element of the list, or NULL if we've reached the start.
|
||||
*/
|
||||
static inline struct list *list_prev(struct list *head, struct list *elem)
|
||||
{
|
||||
return (list_start(head, elem) ? NULL : elem->p);
|
||||
}
|
||||
struct list *list_prev(struct list *head, struct list *elem);
|
||||
|
||||
/*
|
||||
* Return the next element of the list, or NULL if we've reached the end.
|
||||
*/
|
||||
static inline struct list *list_next(struct list *head, struct list *elem)
|
||||
{
|
||||
return (list_end(head, elem) ? NULL : elem->n);
|
||||
}
|
||||
struct list *list_next(struct list *head, struct list *elem);
|
||||
|
||||
/*
|
||||
* Given the address v of an instance of 'struct list' called 'head'
|
||||
@@ -244,15 +198,6 @@ static inline struct list *list_next(struct list *head, struct list *elem)
|
||||
/*
|
||||
* Return the number of elements in a list by walking it.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
unsigned int list_size(const struct list *head);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -116,6 +116,7 @@ static struct cmd_data _cmd_data_v1[] = {
|
||||
{ "mknodes", 0, {4, 0, 0} },
|
||||
{ "versions", 0, {4, 1, 0} },
|
||||
{ "message", 0, {4, 2, 0} },
|
||||
{ "setgeometry",0, {4, 6, 0} },
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
|
||||
@@ -59,7 +59,9 @@
|
||||
#define NUMBER_OF_MAJORS 4096
|
||||
|
||||
/* dm major version no for running kernel */
|
||||
static int _dm_version = DM_VERSION_MAJOR;
|
||||
static unsigned _dm_version = DM_VERSION_MAJOR;
|
||||
static unsigned _dm_version_minor = 0;
|
||||
static unsigned _dm_version_patchlevel = 0;
|
||||
static int _log_suppress = 0;
|
||||
|
||||
static dm_bitset_t _dm_bitset = NULL;
|
||||
@@ -103,6 +105,9 @@ static struct cmd_data _cmd_data_v4[] = {
|
||||
#ifdef DM_TARGET_MSG
|
||||
{"message", DM_TARGET_MSG, {4, 2, 0}},
|
||||
#endif
|
||||
#ifdef DM_DEV_SET_GEOMETRY
|
||||
{"setgeometry", DM_DEV_SET_GEOMETRY, {4, 6, 0}},
|
||||
#endif
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
@@ -236,10 +241,10 @@ static int _create_control(const char *control, uint32_t major, uint32_t minor)
|
||||
}
|
||||
|
||||
#ifdef HAVE_SELINUX
|
||||
if (!dm_set_selinux_context(control, S_IFCHR)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!dm_set_selinux_context(control, S_IFCHR)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
@@ -742,7 +747,7 @@ static int _dm_task_run_v1(struct dm_task *dmt)
|
||||
|
||||
int dm_task_get_driver_version(struct dm_task *dmt, char *version, size_t size)
|
||||
{
|
||||
unsigned int *v;
|
||||
unsigned *v;
|
||||
|
||||
#ifdef DM_COMPAT
|
||||
if (_dm_version == 1)
|
||||
@@ -756,6 +761,9 @@ int dm_task_get_driver_version(struct dm_task *dmt, char *version, size_t size)
|
||||
|
||||
v = dmt->dmi.v4->version;
|
||||
snprintf(version, size, "%u.%u.%u", v[0], v[1], v[2]);
|
||||
_dm_version_minor = v[1];
|
||||
_dm_version_patchlevel = v[2];
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -801,7 +809,7 @@ int dm_check_version(void)
|
||||
if (!_dm_compat)
|
||||
goto bad;
|
||||
|
||||
log_verbose("device-mapper ioctl protocol version %d failed. "
|
||||
log_verbose("device-mapper ioctl protocol version %u failed. "
|
||||
"Trying protocol version 1.", _dm_version);
|
||||
_dm_version = 1;
|
||||
if (_check_version(dmversion, sizeof(dmversion), 0)) {
|
||||
@@ -877,7 +885,7 @@ int dm_format_dev(char *buf, int bufsize, uint32_t dev_major,
|
||||
if (bufsize < 8)
|
||||
return 0;
|
||||
|
||||
r = snprintf(buf, bufsize, "%u:%u", dev_major, dev_minor);
|
||||
r = snprintf(buf, (size_t) bufsize, "%u:%u", dev_major, dev_minor);
|
||||
if (r < 0 || r > bufsize - 1)
|
||||
return 0;
|
||||
|
||||
@@ -1001,6 +1009,23 @@ int dm_task_set_sector(struct dm_task *dmt, uint64_t sector)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int dm_task_set_geometry(struct dm_task *dmt, const char *cylinders, const char *heads, const char *sectors, const char *start)
|
||||
{
|
||||
size_t len = strlen(cylinders) + 1 + strlen(heads) + 1 + strlen(sectors) + 1 + strlen(start) + 1;
|
||||
|
||||
if (!(dmt->geometry = dm_malloc(len))) {
|
||||
log_error("dm_task_set_geometry: dm_malloc failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sprintf(dmt->geometry, "%s %s %s %s", cylinders, heads, sectors, start) < 0) {
|
||||
log_error("dm_task_set_geometry: sprintf failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int dm_task_no_open_count(struct dm_task *dmt)
|
||||
{
|
||||
dmt->no_open_count = 1;
|
||||
@@ -1028,7 +1053,8 @@ struct target *create_target(uint64_t start, uint64_t len, const char *type,
|
||||
struct target *t = dm_malloc(sizeof(*t));
|
||||
|
||||
if (!t) {
|
||||
log_error("create_target: malloc(%d) failed", sizeof(*t));
|
||||
log_error("create_target: malloc(%" PRIsize_t ") failed",
|
||||
sizeof(*t));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1094,6 +1120,40 @@ static void *_add_target(struct target *t, void *out, void *end)
|
||||
return out;
|
||||
}
|
||||
|
||||
static int _lookup_dev_name(uint64_t dev, char *buf, size_t len)
|
||||
{
|
||||
struct dm_names *names;
|
||||
unsigned next = 0;
|
||||
struct dm_task *dmt;
|
||||
int r = 0;
|
||||
|
||||
if (!(dmt = dm_task_create(DM_DEVICE_LIST)))
|
||||
return 0;
|
||||
|
||||
if (!dm_task_run(dmt))
|
||||
goto out;
|
||||
|
||||
if (!(names = dm_task_get_names(dmt)))
|
||||
goto out;
|
||||
|
||||
if (!names->dev)
|
||||
goto out;
|
||||
|
||||
do {
|
||||
names = (void *) names + next;
|
||||
if (names->dev == dev) {
|
||||
strncpy(buf, names->name, len);
|
||||
r = 1;
|
||||
break;
|
||||
}
|
||||
next = names->next;
|
||||
} while (next);
|
||||
|
||||
out:
|
||||
dm_task_destroy(dmt);
|
||||
return r;
|
||||
}
|
||||
|
||||
static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
|
||||
{
|
||||
const size_t min_size = 16 * 1024;
|
||||
@@ -1122,11 +1182,26 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (count && dmt->geometry) {
|
||||
log_error("targets and geometry are incompatible");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (dmt->newname && (dmt->sector || dmt->message)) {
|
||||
log_error("message and newname are incompatible");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (dmt->newname && dmt->geometry) {
|
||||
log_error("geometry and newname are incompatible");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (dmt->geometry && (dmt->sector || dmt->message)) {
|
||||
log_error("geometry and message are incompatible");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (dmt->sector && !dmt->message) {
|
||||
log_error("message is required with sector");
|
||||
return NULL;
|
||||
@@ -1138,6 +1213,9 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
|
||||
if (dmt->message)
|
||||
len += sizeof(struct dm_target_msg) + strlen(dmt->message) + 1;
|
||||
|
||||
if (dmt->geometry)
|
||||
len += strlen(dmt->geometry) + 1;
|
||||
|
||||
/*
|
||||
* Give len a minimum size so that we have space to store
|
||||
* dependencies or status information.
|
||||
@@ -1163,16 +1241,6 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
|
||||
dmi->data_size = len;
|
||||
dmi->data_start = sizeof(struct dm_ioctl);
|
||||
|
||||
if (dmt->dev_name)
|
||||
strncpy(dmi->name, dmt->dev_name, sizeof(dmi->name));
|
||||
|
||||
if (dmt->type == DM_DEVICE_SUSPEND)
|
||||
dmi->flags |= DM_SUSPEND_FLAG;
|
||||
if (dmt->read_only)
|
||||
dmi->flags |= DM_READONLY_FLAG;
|
||||
if (dmt->skip_lockfs)
|
||||
dmi->flags |= DM_SKIP_LOCKFS_FLAG;
|
||||
|
||||
if (dmt->minor >= 0) {
|
||||
if (dmt->major <= 0) {
|
||||
log_error("Missing major number for persistent device.");
|
||||
@@ -1182,9 +1250,31 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
|
||||
dmi->dev = MKDEV(dmt->major, dmt->minor);
|
||||
}
|
||||
|
||||
/* Does driver support device number referencing? */
|
||||
if (_dm_version_minor < 3 && !dmt->dev_name && !dmt->uuid && dmi->dev) {
|
||||
if (!_lookup_dev_name(dmi->dev, dmi->name, sizeof(dmi->name))) {
|
||||
log_error("Unable to find name for device (%" PRIu32
|
||||
":%" PRIu32 ")", dmt->major, dmt->minor);
|
||||
goto bad;
|
||||
}
|
||||
log_verbose("device (%" PRIu32 ":%" PRIu32 ") is %s "
|
||||
"for compatibility with old kernel",
|
||||
dmt->major, dmt->minor, dmi->name);
|
||||
}
|
||||
|
||||
if (dmt->dev_name)
|
||||
strncpy(dmi->name, dmt->dev_name, sizeof(dmi->name));
|
||||
|
||||
if (dmt->uuid)
|
||||
strncpy(dmi->uuid, dmt->uuid, sizeof(dmi->uuid));
|
||||
|
||||
if (dmt->type == DM_DEVICE_SUSPEND)
|
||||
dmi->flags |= DM_SUSPEND_FLAG;
|
||||
if (dmt->read_only)
|
||||
dmi->flags |= DM_READONLY_FLAG;
|
||||
if (dmt->skip_lockfs)
|
||||
dmi->flags |= DM_SKIP_LOCKFS_FLAG;
|
||||
|
||||
dmi->target_count = count;
|
||||
dmi->event_nr = dmt->event_nr;
|
||||
|
||||
@@ -1204,6 +1294,9 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
|
||||
strcpy(tmsg->message, dmt->message);
|
||||
}
|
||||
|
||||
if (dmt->geometry)
|
||||
strcpy(b, dmt->geometry);
|
||||
|
||||
return dmi;
|
||||
|
||||
bad:
|
||||
@@ -1310,6 +1403,9 @@ static int _create_and_load_v4(struct dm_task *dmt)
|
||||
|
||||
task->major = dmt->major;
|
||||
task->minor = dmt->minor;
|
||||
task->uid = dmt->uid;
|
||||
task->gid = dmt->gid;
|
||||
task->mode = dmt->mode;
|
||||
|
||||
r = dm_task_run(task);
|
||||
dm_task_destroy(task);
|
||||
@@ -1338,7 +1434,7 @@ static int _create_and_load_v4(struct dm_task *dmt)
|
||||
task->tail = NULL;
|
||||
dm_task_destroy(task);
|
||||
if (!r)
|
||||
return r;
|
||||
goto revert;
|
||||
|
||||
/* Use the original structure last so the info will be correct */
|
||||
dmt->type = DM_DEVICE_RESUME;
|
||||
@@ -1347,6 +1443,17 @@ static int _create_and_load_v4(struct dm_task *dmt)
|
||||
|
||||
r = dm_task_run(dmt);
|
||||
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
revert:
|
||||
dmt->type = DM_DEVICE_REMOVE;
|
||||
dm_free(dmt->uuid);
|
||||
dmt->uuid = NULL;
|
||||
|
||||
if (!dm_task_run(dmt))
|
||||
log_error("Failed to revert device creation.");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -1434,7 +1541,7 @@ static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command,
|
||||
if (dmt->no_open_count)
|
||||
dmi->flags |= DM_SKIP_BDGET_FLAG;
|
||||
|
||||
log_debug("dm %s %s %s%s%s %s%0.0d%s%0.0d%s"
|
||||
log_debug("dm %s %s %s%s%s %s%.0d%s%.0d%s"
|
||||
"%s%c %.0llu %s [%u]",
|
||||
_cmd_data_v4[dmt->type].name,
|
||||
dmi->name, dmi->uuid, dmt->newname ? " " : "",
|
||||
@@ -1567,6 +1674,9 @@ repeat_ioctl:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Was structure reused? */
|
||||
if (dmt->dmi.v4)
|
||||
dm_free(dmt->dmi.v4);
|
||||
dmt->dmi.v4 = dmi;
|
||||
return 1;
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@ struct dm_task {
|
||||
} dmi;
|
||||
char *newname;
|
||||
char *message;
|
||||
char *geometry;
|
||||
uint64_t sector;
|
||||
int no_open_count;
|
||||
int skip_lockfs;
|
||||
|
||||
@@ -42,7 +42,8 @@
|
||||
*/
|
||||
|
||||
typedef void (*dm_log_fn) (int level, const char *file, int line,
|
||||
const char *f, ...);
|
||||
const char *f, ...)
|
||||
__attribute__ ((format(printf, 4, 5)));
|
||||
|
||||
/*
|
||||
* The library user may wish to register their own
|
||||
@@ -79,7 +80,9 @@ enum {
|
||||
|
||||
DM_DEVICE_LIST_VERSIONS,
|
||||
|
||||
DM_DEVICE_TARGET_MSG
|
||||
DM_DEVICE_TARGET_MSG,
|
||||
|
||||
DM_DEVICE_SET_GEOMETRY
|
||||
};
|
||||
|
||||
struct dm_task;
|
||||
@@ -140,7 +143,11 @@ int dm_task_set_ro(struct dm_task *dmt);
|
||||
int dm_task_set_newname(struct dm_task *dmt, const char *newname);
|
||||
int dm_task_set_minor(struct dm_task *dmt, int minor);
|
||||
int dm_task_set_major(struct dm_task *dmt, int major);
|
||||
int dm_task_set_uid(struct dm_task *dmt, uid_t uid);
|
||||
int dm_task_set_gid(struct dm_task *dmt, gid_t gid);
|
||||
int dm_task_set_mode(struct dm_task *dmt, mode_t mode);
|
||||
int dm_task_set_event_nr(struct dm_task *dmt, uint32_t event_nr);
|
||||
int dm_task_set_geometry(struct dm_task *dmt, const char *cylinders, const char *heads, const char *sectors, const char *start);
|
||||
int dm_task_set_message(struct dm_task *dmt, const char *message);
|
||||
int dm_task_set_sector(struct dm_task *dmt, uint64_t sector);
|
||||
int dm_task_no_open_count(struct dm_task *dmt);
|
||||
@@ -299,6 +306,13 @@ int dm_tree_suspend_children(struct dm_tree_node *dnode,
|
||||
const char *uuid_prefix,
|
||||
size_t uuid_prefix_len);
|
||||
|
||||
/*
|
||||
* Skip the filesystem sync when suspending.
|
||||
* Does nothing with other functions.
|
||||
* Use this when no snapshots are involved.
|
||||
*/
|
||||
void dm_tree_skip_lockfs(struct dm_tree_node *dnode);
|
||||
|
||||
/*
|
||||
* Is the uuid prefix present in the tree?
|
||||
* Only returns 0 if every node was checked successfully.
|
||||
@@ -331,11 +345,18 @@ int dm_tree_node_add_striped_target(struct dm_tree_node *node,
|
||||
uint32_t stripe_size);
|
||||
int dm_tree_node_add_mirror_target(struct dm_tree_node *node,
|
||||
uint64_t size);
|
||||
|
||||
/* Mirror log flags */
|
||||
#define DM_NOSYNC 0x00000001 /* Known already in sync */
|
||||
#define DM_FORCESYNC 0x00000002 /* Force resync */
|
||||
#define DM_BLOCK_ON_ERROR 0x00000004 /* On error, suspend I/O */
|
||||
|
||||
int dm_tree_node_add_mirror_target_log(struct dm_tree_node *node,
|
||||
uint32_t region_size,
|
||||
unsigned clustered,
|
||||
const char *log_uuid,
|
||||
unsigned area_count);
|
||||
unsigned area_count,
|
||||
uint32_t flags);
|
||||
int dm_tree_node_add_target_area(struct dm_tree_node *node,
|
||||
const char *dev_name,
|
||||
const char *dlid,
|
||||
@@ -349,10 +370,9 @@ int dm_tree_node_add_target_area(struct dm_tree_node *node,
|
||||
* Memory management
|
||||
*******************/
|
||||
|
||||
char *dm_strdup(const char *str);
|
||||
|
||||
void *dm_malloc_aux(size_t s, const char *file, int line);
|
||||
void *dm_malloc_aux_debug(size_t s, const char *file, int line);
|
||||
char *dm_strdup_aux(const char *str, const char *file, int line);
|
||||
void dm_free_aux(void *p);
|
||||
void *dm_realloc_aux(void *p, unsigned int s, const char *file, int line);
|
||||
int dm_dump_memory_debug(void);
|
||||
@@ -361,6 +381,7 @@ void dm_bounds_check_debug(void);
|
||||
#ifdef DEBUG_MEM
|
||||
|
||||
# define dm_malloc(s) dm_malloc_aux_debug((s), __FILE__, __LINE__)
|
||||
# define dm_strdup(s) dm_strdup_aux((s), __FILE__, __LINE__)
|
||||
# define dm_free(p) dm_free_aux(p)
|
||||
# define dm_realloc(p, s) dm_realloc_aux(p, s, __FILE__, __LINE__)
|
||||
# define dm_dump_memory() dm_dump_memory_debug()
|
||||
@@ -369,6 +390,7 @@ void dm_bounds_check_debug(void);
|
||||
#else
|
||||
|
||||
# define dm_malloc(s) dm_malloc_aux((s), __FILE__, __LINE__)
|
||||
# define dm_strdup(s) strdup(s)
|
||||
# define dm_free(p) free(p)
|
||||
# define dm_realloc(p, s) realloc(p, s)
|
||||
# define dm_dump_memory() {}
|
||||
@@ -509,6 +531,17 @@ int dm_bit_get_next(dm_bitset_t bs, int last_bit);
|
||||
#define dm_bit_copy(bs1, bs2) \
|
||||
memcpy(bs1 + 1, bs2 + 1, ((*bs1 / DM_BITS_PER_INT) + 1) * sizeof(int))
|
||||
|
||||
/* Returns number of set bits */
|
||||
static inline unsigned hweight32(uint32_t i)
|
||||
{
|
||||
unsigned r = (i & 0x55555555) + ((i >> 1) & 0x55555555);
|
||||
|
||||
r = (r & 0x33333333) + ((r >> 2) & 0x33333333);
|
||||
r = (r & 0x0F0F0F0F) + ((r >> 4) & 0x0F0F0F0F);
|
||||
r = (r & 0x00FF00FF) + ((r >> 8) & 0x00FF00FF);
|
||||
return (r & 0x0000FFFF) + ((r >> 16) & 0x0000FFFF);
|
||||
}
|
||||
|
||||
/****************
|
||||
* hash functions
|
||||
****************/
|
||||
@@ -543,9 +576,9 @@ struct dm_hash_node *dm_hash_get_next(struct dm_hash_table *t, struct dm_hash_no
|
||||
for (v = dm_hash_get_first(h); v; \
|
||||
v = dm_hash_get_next(h, v))
|
||||
|
||||
#endif /* LIB_DEVICE_MAPPER_H */
|
||||
|
||||
/*********
|
||||
* selinux
|
||||
*********/
|
||||
int dm_set_selinux_context(const char *path, mode_t mode);
|
||||
|
||||
#endif /* LIB_DEVICE_MAPPER_H */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user