]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - Create.c
mdadm/tests: add one test case for failfast of raid1
[thirdparty/mdadm.git] / Create.c
index 6ca0924498809770d6f5898ea6f8c151090a0573..6f1b22884b689d508462afbe235030bca605f141 100644 (file)
--- a/Create.c
+++ b/Create.c
@@ -89,8 +89,8 @@ int Create(struct supertype *st, char *mddev,
        char *maxdisc = NULL;
        int dnum, raid_disk_num;
        struct mddev_dev *dv;
+       dev_t rdev;
        int fail = 0, warn = 0;
-       struct stat stb;
        int first_missing = subdevs * 2;
        int second_missing = subdevs * 2;
        int missing_disks = 0;
@@ -325,11 +325,8 @@ int Create(struct supertype *st, char *mddev,
                                dname, strerror(errno));
                        exit(2);
                }
-               if (fstat(dfd, &stb) != 0 ||
-                   (stb.st_mode & S_IFMT) != S_IFBLK) {
+               if (!fstat_is_blkdev(dfd, dname, NULL)) {
                        close(dfd);
-                       pr_err("%s is not a block device\n",
-                               dname);
                        exit(2);
                }
                close(dfd);
@@ -478,6 +475,10 @@ int Create(struct supertype *st, char *mddev,
                        close(fd);
                }
        }
+       if (missing_disks == dnum && !have_container) {
+               pr_err("Subdevs can't be all missing\n");
+               return 1;
+       }
        if (s->raiddisks + s->sparedisks > st->max_devs) {
                pr_err("Too many devices: %s metadata only supports %d\n",
                        st->ss->name, st->max_devs);
@@ -605,7 +606,7 @@ int Create(struct supertype *st, char *mddev,
 
        /* We need to create the device */
        map_lock(&map);
-       mdfd = create_mddev(mddev, name, c->autof, LOCAL, chosen_name);
+       mdfd = create_mddev(mddev, name, c->autof, LOCAL, chosen_name, 1);
        if (mdfd < 0) {
                map_unlock(&map);
                return 1;
@@ -620,6 +621,7 @@ int Create(struct supertype *st, char *mddev,
                        chosen_name);
                close(mdfd);
                map_unlock(&map);
+               udev_unblock();
                return 1;
        }
        mddev = chosen_name;
@@ -640,8 +642,8 @@ int Create(struct supertype *st, char *mddev,
         * with, but it chooses to trust me instead. Sigh
         */
        info.array.md_minor = 0;
-       if (fstat(mdfd, &stb) == 0)
-               info.array.md_minor = minor(stb.st_rdev);
+       if (fstat_is_blkdev(mdfd, mddev, &rdev))
+               info.array.md_minor = minor(rdev);
        info.array.not_persistent = 0;
 
        if (((s->level == 4 || s->level == 5) &&
@@ -821,7 +823,7 @@ int Create(struct supertype *st, char *mddev,
                }
                bitmap_fd = open(s->bitmap_file, O_RDWR);
                if (bitmap_fd < 0) {
-                       pr_err("weird: %s cannot be openned\n",
+                       pr_err("weird: %s cannot be opened\n",
                                s->bitmap_file);
                        goto abort_locked;
                }
@@ -840,7 +842,6 @@ int Create(struct supertype *st, char *mddev,
                for (dnum = 0, raid_disk_num = 0, dv = devlist; dv;
                     dv = (dv->next) ? (dv->next) : moved_disk, dnum++) {
                        int fd;
-                       struct stat stb2;
                        struct mdinfo *inf = &infos[dnum];
 
                        if (dnum >= total_slots)
@@ -896,9 +897,10 @@ int Create(struct supertype *st, char *mddev,
                                                        dv->devname);
                                                goto abort_locked;
                                        }
-                                       fstat(fd, &stb2);
-                                       inf->disk.major = major(stb2.st_rdev);
-                                       inf->disk.minor = minor(stb2.st_rdev);
+                                       if (!fstat_is_blkdev(fd, dv->devname, &rdev))
+                                               return 1;
+                                       inf->disk.major = major(rdev);
+                                       inf->disk.minor = minor(rdev);
                                }
                                if (fd >= 0)
                                        remove_partitions(fd);
@@ -919,8 +921,8 @@ int Create(struct supertype *st, char *mddev,
 
                                if (!have_container) {
                                        /* getinfo_super might have lost these ... */
-                                       inf->disk.major = major(stb2.st_rdev);
-                                       inf->disk.minor = minor(stb2.st_rdev);
+                                       inf->disk.major = major(rdev);
+                                       inf->disk.minor = minor(rdev);
                                }
                                break;
                        case 2:
@@ -1053,9 +1055,15 @@ int Create(struct supertype *st, char *mddev,
                pr_err("not starting array - not enough devices.\n");
        }
        close(mdfd);
+       /* Give udev a moment to process the Change event caused
+        * by the close.
+        */
+       usleep(100*1000);
+       udev_unblock();
        return 0;
 
  abort:
+       udev_unblock();
        map_lock(&map);
  abort_locked:
        map_remove(&map, fd2devnm(mdfd));