]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - Manage.c
Allow data-offset to be specified per-device for create
[thirdparty/mdadm.git] / Manage.c
index d5fc9740c43160fc936849a589092982ac947c4b..296feeb7f6f424adc31831212a91dfa323a6fa8f 100644 (file)
--- a/Manage.c
+++ b/Manage.c
@@ -535,7 +535,7 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv,
               char *update, unsigned long rdev, unsigned long long array_size)
 {
        unsigned long long ldsize;
-       struct supertype *dev_st;
+       struct supertype *dev_st = NULL;
        int j;
        mdu_disk_info_t disc;
 
@@ -549,7 +549,7 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv,
        if (tst->ss->validate_geometry(
                    tst, array->level, array->layout,
                    array->raid_disks, NULL,
-                   ldsize >> 9, NULL, NULL, 0) == 0) {
+                   ldsize >> 9, INVALID_SECTORS, NULL, NULL, 0) == 0) {
                if (!force) {
                        pr_err("%s is larger than %s can "
                               "effectively use.\n"
@@ -628,7 +628,7 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv,
                }
 
                /* Make sure device is large enough */
-               if (tst->ss->avail_size(tst, ldsize/512) <
+               if (tst->ss->avail_size(tst, ldsize/512, INVALID_SECTORS) <
                    array_size) {
                        if (dv->disposition == 'M')
                                return 0;
@@ -733,7 +733,7 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv,
                        disc.state |= 1 << MD_DISK_WRITEMOSTLY;
                dfd = dev_open(dv->devname, O_RDWR | O_EXCL|O_DIRECT);
                if (tst->ss->add_to_super(tst, &disc, dfd,
-                                         dv->devname))
+                                         dv->devname, INVALID_SECTORS))
                        return -1;
                if (tst->ss->write_init_super(tst))
                        return -1;
@@ -786,11 +786,12 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv,
                        return -1;
                }
 
+               Kill(dv->devname, NULL, 0, -1, 0);
                dfd = dev_open(dv->devname, O_RDWR | O_EXCL|O_DIRECT);
                if (mdmon_running(tst->container_dev))
                        tst->update_tail = &tst->updates;
                if (tst->ss->add_to_super(tst, &disc, dfd,
-                                         dv->devname)) {
+                                         dv->devname, INVALID_SECTORS)) {
                        close(dfd);
                        close(container_fd);
                        return -1;
@@ -856,6 +857,7 @@ int Manage_remove(struct supertype *tst, int fd, struct mddev_dev *dv,
                 * hot spare while we are checking, we
                 * get an O_EXCL open on the container
                 */
+               int ret;
                int dnum = fd2devnum(fd);
                lfd = open_dev_excl(dnum);
                if (lfd < 0) {
@@ -863,19 +865,26 @@ int Manage_remove(struct supertype *tst, int fd, struct mddev_dev *dv,
                               " to container - odd\n");
                        return -1;
                }
-               /* In the detached case it is not possible to
-                * check if we are the unique holder, so just
-                * rely on the 'detached' checks
+               /* We may not be able to check on holders in
+                * sysfs, either because we don't have the dev num
+                * (rdev == 0) or because the device has been detached
+                * and the 'holders' directory no longer exists
+                * (ret == -1).  In that case, assume it is OK to
+                * remove.
                 */
-               if (strcmp(dv->devname, "detached") == 0 ||
-                   sysfd >= 0 ||
-                   sysfs_unique_holder(dnum, rdev))
-                       /* pass */;
-               else {
-                       pr_err("%s is %s, cannot remove.\n",
-                              dv->devname,
-                              errno == EEXIST ? "still in use":
-                              "not a member");
+               if (rdev == 0)
+                       ret = -1;
+               else
+                       ret = sysfs_unique_holder(dnum, rdev);
+               if (ret == 0) {
+                       pr_err("%s is not a member, cannot remove.\n",
+                              dv->devname);
+                       close(lfd);
+                       return -1;
+               }
+               if (ret >= 2) {
+                       pr_err("%s is still in use, cannot remove.\n",
+                              dv->devname);
                        close(lfd);
                        return -1;
                }
@@ -1029,7 +1038,7 @@ int Manage_subdevs(char *devname, int fd,
                        struct mddev_dev **dp;
                        if (dv->disposition != 'A') {
                                pr_err("'missing' only meaningful "
-                                       "with --re-add\n");
+                                      "with --re-add\n");
                                goto abort;
                        }
                        add_devlist = conf_get_devs();
@@ -1046,8 +1055,8 @@ int Manage_subdevs(char *devname, int fd,
                }
 
                if (strchr(dv->devname, '/') == NULL &&
-                          strchr(dv->devname, ':') == NULL &&
-                          strlen(dv->devname) < 50) {
+                   strchr(dv->devname, ':') == NULL &&
+                   strlen(dv->devname) < 50) {
                        /* Assume this is a kernel-internal name like 'sda1' */
                        int found = 0;
                        char dname[55];