]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - Manage.c
Add data_offset arg to ->avail_size
[thirdparty/mdadm.git] / Manage.c
index d5fc9740c43160fc936849a589092982ac947c4b..9b5c82b56485294f009ad8107c43241be1062f0b 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;
 
@@ -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;
@@ -786,6 +786,7 @@ 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;
@@ -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];