mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
Add mirror dmeventd library
This commit is contained in:
parent
c6b966c8ee
commit
06f62ad1e4
11
Makefile.in
11
Makefile.in
@ -24,8 +24,13 @@ endif
|
||||
|
||||
SUBDIRS += lib tools daemons
|
||||
|
||||
ifeq ("@DMEVENTD@", "yes")
|
||||
SUBDIRS += dmeventd
|
||||
endif
|
||||
|
||||
ifeq ($(MAKECMDGOALS),distclean)
|
||||
SUBDIRS += daemons/clvmd \
|
||||
dmeventd \
|
||||
lib/format1 \
|
||||
lib/format_pool \
|
||||
lib/locking \
|
||||
@ -40,13 +45,15 @@ include make.tmpl
|
||||
daemons: lib
|
||||
lib: include
|
||||
tools: lib
|
||||
po: tools daemons
|
||||
dmeventd: tools
|
||||
po: tools daemons dmeventd
|
||||
|
||||
ifeq ("@INTL@", "yes")
|
||||
lib.pofile: include.pofile
|
||||
tools.pofile: lib.pofile
|
||||
daemons.pofile: lib.pofile
|
||||
po.pofile: tools.pofile daemons.pofile
|
||||
dmeventd.pofile: tools.pofile
|
||||
po.pofile: tools.pofile daemons.pofile dmeventd.pofile
|
||||
pofile: po.pofile
|
||||
endif
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
Version 2.02.02
|
||||
Version 2.02.02 -
|
||||
====================================
|
||||
Add mirror dmeventd library.
|
||||
Add some activation logic to remove_mirror_images().
|
||||
lvconvert can remove specified PVs from a mirror.
|
||||
lvconvert turns an existing LV into a mirror.
|
||||
|
33
configure
vendored
33
configure
vendored
@ -310,7 +310,7 @@ ac_includes_default="\
|
||||
#endif"
|
||||
|
||||
ac_default_prefix=/usr
|
||||
ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os AWK CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN_S SET_MAKE RANLIB ac_ct_RANLIB CPP EGREP ALLOCA LIBOBJS POW_LIB MSGFMT MODPROBE_CMD JOBS STATIC_LINK LVM1 POOL SNAPSHOTS MIRRORS OWNER GROUP COPTIMISE_FLAG CLDFLAGS CLDWHOLEARCHIVE CLDNOWHOLEARCHIVE LDDEPS SOFLAG LVM_VERSION LVM1_FALLBACK DEBUG DEVMAPPER HAVE_LIBDL HAVE_SELINUX CMDLIB LOCALEDIR CONFDIR STATICDIR INTL_PACKAGE INTL CLVMD CLUSTER FSADM LTLIBOBJS'
|
||||
ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os AWK CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN_S SET_MAKE RANLIB ac_ct_RANLIB CPP EGREP ALLOCA LIBOBJS POW_LIB MSGFMT MODPROBE_CMD JOBS STATIC_LINK LVM1 POOL SNAPSHOTS MIRRORS OWNER GROUP COPTIMISE_FLAG CLDFLAGS CLDWHOLEARCHIVE CLDNOWHOLEARCHIVE LDDEPS SOFLAG LVM_VERSION LVM1_FALLBACK DEBUG DEVMAPPER HAVE_LIBDL HAVE_SELINUX CMDLIB LOCALEDIR CONFDIR STATICDIR INTL_PACKAGE INTL CLVMD CLUSTER FSADM DMEVENTD LTLIBOBJS'
|
||||
ac_subst_files=''
|
||||
|
||||
# Initialize some variables set by options.
|
||||
@ -858,6 +858,7 @@ Optional Features:
|
||||
--disable-o_direct Disable O_DIRECT
|
||||
--enable-cmdlib Build shared command library
|
||||
--enable-fsadm Enable fsadm
|
||||
--enable-dmeventd Enable dmeventd
|
||||
--enable-nls Enable Native Language Support
|
||||
|
||||
Optional Packages:
|
||||
@ -7428,6 +7429,25 @@ fi;
|
||||
echo "$as_me:$LINENO: result: $FSADM" >&5
|
||||
echo "${ECHO_T}$FSADM" >&6
|
||||
|
||||
################################################################################
|
||||
echo "$as_me:$LINENO: checking whether to use dmeventd" >&5
|
||||
echo $ECHO_N "checking whether to use dmeventd... $ECHO_C" >&6
|
||||
# Check whether --enable-dmeventd or --disable-dmeventd was given.
|
||||
if test "${enable_dmeventd+set}" = set; then
|
||||
enableval="$enable_dmeventd"
|
||||
DMEVENTD=$enableval
|
||||
fi;
|
||||
echo "$as_me:$LINENO: result: $DMEVENTD" >&5
|
||||
echo "${ECHO_T}$DMEVENTD" >&6
|
||||
|
||||
if test x$DMEVENTD = xyes && test x$MIRRORS != xinternal; then
|
||||
{ { echo "$as_me:$LINENO: error: --enable-dmeventd currently requires --with-mirrors=internal
|
||||
" >&5
|
||||
echo "$as_me: error: --enable-dmeventd currently requires --with-mirrors=internal
|
||||
" >&2;}
|
||||
{ (exit 1); exit 1; }; }
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
if [ "x$exec_prefix" = xNONE -a "x$prefix" = xNONE ];
|
||||
then exec_prefix="";
|
||||
@ -10853,10 +10873,11 @@ fi
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
################################################################################
|
||||
ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile doc/Makefile include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/snapshot/Makefile man/Makefile po/Makefile tools/Makefile tools/version.h tools/fsadm/Makefile test/mm/Makefile test/device/Makefile test/format1/Makefile test/regex/Makefile test/filters/Makefile"
|
||||
ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile dmeventd/Makefile dmeventd/mirror/Makefile doc/Makefile include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/snapshot/Makefile man/Makefile po/Makefile tools/Makefile tools/version.h tools/fsadm/Makefile test/mm/Makefile test/device/Makefile test/format1/Makefile test/regex/Makefile test/filters/Makefile"
|
||||
cat >confcache <<\_ACEOF
|
||||
# This file is a shell script that caches the results of configure
|
||||
# tests run on this system so they can be shared between configure
|
||||
@ -11412,6 +11433,8 @@ do
|
||||
"make.tmpl" ) CONFIG_FILES="$CONFIG_FILES make.tmpl" ;;
|
||||
"daemons/Makefile" ) CONFIG_FILES="$CONFIG_FILES daemons/Makefile" ;;
|
||||
"daemons/clvmd/Makefile" ) CONFIG_FILES="$CONFIG_FILES daemons/clvmd/Makefile" ;;
|
||||
"dmeventd/Makefile" ) CONFIG_FILES="$CONFIG_FILES dmeventd/Makefile" ;;
|
||||
"dmeventd/mirror/Makefile" ) CONFIG_FILES="$CONFIG_FILES dmeventd/mirror/Makefile" ;;
|
||||
"doc/Makefile" ) CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;;
|
||||
"include/Makefile" ) CONFIG_FILES="$CONFIG_FILES include/Makefile" ;;
|
||||
"lib/Makefile" ) CONFIG_FILES="$CONFIG_FILES lib/Makefile" ;;
|
||||
@ -11576,6 +11599,7 @@ s,@INTL@,$INTL,;t t
|
||||
s,@CLVMD@,$CLVMD,;t t
|
||||
s,@CLUSTER@,$CLUSTER,;t t
|
||||
s,@FSADM@,$FSADM,;t t
|
||||
s,@DMEVENTD@,$DMEVENTD,;t t
|
||||
s,@LTLIBOBJS@,$LTLIBOBJS,;t t
|
||||
CEOF
|
||||
|
||||
@ -11855,3 +11879,8 @@ if test x$FSADM == xyes; then
|
||||
{ echo "$as_me:$LINENO: WARNING: fsadm support is untested" >&5
|
||||
echo "$as_me: WARNING: fsadm support is untested" >&2;}
|
||||
fi
|
||||
|
||||
if test x$DMEVENTD == xyes; then
|
||||
{ echo "$as_me:$LINENO: WARNING: dmeventd support is untested" >&5
|
||||
echo "$as_me: WARNING: dmeventd support is untested" >&2;}
|
||||
fi
|
||||
|
21
configure.in
21
configure.in
@ -355,6 +355,20 @@ AC_ARG_ENABLE(fsadm, [ --enable-fsadm Enable fsadm],
|
||||
FSADM=$enableval)
|
||||
AC_MSG_RESULT($FSADM)
|
||||
|
||||
################################################################################
|
||||
dnl -- enable dmeventd handling
|
||||
AC_MSG_CHECKING(whether to use dmeventd)
|
||||
AC_ARG_ENABLE(dmeventd, [ --enable-dmeventd Enable the device-mapper event daemon],
|
||||
DMEVENTD=$enableval)
|
||||
AC_MSG_RESULT($DMEVENTD)
|
||||
|
||||
dnl -- dmeventd currently requires internal mirror support
|
||||
if test x$DMEVENTD = xyes && test x$MIRRORS != xinternal; then
|
||||
AC_MSG_ERROR(
|
||||
--enable-dmeventd currently requires --with-mirrors=internal
|
||||
)
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Mess with default exec_prefix
|
||||
if [[ "x$exec_prefix" = xNONE -a "x$prefix" = xNONE ]];
|
||||
@ -563,6 +577,7 @@ AC_SUBST(INTL)
|
||||
AC_SUBST(CLVMD)
|
||||
AC_SUBST(CLUSTER)
|
||||
AC_SUBST(FSADM)
|
||||
AC_SUBST(DMEVENTD)
|
||||
|
||||
################################################################################
|
||||
dnl -- First and last lines should not contain files to generate in order to
|
||||
@ -572,6 +587,8 @@ Makefile \
|
||||
make.tmpl \
|
||||
daemons/Makefile \
|
||||
daemons/clvmd/Makefile \
|
||||
dmeventd/Makefile \
|
||||
dmeventd/mirror/Makefile \
|
||||
doc/Makefile \
|
||||
include/Makefile \
|
||||
lib/Makefile \
|
||||
@ -599,3 +616,7 @@ fi
|
||||
if test x$FSADM == xyes; then
|
||||
AC_MSG_WARN(fsadm support is untested)
|
||||
fi
|
||||
|
||||
if test x$DMEVENTD == xyes; then
|
||||
AC_MSG_WARN(dmeventd support is untested)
|
||||
fi
|
||||
|
22
daemons/dmeventd/plugins/Makefile.in
Normal file
22
daemons/dmeventd/plugins/Makefile.in
Normal file
@ -0,0 +1,22 @@
|
||||
#
|
||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
# Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of the LVM2.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
SUBDIRS += mirror
|
||||
|
||||
include $(top_srcdir)/make.tmpl
|
||||
|
3
daemons/dmeventd/plugins/mirror/.exported_symbols
Normal file
3
daemons/dmeventd/plugins/mirror/.exported_symbols
Normal file
@ -0,0 +1,3 @@
|
||||
process_event
|
||||
register_device
|
||||
unregister_device
|
32
daemons/dmeventd/plugins/mirror/Makefile.in
Normal file
32
daemons/dmeventd/plugins/mirror/Makefile.in
Normal file
@ -0,0 +1,32 @@
|
||||
#
|
||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
# Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of the LVM2.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
CFLAGS += -I${top_srcdir}/tools -I${top_srcdir}/include
|
||||
CLDFLAGS += -ldevmapper -llvm2cmd
|
||||
|
||||
SOURCES = dmeventd_mirror.c
|
||||
|
||||
LIB_SHARED = libdevmapper-event-lvm2mirror.so
|
||||
|
||||
include $(top_srcdir)/make.tmpl
|
||||
|
||||
install: libdevmapper-event-lvm2mirror.so
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
|
||||
$(libdir)/$<.$(LIB_VERSION)
|
||||
$(LN_S) -f $(libdir)/$<.$(LIB_VERSION) $(libdir)/$<
|
||||
|
311
daemons/dmeventd/plugins/mirror/dmeventd_mirror.c
Normal file
311
daemons/dmeventd/plugins/mirror/dmeventd_mirror.c
Normal file
@ -0,0 +1,311 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "libdevmapper.h"
|
||||
#include "libdevmapper-event.h"
|
||||
#include "lvm2cmd.h"
|
||||
#include "lvm-string.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* FIXME Replace syslog with multilog */
|
||||
#include <syslog.h>
|
||||
|
||||
#define ME_IGNORE 0
|
||||
#define ME_INSYNC 1
|
||||
#define ME_FAILURE 2
|
||||
|
||||
static int _get_mirror_event(char *params)
|
||||
{
|
||||
int i, rtn = ME_INSYNC;
|
||||
int max_args = 30; /* should support at least 8-way mirrors */
|
||||
char *args[max_args];
|
||||
char *dev_status_str;
|
||||
char *log_status_str;
|
||||
char *sync_str;
|
||||
char *p;
|
||||
int log_argc, num_devs, num_failures=0;
|
||||
|
||||
if (max_args <= split_words(params, max_args, args)) {
|
||||
syslog(LOG_ERR, "Unable to split mirror parameters: Arg list too long");
|
||||
return -E2BIG;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unused: 0 409600 mirror
|
||||
* Used : 2 253:4 253:5 400/400 1 AA 3 cluster 253:3 A
|
||||
*/
|
||||
num_devs = atoi(args[0]);
|
||||
dev_status_str = args[3 + num_devs];
|
||||
log_argc = atoi(args[4 + num_devs]);
|
||||
log_status_str = args[4 + num_devs + log_argc];
|
||||
sync_str = args[1 + num_devs];
|
||||
|
||||
syslog(LOG_DEBUG, " num_devs = %d", num_devs);
|
||||
syslog(LOG_DEBUG, " dev_status_str: %s", dev_status_str);
|
||||
syslog(LOG_DEBUG, " log_argc = %d", log_argc);
|
||||
syslog(LOG_DEBUG, " log_status_str: %s", log_status_str);
|
||||
syslog(LOG_DEBUG, " sync_str: %s", sync_str);
|
||||
|
||||
/* Check for bad mirror devices */
|
||||
for (i = 0; i < num_devs; i++) {
|
||||
if (dev_status_str[i] == 'D') {
|
||||
syslog(LOG_ERR, "Mirror device, %s, has failed.\n", args[i+1]);
|
||||
num_failures++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for bad log device */
|
||||
if (log_status_str[0] == 'D') {
|
||||
syslog(LOG_ERR, "Log device, %s, has failed.\n",
|
||||
args[3 + num_devs + log_argc]);
|
||||
num_failures++;
|
||||
}
|
||||
|
||||
if (num_failures) {
|
||||
rtn = ME_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for(p = strstr(sync_str, "/"), i = (p - sync_str) - 1;
|
||||
p && (i >= 0);
|
||||
i--) {
|
||||
syslog(LOG_DEBUG, "p[%d] (%c) ?= sync_str[%d] (%c)",
|
||||
i+1, p[i+1], i, sync_str[i]);
|
||||
if(p[i+1] != sync_str[i]){
|
||||
rtn = ME_IGNORE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return rtn;
|
||||
}
|
||||
|
||||
/* dmname_to_lvmname
|
||||
* @dmname: the device mapper name
|
||||
* @vg: the returned vg name
|
||||
* @lv: the returned lv name
|
||||
*
|
||||
* Caller must free strings when finished
|
||||
*
|
||||
* Returns: 0, -ENOMEM, -EINVAL
|
||||
*/
|
||||
|
||||
/* FIXME Replace with split_dm_name */
|
||||
|
||||
static int _dmname_to_lvmname(char *dmname, char **vg, char **lv)
|
||||
{
|
||||
int rtn = 0;
|
||||
char *ptr1, *ptr2;
|
||||
// syslog(LOG_DEBUG, "Entering dmname_to_lvmname\n");
|
||||
|
||||
for((ptr1 = dmname); (ptr2 = strstr(ptr1, "/")); ptr2++, (ptr1 = ptr2));
|
||||
for(; (ptr2 = strstr(ptr1, "-")) && (ptr2[1] == '-'); ptr2+=2, ptr1 = ptr2);
|
||||
|
||||
if (!ptr2)
|
||||
return -EINVAL;
|
||||
|
||||
ptr2[0] = '\0';
|
||||
if(!(*vg = strdup(ptr1))) {
|
||||
rtn = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ptr1 = ptr2+1;
|
||||
if(!(*lv = strdup(ptr1))) {
|
||||
rtn = -ENOMEM;
|
||||
free(*vg);
|
||||
}
|
||||
|
||||
fail:
|
||||
ptr2[0] = '-';
|
||||
|
||||
// syslog(LOG_DEBUG, "Exiting dmname_to_lvmname\n");
|
||||
return rtn;
|
||||
}
|
||||
|
||||
static void _temporary_log_fn(int level, const char *file, int line, const char *format)
|
||||
{
|
||||
syslog(LOG_DEBUG, "%s", format);
|
||||
}
|
||||
|
||||
static int _remove_failed_devices(const char *device)
|
||||
{
|
||||
int r;
|
||||
void *handle;
|
||||
int cmd_size = 256; /* FIXME Use system restriction */
|
||||
char cmd_str[cmd_size];
|
||||
char *vg = NULL, *lv = NULL;
|
||||
|
||||
// syslog(LOG_DEBUG, "Entering remove_failed_device\n");
|
||||
if (strlen(device) > 200)
|
||||
return -ENAMETOOLONG;
|
||||
|
||||
if ((r = _dmname_to_lvmname(device, &vg, &lv))) {
|
||||
syslog(LOG_ERR,
|
||||
"Unable to determine LVM name for %s",
|
||||
device);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* FIXME Is any sanity-checking required on %s? */
|
||||
syslog(LOG_INFO, "vgreduce --removemissing %s\n", vg);
|
||||
if (cmd_size <= snprintf(cmd_str, cmd_size, "vgreduce --removemissing %s", vg)) {
|
||||
/* this error should be caught above, but doesn't hurt to check again */
|
||||
syslog(LOG_ERR, "Unable to form LVM command: Device name too long");
|
||||
return -ENAMETOOLONG;
|
||||
}
|
||||
|
||||
lvm2_log_fn(_temporary_log_fn);
|
||||
handle = lvm2_init();
|
||||
lvm2_log_level(handle, 1);
|
||||
r = lvm2_run(handle, cmd_str);
|
||||
|
||||
syslog(LOG_INFO, "lvconvert -m0 %s/%s\n", vg, lv);
|
||||
if (cmd_size <= snprintf(cmd_str, cmd_size, "lvconvert -m0 %s/%s\n", vg, lv)) {
|
||||
/* this error should be caught above, but doesn't hurt to check again */
|
||||
syslog(LOG_ERR, "Unable to form LVM command: Device name too long");
|
||||
return -ENAMETOOLONG;
|
||||
}
|
||||
r = lvm2_run(handle, cmd_str);
|
||||
|
||||
// syslog(LOG_DEBUG, "Exiting remove_failed_device\n");
|
||||
|
||||
free(vg);
|
||||
free(lv);
|
||||
return (r == 1)? 0: -1;
|
||||
}
|
||||
|
||||
void process_event(const char *device, enum dm_event_type event)
|
||||
{
|
||||
int pid;
|
||||
struct dm_task *dmt;
|
||||
void *next = NULL;
|
||||
uint64_t start, length;
|
||||
char *target_type = NULL;
|
||||
char *params;
|
||||
|
||||
/* FIXME Too late to fork here under low memory! */
|
||||
/* FIXME This should run within a dmeventd thread instead. */
|
||||
pid = fork();
|
||||
if (pid > 0)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Fork twice to prevent the process from
|
||||
* becoming a zombie after exiting.
|
||||
*/
|
||||
pid = fork();
|
||||
if(pid > 0) {
|
||||
exit(EXIT_SUCCESS);
|
||||
} else if (pid < 0) {
|
||||
openlog("dmeventd (mirror_dso)", LOG_PID, LOG_DAEMON);
|
||||
syslog(LOG_ERR, "Fork new process to handle device failure");
|
||||
syslog(LOG_ERR, "Handling failure anyway (a harmless zombie process will result)");
|
||||
} else {
|
||||
setsid();
|
||||
openlog("dmeventd (mirror_dso)", LOG_PID, LOG_DAEMON);
|
||||
}
|
||||
|
||||
syslog(LOG_NOTICE, "An event occurred on %s\n", device);
|
||||
|
||||
/* FIXME Move inside libdevmapper */
|
||||
if (!(dmt = dm_task_create(DM_DEVICE_STATUS))) {
|
||||
syslog(LOG_ERR, "Unable to create dm_task.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!dm_task_set_name(dmt, device)) {
|
||||
syslog(LOG_ERR, "Unable to set device name.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!dm_task_run(dmt)) {
|
||||
syslog(LOG_ERR, "Unable to run task.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
do {
|
||||
next = dm_get_next_target(dmt, next, &start, &length,
|
||||
&target_type, ¶ms);
|
||||
|
||||
if (strcmp(target_type, "mirror")) {
|
||||
syslog(LOG_INFO, "%s has unmirrored portion.\n", device);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(_get_mirror_event(params)) {
|
||||
case ME_INSYNC:
|
||||
/* FIXME: all we really know is that this
|
||||
_part_ of the device is in sync
|
||||
Also, this is not an error
|
||||
*/
|
||||
syslog(LOG_NOTICE, "%s is now in-sync\n", device);
|
||||
break;
|
||||
case ME_FAILURE:
|
||||
syslog(LOG_ERR, "Device failure in %s\n", device);
|
||||
if (_remove_failed_devices(device))
|
||||
syslog(LOG_ERR, "Failed to remove faulty devices in %s\n",
|
||||
device);
|
||||
else
|
||||
syslog(LOG_NOTICE, "%s is now a linear device.\n",
|
||||
device);
|
||||
break;
|
||||
case ME_IGNORE:
|
||||
break;
|
||||
default:
|
||||
syslog(LOG_INFO, "Unknown event received.\n");
|
||||
}
|
||||
} while (next);
|
||||
|
||||
fail:
|
||||
if (dmt)
|
||||
dm_task_destroy(dmt);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int register_device(const char *device)
|
||||
{
|
||||
syslog(LOG_INFO, "[%s] %s(%d) - Device: %s\n",
|
||||
__FILE__, __func__, __LINE__, device);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int unregister_device(const char *device)
|
||||
{
|
||||
syslog(LOG_INFO, "[%s] %s(%d) - Device: %s\n",
|
||||
__FILE__, __func__, __LINE__, device);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Overrides for Emacs so that we follow Linus's tabbing style.
|
||||
* Emacs will notice this stuff at the end of the file and automatically
|
||||
* adjust the settings for this buffer only. This must remain at the end
|
||||
* of the file.
|
||||
* ---------------------------------------------------------------------------
|
||||
* Local variables:
|
||||
* c-file-style: "linux"
|
||||
* End:
|
||||
*/
|
22
dmeventd/Makefile.in
Normal file
22
dmeventd/Makefile.in
Normal file
@ -0,0 +1,22 @@
|
||||
#
|
||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
# Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of the LVM2.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
SUBDIRS += mirror
|
||||
|
||||
include $(top_srcdir)/make.tmpl
|
||||
|
3
dmeventd/mirror/.exported_symbols
Normal file
3
dmeventd/mirror/.exported_symbols
Normal file
@ -0,0 +1,3 @@
|
||||
process_event
|
||||
register_device
|
||||
unregister_device
|
32
dmeventd/mirror/Makefile.in
Normal file
32
dmeventd/mirror/Makefile.in
Normal file
@ -0,0 +1,32 @@
|
||||
#
|
||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
# Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of the LVM2.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
CFLAGS += -I${top_srcdir}/tools -I${top_srcdir}/include
|
||||
CLDFLAGS += -ldevmapper -llvm2cmd
|
||||
|
||||
SOURCES = dmeventd_mirror.c
|
||||
|
||||
LIB_SHARED = libdevmapper-event-lvm2mirror.so
|
||||
|
||||
include $(top_srcdir)/make.tmpl
|
||||
|
||||
install: libdevmapper-event-lvm2mirror.so
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
|
||||
$(libdir)/$<.$(LIB_VERSION)
|
||||
$(LN_S) -f $(libdir)/$<.$(LIB_VERSION) $(libdir)/$<
|
||||
|
311
dmeventd/mirror/dmeventd_mirror.c
Normal file
311
dmeventd/mirror/dmeventd_mirror.c
Normal file
@ -0,0 +1,311 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "libdevmapper.h"
|
||||
#include "libdevmapper-event.h"
|
||||
#include "lvm2cmd.h"
|
||||
#include "lvm-string.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* FIXME Replace syslog with multilog */
|
||||
#include <syslog.h>
|
||||
|
||||
#define ME_IGNORE 0
|
||||
#define ME_INSYNC 1
|
||||
#define ME_FAILURE 2
|
||||
|
||||
static int _get_mirror_event(char *params)
|
||||
{
|
||||
int i, rtn = ME_INSYNC;
|
||||
int max_args = 30; /* should support at least 8-way mirrors */
|
||||
char *args[max_args];
|
||||
char *dev_status_str;
|
||||
char *log_status_str;
|
||||
char *sync_str;
|
||||
char *p;
|
||||
int log_argc, num_devs, num_failures=0;
|
||||
|
||||
if (max_args <= split_words(params, max_args, args)) {
|
||||
syslog(LOG_ERR, "Unable to split mirror parameters: Arg list too long");
|
||||
return -E2BIG;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unused: 0 409600 mirror
|
||||
* Used : 2 253:4 253:5 400/400 1 AA 3 cluster 253:3 A
|
||||
*/
|
||||
num_devs = atoi(args[0]);
|
||||
dev_status_str = args[3 + num_devs];
|
||||
log_argc = atoi(args[4 + num_devs]);
|
||||
log_status_str = args[4 + num_devs + log_argc];
|
||||
sync_str = args[1 + num_devs];
|
||||
|
||||
syslog(LOG_DEBUG, " num_devs = %d", num_devs);
|
||||
syslog(LOG_DEBUG, " dev_status_str: %s", dev_status_str);
|
||||
syslog(LOG_DEBUG, " log_argc = %d", log_argc);
|
||||
syslog(LOG_DEBUG, " log_status_str: %s", log_status_str);
|
||||
syslog(LOG_DEBUG, " sync_str: %s", sync_str);
|
||||
|
||||
/* Check for bad mirror devices */
|
||||
for (i = 0; i < num_devs; i++) {
|
||||
if (dev_status_str[i] == 'D') {
|
||||
syslog(LOG_ERR, "Mirror device, %s, has failed.\n", args[i+1]);
|
||||
num_failures++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for bad log device */
|
||||
if (log_status_str[0] == 'D') {
|
||||
syslog(LOG_ERR, "Log device, %s, has failed.\n",
|
||||
args[3 + num_devs + log_argc]);
|
||||
num_failures++;
|
||||
}
|
||||
|
||||
if (num_failures) {
|
||||
rtn = ME_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for(p = strstr(sync_str, "/"), i = (p - sync_str) - 1;
|
||||
p && (i >= 0);
|
||||
i--) {
|
||||
syslog(LOG_DEBUG, "p[%d] (%c) ?= sync_str[%d] (%c)",
|
||||
i+1, p[i+1], i, sync_str[i]);
|
||||
if(p[i+1] != sync_str[i]){
|
||||
rtn = ME_IGNORE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return rtn;
|
||||
}
|
||||
|
||||
/* dmname_to_lvmname
|
||||
* @dmname: the device mapper name
|
||||
* @vg: the returned vg name
|
||||
* @lv: the returned lv name
|
||||
*
|
||||
* Caller must free strings when finished
|
||||
*
|
||||
* Returns: 0, -ENOMEM, -EINVAL
|
||||
*/
|
||||
|
||||
/* FIXME Replace with split_dm_name */
|
||||
|
||||
static int _dmname_to_lvmname(char *dmname, char **vg, char **lv)
|
||||
{
|
||||
int rtn = 0;
|
||||
char *ptr1, *ptr2;
|
||||
// syslog(LOG_DEBUG, "Entering dmname_to_lvmname\n");
|
||||
|
||||
for((ptr1 = dmname); (ptr2 = strstr(ptr1, "/")); ptr2++, (ptr1 = ptr2));
|
||||
for(; (ptr2 = strstr(ptr1, "-")) && (ptr2[1] == '-'); ptr2+=2, ptr1 = ptr2);
|
||||
|
||||
if (!ptr2)
|
||||
return -EINVAL;
|
||||
|
||||
ptr2[0] = '\0';
|
||||
if(!(*vg = strdup(ptr1))) {
|
||||
rtn = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ptr1 = ptr2+1;
|
||||
if(!(*lv = strdup(ptr1))) {
|
||||
rtn = -ENOMEM;
|
||||
free(*vg);
|
||||
}
|
||||
|
||||
fail:
|
||||
ptr2[0] = '-';
|
||||
|
||||
// syslog(LOG_DEBUG, "Exiting dmname_to_lvmname\n");
|
||||
return rtn;
|
||||
}
|
||||
|
||||
static void _temporary_log_fn(int level, const char *file, int line, const char *format)
|
||||
{
|
||||
syslog(LOG_DEBUG, "%s", format);
|
||||
}
|
||||
|
||||
static int _remove_failed_devices(const char *device)
|
||||
{
|
||||
int r;
|
||||
void *handle;
|
||||
int cmd_size = 256; /* FIXME Use system restriction */
|
||||
char cmd_str[cmd_size];
|
||||
char *vg = NULL, *lv = NULL;
|
||||
|
||||
// syslog(LOG_DEBUG, "Entering remove_failed_device\n");
|
||||
if (strlen(device) > 200)
|
||||
return -ENAMETOOLONG;
|
||||
|
||||
if ((r = _dmname_to_lvmname(device, &vg, &lv))) {
|
||||
syslog(LOG_ERR,
|
||||
"Unable to determine LVM name for %s",
|
||||
device);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* FIXME Is any sanity-checking required on %s? */
|
||||
syslog(LOG_INFO, "vgreduce --removemissing %s\n", vg);
|
||||
if (cmd_size <= snprintf(cmd_str, cmd_size, "vgreduce --removemissing %s", vg)) {
|
||||
/* this error should be caught above, but doesn't hurt to check again */
|
||||
syslog(LOG_ERR, "Unable to form LVM command: Device name too long");
|
||||
return -ENAMETOOLONG;
|
||||
}
|
||||
|
||||
lvm2_log_fn(_temporary_log_fn);
|
||||
handle = lvm2_init();
|
||||
lvm2_log_level(handle, 1);
|
||||
r = lvm2_run(handle, cmd_str);
|
||||
|
||||
syslog(LOG_INFO, "lvconvert -m0 %s/%s\n", vg, lv);
|
||||
if (cmd_size <= snprintf(cmd_str, cmd_size, "lvconvert -m0 %s/%s\n", vg, lv)) {
|
||||
/* this error should be caught above, but doesn't hurt to check again */
|
||||
syslog(LOG_ERR, "Unable to form LVM command: Device name too long");
|
||||
return -ENAMETOOLONG;
|
||||
}
|
||||
r = lvm2_run(handle, cmd_str);
|
||||
|
||||
// syslog(LOG_DEBUG, "Exiting remove_failed_device\n");
|
||||
|
||||
free(vg);
|
||||
free(lv);
|
||||
return (r == 1)? 0: -1;
|
||||
}
|
||||
|
||||
void process_event(const char *device, enum dm_event_type event)
|
||||
{
|
||||
int pid;
|
||||
struct dm_task *dmt;
|
||||
void *next = NULL;
|
||||
uint64_t start, length;
|
||||
char *target_type = NULL;
|
||||
char *params;
|
||||
|
||||
/* FIXME Too late to fork here under low memory! */
|
||||
/* FIXME This should run within a dmeventd thread instead. */
|
||||
pid = fork();
|
||||
if (pid > 0)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Fork twice to prevent the process from
|
||||
* becoming a zombie after exiting.
|
||||
*/
|
||||
pid = fork();
|
||||
if(pid > 0) {
|
||||
exit(EXIT_SUCCESS);
|
||||
} else if (pid < 0) {
|
||||
openlog("dmeventd (mirror_dso)", LOG_PID, LOG_DAEMON);
|
||||
syslog(LOG_ERR, "Fork new process to handle device failure");
|
||||
syslog(LOG_ERR, "Handling failure anyway (a harmless zombie process will result)");
|
||||
} else {
|
||||
setsid();
|
||||
openlog("dmeventd (mirror_dso)", LOG_PID, LOG_DAEMON);
|
||||
}
|
||||
|
||||
syslog(LOG_NOTICE, "An event occurred on %s\n", device);
|
||||
|
||||
/* FIXME Move inside libdevmapper */
|
||||
if (!(dmt = dm_task_create(DM_DEVICE_STATUS))) {
|
||||
syslog(LOG_ERR, "Unable to create dm_task.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!dm_task_set_name(dmt, device)) {
|
||||
syslog(LOG_ERR, "Unable to set device name.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!dm_task_run(dmt)) {
|
||||
syslog(LOG_ERR, "Unable to run task.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
do {
|
||||
next = dm_get_next_target(dmt, next, &start, &length,
|
||||
&target_type, ¶ms);
|
||||
|
||||
if (strcmp(target_type, "mirror")) {
|
||||
syslog(LOG_INFO, "%s has unmirrored portion.\n", device);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(_get_mirror_event(params)) {
|
||||
case ME_INSYNC:
|
||||
/* FIXME: all we really know is that this
|
||||
_part_ of the device is in sync
|
||||
Also, this is not an error
|
||||
*/
|
||||
syslog(LOG_NOTICE, "%s is now in-sync\n", device);
|
||||
break;
|
||||
case ME_FAILURE:
|
||||
syslog(LOG_ERR, "Device failure in %s\n", device);
|
||||
if (_remove_failed_devices(device))
|
||||
syslog(LOG_ERR, "Failed to remove faulty devices in %s\n",
|
||||
device);
|
||||
else
|
||||
syslog(LOG_NOTICE, "%s is now a linear device.\n",
|
||||
device);
|
||||
break;
|
||||
case ME_IGNORE:
|
||||
break;
|
||||
default:
|
||||
syslog(LOG_INFO, "Unknown event received.\n");
|
||||
}
|
||||
} while (next);
|
||||
|
||||
fail:
|
||||
if (dmt)
|
||||
dm_task_destroy(dmt);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int register_device(const char *device)
|
||||
{
|
||||
syslog(LOG_INFO, "[%s] %s(%d) - Device: %s\n",
|
||||
__FILE__, __func__, __LINE__, device);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int unregister_device(const char *device)
|
||||
{
|
||||
syslog(LOG_INFO, "[%s] %s(%d) - Device: %s\n",
|
||||
__FILE__, __func__, __LINE__, device);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Overrides for Emacs so that we follow Linus's tabbing style.
|
||||
* Emacs will notice this stuff at the end of the file and automatically
|
||||
* adjust the settings for this buffer only. This must remain at the end
|
||||
* of the file.
|
||||
* ---------------------------------------------------------------------------
|
||||
* Local variables:
|
||||
* c-file-style: "linux"
|
||||
* End:
|
||||
*/
|
Loading…
Reference in New Issue
Block a user