]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - Create.c
mdadm/Detail: show correct state for clustered array
[thirdparty/mdadm.git] / Create.c
index df1bc20c635b53e5c80ae774b9b03bab16b78e38..51f8826b642cbafe52c9da6efbfefbf425ad75b0 100644 (file)
--- a/Create.c
+++ b/Create.c
 #include       "md_p.h"
 #include       <ctype.h>
 
+static int round_size_and_verify(unsigned long long *size, int chunk)
+{
+       if (*size == 0)
+               return 0;
+       *size &= ~(unsigned long long)(chunk - 1);
+       if (*size == 0) {
+               pr_err("Size cannot be smaller than chunk.\n");
+               return 1;
+       }
+       return 0;
+}
+
 static int default_layout(struct supertype *st, int level, int verbose)
 {
        int layout = UnSet;
@@ -39,6 +51,9 @@ static int default_layout(struct supertype *st, int level, int verbose)
                default: /* no layout */
                        layout = 0;
                        break;
+               case 0:
+                       layout = RAID0_ORIG_LAYOUT;
+                       break;
                case 10:
                        layout = 0x102; /* near=2, far=1 */
                        if (verbose > 0)
@@ -89,8 +104,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;
@@ -248,11 +263,14 @@ int Create(struct supertype *st, char *mddev,
                pr_err("unknown level %d\n", s->level);
                return 1;
        }
+
        if (s->size == MAX_SIZE)
                /* use '0' to mean 'max' now... */
                s->size = 0;
        if (s->size && s->chunk && s->chunk != UnSet)
-               s->size &= ~(unsigned long long)(s->chunk - 1);
+               if (round_size_and_verify(&s->size, s->chunk))
+                       return 1;
+
        newsize = s->size * 2;
        if (st && ! st->ss->validate_geometry(st, s->level, s->layout, s->raiddisks,
                                              &s->chunk, s->size*2,
@@ -267,7 +285,8 @@ int Create(struct supertype *st, char *mddev,
                        /* default chunk was just set */
                        if (c->verbose > 0)
                                pr_err("chunk size defaults to %dK\n", s->chunk);
-                       s->size &= ~(unsigned long long)(s->chunk - 1);
+                       if (round_size_and_verify(&s->size, s->chunk))
+                               return 1;
                        do_default_chunk = 0;
                }
        }
@@ -325,11 +344,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);
@@ -416,7 +432,8 @@ int Create(struct supertype *st, char *mddev,
                                /* default chunk was just set */
                                if (c->verbose > 0)
                                        pr_err("chunk size defaults to %dK\n", s->chunk);
-                               s->size &= ~(unsigned long long)(s->chunk - 1);
+                               if (round_size_and_verify(&s->size, s->chunk))
+                                       return 1;
                                do_default_chunk = 0;
                        }
                }
@@ -478,6 +495,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);
@@ -521,6 +542,7 @@ int Create(struct supertype *st, char *mddev,
        if (!s->bitmap_file &&
            s->level >= 1 &&
            st->ss->add_internal_bitmap &&
+           s->journaldisks == 0 &&
            (s->consistency_policy != CONSISTENCY_POLICY_RESYNC &&
             s->consistency_policy != CONSISTENCY_POLICY_PPL) &&
            (s->write_behind || s->size > 100*1024*1024ULL)) {
@@ -641,8 +663,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) &&
@@ -822,7 +844,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;
                }
@@ -841,7 +863,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)
@@ -897,9 +918,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);
@@ -920,8 +942,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:
@@ -932,6 +954,11 @@ int Create(struct supertype *st, char *mddev,
                                if (rv) {
                                        pr_err("ADD_NEW_DISK for %s failed: %s\n",
                                               dv->devname, strerror(errno));
+                                       if (errno == EINVAL &&
+                                           info.array.level == 0) {
+                                               pr_err("Possibly your kernel doesn't support RAID0 layouts.\n");
+                                               pr_err("Either upgrade, or use --layout=dangerous\n");
+                                       }
                                        goto abort_locked;
                                }
                                break;
@@ -1028,6 +1055,9 @@ int Create(struct supertype *st, char *mddev,
                        if (ioctl(mdfd, RUN_ARRAY, &param)) {
                                pr_err("RUN_ARRAY failed: %s\n",
                                       strerror(errno));
+                               if (errno == 524 /* ENOTSUP */ &&
+                                   info.array.level == 0)
+                                       cont_err("Please use --layout=original or --layout=alternate\n");
                                if (info.array.chunk_size & (info.array.chunk_size-1)) {
                                        cont_err("Problem may be that chunk size is not a power of 2\n");
                                }
@@ -1053,12 +1083,9 @@ int Create(struct supertype *st, char *mddev,
        } else {
                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();
+       close(mdfd);
+       sysfs_uevent(&info, "change");
        return 0;
 
  abort: