From 1686dc25ecf60a9b7691d73fc2b5a7e08184c940 Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Fri, 14 Dec 2007 20:14:38 +1100 Subject: [PATCH] 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 2bde9fab..5a408ec0 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 e07e2c06..3c22741c 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 09d397b7..f17105a8 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 0156e370..a001e9f9 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 811627e8..732bc1c4 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) -- 2.39.2