]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - Manage.c
imsm: move expand verification code into new function
[thirdparty/mdadm.git] / Manage.c
index 5a9ea3165ee3a51cf8afb9cbd48a9d8c78c7e032..f54de7c685ef76425eaa86896cb254cd15fec2bf 100644 (file)
--- a/Manage.c
+++ b/Manage.c
@@ -461,17 +461,6 @@ done:
                goto out;
        }
 
-       if (get_linux_version() < 2006028) {
-               /* prior to 2.6.28, KOBJ_CHANGE was not sent when an md array
-                * was stopped, so We'll do it here just to be sure.  Drop any
-                * partitions as well...
-                */
-               if (fd >= 0)
-                       ioctl(fd, BLKRRPART, 0);
-               if (mdi)
-                       sysfs_uevent(mdi, "change");
-       }
-
        if (devnm[0] && use_udev()) {
                struct map_ent *mp = map_by_devnm(&map, devnm);
                remove_devices(devnm, mp ? mp->path : NULL);
@@ -598,9 +587,8 @@ static void add_set(struct mddev_dev *dv, int fd, char set_char)
 
 int attempt_re_add(int fd, int tfd, struct mddev_dev *dv,
                   struct supertype *dev_st, struct supertype *tst,
-                  unsigned long rdev,
-                  char *update, char *devname, int verbose,
-                  mdu_array_info_t *array)
+                  unsigned long rdev, enum update_opt update,
+                  char *devname, int verbose, mdu_array_info_t *array)
 {
        struct mdinfo mdi;
        int duuid[4];
@@ -622,12 +610,6 @@ int attempt_re_add(int fd, int tfd, struct mddev_dev *dv,
                 * though.
                 */
                mdu_disk_info_t disc;
-               /* re-add doesn't work for version-1 superblocks
-                * before 2.6.18 :-(
-                */
-               if (array->major_version == 1 &&
-                   get_linux_version() <= 2006018)
-                       goto skip_re_add;
                disc.number = mdi.disk.number;
                if (md_get_disk_info(fd, &disc) != 0 ||
                    disc.major != 0 || disc.minor != 0)
@@ -666,19 +648,19 @@ int attempt_re_add(int fd, int tfd, struct mddev_dev *dv,
 
                        if (dv->writemostly == FlagSet)
                                rv = dev_st->ss->update_super(
-                                       dev_st, NULL, "writemostly",
+                                       dev_st, NULL, UOPT_SPEC_WRITEMOSTLY,
                                        devname, verbose, 0, NULL);
                        if (dv->writemostly == FlagClear)
                                rv = dev_st->ss->update_super(
-                                       dev_st, NULL, "readwrite",
+                                       dev_st, NULL, UOPT_SPEC_READWRITE,
                                        devname, verbose, 0, NULL);
                        if (dv->failfast == FlagSet)
                                rv = dev_st->ss->update_super(
-                                       dev_st, NULL, "failfast",
+                                       dev_st, NULL, UOPT_SPEC_FAILFAST,
                                        devname, verbose, 0, NULL);
                        if (dv->failfast == FlagClear)
                                rv = dev_st->ss->update_super(
-                                       dev_st, NULL, "nofailfast",
+                                       dev_st, NULL, UOPT_SPEC_NOFAILFAST,
                                        devname, verbose, 0, NULL);
                        if (update)
                                rv = dev_st->ss->update_super(
@@ -714,8 +696,8 @@ skip_re_add:
 int Manage_add(int fd, int tfd, struct mddev_dev *dv,
               struct supertype *tst, mdu_array_info_t *array,
               int force, int verbose, char *devname,
-              char *update, unsigned long rdev, unsigned long long array_size,
-              int raid_slot)
+              enum update_opt update, unsigned long rdev,
+              unsigned long long array_size, int raid_slot)
 {
        unsigned long long ldsize;
        struct supertype *dev_st;
@@ -1322,45 +1304,60 @@ bool is_remove_safe(mdu_array_info_t *array, const int fd, char *devname, const
        sysfs_free(mdi);
 
        bool is_enough = enough(array->level, array->raid_disks,
-                               array->layout, (array->state & 1),
-                               avail);
+                               array->layout, 1, avail);
 
        free(avail);
        return is_enough;
 }
 
+/**
+ * Manage_subdevs() - Execute operation depending on devmode.
+ *
+ * @devname: name of the device.
+ * @fd: file descriptor.
+ * @devlist: list of sub-devices to manage.
+ * @verbose: verbose level.
+ * @test: test flag.
+ * @update: type of update.
+ * @force: force flag.
+ *
+ * This function executes operation defined by devmode
+ * for each dev from devlist.
+ * Devmode can be:
+ * 'a' - add the device
+ * 'S' - add the device as a spare - don't try re-add
+ * 'j' - add the device as a journal device
+ * 'A' - re-add the device
+ * 'r' - remove the device: HOT_REMOVE_DISK
+ *       device can be 'faulty' or 'detached' in which case all
+ *       matching devices are removed.
+ * 'f' - set the device faulty SET_DISK_FAULTY
+ *       device can be 'detached' in which case any device that
+ *       is inaccessible will be marked faulty.
+ * 'I' - remove device by using incremental fail
+ *       which is executed when device is removed surprisingly.
+ * 'R' - mark this device as wanting replacement.
+ * 'W' - this device is added if necessary and activated as
+ *       a replacement for a previous 'R' device.
+ * -----
+ * 'w' - 'W' will be changed to 'w' when it is paired with
+ *       a 'R' device.  If a 'W' is found while walking the list
+ *       it must be unpaired, and is an error.
+ * 'M' - this is created by a 'missing' target.  It is a slight
+ *       variant on 'A'
+ * 'F' - Another variant of 'A', where the device was faulty
+ *       so must be removed from the array first.
+ * 'c' - confirm the device as found (for clustered environments)
+ *
+ * For 'f' and 'r', the device can also be a kernel-internal
+ * name such as 'sdb'.
+ *
+ * Return: 0 on success, otherwise 1 or 2.
+ */
 int Manage_subdevs(char *devname, int fd,
                   struct mddev_dev *devlist, int verbose, int test,
-                  char *update, int force)
+                  enum update_opt update, int force)
 {
-       /* Do something to each dev.
-        * devmode can be
-        *  'a' - add the device
-        *  'S' - add the device as a spare - don't try re-add
-        *  'j' - add the device as a journal device
-        *  'A' - re-add the device
-        *  'r' - remove the device: HOT_REMOVE_DISK
-        *        device can be 'faulty' or 'detached' in which case all
-        *        matching devices are removed.
-        *  'f' - set the device faulty SET_DISK_FAULTY
-        *        device can be 'detached' in which case any device that
-        *        is inaccessible will be marked faulty.
-        *  'R' - mark this device as wanting replacement.
-        *  'W' - this device is added if necessary and activated as
-        *        a replacement for a previous 'R' device.
-        * -----
-        *  'w' - 'W' will be changed to 'w' when it is paired with
-        *        a 'R' device.  If a 'W' is found while walking the list
-        *        it must be unpaired, and is an error.
-        *  'M' - this is created by a 'missing' target.  It is a slight
-        *        variant on 'A'
-        *  'F' - Another variant of 'A', where the device was faulty
-        *        so must be removed from the array first.
-        *  'c' - confirm the device as found (for clustered environments)
-        *
-        * For 'f' and 'r', the device can also be a kernel-internal
-        * name such as 'sdb'.
-        */
        mdu_array_info_t array;
        unsigned long long array_size;
        struct mddev_dev *dv;
@@ -1496,8 +1493,9 @@ int Manage_subdevs(char *devname, int fd,
                        /* Assume this is a kernel-internal name like 'sda1' */
                        int found = 0;
                        char dname[55];
-                       if (dv->disposition != 'r' && dv->disposition != 'f') {
-                               pr_err("%s only meaningful with -r or -f, not -%c\n",
+                       if (dv->disposition != 'r' && dv->disposition != 'f' &&
+                           dv->disposition != 'I') {
+                               pr_err("%s only meaningful with -r, -f or -I, not -%c\n",
                                        dv->devname, dv->disposition);
                                goto abort;
                        }
@@ -1649,7 +1647,7 @@ int Manage_subdevs(char *devname, int fd,
                                        close(sysfd);
                                goto abort;
                        }
-
+               case 'I': /* incremental fail */
                        if ((sysfd >= 0 && write(sysfd, "faulty", 6) != 6) ||
                            (sysfd < 0 && ioctl(fd, SET_DISK_FAULTY,
                                                rdev))) {
@@ -1726,11 +1724,13 @@ int autodetect(void)
        return rv;
 }
 
-int Update_subarray(char *dev, char *subarray, char *update, struct mddev_ident *ident, int verbose)
+int Update_subarray(char *dev, char *subarray, enum update_opt update,
+                   struct mddev_ident *ident, int verbose)
 {
        struct supertype supertype, *st = &supertype;
        int fd, rv = 2;
        struct mdinfo *info = NULL;
+       char *update_verb = map_num(update_options, update);
 
        memset(st, 0, sizeof(*st));
 
@@ -1748,7 +1748,7 @@ int Update_subarray(char *dev, char *subarray, char *update, struct mddev_ident
        if (is_subarray_active(subarray, st->devnm)) {
                if (verbose >= 0)
                        pr_err("Subarray %s in %s is active, cannot update %s\n",
-                              subarray, dev, update);
+                               subarray, dev, update_verb);
                goto free_super;
        }
 
@@ -1757,7 +1757,7 @@ int Update_subarray(char *dev, char *subarray, char *update, struct mddev_ident
 
        info = st->ss->container_content(st, subarray);
 
-       if (strncmp(update, "ppl", 3) == 0 && !is_level456(info->array.level)) {
+       if (update == UOPT_PPL && !is_level456(info->array.level)) {
                pr_err("RWH policy ppl is supported only for raid4, raid5 and raid6.\n");
                goto free_super;
        }
@@ -1767,13 +1767,13 @@ int Update_subarray(char *dev, char *subarray, char *update, struct mddev_ident
        if (rv) {
                if (verbose >= 0)
                        pr_err("Failed to update %s of subarray-%s in %s\n",
-                               update, subarray, dev);
+                               update_verb, subarray, dev);
        } else if (st->update_tail)
                flush_metadata_updates(st);
        else
                st->ss->sync_metadata(st);
 
-       if (rv == 0 && strcmp(update, "name") == 0 && verbose >= 0)
+       if (rv == 0 && update == UOPT_NAME && verbose >= 0)
                pr_err("Updated subarray-%s name from %s, UUIDs may have changed\n",
                       subarray, dev);
 
@@ -1814,10 +1814,10 @@ int move_spare(char *from_devname, char *to_devname, dev_t devid)
        sprintf(devname, "%d:%d", major(devid), minor(devid));
 
        devlist.disposition = 'r';
-       if (Manage_subdevs(from_devname, fd2, &devlist, -1, 0, NULL, 0) == 0) {
+       if (Manage_subdevs(from_devname, fd2, &devlist, -1, 0, UOPT_UNDEFINED, 0) == 0) {
                devlist.disposition = 'a';
                if (Manage_subdevs(to_devname, fd1, &devlist, -1, 0,
-                                  NULL, 0) == 0) {
+                                  UOPT_UNDEFINED, 0) == 0) {
                        /* make sure manager is aware of changes */
                        ping_manager(to_devname);
                        ping_manager(from_devname);
@@ -1827,7 +1827,7 @@ int move_spare(char *from_devname, char *to_devname, dev_t devid)
                }
                else
                        Manage_subdevs(from_devname, fd2, &devlist,
-                                      -1, 0, NULL, 0);
+                                      -1, 0, UOPT_UNDEFINED, 0);
        }
        close(fd1);
        close(fd2);