Neil Brown: Find super from fd on an array.

Martin F. Krafft madduck at alioth.debian.org
Wed Jun 25 15:42:22 UTC 2008


Module: mdadm
Branch: build
Commit: 1686dc25ecf60a9b7691d73fc2b5a7e08184c940
URL:    http://git.debian.org/?p=pkg-mdadm/mdadm.git;a=commit;h=1686dc25ecf60a9b7691d73fc2b5a7e08184c940

Author: Neil Brown <neilb at suse.de>
Date:   Fri Dec 14 20:14:38 2007 +1100

Find super from fd on an array.

We used to use the major/minor numbers, but that isn't sufficient
any more, so pass the fd, and possibly check 'text' version.

---

 Detail.c |    2 +-
 Grow.c   |    8 ++++----
 Manage.c |    6 ++----
 mdadm.h  |    2 +-
 util.c   |   56 +++++++++++++++++++++++++++++++++++++++++++++-----------
 5 files changed, 53 insertions(+), 21 deletions(-)

diff --git a/Detail.c b/Detail.c
index 2bde9fa..5a408ec 100644
--- a/Detail.c
+++ b/Detail.c
@@ -88,7 +88,7 @@ int Detail(char *dev, int brief, int export, int test, char *homehost)
 		close(fd);
 		return rv;
 	}
-	st = super_by_version(array.major_version, array.minor_version);
+	st = super_by_fd(fd);
 
 	if (fstat(fd, &stb) != 0 && !S_ISBLK(stb.st_mode))
 		stb.st_rdev = 0;
diff --git a/Grow.c b/Grow.c
index e07e2c0..3c22741 100644
--- a/Grow.c
+++ b/Grow.c
@@ -58,7 +58,7 @@ int Grow_Add_device(char *devname, int fd, char *newdev)
 		return 1;
 	}
 
-	st = super_by_version(info.array.major_version, info.array.minor_version);
+	st = super_by_fd(fd);
 	if (!st) {
 		fprintf(stderr, Name ": cannot handle arrays with superblock version %d\n", info.array.major_version);
 		return 1;
@@ -277,7 +277,7 @@ int Grow_addbitmap(char *devname, int fd, char *file, int chunk, int delay, int
 		bitmapsize = bitmapsize * array.raid_disks / ncopies;
 	}
 
-	st = super_by_version(array.major_version, array.minor_version);
+	st = super_by_fd(fd);
 	if (!st) {
 		fprintf(stderr, Name ": Cannot understand version %d.%d\n",
 			array.major_version, array.minor_version);
@@ -519,8 +519,8 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
 	case 4:
 	case 5:
 	case 6:
-		st = super_by_version(array.major_version,
-				      array.minor_version);
+		st = super_by_fd(fd);
+
 		/* size can be changed independently.
 		 * layout/chunksize/raid_disks/level can be changed
 		 * though the kernel may not support it all.
diff --git a/Manage.c b/Manage.c
index 09d397b..f17105a 100644
--- a/Manage.c
+++ b/Manage.c
@@ -202,8 +202,7 @@ int Manage_subdevs(char *devname, int fd,
 		return 1;
 	}
 
-	tst = super_by_version(array.major_version,
-			       array.minor_version);
+	tst = super_by_fd(fd);
 	if (!tst) {
 		fprintf(stderr, Name ": unsupport array - version %d.%d\n",
 			array.major_version, array.minor_version);
@@ -308,8 +307,7 @@ int Manage_subdevs(char *devname, int fd,
 			}
 			remove_partitions(tfd);
 
-			st = super_by_version(array.major_version,
-					      array.minor_version);
+			st = dup_super(tst);
 
 			if (array.not_persistent==0)
 				st->ss->load_super(st, tfd, NULL);
diff --git a/mdadm.h b/mdadm.h
index 0156e37..a001e9f 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -381,7 +381,7 @@ struct supertype {
 	void *sb;
 };
 
-extern struct supertype *super_by_version(int vers, int minor);
+extern struct supertype *super_by_fd(int fd);
 extern struct supertype *guess_super(int fd);
 extern struct supertype *dup_super(struct supertype *st);
 extern int get_dev_size(int fd, char *dname, unsigned long long *sizep);
diff --git a/util.c b/util.c
index 811627e..732bc1c 100644
--- a/util.c
+++ b/util.c
@@ -723,29 +723,63 @@ int dev_open(char *dev, int flags)
 
 struct superswitch *superlist[] = { &super0, &super1, NULL };
 
-struct supertype *super_by_version(int vers, int minor)
+struct supertype *super_by_fd(int fd)
 {
-	struct supertype *st = malloc(sizeof(*st));
-	if (!st) return st;
-	if (vers == 0) {
-		st->ss = &super0;
-		st->max_devs = MD_SB_DISKS;
+	mdu_array_info_t array;
+	int vers;
+	int minor;
+	struct supertype *st = NULL;
+	struct sysarray *sra;
+	char *verstr = NULL;
+	char version[20];
+	int i;
+
+	sra = sysfs_read(fd, 0, GET_VERSION);
+
+	if (sra) {
+		vers = sra->major_version;
+		minor = sra->minor_version;
+	} else {
+		if (ioctl(fd, GET_ARRAY_INFO, &array))
+			array.major_version = array.minor_version = 0;
+		vers = array.major_version;
+		minor = array.minor_version;
 	}
 
-	if (vers == 1) {
-		st->ss = &super1;
-		st->max_devs = 384;
+	if (vers != -1) {
+		sprintf(version, "%d.%d", vers, minor);
+		verstr = version;
 	}
-	st->minor_version = minor;
+	for (i = 0; st == NULL && superlist[i] ; i++)
+		st = superlist[i]->match_metadata_desc(verstr);
+
+	if (sra)
+		sysfs_free(sra);
 	st->sb = NULL;
 	return st;
 }
 
 struct supertype *dup_super(struct supertype *st)
 {
+	struct supertype *stnew = NULL;
+	char *verstr = NULL;
+	char version[20];
+	int i;
+
 	if (!st)
 		return st;
-	return super_by_version(st->ss->major, st->minor_version);
+
+	if (st->minor_version == -1)
+		sprintf(version, "%d", st->ss->major);
+	else
+		sprintf(version, "%d.%d", st->ss->major, st->minor_version);
+	verstr = version;
+
+	for (i = 0; stnew == NULL && superlist[i] ; i++)
+		stnew = superlist[i]->match_metadata_desc(verstr);
+
+	stnew->sb = NULL;
+	return stnew;
 }
 
 struct supertype *guess_super(int fd)




More information about the pkg-mdadm-commits mailing list