mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
Add snapshot dmeventd library (enables dmeventd snapshot monitoring).
This commit is contained in:
parent
0ed230fa43
commit
67961c7c10
@ -1,5 +1,6 @@
|
|||||||
Version 2.02.30 -
|
Version 2.02.30 -
|
||||||
===================================
|
===================================
|
||||||
|
Add snapshot dmeventd library (enables dmeventd snapshot monitoring).
|
||||||
Prevent pvcreate from overwriting MDA-less PVs belonging to active VGs.
|
Prevent pvcreate from overwriting MDA-less PVs belonging to active VGs.
|
||||||
Fix a segfault if using pvs with --all argument. (2.02.29)
|
Fix a segfault if using pvs with --all argument. (2.02.29)
|
||||||
Update --uuid argument description in man pages.
|
Update --uuid argument description in man pages.
|
||||||
|
3
configure
vendored
3
configure
vendored
@ -11126,7 +11126,7 @@ fi
|
|||||||
|
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
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 test/Makefile man/Makefile po/Makefile scripts/Makefile tools/Makefile tools/version.h"
|
ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile dmeventd/Makefile dmeventd/mirror/Makefile dmeventd/snapshot/Makefile doc/Makefile include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/snapshot/Makefile test/Makefile man/Makefile po/Makefile scripts/Makefile tools/Makefile tools/version.h"
|
||||||
|
|
||||||
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
|
||||||
@ -11688,6 +11688,7 @@ do
|
|||||||
"daemons/clvmd/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/clvmd/Makefile" ;;
|
"daemons/clvmd/Makefile") CONFIG_FILES="$CONFIG_FILES daemons/clvmd/Makefile" ;;
|
||||||
"dmeventd/Makefile") CONFIG_FILES="$CONFIG_FILES dmeventd/Makefile" ;;
|
"dmeventd/Makefile") CONFIG_FILES="$CONFIG_FILES dmeventd/Makefile" ;;
|
||||||
"dmeventd/mirror/Makefile") CONFIG_FILES="$CONFIG_FILES dmeventd/mirror/Makefile" ;;
|
"dmeventd/mirror/Makefile") CONFIG_FILES="$CONFIG_FILES dmeventd/mirror/Makefile" ;;
|
||||||
|
"dmeventd/snapshot/Makefile" ) CONFIG_FILES="$CONFIG_FILES dmeventd/snapshot/Makefile" ;;
|
||||||
"doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;;
|
"doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;;
|
||||||
"include/Makefile") CONFIG_FILES="$CONFIG_FILES include/Makefile" ;;
|
"include/Makefile") CONFIG_FILES="$CONFIG_FILES include/Makefile" ;;
|
||||||
"lib/Makefile") CONFIG_FILES="$CONFIG_FILES lib/Makefile" ;;
|
"lib/Makefile") CONFIG_FILES="$CONFIG_FILES lib/Makefile" ;;
|
||||||
|
@ -642,6 +642,7 @@ daemons/Makefile
|
|||||||
daemons/clvmd/Makefile
|
daemons/clvmd/Makefile
|
||||||
dmeventd/Makefile
|
dmeventd/Makefile
|
||||||
dmeventd/mirror/Makefile
|
dmeventd/mirror/Makefile
|
||||||
|
dmeventd/snapshot/Makefile
|
||||||
doc/Makefile
|
doc/Makefile
|
||||||
include/Makefile
|
include/Makefile
|
||||||
lib/Makefile
|
lib/Makefile
|
||||||
|
@ -16,7 +16,7 @@ srcdir = @srcdir@
|
|||||||
top_srcdir = @top_srcdir@
|
top_srcdir = @top_srcdir@
|
||||||
VPATH = @srcdir@
|
VPATH = @srcdir@
|
||||||
|
|
||||||
SUBDIRS += mirror
|
SUBDIRS += mirror snapshot
|
||||||
|
|
||||||
include $(top_srcdir)/make.tmpl
|
include $(top_srcdir)/make.tmpl
|
||||||
|
|
||||||
|
36
daemons/dmeventd/plugins/snapshot/Makefile.in
Normal file
36
daemons/dmeventd/plugins/snapshot/Makefile.in
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
# Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
|
||||||
|
#
|
||||||
|
# This file is part of the LVM2.
|
||||||
|
#
|
||||||
|
# This copyrighted material is made available to anyone wishing to use,
|
||||||
|
# modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
# of the GNU General Public License v.2.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
|
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
srcdir = @srcdir@
|
||||||
|
top_srcdir = @top_srcdir@
|
||||||
|
VPATH = @srcdir@
|
||||||
|
|
||||||
|
INCLUDES += -I${top_srcdir}/tools
|
||||||
|
CLDFLAGS += -L${top_srcdir}/tools -ldevmapper -llvm2cmd
|
||||||
|
|
||||||
|
SOURCES = dmeventd_snapshot.c
|
||||||
|
|
||||||
|
ifeq ("@LIB_SUFFIX@","dylib")
|
||||||
|
LIB_SHARED = libdevmapper-event-lvm2snapshot.dylib
|
||||||
|
else
|
||||||
|
LIB_SHARED = libdevmapper-event-lvm2snapshot.so
|
||||||
|
endif
|
||||||
|
|
||||||
|
include $(top_srcdir)/make.tmpl
|
||||||
|
|
||||||
|
install: libdevmapper-event-lvm2snapshot.$(LIB_SUFFIX)
|
||||||
|
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
|
||||||
|
$(libdir)/$<.$(LIB_VERSION)
|
||||||
|
$(LN_S) -f $<.$(LIB_VERSION) $(libdir)/$<
|
||||||
|
|
223
daemons/dmeventd/plugins/snapshot/dmeventd_snapshot.c
Normal file
223
daemons/dmeventd/plugins/snapshot/dmeventd_snapshot.c
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2007-2008 Red Hat, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of LVM2.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU Lesser General Public License v.2.1.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "libdevmapper.h"
|
||||||
|
#include "libdevmapper-event.h"
|
||||||
|
#include "lvm2cmd.h"
|
||||||
|
#include "lvm-string.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <syslog.h> /* FIXME Replace syslog with multilog */
|
||||||
|
/* FIXME Missing openlog? */
|
||||||
|
|
||||||
|
/* First warning when snapshot is 80% full. */
|
||||||
|
#define WARNING_THRESH 80
|
||||||
|
/* Further warnings at 85%, 90% and 95% fullness. */
|
||||||
|
#define WARNING_STEP 5
|
||||||
|
|
||||||
|
static pthread_mutex_t _register_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Number of active registrations.
|
||||||
|
*/
|
||||||
|
static int _register_count = 0;
|
||||||
|
|
||||||
|
static struct dm_pool *_mem_pool = NULL;
|
||||||
|
static void *_lvm_handle = NULL;
|
||||||
|
|
||||||
|
struct snap_status {
|
||||||
|
int invalid;
|
||||||
|
int used;
|
||||||
|
int max;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Currently only one event can be processed at a time.
|
||||||
|
*/
|
||||||
|
static pthread_mutex_t _event_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
|
static void _temporary_log_fn(int level, const char *file,
|
||||||
|
int line, const char *format)
|
||||||
|
{
|
||||||
|
if (!strncmp(format, "WARNING: ", 9) && (level < 5))
|
||||||
|
syslog(LOG_CRIT, "%s", format);
|
||||||
|
else
|
||||||
|
syslog(LOG_DEBUG, "%s", format);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME possibly reconcile this with target_percent when we gain
|
||||||
|
access to regular LVM library here. */
|
||||||
|
static void _parse_snapshot_params(char *params, struct snap_status *stat)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
/*
|
||||||
|
* xx/xx -- fractions used/max
|
||||||
|
* Invalid -- snapshot invalidated
|
||||||
|
* Unknown -- status unknown
|
||||||
|
*/
|
||||||
|
stat->used = stat->max = 0;
|
||||||
|
|
||||||
|
if (!strncmp(params, "Invalid", 7)) {
|
||||||
|
stat->invalid = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When we return without setting non-zero max, the parent is
|
||||||
|
* responsible for reporting errors.
|
||||||
|
*/
|
||||||
|
if (!strncmp(params, "Unknown", 7))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!(p = strstr(params, "/")))
|
||||||
|
return;
|
||||||
|
|
||||||
|
*p = '\0';
|
||||||
|
p++;
|
||||||
|
|
||||||
|
stat->used = atoi(params);
|
||||||
|
stat->max = atoi(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* send unregister command to itself */
|
||||||
|
static void _unregister_self(struct dm_task *dmt)
|
||||||
|
{
|
||||||
|
const char *name = dm_task_get_name(dmt);
|
||||||
|
struct dm_event_handler *dmevh;
|
||||||
|
|
||||||
|
if (!(dmevh = dm_event_handler_create()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (dm_event_handler_set_dev_name(dmevh, name))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
dm_event_handler_set_event_mask(dmevh, DM_EVENT_ALL_ERRORS|DM_EVENT_TIMEOUT);
|
||||||
|
dm_event_unregister_handler(dmevh);
|
||||||
|
fail:
|
||||||
|
dm_event_handler_destroy(dmevh);
|
||||||
|
}
|
||||||
|
|
||||||
|
void process_event(struct dm_task *dmt, enum dm_event_mask event,
|
||||||
|
void **private)
|
||||||
|
{
|
||||||
|
void *next = NULL;
|
||||||
|
uint64_t start, length;
|
||||||
|
char *target_type = NULL;
|
||||||
|
char *params;
|
||||||
|
struct snap_status stat = { 0 };
|
||||||
|
const char *device = dm_task_get_name(dmt);
|
||||||
|
int percent, *percent_warning = (int*)private;
|
||||||
|
|
||||||
|
/* No longer monitoring, waiting for remove */
|
||||||
|
if (!*percent_warning)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (pthread_mutex_trylock(&_event_mutex)) {
|
||||||
|
syslog(LOG_NOTICE, "Another thread is handling an event. Waiting...");
|
||||||
|
pthread_mutex_lock(&_event_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
dm_get_next_target(dmt, next, &start, &length, &target_type, ¶ms);
|
||||||
|
if (!target_type)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
_parse_snapshot_params(params, &stat);
|
||||||
|
/*
|
||||||
|
* If the snapshot has been invalidated or we failed to parse
|
||||||
|
* the status string. Report the full status string to syslog.
|
||||||
|
*/
|
||||||
|
if (stat.invalid || !stat.max) {
|
||||||
|
syslog(LOG_ERR, "Snapshot %s changed state to: %s\n", device, params);
|
||||||
|
_unregister_self(dmt);
|
||||||
|
*percent_warning = 0;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
percent = 100 * stat.used / stat.max;
|
||||||
|
if (percent >= *percent_warning) {
|
||||||
|
syslog(LOG_WARNING, "Snapshot %s is now %i%% full.\n", device, percent);
|
||||||
|
/* Print warning on the next multiple of WARNING_STEP. */
|
||||||
|
*percent_warning = (percent / WARNING_STEP) * WARNING_STEP + WARNING_STEP;
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
pthread_mutex_unlock(&_event_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
int register_device(const char *device, const char *uuid, int major, int minor,
|
||||||
|
void **private)
|
||||||
|
{
|
||||||
|
int r = 0;
|
||||||
|
int *percent_warning = (int*)private;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&_register_mutex);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Need some space for allocations. 1024 should be more
|
||||||
|
* than enough for what we need (device mapper name splitting)
|
||||||
|
*/
|
||||||
|
if (!_mem_pool && !(_mem_pool = dm_pool_create("snapshot_dso", 1024)))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
*percent_warning = WARNING_THRESH; /* Print warning if snapshot is full */
|
||||||
|
|
||||||
|
if (!_lvm_handle) {
|
||||||
|
lvm2_log_fn(_temporary_log_fn);
|
||||||
|
if (!(_lvm_handle = lvm2_init())) {
|
||||||
|
dm_pool_destroy(_mem_pool);
|
||||||
|
_mem_pool = NULL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
lvm2_log_level(_lvm_handle, LVM2_LOG_SUPPRESS);
|
||||||
|
/* FIXME Temporary: move to dmeventd core */
|
||||||
|
lvm2_run(_lvm_handle, "_memlock_inc");
|
||||||
|
}
|
||||||
|
|
||||||
|
syslog(LOG_INFO, "Monitoring snapshot %s\n", device);
|
||||||
|
|
||||||
|
_register_count++;
|
||||||
|
r = 1;
|
||||||
|
|
||||||
|
out:
|
||||||
|
pthread_mutex_unlock(&_register_mutex);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int unregister_device(const char *device, const char *uuid, int major, int minor,
|
||||||
|
void **unused __attribute((unused)))
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&_register_mutex);
|
||||||
|
|
||||||
|
syslog(LOG_INFO, "No longer monitoring snapshot %s\n",
|
||||||
|
device);
|
||||||
|
|
||||||
|
if (!--_register_count) {
|
||||||
|
dm_pool_destroy(_mem_pool);
|
||||||
|
_mem_pool = NULL;
|
||||||
|
lvm2_run(_lvm_handle, "_memlock_dec");
|
||||||
|
lvm2_exit(_lvm_handle);
|
||||||
|
_lvm_handle = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&_register_mutex);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
@ -16,7 +16,7 @@ srcdir = @srcdir@
|
|||||||
top_srcdir = @top_srcdir@
|
top_srcdir = @top_srcdir@
|
||||||
VPATH = @srcdir@
|
VPATH = @srcdir@
|
||||||
|
|
||||||
SUBDIRS += mirror
|
SUBDIRS += mirror snapshot
|
||||||
|
|
||||||
include $(top_srcdir)/make.tmpl
|
include $(top_srcdir)/make.tmpl
|
||||||
|
|
||||||
|
36
dmeventd/snapshot/Makefile.in
Normal file
36
dmeventd/snapshot/Makefile.in
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
# Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
|
||||||
|
#
|
||||||
|
# This file is part of the LVM2.
|
||||||
|
#
|
||||||
|
# This copyrighted material is made available to anyone wishing to use,
|
||||||
|
# modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
# of the GNU General Public License v.2.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
|
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
srcdir = @srcdir@
|
||||||
|
top_srcdir = @top_srcdir@
|
||||||
|
VPATH = @srcdir@
|
||||||
|
|
||||||
|
INCLUDES += -I${top_srcdir}/tools
|
||||||
|
CLDFLAGS += -L${top_srcdir}/tools -ldevmapper -llvm2cmd
|
||||||
|
|
||||||
|
SOURCES = dmeventd_snapshot.c
|
||||||
|
|
||||||
|
ifeq ("@LIB_SUFFIX@","dylib")
|
||||||
|
LIB_SHARED = libdevmapper-event-lvm2snapshot.dylib
|
||||||
|
else
|
||||||
|
LIB_SHARED = libdevmapper-event-lvm2snapshot.so
|
||||||
|
endif
|
||||||
|
|
||||||
|
include $(top_srcdir)/make.tmpl
|
||||||
|
|
||||||
|
install: libdevmapper-event-lvm2snapshot.$(LIB_SUFFIX)
|
||||||
|
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
|
||||||
|
$(libdir)/$<.$(LIB_VERSION)
|
||||||
|
$(LN_S) -f $<.$(LIB_VERSION) $(libdir)/$<
|
||||||
|
|
223
dmeventd/snapshot/dmeventd_snapshot.c
Normal file
223
dmeventd/snapshot/dmeventd_snapshot.c
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2007-2008 Red Hat, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of LVM2.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU Lesser General Public License v.2.1.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "libdevmapper.h"
|
||||||
|
#include "libdevmapper-event.h"
|
||||||
|
#include "lvm2cmd.h"
|
||||||
|
#include "lvm-string.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <syslog.h> /* FIXME Replace syslog with multilog */
|
||||||
|
/* FIXME Missing openlog? */
|
||||||
|
|
||||||
|
/* First warning when snapshot is 80% full. */
|
||||||
|
#define WARNING_THRESH 80
|
||||||
|
/* Further warnings at 85%, 90% and 95% fullness. */
|
||||||
|
#define WARNING_STEP 5
|
||||||
|
|
||||||
|
static pthread_mutex_t _register_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Number of active registrations.
|
||||||
|
*/
|
||||||
|
static int _register_count = 0;
|
||||||
|
|
||||||
|
static struct dm_pool *_mem_pool = NULL;
|
||||||
|
static void *_lvm_handle = NULL;
|
||||||
|
|
||||||
|
struct snap_status {
|
||||||
|
int invalid;
|
||||||
|
int used;
|
||||||
|
int max;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Currently only one event can be processed at a time.
|
||||||
|
*/
|
||||||
|
static pthread_mutex_t _event_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
|
static void _temporary_log_fn(int level, const char *file,
|
||||||
|
int line, const char *format)
|
||||||
|
{
|
||||||
|
if (!strncmp(format, "WARNING: ", 9) && (level < 5))
|
||||||
|
syslog(LOG_CRIT, "%s", format);
|
||||||
|
else
|
||||||
|
syslog(LOG_DEBUG, "%s", format);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME possibly reconcile this with target_percent when we gain
|
||||||
|
access to regular LVM library here. */
|
||||||
|
static void _parse_snapshot_params(char *params, struct snap_status *stat)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
/*
|
||||||
|
* xx/xx -- fractions used/max
|
||||||
|
* Invalid -- snapshot invalidated
|
||||||
|
* Unknown -- status unknown
|
||||||
|
*/
|
||||||
|
stat->used = stat->max = 0;
|
||||||
|
|
||||||
|
if (!strncmp(params, "Invalid", 7)) {
|
||||||
|
stat->invalid = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When we return without setting non-zero max, the parent is
|
||||||
|
* responsible for reporting errors.
|
||||||
|
*/
|
||||||
|
if (!strncmp(params, "Unknown", 7))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!(p = strstr(params, "/")))
|
||||||
|
return;
|
||||||
|
|
||||||
|
*p = '\0';
|
||||||
|
p++;
|
||||||
|
|
||||||
|
stat->used = atoi(params);
|
||||||
|
stat->max = atoi(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* send unregister command to itself */
|
||||||
|
static void _unregister_self(struct dm_task *dmt)
|
||||||
|
{
|
||||||
|
const char *name = dm_task_get_name(dmt);
|
||||||
|
struct dm_event_handler *dmevh;
|
||||||
|
|
||||||
|
if (!(dmevh = dm_event_handler_create()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (dm_event_handler_set_dev_name(dmevh, name))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
dm_event_handler_set_event_mask(dmevh, DM_EVENT_ALL_ERRORS|DM_EVENT_TIMEOUT);
|
||||||
|
dm_event_unregister_handler(dmevh);
|
||||||
|
fail:
|
||||||
|
dm_event_handler_destroy(dmevh);
|
||||||
|
}
|
||||||
|
|
||||||
|
void process_event(struct dm_task *dmt, enum dm_event_mask event,
|
||||||
|
void **private)
|
||||||
|
{
|
||||||
|
void *next = NULL;
|
||||||
|
uint64_t start, length;
|
||||||
|
char *target_type = NULL;
|
||||||
|
char *params;
|
||||||
|
struct snap_status stat = { 0 };
|
||||||
|
const char *device = dm_task_get_name(dmt);
|
||||||
|
int percent, *percent_warning = (int*)private;
|
||||||
|
|
||||||
|
/* No longer monitoring, waiting for remove */
|
||||||
|
if (!*percent_warning)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (pthread_mutex_trylock(&_event_mutex)) {
|
||||||
|
syslog(LOG_NOTICE, "Another thread is handling an event. Waiting...");
|
||||||
|
pthread_mutex_lock(&_event_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
dm_get_next_target(dmt, next, &start, &length, &target_type, ¶ms);
|
||||||
|
if (!target_type)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
_parse_snapshot_params(params, &stat);
|
||||||
|
/*
|
||||||
|
* If the snapshot has been invalidated or we failed to parse
|
||||||
|
* the status string. Report the full status string to syslog.
|
||||||
|
*/
|
||||||
|
if (stat.invalid || !stat.max) {
|
||||||
|
syslog(LOG_ERR, "Snapshot %s changed state to: %s\n", device, params);
|
||||||
|
_unregister_self(dmt);
|
||||||
|
*percent_warning = 0;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
percent = 100 * stat.used / stat.max;
|
||||||
|
if (percent >= *percent_warning) {
|
||||||
|
syslog(LOG_WARNING, "Snapshot %s is now %i%% full.\n", device, percent);
|
||||||
|
/* Print warning on the next multiple of WARNING_STEP. */
|
||||||
|
*percent_warning = (percent / WARNING_STEP) * WARNING_STEP + WARNING_STEP;
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
pthread_mutex_unlock(&_event_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
int register_device(const char *device, const char *uuid, int major, int minor,
|
||||||
|
void **private)
|
||||||
|
{
|
||||||
|
int r = 0;
|
||||||
|
int *percent_warning = (int*)private;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&_register_mutex);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Need some space for allocations. 1024 should be more
|
||||||
|
* than enough for what we need (device mapper name splitting)
|
||||||
|
*/
|
||||||
|
if (!_mem_pool && !(_mem_pool = dm_pool_create("snapshot_dso", 1024)))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
*percent_warning = WARNING_THRESH; /* Print warning if snapshot is full */
|
||||||
|
|
||||||
|
if (!_lvm_handle) {
|
||||||
|
lvm2_log_fn(_temporary_log_fn);
|
||||||
|
if (!(_lvm_handle = lvm2_init())) {
|
||||||
|
dm_pool_destroy(_mem_pool);
|
||||||
|
_mem_pool = NULL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
lvm2_log_level(_lvm_handle, LVM2_LOG_SUPPRESS);
|
||||||
|
/* FIXME Temporary: move to dmeventd core */
|
||||||
|
lvm2_run(_lvm_handle, "_memlock_inc");
|
||||||
|
}
|
||||||
|
|
||||||
|
syslog(LOG_INFO, "Monitoring snapshot %s\n", device);
|
||||||
|
|
||||||
|
_register_count++;
|
||||||
|
r = 1;
|
||||||
|
|
||||||
|
out:
|
||||||
|
pthread_mutex_unlock(&_register_mutex);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int unregister_device(const char *device, const char *uuid, int major, int minor,
|
||||||
|
void **unused __attribute((unused)))
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&_register_mutex);
|
||||||
|
|
||||||
|
syslog(LOG_INFO, "No longer monitoring snapshot %s\n",
|
||||||
|
device);
|
||||||
|
|
||||||
|
if (!--_register_count) {
|
||||||
|
dm_pool_destroy(_mem_pool);
|
||||||
|
_mem_pool = NULL;
|
||||||
|
lvm2_run(_lvm_handle, "_memlock_dec");
|
||||||
|
lvm2_exit(_lvm_handle);
|
||||||
|
_lvm_handle = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&_register_mutex);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
@ -384,10 +384,20 @@ activation {
|
|||||||
# dmeventd {
|
# dmeventd {
|
||||||
# mirror_library is the library used when monitoring a mirror device.
|
# mirror_library is the library used when monitoring a mirror device.
|
||||||
#
|
#
|
||||||
# "libdevmapper-event-lvm2mirror.so" attempts to recover from failures.
|
# "libdevmapper-event-lvm2mirror.so" attempts to recover from
|
||||||
# It removes failed devices from a volume group and reconfigures a
|
# failures. It removes failed devices from a volume group and
|
||||||
# mirror as necessary.
|
# reconfigures a mirror as necessary. If no mirror library is
|
||||||
#
|
# provided, mirrors are not monitored through dmeventd.
|
||||||
|
|
||||||
# mirror_library = "libdevmapper-event-lvm2mirror.so"
|
# mirror_library = "libdevmapper-event-lvm2mirror.so"
|
||||||
|
|
||||||
|
# snapshot_library is the library used when monitoring a snapshot device.
|
||||||
|
#
|
||||||
|
# "libdevmapper-event-lvm2snapshot.so" monitors the filling of
|
||||||
|
# snapshots and emits a warning through syslog, when the use of
|
||||||
|
# snapshot exceedes 80%. The warning is repeated when 85%, 90% and
|
||||||
|
# 95% of the snapshot are filled.
|
||||||
|
|
||||||
|
# snapshot_library = "libdevmapper-event-lvm2snapshot.so"
|
||||||
#}
|
#}
|
||||||
|
|
||||||
|
@ -669,7 +669,7 @@ int monitor_dev_for_events(struct cmd_context *cmd,
|
|||||||
#ifdef DMEVENTD
|
#ifdef DMEVENTD
|
||||||
int i, pending = 0, monitored;
|
int i, pending = 0, monitored;
|
||||||
int r = 1;
|
int r = 1;
|
||||||
struct list *tmp;
|
struct list *tmp, *snh, *snht;
|
||||||
struct lv_segment *seg;
|
struct lv_segment *seg;
|
||||||
int (*monitor_fn) (struct lv_segment *s, int e);
|
int (*monitor_fn) (struct lv_segment *s, int e);
|
||||||
|
|
||||||
@ -683,6 +683,29 @@ int monitor_dev_for_events(struct cmd_context *cmd,
|
|||||||
if (monitor && !dmeventd_monitor_mode())
|
if (monitor && !dmeventd_monitor_mode())
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In case of a snapshot device, we monitor lv->snapshot->lv,
|
||||||
|
* not the actual LV itself.
|
||||||
|
*/
|
||||||
|
if (lv_is_cow(lv))
|
||||||
|
return monitor_dev_for_events(cmd, lv->snapshot->lv, monitor);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In case this LV is a snapshot origin, we instead monitor
|
||||||
|
* each of its respective snapshots (the origin itself does
|
||||||
|
* not need to be monitored).
|
||||||
|
*
|
||||||
|
* TODO: This may change when snapshots of mirrors are allowed.
|
||||||
|
*/
|
||||||
|
if (lv_is_origin(lv)) {
|
||||||
|
list_iterate_safe(snh, snht, &lv->snapshot_segs)
|
||||||
|
if (!monitor_dev_for_events(
|
||||||
|
cmd, list_struct_base(snh,
|
||||||
|
struct lv_segment, origin_list)->cow, monitor))
|
||||||
|
r=0;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
list_iterate(tmp, &lv->segments) {
|
list_iterate(tmp, &lv->segments) {
|
||||||
seg = list_item(tmp, struct lv_segment);
|
seg = list_item(tmp, struct lv_segment);
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
|
* Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
|
||||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
* Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
|
||||||
*
|
*
|
||||||
* This file is part of LVM2.
|
* This file is part of LVM2.
|
||||||
*
|
*
|
||||||
@ -21,6 +21,10 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "activate.h"
|
#include "activate.h"
|
||||||
#include "str_list.h"
|
#include "str_list.h"
|
||||||
|
#ifdef DMEVENTD
|
||||||
|
# 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)
|
||||||
{
|
{
|
||||||
@ -125,6 +129,133 @@ static int _snap_target_present(const struct lv_segment *seg __attribute((unused
|
|||||||
|
|
||||||
return _snap_present;
|
return _snap_present;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DMEVENTD
|
||||||
|
static int _get_snapshot_dso_path(struct cmd_context *cmd, char **dso)
|
||||||
|
{
|
||||||
|
char *path;
|
||||||
|
const char *libpath;
|
||||||
|
|
||||||
|
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 *dmname,
|
||||||
|
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_dev_name(dmevh, dmname))
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
char *dso, *name;
|
||||||
|
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_snapshot_dso_path(vg->cmd, &dso))
|
||||||
|
return_0;
|
||||||
|
|
||||||
|
if (!(name = build_dm_name(vg->cmd->mem, vg->name, seg->cow->name, NULL)))
|
||||||
|
return_0;
|
||||||
|
|
||||||
|
if (!(dmevh = _create_dm_event_handler(name, 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. */
|
||||||
|
static int _target_set_events(struct lv_segment *seg, int events, int set)
|
||||||
|
{
|
||||||
|
char *dso, *name;
|
||||||
|
struct volume_group *vg = seg->lv->vg;
|
||||||
|
struct dm_event_handler *dmevh;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (!_get_snapshot_dso_path(vg->cmd, &dso))
|
||||||
|
return_0;
|
||||||
|
|
||||||
|
if (!(name = build_dm_name(vg->cmd->mem, vg->name, seg->cow->name, NULL)))
|
||||||
|
return_0;
|
||||||
|
|
||||||
|
/* FIXME: make timeout configurable */
|
||||||
|
if (!(dmevh = _create_dm_event_handler(name, 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", name);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _target_register_events(struct lv_segment *seg,
|
||||||
|
int events)
|
||||||
|
{
|
||||||
|
return _target_set_events(seg, events, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _target_unregister_events(struct lv_segment *seg,
|
||||||
|
int events)
|
||||||
|
{
|
||||||
|
return _target_set_events(seg, events, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* DMEVENTD */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int _snap_modules_needed(struct dm_pool *mem,
|
static int _snap_modules_needed(struct dm_pool *mem,
|
||||||
@ -151,6 +282,11 @@ static struct segtype_handler _snapshot_ops = {
|
|||||||
#ifdef DEVMAPPER_SUPPORT
|
#ifdef DEVMAPPER_SUPPORT
|
||||||
.target_percent = _snap_target_percent,
|
.target_percent = _snap_target_percent,
|
||||||
.target_present = _snap_target_present,
|
.target_present = _snap_target_present,
|
||||||
|
#ifdef DMEVENTD
|
||||||
|
.target_monitored = _target_registered,
|
||||||
|
.target_monitor_events = _target_register_events,
|
||||||
|
.target_unmonitor_events = _target_unregister_events,
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
.modules_needed = _snap_modules_needed,
|
.modules_needed = _snap_modules_needed,
|
||||||
.destroy = _snap_destroy,
|
.destroy = _snap_destroy,
|
||||||
@ -164,6 +300,7 @@ 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));
|
||||||
|
char *dso;
|
||||||
|
|
||||||
if (!segtype) {
|
if (!segtype) {
|
||||||
stack;
|
stack;
|
||||||
@ -176,6 +313,10 @@ struct segment_type *init_segtype(struct cmd_context *cmd)
|
|||||||
segtype->private = NULL;
|
segtype->private = NULL;
|
||||||
segtype->flags = SEG_SNAPSHOT;
|
segtype->flags = SEG_SNAPSHOT;
|
||||||
|
|
||||||
|
#ifdef DMEVENTD
|
||||||
|
if (_get_snapshot_dso_path(cmd, &dso))
|
||||||
|
segtype->flags |= SEG_MONITORED;
|
||||||
|
#endif
|
||||||
log_very_verbose("Initialised segtype: %s", segtype->name);
|
log_very_verbose("Initialised segtype: %s", segtype->name);
|
||||||
|
|
||||||
return segtype;
|
return segtype;
|
||||||
|
Loading…
Reference in New Issue
Block a user