* [RFC][PATCH 4/5] dmeventd filtering failed devices
@ 2009-09-30 0:28 Takahiro Yasui
0 siblings, 0 replies; only message in thread
From: Takahiro Yasui @ 2009-09-30 0:28 UTC (permalink / raw)
To: lvm-devel
This patch filters out failed devices from the device list to prevent
those failed devices from being accessed by lvm commands, lvconvert
and vgreduce.
Signed-off-by: Takahiro Yasui <tyasui@redhat.com>
---
daemons/dmeventd/plugins/mirror/dmeventd_mirror.c | 112 +++++++++++++++++++++-
libdm/.exported_symbols | 1
libdm/libdevmapper.h | 1
libdm/libdm-deptree.c | 39 +++++++
4 files changed, 151 insertions(+), 2 deletions(-)
Index: LVM2.02.54-20090928/daemons/dmeventd/plugins/mirror/dmeventd_mirror.c
===================================================================
--- LVM2.02.54-20090928.orig/daemons/dmeventd/plugins/mirror/dmeventd_mirror.c
+++ LVM2.02.54-20090928/daemons/dmeventd/plugins/mirror/dmeventd_mirror.c
@@ -14,6 +14,7 @@
#include "lvm2cmd.h"
#include "errors.h"
+#include "kdev_t.h"
#include <libdevmapper.h>
#include <libdevmapper-event.h>
@@ -42,10 +43,12 @@ struct device {
char *dname; /* device name (ex: /dev/sda) */
unsigned int major;
unsigned int minor;
+ int failed;
};
struct device_info {
struct dm_list dev_all; /* all devices in the vg */
+ struct dm_list dev_failed; /* failed devices */
char filter_str[CMD_SIZE];
};
@@ -85,6 +88,9 @@ static void _build_filter_str(struct dev
int len = 0, size, ct = 0;
dm_list_iterate_items(dev, &devi->dev_all) {
+ if (dev->failed)
+ continue;
+
size = dm_snprintf(devi->filter_str+len, CMD_SIZE-len,
"%s\"a|%s$|\"",
ct++ ? "," : "filter=[", dev->dname);
@@ -106,10 +112,107 @@ err:
return;
}
+/*
+ * Register major:minor number of failed device. This function assumes to be
+ * called at most 9 times (8 mirror legs + 1 mirror log) and memory should
+ * be allocated beforehand. (360 byte = 40 byte * 9 for now)
+ */
+static void _register_failed_device(struct device_info *devi, char *dev_str)
+{
+ unsigned int major, minor;
+ struct device *dev;
+
+ if (!devi)
+ return;
+
+ if (sscanf(dev_str, "%u:%u", &major, &minor) != 2) {
+ syslog(LOG_ERR, "Unrecognized device number (%s)\n",
+ dev_str);
+ return;
+ }
+
+ if (!(dev = dm_malloc(sizeof(*dev))))
+ return;
+
+ dev->major = major;
+ dev->minor = minor;
+
+ dm_list_add(&devi->dev_failed, &dev->list);
+}
+
+static void _release_failed_list(struct device_info *devi)
+{
+ struct device *dev, *devt;
+
+ if (!devi)
+ return;
+
+ dm_list_iterate_items_safe(dev, devt, &devi->dev_failed) {
+ dm_list_del(&dev->list);
+ dm_free(dev);
+ }
+}
+
+static void _mark_device_disabled(struct device_info *devi,
+ unsigned int major, unsigned int minor)
+{
+ struct device *dev;
+
+ dm_list_iterate_items(dev, &devi->dev_all) {
+ if (dev->major == major && dev->minor == minor)
+ dev->failed = 1;
+ }
+}
+
+static void _walk_tree_and_disable_devices(struct dm_tree_node *node,
+ struct device_info *devi)
+{
+ struct dm_tree_node *child;
+ void *handle = NULL;
+ const struct dm_info *info;
+
+ while ((child = dm_tree_next_child(&handle, node, 0))) {
+ if (dm_tree_node_num_children(child, 0))
+ _walk_tree_and_disable_devices(child, devi);
+ else {
+ info = dm_tree_node_get_info(child);
+ _mark_device_disabled(devi, info->major, info->minor);
+ }
+ }
+}
+
+static void _disable_devices(struct device_info *devi, struct dm_tree *dtree,
+ unsigned int major, unsigned int minor)
+{
+ struct dm_tree_node *node;
+
+ if (!(node = dm_tree_find_node(dtree, major, minor))) {
+ syslog(LOG_ERR, "device (%u:%u) doesn't exist.\n",
+ major, minor);
+ return;
+ }
+
+ _walk_tree_and_disable_devices(node, devi);
+}
+
static void _create_filter(struct device_info *devi)
{
+ struct dm_tree *dtree;
+ struct device *dev;
+
if (!devi)
return;
+
+ if (!(dtree = dm_build_deptree())) {
+ syslog(LOG_ERR, "Failed to get device information\n");
+ return;
+ }
+
+ dm_list_iterate_items(dev, &devi->dev_failed)
+ _disable_devices(devi, dtree, dev->major, dev->minor);
+
+ dm_tree_free(dtree);
+
_build_filter_str(devi);
}
@@ -119,7 +222,7 @@ static void _destroy_filter(struct devic
devi->filter_str[0] = '\0';
}
-static int _get_mirror_event(char *params)
+static int _get_mirror_event(char *params, struct device_info *devi)
{
int i, r = ME_INSYNC;
char **args = NULL;
@@ -160,6 +263,7 @@ static int _get_mirror_event(char *param
for (i = 0; i < num_devs; i++)
if (dev_status_str[i] == 'D') {
syslog(LOG_ERR, "Mirror device, %s, has failed.\n", args[i]);
+ _register_failed_device(devi, args[i]);
r = ME_FAILURE;
}
@@ -167,6 +271,7 @@ static int _get_mirror_event(char *param
if (log_argc > 1 && log_status_str[0] == 'D') {
syslog(LOG_ERR, "Log device, %s, has failed.\n",
args[2 + num_devs + log_argc]);
+ _register_failed_device(devi, args[2 + num_devs + log_argc]);
r = ME_FAILURE;
}
@@ -278,7 +383,7 @@ void process_event(struct dm_task *dmt,
continue;
}
- switch(_get_mirror_event(params)) {
+ switch(_get_mirror_event(params, devi)) {
case ME_INSYNC:
/* FIXME: all we really know is that this
_part_ of the device is in sync
@@ -304,6 +409,8 @@ void process_event(struct dm_task *dmt,
/* FIXME Provide value then! */
syslog(LOG_INFO, "Unknown event received.\n");
}
+
+ _release_failed_list(devi);
} while (next);
pthread_mutex_unlock(&_event_mutex);
@@ -355,6 +462,7 @@ static struct device_info *alloc_device_
return NULL;
dm_list_init(&devi->dev_all);
+ dm_list_init(&devi->dev_failed);
return devi;
}
Index: LVM2.02.54-20090928/libdm/.exported_symbols
===================================================================
--- LVM2.02.54-20090928.orig/libdm/.exported_symbols
+++ LVM2.02.54-20090928/libdm/.exported_symbols
@@ -81,6 +81,7 @@ dm_tree_skip_lockfs
dm_tree_use_no_flush_suspend
dm_tree_set_cookie
dm_tree_get_cookie
+dm_build_deptree
dm_is_dm_major
dm_mknodes
dm_malloc_aux
Index: LVM2.02.54-20090928/libdm/libdevmapper.h
===================================================================
--- LVM2.02.54-20090928.orig/libdm/libdevmapper.h
+++ LVM2.02.54-20090928/libdm/libdevmapper.h
@@ -435,6 +435,7 @@ void dm_tree_node_set_read_ahead(struct
void dm_tree_set_cookie(struct dm_tree_node *node, uint32_t cookie);
uint32_t dm_tree_get_cookie(struct dm_tree_node *node);
+struct dm_tree *dm_build_deptree(void);
/*****************************************************************************
* Library functions
Index: LVM2.02.54-20090928/libdm/libdm-deptree.c
===================================================================
--- LVM2.02.54-20090928.orig/libdm/libdm-deptree.c
+++ LVM2.02.54-20090928/libdm/libdm-deptree.c
@@ -1948,3 +1948,42 @@ uint32_t dm_tree_get_cookie(struct dm_tr
{
return node->dtree->cookie;
}
+
+struct dm_tree *dm_build_deptree(void)
+{
+ struct dm_tree *dtree;
+ struct dm_names *names;
+ struct dm_task *dmt = NULL;
+ unsigned next = 0;
+
+ if (!(dtree = dm_tree_create()))
+ return NULL;
+
+ if (!(dmt = dm_task_create(DM_DEVICE_LIST)))
+ goto err;
+
+ if (!dm_task_run(dmt))
+ goto err;
+
+ if (!(names = dm_task_get_names(dmt)))
+ goto err;
+
+ if (!names->dev)
+ goto err;
+
+ do {
+ names = (void *)names + next;
+ if (!dm_tree_add_dev(dtree,
+ (unsigned)MAJOR(names->dev),
+ (unsigned)MINOR(names->dev)))
+ goto err;
+ next = names->next;
+ } while (next);
+
+ return dtree;
+err:
+ if (dmt)
+ dm_task_destroy(dmt);
+ dm_tree_free(dtree);
+ return NULL;
+}
--
Takahiro Yasui
Hitachi Computer Products (America), Inc.
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2009-09-30 0:28 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-09-30 0:28 [RFC][PATCH 4/5] dmeventd filtering failed devices Takahiro Yasui
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.