1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

Various small cleanups and fixes related to monitoring.

This commit is contained in:
Alasdair Kergon 2010-08-16 22:54:35 +00:00
parent 470c18847d
commit d1e8046f56
17 changed files with 412 additions and 283 deletions

View File

@ -1,5 +1,8 @@
Version 2.02.73 - Version 2.02.73 -
================================ ================================
Fix some exit statuses when starting/stopping monitoring fails.
Enable snapshot monitoring by default when dmeventd is enabled.
Move cloned libdevmapper-event client code from segments into lib/activate.
Fix 'lvconvert --splitmirrors' in cluster operation. Fix 'lvconvert --splitmirrors' in cluster operation.
Fix clvmd init script exit code when executed as non-root user. Fix clvmd init script exit code when executed as non-root user.
Change default alignment of pe_start to 1MB. Change default alignment of pe_start to 1MB.

View File

@ -1,5 +1,8 @@
Version 1.02.54 - Version 1.02.54 -
================================ ================================
Add dmeventd/executable to lvm.conf to test alternative dmeventd.
Export dm_event_handler_set_dmeventd_path to override built-in dmeventd path.
Generate libdevmapper-event exported symbols.
Remove superfluous NULL pointer tests before dm_free from dmeventd. Remove superfluous NULL pointer tests before dm_free from dmeventd.
Assume dm-mod autoloading support is in kernel 2.6.36 and higher, not 2.6.35. Assume dm-mod autoloading support is in kernel 2.6.36 and higher, not 2.6.35.
Fix udev rules to support udev database content generated by older rules. Fix udev rules to support udev database content generated by older rules.

178
configure vendored
View File

