diff options
author | Petr Rockai <prockai@redhat.com> | 2008-01-09 15:32:19 +0000 |
---|---|---|
committer | Petr Rockai <prockai@redhat.com> | 2008-01-09 15:32:19 +0000 |
commit | 67961c7c10bfa55fcff73624d601e5f23df7c322 (patch) | |
tree | 1f9de20f0b502b7490fc695cc14319a4b209e5a6 /lib/snapshot/snapshot.c | |
parent | 0ed230fa430c1d66a663e5258b8b5f7aadc19cbe (diff) | |
download | lvm2-67961c7c10bfa55fcff73624d601e5f23df7c322.tar.gz lvm2-67961c7c10bfa55fcff73624d601e5f23df7c322.tar.xz lvm2-67961c7c10bfa55fcff73624d601e5f23df7c322.zip |
Add snapshot dmeventd library (enables dmeventd snapshot monitoring).
Diffstat (limited to 'lib/snapshot/snapshot.c')
-rw-r--r-- | lib/snapshot/snapshot.c | 143 |
1 files changed, 142 insertions, 1 deletions
diff --git a/lib/snapshot/snapshot.c b/lib/snapshot/snapshot.c index 0e4a532d..94fecbee 100644 --- a/lib/snapshot/snapshot.c +++ b/lib/snapshot/snapshot.c @@ -1,6 +1,6 @@ /* * 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. * @@ -21,6 +21,10 @@ #include "config.h" #include "activate.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) { @@ -125,6 +129,133 @@ static int _snap_target_present(const struct lv_segment *seg __attribute((unused 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 static int _snap_modules_needed(struct dm_pool *mem, @@ -151,6 +282,11 @@ static struct segtype_handler _snapshot_ops = { #ifdef DEVMAPPER_SUPPORT .target_percent = _snap_target_percent, .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 .modules_needed = _snap_modules_needed, .destroy = _snap_destroy, @@ -164,6 +300,7 @@ struct segment_type *init_segtype(struct cmd_context *cmd) #endif { struct segment_type *segtype = dm_malloc(sizeof(*segtype)); + char *dso; if (!segtype) { stack; @@ -176,6 +313,10 @@ struct segment_type *init_segtype(struct cmd_context *cmd) segtype->private = NULL; 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); return segtype; |