[PATCH] 5/6: Add reconfiguration support module

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add reconfiguration support for adding and removing devices from RAID1
arrays.

Signed-off-by: Adam DiCarlo <bikko@xxxxxxxxxx>
Signed-off-by: James Simshaw <simshawj@xxxxxxxxxx>
Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx>




--- 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 <djwong@xxxxxxxxxx>,
+ * James Simshaw <simshawj@xxxxxxxxxx>, and
+ * Adam DiCarlo <bikko@xxxxxxxxxx>
+ *
+ * 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)
 



_______________________________________________
Ataraid-list mailing list
Ataraid-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/ataraid-list

[Index of Archives]     [Linux RAID]     [Linux Device Mapper]     [Linux IDE]     [Linux SCSI]     [Kernel]     [Linux Books]     [Linux Admin]     [GFS]     [RPM]     [Yosemite Campgrounds]     [AMD 64]

  Powered by Linux