[PATCH] 1/4: Support multiple raid_devs per physical device

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

 



Hi again,

These are preliminary patches to modify dmraid so that we can have
multiple raid_dev structures per physical device.  The DDF1
specification allows for a disk to participate in multiple RAID arrays,
which is what is gained from these patches.  They've been tested against
2.6.16.19 + dmraid45 on Ubuntu 6.06, and seem to be pretty stable.  At
this stage, I'm looking for comments about the code because it touches
core dmraid code and could (but shouldn't) break support for hardware
that I don't have.

This next patch modifies the dmraid core code.  More specifically:

- setup_rd takes a new parameter "num", which is the number of raid_devs
that have already been initialized by setup_rd for the given device.
Or, it's a zero-based index of the current raid_dev that we're
processing for a given dev_info.

- read_raid_dev now takes a new parameter "f_num_disks".  This function
returns the number of raid_devs that should be created given a chunk of
metadata.  If this parameter is NULL then 1 is assumed.  The function
creates an n-element headless list of raid_devs for the device and calls
 setup_rd on each element.

- Adds a flag is_clone to raid_dev.  If this flag is 1, the structs
pointed to by this raid_dev are owned by another raid_dev.  If 0 (the
default), then this raid_dev owns them and can delete them.

- Modifies free_raid_dev to not free pointers of cloned devices.

- Adds a function clone_raid_dev to copy data from one raid_dev to
another and set the is_clone flag.

- Adds a function find_raid_dev_in_chain that finds a raid_dev that
points to a given dev_info.  This is useful in setup_rd when one wants
to find the first raid_dev for this device for cloning purposes.

- Modifies discover_raid_devices and dmraid_read to do the right thing
with a headless list of raid_devs.

--D

Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx>
diff -Naurp v11.orig/include/dmraid/format.h v11-mdisk3/include/dmraid/format.h
--- v11.orig/include/dmraid/format.h	2006-01-19 02:38:24.000000000 -0800
+++ v11-mdisk3/include/dmraid/format.h	2006-05-25 11:19:09.000000000 -0700
@@ -149,8 +149,9 @@ struct raid_dev *read_raid_dev(
 				void *meta),
 	int (*f_setup_rd)(struct lib_context *lc, struct raid_dev *rd,
 			  struct dev_info *di, void *meta,
-			  union read_info *info),
-	const char *handler);
+			  union read_info *info, unsigned int num),
+	const char *handler,
+	unsigned int (*f_num_disks)(struct lib_context *lc, void *meta));
 
 extern void *alloc_meta_areas(struct lib_context *lc, struct raid_dev *rd,
 			      const char *who, unsigned int n);
