int check_raid(int fd, char *name)
{
- void *super;
struct mdinfo info;
time_t crtime;
char *level;
struct supertype *st = guess_super(fd);
if (!st) return 0;
- st->ss->load_super(st, fd, &super, name);
+ st->ss->load_super(st, fd, name);
/* Looks like a raid array .. */
fprintf(stderr, Name ": %s appears to be part of a raid array:\n",
name);
- st->ss->getinfo_super(&info, super);
- free(super);
+ st->ss->getinfo_super(st, &info);
+ st->ss->free_super(st);
crtime = info.array.ctime;
level = map_num(pers, info.array.level);
if (!level) level = "-unknown-";
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 mdinfo *sra;
+ char *verstr;
+ char version[20];
+ int i;
+
+ sra = sysfs_read(fd, 0, GET_VERSION);
+
+ if (sra) {
+ vers = sra->array.major_version;
+ minor = sra->array.minor_version;
+ verstr = sra->text_version;
+ } else {
+ if (ioctl(fd, GET_ARRAY_INFO, &array))
+ array.major_version = array.minor_version = 0;
+ vers = array.major_version;
+ minor = array.minor_version;
+ verstr = "";
}
- 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;
+
+ 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)
{
/* try each load_super to find the best match,
struct supertype *st;
unsigned long besttime = 0;
int bestsuper = -1;
-
- void *sbp = NULL;
int i;
st = malloc(sizeof(*st));
int rv;
ss = superlist[i];
st->ss = NULL;
- rv = ss->load_super(st, fd, &sbp, NULL);
+ rv = ss->load_super(st, fd, NULL);
if (rv == 0) {
struct mdinfo info;
- ss->getinfo_super(&info, sbp);
+ st->ss->getinfo_super(st, &info);
if (bestsuper == -1 ||
besttime < info.array.ctime) {
bestsuper = i;
besttime = info.array.ctime;
}
- free(sbp);
+ ss->free_super(st);
}
}
if (bestsuper != -1) {
int rv;
st->ss = NULL;
- rv = superlist[bestsuper]->load_super(st, fd, &sbp, NULL);
+ rv = superlist[bestsuper]->load_super(st, fd, NULL);
if (rv == 0) {
- free(sbp);
+ superlist[bestsuper]->free_super(st);
return st;
}
}
int get_dev_size(int fd, char *dname, unsigned long long *sizep)
{
unsigned long long ldsize;
+ struct stat st;
+
+ if (fstat(fd, &st) != -1 && S_ISREG(st.st_mode))
+ ldsize = (unsigned long long)st.st_size;
+ else
#ifdef BLKGETSIZE64
if (ioctl(fd, BLKGETSIZE64, &ldsize) != 0)
#endif