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.
This commit is contained in:
Neil Brown 2007-12-14 20:14:38 +11:00
parent 3da92f272d
commit 1686dc25ec
5 changed files with 53 additions and 21 deletions

View File

@ -88,7 +88,7 @@ int Detail(char *dev, int brief, int export, int test, char *homehost)
close(fd); close(fd);
return rv; 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)) if (fstat(fd, &stb) != 0 && !S_ISBLK(stb.st_mode))
stb.st_rdev = 0; stb.st_rdev = 0;

8
Grow.c
View File

@ -58,7 +58,7 @@ int Grow_Add_device(char *devname, int fd, char *newdev)
return 1; return 1;
} }
st = super_by_version(info.array.major_version, info.array.minor_version); st = super_by_fd(fd);
if (!st) { if (!st) {
fprintf(stderr, Name ": cannot handle arrays with superblock version %d\n", info.array.major_version); fprintf(stderr, Name ": cannot handle arrays with superblock version %d\n", info.array.major_version);
return 1; 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; bitmapsize = bitmapsize * array.raid_disks / ncopies;
} }
st = super_by_version(array.major_version, array.minor_version); st = super_by_fd(fd);
if (!st) { if (!st) {
fprintf(stderr, Name ": Cannot understand version %d.%d\n", fprintf(stderr, Name ": Cannot understand version %d.%d\n",
array.major_version, array.minor_version); 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 4:
case 5: case 5:
case 6: case 6:
st = super_by_version(array.major_version, st = super_by_fd(fd);
array.minor_version);
/* size can be changed independently. /* size can be changed independently.
* layout/chunksize/raid_disks/level can be changed * layout/chunksize/raid_disks/level can be changed
* though the kernel may not support it all. * though the kernel may not support it all.

View File

@ -202,8 +202,7 @@ int Manage_subdevs(char *devname, int fd,
return 1; return 1;
} }
tst = super_by_version(array.major_version, tst = super_by_fd(fd);
array.minor_version);
if (!tst) { if (!tst) {
fprintf(stderr, Name ": unsupport array - version %d.%d\n", fprintf(stderr, Name ": unsupport array - version %d.%d\n",
array.major_version, array.minor_version); array.major_version, array.minor_version);
@ -308,8 +307,7 @@ int Manage_subdevs(char *devname, int fd,
} }
remove_partitions(tfd); remove_partitions(tfd);
st = super_by_version(array.major_version, st = dup_super(tst);
array.minor_version);
if (array.not_persistent==0) if (array.not_persistent==0)
st->ss->load_super(st, tfd, NULL); st->ss->load_super(st, tfd, NULL);

View File

@ -381,7 +381,7 @@ struct supertype {
void *sb; 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 *guess_super(int fd);
extern struct supertype *dup_super(struct supertype *st); extern struct supertype *dup_super(struct supertype *st);
extern int get_dev_size(int fd, char *dname, unsigned long long *sizep); extern int get_dev_size(int fd, char *dname, unsigned long long *sizep);

56
util.c
View File

@ -723,29 +723,63 @@ int dev_open(char *dev, int flags)
struct superswitch *superlist[] = { &super0, &super1, NULL }; 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)); mdu_array_info_t array;
if (!st) return st; int vers;
if (vers == 0) { int minor;
st->ss = &super0; struct supertype *st = NULL;
st->max_devs = MD_SB_DISKS; 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) { if (vers != -1) {
st->ss = &super1; sprintf(version, "%d.%d", vers, minor);
st->max_devs = 384; 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; st->sb = NULL;
return st; return st;
} }
struct supertype *dup_super(struct supertype *st) struct supertype *dup_super(struct supertype *st)
{ {
struct supertype *stnew = NULL;
char *verstr = NULL;
char version[20];
int i;
if (!st) if (!st)
return 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) struct supertype *guess_super(int fd)