@ -688,6 +688,7 @@ DM_DEVICE_UID
DM_DEVICE_MODE DM_DEVICE_MODE
DM_DEVICE_GID DM_DEVICE_GID
DM_COMPAT DM_COMPAT
DMEVENTD_PATH
DMEVENTD DMEVENTD
DL_LIBS DL_LIBS
DEVMAPPER DEVMAPPER
@ -840,6 +841,7 @@ enable_debug
with_optimisation with_optimisation
enable_profiling enable_profiling
enable_testing enable_testing
enable_valgrind_pool
enable_devmapper enable_devmapper
enable_udev_sync enable_udev_sync
enable_udev_rules enable_udev_rules
@ -1538,6 +1540,7 @@ Optional Features:
--enable-debug enable debugging --enable-debug enable debugging
--enable-profiling gather gcov profiling data --enable-profiling gather gcov profiling data
--enable-testing enable testing targets in the makefile --enable-testing enable testing targets in the makefile
--enable-valgrind-pool enable valgrind awareness of pools
--disable-devmapper disable LVM2 device-mapper interaction --disable-devmapper disable LVM2 device-mapper interaction
--enable-udev_sync enable synchronisation with udev processing --enable-udev_sync enable synchronisation with udev processing
--enable-udev_rules install rule files needed for udev synchronisation --enable-udev_rules install rule files needed for udev synchronisation
@ -14406,6 +14409,177 @@ $as_echo "$as_me: error: ruby1.9 and valgrind are required for testing" >&2;}
fi fi
fi fi
################################################################################
{ $as_echo "$as_me:$LINENO: checking whether to enable valgrind awareness of pools" >&5
$as_echo_n "checking whether to enable valgrind awareness of pools... " >&6; }
# Check whether --enable-valgrind_pool was given.
if test "${enable_valgrind_pool+set}" = set; then
enableval=$enable_valgrind_pool; VALGRIND_POOL=$enableval
else
VALGRIND_POOL=no
fi
{ $as_echo "$as_me:$LINENO: result: $VALGRIND_POOL" >&5
$as_echo "$VALGRIND_POOL" >&6; }
if test "$VALGRIND_POOL" = yes; then
for ac_header in valgrind/memcheck.h
do
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
{ $as_echo "$as_me:$LINENO: checking for $ac_header" >&5
$as_echo_n "checking for $ac_header... " >&6; }
if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
$as_echo_n "(cached) " >&6
fi
ac_res=`eval 'as_val=${'$as_ac_Header'}
$as_echo "$as_val"'`
{ $as_echo "$as_me:$LINENO: result: $ac_res" >&5
$as_echo "$ac_res" >&6; }
else
# Is the header compilable?
{ $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5
$as_echo_n "checking $ac_header usability... " >&6; }
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
$ac_includes_default
#include <$ac_header>
_ACEOF
rm -f conftest.$ac_objext
if { (ac_try="$ac_compile"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
$as_echo "$ac_try_echo") >&5
(eval "$ac_compile") 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
$as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } && {
test -z "$ac_c_werror_flag" ||
test ! -s conftest.err
} && test -s conftest.$ac_objext; then
ac_header_compiler=yes
else
$as_echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_header_compiler=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
{ $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
$as_echo "$ac_header_compiler" >&6; }
# Is the header present?
{ $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5
$as_echo_n "checking $ac_header presence... " >&6; }
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
#include <$ac_header>
_ACEOF
if { (ac_try="$ac_cpp conftest.$ac_ext"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
$as_echo "$ac_try_echo") >&5
(eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
$as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } >/dev/null && {
test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
test ! -s conftest.err
}; then
ac_header_preproc=yes
else
$as_echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_header_preproc=no
fi
rm -f conftest.err conftest.$ac_ext
{ $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
$as_echo "$ac_header_preproc" >&6; }
# So? What about this header?
case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
yes:no: )
{ $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
$as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
{ $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
$as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
ac_header_preproc=yes
;;
no:yes:* )
{ $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
$as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
{ $as_echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
$as_echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
{ $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
$as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
{ $as_echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
$as_echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
{ $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
$as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
{ $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
$as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
;;
esac
{ $as_echo "$as_me:$LINENO: checking for $ac_header" >&5
$as_echo_n "checking for $ac_header... " >&6; }
if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
$as_echo_n "(cached) " >&6
else
eval "$as_ac_Header=\$ac_header_preproc"
fi
ac_res=`eval 'as_val=${'$as_ac_Header'}
$as_echo "$as_val"'`
{ $as_echo "$as_me:$LINENO: result: $ac_res" >&5
$as_echo "$ac_res" >&6; }
fi
as_val=`eval 'as_val=${'$as_ac_Header'}
$as_echo "$as_val"'`
if test "x$as_val" = x""yes; then
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF
else
{ { $as_echo "$as_me:$LINENO: error: bailing out" >&5
$as_echo "$as_me: error: bailing out" >&2;}
{ (exit 1); exit 1; }; }
fi
done
cat >>confdefs.h <<\_ACEOF
#define VALGRIND_POOL 1
_ACEOF
fi
################################################################################ ################################################################################
{ $as_echo "$as_me:$LINENO: checking whether to use device-mapper" >&5 { $as_echo "$as_me:$LINENO: checking whether to use device-mapper" >&5
$as_echo_n "checking whether to use device-mapper... " >&6; } $as_echo_n "checking whether to use device-mapper... " >&6; }
@ -18043,10 +18217,11 @@ LVM_LIBAPI=`echo "$VER" | $AWK -F '[()]' '{print $2}'`
################################################################################ ################################################################################
ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile daemons/cmirrord/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/lvm2/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile doc/Makefile doc/example.conf include/.symlinks include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/replicator/Makefile lib/misc/lvm-version.h lib/snapshot/Makefile libdm/Makefile libdm/libdevmapper.pc liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile scripts/clvmd_init_red_hat scripts/cmirrord_init_red_hat scripts/lvm2_monitoring_init_red_hat scripts/Makefile test/Makefile test/api/Makefile tools/Makefile udev/Makefile unit-tests/datastruct/Makefile unit-tests/regex/Makefile" ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile daemons/cmirrord/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/lvm2/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile doc/Makefile doc/example.conf include/.symlinks include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/replicator/Makefile lib/misc/lvm-version.h lib/snapshot/Makefile libdm/Makefile libdm/libdevmapper.pc liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile scripts/clvmd_init_red_hat scripts/cmirrord_init_red_hat scripts/lvm2_monitoring_init_red_hat scripts/Makefile test/Makefile test/api/Makefile tools/Makefile udev/Makefile unit-tests/datastruct/Makefile unit-tests/regex/Makefile unit-tests/mm/Makefile"
cat >confcache <<\_ACEOF cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure # This file is a shell script that caches the results of configure
@ -18684,6 +18859,7 @@ do
"udev/Makefile") CONFIG_FILES="$CONFIG_FILES udev/Makefile" ;; "udev/Makefile") CONFIG_FILES="$CONFIG_FILES udev/Makefile" ;;
"unit-tests/datastruct/Makefile") CONFIG_FILES="$CONFIG_FILES unit-tests/datastruct/Makefile" ;; "unit-tests/datastruct/Makefile") CONFIG_FILES="$CONFIG_FILES unit-tests/datastruct/Makefile" ;;
"unit-tests/regex/Makefile") CONFIG_FILES="$CONFIG_FILES unit-tests/regex/Makefile" ;; "unit-tests/regex/Makefile") CONFIG_FILES="$CONFIG_FILES unit-tests/regex/Makefile" ;;
"unit-tests/mm/Makefile") CONFIG_FILES="$CONFIG_FILES unit-tests/mm/Makefile" ;;
*) { { $as_echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 *) { { $as_echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
$as_echo "$as_me: error: invalid argument: $ac_config_target" >&2;} $as_echo "$as_me: error: invalid argument: $ac_config_target" >&2;}

View File

@ -1251,6 +1251,7 @@ AC_SUBST(DLM_CFLAGS)
AC_SUBST(DLM_LIBS) AC_SUBST(DLM_LIBS)
AC_SUBST(DL_LIBS) AC_SUBST(DL_LIBS)
AC_SUBST(DMEVENTD) AC_SUBST(DMEVENTD)
AC_SUBST(DMEVENTD_PATH)
AC_SUBST(DM_COMPAT) AC_SUBST(DM_COMPAT)
AC_SUBST(DM_DEVICE_GID) AC_SUBST(DM_DEVICE_GID)
AC_SUBST(DM_DEVICE_MODE) AC_SUBST(DM_DEVICE_MODE)

View File

@ -1,19 +0,0 @@
dm_event_handler_create
dm_event_handler_destroy
dm_event_handler_set_dso
dm_event_handler_set_dev_name
dm_event_handler_set_uuid
dm_event_handler_set_major
dm_event_handler_set_minor
dm_event_handler_set_event_mask
dm_event_handler_get_dso
dm_event_handler_get_devname
dm_event_handler_get_uuid
dm_event_handler_get_major
dm_event_handler_get_minor
dm_event_handler_get_event_mask
dm_event_register_handler
dm_event_unregister_handler
dm_event_get_registered_device
dm_event_handler_set_timeout
dm_event_handler_get_timeout

View File

@ -48,6 +48,9 @@ CFLOW_LIST = $(SOURCES)
CFLOW_LIST_TARGET = $(LIB_NAME).cflow CFLOW_LIST_TARGET = $(LIB_NAME).cflow
CFLOW_TARGET = dmeventd CFLOW_TARGET = dmeventd
EXPORTED_HEADER = $(srcdir)/libdevmapper-event.h
EXPORTED_FN_PREFIX = dm_event
include $(top_builddir)/make.tmpl include $(top_builddir)/make.tmpl
all: device-mapper all: device-mapper
@ -102,4 +105,4 @@ install: install_include install_lib install_dmeventd
install_device-mapper: install_include install_lib install_dmeventd install_device-mapper: install_include install_lib install_dmeventd
DISTCLEAN_TARGETS += libdevmapper-event.pc DISTCLEAN_TARGETS += libdevmapper-event.pc .exported_symbols_generated

View File

@ -35,6 +35,8 @@ static int _sequence_nr = 0;
struct dm_event_handler { struct dm_event_handler {
char *dso; char *dso;
char *dmeventd_path;
char *dev_name; char *dev_name;
char *uuid; char *uuid;
@ -60,6 +62,7 @@ struct dm_event_handler *dm_event_handler_create(void)
if (!(dmevh = dm_malloc(sizeof(*dmevh)))) if (!(dmevh = dm_malloc(sizeof(*dmevh))))
return NULL; return NULL;
dmevh->dmeventd_path = NULL;
dmevh->dso = dmevh->dev_name = dmevh->uuid = NULL; dmevh->dso = dmevh->dev_name = dmevh->uuid = NULL;
dmevh->major = dmevh->minor = 0; dmevh->major = dmevh->minor = 0;
dmevh->mask = 0; dmevh->mask = 0;
@ -72,9 +75,24 @@ void dm_event_handler_destroy(struct dm_event_handler *dmevh)
{ {
_dm_event_handler_clear_dev_info(dmevh); _dm_event_handler_clear_dev_info(dmevh);
dm_free(dmevh->dso); dm_free(dmevh->dso);
dm_free(dmevh->dmeventd_path);
dm_free(dmevh); dm_free(dmevh);
} }
int dm_event_handler_set_dmeventd_path(struct dm_event_handler *dmevh, const char *dmeventd_path)
{
if (!dmeventd_path) /* noop */
return 0;
dm_free(dmevh->dmeventd_path);
dmevh->dmeventd_path = dm_strdup(dmeventd_path);
if (!dmevh->dmeventd_path)
return -ENOMEM;
return 0;
}
int dm_event_handler_set_dso(struct dm_event_handler *dmevh, const char *path) int dm_event_handler_set_dso(struct dm_event_handler *dmevh, const char *path)
{ {
if (!path) /* noop */ if (!path) /* noop */
@ -387,13 +405,13 @@ static int _daemon_talk(struct dm_event_fifos *fifos,
* *
* Returns: 1 on success, 0 otherwise * Returns: 1 on success, 0 otherwise
*/ */
static int _start_daemon(struct dm_event_fifos *fifos) static int _start_daemon(char *dmeventd_path, struct dm_event_fifos *fifos)
{ {
int pid, ret = 0; int pid, ret = 0;
int status; int status;
struct stat statbuf; struct stat statbuf;
char dmeventdpath[] = DMEVENTD_PATH; /* const type for execvp */ char default_dmeventd_path[] = DMEVENTD_PATH;
char * const args[] = { dmeventdpath, NULL }; char *args[] = { dmeventd_path ? : default_dmeventd_path, NULL };
if (stat(fifos->client_path, &statbuf)) if (stat(fifos->client_path, &statbuf))
goto start_server; goto start_server;
@ -449,17 +467,19 @@ static int _start_daemon(struct dm_event_fifos *fifos)
} }
/* Initialize client. */ /* Initialize client. */
static int _init_client(struct dm_event_fifos *fifos) static int _init_client(char *dmeventd_path, struct dm_event_fifos *fifos)
{ {
/* FIXME? Is fifo the most suitable method? Why not share /* FIXME? Is fifo the most suitable method? Why not share
comms/daemon code with something else e.g. multipath? */ comms/daemon code with something else e.g. multipath? */
/* init fifos */ /* init fifos */
memset(fifos, 0, sizeof(*fifos)); memset(fifos, 0, sizeof(*fifos));
/* FIXME Make these either configurable or depend directly on dmeventd_path */
fifos->client_path = DM_EVENT_FIFO_CLIENT; fifos->client_path = DM_EVENT_FIFO_CLIENT;
fifos->server_path = DM_EVENT_FIFO_SERVER; fifos->server_path = DM_EVENT_FIFO_SERVER;
if (!_start_daemon(fifos)) { if (!_start_daemon(dmeventd_path, fifos)) {
stack; stack;
return 0; return 0;
} }
@ -544,14 +564,14 @@ failed:
} }
/* Handle the event (de)registration call and return negative error codes. */ /* Handle the event (de)registration call and return negative error codes. */
static int _do_event(int cmd, struct dm_event_daemon_message *msg, static int _do_event(int cmd, char *dmeventd_path, struct dm_event_daemon_message *msg,
const char *dso_name, const char *dev_name, const char *dso_name, const char *dev_name,
enum dm_event_mask evmask, uint32_t timeout) enum dm_event_mask evmask, uint32_t timeout)
{ {
int ret; int ret;
struct dm_event_fifos fifos; struct dm_event_fifos fifos;
if (!_init_client(&fifos)) { if (!_init_client(dmeventd_path, &fifos)) {
stack; stack;
return -ESRCH; return -ESRCH;
} }
@ -585,7 +605,7 @@ int dm_event_register_handler(const struct dm_event_handler *dmevh)
uuid = dm_task_get_uuid(dmt); uuid = dm_task_get_uuid(dmt);
if ((err = _do_event(DM_EVENT_CMD_REGISTER_FOR_EVENT, &msg, if ((err = _do_event(DM_EVENT_CMD_REGISTER_FOR_EVENT, dmevh->dmeventd_path, &msg,
dmevh->dso, uuid, dmevh->mask, dmevh->timeout)) < 0) { dmevh->dso, uuid, dmevh->mask, dmevh->timeout)) < 0) {
log_error("%s: event registration failed: %s", log_error("%s: event registration failed: %s",
dm_task_get_name(dmt), dm_task_get_name(dmt),
@ -614,7 +634,7 @@ int dm_event_unregister_handler(const struct dm_event_handler *dmevh)
uuid = dm_task_get_uuid(dmt); uuid = dm_task_get_uuid(dmt);
if ((err = _do_event(DM_EVENT_CMD_UNREGISTER_FOR_EVENT, &msg, if ((err = _do_event(DM_EVENT_CMD_UNREGISTER_FOR_EVENT, dmevh->dmeventd_path, &msg,
dmevh->dso, uuid, dmevh->mask, dmevh->timeout)) < 0) { dmevh->dso, uuid, dmevh->mask, dmevh->timeout)) < 0) {
log_error("%s: event deregistration failed: %s", log_error("%s: event deregistration failed: %s",
dm_task_get_name(dmt), dm_task_get_name(dmt),
@ -689,7 +709,7 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
uuid = dm_task_get_uuid(dmt); uuid = dm_task_get_uuid(dmt);
if (!(ret = _do_event(next ? DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE : if (!(ret = _do_event(next ? DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE :
DM_EVENT_CMD_GET_REGISTERED_DEVICE, DM_EVENT_CMD_GET_REGISTERED_DEVICE, dmevh->dmeventd_path,
&msg, dmevh->dso, uuid, dmevh->mask, 0))) { &msg, dmevh->dso, uuid, dmevh->mask, 0))) {
/* FIXME this will probably horribly break if we get /* FIXME this will probably horribly break if we get
ill-formatted reply */ ill-formatted reply */

View File

@ -55,12 +55,17 @@ void dm_event_handler_destroy(struct dm_event_handler *dmevh);
/* /*
* Path of shared library to handle events. * Path of shared library to handle events.
* *
* All of dso, device_name and uuid strings are duplicated, you do not * All of dmeventd, dso, device_name and uuid strings are duplicated so
* need to keep the pointers valid after the call succeeds. Thes may * you do not need to keep the pointers valid after the call succeeds.
* return -ENOMEM though. * They may return -ENOMEM though.
*/ */
int dm_event_handler_set_dso(struct dm_event_handler *dmevh, const char *path); int dm_event_handler_set_dso(struct dm_event_handler *dmevh, const char *path);
/*
* Path of dmeventd binary.
*/
int dm_event_handler_set_dmeventd_path(struct dm_event_handler *dmevh, const char *dmeventd_path);
/* /*
* Identify the device to monitor by exactly one of device_name, uuid or * Identify the device to monitor by exactly one of device_name, uuid or
* device number. String arguments are duplicated, see above. * device number. String arguments are duplicated, see above.

View File

@ -509,9 +509,13 @@ dmeventd {
# snapshot_library is the library used when monitoring a snapshot device. # snapshot_library is the library used when monitoring a snapshot device.
# #
# "libdevmapper-event-lvm2snapshot.so" monitors the filling of # "libdevmapper-event-lvm2snapshot.so" monitors the filling of
# snapshots and emits a warning through syslog, when the use of # snapshots and emits a warning through syslog when the use of
# snapshot exceedes 80%. The warning is repeated when 85%, 90% and # the snapshot exceeds 80%. The warning is repeated when 85%, 90% and
# 95% of the snapshot are filled. # 95% of the snapshot is filled.
snapshot_library = "libdevmapper-event-lvm2snapshot.so" snapshot_library = "libdevmapper-event-lvm2snapshot.so"
# Full path of the dmeventd binary.
#
# executable = "@DMEVENTD_PATH@"
} }

View File

@ -28,6 +28,7 @@
#include "config.h" #include "config.h"
#include "filter.h" #include "filter.h"
#include "segtype.h" #include "segtype.h"
#include "sharedlib.h"
#include <limits.h> #include <limits.h>
#include <fcntl.h> #include <fcntl.h>
@ -727,6 +728,112 @@ int lv_is_active(struct logical_volume *lv)
return 1; return 1;
} }
#ifdef DMEVENTD
static struct dm_event_handler *_create_dm_event_handler(struct cmd_context *cmd, const char *dmuuid, const char *dso,
const int timeout, enum dm_event_mask mask)
{
struct dm_event_handler *dmevh;
if (!(dmevh = dm_event_handler_create()))
return_NULL;
if (dm_event_handler_set_dmeventd_path(dmevh, find_config_tree_str(cmd, "dmeventd/executable", NULL)))
goto_bad;
if (dm_event_handler_set_dso(dmevh, dso))
goto_bad;
if (dm_event_handler_set_uuid(dmevh, dmuuid))
goto_bad;
dm_event_handler_set_timeout(dmevh, timeout);
dm_event_handler_set_event_mask(dmevh, mask);
return dmevh;
bad:
dm_event_handler_destroy(dmevh);
return NULL;
}
char *get_monitor_dso_path(struct cmd_context *cmd, const char *libpath)
{
char *path;
if (!(path = dm_pool_alloc(cmd->mem, PATH_MAX))) {
log_error("Failed to allocate dmeventd library path.");
return NULL;
}
get_shared_library_path(cmd, libpath, path, PATH_MAX);
return path;
}
int target_registered_with_dmeventd(struct cmd_context *cmd, const char *dso, const char *lvid, int *pending)
{
char *uuid;
enum dm_event_mask evmask = 0;
struct dm_event_handler *dmevh;
*pending = 0;
if (!dso)
return_0;
if (!(uuid = build_dm_uuid(cmd->mem, lvid, NULL)))
return_0;
if (!(dmevh = _create_dm_event_handler(cmd, uuid, dso, 0, DM_EVENT_ALL_ERRORS)))
return_0;
if (dm_event_get_registered_device(dmevh, 0)) {
dm_event_handler_destroy(dmevh);
return 0;
}
evmask = dm_event_handler_get_event_mask(dmevh);
if (evmask & DM_EVENT_REGISTRATION_PENDING) {
*pending = 1;
evmask &= ~DM_EVENT_REGISTRATION_PENDING;
}
dm_event_handler_destroy(dmevh);
return evmask;
}
int target_register_events(struct cmd_context *cmd, const char *dso, const char *lvid,
int evmask __attribute__((unused)), int set, int timeout)
{
char *uuid;
struct dm_event_handler *dmevh;
int r;
if (!dso)
return_0;
if (!(uuid = build_dm_uuid(cmd->mem, lvid, NULL)))
return_0;
if (!(dmevh = _create_dm_event_handler(cmd, uuid, dso, timeout,
DM_EVENT_ALL_ERRORS | (timeout ? DM_EVENT_TIMEOUT : 0))))
return_0;
r = set ? dm_event_register_handler(dmevh) : dm_event_unregister_handler(dmevh);
dm_event_handler_destroy(dmevh);
if (!r)
return_0;
log_info("%s %s for events", set ? "Monitored" : "Unmonitored", uuid);
return 1;
}
#endif
/* /*
* Returns 0 if an attempt to (un)monitor the device failed. * Returns 0 if an attempt to (un)monitor the device failed.
* Returns 1 otherwise. * Returns 1 otherwise.

View File

@ -44,7 +44,7 @@ int module_present(struct cmd_context *cmd, const char *target_name);
int target_present(struct cmd_context *cmd, const char *target_name, int target_present(struct cmd_context *cmd, const char *target_name,
int use_modprobe); int use_modprobe);
int target_version(const char *target_name, uint32_t *maj, int target_version(const char *target_name, uint32_t *maj,
uint32_t *min, uint32_t *patchlevel); uint32_t *min, uint32_t *patchlevel);
int list_segment_modules(struct dm_pool *mem, const struct lv_segment *seg, int list_segment_modules(struct dm_pool *mem, const struct lv_segment *seg,
struct dm_list *modules); struct dm_list *modules);
int list_lv_modules(struct dm_pool *mem, const struct logical_volume *lv, int list_lv_modules(struct dm_pool *mem, const struct logical_volume *lv,
@ -102,6 +102,14 @@ int lv_has_target_type(struct dm_pool *mem, struct logical_volume *lv,
int monitor_dev_for_events(struct cmd_context *cmd, int monitor_dev_for_events(struct cmd_context *cmd,
struct logical_volume *lv, int do_reg); struct logical_volume *lv, int do_reg);
#ifdef DMEVENTD
# include "libdevmapper-event.h"
char *get_monitor_dso_path(struct cmd_context *cmd, const char *libpath);
int target_registered_with_dmeventd(struct cmd_context *cmd, const char *libpath, const char *lvid, int *pending);
int target_register_events(struct cmd_context *cmd, const char *dso, const char *lvid,
int evmask __attribute__((unused)), int set, int timeout);
#endif
/* /*
* Returns 1 if PV has a dependency tree that uses anything in VG. * Returns 1 if PV has a dependency tree that uses anything in VG.
*/ */

View File

@ -48,6 +48,7 @@
#define DEFAULT_MIRROR_IMAGE_FAULT_POLICY "remove" #define DEFAULT_MIRROR_IMAGE_FAULT_POLICY "remove"
#define DEFAULT_MIRROR_MAX_IMAGES 8 /* limited by kernel DM_KCOPYD_MAX_REGIONS */ #define DEFAULT_MIRROR_MAX_IMAGES 8 /* limited by kernel DM_KCOPYD_MAX_REGIONS */
#define DEFAULT_DMEVENTD_MIRROR_LIB "libdevmapper-event-lvm2mirror.so" #define DEFAULT_DMEVENTD_MIRROR_LIB "libdevmapper-event-lvm2mirror.so"
#define DEFAULT_DMEVENTD_SNAPSHOT_LIB "libdevmapper-event-lvm2snapshot.so"
#define DEFAULT_DMEVENTD_MONITOR 1 #define DEFAULT_DMEVENTD_MONITOR 1
#define DEFAULT_BACKGROUND_POLLING 1 #define DEFAULT_BACKGROUND_POLLING 1

View File

@ -30,10 +30,6 @@
#include <sys/utsname.h> #include <sys/utsname.h>
#ifdef DMEVENTD
# include "libdevmapper-event.h"
#endif
static int _block_on_error_available = 0; static int _block_on_error_available = 0;
static unsigned _mirror_attributes = 0; static unsigned _mirror_attributes = 0;
@ -520,19 +516,19 @@ static int _mirrored_target_present(struct cmd_context *cmd,
} else if (module_present(cmd, "log-userspace")) } else if (module_present(cmd, "log-userspace"))
_mirror_attributes |= MIRROR_LOG_CLUSTERED; _mirror_attributes |= MIRROR_LOG_CLUSTERED;
if (!(_mirror_attributes & MIRROR_LOG_CLUSTERED)) if (!(_mirror_attributes & MIRROR_LOG_CLUSTERED))
log_verbose("Cluster mirror log module is not available"); log_verbose("Cluster mirror log module is not available");
/* /*
* The cluster mirror log daemon must be running, * The cluster mirror log daemon must be running,
* otherwise, the kernel module will fail to make * otherwise, the kernel module will fail to make
* contact. * contact.
*/ */
#ifdef CMIRRORD_PIDFILE #ifdef CMIRRORD_PIDFILE
if (!dm_daemon_is_running(CMIRRORD_PIDFILE)) { if (!dm_daemon_is_running(CMIRRORD_PIDFILE)) {
log_verbose("Cluster mirror log daemon is not running"); log_verbose("Cluster mirror log daemon is not running");
_mirror_attributes &= ~MIRROR_LOG_CLUSTERED; _mirror_attributes &= ~MIRROR_LOG_CLUSTERED;
} }
#else #else
log_verbose("Cluster mirror log daemon not included in build"); log_verbose("Cluster mirror log daemon not included in build");
_mirror_attributes &= ~MIRROR_LOG_CLUSTERED; _mirror_attributes &= ~MIRROR_LOG_CLUSTERED;
@ -546,116 +542,23 @@ static int _mirrored_target_present(struct cmd_context *cmd,
} }
#ifdef DMEVENTD #ifdef DMEVENTD
static int _get_mirror_dso_path(struct cmd_context *cmd, char **dso) static const char *_get_mirror_dso_path(struct cmd_context *cmd)
{ {
char *path; return get_monitor_dso_path(cmd, find_config_tree_str(cmd, "dmeventd/mirror_library",
const char *libpath; DEFAULT_DMEVENTD_MIRROR_LIB));
if (!(path = dm_pool_alloc(cmd->mem, PATH_MAX))) {
log_error("Failed to allocate dmeventd library path.");
return 0;
}
libpath = find_config_tree_str(cmd, "dmeventd/mirror_library",
DEFAULT_DMEVENTD_MIRROR_LIB);
get_shared_library_path(cmd, libpath, path, PATH_MAX);
*dso = path;
return 1;
} }
static struct dm_event_handler *_create_dm_event_handler(const char *dmuuid, static int _target_registered(struct lv_segment *seg, int *pending)
const char *dso,
enum dm_event_mask mask)
{ {
struct dm_event_handler *dmevh; return target_registered_with_dmeventd(seg->lv->vg->cmd, _get_mirror_dso_path(seg->lv->vg->cmd),
seg->lv->lvid.s, pending);
if (!(dmevh = dm_event_handler_create()))
return_0;
if (dm_event_handler_set_dso(dmevh, dso))
goto fail;
if (dm_event_handler_set_uuid(dmevh, dmuuid))
goto fail;
dm_event_handler_set_event_mask(dmevh, mask);
return dmevh;
fail:
dm_event_handler_destroy(dmevh);
return NULL;
}
static int _target_monitored(struct lv_segment *seg, int *pending)
{
char *dso, *uuid;
struct logical_volume *lv;
struct volume_group *vg;
enum dm_event_mask evmask = 0;
struct dm_event_handler *dmevh;
lv = seg->lv;
vg = lv->vg;
*pending = 0;
if (!_get_mirror_dso_path(vg->cmd, &dso))
return_0;
if (!(uuid = build_dm_uuid(vg->cmd->mem, lv->lvid.s, NULL)))
return_0;
if (!(dmevh = _create_dm_event_handler(uuid, dso, DM_EVENT_ALL_ERRORS)))
return_0;
if (dm_event_get_registered_device(dmevh, 0)) {
dm_event_handler_destroy(dmevh);
return 0;
}
evmask = dm_event_handler_get_event_mask(dmevh);
if (evmask & DM_EVENT_REGISTRATION_PENDING) {
*pending = 1;
evmask &= ~DM_EVENT_REGISTRATION_PENDING;
}
dm_event_handler_destroy(dmevh);
return evmask;
} }
/* FIXME This gets run while suspended and performs banned operations. */ /* FIXME This gets run while suspended and performs banned operations. */
static int _target_set_events(struct lv_segment *seg, static int _target_set_events(struct lv_segment *seg, int evmask, int set)
int evmask __attribute__((unused)), int set)
{ {
char *dso, *uuid; return target_register_events(seg->lv->vg->cmd, _get_mirror_dso_path(seg->lv->vg->cmd),
struct logical_volume *lv; seg->lv->lvid.s, evmask, set, 0);
struct volume_group *vg;
struct dm_event_handler *dmevh;
int r;
lv = seg->lv;
vg = lv->vg;
if (!_get_mirror_dso_path(vg->cmd, &dso))
return_0;
if (!(uuid = build_dm_uuid(vg->cmd->mem, lv->lvid.s, NULL)))
return_0;
if (!(dmevh = _create_dm_event_handler(uuid, dso, DM_EVENT_ALL_ERRORS)))
return_0;
r = set ? dm_event_register_handler(dmevh) : dm_event_unregister_handler(dmevh);
dm_event_handler_destroy(dmevh);
if (!r)
return_0;
log_info("%s %s for events", set ? "Monitored" : "Unmonitored", uuid);
return 1;
} }
static int _target_monitor_events(struct lv_segment *seg, int events) static int _target_monitor_events(struct lv_segment *seg, int events)
@ -710,7 +613,7 @@ static struct segtype_handler _mirrored_ops = {
.target_present = _mirrored_target_present, .target_present = _mirrored_target_present,
.check_transient_status = _mirrored_transient_status, .check_transient_status = _mirrored_transient_status,
#ifdef DMEVENTD #ifdef DMEVENTD
.target_monitored = _target_monitored, .target_monitored = _target_registered,
.target_monitor_events = _target_monitor_events, .target_monitor_events = _target_monitor_events,
.target_unmonitor_events = _target_unmonitor_events, .target_unmonitor_events = _target_unmonitor_events,
#endif #endif
@ -735,7 +638,12 @@ struct segment_type *init_segtype(struct cmd_context *cmd)
segtype->ops = &_mirrored_ops; segtype->ops = &_mirrored_ops;
segtype->name = "mirror"; segtype->name = "mirror";
segtype->private = NULL; segtype->private = NULL;
segtype->flags = SEG_AREAS_MIRRORED | SEG_MONITORED; segtype->flags = SEG_AREAS_MIRRORED;
#ifdef DMEVENTD
if (_get_mirror_dso_path(cmd))
segtype->flags |= SEG_MONITORED;
#endif
log_very_verbose("Initialised segtype: %s", segtype->name); log_very_verbose("Initialised segtype: %s", segtype->name);

View File

@ -417,6 +417,9 @@
/* Define to 1 if you have the <utmpx.h> header file. */ /* Define to 1 if you have the <utmpx.h> header file. */
#undef HAVE_UTMPX_H #undef HAVE_UTMPX_H
/* Define to 1 if you have the <valgrind/memcheck.h> header file. */
#undef HAVE_VALGRIND_MEMCHECK_H
/* Define to 1 if you have the `vfork' function. */ /* Define to 1 if you have the `vfork' function. */
#undef HAVE_VFORK #undef HAVE_VFORK
@ -522,6 +525,9 @@
/* Define to 1 to enable synchronisation with udev processing. */ /* Define to 1 to enable synchronisation with udev processing. */
#undef UDEV_SYNC_SUPPORT #undef UDEV_SYNC_SUPPORT
/* Enable a valgrind aware build of pool */
#undef VALGRIND_POOL
/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>, /* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
#define below would cause a syntax error. */ #define below would cause a syntax error. */

View File

@ -21,10 +21,7 @@
#include "config.h" #include "config.h"
#include "activate.h" #include "activate.h"
#include "str_list.h" #include "str_list.h"
#ifdef DMEVENTD #include "defaults.h"
# include "sharedlib.h"
# include "libdevmapper-event.h"
#endif
static const char *_snap_name(const struct lv_segment *seg) static const char *_snap_name(const struct lv_segment *seg)
{ {
@ -164,117 +161,25 @@ static int _snap_target_present(struct cmd_context *cmd,
} }
#ifdef DMEVENTD #ifdef DMEVENTD
static int _get_snapshot_dso_path(struct cmd_context *cmd, char **dso)
static const char *_get_snapshot_dso_path(struct cmd_context *cmd)
{ {
char *path; return get_monitor_dso_path(cmd, find_config_tree_str(cmd, "dmeventd/snapshot_library",
const char *libpath; DEFAULT_DMEVENTD_SNAPSHOT_LIB));
if (!(path = dm_pool_alloc(cmd->mem, PATH_MAX))) {
log_error("Failed to allocate dmeventd library path.");
return 0;
}
libpath = find_config_tree_str(cmd, "dmeventd/snapshot_library", NULL);
if (!libpath)
return 0;
get_shared_library_path(cmd, libpath, path, PATH_MAX);
*dso = path;
return 1;
}
static struct dm_event_handler *_create_dm_event_handler(const char *dmuuid,
const char *dso,
const int timeout,
enum dm_event_mask mask)
{
struct dm_event_handler *dmevh;
if (!(dmevh = dm_event_handler_create()))
return_0;
if (dm_event_handler_set_dso(dmevh, dso))
goto fail;
if (dm_event_handler_set_uuid(dmevh, dmuuid))
goto fail;
dm_event_handler_set_timeout(dmevh, timeout);
dm_event_handler_set_event_mask(dmevh, mask);
return dmevh;
fail:
dm_event_handler_destroy(dmevh);
return NULL;
} }
static int _target_registered(struct lv_segment *seg, int *pending) static int _target_registered(struct lv_segment *seg, int *pending)
{ {
char *dso, *uuid; return target_registered_with_dmeventd(seg->lv->vg->cmd, _get_snapshot_dso_path(seg->lv->vg->cmd),
struct logical_volume *lv; seg->cow->lvid.s, pending);
struct volume_group *vg;
enum dm_event_mask evmask = 0;
struct dm_event_handler *dmevh;
lv = seg->lv;
vg = lv->vg;
*pending = 0;
if (!_get_snapshot_dso_path(vg->cmd, &dso))
return_0;
if (!(uuid = build_dm_uuid(vg->cmd->mem, seg->cow->lvid.s, NULL)))
return_0;
if (!(dmevh = _create_dm_event_handler(uuid, dso, 0, DM_EVENT_ALL_ERRORS)))
return_0;
if (dm_event_get_registered_device(dmevh, 0)) {
dm_event_handler_destroy(dmevh);
return 0;
}
evmask = dm_event_handler_get_event_mask(dmevh);
if (evmask & DM_EVENT_REGISTRATION_PENDING) {
*pending = 1;
evmask &= ~DM_EVENT_REGISTRATION_PENDING;
}
dm_event_handler_destroy(dmevh);
return evmask;
} }
/* FIXME This gets run while suspended and performs banned operations. */ /* FIXME This gets run while suspended and performs banned operations. */
static int _target_set_events(struct lv_segment *seg, static int _target_set_events(struct lv_segment *seg, int evmask, int set)
int events __attribute__((unused)), int set)
{ {
char *dso, *uuid; /* FIXME Make timeout (10) configurable */
struct volume_group *vg = seg->lv->vg; return target_register_events(seg->lv->vg->cmd, _get_snapshot_dso_path(seg->lv->vg->cmd),
struct dm_event_handler *dmevh; seg->cow->lvid.s, evmask, set, 10);
int r;
if (!_get_snapshot_dso_path(vg->cmd, &dso))
return_0;
if (!(uuid = build_dm_uuid(vg->cmd->mem, seg->cow->lvid.s, NULL)))
return_0;
/* FIXME: make timeout configurable */
if (!(dmevh = _create_dm_event_handler(uuid, dso, 10,
DM_EVENT_ALL_ERRORS|DM_EVENT_TIMEOUT)))
return_0;
r = set ? dm_event_register_handler(dmevh) : dm_event_unregister_handler(dmevh);
dm_event_handler_destroy(dmevh);
if (!r)
return_0;
log_info("%s %s for events", set ? "Registered" : "Unregistered", uuid);
return 1;
} }
static int _target_register_events(struct lv_segment *seg, static int _target_register_events(struct lv_segment *seg,
@ -335,9 +240,6 @@ struct segment_type *init_segtype(struct cmd_context *cmd)
#endif #endif
{ {
struct segment_type *segtype = dm_malloc(sizeof(*segtype)); struct segment_type *segtype = dm_malloc(sizeof(*segtype));
#ifdef DMEVENTD
char *dso;
#endif
if (!segtype) if (!segtype)
return_NULL; return_NULL;
@ -349,7 +251,7 @@ struct segment_type *init_segtype(struct cmd_context *cmd)
segtype->flags = SEG_SNAPSHOT; segtype->flags = SEG_SNAPSHOT;
#ifdef DMEVENTD #ifdef DMEVENTD
if (_get_snapshot_dso_path(cmd, &dso)) if (_get_snapshot_dso_path(cmd))
segtype->flags |= SEG_MONITORED; segtype->flags |= SEG_MONITORED;
#endif #endif
log_very_verbose("Initialised segtype: %s", segtype->name); log_very_verbose("Initialised segtype: %s", segtype->name);

View File

@ -97,7 +97,7 @@ static int lvchange_monitoring(struct cmd_context *cmd,
if ((dmeventd_monitor_mode() != DMEVENTD_MONITOR_IGNORE) && if ((dmeventd_monitor_mode() != DMEVENTD_MONITOR_IGNORE) &&
!monitor_dev_for_events(cmd, lv, dmeventd_monitor_mode())) !monitor_dev_for_events(cmd, lv, dmeventd_monitor_mode()))
stack; return_0;
return 1; return 1;
} }

View File

@ -15,14 +15,17 @@
#include "tools.h" #include "tools.h"
/*
* Increments *count by the number of _new_ monitored devices.
*/
static int _monitor_lvs_in_vg(struct cmd_context *cmd, static int _monitor_lvs_in_vg(struct cmd_context *cmd,
struct volume_group *vg, int reg) struct volume_group *vg, int reg, int *count)
{ {
struct lv_list *lvl; struct lv_list *lvl;
struct logical_volume *lv; struct logical_volume *lv;
struct lvinfo info; struct lvinfo info;
int lv_active; int lv_active;
int count = 0; int r = ECMD_PROCESSED;
dm_list_iterate_items(lvl, &vg->lvs) { dm_list_iterate_items(lvl, &vg->lvs) {
lv = lvl->lv; lv = lvl->lv;
@ -39,16 +42,13 @@ static int _monitor_lvs_in_vg(struct cmd_context *cmd,
continue; continue;
if (!monitor_dev_for_events(cmd, lv, reg)) { if (!monitor_dev_for_events(cmd, lv, reg)) {
r = ECMD_FAILED;
continue; continue;
} else } else
count++; (*count)++;
} }
/* return r;
* returns the number of _new_ monitored devices
*/
return count;
} }
static int _poll_lvs_in_vg(struct cmd_context *cmd, static int _poll_lvs_in_vg(struct cmd_context *cmd,
@ -160,17 +160,18 @@ static int _activate_lvs_in_vg(struct cmd_context *cmd,
static int _vgchange_monitoring(struct cmd_context *cmd, struct volume_group *vg) static int _vgchange_monitoring(struct cmd_context *cmd, struct volume_group *vg)
{ {
int monitored; int ret_max = ECMD_PROCESSED;
int monitored = 0;
if (lvs_in_vg_activated(vg) && if (lvs_in_vg_activated(vg) &&
dmeventd_monitor_mode() != DMEVENTD_MONITOR_IGNORE) { dmeventd_monitor_mode() != DMEVENTD_MONITOR_IGNORE) {
monitored = _monitor_lvs_in_vg(cmd, vg, dmeventd_monitor_mode()); ret_max = max(ret_max, _monitor_lvs_in_vg(cmd, vg, dmeventd_monitor_mode(), &monitored));
log_print("%d logical volume(s) in volume group " log_print("%d logical volume(s) in volume group "
"\"%s\" %smonitored", "\"%s\" %smonitored",
monitored, vg->name, (dmeventd_monitor_mode()) ? "" : "un"); monitored, vg->name, (dmeventd_monitor_mode()) ? "" : "un");
} }
return ECMD_PROCESSED; return ret_max;
} }
static int _vgchange_background_polling(struct cmd_context *cmd, struct volume_group *vg) static int _vgchange_background_polling(struct cmd_context *cmd, struct volume_group *vg)
@ -190,7 +191,7 @@ static int _vgchange_background_polling(struct cmd_context *cmd, struct volume_g
static int _vgchange_available(struct cmd_context *cmd, struct volume_group *vg) static int _vgchange_available(struct cmd_context *cmd, struct volume_group *vg)
{ {
int lv_open, active, monitored; int lv_open, active, monitored;
int available, ret; int available, ret_max = ECMD_PROCESSED;
int activate = 1; int activate = 1;
/* /*
@ -219,7 +220,7 @@ static int _vgchange_available(struct cmd_context *cmd, struct volume_group *vg)
log_verbose("%d logical volume(s) in volume group \"%s\" " log_verbose("%d logical volume(s) in volume group \"%s\" "
"already active", active, vg->name); "already active", active, vg->name);
if (dmeventd_monitor_mode() != DMEVENTD_MONITOR_IGNORE) { if (dmeventd_monitor_mode() != DMEVENTD_MONITOR_IGNORE) {
monitored = _monitor_lvs_in_vg(cmd, vg, dmeventd_monitor_mode()); ret_max = max(ret_max, _monitor_lvs_in_vg(cmd, vg, dmeventd_monitor_mode(), &monitored));
log_verbose("%d existing logical volume(s) in volume " log_verbose("%d existing logical volume(s) in volume "
"group \"%s\" %smonitored", "group \"%s\" %smonitored",
monitored, vg->name, monitored, vg->name,
@ -227,13 +228,13 @@ static int _vgchange_available(struct cmd_context *cmd, struct volume_group *vg)
} }
} }
ret = _activate_lvs_in_vg(cmd, vg, available); ret_max = max(ret_max, _activate_lvs_in_vg(cmd, vg, available));
/* Print message only if there was not found a missing VG */ /* Print message only if there was not found a missing VG */
if (!vg->cmd_missing_vgs) if (!vg->cmd_missing_vgs)
log_print("%d logical volume(s) in volume group \"%s\" now active", log_print("%d logical volume(s) in volume group \"%s\" now active",
lvs_in_vg_activated(vg), vg->name); lvs_in_vg_activated(vg), vg->name);
return ret; return ret_max;
} }
static int _vgchange_alloc(struct cmd_context *cmd, struct volume_group *vg) static int _vgchange_alloc(struct cmd_context *cmd, struct volume_group *vg)