[PATCH] 5/6: Add reconfiguration support module

Adam DiCarlo <[email protected]>
Newsgroups gmane.linux.ataraid
Message-ID <[email protected]>
Add reconfiguration support for adding and removing devices from RAID1
arrays.

Signed-off-by: Adam DiCarlo <[email protected]>
Signed-off-by: James Simshaw <[email protected]>
Signed-off-by: Darrick J. Wong <[email protected]>

_______________________________________________
Ataraid-list mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/ataraid-list
reconfig.patch (text/x-patch, 8.1 KB)
--- ORIGINAL/lib/reconfig/reconfig.c	1969-12-31 16:00:00.000000000 -0800
+++ PATCHED/lib/reconfig/reconfig.c	2006-08-29 13:55:33.000000000 -0700
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2006 IBM, all rights reserved.
+ * Written by Darrick Wong <[email protected]>,
+ * James Simshaw <[email protected]>, and
+ * Adam DiCarlo <[email protected]>
+ *
+ * See file LICENSE at the top of this source tree for license information.
+ */
+#include "internal.h"
+#include <errno.h>
+
+/* Add a device to a RAID1 set and start the resync */
+static int add_dev_to_raid1(struct lib_context *lc, struct raid_set *rs, struct raid_dev *rd)
+{
+	struct raid_dev *tmp;
+	struct list_head log;
+	struct change *entry;
+	int ret;
+
+	/* Init playback log */
+	INIT_LIST_HEAD(&log);
+
+	/* Add device to the raid set */
+	if (!(entry = dbg_malloc(sizeof (*entry)))) {
+		ret = -ENOMEM;
+		goto err;
+	}
+	entry->type = ADD_TO_SET;
+	entry->rs = rs;
+	entry->rd = rd;
+	list_add_tail(&entry->changes, &log);
+	list_add_tail(&rd->devs, &rs->devs);
+	rd->type = t_raid1;
+
+	/* Check that this is a sane configuration */
+	list_for_each_entry(tmp, &rs->devs, devs)
+		if (!tmp->fmt->check(lc, rs)) {
+			ret = -ENXIO;
+			goto err;
+		}
+
+	/* Write the metadata of the drive we're adding _first_ */
+	if (!(entry = dbg_malloc(sizeof (*entry)))) {
+		ret = -ENOMEM;
+		goto err;
+	}
+	entry->type = WRITE_METADATA;
+	entry->rd = rd;
+	list_add_tail(&entry->changes, &log);
+	ret = rd->fmt->write(lc, rd, 0);
+	if (!ret)
+		goto err;
+
+	/* Write metadatas of every device in the set */
+	list_for_each_entry(tmp, &rs->devs, devs) {
+		if (tmp == rd)
+			continue;
+		if (!(entry = dbg_malloc(sizeof (*entry)))) {
+			ret = -ENOMEM;
+			goto err;
+		}
+		entry->type = WRITE_METADATA;
+		entry->rd = tmp;
+		list_add_tail(&entry->changes, &log);
+		ret = tmp->fmt->write(lc, tmp, 0);
+		if (!ret)
+			goto err;
+	}
+
+	/* Reconfigure device mapper */
+	// FIXME: is nosync enough? rs->status |= s_inconsistent;
+	rs->status |= s_nosync;
+	change_set(lc, A_ACTIVATE, rs);
+	ret = change_set(lc, A_RELOAD, rs);
+	// FIXME: might need this later: change_set(lc, A_DEACTIVATE,rs);
+	if (!ret)
+		goto err;
+
+	/* End transaction */
+	end_log(lc, &log);
+	return 0;
+
+err:
+	revert_log(lc, &log);
+	return ret;
+}
+
+int nuke_spare(struct lib_context *lc, struct raid_dev *rd)
+{
+	printf("Nuking Spare\n");
+	list_del(&rd->devs);
+	return 0;
+}
+
+/* Add a disk to an array. */
+int add_dev_to_set(struct lib_context *lc, struct raid_set *rs, struct raid_dev *rd)
+{
+	struct {
+		enum change_type type;
+		int (*func) (struct lib_context *lc, struct raid_set *rs, struct raid_dev *rd);
+	} handlers[] = {
+		{t_raid1, add_dev_to_raid1},
+		{t_undef, NULL},
+	}, *h = handlers;
+
+	if(rd->type == t_spare)
+		nuke_spare(lc, rd);
+
+	if (rd->type != t_spare && rd->devs.next)
+		LOG_ERR(lc, -EBUSY, "Disk already in another set!");
+
+	if (rd->type == t_group)
+		LOG_ERR(lc, -EISDIR, "Can't add a group raid_dev to a raid_set.");
+
+	do {
+		if (h->type == rs->type)
+			return h->func(lc, rs, rd);
+	} while ((++h)->type != t_undef);
+
+	return 0;
+}
+
+/* Remove a disk from a raid1 */
+static int del_dev_in_raid1(struct lib_context *lc, struct raid_set *rs, struct raid_dev *rd)
+{
+	struct raid_dev *tmp;
+	struct list_head log;
+	struct change *entry;
+	int ret;
+
+	/* Init playback log */
+	INIT_LIST_HEAD(&log);
+
+	/* Remove device from the raid set */
+	if (!(entry = dbg_malloc(sizeof (*entry)))) {
+		ret = -ENOMEM;
+		goto err;
+	}
+	entry->type = DELETE_FROM_SET;
+	entry->rs = rs;
+	entry->rd = rd;
+	list_add_tail(&entry->changes, &log);
+	list_del(&rd->devs);
+	rd->type = t_spare;
+
+	/* Check that this is a sane configuration */
+	list_for_each_entry(tmp, &rs->devs, devs)
+		if (!tmp->fmt->check(lc, rs)) {
+			ret = -ENXIO;
+			goto err;
+		}
+
+	/* Write the metadata of the drive we're removing _first_ */
+	if (!(entry = dbg_malloc(sizeof (*entry)))) {
+		ret = -ENOMEM;
+		goto err;
+	}
+	entry->type = WRITE_METADATA;
+	entry->rd = rd;
+	list_add_tail(&entry->changes, &log);
+	ret = rd->fmt->write(lc, rd, 0);
+	if (!ret)
+		goto err;
+
+	/* Write metadatas of every device in the set */
+	list_for_each_entry(tmp, &rs->devs, devs) {
+		if (tmp == rd)
+			continue;
+		if (!(entry = dbg_malloc(sizeof (*entry)))) {
+			ret = -ENOMEM;
+			goto err;
+		}
+		entry->type = WRITE_METADATA;
+		entry->rd = tmp;
+		list_add_tail(&entry->changes, &log);
+		ret = tmp->fmt->write(lc, tmp, 0);
+		if (!ret)
+			goto err;
+	}
+
+	/* Reconfigure device mapper */
+	rs->status |= s_inconsistent;
+	rs->status |= s_nosync;
+	ret = change_set(lc, A_RELOAD, rs);
+	if (!ret)
+		goto err;
+
+	/* End transaction */
+	end_log(lc, &log);
+	return 0;
+
+err:
+	revert_log(lc, &log);
+	return ret;
+
+	return 0;
+}
+
+
+
+/* Remove a disk from an array */
+int del_dev_in_set(struct lib_context *lc, struct raid_set *rs, struct raid_dev *rd)
+{
+	struct {
+		enum change_type type;
+		int (*func) (struct lib_context *lc, struct raid_set *rs, struct raid_dev *rd);
+	} handlers[] = {
+		{t_raid1, del_dev_in_raid1},
+		{t_undef, NULL},
+	}, *h = handlers;
+
+	if (!(rd->devs.next))
+		LOG_ERR(lc, -EBUSY, "Disk is not in a set!");
+
+	/* FIXME: Not sure if this is true. */
+	if (rd->type == t_group)
+		LOG_ERR(lc, -EISDIR, "Can't remove a group raid_dev from a raid_set.");
+
+	do {
+		if (h->type == rs->type)
+			return h->func(lc, rs, rd);
+	} while ((++h)->type != t_undef);
+
+	return 0;
+}
--- ORIGINAL/include/dmraid/reconfig.h	1969-12-31 16:00:00.000000000 -0800
+++ PATCHED/include/dmraid/reconfig.h	2006-08-03 14:46:23.000000000 -0700
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2006 Darrick Wong, IBM.
+ *                    All rights reserved.
+ *
+ * See the file LICENSE at the top of this source tree for license information.
+ */
+
+#ifndef _RECONFIG_H_
+#define _RECONFIG_H_
+
+#include <dmraid/metadata.h>
+#include <dmraid/list.h>
+
+/* Type of change that a log entry describes */
+enum change_type {
+	ADD_TO_SET,
+	DELETE_FROM_SET,
+	WRITE_METADATA,
+	CREATE_CHILD_RD,
+	CREATE_RD,
+	DELETE_RD,
+	CREATE_RS,
+	DELETE_RS,
+	END_TRANSACTION
+};
+
+/* Change log entry */
+struct change {
+	struct list_head changes;	/* Chain of log entries */
+	enum change_type type;
+
+	/* All of these items may be listed as parameters */
+	struct raid_set *rs;
+	struct raid_dev *rd;
+
+	uint64_t offset;
+	uint64_t length;
+
+	struct dev_info *di;
+
+	char *name;
+};
+
+extern int add_dev_to_set(struct lib_context *lc, struct raid_set *rs, struct raid_dev *rd);
+extern int del_dev_in_set(struct lib_context *lc, struct raid_set *rs, struct raid_dev *rd);
+extern void end_log(struct lib_context *lc, struct list_head *log);
+extern int revert_log(struct lib_context *lc, struct list_head *log);
+
+#endif
--- ORIGINAL/lib/reconfig/log_ops.c	1969-12-31 16:00:00.000000000 -0800
+++ PATCHED/lib/reconfig/log_ops.c	2006-08-03 14:46:26.000000000 -0700
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2006 Darrick Wong, IBM
+ *                    All rights reserved.
+ *
+ * See file LICENSE at the top of this source tree for license information.
+ */
+#include "internal.h"
+
+void end_log(struct lib_context *lc, struct list_head *log)
+{
+	struct list_head *a, *b;
+
+	list_for_each_safe(a, b, log)
+		list_del(a);
+}
+
+int revert_log(struct lib_context *lc, struct list_head *log)
+{
+	struct change *entry;
+	struct raid_dev *rd;
+	int ret;
+	int writes_started = 0;
+
+	list_for_each_entry(entry, log, changes) {
+		if (writes_started && entry->type != WRITE_METADATA)
+			LOG_ERR(lc, 1, "State change after metadata write?");
+		if (entry->type == ADD_TO_SET) {
+			rd->type = t_spare;
+			list_del(&entry->rd->devs);
+		} else if (entry->type == WRITE_METADATA) {
+			writes_started = 1;
+			rd = entry->rd;
+			ret = rd->fmt->write(lc, rd, 0);
+			if (ret)
+				LOG_ERR(lc, ret, "Error while reverting metadata.");
+		}
+	}
+
+	return 0;
+}
--- ORIGINAL/lib/Makefile.in	2006-07-25 06:17:02.000000000 -0700
+++ PATCHED/lib/Makefile.in	2006-08-24 11:57:29.000000000 -0700
@@ -41,7 +41,9 @@ SOURCES=\
 	format/ddf/ddf1_crc.c \
 	format/ddf/ddf1_cvt.c \
 	format/ddf/ddf1_dump.c \
-	format/partition/dos.c
+	format/partition/dos.c \
+	reconfig/log_ops.c \
+	reconfig/reconfig.c
 
 OBJECTS=$(SOURCES:%.c=%.o)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.