mirror of
git://sourceware.org/git/lvm2.git
synced 2025-12-25 20:23:49 +03:00
Compare commits
85 Commits
dm_v1_02_0
...
dm_v1_02_1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1485586f7e | ||
|
|
d5c9024335 | ||
|
|
860cf80703 | ||
|
|
897ff3161f | ||
|
|
b356b2e501 | ||
|
|
1d2733c893 | ||
|
|
32d9126094 | ||
|
|
db43314e50 | ||
|
|
68d2baeb65 | ||
|
|
1fd5f562d3 | ||
|
|
48e02f2086 | ||
|
|
eab7b2b581 | ||
|
|
45abade7fc | ||
|
|
5372fc4b43 | ||
|
|
4e2f240c98 | ||
|
|
bb3605518d | ||
|
|
3ef6d37f27 | ||
|
|
88e9f2f7f4 | ||
|
|
704a447df9 | ||
|
|
a5fcb26a33 | ||
|
|
2491a61481 | ||
|
|
91831d51ed | ||
|
|
174f0c19f7 | ||
|
|
de6fadfb4f | ||
|
|
f946db3e00 | ||
|
|
8d05e5bc31 | ||
|
|
cfb46820e4 | ||
|
|
081f1cbcc2 | ||
|
|
7bc6da326f | ||
|
|
cd95a0df7b | ||
|
|
82fa497c16 | ||
|
|
44fd345206 | ||
|
|
088e1c9db4 | ||
|
|
d4f16e666e | ||
|
|
8233cfd371 | ||
|
|
ff05e2e30d | ||
|
|
a8ea7dd3fb | ||
|
|
96f70a5303 | ||
|
|
f1604c3e69 | ||
|
|
c42c8c5192 | ||
|
|
5facb53a41 | ||
|
|
d039ce89af | ||
|
|
bc7605103f | ||
|
|
d305d655d4 | ||
|
|
4ef1220b16 | ||
|
|
a4fef143cd | ||
|
|
74ecb724a9 | ||
|
|
af235897ab | ||
|
|
5ec4e458b5 | ||
|
|
2dae63ce21 | ||
|
|
be748fe33b | ||
|
|
7408340b6a | ||
|
|
29eb92446e | ||
|
|
ae6918742e | ||
|
|
863484bb65 | ||
|
|
1cd7ebce4c | ||
|
|
eef8c7862e | ||
|
|
b52375d446 | ||
|
|
6e2babc2ce | ||
|
|
08e253bed1 | ||
|
|
c6661477a2 | ||
|
|
415cfd99a0 | ||
|
|
8c2e37381a | ||
|
|
45df79feba | ||
|
|
5824f992b7 | ||
|
|
b0b60fafd5 | ||
|
|
8d98b02ba2 | ||
|
|
a93fe79bc4 | ||
|
|
4aebd7be37 | ||
|
|
3170a5db32 | ||
|
|
3605b9eef6 | ||
|
|
a945f1fde2 | ||
|
|
461a997b5b | ||
|
|
a80afd7b4e | ||
|
|
aad2b51d85 | ||
|
|
36a9a81ff1 | ||
|
|
42c88546ae | ||
|
|
0f0e86ef9b | ||
|
|
98efd9a857 | ||
|
|
a0c27d95b7 | ||
|
|
984651d99d | ||
|
|
c6f7370b30 | ||
|
|
3e4b8e8985 | ||
|
|
73f08b98d2 | ||
|
|
8607a74206 |
70
WHATS_NEW
70
WHATS_NEW
@@ -1,5 +1,71 @@
|
||||
Version 2.02.08 -
|
||||
================================
|
||||
Version 2.02.12 -
|
||||
===================================
|
||||
Propogate clustered flag in vgsplit and require resizeable flag.
|
||||
|
||||
Version 2.02.11 - 12th October 2006
|
||||
===================================
|
||||
Add clvmd function to return the cluster name. not used by LVM yet.
|
||||
Add cling allocation policy.
|
||||
Change _check_contiguous() to use _for_each_pv().
|
||||
Extend _for_each_pv() to allow termination without error.
|
||||
Abstract _is_contiguous().
|
||||
Remove duplicated pv arg from _check_contiguous().
|
||||
Accept regionsize with lvconvert.
|
||||
Add report columns with underscore before field names ending 'size'.
|
||||
Correct regionsize default on lvcreate man page (MB).
|
||||
Fix clvmd bug that could cause it to die when a node with a long name crashed.
|
||||
Add device size to text metadata.
|
||||
Fix format_text mda_setup pv->size and pv_setup pe_count calculations.
|
||||
Fix _for_each_pv() for mirror with core log.
|
||||
Add lvm_dump.sh script to create a tarball of debugging info from a system.
|
||||
Capture error messages in clvmd and pass them back to the user.
|
||||
Remove unused #defines from filter-md.c.
|
||||
Make clvmd restart init script wait until clvmd has died before starting it.
|
||||
Add -R to clvmd which tells running clvmds to reload their device cache.
|
||||
Add LV column to reports listing kernel modules needed for activation.
|
||||
Show available fields if report given invalid field. (e.g. lvs -o list)
|
||||
Add timestamp functions with --disable-realtime configure option.
|
||||
Add %VG, %LV and %FREE suffices to lvcreate/lvresize --extents arg.
|
||||
Fix two potential NULL pointer derefs in error cases in vg_read().
|
||||
Separate --enable-cluster from locking lib options in lvmconf.sh.
|
||||
Add a missing comma in lvcreate man page.
|
||||
|
||||
Version 2.02.10 - 19th September 2006
|
||||
=====================================
|
||||
Fix lvconvert mirror change case detection logic.
|
||||
Fix mirror log detachment so it correctly becomes a standalone LV.
|
||||
Extend _check_contiguous() to detect single-area LVs.
|
||||
Include mirror log (untested) in _for_each_pv() processing.
|
||||
Use MIRROR_LOG_SIZE constant.
|
||||
Remove struct seg_pvs from _for_each_pv() to generalise.
|
||||
Avoid adding duplicates to list of parallel PVs to avoid.
|
||||
Fix several incorrect comparisons in parallel area avoidance code.
|
||||
Fix segment lengths when flattening existing parallel areas.
|
||||
Log existing parallel areas prior to allocation.
|
||||
Fix mirror log creation when activation disabled.
|
||||
Don't attempt automatic recovery without proper locking.
|
||||
When using local file locking, skip clustered VGs.
|
||||
Add fallback_to_clustered_locking and fallback_to_local_locking parameters.
|
||||
lvm.static uses built-in cluster locking instead of external locking.
|
||||
Don't attempt to load shared libraries if built statically.
|
||||
Change default locking_lib to liblvm2clusterlock.so.
|
||||
Add skip_dev_dir() to process command line VGs.
|
||||
Stop clvmd complaining about nodes that have left the cluster.
|
||||
Move lvm_snprintf(), split_words() and split_dm_name() into libdevmapper.
|
||||
Add lvconvert man page.
|
||||
Add mirror options to man pages.
|
||||
Prevent mirror renames.
|
||||
Move CMDLIB code into separate file and record whether static build.
|
||||
|
||||
Version 2.02.09 - 17th August 2006
|
||||
==================================
|
||||
Fix PE_ALIGN for pagesize over 32KB.
|
||||
Separate out LVM1_PE_ALIGN and pe_align().
|
||||
Add lvm_getpagesize wrapper.
|
||||
Add --maxphysicalvolumes to vgchange.
|
||||
|
||||
Version 2.02.08 - 15th August 2006
|
||||
==================================
|
||||
Add checks for duplicate LV name, lvid and PV id before writing metadata.
|
||||
Report all sanity check failures, not just the first.
|
||||
Fix missing lockfs on first snapshot creation.
|
||||
|
||||
17
WHATS_NEW_DM
17
WHATS_NEW_DM
@@ -1,5 +1,20 @@
|
||||
Version 1.02.09 - 15 Aug 2006
|
||||
Version 1.02.12 - 13 Oct 2006
|
||||
=============================
|
||||
Avoid deptree attempting to suspend a device that's already suspended.
|
||||
|
||||
Version 1.02.11 - 12 Oct 2006
|
||||
==============================
|
||||
Add suspend noflush support.
|
||||
Add basic dmsetup loop support.
|
||||
Switch dmsetup to use dm_malloc and dm_free.
|
||||
|
||||
Version 1.02.10 - 19 Sep 2006
|
||||
=============================
|
||||
Add dm_snprintf(), dm_split_words() and dm_split_lvm_name() to libdevmapper.
|
||||
Reorder mm bounds_check code to reduce window for a dmeventd race.
|
||||
|
||||
Version 1.02.09 - 15 Aug 2006
|
||||
=============================
|
||||
Add --table argument to dmsetup for a one-line table.
|
||||
Abort if errors are found during cmdline option processing.
|
||||
Add lockfs indicator to debug output.
|
||||
|
||||
116
configure
vendored
116
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 CFLOW_CMD CSCOPE_CMD CPP EGREP ALLOCA LIBOBJS POW_LIB MSGFMT MODPROBE_CMD JOBS STATIC_LINK LVM1 POOL SNAPSHOTS MIRRORS OWNER GROUP 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_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 COPTIMISE_FLAG CLDFLAGS CLDWHOLEARCHIVE CLDNOWHOLEARCHIVE LDDEPS LIB_SUFFIX LVM_VERSION LVM1_FALLBACK DEBUG DEVMAPPER HAVE_LIBDL HAVE_SELINUX HAVE_REALTIME CMDLIB LOCALEDIR CONFDIR STATICDIR INTL_PACKAGE INTL CLVMD CLUSTER FSADM DMEVENTD LTLIBOBJS'
|
||||
ac_subst_files=''
|
||||
|
||||
# Initialize some variables set by options.
|
||||
@@ -853,6 +853,7 @@ Optional Features:
|
||||
statically. Default is dynamic linking
|
||||
--enable-readline Enable readline support
|
||||
--disable-selinux Disable selinux support
|
||||
--disable-realtime Disable realtime clock support
|
||||
--enable-debug Enable debugging
|
||||
--disable-devmapper Disable device-mapper interaction
|
||||
--disable-o_direct Disable O_DIRECT
|
||||
@@ -1459,6 +1460,7 @@ case "$host_os" in
|
||||
DEVMAPPER=yes
|
||||
ODIRECT=yes
|
||||
SELINUX=yes
|
||||
REALTIME=yes
|
||||
CLUSTER=internal
|
||||
FSADM=no ;;
|
||||
darwin*)
|
||||
@@ -1473,6 +1475,7 @@ case "$host_os" in
|
||||
DEVMAPPER=yes
|
||||
ODIRECT=no
|
||||
SELINUX=no
|
||||
REALTIME=no
|
||||
CLUSTER=none
|
||||
FSADM=no ;;
|
||||
esac
|
||||
@@ -7431,6 +7434,17 @@ fi;
|
||||
echo "$as_me:$LINENO: result: $SELINUX" >&5
|
||||
echo "${ECHO_T}$SELINUX" >&6
|
||||
|
||||
################################################################################
|
||||
echo "$as_me:$LINENO: checking whether to enable realtime support" >&5
|
||||
echo $ECHO_N "checking whether to enable realtime support... $ECHO_C" >&6
|
||||
# Check whether --enable-realtime or --disable-realtime was given.
|
||||
if test "${enable_realtime+set}" = set; then
|
||||
enableval="$enable_realtime"
|
||||
REALTIME=$enableval
|
||||
fi;
|
||||
echo "$as_me:$LINENO: result: $REALTIME" >&5
|
||||
echo "${ECHO_T}$REALTIME" >&6
|
||||
|
||||
################################################################################
|
||||
echo "$as_me:$LINENO: checking whether to build cluster LVM daemon" >&5
|
||||
echo $ECHO_N "checking whether to build cluster LVM daemon... $ECHO_C" >&6
|
||||
@@ -7534,14 +7548,6 @@ fi;
|
||||
echo "$as_me:$LINENO: result: $CMDLIB" >&5
|
||||
echo "${ECHO_T}$CMDLIB" >&6
|
||||
|
||||
if test x$CMDLIB = xyes; then
|
||||
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define CMDLIB 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
echo "$as_me:$LINENO: checking whether to build fsadm" >&5
|
||||
echo $ECHO_N "checking whether to build fsadm... $ECHO_C" >&6
|
||||
@@ -8428,6 +8434,96 @@ echo "$as_me: WARNING: Disabling selinux" >&2;}
|
||||
fi
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
if test x$REALTIME = xyes; then
|
||||
echo "$as_me:$LINENO: checking for clock_gettime function" >&5
|
||||
echo $ECHO_N "checking for clock_gettime function... $ECHO_C" >&6
|
||||
echo "$as_me:$LINENO: checking for clock_gettime in -lrt" >&5
|
||||
echo $ECHO_N "checking for clock_gettime in -lrt... $ECHO_C" >&6
|
||||
if test "${ac_cv_lib_rt_clock_gettime+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
ac_check_lib_save_LIBS=$LIBS
|
||||
LIBS="-lrt $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 clock_gettime ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
clock_gettime ();
|
||||
;
|
||||
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_rt_clock_gettime=yes
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
ac_cv_lib_rt_clock_gettime=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_rt_clock_gettime" >&5
|
||||
echo "${ECHO_T}$ac_cv_lib_rt_clock_gettime" >&6
|
||||
if test $ac_cv_lib_rt_clock_gettime = yes; then
|
||||
HAVE_REALTIME=yes
|
||||
else
|
||||
HAVE_REALTIME=no
|
||||
fi
|
||||
|
||||
echo "$as_me:$LINENO: result: $HAVE_REALTIME" >&5
|
||||
echo "${ECHO_T}$HAVE_REALTIME" >&6
|
||||
|
||||
if test x$HAVE_REALTIME = xyes; then
|
||||
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define HAVE_REALTIME 1
|
||||
_ACEOF
|
||||
|
||||
LIBS="-lrt $LIBS"
|
||||
else
|
||||
{ echo "$as_me:$LINENO: WARNING: Disabling realtime clock" >&5
|
||||
echo "$as_me: WARNING: Disabling realtime clock" >&2;}
|
||||
fi
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
|
||||
for ac_header in getopt.h
|
||||
@@ -11103,6 +11199,7 @@ fi
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
################################################################################
|
||||
@@ -11797,6 +11894,7 @@ s,@DEBUG@,$DEBUG,;t t
|
||||
s,@DEVMAPPER@,$DEVMAPPER,;t t
|
||||
s,@HAVE_LIBDL@,$HAVE_LIBDL,;t t
|
||||
s,@HAVE_SELINUX@,$HAVE_SELINUX,;t t
|
||||
s,@HAVE_REALTIME@,$HAVE_REALTIME,;t t
|
||||
s,@CMDLIB@,$CMDLIB,;t t
|
||||
s,@LOCALEDIR@,$LOCALEDIR,;t t
|
||||
s,@CONFDIR@,$CONFDIR,;t t
|
||||
|
||||
29
configure.in
29
configure.in
@@ -42,6 +42,7 @@ case "$host_os" in
|
||||
DEVMAPPER=yes
|
||||
ODIRECT=yes
|
||||
SELINUX=yes
|
||||
REALTIME=yes
|
||||
CLUSTER=internal
|
||||
FSADM=no ;;
|
||||
darwin*)
|
||||
@@ -56,6 +57,7 @@ case "$host_os" in
|
||||
DEVMAPPER=yes
|
||||
ODIRECT=no
|
||||
SELINUX=no
|
||||
REALTIME=no
|
||||
CLUSTER=none
|
||||
FSADM=no ;;
|
||||
esac
|
||||
@@ -282,6 +284,13 @@ AC_ARG_ENABLE(selinux, [ --disable-selinux Disable selinux support],
|
||||
SELINUX=$enableval)
|
||||
AC_MSG_RESULT($SELINUX)
|
||||
|
||||
################################################################################
|
||||
dnl -- Disable realtime clock support
|
||||
AC_MSG_CHECKING(whether to enable realtime support)
|
||||
AC_ARG_ENABLE(realtime, [ --disable-realtime Disable realtime clock support],
|
||||
REALTIME=$enableval)
|
||||
AC_MSG_RESULT($REALTIME)
|
||||
|
||||
################################################################################
|
||||
dnl -- Build cluster LVM daemon
|
||||
AC_MSG_CHECKING(whether to build cluster LVM daemon)
|
||||
@@ -351,10 +360,6 @@ AC_ARG_ENABLE(cmdlib, [ --enable-cmdlib Build shared command library],
|
||||
CMDLIB=$enableval, CMDLIB=no)
|
||||
AC_MSG_RESULT($CMDLIB)
|
||||
|
||||
if test x$CMDLIB = xyes; then
|
||||
AC_DEFINE([CMDLIB], 1, [Define to 1 to build the shared command library.])
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Enable fsadm
|
||||
AC_MSG_CHECKING(whether to build fsadm)
|
||||
@@ -453,6 +458,21 @@ if test x$SELINUX = xyes; then
|
||||
fi
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Check for realtime clock support
|
||||
if test x$REALTIME = xyes; then
|
||||
AC_MSG_CHECKING(for clock_gettime function)
|
||||
AC_CHECK_LIB(rt, clock_gettime, HAVE_REALTIME=yes, HAVE_REALTIME=no)
|
||||
AC_MSG_RESULT($HAVE_REALTIME)
|
||||
|
||||
if test x$HAVE_REALTIME = xyes; then
|
||||
AC_DEFINE([HAVE_REALTIME], 1, [Define to 1 to include support for realtime clock.])
|
||||
LIBS="-lrt $LIBS"
|
||||
else
|
||||
AC_MSG_WARN(Disabling realtime clock)
|
||||
fi
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Check for getopt
|
||||
AC_CHECK_HEADERS(getopt.h, AC_DEFINE([HAVE_GETOPTLONG], 1, [Define to 1 to if getopt_long is available.]))
|
||||
@@ -582,6 +602,7 @@ AC_SUBST(DEBUG)
|
||||
AC_SUBST(DEVMAPPER)
|
||||
AC_SUBST(HAVE_LIBDL)
|
||||
AC_SUBST(HAVE_SELINUX)
|
||||
AC_SUBST(HAVE_REALTIME)
|
||||
AC_SUBST(CMDLIB)
|
||||
AC_SUBST(MSGFMT)
|
||||
AC_SUBST(LOCALEDIR)
|
||||
|
||||
@@ -19,6 +19,7 @@ SOURCES = \
|
||||
clvmd-command.c \
|
||||
clvmd.c \
|
||||
lvm-functions.c \
|
||||
refresh_clvmd.c \
|
||||
system-lv.c
|
||||
|
||||
ifeq ("@CLVMD@", "gulm")
|
||||
|
||||
@@ -63,4 +63,8 @@ static const char CLVMD_SOCKNAME[] = "\0clvmd";
|
||||
#define CLVMD_CMD_LOCK_LV 50
|
||||
#define CLVMD_CMD_LOCK_VG 51
|
||||
|
||||
/* Misc functions */
|
||||
#define CLVMD_CMD_REFRESH 40
|
||||
#define CLVMD_CMD_GET_CLUSTERNAME 41
|
||||
|
||||
#endif
|
||||
|
||||
@@ -137,7 +137,7 @@ static int _cluster_send_message(void *buf, int msglen, char *csid, const char *
|
||||
|
||||
if (cman_send_data(c_handle, buf, msglen, 0, CLUSTER_PORT_CLVMD, nodeid) <= 0)
|
||||
{
|
||||
log_error(errtext);
|
||||
log_error(errtext);
|
||||
}
|
||||
return msglen;
|
||||
}
|
||||
@@ -152,16 +152,18 @@ static void _get_our_csid(char *csid)
|
||||
|
||||
/* Call a callback routine for each node is that known (down means not running a clvmd) */
|
||||
static int _cluster_do_node_callback(struct local_client *client,
|
||||
void (*callback) (struct local_client *, char *,
|
||||
int))
|
||||
void (*callback) (struct local_client *, char *,
|
||||
int))
|
||||
{
|
||||
int i;
|
||||
int somedown = 0;
|
||||
|
||||
for (i = 0; i < _get_num_nodes(); i++) {
|
||||
callback(client, (char *)&nodes[i].cn_nodeid, node_updown[nodes[i].cn_nodeid]);
|
||||
if (!node_updown[nodes[i].cn_nodeid])
|
||||
somedown = -1;
|
||||
if (nodes[i].cn_member) {
|
||||
callback(client, (char *)&nodes[i].cn_nodeid, node_updown[nodes[i].cn_nodeid]);
|
||||
if (!node_updown[nodes[i].cn_nodeid])
|
||||
somedown = -1;
|
||||
}
|
||||
}
|
||||
return somedown;
|
||||
}
|
||||
@@ -170,7 +172,7 @@ static int _cluster_do_node_callback(struct local_client *client,
|
||||
this currently just means that a node has stopped listening on our port */
|
||||
static void event_callback(cman_handle_t handle, void *private, int reason, int arg)
|
||||
{
|
||||
char namebuf[MAX_CLUSTER_NAME_LEN];
|
||||
char namebuf[MAX_CLUSTER_MEMBER_NAME_LEN];
|
||||
|
||||
switch (reason) {
|
||||
case CMAN_REASON_PORTCLOSED:
|
||||
@@ -205,7 +207,7 @@ static void event_callback(cman_handle_t handle, void *private, int reason, int
|
||||
|
||||
static struct local_client *cman_client;
|
||||
static int _cluster_fd_callback(struct local_client *fd, char *buf, int len, char *csid,
|
||||
struct local_client **new_client)
|
||||
struct local_client **new_client)
|
||||
{
|
||||
|
||||
/* Save this for data_callback */
|
||||
@@ -243,7 +245,7 @@ static void _add_up_node(char *csid)
|
||||
max_updown_nodes);
|
||||
} else {
|
||||
log_error
|
||||
("Realloc failed. Node status for clvmd will be wrong. quitting\n");
|
||||
("Realloc failed. Node status for clvmd will be wrong. quitting\n");
|
||||
exit(999);
|
||||
}
|
||||
}
|
||||
@@ -297,36 +299,37 @@ static void get_members()
|
||||
return;
|
||||
}
|
||||
|
||||
/* Not enough room for new nodes list ? */
|
||||
if (num_nodes > count_nodes && nodes) {
|
||||
free(nodes);
|
||||
nodes = NULL;
|
||||
}
|
||||
/* Not enough room for new nodes list ? */
|
||||
if (num_nodes > count_nodes && nodes) {
|
||||
free(nodes);
|
||||
nodes = NULL;
|
||||
}
|
||||
|
||||
if (nodes == NULL) {
|
||||
count_nodes = num_nodes + 10; /* Overallocate a little */
|
||||
if (nodes == NULL) {
|
||||
count_nodes = num_nodes + 10; /* Overallocate a little */
|
||||
nodes = malloc(count_nodes * sizeof(struct cman_node));
|
||||
if (!nodes) {
|
||||
log_error("Unable to allocate nodes array\n");
|
||||
exit(5);
|
||||
}
|
||||
if (!nodes) {
|
||||
log_error("Unable to allocate nodes array\n");
|
||||
exit(5);
|
||||
}
|
||||
}
|
||||
|
||||
status = cman_get_nodes(c_handle, count_nodes, &retnodes, nodes);
|
||||
if (status < 0) {
|
||||
log_error("Unable to get node details");
|
||||
exit(6);
|
||||
}
|
||||
|
||||
if (node_updown == NULL) {
|
||||
node_updown =
|
||||
(int *) malloc(sizeof(int) *
|
||||
max(num_nodes, max_updown_nodes));
|
||||
memset(node_updown, 0,
|
||||
sizeof(int) * max(num_nodes, max_updown_nodes));
|
||||
}
|
||||
log_error("Unable to get node details");
|
||||
exit(6);
|
||||
}
|
||||
|
||||
if (node_updown == NULL) {
|
||||
node_updown =
|
||||
(int *) malloc(sizeof(int) *
|
||||
max(num_nodes, max_updown_nodes));
|
||||
memset(node_updown, 0,
|
||||
sizeof(int) * max(num_nodes, max_updown_nodes));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Convert a node name to a CSID */
|
||||
static int _csid_from_name(char *csid, char *name)
|
||||
{
|
||||
@@ -468,6 +471,18 @@ static int _sync_unlock(const char *resource /* UNUSED */, int lockid)
|
||||
|
||||
}
|
||||
|
||||
static int _get_cluster_name(char *buf, int buflen)
|
||||
{
|
||||
cman_cluster_t cluster_info;
|
||||
int status;
|
||||
|
||||
status = cman_get_cluster(c_handle, &cluster_info);
|
||||
if (!status) {
|
||||
strncpy(buf, cluster_info.ci_name, buflen);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static struct cluster_ops _cluster_cman_ops = {
|
||||
.cluster_init_completed = _cluster_init_completed,
|
||||
.cluster_send_message = _cluster_send_message,
|
||||
@@ -481,6 +496,7 @@ static struct cluster_ops _cluster_cman_ops = {
|
||||
.get_our_csid = _get_our_csid,
|
||||
.add_up_node = _add_up_node,
|
||||
.cluster_closedown = _cluster_closedown,
|
||||
.get_cluster_name = _get_cluster_name,
|
||||
.sync_lock = _sync_lock,
|
||||
.sync_unlock = _sync_unlock,
|
||||
};
|
||||
|
||||
@@ -75,6 +75,8 @@
|
||||
#include "clvmd.h"
|
||||
#include "libdlm.h"
|
||||
|
||||
extern struct cluster_ops *clops;
|
||||
|
||||
/* This is where all the real work happens:
|
||||
NOTE: client will be NULL when this is executed on a remote node */
|
||||
int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
|
||||
@@ -117,11 +119,21 @@ int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
|
||||
if (status == EIO) {
|
||||
*retlen =
|
||||
1 + snprintf(*buf, buflen,
|
||||
"Internal lvm error, check syslog");
|
||||
get_last_lvm_error());
|
||||
return EIO;
|
||||
}
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_REFRESH:
|
||||
do_refresh_cache();
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_GET_CLUSTERNAME:
|
||||
status = clops->get_cluster_name(*buf, buflen);
|
||||
if (!status)
|
||||
*retlen = strlen(*buf);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Won't get here because command is validated in pre_command */
|
||||
break;
|
||||
@@ -222,6 +234,10 @@ int do_pre_command(struct local_client *client)
|
||||
status = pre_lock_lv(lock_cmd, lock_flags, lockname);
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_REFRESH:
|
||||
case CLVMD_CMD_GET_CLUSTERNAME:
|
||||
break;
|
||||
|
||||
default:
|
||||
log_error("Unknown command %d received\n", header->cmd);
|
||||
status = EINVAL;
|
||||
|
||||
@@ -43,6 +43,8 @@ struct cluster_ops {
|
||||
void (*reread_config) (void);
|
||||
void (*cluster_closedown) (void);
|
||||
|
||||
int (*get_cluster_name)(char *buf, int buflen);
|
||||
|
||||
int (*sync_lock) (const char *resource, int mode, int flags, int *lockid);
|
||||
int (*sync_unlock) (const char *resource, int lockid);
|
||||
|
||||
|
||||
@@ -973,6 +973,12 @@ static int _cluster_send_message(void *buf, int msglen, char *csid, const char *
|
||||
return gulm_cluster_send_message(buf, msglen, csid, errtext);
|
||||
}
|
||||
|
||||
static int _get_cluster_name(char *buf, int buflen)
|
||||
{
|
||||
strncpy(buf, cluster_name, buflen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct cluster_ops _cluster_gulm_ops = {
|
||||
.cluster_init_completed = NULL,
|
||||
.cluster_send_message = _cluster_send_message,
|
||||
@@ -987,6 +993,7 @@ static struct cluster_ops _cluster_gulm_ops = {
|
||||
.add_up_node = gulm_add_up_node,
|
||||
.reread_config = _reread_config,
|
||||
.cluster_closedown = _cluster_closedown,
|
||||
.get_cluster_name = _get_cluster_name,
|
||||
.sync_lock = _sync_lock,
|
||||
.sync_unlock = _sync_unlock,
|
||||
};
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include "clvm.h"
|
||||
#include "version.h"
|
||||
#include "clvmd.h"
|
||||
#include "refresh_clvmd.h"
|
||||
#include "libdlm.h"
|
||||
#include "system-lv.h"
|
||||
#include "list.h"
|
||||
@@ -66,7 +67,7 @@ static struct local_client local_client_head;
|
||||
|
||||
static unsigned short global_xid = 0; /* Last transaction ID issued */
|
||||
|
||||
static struct cluster_ops *clops = NULL;
|
||||
struct cluster_ops *clops = NULL;
|
||||
|
||||
static char our_csid[MAX_CSID_LEN];
|
||||
static unsigned max_csid_len;
|
||||
@@ -143,6 +144,7 @@ static void usage(char *prog, FILE *file)
|
||||
fprintf(file, " -V Show version of clvmd\n");
|
||||
fprintf(file, " -h Show this help information\n");
|
||||
fprintf(file, " -d Don't fork, run in the foreground\n");
|
||||
fprintf(file, " -R Tell all running clvmds in the cluster to reload their device cache\n");
|
||||
fprintf(file, " -t<secs> Command timeout (default 60 seconds)\n");
|
||||
fprintf(file, "\n");
|
||||
}
|
||||
@@ -173,7 +175,7 @@ int main(int argc, char *argv[])
|
||||
/* Deal with command-line arguments */
|
||||
opterr = 0;
|
||||
optind = 0;
|
||||
while ((opt = getopt(argc, argv, "?vVhdt:")) != EOF) {
|
||||
while ((opt = getopt(argc, argv, "?vVhdt:R")) != EOF) {
|
||||
switch (opt) {
|
||||
case 'h':
|
||||
usage(argv[0], stdout);
|
||||
@@ -183,6 +185,9 @@ int main(int argc, char *argv[])
|
||||
usage(argv[0], stderr);
|
||||
exit(0);
|
||||
|
||||
case 'R':
|
||||
return refresh_clvmd();
|
||||
|
||||
case 'd':
|
||||
debug++;
|
||||
break;
|
||||
@@ -1684,6 +1689,7 @@ static void *lvm_thread_fn(void *arg)
|
||||
}
|
||||
pthread_mutex_unlock(&lvm_thread_mutex);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Pass down some work to the LVM thread */
|
||||
|
||||
@@ -50,12 +50,18 @@
|
||||
static struct cmd_context *cmd = NULL;
|
||||
static struct dm_hash_table *lv_hash = NULL;
|
||||
static pthread_mutex_t lv_hash_lock;
|
||||
static char last_error[1024];
|
||||
|
||||
struct lv_info {
|
||||
int lock_id;
|
||||
int lock_mode;
|
||||
};
|
||||
|
||||
char *get_last_lvm_error()
|
||||
{
|
||||
return last_error;
|
||||
}
|
||||
|
||||
/* Return the mode a lock is currently held at (or -1 if not held) */
|
||||
static int get_current_lock(char *resource)
|
||||
{
|
||||
@@ -201,8 +207,17 @@ static int do_activate_lv(char *resource, unsigned char lock_flags, int mode)
|
||||
/* Try to get the lock if it's a clustered volume group */
|
||||
if (lock_flags & LCK_CLUSTER_VG) {
|
||||
status = hold_lock(resource, mode, LKF_NOQUEUE);
|
||||
if (status)
|
||||
if (status) {
|
||||
/* Return an LVM-sensible error for this.
|
||||
* Forcing EIO makes the upper level return this text
|
||||
* rather than the strerror text for EAGAIN.
|
||||
*/
|
||||
if (errno == EAGAIN) {
|
||||
sprintf(last_error, "Volume is busy on another node");
|
||||
errno = EIO;
|
||||
}
|
||||
return errno;
|
||||
}
|
||||
}
|
||||
|
||||
/* If it's suspended then resume it */
|
||||
@@ -416,6 +431,13 @@ int do_check_lvm1(char *vgname)
|
||||
return status == 1 ? 0 : EBUSY;
|
||||
}
|
||||
|
||||
int do_refresh_cache()
|
||||
{
|
||||
DEBUGLOG("Refreshing context\n");
|
||||
log_notice("Refreshing context");
|
||||
return refresh_toolcontext(cmd)==1?0:-1;
|
||||
}
|
||||
|
||||
|
||||
/* Only called at gulm startup. Drop any leftover VG or P_orphan locks
|
||||
that might be hanging around if we died for any reason
|
||||
@@ -505,6 +527,20 @@ static void *get_initial_state()
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void lvm2_log_fn(int level, const char *file, int line,
|
||||
const char *message)
|
||||
{
|
||||
/*
|
||||
* Ignore non-error messages, but store the latest one for returning
|
||||
* to the user.
|
||||
*/
|
||||
if (level != _LOG_ERR && level != _LOG_FATAL)
|
||||
return;
|
||||
|
||||
strncpy(last_error, message, sizeof(last_error));
|
||||
last_error[sizeof(last_error)-1] = '\0';
|
||||
}
|
||||
|
||||
/* This checks some basic cluster-LVM configuration stuff */
|
||||
static void check_config()
|
||||
{
|
||||
@@ -539,7 +575,7 @@ void init_lvhash()
|
||||
/* Called to initialise the LVM context of the daemon */
|
||||
int init_lvm(int using_gulm)
|
||||
{
|
||||
if (!(cmd = create_toolcontext(NULL))) {
|
||||
if (!(cmd = create_toolcontext(NULL, 0))) {
|
||||
log_error("Failed to allocate command context");
|
||||
return 0;
|
||||
}
|
||||
@@ -557,5 +593,8 @@ int init_lvm(int using_gulm)
|
||||
|
||||
get_initial_state();
|
||||
|
||||
/* Trap log messages so we can pass them back to the user */
|
||||
init_log_fn(lvm2_log_fn);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -25,11 +25,13 @@ extern int do_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
|
||||
extern int post_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
|
||||
char *resource);
|
||||
extern int do_check_lvm1(char *vgname);
|
||||
extern int do_refresh_cache(void);
|
||||
extern int init_lvm(int using_gulm);
|
||||
extern void init_lvhash(void);
|
||||
|
||||
extern int hold_unlock(char *resource);
|
||||
extern int hold_lock(char *resource, int mode, int flags);
|
||||
extern void unlock_all(void);
|
||||
extern char *get_last_lvm_error(void);
|
||||
|
||||
#endif
|
||||
|
||||
334
daemons/clvmd/refresh_clvmd.c
Normal file
334
daemons/clvmd/refresh_clvmd.c
Normal file
@@ -0,0 +1,334 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tell all clvmds in a cluster to refresh their toolcontext
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <libdevmapper.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "clvm.h"
|
||||
#include "refresh_clvmd.h"
|
||||
|
||||
typedef struct lvm_response {
|
||||
char node[255];
|
||||
char *response;
|
||||
int status;
|
||||
int len;
|
||||
} lvm_response_t;
|
||||
|
||||
/*
|
||||
* This gets stuck at the start of memory we allocate so we
|
||||
* can sanity-check it at deallocation time
|
||||
*/
|
||||
#define LVM_SIGNATURE 0x434C564D
|
||||
|
||||
static int _clvmd_sock = -1;
|
||||
|
||||
/* Open connection to the Cluster Manager daemon */
|
||||
static int _open_local_sock(void)
|
||||
{
|
||||
int local_socket;
|
||||
struct sockaddr_un sockaddr;
|
||||
|
||||
/* Open local socket */
|
||||
if ((local_socket = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
|
||||
fprintf(stderr, "Local socket creation failed: %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||
memcpy(sockaddr.sun_path, CLVMD_SOCKNAME, sizeof(CLVMD_SOCKNAME));
|
||||
|
||||
sockaddr.sun_family = AF_UNIX;
|
||||
|
||||
if (connect(local_socket,(struct sockaddr *) &sockaddr,
|
||||
sizeof(sockaddr))) {
|
||||
int saved_errno = errno;
|
||||
|
||||
fprintf(stderr, "connect() failed on local socket: %s\n",
|
||||
strerror(errno));
|
||||
if (close(local_socket))
|
||||
return -1;
|
||||
|
||||
errno = saved_errno;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return local_socket;
|
||||
}
|
||||
|
||||
/* Send a request and return the status */
|
||||
static int _send_request(char *inbuf, int inlen, char **retbuf)
|
||||
{
|
||||
char outbuf[PIPE_BUF];
|
||||
struct clvm_header *outheader = (struct clvm_header *) outbuf;
|
||||
int len;
|
||||
int off;
|
||||
int buflen;
|
||||
int err;
|
||||
|
||||
/* Send it to CLVMD */
|
||||
rewrite:
|
||||
if ( (err = write(_clvmd_sock, inbuf, inlen)) != inlen) {
|
||||
if (err == -1 && errno == EINTR)
|
||||
goto rewrite;
|
||||
fprintf(stderr, "Error writing data to clvmd: %s", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get the response */
|
||||
reread:
|
||||
if ((len = read(_clvmd_sock, outbuf, sizeof(struct clvm_header))) < 0) {
|
||||
if (errno == EINTR)
|
||||
goto reread;
|
||||
fprintf(stderr, "Error reading data from clvmd: %s", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
fprintf(stderr, "EOF reading CLVMD");
|
||||
errno = ENOTCONN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Allocate buffer */
|
||||
buflen = len + outheader->arglen;
|
||||
*retbuf = dm_malloc(buflen);
|
||||
if (!*retbuf) {
|
||||
errno = ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Copy the header */
|
||||
memcpy(*retbuf, outbuf, len);
|
||||
outheader = (struct clvm_header *) *retbuf;
|
||||
|
||||
/* Read the returned values */
|
||||
off = 1; /* we've already read the first byte */
|
||||
while (off <= outheader->arglen && len > 0) {
|
||||
len = read(_clvmd_sock, outheader->args + off,
|
||||
buflen - off - offsetof(struct clvm_header, args));
|
||||
if (len > 0)
|
||||
off += len;
|
||||
}
|
||||
|
||||
/* Was it an error ? */
|
||||
if (outheader->status != 0) {
|
||||
errno = outheader->status;
|
||||
|
||||
/* Only return an error here if there are no node-specific
|
||||
errors present in the message that might have more detail */
|
||||
if (!(outheader->flags & CLVMD_FLAG_NODEERRS)) {
|
||||
fprintf(stderr, "cluster request failed: %s\n", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Build the structure header and parse-out wildcard node names */
|
||||
static void _build_header(struct clvm_header *head, int cmd, const char *node,
|
||||
int len)
|
||||
{
|
||||
head->cmd = cmd;
|
||||
head->status = 0;
|
||||
head->flags = 0;
|
||||
head->clientid = 0;
|
||||
head->arglen = len;
|
||||
|
||||
if (node) {
|
||||
/*
|
||||
* Allow a couple of special node names:
|
||||
* "*" for all nodes,
|
||||
* "." for the local node only
|
||||
*/
|
||||
if (strcmp(node, "*") == 0) {
|
||||
head->node[0] = '\0';
|
||||
} else if (strcmp(node, ".") == 0) {
|
||||
head->node[0] = '\0';
|
||||
head->flags = CLVMD_FLAG_LOCAL;
|
||||
} else
|
||||
strcpy(head->node, node);
|
||||
} else
|
||||
head->node[0] = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a message to a(or all) node(s) in the cluster and wait for replies
|
||||
*/
|
||||
static int _cluster_request(char cmd, const char *node, void *data, int len,
|
||||
lvm_response_t ** response, int *num)
|
||||
{
|
||||
char outbuf[sizeof(struct clvm_header) + len + strlen(node) + 1];
|
||||
int *outptr;
|
||||
char *inptr;
|
||||
char *retbuf = NULL;
|
||||
int status;
|
||||
int i;
|
||||
int num_responses = 0;
|
||||
struct clvm_header *head = (struct clvm_header *) outbuf;
|
||||
lvm_response_t *rarray;
|
||||
|
||||
*num = 0;
|
||||
|
||||
if (_clvmd_sock == -1)
|
||||
_clvmd_sock = _open_local_sock();
|
||||
|
||||
if (_clvmd_sock == -1)
|
||||
return 0;
|
||||
|
||||
_build_header(head, cmd, node, len);
|
||||
memcpy(head->node + strlen(head->node) + 1, data, len);
|
||||
|
||||
status = _send_request(outbuf, sizeof(struct clvm_header) +
|
||||
strlen(head->node) + len, &retbuf);
|
||||
if (!status)
|
||||
goto out;
|
||||
|
||||
/* Count the number of responses we got */
|
||||
head = (struct clvm_header *) retbuf;
|
||||
inptr = head->args;
|
||||
while (inptr[0]) {
|
||||
num_responses++;
|
||||
inptr += strlen(inptr) + 1;
|
||||
inptr += sizeof(int);
|
||||
inptr += strlen(inptr) + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate response array.
|
||||
* With an extra pair of INTs on the front to sanity
|
||||
* check the pointer when we are given it back to free
|
||||
*/
|
||||
outptr = dm_malloc(sizeof(lvm_response_t) * num_responses +
|
||||
sizeof(int) * 2);
|
||||
if (!outptr) {
|
||||
errno = ENOMEM;
|
||||
status = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
*response = (lvm_response_t *) (outptr + 2);
|
||||
outptr[0] = LVM_SIGNATURE;
|
||||
outptr[1] = num_responses;
|
||||
rarray = *response;
|
||||
|
||||
/* Unpack the response into an lvm_response_t array */
|
||||
inptr = head->args;
|
||||
i = 0;
|
||||
while (inptr[0]) {
|
||||
strcpy(rarray[i].node, inptr);
|
||||
inptr += strlen(inptr) + 1;
|
||||
|
||||
memcpy(&rarray[i].status, inptr, sizeof(int));
|
||||
inptr += sizeof(int);
|
||||
|
||||
rarray[i].response = dm_malloc(strlen(inptr) + 1);
|
||||
if (rarray[i].response == NULL) {
|
||||
/* Free up everything else and return error */
|
||||
int j;
|
||||
for (j = 0; j < i; j++)
|
||||
dm_free(rarray[i].response);
|
||||
free(outptr);
|
||||
errno = ENOMEM;
|
||||
status = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
strcpy(rarray[i].response, inptr);
|
||||
rarray[i].len = strlen(inptr);
|
||||
inptr += strlen(inptr) + 1;
|
||||
i++;
|
||||
}
|
||||
*num = num_responses;
|
||||
*response = rarray;
|
||||
|
||||
out:
|
||||
if (retbuf)
|
||||
dm_free(retbuf);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Free reply array */
|
||||
static int _cluster_free_request(lvm_response_t * response)
|
||||
{
|
||||
int *ptr = (int *) response - 2;
|
||||
int i;
|
||||
int num;
|
||||
|
||||
/* Check it's ours to free */
|
||||
if (response == NULL || *ptr != LVM_SIGNATURE) {
|
||||
errno = EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
num = ptr[1];
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
dm_free(response[i].response);
|
||||
}
|
||||
|
||||
dm_free(ptr);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int refresh_clvmd()
|
||||
{
|
||||
int num_responses;
|
||||
char args[1]; // No args really.
|
||||
lvm_response_t *response;
|
||||
int saved_errno;
|
||||
int status;
|
||||
int i;
|
||||
|
||||
status = _cluster_request(CLVMD_CMD_REFRESH, "*", args, 0, &response, &num_responses);
|
||||
|
||||
/* If any nodes were down then display them and return an error */
|
||||
for (i = 0; i < num_responses; i++) {
|
||||
if (response[i].status == EHOSTDOWN) {
|
||||
fprintf(stderr, "clvmd not running on node %s",
|
||||
response[i].node);
|
||||
status = 0;
|
||||
errno = response[i].status;
|
||||
} else if (response[i].status) {
|
||||
fprintf(stderr, "Error resetting node %s: %s",
|
||||
response[i].node,
|
||||
response[i].response[0] ?
|
||||
response[i].response :
|
||||
strerror(response[i].status));
|
||||
status = 0;
|
||||
errno = response[i].status;
|
||||
}
|
||||
}
|
||||
|
||||
saved_errno = errno;
|
||||
_cluster_free_request(response);
|
||||
errno = saved_errno;
|
||||
|
||||
return status;
|
||||
}
|
||||
2
daemons/clvmd/refresh_clvmd.h
Normal file
2
daemons/clvmd/refresh_clvmd.h
Normal file
@@ -0,0 +1,2 @@
|
||||
int refresh_clvmd(void);
|
||||
|
||||
@@ -48,7 +48,7 @@ static int _get_mirror_event(char *params)
|
||||
char *p;
|
||||
int log_argc, num_devs, num_failures=0;
|
||||
|
||||
if (max_args <= split_words(params, max_args, args)) {
|
||||
if (max_args <= dm_split_words(params, max_args, 0, args)) {
|
||||
syslog(LOG_ERR, "Unable to split mirror parameters: Arg list too long");
|
||||
return -E2BIG;
|
||||
}
|
||||
@@ -121,7 +121,7 @@ static int _remove_failed_devices(const char *device)
|
||||
if (strlen(device) > 200)
|
||||
return -ENAMETOOLONG;
|
||||
|
||||
if (!split_dm_name(mem_pool, device, &vg, &lv, &layer)) {
|
||||
if (!dm_split_lvm_name(mem_pool, device, &vg, &lv, &layer)) {
|
||||
syslog(LOG_ERR, "Unable to determine VG name from %s",
|
||||
device);
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -48,7 +48,7 @@ static int _get_mirror_event(char *params)
|
||||
char *p;
|
||||
int log_argc, num_devs, num_failures=0;
|
||||
|
||||
if (max_args <= split_words(params, max_args, args)) {
|
||||
if (max_args <= dm_split_words(params, max_args, 0, args)) {
|
||||
syslog(LOG_ERR, "Unable to split mirror parameters: Arg list too long");
|
||||
return -E2BIG;
|
||||
}
|
||||
@@ -121,7 +121,7 @@ static int _remove_failed_devices(const char *device)
|
||||
if (strlen(device) > 200)
|
||||
return -ENAMETOOLONG;
|
||||
|
||||
if (!split_dm_name(mem_pool, device, &vg, &lv, &layer)) {
|
||||
if (!dm_split_lvm_name(mem_pool, device, &vg, &lv, &layer)) {
|
||||
syslog(LOG_ERR, "Unable to determine VG name from %s",
|
||||
device);
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -207,11 +207,26 @@ global {
|
||||
# Location of proc filesystem
|
||||
proc = "/proc"
|
||||
|
||||
# Type of locking to use. Defaults to file-based locking (1).
|
||||
# Type of locking to use. Defaults to local file-based locking (1).
|
||||
# Turn locking off by setting to 0 (dangerous: risks metadata corruption
|
||||
# if LVM2 commands get run concurrently).
|
||||
# Type 2 uses the external shared library locking_library.
|
||||
# Type 3 uses built-in clustered locking.
|
||||
locking_type = 1
|
||||
|
||||
# If using external locking (type 2) and initialisation fails,
|
||||
# with this set to 1 an attempt will be made to use the built-in
|
||||
# clustered locking.
|
||||
# If you are using a customised locking_library you should set this to 0.
|
||||
fallback_to_clustered_locking = 1
|
||||
|
||||
# If an attempt to initialise type 2 or type 3 locking failed, perhaps
|
||||
# because cluster components such as clvmd are not running, with this set
|
||||
# to 1 an attempt will be made to use local file-based locking (type 1).
|
||||
# If this succeeds, only commands against local volume groups will proceed.
|
||||
# Volume Groups marked as clustered will be ignored.
|
||||
fallback_to_local_locking = 1
|
||||
|
||||
# Local non-LV directory that holds file-based locks while commands are
|
||||
# in progress. A directory like /tmp that may get wiped on reboot is OK.
|
||||
locking_dir = "/var/lock/lvm"
|
||||
@@ -223,6 +238,9 @@ global {
|
||||
|
||||
# Search this directory first for shared libraries.
|
||||
# library_dir = "/lib"
|
||||
|
||||
# The external locking library to load if locking_type is set to 2.
|
||||
# locking_library = "liblvm2clusterlock.so"
|
||||
}
|
||||
|
||||
activation {
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
../lib/misc/lvm-exec.h
|
||||
../lib/misc/lvm-file.h
|
||||
../lib/misc/lvm-string.h
|
||||
../lib/misc/lvm-wrappers.h
|
||||
../lib/misc/sharedlib.h
|
||||
../lib/regex/matcher.h
|
||||
../lib/report/report.h
|
||||
|
||||
@@ -78,6 +78,8 @@ SOURCES =\
|
||||
misc/lvm-exec.c \
|
||||
misc/lvm-file.c \
|
||||
misc/lvm-string.c \
|
||||
misc/lvm-wrappers.c \
|
||||
misc/timestamp.c \
|
||||
mm/memlock.c \
|
||||
regex/matcher.c \
|
||||
regex/parse_rx.c \
|
||||
|
||||
@@ -39,7 +39,7 @@ int lvm1_present(struct cmd_context *cmd)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
|
||||
if (lvm_snprintf(path, sizeof(path), "%s/lvm/global", cmd->proc_dir)
|
||||
if (dm_snprintf(path, sizeof(path), "%s/lvm/global", cmd->proc_dir)
|
||||
< 0) {
|
||||
log_error("LVM1 proc global snprintf failed");
|
||||
return 0;
|
||||
@@ -51,6 +51,66 @@ int lvm1_present(struct cmd_context *cmd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int list_segment_modules(struct dm_pool *mem, const struct lv_segment *seg,
|
||||
struct list *modules)
|
||||
{
|
||||
unsigned int s;
|
||||
struct lv_segment *seg2, *snap_seg;
|
||||
struct list *snh;
|
||||
|
||||
if (seg->segtype->ops->modules_needed &&
|
||||
!seg->segtype->ops->modules_needed(mem, seg, modules)) {
|
||||
log_error("module string allocation failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lv_is_origin(seg->lv))
|
||||
list_iterate(snh, &seg->lv->snapshot_segs)
|
||||
if (!list_lv_modules(mem,
|
||||
list_struct_base(snh,
|
||||
struct lv_segment,
|
||||
origin_list)->cow,
|
||||
modules))
|
||||
return_0;
|
||||
|
||||
if (lv_is_cow(seg->lv)) {
|
||||
snap_seg = find_cow(seg->lv);
|
||||
if (snap_seg->segtype->ops->modules_needed &&
|
||||
!snap_seg->segtype->ops->modules_needed(mem, snap_seg,
|
||||
modules)) {
|
||||
log_error("snap_seg module string allocation failed");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (s = 0; s < seg->area_count; s++) {
|
||||
switch (seg_type(seg, s)) {
|
||||
case AREA_LV:
|
||||
seg2 = find_seg_by_le(seg_lv(seg, s), seg_le(seg, s));
|
||||
if (seg2 && !list_segment_modules(mem, seg2, modules))
|
||||
return_0;
|
||||
break;
|
||||
case AREA_PV:
|
||||
case AREA_UNASSIGNED:
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int list_lv_modules(struct dm_pool *mem, const struct logical_volume *lv,
|
||||
struct list *modules)
|
||||
{
|
||||
struct lv_segment *seg;
|
||||
|
||||
list_iterate_items(seg, &lv->segments)
|
||||
if (!list_segment_modules(mem, seg, modules))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef DEVMAPPER_SUPPORT
|
||||
void set_activation(int act)
|
||||
{
|
||||
@@ -257,9 +317,9 @@ static int _passes_activation_filter(struct cmd_context *cmd,
|
||||
continue;
|
||||
}
|
||||
/* vgname/lvname */
|
||||
if (lvm_snprintf(path, sizeof(path), "%s/%s", lv->vg->name,
|
||||
if (dm_snprintf(path, sizeof(path), "%s/%s", lv->vg->name,
|
||||
lv->name) < 0) {
|
||||
log_error("lvm_snprintf error from %s/%s", lv->vg->name,
|
||||
log_error("dm_snprintf error from %s/%s", lv->vg->name,
|
||||
lv->name);
|
||||
continue;
|
||||
}
|
||||
@@ -342,7 +402,7 @@ int target_present(const char *target_name, int use_modprobe)
|
||||
if (target_version(target_name, &maj, &min, &patchlevel))
|
||||
return 1;
|
||||
|
||||
if (lvm_snprintf(module, sizeof(module), "dm-%s", target_name)
|
||||
if (dm_snprintf(module, sizeof(module), "dm-%s", target_name)
|
||||
< 0) {
|
||||
log_error("target_present module name too long: %s",
|
||||
target_name);
|
||||
|
||||
@@ -39,6 +39,10 @@ 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);
|
||||
int list_segment_modules(struct dm_pool *mem, const struct lv_segment *seg,
|
||||
struct list *modules);
|
||||
int list_lv_modules(struct dm_pool *mem, const struct logical_volume *lv,
|
||||
struct list *modules);
|
||||
|
||||
void activation_release(void);
|
||||
void activation_exit(void);
|
||||
|
||||
@@ -912,7 +912,7 @@ static int _create_lv_symlinks(struct dev_manager *dm, struct dm_tree_node *root
|
||||
name = dm_tree_node_get_name(child);
|
||||
|
||||
if (name && lvlayer->old_name && *lvlayer->old_name && strcmp(name, lvlayer->old_name)) {
|
||||
if (!split_dm_name(dm->mem, lvlayer->old_name, &vgname, &lvname, &layer)) {
|
||||
if (!dm_split_lvm_name(dm->mem, lvlayer->old_name, &vgname, &lvname, &layer)) {
|
||||
log_error("_create_lv_symlinks: Couldn't split up old device name %s", lvlayer->old_name);
|
||||
return 0;
|
||||
}
|
||||
@@ -938,7 +938,7 @@ static int _clean_tree(struct dev_manager *dm, struct dm_tree_node *root)
|
||||
if (!(uuid = dm_tree_node_get_uuid(child)))
|
||||
continue;
|
||||
|
||||
if (!split_dm_name(dm->mem, name, &vgname, &lvname, &layer)) {
|
||||
if (!dm_split_lvm_name(dm->mem, name, &vgname, &lvname, &layer)) {
|
||||
log_error("_clean_tree: Couldn't split up device name %s.", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ static int _mk_dir(const char *dev_dir, const char *vg_name)
|
||||
{
|
||||
char vg_path[PATH_MAX];
|
||||
|
||||
if (lvm_snprintf(vg_path, sizeof(vg_path), "%s%s",
|
||||
if (dm_snprintf(vg_path, sizeof(vg_path), "%s%s",
|
||||
dev_dir, vg_name) == -1) {
|
||||
log_error("Couldn't construct name of volume "
|
||||
"group directory.");
|
||||
@@ -53,7 +53,7 @@ static int _rm_dir(const char *dev_dir, const char *vg_name)
|
||||
{
|
||||
char vg_path[PATH_MAX];
|
||||
|
||||
if (lvm_snprintf(vg_path, sizeof(vg_path), "%s%s",
|
||||
if (dm_snprintf(vg_path, sizeof(vg_path), "%s%s",
|
||||
dev_dir, vg_name) == -1) {
|
||||
log_error("Couldn't construct name of volume "
|
||||
"group directory.");
|
||||
@@ -87,7 +87,7 @@ static void _rm_blks(const char *dir)
|
||||
if (!strcmp(name, ".") || !strcmp(name, ".."))
|
||||
continue;
|
||||
|
||||
if (lvm_snprintf(path, sizeof(path), "%s/%s", dir, name) == -1) {
|
||||
if (dm_snprintf(path, sizeof(path), "%s/%s", dir, name) == -1) {
|
||||
log_error("Couldn't create path for %s", name);
|
||||
continue;
|
||||
}
|
||||
@@ -109,28 +109,28 @@ static int _mk_link(const char *dev_dir, const char *vg_name,
|
||||
char vg_path[PATH_MAX];
|
||||
struct stat buf;
|
||||
|
||||
if (lvm_snprintf(vg_path, sizeof(vg_path), "%s%s",
|
||||
if (dm_snprintf(vg_path, sizeof(vg_path), "%s%s",
|
||||
dev_dir, vg_name) == -1) {
|
||||
log_error("Couldn't create path for volume group dir %s",
|
||||
vg_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lvm_snprintf(lv_path, sizeof(lv_path), "%s/%s", vg_path,
|
||||
if (dm_snprintf(lv_path, sizeof(lv_path), "%s/%s", vg_path,
|
||||
lv_name) == -1) {
|
||||
log_error("Couldn't create source pathname for "
|
||||
"logical volume link %s", lv_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lvm_snprintf(link_path, sizeof(link_path), "%s/%s",
|
||||
if (dm_snprintf(link_path, sizeof(link_path), "%s/%s",
|
||||
dm_dir(), dev) == -1) {
|
||||
log_error("Couldn't create destination pathname for "
|
||||
"logical volume link for %s", lv_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lvm_snprintf(lvm1_group_path, sizeof(lvm1_group_path), "%s/group",
|
||||
if (dm_snprintf(lvm1_group_path, sizeof(lvm1_group_path), "%s/group",
|
||||
vg_path) == -1) {
|
||||
log_error("Couldn't create pathname for LVM1 group file for %s",
|
||||
vg_name);
|
||||
@@ -190,7 +190,7 @@ static int _rm_link(const char *dev_dir, const char *vg_name,
|
||||
struct stat buf;
|
||||
char lv_path[PATH_MAX];
|
||||
|
||||
if (lvm_snprintf(lv_path, sizeof(lv_path), "%s%s/%s",
|
||||
if (dm_snprintf(lv_path, sizeof(lv_path), "%s%s/%s",
|
||||
dev_dir, vg_name, lv_name) == -1) {
|
||||
log_error("Couldn't determine link pathname.");
|
||||
return 0;
|
||||
|
||||
@@ -67,7 +67,7 @@ static int _get_env_vars(struct cmd_context *cmd)
|
||||
|
||||
/* Set to "" to avoid using any system directory */
|
||||
if ((e = getenv("LVM_SYSTEM_DIR"))) {
|
||||
if (lvm_snprintf(cmd->sys_dir, sizeof(cmd->sys_dir),
|
||||
if (dm_snprintf(cmd->sys_dir, sizeof(cmd->sys_dir),
|
||||
"%s", e) < 0) {
|
||||
log_error("LVM_SYSTEM_DIR environment variable "
|
||||
"is too long.");
|
||||
@@ -167,7 +167,7 @@ static int _process_config(struct cmd_context *cmd)
|
||||
log_verbose("Set umask to %04o", cmd->default_settings.umask);
|
||||
|
||||
/* dev dir */
|
||||
if (lvm_snprintf(cmd->dev_dir, sizeof(cmd->dev_dir), "%s/",
|
||||
if (dm_snprintf(cmd->dev_dir, sizeof(cmd->dev_dir), "%s/",
|
||||
find_config_tree_str(cmd, "devices/dir",
|
||||
DEFAULT_DEV_DIR)) < 0) {
|
||||
log_error("Device directory given in config file too long");
|
||||
@@ -178,7 +178,7 @@ static int _process_config(struct cmd_context *cmd)
|
||||
#endif
|
||||
|
||||
/* proc dir */
|
||||
if (lvm_snprintf(cmd->proc_dir, sizeof(cmd->proc_dir), "%s",
|
||||
if (dm_snprintf(cmd->proc_dir, sizeof(cmd->proc_dir), "%s",
|
||||
find_config_tree_str(cmd, "global/proc",
|
||||
DEFAULT_PROC_DIR)) < 0) {
|
||||
log_error("Device directory given in config file too long");
|
||||
@@ -319,7 +319,7 @@ static int _load_config_file(struct cmd_context *cmd, const char *tag)
|
||||
if (*tag)
|
||||
filler = "_";
|
||||
|
||||
if (lvm_snprintf(config_file, sizeof(config_file), "%s/lvm%s%s.conf",
|
||||
if (dm_snprintf(config_file, sizeof(config_file), "%s/lvm%s%s.conf",
|
||||
cmd->sys_dir, filler, tag) < 0) {
|
||||
log_error("LVM_SYSTEM_DIR or tag was too long");
|
||||
return 0;
|
||||
@@ -587,7 +587,7 @@ static int _init_filters(struct cmd_context *cmd)
|
||||
if (!(f3 = _init_filter_components(cmd)))
|
||||
return 0;
|
||||
|
||||
if (lvm_snprintf(cache_file, sizeof(cache_file),
|
||||
if (dm_snprintf(cache_file, sizeof(cache_file),
|
||||
"%s/.cache", cmd->sys_dir) < 0) {
|
||||
log_error("Persistent cache filename too long ('%s/.cache').",
|
||||
cmd->sys_dir);
|
||||
@@ -646,8 +646,9 @@ static int _init_formats(struct cmd_context *cmd)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBDL
|
||||
/* Load any formats in shared libs */
|
||||
if ((cn = find_config_tree_node(cmd, "global/format_libraries"))) {
|
||||
/* Load any formats in shared libs if not static */
|
||||
if (!cmd->is_static &&
|
||||
(cn = find_config_tree_node(cmd, "global/format_libraries"))) {
|
||||
|
||||
struct config_value *cv;
|
||||
struct format_type *(*init_format_fn) (struct cmd_context *);
|
||||
@@ -740,8 +741,9 @@ static int _init_segtypes(struct cmd_context *cmd)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBDL
|
||||
/* Load any formats in shared libs */
|
||||
if ((cn = find_config_tree_node(cmd, "global/segment_libraries"))) {
|
||||
/* Load any formats in shared libs unless static */
|
||||
if (!cmd->is_static &&
|
||||
(cn = find_config_tree_node(cmd, "global/segment_libraries"))) {
|
||||
|
||||
struct config_value *cv;
|
||||
struct segment_type *(*init_segtype_fn) (struct cmd_context *);
|
||||
@@ -839,7 +841,7 @@ static int _init_backup(struct cmd_context *cmd)
|
||||
min = (uint32_t) find_config_tree_int(cmd, "backup/retain_min",
|
||||
DEFAULT_ARCHIVE_NUMBER);
|
||||
|
||||
if (lvm_snprintf
|
||||
if (dm_snprintf
|
||||
(default_dir, sizeof(default_dir), "%s/%s", cmd->sys_dir,
|
||||
DEFAULT_ARCHIVE_SUBDIR) == -1) {
|
||||
log_err("Couldn't create default archive path '%s/%s'.",
|
||||
@@ -860,7 +862,7 @@ static int _init_backup(struct cmd_context *cmd)
|
||||
find_config_tree_bool(cmd, "backup/backup",
|
||||
DEFAULT_BACKUP_ENABLED);
|
||||
|
||||
if (lvm_snprintf
|
||||
if (dm_snprintf
|
||||
(default_dir, sizeof(default_dir), "%s/%s", cmd->sys_dir,
|
||||
DEFAULT_BACKUP_SUBDIR) == -1) {
|
||||
log_err("Couldn't create default backup path '%s/%s'.",
|
||||
@@ -879,7 +881,7 @@ static int _init_backup(struct cmd_context *cmd)
|
||||
}
|
||||
|
||||
/* Entry point */
|
||||
struct cmd_context *create_toolcontext(struct arg *the_args)
|
||||
struct cmd_context *create_toolcontext(struct arg *the_args, unsigned is_static)
|
||||
{
|
||||
struct cmd_context *cmd;
|
||||
|
||||
@@ -902,6 +904,7 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
|
||||
}
|
||||
memset(cmd, 0, sizeof(*cmd));
|
||||
cmd->args = the_args;
|
||||
cmd->is_static = is_static;
|
||||
cmd->hosttags = 0;
|
||||
list_init(&cmd->formats);
|
||||
list_init(&cmd->segtypes);
|
||||
|
||||
@@ -64,6 +64,7 @@ struct cmd_context {
|
||||
struct command *command;
|
||||
struct arg *args;
|
||||
char **argv;
|
||||
unsigned is_static; /* Static binary? */
|
||||
|
||||
struct dev_filter *filter;
|
||||
int dump_filter; /* Dump filter when exiting? */
|
||||
@@ -87,7 +88,7 @@ struct cmd_context {
|
||||
char proc_dir[PATH_MAX];
|
||||
};
|
||||
|
||||
struct cmd_context *create_toolcontext(struct arg *the_args);
|
||||
struct cmd_context *create_toolcontext(struct arg *the_args, unsigned is_static);
|
||||
void destroy_toolcontext(struct cmd_context *cmd);
|
||||
int refresh_toolcontext(struct cmd_context *cmd);
|
||||
int config_files_changed(struct cmd_context *cmd);
|
||||
|
||||
@@ -187,7 +187,7 @@ int read_config_fd(struct config_tree *cft, struct device *dev,
|
||||
use_mmap = 0;
|
||||
|
||||
if (use_mmap) {
|
||||
mmap_offset = offset % getpagesize();
|
||||
mmap_offset = offset % lvm_getpagesize();
|
||||
/* memory map the file */
|
||||
p->fb = mmap((caddr_t) 0, size + mmap_offset, PROT_READ,
|
||||
MAP_PRIVATE, dev_fd(dev), offset - mmap_offset);
|
||||
|
||||
@@ -32,7 +32,9 @@
|
||||
#define DEFAULT_MD_COMPONENT_DETECTION 1
|
||||
|
||||
#define DEFAULT_LOCK_DIR "/var/lock/lvm"
|
||||
#define DEFAULT_LOCKING_LIB "lvm2_locking.so"
|
||||
#define DEFAULT_LOCKING_LIB "liblvm2clusterlock.so"
|
||||
#define DEFAULT_FALLBACK_TO_LOCAL_LOCKING 1
|
||||
#define DEFAULT_FALLBACK_TO_CLUSTERED_LOCKING 1
|
||||
|
||||
#define DEFAULT_MIRROR_LOG_FAULT_POLICY "allocate"
|
||||
#define DEFAULT_MIRROR_DEV_FAULT_POLICY "remove"
|
||||
|
||||
@@ -176,7 +176,7 @@ static int _aligned_io(struct device_area *where, void *buffer,
|
||||
}
|
||||
|
||||
if (!block_size)
|
||||
block_size = getpagesize();
|
||||
block_size = lvm_getpagesize();
|
||||
|
||||
_widen_region(block_size, where, &widened);
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ static struct {
|
||||
} _policies[] = {
|
||||
{
|
||||
ALLOC_CONTIGUOUS, "contiguous"}, {
|
||||
ALLOC_CLING, "cling"}, {
|
||||
ALLOC_NORMAL, "normal"}, {
|
||||
ALLOC_ANYWHERE, "anywhere"}, {
|
||||
ALLOC_INHERIT, "inherit"}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "targets.h"
|
||||
#include "lvm-string.h"
|
||||
#include "activate.h"
|
||||
#include "str_list.h"
|
||||
|
||||
static const char *_errseg_name(const struct lv_segment *seg)
|
||||
{
|
||||
@@ -64,6 +65,18 @@ static int _errseg_target_present(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int _errseg_modules_needed(struct dm_pool *mem,
|
||||
const struct lv_segment *seg,
|
||||
struct list *modules)
|
||||
{
|
||||
if (!str_list_add(mem, modules, "error")) {
|
||||
log_error("error module string list allocation failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _errseg_destroy(const struct segment_type *segtype)
|
||||
{
|
||||
dm_free((void *)segtype);
|
||||
@@ -76,6 +89,7 @@ static struct segtype_handler _error_ops = {
|
||||
.add_target_line = _errseg_add_target_line,
|
||||
.target_present = _errseg_target_present,
|
||||
#endif
|
||||
.modules_needed = _errseg_modules_needed,
|
||||
.destroy = _errseg_destroy,
|
||||
};
|
||||
|
||||
|
||||
@@ -18,14 +18,6 @@
|
||||
|
||||
#ifdef linux
|
||||
|
||||
/* Lifted from <linux/raid/md_p.h> because of difficulty including it */
|
||||
|
||||
#define MD_SB_MAGIC 0xa92b4efc
|
||||
#define MD_RESERVED_BYTES (64 * 1024)
|
||||
#define MD_RESERVED_SECTORS (MD_RESERVED_BYTES / 512)
|
||||
#define MD_NEW_SIZE_SECTORS(x) ((x & ~(MD_RESERVED_SECTORS - 1)) \
|
||||
- MD_RESERVED_SECTORS)
|
||||
|
||||
static int _ignore_md(struct dev_filter *f, struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@@ -32,7 +32,7 @@ static int _locate_sysfs_blocks(const char *proc, char *path, size_t len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lvm_snprintf(proc_mounts, sizeof(proc_mounts),
|
||||
if (dm_snprintf(proc_mounts, sizeof(proc_mounts),
|
||||
"%s/mounts", proc) < 0) {
|
||||
log_error("Failed to create /proc/mounts string");
|
||||
return 0;
|
||||
@@ -44,9 +44,9 @@ static int _locate_sysfs_blocks(const char *proc, char *path, size_t len)
|
||||
}
|
||||
|
||||
while (fgets(buffer, sizeof(buffer), fp)) {
|
||||
if (split_words(buffer, 4, split) == 4 &&
|
||||
if (dm_split_words(buffer, 4, 0, split) == 4 &&
|
||||
!strcmp(split[2], "sysfs")) {
|
||||
if (lvm_snprintf(path, len, "%s/%s", split[1],
|
||||
if (dm_snprintf(path, len, "%s/%s", split[1],
|
||||
"block") >= 0) {
|
||||
r = 1;
|
||||
}
|
||||
@@ -183,7 +183,7 @@ static int _read_devs(struct dev_set *ds, const char *dir)
|
||||
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
|
||||
continue;
|
||||
|
||||
if (lvm_snprintf(path, sizeof(path), "%s/%s", dir,
|
||||
if (dm_snprintf(path, sizeof(path), "%s/%s", dir,
|
||||
d->d_name) < 0) {
|
||||
log_error("sysfs path name too long: %s in %s",
|
||||
d->d_name, dir);
|
||||
|
||||
@@ -145,7 +145,7 @@ static int _scan_proc_dev(const char *proc, const struct config_node *cn)
|
||||
/* All types unrecognised initially */
|
||||
memset(_max_partitions_by_major, 0, sizeof(int) * NUMBER_OF_MAJORS);
|
||||
|
||||
if (lvm_snprintf(proc_devices, sizeof(proc_devices),
|
||||
if (dm_snprintf(proc_devices, sizeof(proc_devices),
|
||||
"%s/devices", proc) < 0) {
|
||||
log_error("Failed to create /proc/devices string");
|
||||
return 0;
|
||||
|
||||
@@ -172,6 +172,7 @@ struct disk_list {
|
||||
* Layout constants.
|
||||
*/
|
||||
#define METADATA_ALIGN 4096UL
|
||||
#define LVM1_PE_ALIGN (65536UL >> SECTOR_SHIFT) /* PE alignment */
|
||||
|
||||
#define METADATA_BASE 0UL
|
||||
#define PV_SIZE 1024UL
|
||||
|
||||
@@ -408,7 +408,7 @@ static int _format1_pv_write(const struct format_type *fmt, struct physical_volu
|
||||
|
||||
/* Ensure any residual PE structure is gone */
|
||||
pv->pe_size = pv->pe_count = 0;
|
||||
pv->pe_start = PE_ALIGN;
|
||||
pv->pe_start = LVM1_PE_ALIGN;
|
||||
|
||||
if (!(mem = dm_pool_create("lvm1 pv_write", 1024))) {
|
||||
stack;
|
||||
@@ -431,7 +431,7 @@ static int _format1_pv_write(const struct format_type *fmt, struct physical_volu
|
||||
dev_write in order to make other disk tools happy */
|
||||
dl->pvd.pv_on_disk.base = METADATA_BASE;
|
||||
dl->pvd.pv_on_disk.size = PV_SIZE;
|
||||
dl->pvd.pe_on_disk.base = PE_ALIGN << SECTOR_SHIFT;
|
||||
dl->pvd.pe_on_disk.base = LVM1_PE_ALIGN << SECTOR_SHIFT;
|
||||
|
||||
list_add(&pvs, &dl->list);
|
||||
if (!write_disks(fmt, &pvs)) {
|
||||
|
||||
@@ -103,7 +103,7 @@ int import_pv(struct dm_pool *mem, struct device *dev,
|
||||
static int _system_id(struct cmd_context *cmd, char *s, const char *prefix)
|
||||
{
|
||||
|
||||
if (lvm_snprintf(s, NAME_LEN, "%s%s%lu",
|
||||
if (dm_snprintf(s, NAME_LEN, "%s%s%lu",
|
||||
prefix, cmd->hostname, time(NULL)) < 0) {
|
||||
log_error("Generated system_id too long");
|
||||
return 0;
|
||||
|
||||
@@ -153,7 +153,7 @@ int calculate_extent_count(struct physical_volume *pv, uint32_t extent_size,
|
||||
if (pe_start && end < pe_start)
|
||||
end = pe_start;
|
||||
|
||||
pvd->pe_start = _round_up(end, PE_ALIGN);
|
||||
pvd->pe_start = _round_up(end, LVM1_PE_ALIGN);
|
||||
|
||||
} while ((pvd->pe_start + (pvd->pe_total * extent_size))
|
||||
> pv->size);
|
||||
|
||||
@@ -277,7 +277,7 @@ int archive_vg(struct volume_group *vg,
|
||||
}
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
if (lvm_snprintf(archive_name, sizeof(archive_name),
|
||||
if (dm_snprintf(archive_name, sizeof(archive_name),
|
||||
"%s/%s_%05u.vg", dir, vg->name, ix) < 0) {
|
||||
log_error("Archive file name too long.");
|
||||
return 0;
|
||||
|
||||
@@ -190,7 +190,7 @@ static int __backup(struct volume_group *vg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lvm_snprintf(name, sizeof(name), "%s/%s",
|
||||
if (dm_snprintf(name, sizeof(name), "%s/%s",
|
||||
vg->cmd->backup_params->dir, vg->name) < 0) {
|
||||
log_error("Failed to generate volume group metadata backup "
|
||||
"filename.");
|
||||
@@ -233,7 +233,7 @@ int backup_remove(struct cmd_context *cmd, const char *vg_name)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
|
||||
if (lvm_snprintf(path, sizeof(path), "%s/%s",
|
||||
if (dm_snprintf(path, sizeof(path), "%s/%s",
|
||||
cmd->backup_params->dir, vg_name) < 0) {
|
||||
log_err("Failed to generate backup filename (for removal).");
|
||||
return 0;
|
||||
@@ -342,7 +342,7 @@ int backup_restore(struct cmd_context *cmd, const char *vg_name)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
|
||||
if (lvm_snprintf(path, sizeof(path), "%s/%s",
|
||||
if (dm_snprintf(path, sizeof(path), "%s/%s",
|
||||
cmd->backup_params->dir, vg_name) < 0) {
|
||||
log_err("Failed to generate backup filename (for restore).");
|
||||
return 0;
|
||||
@@ -397,7 +397,7 @@ void check_current_backup(struct volume_group *vg)
|
||||
if ((vg->status & PARTIAL_VG) || (vg->status & EXPORTED_VG))
|
||||
return;
|
||||
|
||||
if (lvm_snprintf(path, sizeof(path), "%s/%s",
|
||||
if (dm_snprintf(path, sizeof(path), "%s/%s",
|
||||
vg->cmd->backup_params->dir, vg->name) < 0) {
|
||||
log_debug("Failed to generate backup filename.");
|
||||
return;
|
||||
|
||||
@@ -233,7 +233,7 @@ static int _sectors_to_units(uint64_t sectors, char *buffer, size_t s)
|
||||
for (i = 0; (d > 1024.0) && _units[i]; i++)
|
||||
d /= 1024.0;
|
||||
|
||||
return lvm_snprintf(buffer, s, "# %g %s", d, _units[i]) > 0;
|
||||
return dm_snprintf(buffer, s, "# %g %s", d, _units[i]) > 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -409,6 +409,11 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
|
||||
outf(f, "tags = %s", buffer);
|
||||
}
|
||||
|
||||
if (!out_size(f, pv->size, "dev_size = %" PRIu64, pv->size)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
outf(f, "pe_start = %" PRIu64, pv->pe_start);
|
||||
if (!out_size(f, vg->extent_size * (uint64_t) pv->pe_count,
|
||||
"pe_count = %u", pv->pe_count)) {
|
||||
@@ -623,7 +628,7 @@ static int _build_pv_names(struct formatter *f, struct volume_group *vg)
|
||||
pv = pvl->pv;
|
||||
|
||||
/* FIXME But skip if there's already an LV called pv%d ! */
|
||||
if (lvm_snprintf(buffer, sizeof(buffer), "pv%d", count++) < 0)
|
||||
if (dm_snprintf(buffer, sizeof(buffer), "pv%d", count++) < 0)
|
||||
return_0;
|
||||
|
||||
if (!(name = dm_pool_strdup(f->mem, buffer)))
|
||||
|
||||
@@ -853,7 +853,7 @@ static int _scan_file(const struct format_type *fmt)
|
||||
tmp != dirent->d_name + strlen(dirent->d_name)
|
||||
- 4)) {
|
||||
vgname = dirent->d_name;
|
||||
if (lvm_snprintf(path, PATH_MAX, "%s/%s",
|
||||
if (dm_snprintf(path, PATH_MAX, "%s/%s",
|
||||
dl->dir, vgname) < 0) {
|
||||
log_error("Name too long %s/%s",
|
||||
dl->dir, vgname);
|
||||
@@ -994,7 +994,7 @@ static int _text_scan(const struct format_type *fmt)
|
||||
}
|
||||
|
||||
/* For orphan, creates new mdas according to policy.
|
||||
Always have an mda between end-of-label and PE_ALIGN boundary */
|
||||
Always have an mda between end-of-label and pe_align() boundary */
|
||||
static int _mda_setup(const struct format_type *fmt,
|
||||
uint64_t pe_start, uint64_t pe_end,
|
||||
int pvmetadatacopies,
|
||||
@@ -1005,15 +1005,12 @@ static int _mda_setup(const struct format_type *fmt,
|
||||
uint64_t start1, mda_size1; /* First area - start of disk */
|
||||
uint64_t start2, mda_size2; /* Second area - end of disk */
|
||||
uint64_t wipe_size = 8 << SECTOR_SHIFT;
|
||||
size_t pagesize = getpagesize();
|
||||
size_t pagesize = lvm_getpagesize();
|
||||
|
||||
if (!pvmetadatacopies) {
|
||||
/* Space available for PEs */
|
||||
pv->size -= PE_ALIGN;
|
||||
if (!pvmetadatacopies)
|
||||
return 1;
|
||||
}
|
||||
|
||||
alignment = PE_ALIGN << SECTOR_SHIFT;
|
||||
alignment = pe_align() << SECTOR_SHIFT;
|
||||
disk_size = pv->size << SECTOR_SHIFT;
|
||||
pe_start <<= SECTOR_SHIFT;
|
||||
pe_end <<= SECTOR_SHIFT;
|
||||
@@ -1027,9 +1024,6 @@ static int _mda_setup(const struct format_type *fmt,
|
||||
/* Requested metadatasize */
|
||||
mda_size1 = pvmetadatasize << SECTOR_SHIFT;
|
||||
|
||||
/* Space available for PEs (before any mdas created) */
|
||||
pv->size -= LABEL_SCAN_SECTORS;
|
||||
|
||||
/* Place mda straight after label area at start of disk */
|
||||
start1 = LABEL_SCAN_SIZE;
|
||||
|
||||
@@ -1037,11 +1031,8 @@ static int _mda_setup(const struct format_type *fmt,
|
||||
if ((!pe_start && !pe_end) ||
|
||||
((pe_start > start1) && (pe_start - start1 >= MDA_SIZE_MIN))) {
|
||||
mda_adjustment = start1 % pagesize;
|
||||
if (mda_adjustment) {
|
||||
if (mda_adjustment)
|
||||
start1 += (pagesize - mda_adjustment);
|
||||
pv->size -= ((pagesize - mda_adjustment) >>
|
||||
SECTOR_SHIFT);
|
||||
}
|
||||
}
|
||||
|
||||
/* Ensure it's not going to be bigger than the disk! */
|
||||
@@ -1055,7 +1046,7 @@ static int _mda_setup(const struct format_type *fmt,
|
||||
pvmetadatacopies = 1;
|
||||
}
|
||||
|
||||
/* Round up to PE_ALIGN boundary */
|
||||
/* Round up to pe_align() boundary */
|
||||
mda_adjustment = (mda_size1 + start1) % alignment;
|
||||
if (mda_adjustment)
|
||||
mda_size1 += (alignment - mda_adjustment);
|
||||
@@ -1071,7 +1062,8 @@ static int _mda_setup(const struct format_type *fmt,
|
||||
/* FIXME If creating new mdas, wipe them! */
|
||||
if (mda_size1) {
|
||||
if (!add_mda(fmt, fmt->cmd->mem, mdas, pv->dev, start1,
|
||||
mda_size1)) return 0;
|
||||
mda_size1))
|
||||
return 0;
|
||||
|
||||
if (!dev_set((struct device *) pv->dev, start1,
|
||||
(size_t) (mda_size1 >
|
||||
@@ -1080,7 +1072,6 @@ static int _mda_setup(const struct format_type *fmt,
|
||||
return 0;
|
||||
}
|
||||
|
||||
pv->size -= mda_size1 >> SECTOR_SHIFT;
|
||||
if (pvmetadatacopies == 1)
|
||||
return 1;
|
||||
} else
|
||||
@@ -1125,7 +1116,6 @@ static int _mda_setup(const struct format_type *fmt,
|
||||
log_error("Failed to wipe new metadata area");
|
||||
return 0;
|
||||
}
|
||||
pv->size -= mda_size2 >> SECTOR_SHIFT;
|
||||
} else
|
||||
return 0;
|
||||
|
||||
@@ -1189,18 +1179,18 @@ static int _text_pv_write(const struct format_type *fmt, struct physical_volume
|
||||
|
||||
/* Set pe_start to first aligned sector after any metadata
|
||||
* areas that begin before pe_start */
|
||||
pv->pe_start = PE_ALIGN;
|
||||
pv->pe_start = pe_align();
|
||||
list_iterate_items(mda, &info->mdas) {
|
||||
mdac = (struct mda_context *) mda->metadata_locn;
|
||||
if (pv->dev == mdac->area.dev &&
|
||||
(mdac->area.start < (pv->pe_start << SECTOR_SHIFT)) &&
|
||||
(mdac->area.start <= (pv->pe_start << SECTOR_SHIFT)) &&
|
||||
(mdac->area.start + mdac->area.size >
|
||||
(pv->pe_start << SECTOR_SHIFT))) {
|
||||
pv->pe_start = (mdac->area.start + mdac->area.size)
|
||||
>> SECTOR_SHIFT;
|
||||
adjustment = pv->pe_start % PE_ALIGN;
|
||||
adjustment = pv->pe_start % pe_align();
|
||||
if (adjustment)
|
||||
pv->pe_start += (PE_ALIGN - adjustment);
|
||||
pv->pe_start += (pe_align() - adjustment);
|
||||
}
|
||||
}
|
||||
if (!add_da
|
||||
@@ -1416,8 +1406,8 @@ static int _text_pv_setup(const struct format_type *fmt,
|
||||
struct lvmcache_info *info;
|
||||
int found;
|
||||
uint64_t pe_end = 0;
|
||||
|
||||
/* FIXME if vg, adjust start/end of pe area to avoid mdas! */
|
||||
unsigned mda_count = 0;
|
||||
uint64_t mda_size2 = 0;
|
||||
|
||||
/* FIXME Cope with pvchange */
|
||||
/* FIXME Merge code with _text_create_text_instance */
|
||||
@@ -1428,11 +1418,16 @@ static int _text_pv_setup(const struct format_type *fmt,
|
||||
if ((info = info_from_pvid(pv->dev->pvid))) {
|
||||
pvmdas = &info->mdas;
|
||||
list_iterate_items(mda, pvmdas) {
|
||||
mda_count++;
|
||||
mdac =
|
||||
(struct mda_context *) mda->metadata_locn;
|
||||
|
||||
/* FIXME Check it isn't already in use */
|
||||
|
||||
/* Reduce usable device size */
|
||||
if (mda_count > 1)
|
||||
mda_size2 = mdac->area.size >> SECTOR_SHIFT;
|
||||
|
||||
/* Ensure it isn't already on list */
|
||||
found = 0;
|
||||
list_iterate_items(mda2, mdas) {
|
||||
@@ -1470,6 +1465,17 @@ static int _text_pv_setup(const struct format_type *fmt,
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME Cope with genuine pe_count 0 */
|
||||
|
||||
/* If missing, estimate pv->size from file-based metadata */
|
||||
if (!pv->size && pv->pe_count)
|
||||
pv->size = pv->pe_count * (uint64_t) vg->extent_size +
|
||||
pv->pe_start + mda_size2;
|
||||
|
||||
/* Recalculate number of extents that will fit */
|
||||
if (!pv->pe_count)
|
||||
pv->pe_count = (pv->size - pv->pe_start - mda_size2) / vg->extent_size;
|
||||
|
||||
/* Unlike LVM1, we don't store this outside a VG */
|
||||
/* FIXME Default from config file? vgextend cmdline flag? */
|
||||
pv->status |= ALLOCATABLE_PV;
|
||||
@@ -1533,7 +1539,7 @@ static struct format_instance *_text_create_text_instance(const struct format_ty
|
||||
dir_list = &((struct mda_lists *) fmt->private)->dirs;
|
||||
|
||||
list_iterate_items(dl, dir_list) {
|
||||
if (lvm_snprintf(path, PATH_MAX, "%s/%s",
|
||||
if (dm_snprintf(path, PATH_MAX, "%s/%s",
|
||||
dl->dir, vgname) < 0) {
|
||||
log_error("Name too long %s/%s", dl->dir,
|
||||
vgname);
|
||||
|
||||
@@ -179,6 +179,9 @@ static int _read_pv(struct format_instance *fid, struct dm_pool *mem,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Late addition */
|
||||
_read_int64(pvn, "dev_size", &pv->size);
|
||||
|
||||
if (!_read_int64(pvn, "pe_start", &pv->pe_start)) {
|
||||
log_error("Couldn't read extent size for volume group.");
|
||||
return 0;
|
||||
@@ -206,7 +209,7 @@ static int _read_pv(struct format_instance *fid, struct dm_pool *mem,
|
||||
vg->free_count += pv->pe_count;
|
||||
|
||||
pv->pe_size = vg->extent_size;
|
||||
pv->size = vg->extent_size * (uint64_t) pv->pe_count;
|
||||
|
||||
pv->pe_alloc_count = 0;
|
||||
pv->fmt = fid->fmt;
|
||||
|
||||
|
||||
@@ -83,6 +83,6 @@ struct mda_context {
|
||||
#define FMTT_VERSION 1
|
||||
#define MDA_HEADER_SIZE 512
|
||||
#define LVM2_LABEL "LVM2 001"
|
||||
#define MDA_SIZE_MIN (8 * (unsigned) getpagesize())
|
||||
#define MDA_SIZE_MIN (8 * (unsigned) lvm_getpagesize())
|
||||
|
||||
#endif
|
||||
|
||||
@@ -398,9 +398,9 @@ int lock_resource(struct cmd_context *cmd, const char *resource, int flags)
|
||||
case LCK_VG:
|
||||
/* If the VG name is empty then lock the unused PVs */
|
||||
if (!*resource)
|
||||
lvm_snprintf(lockname, sizeof(lockname), "P_orphans");
|
||||
dm_snprintf(lockname, sizeof(lockname), "P_orphans");
|
||||
else
|
||||
lvm_snprintf(lockname, sizeof(lockname), "V_%s",
|
||||
dm_snprintf(lockname, sizeof(lockname), "V_%s",
|
||||
resource);
|
||||
|
||||
cluster_cmd = CLVMD_CMD_LOCK_VG;
|
||||
|
||||
@@ -212,10 +212,10 @@ static int _file_lock_resource(struct cmd_context *cmd, const char *resource,
|
||||
switch (flags & LCK_SCOPE_MASK) {
|
||||
case LCK_VG:
|
||||
if (!*resource)
|
||||
lvm_snprintf(lockfile, sizeof(lockfile),
|
||||
dm_snprintf(lockfile, sizeof(lockfile),
|
||||
"%s/P_orphans", _lock_dir);
|
||||
else
|
||||
lvm_snprintf(lockfile, sizeof(lockfile),
|
||||
dm_snprintf(lockfile, sizeof(lockfile),
|
||||
"%s/V_%s", _lock_dir, resource);
|
||||
|
||||
if (!_lock_file(lockfile, flags))
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "activate.h"
|
||||
#include "toolcontext.h"
|
||||
#include "memlock.h"
|
||||
#include "defaults.h"
|
||||
|
||||
#include <signal.h>
|
||||
#include <sys/stat.h>
|
||||
@@ -134,24 +135,31 @@ int init_locking(int type, struct cmd_context *cmd)
|
||||
return 1;
|
||||
|
||||
case 1:
|
||||
log_very_verbose("File-based locking selected.");
|
||||
if (!init_file_locking(&_locking, cmd))
|
||||
break;
|
||||
log_very_verbose("File-based locking enabled.");
|
||||
return 1;
|
||||
|
||||
#ifdef HAVE_LIBDL
|
||||
case 2:
|
||||
if (!init_external_locking(&_locking, cmd))
|
||||
if (!cmd->is_static) {
|
||||
log_very_verbose("External locking selected.");
|
||||
if (!init_external_locking(&_locking, cmd))
|
||||
break;
|
||||
return 1;
|
||||
}
|
||||
if (!find_config_tree_int(cmd, "locking/fallback_to_clustered_locking",
|
||||
DEFAULT_FALLBACK_TO_CLUSTERED_LOCKING))
|
||||
break;
|
||||
log_very_verbose("External locking enabled.");
|
||||
return 1;
|
||||
log_very_verbose("Falling back to clustered locking.");
|
||||
/* Fall through */
|
||||
#endif
|
||||
|
||||
#ifdef CLUSTER_LOCKING_INTERNAL
|
||||
case 3:
|
||||
log_very_verbose("Cluster locking selected.");
|
||||
if (!init_cluster_locking(&_locking, cmd))
|
||||
break;
|
||||
log_very_verbose("Cluster locking enabled.");
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
@@ -160,6 +168,16 @@ int init_locking(int type, struct cmd_context *cmd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((type == 2 || type == 3) &&
|
||||
find_config_tree_int(cmd, "locking/fallback_to_local_locking",
|
||||
DEFAULT_FALLBACK_TO_LOCAL_LOCKING)) {
|
||||
log_print("WARNING: Falling back to local file-based locking.");
|
||||
log_print("Volume Groups with the clustered attribute will "
|
||||
"be inaccessible.");
|
||||
if (init_file_locking(&_locking, cmd))
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!ignorelockingfailure())
|
||||
return 0;
|
||||
|
||||
@@ -189,7 +207,7 @@ int check_lvm1_vg_inactive(struct cmd_context *cmd, const char *vgname)
|
||||
if (!*vgname)
|
||||
return 1;
|
||||
|
||||
if (lvm_snprintf(path, sizeof(path), "%s/lvm/VGs/%s", cmd->proc_dir,
|
||||
if (dm_snprintf(path, sizeof(path), "%s/lvm/VGs/%s", cmd->proc_dir,
|
||||
vgname) < 0) {
|
||||
log_error("LVM1 proc VG pathname too long for %s", vgname);
|
||||
return 0;
|
||||
|
||||
@@ -318,7 +318,7 @@ void print_log(int level, const char *file, int line, const char *format, ...)
|
||||
log_it:
|
||||
if (!_log_suppress) {
|
||||
if (_verbose_level > _LOG_DEBUG)
|
||||
lvm_snprintf(locn, sizeof(locn), "#%s:%d ",
|
||||
dm_snprintf(locn, sizeof(locn), "#%s:%d ",
|
||||
file, line);
|
||||
else
|
||||
locn[0] = '\0';
|
||||
@@ -413,7 +413,7 @@ void print_log(int level, const char *file, int line, const char *format, ...)
|
||||
_already_logging = 1;
|
||||
memset(&buf, ' ', sizeof(buf));
|
||||
bufused = 0;
|
||||
if ((n = lvm_snprintf(buf, sizeof(buf) - bufused - 1,
|
||||
if ((n = dm_snprintf(buf, sizeof(buf) - bufused - 1,
|
||||
"%s:%d %s%s", file, line, _cmd_name,
|
||||
_msg_prefix)) == -1)
|
||||
goto done;
|
||||
|
||||
@@ -158,7 +158,7 @@ void release_lv_segment_area(struct lv_segment *seg, uint32_t s,
|
||||
}
|
||||
|
||||
if (seg_lv(seg, s)->status & MIRROR_IMAGE) {
|
||||
lv_reduce(seg_lv(seg, s), area_reduction);
|
||||
lv_reduce(seg_lv(seg, s), area_reduction);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -398,6 +398,7 @@ struct alloced_area {
|
||||
* Details of an allocation attempt
|
||||
*/
|
||||
struct alloc_handle {
|
||||
struct cmd_context *cmd;
|
||||
struct dm_pool *mem;
|
||||
|
||||
alloc_policy_t alloc; /* Overall policy */
|
||||
@@ -417,7 +418,8 @@ struct alloc_handle {
|
||||
/*
|
||||
* Preparation for a specific allocation attempt
|
||||
*/
|
||||
static struct alloc_handle *_alloc_init(struct dm_pool *mem,
|
||||
static struct alloc_handle *_alloc_init(struct cmd_context *cmd,
|
||||
struct dm_pool *mem,
|
||||
const struct segment_type *segtype,
|
||||
alloc_policy_t alloc,
|
||||
uint32_t mirrors,
|
||||
@@ -464,6 +466,8 @@ static struct alloc_handle *_alloc_init(struct dm_pool *mem,
|
||||
if (segtype_is_virtual(segtype))
|
||||
return ah;
|
||||
|
||||
ah->cmd = cmd;
|
||||
|
||||
if (!(ah->mem = dm_pool_create("allocation", 1024))) {
|
||||
log_error("allocation pool creation failed");
|
||||
return NULL;
|
||||
@@ -490,6 +494,49 @@ void alloc_destroy(struct alloc_handle *ah)
|
||||
dm_pool_destroy(ah->mem);
|
||||
}
|
||||
|
||||
static int _log_parallel_areas(struct dm_pool *mem, struct list *parallel_areas)
|
||||
{
|
||||
struct seg_pvs *spvs;
|
||||
struct pv_list *pvl;
|
||||
char *pvnames;
|
||||
|
||||
if (!parallel_areas)
|
||||
return 1;
|
||||
|
||||
if (!dm_pool_begin_object(mem, 256)) {
|
||||
log_error("dm_pool_begin_object failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
list_iterate_items(spvs, parallel_areas) {
|
||||
list_iterate_items(pvl, &spvs->pvs) {
|
||||
if (!dm_pool_grow_object(mem, dev_name(pvl->pv->dev), strlen(dev_name(pvl->pv->dev)))) {
|
||||
log_error("dm_pool_grow_object failed");
|
||||
dm_pool_abandon_object(mem);
|
||||
return 0;
|
||||
}
|
||||
if (!dm_pool_grow_object(mem, " ", 1)) {
|
||||
log_error("dm_pool_grow_object failed");
|
||||
dm_pool_abandon_object(mem);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dm_pool_grow_object(mem, "\0", 1)) {
|
||||
log_error("dm_pool_grow_object failed");
|
||||
dm_pool_abandon_object(mem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pvnames = dm_pool_end_object(mem);
|
||||
log_debug("Parallel PVs at LE %" PRIu32 " length %" PRIu32 ": %s",
|
||||
spvs->le, spvs->len, pvnames);
|
||||
dm_pool_free(mem, pvnames);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _setup_alloced_segment(struct logical_volume *lv, uint32_t status,
|
||||
uint32_t area_count,
|
||||
uint32_t stripe_size,
|
||||
@@ -614,7 +661,7 @@ static int _alloc_parallel_area(struct alloc_handle *ah, uint32_t needed,
|
||||
if (log_area) {
|
||||
ah->log_area.pv = log_area->map->pv;
|
||||
ah->log_area.pe = log_area->start;
|
||||
ah->log_area.len = 1; /* FIXME Calculate & check this */
|
||||
ah->log_area.len = MIRROR_LOG_SIZE; /* FIXME Calculate & check this */
|
||||
consume_pv_area(log_area, ah->log_area.len);
|
||||
}
|
||||
|
||||
@@ -623,6 +670,82 @@ static int _alloc_parallel_area(struct alloc_handle *ah, uint32_t needed,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Call fn for each AREA_PV used by the LV segment at lv:le of length *max_seg_len.
|
||||
* If any constituent area contains more than one segment, max_seg_len is
|
||||
* reduced to cover only the first.
|
||||
* fn should return 0 on error, 1 to continue scanning or >1 to terminate without error.
|
||||
* In the last case, this function passes on the return code.
|
||||
*/
|
||||
static int _for_each_pv(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
uint32_t le, uint32_t len, uint32_t *max_seg_len,
|
||||
uint32_t first_area, uint32_t max_areas,
|
||||
int top_level_area_index,
|
||||
int only_single_area_segments,
|
||||
int (*fn)(struct cmd_context *cmd,
|
||||
struct pv_segment *peg, uint32_t s,
|
||||
void *data),
|
||||
void *data)
|
||||
{
|
||||
struct lv_segment *seg;
|
||||
uint32_t s;
|
||||
uint32_t remaining_seg_len, area_len, area_multiple;
|
||||
int r = 1;
|
||||
|
||||
if (!(seg = find_seg_by_le(lv, le))) {
|
||||
log_error("Failed to find segment for %s extent %" PRIu32,
|
||||
lv->name, le);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Remaining logical length of segment */
|
||||
remaining_seg_len = seg->len - (le - seg->le);
|
||||
|
||||
if (remaining_seg_len > len)
|
||||
remaining_seg_len = len;
|
||||
|
||||
if (max_seg_len && *max_seg_len > remaining_seg_len)
|
||||
*max_seg_len = remaining_seg_len;
|
||||
|
||||
area_multiple = segtype_is_striped(seg->segtype) ? seg->area_count : 1;
|
||||
area_len = remaining_seg_len / area_multiple ? : 1;
|
||||
|
||||
for (s = first_area;
|
||||
s < seg->area_count && (!max_areas || s <= max_areas);
|
||||
s++) {
|
||||
if (seg_type(seg, s) == AREA_LV) {
|
||||
if (!(r = _for_each_pv(cmd, seg_lv(seg, s),
|
||||
seg_le(seg, s) +
|
||||
(le - seg->le) / area_multiple,
|
||||
area_len, max_seg_len,
|
||||
only_single_area_segments ? 0 : 0,
|
||||
only_single_area_segments ? 1 : 0,
|
||||
top_level_area_index != -1 ? top_level_area_index : s,
|
||||
only_single_area_segments, fn,
|
||||
data)))
|
||||
stack;
|
||||
} else if (seg_type(seg, s) == AREA_PV)
|
||||
if (!(r = fn(cmd, seg_pvseg(seg, s), top_level_area_index != -1 ? top_level_area_index : s, data)))
|
||||
stack;
|
||||
if (r != 1)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* FIXME only_single_area_segments used as workaround to skip log LV - needs new param? */
|
||||
if (!only_single_area_segments && seg_is_mirrored(seg) && seg->log_lv) {
|
||||
if (!(r = _for_each_pv(cmd, seg->log_lv, 0, MIRROR_LOG_SIZE,
|
||||
NULL, 0, 0, 0, only_single_area_segments,
|
||||
fn, data)))
|
||||
stack;
|
||||
if (r != 1)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* FIXME Add snapshot cow LVs etc. */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _comp_area(const void *l, const void *r)
|
||||
{
|
||||
const struct pv_area *lhs = *((const struct pv_area **) l);
|
||||
@@ -637,33 +760,114 @@ static int _comp_area(const void *l, const void *r)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Search for pvseg that matches condition
|
||||
*/
|
||||
struct pv_match {
|
||||
int (*condition)(struct pv_segment *pvseg, struct pv_area *pva);
|
||||
|
||||
struct pv_area **areas;
|
||||
struct pv_area *pva;
|
||||
uint32_t areas_size;
|
||||
int s; /* Area index of match */
|
||||
};
|
||||
|
||||
/*
|
||||
* Is PV area on the same PV?
|
||||
*/
|
||||
static int _is_same_pv(struct pv_segment *pvseg, struct pv_area *pva)
|
||||
{
|
||||
if (pvseg->pv != pva->map->pv)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Is PV area contiguous to PV segment?
|
||||
*/
|
||||
static int _is_contiguous(struct pv_segment *pvseg, struct pv_area *pva)
|
||||
{
|
||||
if (pvseg->pv != pva->map->pv)
|
||||
return 0;
|
||||
|
||||
if (pvseg->pe + pvseg->len != pva->start)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _is_condition(struct cmd_context *cmd,
|
||||
struct pv_segment *pvseg, uint32_t s,
|
||||
void *data)
|
||||
{
|
||||
struct pv_match *pvmatch = data;
|
||||
|
||||
if (!pvmatch->condition(pvseg, pvmatch->pva))
|
||||
return 1; /* Continue */
|
||||
|
||||
if (s >= pvmatch->areas_size)
|
||||
return 1;
|
||||
|
||||
pvmatch->areas[s] = pvmatch->pva;
|
||||
|
||||
return 2; /* Finished */
|
||||
}
|
||||
|
||||
/*
|
||||
* Is pva on same PV as any existing areas?
|
||||
*/
|
||||
static int _check_cling(struct cmd_context *cmd,
|
||||
struct lv_segment *prev_lvseg, struct pv_area *pva,
|
||||
struct pv_area **areas, uint32_t areas_size)
|
||||
{
|
||||
struct pv_match pvmatch;
|
||||
int r;
|
||||
|
||||
pvmatch.condition = _is_same_pv;
|
||||
pvmatch.areas = areas;
|
||||
pvmatch.areas_size = areas_size;
|
||||
pvmatch.pva = pva;
|
||||
|
||||
/* FIXME Cope with stacks by flattening */
|
||||
if (!(r = _for_each_pv(cmd, prev_lvseg->lv,
|
||||
prev_lvseg->le + prev_lvseg->len - 1, 1, NULL,
|
||||
0, 0, -1, 1,
|
||||
_is_condition, &pvmatch)))
|
||||
stack;
|
||||
|
||||
if (r != 2)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Is pva contiguous to any existing areas or on the same PV?
|
||||
*/
|
||||
static int _check_contiguous(struct lv_segment *prev_lvseg,
|
||||
struct physical_volume *pv, struct pv_area *pva,
|
||||
struct pv_area **areas)
|
||||
static int _check_contiguous(struct cmd_context *cmd,
|
||||
struct lv_segment *prev_lvseg, struct pv_area *pva,
|
||||
struct pv_area **areas, uint32_t areas_size)
|
||||
{
|
||||
struct pv_segment *prev_pvseg;
|
||||
uint32_t s;
|
||||
struct pv_match pvmatch;
|
||||
int r;
|
||||
|
||||
for (s = 0; s < prev_lvseg->area_count; s++) {
|
||||
if (seg_type(prev_lvseg, s) != AREA_PV)
|
||||
continue; /* FIXME Broken */
|
||||
pvmatch.condition = _is_contiguous;
|
||||
pvmatch.areas = areas;
|
||||
pvmatch.areas_size = areas_size;
|
||||
pvmatch.pva = pva;
|
||||
|
||||
if (!(prev_pvseg = seg_pvseg(prev_lvseg, s)))
|
||||
continue; /* FIXME Broken */
|
||||
/* FIXME Cope with stacks by flattening */
|
||||
if (!(r = _for_each_pv(cmd, prev_lvseg->lv,
|
||||
prev_lvseg->le + prev_lvseg->len - 1, 1, NULL,
|
||||
0, 0, -1, 1,
|
||||
_is_condition, &pvmatch)))
|
||||
stack;
|
||||
|
||||
if ((prev_pvseg->pv != pv))
|
||||
continue;
|
||||
if (r != 2)
|
||||
return 0;
|
||||
|
||||
if (prev_pvseg->pe + prev_pvseg->len == pva->start) {
|
||||
areas[s] = pva;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -679,9 +883,9 @@ static int _find_parallel_space(struct alloc_handle *ah, alloc_policy_t alloc,
|
||||
struct pv_area *pva;
|
||||
struct pv_list *pvl;
|
||||
unsigned already_found_one = 0;
|
||||
unsigned contiguous = 0, contiguous_count = 0;
|
||||
unsigned contiguous = 0, cling = 0, preferred_count = 0;
|
||||
unsigned ix;
|
||||
unsigned ix_offset = 0; /* Offset for non-contiguous allocations */
|
||||
unsigned ix_offset = 0; /* Offset for non-preferred allocations */
|
||||
uint32_t max_parallel; /* Maximum extents to allocate */
|
||||
uint32_t next_le;
|
||||
struct seg_pvs *spvs;
|
||||
@@ -691,9 +895,14 @@ static int _find_parallel_space(struct alloc_handle *ah, alloc_policy_t alloc,
|
||||
/* FIXME Select log PV appropriately if there isn't one yet */
|
||||
|
||||
/* Are there any preceding segments we must follow on from? */
|
||||
if ((alloc == ALLOC_CONTIGUOUS) && prev_lvseg) {
|
||||
contiguous = 1;
|
||||
if (prev_lvseg) {
|
||||
ix_offset = prev_lvseg->area_count;
|
||||
if ((alloc == ALLOC_CONTIGUOUS))
|
||||
contiguous = 1;
|
||||
else if ((alloc == ALLOC_CLING))
|
||||
cling = 1;
|
||||
else
|
||||
ix_offset = 0;
|
||||
}
|
||||
|
||||
/* FIXME This algorithm needs a lot of cleaning up! */
|
||||
@@ -702,6 +911,7 @@ static int _find_parallel_space(struct alloc_handle *ah, alloc_policy_t alloc,
|
||||
/* ix holds the number of areas found on other PVs */
|
||||
do {
|
||||
ix = 0;
|
||||
preferred_count = 0;
|
||||
|
||||
parallel_pvs = NULL;
|
||||
max_parallel = needed;
|
||||
@@ -711,14 +921,15 @@ static int _find_parallel_space(struct alloc_handle *ah, alloc_policy_t alloc,
|
||||
* the maximum we can allocate in one go accordingly.
|
||||
*/
|
||||
if (ah->parallel_areas) {
|
||||
next_le = (prev_lvseg ? prev_lvseg->le + prev_lvseg->len : 0) + *allocated / ah->area_multiple;
|
||||
list_iterate_items(spvs, ah->parallel_areas) {
|
||||
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) * ah->area_multiple;
|
||||
parallel_pvs = &spvs->pvs;
|
||||
break;
|
||||
}
|
||||
if (next_le >= spvs->le + spvs->len)
|
||||
continue;
|
||||
|
||||
if (max_parallel > (spvs->le + spvs->len) * ah->area_multiple)
|
||||
max_parallel = (spvs->le + spvs->len) * ah->area_multiple;
|
||||
parallel_pvs = &spvs->pvs;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -750,17 +961,30 @@ static int _find_parallel_space(struct alloc_handle *ah, alloc_policy_t alloc,
|
||||
list_iterate_items(pva, &pvm->areas) {
|
||||
if (contiguous) {
|
||||
if (prev_lvseg &&
|
||||
_check_contiguous(prev_lvseg,
|
||||
pvm->pv,
|
||||
pva, areas)) {
|
||||
contiguous_count++;
|
||||
_check_contiguous(ah->cmd,
|
||||
prev_lvseg,
|
||||
pva, areas,
|
||||
areas_size)) {
|
||||
preferred_count++;
|
||||
goto next_pv;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cling) {
|
||||
if (prev_lvseg &&
|
||||
_check_cling(ah->cmd,
|
||||
prev_lvseg,
|
||||
pva, areas,
|
||||
areas_size)) {
|
||||
preferred_count++;
|
||||
}
|
||||
goto next_pv;
|
||||
}
|
||||
|
||||
/* Is it big enough on its own? */
|
||||
if ((pva->count < max_parallel - *allocated) &&
|
||||
if (pva->count * ah->area_multiple <
|
||||
max_parallel - *allocated &&
|
||||
((!can_split && !ah->log_count) ||
|
||||
(already_found_one &&
|
||||
!(alloc == ALLOC_ANYWHERE))))
|
||||
@@ -781,7 +1005,7 @@ static int _find_parallel_space(struct alloc_handle *ah, alloc_policy_t alloc,
|
||||
break;
|
||||
}
|
||||
|
||||
if (contiguous && (contiguous_count < ix_offset))
|
||||
if ((contiguous || cling) && (preferred_count < ix_offset))
|
||||
break;
|
||||
|
||||
/* Only allocate log_area the first time around */
|
||||
@@ -853,6 +1077,9 @@ static int _allocate(struct alloc_handle *ah,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!_log_parallel_areas(ah->mem, ah->parallel_areas))
|
||||
stack;
|
||||
|
||||
areas_size = list_size(pvms);
|
||||
if (areas_size < ah->area_count + ah->log_count) {
|
||||
if (ah->alloc != ALLOC_ANYWHERE) {
|
||||
@@ -887,6 +1114,18 @@ static int _allocate(struct alloc_handle *ah,
|
||||
(!can_split && (allocated != old_allocated)))
|
||||
goto finished;
|
||||
|
||||
old_allocated = allocated;
|
||||
if (!_find_parallel_space(ah, ALLOC_CLING, pvms, areas,
|
||||
areas_size, can_split,
|
||||
prev_lvseg, &allocated, new_extents)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((allocated == new_extents) || (ah->alloc == ALLOC_CLING) ||
|
||||
(!can_split && (allocated != old_allocated)))
|
||||
goto finished;
|
||||
|
||||
old_allocated = allocated;
|
||||
if (!_find_parallel_space(ah, ALLOC_NORMAL, pvms, areas,
|
||||
areas_size, can_split,
|
||||
@@ -982,7 +1221,7 @@ struct alloc_handle *allocate_extents(struct volume_group *vg,
|
||||
if (alloc == ALLOC_INHERIT)
|
||||
alloc = vg->alloc;
|
||||
|
||||
if (!(ah = _alloc_init(vg->cmd->mem, segtype, alloc, mirrors,
|
||||
if (!(ah = _alloc_init(vg->cmd, vg->cmd->mem, segtype, alloc, mirrors,
|
||||
stripes, log_count, mirrored_pv,
|
||||
mirrored_pe, parallel_areas))) {
|
||||
stack;
|
||||
@@ -1213,7 +1452,7 @@ int lv_extend(struct logical_volume *lv,
|
||||
log_error("Aborting. Failed to extend %s.",
|
||||
seg_lv(seg, m)->name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
seg->area_len += extents;
|
||||
seg->len += extents;
|
||||
@@ -1240,7 +1479,7 @@ char *generate_lv_name(struct volume_group *vg, const char *format,
|
||||
high = i;
|
||||
}
|
||||
|
||||
if (lvm_snprintf(buffer, len, format, high + 1) < 0)
|
||||
if (dm_snprintf(buffer, len, format, high + 1) < 0)
|
||||
return NULL;
|
||||
|
||||
return buffer;
|
||||
@@ -1326,58 +1565,16 @@ struct logical_volume *lv_create_empty(struct format_instance *fi,
|
||||
return lv;
|
||||
}
|
||||
|
||||
/* Recursively process each PV used by part of an LV */
|
||||
static int _for_each_pv(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
uint32_t le, uint32_t len,
|
||||
int (*fn)(struct cmd_context *cmd, struct pv_segment *peg, struct seg_pvs *spvs),
|
||||
struct seg_pvs *spvs)
|
||||
{
|
||||
struct lv_segment *seg;
|
||||
uint32_t s;
|
||||
uint32_t remaining_seg_len, area_len, area_multiple;
|
||||
|
||||
if (!(seg = find_seg_by_le(lv, le))) {
|
||||
log_error("Failed to find segment for %s extent %" PRIu32,
|
||||
lv->name, le);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Remaining logical length of segment */
|
||||
remaining_seg_len = seg->len - (le - seg->le);
|
||||
|
||||
if (len > remaining_seg_len)
|
||||
remaining_seg_len = len;
|
||||
|
||||
if (spvs->len > remaining_seg_len)
|
||||
spvs->len = remaining_seg_len;
|
||||
|
||||
area_multiple = segtype_is_striped(seg->segtype) ? seg->area_count : 1;
|
||||
area_len = remaining_seg_len / area_multiple;
|
||||
|
||||
for (s = 0; s < seg->area_count; s++) {
|
||||
if (seg_type(seg, s) == AREA_LV) {
|
||||
if (!_for_each_pv(cmd, seg_lv(seg, s),
|
||||
seg_le(seg, s) + (le - seg->le) / area_multiple,
|
||||
area_len, fn, spvs)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
} else if (seg_type(seg, s) == AREA_PV) {
|
||||
if (!fn(cmd, seg_pvseg(seg, s), spvs)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _add_pvs(struct cmd_context *cmd, struct pv_segment *peg, struct seg_pvs *spvs)
|
||||
static int _add_pvs(struct cmd_context *cmd, struct pv_segment *peg,
|
||||
uint32_t s __attribute((unused)), void *data)
|
||||
{
|
||||
struct seg_pvs *spvs = (struct seg_pvs *) data;
|
||||
struct pv_list *pvl;
|
||||
|
||||
/* FIXME Don't add again if it's already on the list! */
|
||||
/* Don't add again if it's already on list. */
|
||||
list_iterate_items(pvl, &spvs->pvs)
|
||||
if (pvl->pv == peg->pv)
|
||||
return 1;
|
||||
|
||||
if (!(pvl = dm_pool_alloc(cmd->mem, sizeof(*pvl)))) {
|
||||
log_error("pv_list allocation failed");
|
||||
@@ -1386,11 +1583,8 @@ static int _add_pvs(struct cmd_context *cmd, struct pv_segment *peg, struct seg_
|
||||
|
||||
pvl->pv = peg->pv;
|
||||
|
||||
/* FIXME Use ordered list to facilitate comparison */
|
||||
list_add(&spvs->pvs, &pvl->list);
|
||||
|
||||
/* FIXME Add mirror logs, snapshot cow LVs etc. */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1426,7 +1620,8 @@ struct list *build_parallel_areas_from_lv(struct cmd_context *cmd,
|
||||
|
||||
/* Find next segment end */
|
||||
/* FIXME Unnecessary nesting! */
|
||||
if (!_for_each_pv(cmd, lv, current_le, lv->le_count, _add_pvs, spvs)) {
|
||||
if (!_for_each_pv(cmd, lv, current_le, spvs->len, &spvs->len,
|
||||
0, 0, -1, 0, _add_pvs, (void *) spvs)) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,13 @@
|
||||
#include "pv_alloc.h"
|
||||
#include "activate.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
|
||||
unsigned long pe_align(void)
|
||||
{
|
||||
return MAX(65536UL, lvm_getpagesize()) >> SECTOR_SHIFT;
|
||||
}
|
||||
|
||||
static int _add_pv_to_vg(struct format_instance *fid, struct volume_group *vg,
|
||||
const char *pv_name)
|
||||
{
|
||||
@@ -78,15 +85,12 @@ static int _add_pv_to_vg(struct format_instance *fid, struct volume_group *vg,
|
||||
|
||||
/* FIXME Do proper rounding-up alignment? */
|
||||
/* Reserved space for label; this holds 0 for PVs created by LVM1 */
|
||||
if (pv->pe_start < PE_ALIGN)
|
||||
pv->pe_start = PE_ALIGN;
|
||||
if (pv->pe_start < pe_align())
|
||||
pv->pe_start = pe_align();
|
||||
|
||||
/*
|
||||
* The next two fields should be corrected
|
||||
* by fid->pv_setup.
|
||||
* pe_count must always be calculated by pv_setup
|
||||
*/
|
||||
pv->pe_count = (pv->size - pv->pe_start) / vg->extent_size;
|
||||
|
||||
pv->pe_alloc_count = 0;
|
||||
|
||||
if (!fid->fmt->ops->pv_setup(fid->fmt, UINT64_C(0), 0,
|
||||
@@ -727,6 +731,8 @@ int vg_validate(struct volume_group *vg)
|
||||
char uuid[64];
|
||||
int r = 1;
|
||||
|
||||
/* FIXME Also check there's no data/metadata overlap */
|
||||
|
||||
list_iterate_items(pvl, &vg->pvs) {
|
||||
list_iterate_items(pvl2, &vg->pvs) {
|
||||
if (pvl == pvl2)
|
||||
@@ -1037,7 +1043,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
|
||||
if (correct_vg) {
|
||||
if (list_size(&correct_vg->pvs) != list_size(pvids)) {
|
||||
log_debug("Cached VG %s had incorrect PV list",
|
||||
vg->name);
|
||||
vgname);
|
||||
|
||||
if (memlock())
|
||||
inconsistent = 1;
|
||||
@@ -1046,7 +1052,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
|
||||
} else list_iterate_items(pvl, &correct_vg->pvs) {
|
||||
if (!str_list_match_item(pvids, pvl->pv->dev->pvid)) {
|
||||
log_debug("Cached VG %s had incorrect PV list",
|
||||
vg->name);
|
||||
vgname);
|
||||
correct_vg = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -29,12 +29,12 @@
|
||||
#define MAX_STRIPES 128U
|
||||
#define SECTOR_SHIFT 9L
|
||||
#define SECTOR_SIZE ( 1L << SECTOR_SHIFT )
|
||||
#define STRIPE_SIZE_MIN ( (unsigned) getpagesize() >> SECTOR_SHIFT) /* PAGESIZE in sectors */
|
||||
#define STRIPE_SIZE_MIN ( (unsigned) lvm_getpagesize() >> SECTOR_SHIFT) /* PAGESIZE in sectors */
|
||||
#define STRIPE_SIZE_MAX ( 512L * 1024L >> SECTOR_SHIFT) /* 512 KB in sectors */
|
||||
#define STRIPE_SIZE_LIMIT ((UINT_MAX >> 2) + 1)
|
||||
#define PV_MIN_SIZE ( 512L * 1024L >> SECTOR_SHIFT) /* 512 KB in sectors */
|
||||
#define PE_ALIGN (65536UL >> SECTOR_SHIFT) /* PE alignment */
|
||||
#define MAX_RESTRICTED_LVS 255 /* Used by FMT_RESTRICTED_LVIDS */
|
||||
#define MIRROR_LOG_SIZE 1 /* Extents */
|
||||
|
||||
/* Various flags */
|
||||
/* Note that the bits no longer necessarily correspond to LVM1 disk format */
|
||||
@@ -82,6 +82,7 @@ typedef enum {
|
||||
ALLOC_INVALID = 0,
|
||||
ALLOC_INHERIT,
|
||||
ALLOC_CONTIGUOUS,
|
||||
ALLOC_CLING,
|
||||
ALLOC_NORMAL,
|
||||
ALLOC_ANYWHERE
|
||||
} alloc_policy_t;
|
||||
@@ -403,6 +404,7 @@ struct format_handler {
|
||||
/*
|
||||
* Utility functions
|
||||
*/
|
||||
unsigned long pe_align(void);
|
||||
int vg_validate(struct volume_group *vg);
|
||||
int vg_write(struct volume_group *vg);
|
||||
int vg_commit(struct volume_group *vg);
|
||||
|
||||
@@ -161,9 +161,11 @@ int remove_mirror_images(struct lv_segment *mirrored_seg, uint32_t num_mirrors,
|
||||
remove_log = 1;
|
||||
}
|
||||
|
||||
if (remove_log) {
|
||||
if (remove_log && mirrored_seg->log_lv) {
|
||||
log_lv = mirrored_seg->log_lv;
|
||||
mirrored_seg->log_lv = NULL;
|
||||
log_lv->status &= ~MIRROR_LOG;
|
||||
log_lv->status |= VISIBLE_LV;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -428,7 +430,7 @@ static int _create_layers_for_mirror(struct alloc_handle *ah,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lvm_snprintf(img_name, len, "%s_mimage_%%d", lv->name) < 0) {
|
||||
if (dm_snprintf(img_name, len, "%s_mimage_%%d", lv->name) < 0) {
|
||||
log_error("img_name allocation failed. "
|
||||
"Remove new LV and retry.");
|
||||
return 0;
|
||||
|
||||
@@ -77,6 +77,9 @@ struct segtype_handler {
|
||||
uint64_t *total_numerator,
|
||||
uint64_t *total_denominator, float *percent);
|
||||
int (*target_present) (void);
|
||||
int (*modules_needed) (struct dm_pool *mem,
|
||||
const struct lv_segment *seg,
|
||||
struct list *modules);
|
||||
void (*destroy) (const struct segment_type * segtype);
|
||||
int (*target_register_events) (struct lv_segment *seg, int events);
|
||||
int (*target_unregister_events) (struct lv_segment *seg, int events);
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "targets.h"
|
||||
#include "activate.h"
|
||||
#include "sharedlib.h"
|
||||
#include "str_list.h"
|
||||
|
||||
#ifdef DMEVENTD
|
||||
# include <libdevmapper-event.h>
|
||||
@@ -447,6 +448,28 @@ static int _target_unregister_events(struct lv_segment *seg,
|
||||
#endif /* DMEVENTD */
|
||||
#endif /* DEVMAPPER_SUPPORT */
|
||||
|
||||
static int _mirrored_modules_needed(struct dm_pool *mem,
|
||||
const struct lv_segment *seg,
|
||||
struct list *modules)
|
||||
{
|
||||
if (seg->log_lv &&
|
||||
!list_segment_modules(mem, first_seg(seg->log_lv), modules))
|
||||
return_0;
|
||||
|
||||
if ((seg->lv->vg->status & CLUSTERED) &&
|
||||
!str_list_add(mem, modules, "clog")) {
|
||||
log_error("cluster log string list allocation failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!str_list_add(mem, modules, "mirror")) {
|
||||
log_error("mirror string list allocation failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _mirrored_destroy(const struct segment_type *segtype)
|
||||
{
|
||||
dm_free((void *) segtype);
|
||||
@@ -467,6 +490,7 @@ static struct segtype_handler _mirrored_ops = {
|
||||
.target_unregister_events = _target_unregister_events,
|
||||
#endif
|
||||
#endif
|
||||
.modules_needed = _mirrored_modules_needed,
|
||||
.destroy = _mirrored_destroy,
|
||||
};
|
||||
|
||||
|
||||
@@ -174,6 +174,9 @@
|
||||
/* Define to 1 if you have the <selinux/selinux.h> header file. */
|
||||
#undef HAVE_SELINUX_SELINUX_H
|
||||
|
||||
/* define to 1 to include support for realtime clock */
|
||||
#undef HAVE_REALTIME
|
||||
|
||||
/* Define to 1 if you have the `setlocale' function. */
|
||||
#undef HAVE_SETLOCALE
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "log.h"
|
||||
#include "intl.h"
|
||||
#include "lvm-types.h"
|
||||
#include "lvm-wrappers.h"
|
||||
|
||||
#include <libdevmapper.h>
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ int create_temp_name(const char *dir, char *buffer, size_t len, int *fd)
|
||||
|
||||
for (i = 0; i < 20; i++, num++) {
|
||||
|
||||
if (lvm_snprintf(buffer, len, "%s/.lvm_%s_%d_%d",
|
||||
if (dm_snprintf(buffer, len, "%s/.lvm_%s_%d_%d",
|
||||
dir, hostname, pid, num) == -1) {
|
||||
log_err("Not enough space to build temporary file "
|
||||
"string.");
|
||||
|
||||
@@ -14,33 +14,10 @@
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
#include "lvm-types.h"
|
||||
#include "lvm-string.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
/*
|
||||
* On error, up to glibc 2.0.6, snprintf returned -1 if buffer was too small;
|
||||
* From glibc 2.1 it returns number of chars (excl. trailing null) that would
|
||||
* have been written had there been room.
|
||||
*
|
||||
* lvm_snprintf reverts to the old behaviour.
|
||||
*/
|
||||
int lvm_snprintf(char *buf, size_t bufsize, const char *format, ...)
|
||||
{
|
||||
int n;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
n = vsnprintf(buf, bufsize, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (n < 0 || (n > bufsize - 1))
|
||||
return -1;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
int emit_to_buffer(char **buffer, size_t *size, const char *fmt, ...)
|
||||
{
|
||||
int n;
|
||||
@@ -58,47 +35,6 @@ int emit_to_buffer(char **buffer, size_t *size, const char *fmt, ...)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* consume characters while they match the predicate function.
|
||||
*/
|
||||
static char *_consume(char *buffer, int (*fn) (int))
|
||||
{
|
||||
while (*buffer && fn(*buffer))
|
||||
buffer++;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static int _isword(int c)
|
||||
{
|
||||
return !isspace(c);
|
||||
}
|
||||
|
||||
/*
|
||||
* Split buffer into NULL-separated words in argv.
|
||||
* Returns number of words.
|
||||
*/
|
||||
int split_words(char *buffer, unsigned max, char **argv)
|
||||
{
|
||||
unsigned arg;
|
||||
|
||||
for (arg = 0; arg < max; arg++) {
|
||||
buffer = _consume(buffer, isspace);
|
||||
if (!*buffer)
|
||||
break;
|
||||
|
||||
argv[arg] = buffer;
|
||||
buffer = _consume(buffer, _isword);
|
||||
|
||||
if (*buffer) {
|
||||
*buffer = '\0';
|
||||
buffer++;
|
||||
}
|
||||
}
|
||||
|
||||
return arg;
|
||||
}
|
||||
|
||||
/*
|
||||
* Device layer names are all of the form <vg>-<lv>-<layer>, any
|
||||
* other hyphens that appear in these names are quoted with yet
|
||||
@@ -169,47 +105,6 @@ char *build_dm_name(struct dm_pool *mem, const char *vgname,
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove hyphen quoting from a component of a name.
|
||||
* NULL-terminates the component and returns start of next component.
|
||||
*/
|
||||
static char *_unquote(char *component)
|
||||
{
|
||||
char *c = component;
|
||||
char *o = c;
|
||||
char *r;
|
||||
|
||||
while (*c) {
|
||||
if (*(c + 1)) {
|
||||
if (*c == '-') {
|
||||
if (*(c + 1) == '-')
|
||||
c++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
*o = *c;
|
||||
o++;
|
||||
c++;
|
||||
}
|
||||
|
||||
r = (*c) ? c + 1 : c;
|
||||
*o = '\0';
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int split_dm_name(struct dm_pool *mem, const char *dmname,
|
||||
char **vgname, char **lvname, char **layer)
|
||||
{
|
||||
if (!(*vgname = dm_pool_strdup(mem, dmname)))
|
||||
return 0;
|
||||
|
||||
_unquote(*layer = _unquote(*lvname = _unquote(*vgname)));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int validate_name(const char *n)
|
||||
{
|
||||
register char c;
|
||||
|
||||
@@ -23,25 +23,11 @@
|
||||
|
||||
struct pool;
|
||||
|
||||
/*
|
||||
* On error, up to glibc 2.0.6, snprintf returned -1 if buffer was too small;
|
||||
* From glibc 2.1 it returns number of chars (excl. trailing null) that would
|
||||
* have been written had there been room.
|
||||
*
|
||||
* lvm_snprintf reverts to the old behaviour.
|
||||
*/
|
||||
int lvm_snprintf(char *buf, size_t bufsize, const char *format, ...);
|
||||
|
||||
int emit_to_buffer(char **buffer, size_t *size, const char *fmt, ...);
|
||||
|
||||
int split_words(char *buffer, unsigned max, char **argv);
|
||||
|
||||
char *build_dm_name(struct dm_pool *mem, const char *vg,
|
||||
const char *lv, const char *layer);
|
||||
|
||||
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
lib/misc/lvm-wrappers.c
Normal file
22
lib/misc/lvm-wrappers.c
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2006 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
int lvm_getpagesize(void)
|
||||
{
|
||||
return getpagesize();
|
||||
}
|
||||
21
lib/misc/lvm-wrappers.h
Normal file
21
lib/misc/lvm-wrappers.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* 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 LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_WRAPPERS_H
|
||||
#define _LVM_WRAPPERS_H
|
||||
|
||||
int lvm_getpagesize(void);
|
||||
|
||||
#endif
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "config.h"
|
||||
#include "lvm-string.h"
|
||||
#include "sharedlib.h"
|
||||
#include "toolcontext.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <sys/stat.h>
|
||||
@@ -32,7 +33,7 @@ void get_shared_library_path(struct cmd_context *cmd, const char *libname,
|
||||
* if present */
|
||||
if (libname[0] == '/' ||
|
||||
!(lib_dir = find_config_tree_str(cmd, "global/library_dir", 0)) ||
|
||||
(lvm_snprintf(path, path_len, "%s/%s", lib_dir,
|
||||
(dm_snprintf(path, path_len, "%s/%s", lib_dir,
|
||||
libname) == -1) || stat(path, &info) == -1)
|
||||
strncpy(path, libname, path_len);
|
||||
}
|
||||
@@ -43,6 +44,12 @@ void *load_shared_library(struct cmd_context *cmd, const char *libname,
|
||||
char path[PATH_MAX];
|
||||
void *library;
|
||||
|
||||
if (cmd->is_static) {
|
||||
log_error("Not loading shared %s library %s in static mode.",
|
||||
desc, libname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
get_shared_library_path(cmd, libname, path, sizeof(path));
|
||||
|
||||
log_very_verbose("Opening shared %s library %s", desc, path);
|
||||
|
||||
130
lib/misc/timestamp.c
Normal file
130
lib/misc/timestamp.c
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (C) 2006 Rackable Systems All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Abstract out the time methods used so they can be adjusted later -
|
||||
* the results of these routines should stay in-core. This implementation
|
||||
* requires librt.
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "timestamp.h"
|
||||
|
||||
/*
|
||||
* The realtime section uses clock_gettime with the CLOCK_MONOTONIC
|
||||
* parameter to prevent issues with time warps
|
||||
*/
|
||||
#ifdef HAVE_REALTIME
|
||||
|
||||
#include <time.h>
|
||||
#include <bits/time.h>
|
||||
|
||||
struct timestamp {
|
||||
struct timespec t;
|
||||
};
|
||||
|
||||
struct timestamp *get_timestamp(void)
|
||||
{
|
||||
struct timestamp *ts = NULL;
|
||||
|
||||
if (!(ts = dm_malloc(sizeof(*ts))))
|
||||
return_NULL;
|
||||
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &ts->t)) {
|
||||
log_sys_error("clock_gettime", "get_timestamp");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ts;
|
||||
}
|
||||
|
||||
/* cmp_timestamp: Compare two timestamps
|
||||
*
|
||||
* Return: -1 if t1 is less than t2
|
||||
* 0 if t1 is equal to t2
|
||||
* 1 if t1 is greater than t2
|
||||
*/
|
||||
int cmp_timestamp(struct timestamp *t1, struct timestamp *t2)
|
||||
{
|
||||
if(t1->t.tv_sec < t2->t.tv_sec)
|
||||
return -1;
|
||||
if(t1->t.tv_sec > t2->t.tv_sec)
|
||||
return 1;
|
||||
|
||||
if(t1->t.tv_nsec < t2->t.tv_nsec)
|
||||
return -1;
|
||||
if(t1->t.tv_nsec > t2->t.tv_nsec)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* ! HAVE_REALTIME */
|
||||
|
||||
/*
|
||||
* The !realtime section just uses gettimeofday and is therefore subject
|
||||
* to ntp-type time warps - not sure if should allow that.
|
||||
*/
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
struct timestamp {
|
||||
struct timeval t;
|
||||
};
|
||||
|
||||
struct timestamp *get_timestamp(void)
|
||||
{
|
||||
struct timestamp *ts = NULL;
|
||||
|
||||
if (!(ts = dm_malloc(sizeof(*ts))))
|
||||
return_NULL;
|
||||
|
||||
if (gettimeofday(&ts->t, NULL)) {
|
||||
log_sys_error("gettimeofday", "get_timestamp");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ts;
|
||||
}
|
||||
|
||||
/* cmp_timestamp: Compare two timestamps
|
||||
*
|
||||
* Return: -1 if t1 is less than t2
|
||||
* 0 if t1 is equal to t2
|
||||
* 1 if t1 is greater than t2
|
||||
*/
|
||||
int cmp_timestamp(struct timestamp *t1, struct timestamp *t2)
|
||||
{
|
||||
if(t1->t.tv_sec < t2->t.tv_sec)
|
||||
return -1;
|
||||
if(t1->t.tv_sec > t2->t.tv_sec)
|
||||
return 1;
|
||||
|
||||
if(t1->t.tv_usec < t2->t.tv_usec)
|
||||
return -1;
|
||||
if(t1->t.tv_usec > t2->t.tv_usec)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* HAVE_REALTIME */
|
||||
|
||||
void destroy_timestamp(struct timestamp *t)
|
||||
{
|
||||
if (t)
|
||||
dm_free(t);
|
||||
}
|
||||
33
lib/misc/timestamp.h
Normal file
33
lib/misc/timestamp.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2006 Rackable Systems All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_TIMESTAMP_H
|
||||
#define _LVM_TIMESTAMP_H
|
||||
|
||||
struct timestamp;
|
||||
|
||||
struct timestamp *get_timestamp(void);
|
||||
|
||||
/* cmp_timestamp: Compare two timestamps
|
||||
*
|
||||
* Return: -1 if t1 is less than t2
|
||||
* 0 if t1 is equal to t2
|
||||
* 1 if t1 is greater than t2
|
||||
*/
|
||||
int cmp_timestamp(struct timestamp *t1, struct timestamp *t2);
|
||||
|
||||
void destroy_timestamp(struct timestamp *t);
|
||||
|
||||
#endif /* _LVM_TIMESTAMP_H */
|
||||
|
||||
@@ -58,7 +58,7 @@ static int _default_priority;
|
||||
|
||||
static void _touch_memory(void *mem, size_t size)
|
||||
{
|
||||
size_t pagesize = getpagesize();
|
||||
size_t pagesize = lvm_getpagesize();
|
||||
void *pos = mem;
|
||||
void *end = mem + size - sizeof(long);
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ FIELD(LVS, lv, NUM, "Copy%", lvid, 6, copypercent, "copy_percent")
|
||||
FIELD(LVS, lv, STR, "Move", lvid, 4, movepv, "move_pv")
|
||||
FIELD(LVS, lv, STR, "LV Tags", tags, 7, tags, "lv_tags")
|
||||
FIELD(LVS, lv, STR, "Log", lvid, 3, loglv, "mirror_log")
|
||||
FIELD(LVS, lv, STR, "Modules", lvid, 7, modules, "modules")
|
||||
|
||||
FIELD(PVS, pv, STR, "Fmt", id, 3, pvfmt, "pv_fmt")
|
||||
FIELD(PVS, pv, STR, "PV UUID", id, 38, uuid, "pv_uuid")
|
||||
@@ -68,8 +69,11 @@ FIELD(VGS, vg, STR, "VG Tags", tags, 7, tags, "vg_tags")
|
||||
FIELD(SEGS, seg, STR, "Type", list, 4, segtype, "segtype")
|
||||
FIELD(SEGS, seg, NUM, "#Str", area_count, 4, uint32, "stripes")
|
||||
FIELD(SEGS, seg, NUM, "Stripe", stripe_size, 6, size32, "stripesize")
|
||||
FIELD(SEGS, seg, NUM, "Stripe", stripe_size, 6, size32, "stripe_size")
|
||||
FIELD(SEGS, seg, NUM, "Chunk", list, 5, chunksize, "chunksize")
|
||||
FIELD(SEGS, seg, NUM, "Chunk", list, 5, chunksize, "chunk_size")
|
||||
FIELD(SEGS, seg, NUM, "Region", region_size, 6, size32, "regionsize")
|
||||
FIELD(SEGS, seg, NUM, "Region", region_size, 6, size32, "region_size")
|
||||
FIELD(SEGS, seg, NUM, "Start", list, 5, segstart, "seg_start")
|
||||
FIELD(SEGS, seg, NUM, "SSize", list, 5, segsize, "seg_size")
|
||||
FIELD(SEGS, seg, STR, "Seg Tags", tags, 8, tags, "seg_tags")
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "display.h"
|
||||
#include "activate.h"
|
||||
#include "segtype.h"
|
||||
#include "str_list.h"
|
||||
|
||||
/*
|
||||
* For macro use
|
||||
@@ -103,6 +104,8 @@ static char _alloc_policy_char(alloc_policy_t alloc)
|
||||
switch (alloc) {
|
||||
case ALLOC_CONTIGUOUS:
|
||||
return 'c';
|
||||
case ALLOC_CLING:
|
||||
return 'C';
|
||||
case ALLOC_NORMAL:
|
||||
return 'n';
|
||||
case ALLOC_ANYWHERE:
|
||||
@@ -172,9 +175,9 @@ static int _devices_disp(struct report_handle *rh, struct field *field,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lvm_snprintf(extent_str, sizeof(extent_str), "(%" PRIu32
|
||||
if (dm_snprintf(extent_str, sizeof(extent_str), "(%" PRIu32
|
||||
")", extent) < 0) {
|
||||
log_error("Extent number lvm_snprintf failed");
|
||||
log_error("Extent number dm_snprintf failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -200,6 +203,7 @@ static int _devices_disp(struct report_handle *rh, struct field *field,
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _tags_disp(struct report_handle *rh, struct field *field,
|
||||
const void *data)
|
||||
{
|
||||
@@ -230,6 +234,23 @@ static int _tags_disp(struct report_handle *rh, struct field *field,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _modules_disp(struct report_handle *rh, struct field *field,
|
||||
const void *data)
|
||||
{
|
||||
const struct logical_volume *lv = (const struct logical_volume *) data;
|
||||
struct list *modules;
|
||||
|
||||
if (!(modules = str_list_create(rh->mem))) {
|
||||
log_error("modules str_list allocation failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!list_lv_modules(rh->mem, lv, modules))
|
||||
return_0;
|
||||
|
||||
return _tags_disp(rh, field, modules);
|
||||
}
|
||||
|
||||
static int _vgfmt_disp(struct report_handle *rh, struct field *field,
|
||||
const void *data)
|
||||
{
|
||||
@@ -276,7 +297,7 @@ static int _int_disp(struct report_handle *rh, struct field *field,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lvm_snprintf(repstr, 12, "%d", value) < 0) {
|
||||
if (dm_snprintf(repstr, 12, "%d", value) < 0) {
|
||||
log_error("int too big: %d", value);
|
||||
return 0;
|
||||
}
|
||||
@@ -540,7 +561,7 @@ static int _lvname_disp(struct report_handle *rh, struct field *field,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lvm_snprintf(repstr, len, "[%s]", lv->name) < 0) {
|
||||
if (dm_snprintf(repstr, len, "[%s]", lv->name) < 0) {
|
||||
log_error("lvname snprintf failed");
|
||||
return 0;
|
||||
}
|
||||
@@ -784,7 +805,7 @@ static int _uint32_disp(struct report_handle *rh, struct field *field,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lvm_snprintf(repstr, 11, "%u", value) < 0) {
|
||||
if (dm_snprintf(repstr, 11, "%u", value) < 0) {
|
||||
log_error("uint32 too big: %u", value);
|
||||
return 0;
|
||||
}
|
||||
@@ -813,7 +834,7 @@ static int _int32_disp(struct report_handle *rh, struct field *field,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lvm_snprintf(repstr, 12, "%d", value) < 0) {
|
||||
if (dm_snprintf(repstr, 12, "%d", value) < 0) {
|
||||
log_error("int32 too big: %d", value);
|
||||
return 0;
|
||||
}
|
||||
@@ -870,7 +891,7 @@ static int _snpercent_disp(struct report_handle *rh, struct field *field,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lvm_snprintf(repstr, 7, "%.2f", snap_percent) < 0) {
|
||||
if (dm_snprintf(repstr, 7, "%.2f", snap_percent) < 0) {
|
||||
log_error("snapshot percentage too large");
|
||||
return 0;
|
||||
}
|
||||
@@ -910,7 +931,7 @@ static int _copypercent_disp(struct report_handle *rh, struct field *field,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lvm_snprintf(repstr, 7, "%.2f", percent) < 0) {
|
||||
if (dm_snprintf(repstr, 7, "%.2f", percent) < 0) {
|
||||
log_error("copy percentage too large");
|
||||
return 0;
|
||||
}
|
||||
@@ -948,6 +969,44 @@ static struct {
|
||||
|
||||
const unsigned int _num_fields = sizeof(_fields) / sizeof(_fields[0]);
|
||||
|
||||
static void _display_fields(void)
|
||||
{
|
||||
uint32_t f;
|
||||
const char *type, *last_type = "";
|
||||
|
||||
for (f = 0; f < _num_fields; f++) {
|
||||
switch (_fields[f].type) {
|
||||
case PVS:
|
||||
type = "Physical Volume";
|
||||
break;
|
||||
case LVS:
|
||||
type = "Logical Volume";
|
||||
break;
|
||||
case VGS:
|
||||
type = "Volume Group";
|
||||
break;
|
||||
case SEGS:
|
||||
type = "Logical Volume Segment";
|
||||
break;
|
||||
case PVSEGS:
|
||||
type = "Physical Volume Segment";
|
||||
break;
|
||||
default:
|
||||
type = " ";
|
||||
}
|
||||
|
||||
if (type != last_type) {
|
||||
if (*last_type)
|
||||
log_print(" ");
|
||||
log_print("%s Fields", type);
|
||||
}
|
||||
|
||||
log_print("- %s", _fields[f].id);
|
||||
|
||||
last_type = type;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialise report handle
|
||||
*/
|
||||
@@ -1080,6 +1139,8 @@ static int _parse_options(struct report_handle *rh, const char *format)
|
||||
while (*we && *we != ',')
|
||||
we++;
|
||||
if (!_field_match(rh, ws, (size_t) (we - ws))) {
|
||||
_display_fields();
|
||||
log_print(" ");
|
||||
log_error("Unrecognised field: %.*s", (int) (we - ws),
|
||||
ws);
|
||||
return 0;
|
||||
@@ -1324,7 +1385,7 @@ static int _report_headings(void *handle)
|
||||
|
||||
heading = _fields[fp->field_num].heading;
|
||||
if (rh->flags & RH_ALIGNED) {
|
||||
if (lvm_snprintf(buf, sizeof(buf), "%-*.*s",
|
||||
if (dm_snprintf(buf, sizeof(buf), "%-*.*s",
|
||||
fp->width, fp->width, heading) < 0) {
|
||||
log_error("snprintf heading failed");
|
||||
dm_pool_end_object(rh->mem);
|
||||
@@ -1467,7 +1528,7 @@ int report_output(void *handle)
|
||||
strlen(repstr)))
|
||||
goto bad;
|
||||
} else if (field->props->flags & FLD_ALIGN_LEFT) {
|
||||
if (lvm_snprintf(buf, sizeof(buf), "%-*.*s",
|
||||
if (dm_snprintf(buf, sizeof(buf), "%-*.*s",
|
||||
width, width, repstr) < 0) {
|
||||
log_error("snprintf repstr failed");
|
||||
dm_pool_end_object(rh->mem);
|
||||
@@ -1476,7 +1537,7 @@ int report_output(void *handle)
|
||||
if (!dm_pool_grow_object(rh->mem, buf, width))
|
||||
goto bad;
|
||||
} else if (field->props->flags & FLD_ALIGN_RIGHT) {
|
||||
if (lvm_snprintf(buf, sizeof(buf), "%*.*s",
|
||||
if (dm_snprintf(buf, sizeof(buf), "%*.*s",
|
||||
width, width, repstr) < 0) {
|
||||
log_error("snprintf repstr failed");
|
||||
dm_pool_end_object(rh->mem);
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "text_export.h"
|
||||
#include "config.h"
|
||||
#include "activate.h"
|
||||
#include "str_list.h"
|
||||
|
||||
static const char *_snap_name(const struct lv_segment *seg)
|
||||
{
|
||||
@@ -126,6 +127,18 @@ static int _snap_target_present(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int _snap_modules_needed(struct dm_pool *mem,
|
||||
const struct lv_segment *seg,
|
||||
struct list *modules)
|
||||
{
|
||||
if (!str_list_add(mem, modules, "snapshot")) {
|
||||
log_error("snapshot string list allocation failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _snap_destroy(const struct segment_type *segtype)
|
||||
{
|
||||
dm_free((void *)segtype);
|
||||
@@ -139,6 +152,7 @@ static struct segtype_handler _snapshot_ops = {
|
||||
.target_percent = _snap_target_percent,
|
||||
.target_present = _snap_target_present,
|
||||
#endif
|
||||
.modules_needed = _snap_modules_needed,
|
||||
.destroy = _snap_destroy,
|
||||
};
|
||||
|
||||
|
||||
@@ -63,6 +63,18 @@ static int _zero_target_present(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int _zero_modules_needed(struct dm_pool *mem,
|
||||
const struct lv_segment *seg,
|
||||
struct list *modules)
|
||||
{
|
||||
if (!str_list_add(mem, modules, "zero")) {
|
||||
log_error("zero module string list allocation failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _zero_destroy(const struct segment_type *segtype)
|
||||
{
|
||||
dm_free((void *) segtype);
|
||||
@@ -75,6 +87,7 @@ static struct segtype_handler _zero_ops = {
|
||||
.add_target_line = _zero_add_target_line,
|
||||
.target_present = _zero_target_present,
|
||||
#endif
|
||||
.modules_needed = _zero_modules_needed,
|
||||
.destroy = _zero_destroy,
|
||||
};
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ dm_task_set_gid
|
||||
dm_task_set_mode
|
||||
dm_task_suppress_identical_reload
|
||||
dm_task_add_target
|
||||
dm_task_no_flush
|
||||
dm_task_no_open_count
|
||||
dm_task_skip_lockfs
|
||||
dm_task_update_nodes
|
||||
@@ -109,3 +110,6 @@ dm_hash_get_first
|
||||
dm_hash_get_next
|
||||
dm_set_selinux_context
|
||||
dm_task_set_geometry
|
||||
dm_split_lvm_name
|
||||
dm_split_words
|
||||
dm_snprintf
|
||||
|
||||
@@ -23,6 +23,7 @@ SOURCES =\
|
||||
libdm-common.c \
|
||||
libdm-file.c \
|
||||
libdm-deptree.c \
|
||||
libdm-string.c \
|
||||
mm/dbg_malloc.c \
|
||||
mm/pool.c \
|
||||
$(interface)/libdm-iface.c
|
||||
|
||||
@@ -1026,6 +1026,13 @@ int dm_task_set_geometry(struct dm_task *dmt, const char *cylinders, const char
|
||||
return 1;
|
||||
}
|
||||
|
||||
int dm_task_no_flush(struct dm_task *dmt)
|
||||
{
|
||||
dmt->no_flush = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int dm_task_no_open_count(struct dm_task *dmt)
|
||||
{
|
||||
dmt->no_open_count = 1;
|
||||
@@ -1270,6 +1277,8 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
|
||||
|
||||
if (dmt->type == DM_DEVICE_SUSPEND)
|
||||
dmi->flags |= DM_SUSPEND_FLAG;
|
||||
if (dmt->no_flush)
|
||||
dmi->flags |= DM_NOFLUSH_FLAG;
|
||||
if (dmt->read_only)
|
||||
dmi->flags |= DM_READONLY_FLAG;
|
||||
if (dmt->skip_lockfs)
|
||||
@@ -1543,7 +1552,7 @@ static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command,
|
||||
dmi->flags |= DM_SKIP_BDGET_FLAG;
|
||||
|
||||
log_debug("dm %s %s %s%s%s %s%.0d%s%.0d%s"
|
||||
"%s%c%s %.0llu %s [%u]",
|
||||
"%s%c%c%s %.0llu %s [%u]",
|
||||
_cmd_data_v4[dmt->type].name,
|
||||
dmi->name, dmi->uuid, dmt->newname ? " " : "",
|
||||
dmt->newname ? dmt->newname : "",
|
||||
@@ -1554,6 +1563,7 @@ static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command,
|
||||
dmt->major > 0 && dmt->minor == 0 ? "0" : "",
|
||||
dmt->major > 0 ? ") " : "",
|
||||
dmt->no_open_count ? 'N' : 'O',
|
||||
dmt->no_flush ? 'N' : 'F',
|
||||
dmt->skip_lockfs ? "S " : "",
|
||||
dmt->sector, dmt->message ? dmt->message : "",
|
||||
dmi->data_size);
|
||||
|
||||
@@ -52,6 +52,7 @@ struct dm_task {
|
||||
char *message;
|
||||
char *geometry;
|
||||
uint64_t sector;
|
||||
int no_flush;
|
||||
int no_open_count;
|
||||
int skip_lockfs;
|
||||
int suppress_identical_reload;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#define LIB_DEVICE_MAPPER_H
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef linux
|
||||
@@ -150,6 +151,7 @@ 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_flush(struct dm_task *dmt);
|
||||
int dm_task_no_open_count(struct dm_task *dmt);
|
||||
int dm_task_skip_lockfs(struct dm_task *dmt);
|
||||
int dm_task_suppress_identical_reload(struct dm_task *dmt);
|
||||
@@ -582,4 +584,28 @@ struct dm_hash_node *dm_hash_get_next(struct dm_hash_table *t, struct dm_hash_no
|
||||
*********/
|
||||
int dm_set_selinux_context(const char *path, mode_t mode);
|
||||
|
||||
/*********************
|
||||
* string manipulation
|
||||
*********************/
|
||||
|
||||
/*
|
||||
* Break up the name of a mapped device into its constituent
|
||||
* Volume Group, Logical Volume and Layer (if present).
|
||||
*/
|
||||
int dm_split_lvm_name(struct dm_pool *mem, const char *dmname,
|
||||
char **vgname, char **lvname, char **layer);
|
||||
|
||||
/*
|
||||
* Destructively split buffer into NULL-separated words in argv.
|
||||
* Returns number of words.
|
||||
*/
|
||||
int dm_split_words(char *buffer, unsigned max,
|
||||
unsigned ignore_comments, /* Not implemented */
|
||||
char **argv);
|
||||
|
||||
/*
|
||||
* Returns -1 if buffer too small
|
||||
*/
|
||||
int dm_snprintf(char *buf, size_t bufsize, const char *format, ...);
|
||||
|
||||
#endif /* LIB_DEVICE_MAPPER_H */
|
||||
|
||||
@@ -1028,7 +1028,7 @@ int dm_tree_suspend_children(struct dm_tree_node *dnode,
|
||||
continue;
|
||||
|
||||
if (!_info_by_dev(dinfo->major, dinfo->minor, 0, &info) ||
|
||||
!info.exists)
|
||||
!info.exists || info.suspended)
|
||||
continue;
|
||||
|
||||
if (!_suspend_node(name, info.major, info.minor,
|
||||
|
||||
123
libdm/libdm-string.c
Normal file
123
libdm/libdm-string.c
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (C) 2006 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of the device-mapper userspace tools.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
#include "libdevmapper.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
/*
|
||||
* consume characters while they match the predicate function.
|
||||
*/
|
||||
static char *_consume(char *buffer, int (*fn) (int))
|
||||
{
|
||||
while (*buffer && fn(*buffer))
|
||||
buffer++;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static int _isword(int c)
|
||||
{
|
||||
return !isspace(c);
|
||||
}
|
||||
|
||||
/*
|
||||
* Split buffer into NULL-separated words in argv.
|
||||
* Returns number of words.
|
||||
*/
|
||||
int dm_split_words(char *buffer, unsigned max, unsigned ignore_comments,
|
||||
char **argv)
|
||||
{
|
||||
unsigned arg;
|
||||
|
||||
for (arg = 0; arg < max; arg++) {
|
||||
buffer = _consume(buffer, isspace);
|
||||
if (!*buffer)
|
||||
break;
|
||||
|
||||
argv[arg] = buffer;
|
||||
buffer = _consume(buffer, _isword);
|
||||
|
||||
if (*buffer) {
|
||||
*buffer = '\0';
|
||||
buffer++;
|
||||
}
|
||||
}
|
||||
|
||||
return arg;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove hyphen quoting from a component of a name.
|
||||
* NULL-terminates the component and returns start of next component.
|
||||
*/
|
||||
static char *_unquote(char *component)
|
||||
{
|
||||
char *c = component;
|
||||
char *o = c;
|
||||
char *r;
|
||||
|
||||
while (*c) {
|
||||
if (*(c + 1)) {
|
||||
if (*c == '-') {
|
||||
if (*(c + 1) == '-')
|
||||
c++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
*o = *c;
|
||||
o++;
|
||||
c++;
|
||||
}
|
||||
|
||||
r = (*c) ? c + 1 : c;
|
||||
*o = '\0';
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int dm_split_lvm_name(struct dm_pool *mem, const char *dmname,
|
||||
char **vgname, char **lvname, char **layer)
|
||||
{
|
||||
if (!(*vgname = dm_pool_strdup(mem, dmname)))
|
||||
return 0;
|
||||
|
||||
_unquote(*layer = _unquote(*lvname = _unquote(*vgname)));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* On error, up to glibc 2.0.6, snprintf returned -1 if buffer was too small;
|
||||
* From glibc 2.1 it returns number of chars (excl. trailing null) that would
|
||||
* have been written had there been room.
|
||||
*
|
||||
* dm_snprintf reverts to the old behaviour.
|
||||
*/
|
||||
int dm_snprintf(char *buf, size_t bufsize, const char *format, ...)
|
||||
{
|
||||
int n;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
n = vsnprintf(buf, bufsize, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (n < 0 || (n > bufsize - 1))
|
||||
return -1;
|
||||
|
||||
return n;
|
||||
}
|
||||
@@ -77,15 +77,6 @@ void *dm_malloc_aux_debug(size_t s, const char *file, int line)
|
||||
nb->length = s;
|
||||
nb->id = ++_mem_stats.block_serialno;
|
||||
nb->next = 0;
|
||||
nb->prev = _tail;
|
||||
|
||||
/* link to tail of the list */
|
||||
if (!_head)
|
||||
_head = _tail = nb;
|
||||
else {
|
||||
_tail->next = nb;
|
||||
_tail = nb;
|
||||
}
|
||||
|
||||
/* stomp a pretty pattern across the new memory
|
||||
and fill in the boundary bytes */
|
||||
@@ -99,6 +90,16 @@ void *dm_malloc_aux_debug(size_t s, const char *file, int line)
|
||||
*ptr++ = (char) nb->id;
|
||||
}
|
||||
|
||||
nb->prev = _tail;
|
||||
|
||||
/* link to tail of the list */
|
||||
if (!_head)
|
||||
_head = _tail = nb;
|
||||
else {
|
||||
_tail->next = nb;
|
||||
_tail = nb;
|
||||
}
|
||||
|
||||
_mem_stats.blocks_allocated++;
|
||||
if (_mem_stats.blocks_allocated > _mem_stats.blocks_max)
|
||||
_mem_stats.blocks_max = _mem_stats.blocks_allocated;
|
||||
@@ -134,12 +135,6 @@ void dm_free_aux(void *p)
|
||||
|
||||
/* have we freed this before ? */
|
||||
assert(mb->id != 0);
|
||||
mb->id = 0;
|
||||
|
||||
/* stomp a different pattern across the memory */
|
||||
ptr = ((char *) mb) + sizeof(struct memblock);
|
||||
for (i = 0; i < mb->length; i++)
|
||||
*ptr++ = i & 1 ? (char) 0xde : (char) 0xad;
|
||||
|
||||
/* unlink */
|
||||
if (mb->prev)
|
||||
@@ -152,6 +147,13 @@ void dm_free_aux(void *p)
|
||||
else
|
||||
_tail = mb->prev;
|
||||
|
||||
mb->id = 0;
|
||||
|
||||
/* stomp a different pattern across the memory */
|
||||
ptr = ((char *) mb) + sizeof(struct memblock);
|
||||
for (i = 0; i < mb->length; i++)
|
||||
*ptr++ = i & 1 ? (char) 0xde : (char) 0xad;
|
||||
|
||||
assert(_mem_stats.blocks_allocated);
|
||||
_mem_stats.blocks_allocated--;
|
||||
_mem_stats.bytes -= mb->length;
|
||||
|
||||
@@ -17,7 +17,8 @@ top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
MAN5=lvm.conf.5
|
||||
MAN8=lvchange.8 lvcreate.8 lvdisplay.8 lvextend.8 lvm.8 lvmchange.8 \
|
||||
MAN8=lvchange.8 lvconvert.8 lvcreate.8 lvdisplay.8 lvextend.8 lvm.8 \
|
||||
lvmchange.8 \
|
||||
lvmdiskscan.8 lvreduce.8 lvremove.8 lvrename.8 lvresize.8 lvs.8 \
|
||||
lvscan.8 pvchange.8 pvcreate.8 pvdisplay.8 pvmove.8 pvremove.8 \
|
||||
pvresize.8 pvs.8 pvscan.8 vgcfgbackup.8 vgcfgrestore.8 vgchange.8 \
|
||||
|
||||
@@ -4,6 +4,7 @@ clvmd \- cluster LVM daemon
|
||||
.SH SYNOPSIS
|
||||
.B clvmd
|
||||
[\-d] [\-h]
|
||||
[\-R]
|
||||
[\-t <timeout>]
|
||||
[\-V]
|
||||
.SH DESCRIPTION
|
||||
@@ -22,6 +23,11 @@ be so small that commands with many disk updates to do will fail, so you
|
||||
may need to increase this on systems with very large disk farms.
|
||||
The default is 30 seconds.
|
||||
.TP
|
||||
.I \-R
|
||||
Tells all the running clvmd in the cluster to reload their device cache and
|
||||
re-read the lvm configuration file. This command should be run whenever the
|
||||
devices on a cluster system are changed.
|
||||
.TP
|
||||
.I \-V
|
||||
Display the version of the cluster LVM daemon.
|
||||
.SH SEE ALSO
|
||||
|
||||
@@ -13,7 +13,7 @@ dmsetup \- low level logical volume management
|
||||
.I [-f|--force]
|
||||
.br
|
||||
.B dmsetup suspend
|
||||
.I [--nolockfs] device_name
|
||||
.I [--nolockfs] [--noflush] device_name
|
||||
.br
|
||||
.B dmsetup resume
|
||||
.I device_name
|
||||
@@ -213,7 +213,7 @@ Outputs status information for each of the device's targets.
|
||||
With --target, only information relating to the specified target type
|
||||
is displayed.
|
||||
.IP \fBsuspend
|
||||
.I [--nolockfs]
|
||||
.I [--nolockfs] [--noflush]
|
||||
.I device_name
|
||||
.br
|
||||
Suspends a device. Any I/O that has already been mapped by the device
|
||||
@@ -221,6 +221,9 @@ but has not yet completed will be flushed. Any further I/O to that
|
||||
device will be postponed for as long as the device is suspended.
|
||||
If there's a filesystem on the device which supports the operation,
|
||||
an attempt will be made to sync it first unless --nolockfs is specified.
|
||||
Some targets such as recent (October 2006) versions of multipath may support
|
||||
the --noflush option. This lets outstanding I/O that has not yet reached the
|
||||
device to remain unflushed.
|
||||
.IP \fBtable
|
||||
.I [--target target_type]
|
||||
.I [device_name]
|
||||
|
||||
@@ -9,6 +9,7 @@ lvchange \- change attributes of a logical volume
|
||||
[\-C/\-\-contiguous y/n] [\-d/\-\-debug] [\-\-deltag Tag]
|
||||
[\-h/\-?/\-\-help]
|
||||
[\-\-ignorelockingfailure]
|
||||
[\-\-monitor {y|n}]
|
||||
[\-M/\-\-persistent y/n] [\-\-minor minor]
|
||||
[\-P/\-\-partial y/n]
|
||||
[\-p/\-\-permission r/w] [\-r/\-\-readahead ReadAheadSectors]
|
||||
@@ -42,6 +43,14 @@ allocated physical extents are already contiguous.
|
||||
.I \-\-minor minor
|
||||
Set the minor number.
|
||||
.TP
|
||||
.I \-\-monitor y/n
|
||||
Controls whether or not a mirrored logical volume is monitored by
|
||||
dmeventd, if it is installed.
|
||||
If a device used by a monitored mirror reports an I/O error,
|
||||
the failure is handled according to
|
||||
\fBmirror_image_fault_policy\fP and \fBmirror_log_fault_policy\fP
|
||||
set in \fBlvm.conf\fP.
|
||||
.TP
|
||||
.I \-M, \-\-persistent y/n
|
||||
Set to y to make the minor number specified persistent.
|
||||
.TP
|
||||
|
||||
61
man/lvconvert.8
Normal file
61
man/lvconvert.8
Normal file
@@ -0,0 +1,61 @@
|
||||
.TH LVCONVERT 8 "LVM TOOLS" "Red Hat, Inc" \" -*- nroff -*-
|
||||
.SH NAME
|
||||
lvconvert \- convert a logical volume between linear and mirror
|
||||
.SH SYNOPSIS
|
||||
.B lvconvert
|
||||
[\-m/\-\-mirrors Mirrors [\-\-corelog] [\-R/\-\-regionsize MirrorLogRegionSize]]
|
||||
[\-A/\-\-alloc AllocationPolicy]
|
||||
[\-h/\-?/\-\-help]
|
||||
[\-v/\-\-verbose]
|
||||
[\-\-version]
|
||||
LogicalVolume[Path] [PhysicalVolume[Path]...]
|
||||
.SH DESCRIPTION
|
||||
lvconvert will change a linear logical volume to a mirror
|
||||
logical volume or vis versa. It is also used to add and
|
||||
remove disk logs from mirror devices.
|
||||
.SH OPTIONS
|
||||
See \fBlvm\fP for common options.
|
||||
.TP
|
||||
.I \-m, \-\-mirrors Mirrors
|
||||
Specifies the degree of the mirror you wish to create.
|
||||
For example, "-m 1" would convert the original logical
|
||||
volume to a mirror volume with 2-sides; that is, a
|
||||
linear volume plus one copy.
|
||||
.TP
|
||||
.I \-\-corelog
|
||||
This optional argument tells lvconvert to switch the
|
||||
mirror from using a disk-based (persistent) log to
|
||||
an in-memory log. You may only specify this option
|
||||
when the \-\-mirror argument is the same degree of
|
||||
the mirror you are changing.
|
||||
.TP
|
||||
.I \-R, \-\-regionsize MirrorLogRegionSize
|
||||
A mirror is divided into regions of this size (in MB), and the mirror log
|
||||
uses this granularity to track which regions are in sync.
|
||||
.SH Examples
|
||||
"lvconvert -m1 vg00/lvol1"
|
||||
.br
|
||||
converts the linear logical volume "vg00/lvol1" to
|
||||
a mirror logical volume. This command could also
|
||||
be used to convert a two-way mirror with an
|
||||
in-memory log to a two-way mirror with a disk log.
|
||||
|
||||
"lvconvert -m1 --corelog vg00/lvol1"
|
||||
.br
|
||||
converts a two-way mirror with a disk log to a
|
||||
two-way mirror with an in-memory log.
|
||||
|
||||
"lvconvert -m0 vg00/lvol1"
|
||||
.br
|
||||
converts a mirror logical volume to a linear logical
|
||||
volume.
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR lvm (8),
|
||||
.BR vgcreate (8),
|
||||
.BR lvremove (8),
|
||||
.BR lvrename (8),
|
||||
.BR lvextend (8),
|
||||
.BR lvreduce (8),
|
||||
.BR lvdisplay (8),
|
||||
.BR lvscan (8)
|
||||
@@ -8,12 +8,13 @@ lvcreate \- create a logical volume in an existing volume group
|
||||
[\-A/\-\-autobackup y/n] [\-C/\-\-contiguous y/n] [\-d/\-\-debug]
|
||||
[\-h/\-?/\-\-help]
|
||||
[\-i/\-\-stripes Stripes [\-I/\-\-stripesize StripeSize]]
|
||||
{\-l/\-\-extents LogicalExtentsNumber |
|
||||
{\-l/\-\-extents LogicalExtentsNumber[%{VG|FREE}] |
|
||||
\-L/\-\-size LogicalVolumeSize[kKmMgGtT]}
|
||||
[\-M/\-\-persistent y/n] [\-\-minor minor]
|
||||
[\-m/\-\-mirrors Mirrors [\-\-nosync] [\-\-corelog]
|
||||
[\-R/\-\-regionsize MirrorLogRegionSize]]
|
||||
[\-n/\-\-name LogicalVolumeName]
|
||||
[\-p/\-\-permission r/rw] [\-r/\-\-readahead ReadAheadSectors]
|
||||
[-R|--regionsize MirrorLogRegionSize]
|
||||
[\-t/\-\-test]
|
||||
[\-v/\-\-verbose] [\-Z/\-\-zero y/n]
|
||||
VolumeGroupName [PhysicalVolumePath...]
|
||||
@@ -21,7 +22,7 @@ VolumeGroupName [PhysicalVolumePath...]
|
||||
|
||||
.br
|
||||
.B lvcreate
|
||||
{\-l/\-\-extents LogicalExtentsNumber |
|
||||
{\-l/\-\-extents LogicalExtentsNumber[%{VG|FREE}] |
|
||||
\-L/\-\-size LogicalVolumeSize[kKmMgGtT]}
|
||||
[\-c/\-\-chunksize ChunkSize]
|
||||
\-s/\-\-snapshot \-n/\-\-name SnapshotLogicalVolumeName OriginalLogicalVolumePath
|
||||
@@ -62,9 +63,12 @@ StripeSize must be 2^n (n = 2 to 9) for metadata in LVM1 format.
|
||||
For metadata in LVM2 format, the stripe size may be a larger
|
||||
power of 2 but must not exceed the physical extent size.
|
||||
.TP
|
||||
.I \-l, \-\-extents LogicalExtentsNumber
|
||||
.I \-l, \-\-extents LogicalExtentsNumber[%{VG|FREE}]
|
||||
Gives the number of logical extents to allocate for the new
|
||||
logical volume.
|
||||
This can also be expressed as a percentage of the total space
|
||||
in the Volume Group with the suffix %VG or of the remaining free space
|
||||
with the suffix %FREE.
|
||||
.TP
|
||||
.I \-L, \-\-size LogicalVolumeSize[kKmMgGtT]
|
||||
Gives the size to allocate for the new logical volume.
|
||||
@@ -79,6 +83,23 @@ Set the minor number.
|
||||
.I \-M, \-\-persistent y/n
|
||||
Set to y to make the minor number specified persistent.
|
||||
.TP
|
||||
.I \-m, \-\-mirrors Mirrors
|
||||
Creates a mirrored logical volume with "Mirrors" copies. For example,
|
||||
specifying "-m 1" would result in a mirror with two-sides; that is, a
|
||||
linear volume plus one copy.
|
||||
|
||||
Specifying the optional argument "--nosync" will cause the creation
|
||||
of the mirror to skip the initial resynchronization. Any data written
|
||||
afterwards will be mirrored, but the original contents will not be
|
||||
copied. This is useful for skipping a potentially long and resource
|
||||
intensive initial sync.
|
||||
|
||||
Specifying the optional argument "--corelog" will create a mirror with
|
||||
an in-memory log verses a disk-based (persistent) log. While this
|
||||
removes the need for an extra log device and *may* be slightly faster,
|
||||
it requires that the entire mirror be resynchronized upon each
|
||||
instantiation (e.g. a reboot).
|
||||
.TP
|
||||
.I \-n, \-\-name LogicalVolumeName
|
||||
The name for the new logical volume.
|
||||
.br
|
||||
@@ -94,8 +115,8 @@ Default is read and write.
|
||||
Set read ahead sector count of this logical volume to a value between 2 and 120.
|
||||
Ignored by device-mapper.
|
||||
.TP
|
||||
.I \-R \-\-regionsize MirrorLogRegionSize
|
||||
A mirror is divided into regions of this size (in KB), and the mirror log
|
||||
.I \-R, \-\-regionsize MirrorLogRegionSize
|
||||
A mirror is divided into regions of this size (in MB), and the mirror log
|
||||
uses this granularity to track which regions are in sync.
|
||||
.TP
|
||||
.I \-s, \-\-snapshot
|
||||
@@ -122,10 +143,15 @@ Default is yes.
|
||||
Warning: trying to mount an unzeroed logical volume can cause the system to
|
||||
hang.
|
||||
.SH Examples
|
||||
"lvcreate -i 3 -I 8 -L 100 vg00" tries to create a striped logical
|
||||
"lvcreate -i 3 -I 8 -L 100M vg00" tries to create a striped logical
|
||||
volume with 3 stripes, a stripesize of 8KB and a size of 100MB in the volume
|
||||
group named vg00. The logical volume name will be chosen by lvcreate.
|
||||
|
||||
"lvcreate -m1 -L 500M vg00" tries to create a mirror logical volume
|
||||
with 2 sides with a useable size of 500 MiB. This operation would
|
||||
require 3 devices - two for the mirror devices and one for the disk
|
||||
log.
|
||||
|
||||
"lvcreate --size 100m --snapshot --name snap /dev/vg00/lvol1"
|
||||
.br
|
||||
creates a snapshot logical volume named /dev/vg00/snap which has access to the
|
||||
|
||||
@@ -6,7 +6,7 @@ lvextend \- extend the size of a logical volume
|
||||
[\-\-alloc AllocationPolicy]
|
||||
[\-A/\-\-autobackup y/n] [\-d/\-\-debug] [\-h/\-?/\-\-help]
|
||||
[\-i/\-\-stripes Stripes [\-I/\-\-stripesize StripeSize]]
|
||||
{\-l/\-\-extents [+]LogicalExtentsNumber |
|
||||
{\-l/\-\-extents [+]LogicalExtentsNumber[%{VG|LV|FREE}] |
|
||||
\-L/\-\-size [+]LogicalVolumeSize[kKmMgGtT]}
|
||||
[\-t/\-\-test]
|
||||
[\-v/\-\-verbose] LogicalVolumePath [PhysicalVolumePath...]
|
||||
@@ -15,13 +15,20 @@ lvextend allows you to extend the size of a logical volume.
|
||||
Extension of snapshot logical volumes (see
|
||||
.B lvcreate(8)
|
||||
for information to create snapshots) is supported as well.
|
||||
But to change the number of copies in a mirrored logical
|
||||
volume use
|
||||
.BR lvconvert (8).
|
||||
.SH OPTIONS
|
||||
See \fBlvm\fP for common options.
|
||||
.TP
|
||||
.I \-l, \-\-extents [+]LogicalExtentsNumber
|
||||
.I \-l, \-\-extents [+]LogicalExtentsNumber[%{VG|LV|FREE}]
|
||||
Extend or set the logical volume size in units of logical extents.
|
||||
With the + sign the value is added to the actual size
|
||||
of the logical volume and without it, the value is taken as an absolute one.
|
||||
The number can also be expressed as a percentage of the total space
|
||||
in the Volume Group with the suffix %VG or relative to the existing
|
||||
size of the Logical Volume with the suffix %LV or as a percentage of the remaining
|
||||
free space in the Volume Group with the suffix %FREE.
|
||||
.TP
|
||||
.I \-L, \-\-size [+]LogicalVolumeSize[kKmMgGtT]
|
||||
Extend or set the logical volume size in units in units of megabytes.
|
||||
@@ -48,6 +55,7 @@ there are enough free physical extents in it.
|
||||
.SH SEE ALSO
|
||||
.BR lvm (8),
|
||||
.BR lvcreate (8),
|
||||
.BR lvconvert (8),
|
||||
.BR lvreduce (8),
|
||||
.BR lvresize (8),
|
||||
.BR lvchange (8)
|
||||
|
||||
15
man/lvm.8
15
man/lvm.8
@@ -38,7 +38,7 @@ The following commands are built into lvm without links normally
|
||||
being created in the filesystem for them.
|
||||
.TP
|
||||
\fBdumpconfig\fP \(em Display the configuration information after
|
||||
loading \fBlvm.conf\fP (8) and any other configuration files.
|
||||
loading \fBlvm.conf\fP (5) and any other configuration files.
|
||||
.TP
|
||||
\fBformats\fP \(em Display recognised metadata formats.
|
||||
.TP
|
||||
@@ -136,7 +136,7 @@ Characters allowed in tags are: A-Z a-z 0-9 _ + . -
|
||||
Delete the tag \fBtag\fP from a PV, VG or LV, if it's present.
|
||||
.TP
|
||||
\fB--alloc AllocationPolicy\fP
|
||||
The allocation policy to use: \fBcontiguous\fP, \fBnormal\fP, \fBanywhere\fP or \fBinherit\fP.
|
||||
The allocation policy to use: \fBcontiguous\fP, \fBcling\fP, \fBnormal\fP, \fBanywhere\fP or \fBinherit\fP.
|
||||
When a command needs to allocate physical extents from the volume group,
|
||||
the allocation policy controls how they are chosen.
|
||||
Each volume group and logical volume has an allocation policy.
|
||||
@@ -146,15 +146,18 @@ physical volume. The default for a logical volume is \fBinherit\fP
|
||||
which applies the same policy as for the volume group. These policies can
|
||||
be changed using \fBlvchange\fP (8) and \fBvgchange\fP (8) or over-ridden
|
||||
on the command line of any command that performs allocation.
|
||||
The \fBcontiguous\fP policy requires that new extents are adjacent to
|
||||
existing extents. If there are sufficient free extents to satisfy
|
||||
The \fBcontiguous\fP policy requires that new extents be placed adjacent
|
||||
to existing extents.
|
||||
The \fBcling\fP policy places new extents on the same physical
|
||||
volume as existing extents in the same stripe of the Logical Volume.
|
||||
If there are sufficient free extents to satisfy
|
||||
an allocation request but \fBnormal\fP doesn't use them,
|
||||
\fBanywhere\fP will - even if that reduces performance by
|
||||
placing two stripes on the same physical volume.
|
||||
.IP
|
||||
N.B. The policies described above are not implemented fully yet.
|
||||
In particular, \fBcontiguous\fP does not place new extents adjacent to existing
|
||||
extents and \fBanywhere\fP is not implemented at all.
|
||||
In particular, contiguous free space cannot be broken up to
|
||||
satisfy allocation attempts.
|
||||
.SH ENVIRONMENT VARIABLES
|
||||
.TP
|
||||
\fBLVM_SYSTEM_DIR\fP
|
||||
|
||||
@@ -252,7 +252,7 @@ if \fBlocking_type\fP is set to 1. The default is \fB/var/lock/lvm\fP.
|
||||
.IP
|
||||
\fBlocking_library\fP \(em The name of the external locking
|
||||
library to load if \fBlocking_type\fP is set to 2.
|
||||
The default is \fBlvm2_locking.so\fP. If you need to write
|
||||
The default is \fBliblvm2clusterlock.so\fP. If you need to write
|
||||
such a library, look at the lib/locking source code directory.
|
||||
.TP
|
||||
\fBtags\fP \(em Host tag settings
|
||||
|
||||
@@ -4,7 +4,8 @@ lvreduce \- reduce the size of a logical volume
|
||||
.SH SYNOPSIS
|
||||
.B lvreduce
|
||||
[\-A/\-\-autobackup y/n] [\-d/\-\-debug] [\-f/\-\-force]
|
||||
[\-h/\-?/\-\-help] {\-l/\-\-extents [\-]LogicalExtentsNumber |
|
||||
[\-h/\-?/\-\-help]
|
||||
{\-l/\-\-extents [\-]LogicalExtentsNumber[%{VG|LV|FREE}] |
|
||||
\-L/\-\-size [\-]LogicalVolumeSize[kKmMgGtT]}
|
||||
[\-t/\-\-test]
|
||||
[\-v/\-\-verbose] LogicalVolume[Path]
|
||||
@@ -21,21 +22,29 @@ running lvreduce so that the extents that are to be removed are not in use.
|
||||
Shrinking snapshot logical volumes (see
|
||||
.B lvcreate(8)
|
||||
for information to create snapshots) is supported as well.
|
||||
But to change the number of copies in a mirrored logical
|
||||
volume use
|
||||
.B lvconvert (8).
|
||||
.br
|
||||
Sizes will be rounded if necessary - for example, the volume size must
|
||||
be an exact number of extents and the size of a striped segment must
|
||||
be a multiple of the number of stripes.
|
||||
.br
|
||||
.SH OPTIONS
|
||||
See \fBlvm\fP for common options.
|
||||
.TP
|
||||
.I \-f, \-\-force
|
||||
Force size reduction without any question.
|
||||
.TP
|
||||
.I \-l, \-\-extents [\-]LogicalExtentsNumber
|
||||
.I \-l, \-\-extents [\-]LogicalExtentsNumber[%{VG|LV|FREE}]
|
||||
Reduce or set the logical volume size in units of logical extents.
|
||||
With the - sign the value will be subtracted from
|
||||
the logical volume's actual size and without it the will be taken as
|
||||
an absolute size.
|
||||
The number can also be expressed as a percentage of the total space
|
||||
in the Volume Group with the suffix %VG or relative to the existing
|
||||
size of the Logical Volume with the suffix %LV or as a percentage of the remaining
|
||||
free space in the Volume Group with the suffix %FREE.
|
||||
.TP
|
||||
.I \-L, \-\-size [\-]LogicalVolumeSize[kKmMgGtT]
|
||||
Reduce or set the logical volume size in units of megabyte by default.
|
||||
@@ -49,6 +58,7 @@ an absolute size.
|
||||
in volume group vg00 by 3 logical extents.
|
||||
.SH SEE ALSO
|
||||
.BR lvchange (8),
|
||||
.BR lvconvert (8),
|
||||
.BR lvcreate (8),
|
||||
.BR lvextend (8),
|
||||
.BR lvm (8),
|
||||
|
||||
@@ -6,7 +6,7 @@ lvresize \- resize a logical volume
|
||||
[\-\-alloc AllocationPolicy]
|
||||
[\-A/\-\-autobackup y/n] [\-d/\-\-debug] [\-h/\-?/\-\-help]
|
||||
[\-i/\-\-stripes Stripes [\-I/\-\-stripesize StripeSize]]
|
||||
{\-l/\-\-extents [+]LogicalExtentsNumber |
|
||||
{\-l/\-\-extents [+]LogicalExtentsNumber[%{VG|LV|FREE}] |
|
||||
\-L/\-\-size [+]LogicalVolumeSize[kKmMgGtT]}
|
||||
[\-t/\-\-test]
|
||||
[\-v/\-\-verbose] LogicalVolumePath [PhysicalVolumePath...]
|
||||
@@ -19,13 +19,20 @@ shrunk first so that the extents that are to be removed are not in use.
|
||||
Resizing snapshot logical volumes (see
|
||||
.B lvcreate(8)
|
||||
for information about creating snapshots) is supported as well.
|
||||
But to change the number of copies in a mirrored logical
|
||||
volume use
|
||||
.BR lvconvert (8).
|
||||
.SH OPTIONS
|
||||
See \fBlvm\fP for common options.
|
||||
.TP
|
||||
.I \-l, \-\-extents [+/-]LogicalExtentsNumber
|
||||
.I \-l, \-\-extents [+/-]LogicalExtentsNumber[%{VG|LV|FREE}]
|
||||
Change or set the logical volume size in units of logical extents.
|
||||
With the + or - sign the value is added to or subtracted from the actual size
|
||||
of the logical volume and without it, the value is taken as an absolute one.
|
||||
The number can also be expressed as a percentage of the total space
|
||||
in the Volume Group with the suffix %VG or relative to the existing
|
||||
size of the Logical Volume with the suffix %LV or as a percentage of the remaining
|
||||
free space in the Volume Group with the suffix %FREE.
|
||||
.TP
|
||||
.I \-L, \-\-size [+/-]LogicalVolumeSize[kKmMgGtT]
|
||||
Change or set the logical volume size in units of megabytes.
|
||||
@@ -49,6 +56,7 @@ must use a single value throughout.
|
||||
StripeSize must be 2^n (n = 2 to 9)
|
||||
.SH SEE ALSO
|
||||
.BR lvm (8),
|
||||
.BR lvconvert (8),
|
||||
.BR lvcreate (8),
|
||||
.BR lvreduce (8),
|
||||
.BR lvchange (8)
|
||||
|
||||
@@ -9,6 +9,7 @@ vgchange \- change attributes of a volume group
|
||||
.IR AllocationPolicy ]
|
||||
.RB [ \-A | \-\-autobackup " {" y | n }]
|
||||
.RB [ \-a | \-\-available " [e|l] {" y | n }]
|
||||
.RB [ \-\-monitor " {" y | n }]
|
||||
.RB [ \-d | \-\-debug]
|
||||
.RB [ \-\-deltag
|
||||
.IR Tag ]
|
||||
@@ -16,6 +17,8 @@ vgchange \- change attributes of a volume group
|
||||
.RB [ \-\-ignorelockingfailure]
|
||||
.RB [ \-l | \-\-logicalvolume
|
||||
.IR MaxLogicalVolumes ]
|
||||
.RB [ -p | \-\-maxphysicalvolumes
|
||||
.IR MaxPhysicalVolumes ]
|
||||
.RB [ \-P | \-\-partial]
|
||||
.RB [ \-s | \-\-physicalextentsize
|
||||
.IR PhysicalExtentSize [ \fBkKmMgGtT\fR ]]
|
||||
@@ -57,10 +60,33 @@ on the local node.
|
||||
Logical volumes with single-host snapshots are always activated
|
||||
exclusively because they can only be used on one node at once.
|
||||
.TP
|
||||
.BR \-\-monitor " " { y | n }
|
||||
Controls whether or not a mirrored logical volume is monitored by
|
||||
dmeventd, if it is installed.
|
||||
If a device used by a monitored mirror reports an I/O error,
|
||||
the failure is handled according to
|
||||
.BR mirror_image_fault_policy
|
||||
and
|
||||
.BR mirror_log_fault_policy
|
||||
set in
|
||||
.BR lvm.conf (5).
|
||||
.TP
|
||||
.BR \-l ", " \-\-logicalvolume " " \fIMaxLogicalVolumes\fR
|
||||
Changes the maximum logical volume number of an existing inactive
|
||||
volume group.
|
||||
.TP
|
||||
.BR \-p ", " \-\-maxphysicalvolumes " " \fIMaxPhysicalVolumes\fR
|
||||
Changes the maximum number of physical volumes that can belong
|
||||
to this volume group.
|
||||
For volume groups with metadata in lvm1 format, the limit is 255.
|
||||
If the metadata uses lvm2 format, the value 0
|
||||
removes this restriction: there is then no limit.
|
||||
If you have a large number of physical volumes in
|
||||
a volume group with metadata in lvm2 format,
|
||||
for tool performance reasons, you should consider
|
||||
some use of \fB--metadatacopies 0\fP
|
||||
as described in \fBpvcreate(8)\fP.
|
||||
.TP
|
||||
.BR \-s ", " \-\-physicalextentsize " " \fIPhysicalExtentSize\fR[\fBkKmMgGtT\fR]
|
||||
Changes the physical extent size on physical volumes of this volume group.
|
||||
A size suffix (k for kilobytes up to t for terabytes) is optional, megabytes
|
||||
|
||||
@@ -11,7 +11,7 @@ vgscan \- scan all disks for volume groups and rebuild caches
|
||||
.SH DESCRIPTION
|
||||
vgscan scans all SCSI, (E)IDE disks, multiple devices and a bunch
|
||||
of other disk devices in the system looking for LVM physical volumes
|
||||
and volume groups. Define a filter in \fBlvm.conf\fP(8) to restrict
|
||||
and volume groups. Define a filter in \fBlvm.conf\fP(5) to restrict
|
||||
the scan to avoid a CD ROM, for example.
|
||||
.LP
|
||||
In LVM2, vgscans take place automatically; but you might still need to
|
||||
|
||||
@@ -93,6 +93,24 @@ stop()
|
||||
return $rtrn
|
||||
}
|
||||
|
||||
wait_for_finish()
|
||||
{
|
||||
count=0
|
||||
|
||||
while [ "$count" -le 10 -a -n "`pidof clvmd`" ]
|
||||
do
|
||||
sleep 1
|
||||
count=$((count + 1))
|
||||
done
|
||||
|
||||
if [ `pidof clvmd` ]
|
||||
then
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
rtrn=1
|
||||
|
||||
# See how we were called.
|
||||
@@ -112,6 +130,7 @@ case "$1" in
|
||||
restart)
|
||||
if stop
|
||||
then
|
||||
wait_for_finish
|
||||
start
|
||||
fi
|
||||
rtrn=$?
|
||||
|
||||
118
scripts/lvm_dump.sh
Executable file
118
scripts/lvm_dump.sh
Executable file
@@ -0,0 +1,118 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# lvm_dump: This script is used to collect pertinent information for
|
||||
# the debugging of lvm issues.
|
||||
#
|
||||
|
||||
function usage {
|
||||
echo "$0 [options]"
|
||||
echo " -h print this message"
|
||||
echo " -a advanced collection - warning: if lvm is already hung,"
|
||||
echo " then this script may hang as well if -a is used"
|
||||
echo " -m gather LVM metadata from the PVs"
|
||||
echo " -d dump directory to place data in (default=/tmp/lvm_dump.\$\$)"
|
||||
echo " -c if running clvmd, gather cluster data as well"
|
||||
echo ""
|
||||
|
||||
exit 1
|
||||
}
|
||||
|
||||
advanced=0
|
||||
clustered=0
|
||||
metadata=0
|
||||
while getopts :acd:hm opt; do
|
||||
case $opt in
|
||||
a) advanced=1 ;;
|
||||
c) clustered=1 ;;
|
||||
d) lvm_dir=$OPTARG ;;
|
||||
h) usage ;;
|
||||
m) metadata=1 ;;
|
||||
:) echo "$0: $OPTARG requires a value:"; usage ;;
|
||||
\?) echo "$0: unknown option $OPTARG"; usage ;;
|
||||
*) usage ;;
|
||||
esac
|
||||
done
|
||||
|
||||
dir=`mktemp -d -p /tmp lvm_dump.XXXXXX` || exit 2
|
||||
lvm_dir="$dir/lvm_dump"
|
||||
|
||||
echo " "
|
||||
echo "Creating dump directory: $lvm_dir"
|
||||
echo " "
|
||||
|
||||
mkdir -p $lvm_dir || exit 3
|
||||
|
||||
if (( $advanced )); then
|
||||
echo "Gathering LVM volume info..."
|
||||
|
||||
echo " vgscan..."
|
||||
vgscan -vvvv > $lvm_dir/vgscan 2>&1
|
||||
|
||||
echo " pvscan..."
|
||||
pvscan -v >> $lvm_dir/pvscan 2>/dev/null
|
||||
|
||||
echo " lvs..."
|
||||
lvs -a -o +devices >> $lvm_dir/lvs 2>/dev/null
|
||||
|
||||
echo " pvs..."
|
||||
pvs -a -v > $lvm_dir/pvs 2>/dev/null
|
||||
|
||||
echo " vgs..."
|
||||
vgs -v > $lvm_dir/vgs 2>/dev/null
|
||||
fi
|
||||
|
||||
if (( $clustered )); then
|
||||
echo "Gathering cluster info..."
|
||||
echo "STATUS: " > $lvm_dir/cluster_info
|
||||
echo "----------------------------------" >> $lvm_dir/cluster_info
|
||||
cman_tool status >> $lvm_dir/cluster_info
|
||||
echo " " >> $lvm_dir/lvm_info
|
||||
|
||||
echo "SERVICES: " >> $lvm_dir/cluster_info
|
||||
echo "----------------------------------" >> $lvm_dir/cluster_info
|
||||
cman_tool services >> $lvm_dir/cluster_info
|
||||
echo " " >> $lvm_dir/lvm_info
|
||||
fi
|
||||
|
||||
echo "Gathering LVM & device-mapper version info..."
|
||||
echo "LVM VERSION:" > $lvm_dir/versions
|
||||
lvs --version >> $lvm_dir/versions
|
||||
echo "DEVICE MAPPER VERSION:" >> $lvm_dir/versions
|
||||
dmsetup --version >> $lvm_dir/versions
|
||||
|
||||
echo "Gathering dmsetup info..."
|
||||
dmsetup info -c > $lvm_dir/dmsetup_info
|
||||
dmsetup table > $lvm_dir/dmsetup_table
|
||||
dmsetup status > $lvm_dir/dmsetup_status
|
||||
|
||||
echo "Gathering process info..."
|
||||
ps alx > $lvm_dir/ps_info
|
||||
|
||||
echo "Gathering console messages..."
|
||||
tail -n 75 /var/log/messages > $lvm_dir/messages
|
||||
|
||||
echo "Gathering /etc/lvm info..."
|
||||
cp -a /etc/lvm $lvm_dir/lvm
|
||||
|
||||
echo "Gathering /dev listing..."
|
||||
ls -la /dev > $lvm_dir/dev_listing
|
||||
|
||||
if (( $metadata )); then
|
||||
echo "Gathering LVM metadata from Physical Volumes..."
|
||||
|
||||
mkdir -p $lvm_dir/metadata
|
||||
|
||||
for pv in `pvs --noheadings -o name`
|
||||
do
|
||||
echo " $pv"
|
||||
name=`basename $pv`
|
||||
dd if=$pv of=$lvm_dir/metadata/$name bs=512 count=`pvs --noheadings --nosuffix --units s -o pe_start $pv | tr -d \ `
|
||||
done 2>/dev/null
|
||||
fi
|
||||
|
||||
lvm_dump=$lvm_dir.tgz
|
||||
echo "Creating tarball $lvm_dump..."
|
||||
tar czf $lvm_dump $lvm_dir 2>/dev/null
|
||||
|
||||
exit 0
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
|
||||
# Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of the lvm2-cluster package.
|
||||
#
|
||||
@@ -21,8 +21,9 @@ function usage
|
||||
echo "usage: $0 <command>"
|
||||
echo ""
|
||||
echo "Commands:"
|
||||
echo "Enable clvm: --enable-cluster --lockinglibdir <dir> [--lockinglib <lib>]"
|
||||
echo "Enable clvm: --enable-cluster [--lockinglibdir <dir>] [--lockinglib <lib>]"
|
||||
echo "Disable clvm: --disable-cluster"
|
||||
echo "Set locking library: --lockinglibdir <dir> [--lockinglib <lib>]"
|
||||
echo ""
|
||||
echo "Global options:"
|
||||
echo "Config file location: --file <configfile>"
|
||||
@@ -86,14 +87,13 @@ function validate_args
|
||||
exit 10
|
||||
fi
|
||||
|
||||
if [ -z "$LOCKING_TYPE" ]; then
|
||||
if [ -z "$LOCKING_TYPE" ] && [ -z "$LOCKINGLIBDIR" ]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$LOCKING_TYPE" == "2" ]; then
|
||||
if [ -n "$LOCKINGLIBDIR" ]; then
|
||||
|
||||
[ -z "$LOCKINGLIBDIR" ] && usage && exit 1
|
||||
[ -z "$LOCKINGLIB" ] && LOCKINGLIB="liblvm2clusterlock.so"
|
||||
|
||||
if [ "${LOCKINGLIBDIR:0:1}" != "/" ]
|
||||
@@ -109,6 +109,10 @@ function validate_args
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
if [ "$LOCKING_TYPE" = "1" ] && [ -n "$LOCKINGLIBDIR" -o -n "$LOCKINGLIB" ]; then
|
||||
echo "Superfluous locking lib parameter, ignoring"
|
||||
fi
|
||||
}
|
||||
|
||||
umask 0077
|
||||
@@ -153,11 +157,19 @@ then
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$LOCKING_TYPE" = "2" ] && [ -z "$LOCKINGLIBDIR" ] && [ "$have_dir" = "1" ]; then
|
||||
echo "no library_dir specified in $CONFIGFILE"
|
||||
exit 16
|
||||
fi
|
||||
|
||||
# So if we don't have "global {" we need to create one and
|
||||
# populate it
|
||||
|
||||
if [ "$have_global" = "1" ]
|
||||
then
|
||||
if [ -z "$LOCKING_TYPE" ]; then
|
||||
LOCKING_TYPE=1
|
||||
fi
|
||||
if [ "$LOCKING_TYPE" = "2" ]; then
|
||||
cat $CONFIGFILE - <<EOF > $TMPFILE
|
||||
global {
|
||||
@@ -180,14 +192,16 @@ else
|
||||
# locking entries as appropriate
|
||||
#
|
||||
|
||||
if [ "$have_type" = "0" ]
|
||||
then
|
||||
SEDCMD=" s/^[[:blank:]]*locking_type[[:blank:]]*=.*/\ \ \ \ locking_type = $LOCKING_TYPE/g"
|
||||
else
|
||||
SEDCMD=" /global[[:blank:]]*{/a\ \ \ \ locking_type = $LOCKING_TYPE"
|
||||
if [ -n "$LOCKING_TYPE" ]; then
|
||||
if [ "$have_type" = "0" ]
|
||||
then
|
||||
SEDCMD=" s/^[[:blank:]]*locking_type[[:blank:]]*=.*/\ \ \ \ locking_type = $LOCKING_TYPE/g"
|
||||
else
|
||||
SEDCMD=" /global[[:blank:]]*{/a\ \ \ \ locking_type = $LOCKING_TYPE"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$LOCKING_TYPE" = "2" ]; then
|
||||
if [ -n "$LOCKINGLIBDIR" ]; then
|
||||
if [ "$have_dir" = "0" ]
|
||||
then
|
||||
SEDCMD="${SEDCMD}\ns'^[[:blank:]]*library_dir[[:blank:]]*=.*'\ \ \ \ library_dir = \"$LOCKINGLIBDIR\"'g"
|
||||
@@ -201,7 +215,9 @@ else
|
||||
else
|
||||
SEDCMD="${SEDCMD}\n/global[[:blank:]]*{/a\ \ \ \ locking_library = \"$LOCKINGLIB\""
|
||||
fi
|
||||
else
|
||||
fi
|
||||
|
||||
if [ "$LOCKING_TYPE" = "1" ]; then
|
||||
# if we're not using cluster locking, remove the library dir and locking library name
|
||||
if [ "$have_dir" = "0" ]
|
||||
then
|
||||
|
||||
@@ -80,7 +80,9 @@ endif
|
||||
|
||||
LVMLIBS = -llvm
|
||||
|
||||
CLEAN_TARGETS = liblvm2cmd.so liblvm2cmd.a lvm lvm.o lvm.static lvm.cflow lvm.xref lvm.tree lvm.rxref lvm.rtree
|
||||
CLEAN_TARGETS = liblvm2cmd.so liblvm2cmd.a liblvm2cmd-static.a lvm lvm.o \
|
||||
lvm2cmd.o lvm2cmd-static.o lvm2cmdlib.o lvm.static \
|
||||
lvm.cflow lvm.xref lvm.tree lvm.rxref lvm.rtree
|
||||
|
||||
ifeq ("@CMDLIB@", "yes")
|
||||
TARGETS += liblvm2cmd.so
|
||||
@@ -104,9 +106,13 @@ lvm.static: $(OBJECTS) lvm-static.o $(top_srcdir)/lib/liblvm.a
|
||||
$(CC) -o $@ $(OBJECTS) lvm-static.o -static $(LDFLAGS) $(LVMLIBS) \
|
||||
$(LIBS) -rdynamic
|
||||
|
||||
liblvm2cmd.a: $(top_srcdir)/lib/liblvm.a $(OBJECTS)
|
||||
liblvm2cmd.a: $(top_srcdir)/lib/liblvm.a $(OBJECTS) lvmcmdlib.o lvm2cmd.o
|
||||
cat $(top_srcdir)/lib/liblvm.a > $@
|
||||
$(AR) rs $@ $(OBJECTS)
|
||||
$(AR) rs $@ $(OBJECTS) lvmcmdlib.o lvm2cmd.o
|
||||
|
||||
liblvm2cmd-static.a: $(top_srcdir)/lib/liblvm.a $(OBJECTS) lvmcmdlib.o lvm2cmd-static.o
|
||||
cat $(top_srcdir)/lib/liblvm.a > $@
|
||||
$(AR) rs $@ $(OBJECTS) lvmcmdlib.o lvm2cmd-static.o
|
||||
|
||||
liblvm2cmd.so: liblvm2cmd.a $(LDDEPS)
|
||||
|
||||
@@ -141,8 +147,8 @@ install_cmdlib_dynamic: liblvm2cmd.so
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 444 lvm2cmd.h \
|
||||
$(includedir)/lvm2cmd.h
|
||||
|
||||
install_cmdlib_static: liblvm2cmd.a
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) liblvm2cmd.a \
|
||||
install_cmdlib_static: liblvm2cmd-static.a
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) liblvm2cmd-static.a \
|
||||
$(libdir)/liblvm2cmd.a.$(LIB_VERSION)
|
||||
$(LN_S) -f liblvm2cmd.a.$(LIB_VERSION) $(libdir)/liblvm2cmd.a
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 444 lvm2cmd.h \
|
||||
|
||||
@@ -84,7 +84,7 @@ arg(interval_ARG, 'i', "interval", int_arg)
|
||||
arg(iop_version_ARG, 'i', "iop_version", NULL)
|
||||
arg(logicalvolume_ARG, 'l', "logicalvolume", int_arg)
|
||||
arg(maxlogicalvolumes_ARG, 'l', "maxlogicalvolumes", int_arg)
|
||||
arg(extents_ARG, 'l', "extents", int_arg_with_sign)
|
||||
arg(extents_ARG, 'l', "extents", int_arg_with_sign_and_percent)
|
||||
arg(lvmpartition_ARG, 'l', "lvmpartition", NULL)
|
||||
arg(list_ARG, 'l', "list", NULL)
|
||||
arg(size_ARG, 'L', "size", size_mb_arg)
|
||||
|
||||
@@ -83,6 +83,7 @@ xx(lvconvert,
|
||||
"Change logical volume layout",
|
||||
"lvconvert "
|
||||
"[-m|--mirrors Mirrors [--corelog]]\n"
|
||||
"\t[-R|--regionsize MirrorLogRegionSize]\n"
|
||||
"\t[--alloc AllocationPolicy]\n"
|
||||
"\t[-d|--debug]\n"
|
||||
"\t[-h|-?|--help]\n"
|
||||
@@ -100,7 +101,7 @@ xx(lvconvert,
|
||||
"\t[--version]" "\n"
|
||||
"\tOriginalLogicalVolume[Path] SnapshotLogicalVolume[Path]\n",
|
||||
|
||||
alloc_ARG, chunksize_ARG, mirrors_ARG, corelog_ARG,
|
||||
alloc_ARG, chunksize_ARG, mirrors_ARG, corelog_ARG, regionsize_ARG,
|
||||
snapshot_ARG, test_ARG, zero_ARG)
|
||||
|
||||
xx(lvcreate,
|
||||
@@ -137,7 +138,7 @@ xx(lvcreate,
|
||||
"\t[-d|--debug]\n"
|
||||
"\t[-h|-?|--help]\n"
|
||||
"\t[-i|--stripes Stripes [-I|--stripesize StripeSize]]\n"
|
||||
"\t{-l|--extents LogicalExtentsNumber |\n"
|
||||
"\t{-l|--extents LogicalExtentsNumber[%{VG|LV|FREE}] |\n"
|
||||
"\t -L|--size LogicalVolumeSize[kKmMgGtT]}\n"
|
||||
"\t[-M|--persistent {y|n}] [--major major] [--minor minor]\n"
|
||||
"\t[-n|--name LogicalVolumeName]\n"
|
||||
@@ -202,7 +203,7 @@ xx(lvextend,
|
||||
"\t[-d|--debug]\n"
|
||||
"\t[-h|--help]\n"
|
||||
"\t[-i|--stripes Stripes [-I|--stripesize StripeSize]]\n"
|
||||
"\t{-l|--extents [+]LogicalExtentsNumber |\n"
|
||||
"\t{-l|--extents [+]LogicalExtentsNumber[%{VG|FREE}] |\n"
|
||||
"\t -L|--size [+]LogicalVolumeSize[kKmMgGtT]}\n"
|
||||
"\t[-m|--mirrors Mirrors]\n"
|
||||
"\t[-n|--nofsck]\n"
|
||||
@@ -267,7 +268,7 @@ xx(lvreduce,
|
||||
"\t[-d|--debug]\n"
|
||||
"\t[-f|--force]\n"
|
||||
"\t[-h|--help]\n"
|
||||
"\t{-l|--extents [-]LogicalExtentsNumber |\n"
|
||||
"\t{-l|--extents [-]LogicalExtentsNumber[%{VG|LV|FREE}] |\n"
|
||||
"\t -L|--size [-]LogicalVolumeSize[kKmMgGtT]}\n"
|
||||
"\t[-n|--nofsck]\n"
|
||||
"\t[-r|--resizefs]\n"
|
||||
@@ -315,7 +316,7 @@ xx(lvresize,
|
||||
"\t[-d|--debug]\n"
|
||||
"\t[-h|--help]\n"
|
||||
"\t[-i|--stripes Stripes [-I|--stripesize StripeSize]]\n"
|
||||
"\t{-l|--extents [+|-]LogicalExtentsNumber |\n"
|
||||
"\t{-l|--extents [+|-]LogicalExtentsNumber[%{VG|LV|FREE}] |\n"
|
||||
"\t -L|--size [+|-]LogicalVolumeSize[kKmMgGtT]}\n"
|
||||
"\t[-n|--nofsck]\n"
|
||||
"\t[-r|--resizefs]\n"
|
||||
@@ -607,6 +608,7 @@ xx(vgchange,
|
||||
"\t -c|--clustered {y|n} |" "\n"
|
||||
"\t -x|--resizeable {y|n} |" "\n"
|
||||
"\t -l|--logicalvolume MaxLogicalVolumes |" "\n"
|
||||
"\t -p|--maxphysicalvolumes MaxPhysicalVolumes |" "\n"
|
||||
"\t -s|--physicalextentsize PhysicalExtentSize[kKmMgGtT] |" "\n"
|
||||
"\t --addtag Tag |\n"
|
||||
"\t --deltag Tag}\n"
|
||||
@@ -614,8 +616,8 @@ xx(vgchange,
|
||||
|
||||
addtag_ARG, alloc_ARG, allocation_ARG, autobackup_ARG, available_ARG,
|
||||
clustered_ARG, deltag_ARG, ignorelockingfailure_ARG, logicalvolume_ARG,
|
||||
monitor_ARG, partial_ARG, physicalextentsize_ARG, resizeable_ARG,
|
||||
resizable_ARG, test_ARG, uuid_ARG)
|
||||
maxphysicalvolumes_ARG, monitor_ARG, partial_ARG, physicalextentsize_ARG,
|
||||
resizeable_ARG, resizable_ARG, test_ARG, uuid_ARG)
|
||||
|
||||
xx(vgck,
|
||||
"Check the consistency of volume group(s)",
|
||||
|
||||
279
tools/dmsetup.c
279
tools/dmsetup.c
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2005 NEC Corperation
|
||||
*
|
||||
* This file is part of the device-mapper userspace tools.
|
||||
@@ -38,6 +38,16 @@
|
||||
#include <locale.h>
|
||||
#include <langinfo.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
/* FIXME Unused so far */
|
||||
#undef HAVE_SYS_STATVFS_H
|
||||
|
||||
#ifdef HAVE_SYS_STATVFS_H
|
||||
# include <sys/statvfs.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_IOCTL_H
|
||||
# include <sys/ioctl.h>
|
||||
#endif
|
||||
@@ -78,6 +88,11 @@ extern char *optarg;
|
||||
|
||||
#define LINE_SIZE 4096
|
||||
#define ARGS_MAX 256
|
||||
#define LOOP_TABLE_SIZE (PATH_MAX + 255)
|
||||
|
||||
/* FIXME Should be elsewhere */
|
||||
#define SECTOR_SHIFT 9L
|
||||
#define DEV_PATH "/dev/"
|
||||
|
||||
#define err(msg, x...) fprintf(stderr, msg "\n", ##x)
|
||||
|
||||
@@ -93,6 +108,7 @@ enum {
|
||||
MAJOR_ARG,
|
||||
MINOR_ARG,
|
||||
MODE_ARG,
|
||||
NOFLUSH_ARG,
|
||||
NOHEADINGS_ARG,
|
||||
NOLOCKFS_ARG,
|
||||
NOOPENCOUNT_ARG,
|
||||
@@ -180,7 +196,7 @@ static int _parse_file(struct dm_task *dmt, const char *file)
|
||||
|
||||
#ifndef HAVE_GETLINE
|
||||
buffer_size = LINE_SIZE;
|
||||
if (!(buffer = malloc(buffer_size))) {
|
||||
if (!(buffer = dm_malloc(buffer_size))) {
|
||||
err("Failed to malloc line buffer.");
|
||||
return 0;
|
||||
}
|
||||
@@ -195,7 +211,7 @@ static int _parse_file(struct dm_task *dmt, const char *file)
|
||||
r = 1;
|
||||
|
||||
out:
|
||||
free(buffer);
|
||||
dm_free(buffer);
|
||||
if (file)
|
||||
fclose(fp);
|
||||
return r;
|
||||
@@ -512,7 +528,7 @@ static int _message(int argc, char **argv, void *data __attribute((unused)))
|
||||
for (i = 0; i < argc; i++)
|
||||
sz += strlen(argv[i]) + 1;
|
||||
|
||||
str = malloc(sz);
|
||||
str = dm_malloc(sz);
|
||||
memset(str, 0, sz);
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
@@ -524,7 +540,7 @@ static int _message(int argc, char **argv, void *data __attribute((unused)))
|
||||
if (!dm_task_set_message(dmt, str))
|
||||
goto out;
|
||||
|
||||
free(str);
|
||||
dm_free(str);
|
||||
|
||||
if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
|
||||
goto out;
|
||||
@@ -603,6 +619,9 @@ static int _simple(int task, const char *name, uint32_t event_nr, int display)
|
||||
if (event_nr && !dm_task_set_event_nr(dmt, event_nr))
|
||||
goto out;
|
||||
|
||||
if (_switches[NOFLUSH_ARG] && !dm_task_no_flush(dmt))
|
||||
goto out;
|
||||
|
||||
if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
|
||||
goto out;
|
||||
|
||||
@@ -744,28 +763,28 @@ static int _error_device(int argc __attribute((unused)), char **argv __attribute
|
||||
return 0;
|
||||
|
||||
if (!_set_task_device(dmt, name, 0))
|
||||
goto err;
|
||||
goto error;
|
||||
|
||||
if (!dm_task_add_target(dmt, 0, size, "error", ""))
|
||||
goto err;
|
||||
goto error;
|
||||
|
||||
if (_switches[READ_ONLY] && !dm_task_set_ro(dmt))
|
||||
goto err;
|
||||
goto error;
|
||||
|
||||
if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
|
||||
goto err;
|
||||
goto error;
|
||||
|
||||
if (!dm_task_run(dmt))
|
||||
goto err;
|
||||
goto error;
|
||||
|
||||
if (!_simple(DM_DEVICE_RESUME, name, 0, 0)) {
|
||||
_simple(DM_DEVICE_CLEAR, name, 0, 0);
|
||||
goto err;
|
||||
goto error;
|
||||
}
|
||||
|
||||
r = 1;
|
||||
|
||||
err:
|
||||
error:
|
||||
dm_task_destroy(dmt);
|
||||
return r;
|
||||
}
|
||||
@@ -1487,12 +1506,12 @@ struct command {
|
||||
static struct command _commands[] = {
|
||||
{"create", "<dev_name> [-j|--major <major> -m|--minor <minor>]\n"
|
||||
"\t [-U|--uid <uid>] [-G|--gid <gid>] [-M|--mode <octal_mode>]\n"
|
||||
"\t [-u|uuid <uuid>]"
|
||||
"\t [-u|uuid <uuid>]\n"
|
||||
"\t [--notable | --table <table> | <table_file>]",
|
||||
1, 2, _create},
|
||||
{"remove", "[-f|--force] <device>", 0, 1, _remove},
|
||||
{"remove_all", "[-f|--force]", 0, 0, _remove_all},
|
||||
{"suspend", "<device>", 0, 1, _suspend},
|
||||
{"suspend", "[--noflush] <device>", 0, 1, _suspend},
|
||||
{"resume", "<device>", 0, 1, _resume},
|
||||
{"load", "<device> [<table_file>]", 0, 2, _load},
|
||||
{"clear", "<device>", 0, 1, _clear},
|
||||
@@ -1529,6 +1548,13 @@ static void _usage(FILE *out)
|
||||
return;
|
||||
}
|
||||
|
||||
static void _losetup_usage(FILE *out)
|
||||
{
|
||||
fprintf(out, "Usage:\n\n");
|
||||
fprintf(out, "losetup [-d|-a] [-e encryption] "
|
||||
"[-o offset] [-f|loop_device] [file]\n\n");
|
||||
}
|
||||
|
||||
static struct command *_find_command(const char *name)
|
||||
{
|
||||
int i;
|
||||
@@ -1606,11 +1632,225 @@ static int _process_tree_options(const char *options)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the full absolute path, or NULL if the path could
|
||||
* not be resolved.
|
||||
*/
|
||||
static char *_get_abspath(char *path)
|
||||
{
|
||||
char *_path;
|
||||
|
||||
#ifdef HAVE_CANONICALIZE_FILE_NAME
|
||||
_path = canonicalize_file_name(path);
|
||||
#else
|
||||
/* FIXME Provide alternative */
|
||||
#endif
|
||||
return _path;
|
||||
}
|
||||
|
||||
static char *parse_loop_device_name(char *dev)
|
||||
{
|
||||
char *buf;
|
||||
char *device;
|
||||
|
||||
if (!(buf = dm_malloc(PATH_MAX)));
|
||||
return NULL;
|
||||
|
||||
if (dev[0] == '/') {
|
||||
if (!(device = _get_abspath(dev)))
|
||||
goto error;
|
||||
|
||||
if (strncmp(device, DEV_PATH, strlen(DEV_PATH)))
|
||||
goto error;
|
||||
|
||||
strncpy(buf, strrchr(device, '/') + 1, PATH_MAX);
|
||||
dm_free(device);
|
||||
|
||||
} else {
|
||||
/* check for device number */
|
||||
if (!strncmp(dev, "loop", strlen("loop")))
|
||||
strncpy(buf, dev, PATH_MAX);
|
||||
else
|
||||
goto error;
|
||||
}
|
||||
|
||||
return buf;
|
||||
|
||||
error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* create a table for a mapped device using the loop target.
|
||||
*/
|
||||
static int _loop_table(char *table, size_t tlen, char *file, char *dev, off_t off)
|
||||
{
|
||||
struct stat fbuf;
|
||||
off_t size, sectors;
|
||||
int fd = -1;
|
||||
#ifdef HAVE_SYS_STATVFS_H
|
||||
struct statvfs fsbuf;
|
||||
off_t blksize;
|
||||
#endif
|
||||
|
||||
if (!_switches[READ_ONLY])
|
||||
fd = open(file, O_RDWR);
|
||||
|
||||
if (fd < 0) {
|
||||
_switches[READ_ONLY]++;
|
||||
fd = open(file, O_RDONLY);
|
||||
}
|
||||
|
||||
if (fd < 0)
|
||||
goto error;
|
||||
|
||||
if (fstat(fd, &fbuf))
|
||||
goto error;
|
||||
|
||||
size = (fbuf.st_size - off);
|
||||
sectors = size >> SECTOR_SHIFT;
|
||||
|
||||
if (_switches[VERBOSE_ARG])
|
||||
fprintf(stderr, "losetup: set loop size to %llukB (%llu sectors)\n",
|
||||
sectors >> 1, sectors);
|
||||
|
||||
#ifdef HAVE_SYS_STATVFS_H
|
||||
if (fstatvfs(fd, &fsbuf))
|
||||
goto error;
|
||||
|
||||
/* FIXME Fragment size currently unused */
|
||||
blksize = fsbuf.f_frsize;
|
||||
#endif
|
||||
|
||||
close(fd);
|
||||
|
||||
if (dm_snprintf(table, tlen, "%llu %llu loop %s %llu\n", 0ULL,
|
||||
(long long unsigned)sectors, file, off) < 0)
|
||||
return 0;
|
||||
|
||||
if (_switches[VERBOSE_ARG] > 1)
|
||||
fprintf(stderr, "Table: %s\n", table);
|
||||
|
||||
return 1;
|
||||
|
||||
error:
|
||||
if (fd > -1)
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _process_losetup_switches(const char *base, int *argc, char ***argv)
|
||||
{
|
||||
static int ind;
|
||||
int c;
|
||||
int encrypt_loop = 0, delete = 0, find = 0, show_all = 0;
|
||||
char *device_name = NULL;
|
||||
char *loop_file = NULL;
|
||||
off_t offset = 0;
|
||||
|
||||
#ifdef HAVE_GETOPTLONG
|
||||
static struct option long_options[] = {
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
#endif
|
||||
|
||||
optarg = 0;
|
||||
optind = OPTIND_INIT;
|
||||
while ((ind = -1, c = GETOPTLONG_FN(*argc, *argv, "ade:fo:v",
|
||||
long_options, NULL)) != -1 ) {
|
||||
if (c == ':' || c == '?')
|
||||
return 0;
|
||||
if (c == 'a')
|
||||
show_all++;
|
||||
if (c == 'd')
|
||||
delete++;
|
||||
if (c == 'e')
|
||||
encrypt_loop++;
|
||||
if (c == 'f')
|
||||
find++;
|
||||
if (c == 'o')
|
||||
offset = atoi(optarg);
|
||||
if (c == 'v')
|
||||
_switches[VERBOSE_ARG]++;
|
||||
}
|
||||
|
||||
*argv += optind ;
|
||||
*argc -= optind ;
|
||||
|
||||
if (encrypt_loop){
|
||||
fprintf(stderr, "%s: Sorry, cryptoloop is not yet implemented "
|
||||
"in this version.\n", base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (show_all) {
|
||||
fprintf(stderr, "%s: Sorry, show all is not yet implemented "
|
||||
"in this version.\n", base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (find) {
|
||||
fprintf(stderr, "%s: Sorry, find is not yet implemented "
|
||||
"in this version.\n", base);
|
||||
if (!*argc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!*argc) {
|
||||
fprintf(stderr, "%s: Please specify loop_device.\n", base);
|
||||
_losetup_usage(stderr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(device_name = parse_loop_device_name((*argv)[0]))) {
|
||||
fprintf(stderr, "%s: Could not parse loop_device %s\n",
|
||||
base, (*argv)[0]);
|
||||
_losetup_usage(stderr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (delete) {
|
||||
*argc = 2;
|
||||
|
||||
(*argv)[1] = device_name;
|
||||
(*argv)[0] = (char *) "remove";
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (*argc != 2) {
|
||||
fprintf(stderr, "%s: Too few arguments\n", base);
|
||||
_losetup_usage(stderr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* FIXME move these to make them available to native dmsetup */
|
||||
if (!(loop_file = _get_abspath((*argv)[(find) ? 0 : 1]))) {
|
||||
fprintf(stderr, "%s: Could not parse loop file name %s\n",
|
||||
base, (*argv)[1]);
|
||||
_losetup_usage(stderr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* FIXME Missing free */
|
||||
_table = dm_malloc(LOOP_TABLE_SIZE);
|
||||
if (!_loop_table(_table, LOOP_TABLE_SIZE, loop_file, device_name, offset)) {
|
||||
fprintf(stderr, "Could not build device-mapper table for %s\n", (*argv)[0]);
|
||||
return 0;
|
||||
}
|
||||
_switches[TABLE_ARG]++;
|
||||
|
||||
(*argv)[0] = (char *) "create";
|
||||
(*argv)[1] = device_name ;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _process_switches(int *argc, char ***argv)
|
||||
{
|
||||
char *base, *namebase;
|
||||
static int ind;
|
||||
int c;
|
||||
int c, r;
|
||||
|
||||
#ifdef HAVE_GETOPTLONG
|
||||
static struct option long_options[] = {
|
||||
@@ -1622,6 +1862,7 @@ static int _process_switches(int *argc, char ***argv)
|
||||
{"major", 1, &ind, MAJOR_ARG},
|
||||
{"minor", 1, &ind, MINOR_ARG},
|
||||
{"mode", 1, &ind, MODE_ARG},
|
||||
{"noflush", 0, &ind, NOFLUSH_ARG},
|
||||
{"noheadings", 0, &ind, NOHEADINGS_ARG},
|
||||
{"nolockfs", 0, &ind, NOLOCKFS_ARG},
|
||||
{"noopencount", 0, &ind, NOOPENCOUNT_ARG},
|
||||
@@ -1678,6 +1919,12 @@ static int _process_switches(int *argc, char ***argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(!strcmp(base, "losetup") || !strcmp(base, "dmlosetup")){
|
||||
r = _process_losetup_switches(base, argc, argv);
|
||||
free(namebase);
|
||||
return r;
|
||||
}
|
||||
|
||||
free(namebase);
|
||||
|
||||
optarg = 0;
|
||||
@@ -1733,6 +1980,8 @@ static int _process_switches(int *argc, char ***argv)
|
||||
_switches[TARGET_ARG]++;
|
||||
_target = optarg;
|
||||
}
|
||||
if ((ind == NOFLUSH_ARG))
|
||||
_switches[NOFLUSH_ARG]++;
|
||||
if ((ind == NOHEADINGS_ARG))
|
||||
_switches[NOHEADINGS_ARG]++;
|
||||
if ((ind == NOLOCKFS_ARG))
|
||||
|
||||
@@ -102,7 +102,7 @@ static int _read_params(struct lvconvert_params *lp, struct cmd_context *cmd,
|
||||
int argc, char **argv)
|
||||
{
|
||||
int region_size;
|
||||
int pagesize = getpagesize();
|
||||
int pagesize = lvm_getpagesize();
|
||||
|
||||
memset(lp, 0, sizeof(*lp));
|
||||
|
||||
@@ -344,8 +344,7 @@ static int lvconvert_mirrors(struct cmd_context * cmd, struct logical_volume * l
|
||||
lp->mirrors - 1);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (lp->mirrors > existing_mirrors) {
|
||||
} else if (lp->mirrors > existing_mirrors) {
|
||||
/* FIXME Unless anywhere, remove PV of log_lv
|
||||
* from allocatable_pvs & allocate
|
||||
* (mirrors - existing_mirrors) new areas
|
||||
@@ -565,6 +564,12 @@ int lvconvert(struct cmd_context * cmd, int argc, char **argv)
|
||||
goto error;
|
||||
}
|
||||
|
||||
if ((vg->status & CLUSTERED) && !locking_is_clustered() &&
|
||||
!lockingfailed()) {
|
||||
log_error("Skipping clustered volume group %s", lp.vg_name);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (vg->status & EXPORTED_VG) {
|
||||
log_error("Volume group \"%s\" is exported", lp.vg_name);
|
||||
goto error;
|
||||
|
||||
@@ -43,6 +43,7 @@ struct lvcreate_params {
|
||||
/* size */
|
||||
uint32_t extents;
|
||||
uint64_t size;
|
||||
percent_t percent;
|
||||
|
||||
uint32_t permission;
|
||||
uint32_t read_ahead;
|
||||
@@ -94,19 +95,7 @@ static int _lvcreate_name_params(struct lvcreate_params *lp,
|
||||
}
|
||||
|
||||
} else {
|
||||
vg_name = argv[0];
|
||||
/* Strip dev_dir (optional) */
|
||||
if (*vg_name == '/') {
|
||||
while (*vg_name == '/')
|
||||
vg_name++;
|
||||
vg_name--;
|
||||
}
|
||||
if (!strncmp(vg_name, cmd->dev_dir,
|
||||
strlen(cmd->dev_dir))) {
|
||||
vg_name += strlen(cmd->dev_dir);
|
||||
while (*vg_name == '/')
|
||||
vg_name++;
|
||||
}
|
||||
vg_name = skip_dev_dir(cmd, argv[0]);
|
||||
if (strrchr(vg_name, '/')) {
|
||||
log_error("Volume group name expected "
|
||||
"(no slash)");
|
||||
@@ -169,6 +158,7 @@ static int _read_size_params(struct lvcreate_params *lp,
|
||||
return 0;
|
||||
}
|
||||
lp->extents = arg_uint_value(cmd, extents_ARG, 0);
|
||||
lp->percent = arg_percent_value(cmd, extents_ARG, PERCENT_NONE);
|
||||
}
|
||||
|
||||
/* Size returned in kilobyte units; held in sectors */
|
||||
@@ -178,6 +168,7 @@ static int _read_size_params(struct lvcreate_params *lp,
|
||||
return 0;
|
||||
}
|
||||
lp->size = arg_uint64_value(cmd, size_ARG, UINT64_C(0)) * 2;
|
||||
lp->percent = PERCENT_NONE;
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -249,7 +240,7 @@ static int _read_mirror_params(struct lvcreate_params *lp,
|
||||
{
|
||||
int argc = *pargc;
|
||||
int region_size;
|
||||
int pagesize = getpagesize();
|
||||
int pagesize = lvm_getpagesize();
|
||||
|
||||
if (argc && (unsigned) argc < lp->mirrors) {
|
||||
log_error("Too few physical volumes on "
|
||||
@@ -498,6 +489,12 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((vg->status & CLUSTERED) && !locking_is_clustered() &&
|
||||
!lockingfailed()) {
|
||||
log_error("Skipping clustered volume group %s", lp->vg_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (vg->status & EXPORTED_VG) {
|
||||
log_error("Volume group \"%s\" is exported", lp->vg_name);
|
||||
return 0;
|
||||
@@ -562,6 +559,20 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
|
||||
lp->extents = tmp_size / vg->extent_size;
|
||||
}
|
||||
|
||||
switch(lp->percent) {
|
||||
case PERCENT_VG:
|
||||
lp->extents = lp->extents * vg->extent_count / 100;
|
||||
break;
|
||||
case PERCENT_FREE:
|
||||
lp->extents = lp->extents * vg->free_count / 100;
|
||||
break;
|
||||
case PERCENT_LV:
|
||||
log_error("Please express size as %%VG or %%FREE.");
|
||||
return 0;
|
||||
case PERCENT_NONE:
|
||||
break;
|
||||
}
|
||||
|
||||
if ((size_rest = lp->extents % lp->stripes)) {
|
||||
log_print("Rounding size (%d extents) up to stripe boundary "
|
||||
"size (%d extents)", lp->extents,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user