diff -Naurp v11.orig/include/dmraid/metadata.h v11-mdisk3/include/dmraid/metadata.h
--- v11.orig/include/dmraid/metadata.h	2006-03-23 04:32:00.000000000 -0800
+++ v11-mdisk3/include/dmraid/metadata.h	2006-06-01 11:06:21.000000000 -0700
@@ -134,6 +134,11 @@ struct raid_dev {
 	uint64_t	offset;		/* Data offset on device. */
 	uint64_t	sectors;	/* Length of the segment to map. */
 
+	int		is_clone;	/* If this is a clone of another
+					 * raid_dev, we don't own any of the
+					 * pointer fields and mustn't try to
+					 * free them. */
+
 	unsigned int	areas;		/* # of metadata areas on the device. */
 	struct meta_areas *meta_areas;	/* Dynamic array of metadata areas. */
 
@@ -205,6 +210,8 @@ extern struct dev_info *alloc_dev_info(s
 extern void free_dev_info(struct lib_context *lc, struct dev_info *di);
 extern struct raid_dev *alloc_raid_dev(struct lib_context *lc, const char *who);
 extern void free_raid_dev(struct lib_context *lc, struct raid_dev **rd);
+extern void clone_raid_dev(struct raid_dev *clone, struct raid_dev *orig);
+extern struct raid_dev *find_raid_dev_in_chain(struct raid_dev *start, struct dev_info *di);
 extern void list_add_sorted(struct lib_context *lc,
 		     struct list_head *to, struct list_head *new,
 		     int (*sort)(struct list_head *pos,
diff -Naurp v11.orig/lib/format/format.c v11-mdisk3/lib/format/format.c
--- v11.orig/lib/format/format.c	2006-02-17 08:19:09.000000000 -0800
+++ v11-mdisk3/lib/format/format.c	2006-06-01 15:18:04.000000000 -0700
@@ -407,11 +407,14 @@ struct raid_dev *read_raid_dev(
 				void *meta),
 	int (*f_setup_rd)(struct lib_context *lc, struct raid_dev *rd,
 			  struct dev_info *di, void *meta,
-			  union read_info *info),
-	const char *handler)
+			  union read_info *info, unsigned int num),
+	const char *handler,
+	unsigned int (*f_num_disks)(struct lib_context *lc, void *meta))
 {
 	struct raid_dev *rd = NULL;
+	struct raid_dev *rd2;
 	void *meta;
+	unsigned int num_disks, i;
 	union read_info info;
 
 	/*
@@ -442,18 +445,46 @@ struct raid_dev *read_raid_dev(
 		file_dev_size(lc, handler, di);
 	}
 
+	/* Figure out how many raid_devs we need to create */
+	num_disks = f_num_disks ? f_num_disks(lc, meta) : 1;
+
 	/* Allocate RAID device structure. */
 	if (!(rd = alloc_raid_dev(lc, handler)))
 		goto bad;
+	for (i = 1; i < num_disks; i++) {
+		rd2 = alloc_raid_dev(lc, handler);
+		if (!rd2)
+			goto bad2;
+		list_add(&rd2->list, &rd->list);
+	}
 
 	/* Use metadata format handler setup function on it. */
-	if (f_setup_rd(lc, rd, di, meta, &info))
-		goto out;
-
-	log_err(lc, "%s: setting up RAID device %s", handler, di->path);
-	free_raid_dev(lc, &rd);
+	rd2 = rd;
+	for (i = 0; i < num_disks; i++) {
+		if (!f_setup_rd(lc, rd2, di, meta, &info, i))
+			goto bad3;
+		rd2 = list_entry(rd2->list.next, struct raid_dev, list);
+	}
 	goto out;
 
+   bad3:
+	log_err(lc, "%s: setting up RAID device %s #%d", handler, di->path, i);
+	rd2 = rd;
+	for (; i >= 0; i--) {
+		rd = rd2;
+		rd2 = list_entry(rd2->list.next, struct raid_dev, list);
+		free_raid_dev(lc, &rd);
+	}
+	rd = NULL;
+	goto bad;
+
+   bad2:
+	for (i = 0; i < num_disks; i++) {
+		rd2 = list_entry(rd2->list.next, struct raid_dev, list);
+		free (rd);
+		rd = rd2;
+	}
+	rd = NULL;
    bad:
 	dbg_free(meta);
    out:
diff -Naurp v11.orig/lib/metadata/metadata.c v11-mdisk3/lib/metadata/metadata.c
--- v11.orig/lib/metadata/metadata.c	2006-03-28 06:03:13.000000000 -0800
+++ v11-mdisk3/lib/metadata/metadata.c	2006-06-01 15:21:05.000000000 -0700
@@ -234,6 +234,10 @@ static void _free_dev_pointers(struct li
 	int area, i, idx = 0;
 	void **p;
 
+	/* Don't delete pointers of a clone. */
+	if (rd->is_clone)
+		return;
+
 	/* Count private and area pointers. */
 	if (!(area = (rd->private.ptr ? 1 : 0) + rd->areas))
 		return;
@@ -327,6 +331,7 @@ struct raid_dev *alloc_raid_dev(struct l
 	} else
 		log_alloc_err(lc, who);
 
+	ret->is_clone = 0;
 	return ret;
 }
 
@@ -344,7 +349,8 @@ static void _free_raid_dev(struct lib_co
 	 */
 	_free_dev_pointers(lc, r);
 
-	dbg_free(r->name);
+	if (!r->is_clone)
+		dbg_free(r->name);
 	dbg_free(r);
 	*rd = NULL;
 }
@@ -366,6 +372,34 @@ void free_raid_dev(struct lib_context *l
 	rd ? _free_raid_dev(lc, rd) : _free_raid_devs(lc);
 }
 
+/* Find a raid_dev for a given dev_info. */
+struct raid_dev *find_raid_dev_in_chain(struct raid_dev *start, struct dev_info *di)
+{
+	struct raid_dev *rd;
+
+	list_for_each_entry(rd, &start->list, list)
+		if (rd->di == di)
+			return rd;
+
+	return NULL;
+}
+
+/* Clone orig's fields into clone. */
+void clone_raid_dev(struct raid_dev *clone, struct raid_dev *orig)
+{
+	clone->name = orig->name;
+	clone->di = orig->di;
+	clone->fmt = orig->fmt;
+	clone->status = orig->status;
+	clone->type = orig->type;
+	clone->offset = orig->offset;
+	clone->sectors = orig->sectors;
+	clone->areas = orig->areas;
+	clone->meta_areas = orig->meta_areas;
+	clone->private = orig->private;
+	clone->is_clone = 1;
+}
+
 /* Allocate/Free RAID set. */
 struct raid_set *alloc_raid_set(struct lib_context *lc, const char *who)
 {
@@ -558,7 +592,7 @@ static unsigned int _count_devices(struc
 		list = LC_RD(lc);
 	else
 		return 0;
-	
+
 	list_for_each(elem, list)
 			ret++;
 
@@ -603,7 +637,8 @@ static struct raid_dev *dmraid_read(stru
 				      enum fmt_type type)
 {
 	struct format_list *fl;
-	struct raid_dev *rd = NULL, *rd_tmp;
+	struct raid_dev *rd = NULL, *rd_tmp, *del;
+	struct list_head *elem, *tmp;
 
 	/* FIXME: dropping multiple formats ? */
 	list_for_each_entry(fl, LC_FMT(lc), list) {
@@ -614,7 +649,10 @@ static struct raid_dev *dmraid_read(stru
 					  "discovered (using %s)!",
 					  di->path, rd_tmp->fmt->name,
 					  rd->fmt->name, rd->fmt->name);
-				free_raid_dev(lc, &rd_tmp);
+				list_for_each_safe(elem, tmp, &rd_tmp->list) {
+					del = list_entry(elem, struct raid_dev, list);
+					free_raid_dev(lc, &del);
+				}
 			} else
 				rd = rd_tmp;
 		}
@@ -694,8 +732,12 @@ void discover_raid_devices(struct lib_co
 				p = sep;
 				sep = remove_delimiter(sep, delim);
 
-				if ((rd = dmraid_read(lc, di, p, FMT_RAID)))
-					list_add_tail(&rd->list, LC_RD(lc));
+				if ((rd = dmraid_read(lc, di, p, FMT_RAID))) {
+					if (list_empty(&rd->list))
+						list_add_tail(&rd->list, LC_RD(lc));
+					else
+						list_splice(&rd->list, LC_RD(lc));
+				}
 
 				add_delimiter(&sep, delim);
 			} while (sep);
_______________________________________________

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