+
+
+
+static int get_super_block(struct intel_super **super_list, int devnum, char *devname,
+ int major, int minor, int keep_fd)
+{
+ struct intel_super*s = NULL;
+ char nm[32];
+ int dfd = -1;
+ int rv;
+ int err = 0;
+ int retry;
+
+ s = alloc_super();
+ if (!s) {
+ err = 1;
+ goto error;
+ }
+
+ sprintf(nm, "%d:%d", major, minor);
+ dfd = dev_open(nm, O_RDWR);
+ if (dfd < 0) {
+ err = 2;
+ goto error;
+ }
+
+ rv = find_intel_hba_capability(dfd, s, devname);
+ /* no orom/efi or non-intel hba of the disk */
+ if (rv != 0) {
+ err = 4;
+ goto error;
+ }
+
+ err = load_and_parse_mpb(dfd, s, NULL, keep_fd);
+
+ /* retry the load if we might have raced against mdmon */
+ if (err == 3 && (devnum != -1) && mdmon_running(devnum))
+ for (retry = 0; retry < 3; retry++) {
+ usleep(3000);
+ err = load_and_parse_mpb(dfd, s, NULL, keep_fd);
+ if (err != 3)
+ break;
+ }
+ error:
+ if (!err) {
+ s->next = *super_list;
+ *super_list = s;
+ } else {
+ if (s)
+ free(s);
+ if (dfd)
+ close(dfd);
+ }
+ if ((dfd >= 0) && (!keep_fd))
+ close(dfd);
+ return err;
+
+}
+
+static int
+get_sra_super_block(int fd, struct intel_super **super_list, char *devname, int *max, int keep_fd)
+{
+ struct mdinfo *sra;
+ int devnum;
+ struct mdinfo *sd;
+ int err = 0;
+ int i = 0;
+ sra = sysfs_read(fd, 0, GET_LEVEL|GET_VERSION|GET_DEVS|GET_STATE);
+ if (!sra)
+ return 1;
+
+ if (sra->array.major_version != -1 ||
+ sra->array.minor_version != -2 ||
+ strcmp(sra->text_version, "imsm") != 0) {
+ err = 1;
+ goto error;
+ }
+ /* load all mpbs */
+ devnum = fd2devnum(fd);
+ for (sd = sra->devs, i = 0; sd; sd = sd->next, i++) {
+ if (get_super_block(super_list, devnum, devname,
+ sd->disk.major, sd->disk.minor, keep_fd) != 0) {
+ err = 7;
+ goto error;
+ }
+ }
+ error:
+ sysfs_free(sra);
+ *max = i;
+ return err;
+}
+