]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - Incremental.c
added --path <path_id> to give the information on the 'path-id' of removed device
[thirdparty/mdadm.git] / Incremental.c
index 23f59800d38ecadac827218b963e8c672c816d2c..a2235530fa6682449a8a742afb1f3280fe1c5138 100644 (file)
@@ -40,6 +40,15 @@ static void find_reject(int mdfd, struct supertype *st, struct mdinfo *sra,
 static int try_spare(char *devname, int *dfdp, struct dev_policy *pol,
                     struct supertype *st, int verbose);
 
+static int Incremental_container(struct supertype *st, char *devname,
+                                char *homehost,
+                                int verbose, int runstop, int autof);
+
+static struct mddev_ident *search_mdstat(struct supertype *st,
+                                          struct mdinfo *info,
+                                          char *devname,
+                                          int verbose, int *rvp);
+
 int Incremental(char *devname, int verbose, int runstop,
                struct supertype *st, char *homehost, int require_homehost,
                int autof)
@@ -83,20 +92,55 @@ int Incremental(char *devname, int verbose, int runstop,
         */
        struct stat stb;
        struct mdinfo info, dinfo;
-       struct mddev_ident_s *array_list, *match;
+       struct mddev_ident *match;
        char chosen_name[1024];
        int rv = 1;
        struct map_ent *mp, *map = NULL;
        int dfd = -1, mdfd = -1;
        char *avail;
        int active_disks;
-       int trustworthy = FOREIGN;
+       int trustworthy;
        char *name_to_use;
        mdu_array_info_t ainf;
        struct dev_policy *policy = NULL;
 
        struct createinfo *ci = conf_get_create_info();
 
+       if (stat(devname, &stb) < 0) {
+               if (verbose >= 0)
+                       fprintf(stderr, Name ": stat failed for %s: %s.\n",
+                               devname, strerror(errno));
+               return rv;
+       }
+       if ((stb.st_mode & S_IFMT) != S_IFBLK) {
+               if (verbose >= 0)
+                       fprintf(stderr, Name ": %s is not a block device.\n",
+                               devname);
+               return rv;
+       }
+       dfd = dev_open(devname, O_RDONLY|O_EXCL);
+       if (dfd < 0) {
+               if (verbose >= 0)
+                       fprintf(stderr, Name ": cannot open %s: %s.\n",
+                               devname, strerror(errno));
+               return rv;
+       }
+       /* If the device is a container, we do something very different */
+       if (must_be_container(dfd)) {
+               if (!st)
+                       st = super_by_fd(dfd, NULL);
+               if (st)
+                       rv = st->ss->load_container(st, dfd, NULL);
+
+               close(dfd);
+               if (!rv && st->ss->container_content)
+                       return Incremental_container(st, devname, homehost,
+                                                    verbose, runstop, autof);
+
+               fprintf(stderr, Name ": %s is not part of an md array.\n",
+                       devname);
+               return rv;
+       }
 
        /* 1/ Check if device is permitted by mdadm.conf */
 
@@ -111,13 +155,6 @@ int Incremental(char *devname, int verbose, int runstop,
        /* 2/ Find metadata, reject if none appropriate (check
         *            version/name from args) */
 
-       dfd = dev_open(devname, O_RDONLY|O_EXCL);
-       if (dfd < 0) {
-               if (verbose >= 0)
-                       fprintf(stderr, Name ": cannot open %s: %s.\n",
-                               devname, strerror(errno));
-               goto out;
-       }
        if (fstat(dfd, &stb) < 0) {
                if (verbose >= 0)
                        fprintf(stderr, Name ": fstat failed for %s: %s.\n",
@@ -157,71 +194,11 @@ int Incremental(char *devname, int verbose, int runstop,
 
        memset(&info, 0, sizeof(info));
        st->ss->getinfo_super(st, &info, NULL);
-       /* 3/ Check if there is a match in mdadm.conf */
-
-       array_list = conf_get_ident(NULL);
-       match = NULL;
-       for (; array_list; array_list = array_list->next) {
-               if (array_list->uuid_set &&
-                   same_uuid(array_list->uuid, info.uuid, st->ss->swapuuid)
-                   == 0) {
-                       if (verbose >= 2 && array_list->devname)
-                               fprintf(stderr, Name
-                                       ": UUID differs from %s.\n",
-                                       array_list->devname);
-                       continue;
-               }
-               if (array_list->name[0] &&
-                   strcasecmp(array_list->name, info.name) != 0) {
-                       if (verbose >= 2 && array_list->devname)
-                               fprintf(stderr, Name
-                                       ": Name differs from %s.\n",
-                                       array_list->devname);
-                       continue;
-               }
-               if (array_list->devices &&
-                   !match_oneof(array_list->devices, devname)) {
-                       if (verbose >= 2 && array_list->devname)
-                               fprintf(stderr, Name
-                                       ": Not a listed device for %s.\n",
-                                       array_list->devname);
-                       continue;
-               }
-               if (array_list->super_minor != UnSet &&
-                   array_list->super_minor != info.array.md_minor) {
-                       if (verbose >= 2 && array_list->devname)
-                               fprintf(stderr, Name
-                                       ": Different super-minor to %s.\n",
-                                       array_list->devname);
-                       continue;
-               }
-               if (!array_list->uuid_set &&
-                   !array_list->name[0] &&
-                   !array_list->devices &&
-                   array_list->super_minor == UnSet) {
-                       if (verbose >= 2 && array_list->devname)
-                               fprintf(stderr, Name
-                            ": %s doesn't have any identifying information.\n",
-                                       array_list->devname);
-                       continue;
-               }
-               /* FIXME, should I check raid_disks and level too?? */
 
-               if (match) {
-                       if (verbose >= 0) {
-                               if (match->devname && array_list->devname)
-                                       fprintf(stderr, Name
-                  ": we match both %s and %s - cannot decide which to use.\n",
-                                               match->devname, array_list->devname);
-                               else
-                                       fprintf(stderr, Name
-                                               ": multiple lines in mdadm.conf match\n");
-                       }
-                       rv = 2;
-                       goto out;
-               }
-               match = array_list;
-       }
+       /* 3/ Check if there is a match in mdadm.conf */
+       match = search_mdstat(st, &info, devname, verbose, &rv);
+       if (!match && rv == 2)
+               goto out;
 
        if (match && match->devname
            && strcasecmp(match->devname, "<ignore>") == 0) {
@@ -268,25 +245,6 @@ int Incremental(char *devname, int verbose, int runstop,
        if (autof == 0)
                autof = ci->autof;
 
-       if (st->ss->container_content && st->loaded_container) {
-               if ((runstop > 0 && info.container_enough >= 0) ||
-                   info.container_enough > 0)
-                       /* pass */;
-               else {
-                       if (verbose)
-                               fprintf(stderr, Name ": not enough devices to start the container\n");
-                       rv = 0;
-                       goto out;
-               }
-
-               /* This is a pre-built container array, so we do something
-                * rather different.
-                */
-               rv = Incremental_container(st, devname, verbose, runstop,
-                                            autof, trustworthy);
-               goto out;
-       }
-
        name_to_use = info.name;
        if (name_to_use[0] == 0 &&
            info.array.level == LEVEL_CONTAINER &&
@@ -597,6 +555,79 @@ out:
        return rv;
 }
 
+static struct mddev_ident *search_mdstat(struct supertype *st,
+                                          struct mdinfo *info,
+                                          char *devname,
+                                          int verbose, int *rvp)
+{
+       struct mddev_ident *array_list, *match;
+       array_list = conf_get_ident(NULL);
+       match = NULL;
+       for (; array_list; array_list = array_list->next) {
+               if (array_list->uuid_set &&
+                   same_uuid(array_list->uuid, info->uuid, st->ss->swapuuid)
+                   == 0) {
+                       if (verbose >= 2 && array_list->devname)
+                               fprintf(stderr, Name
+                                       ": UUID differs from %s.\n",
+                                       array_list->devname);
+                       continue;
+               }
+               if (array_list->name[0] &&
+                   strcasecmp(array_list->name, info->name) != 0) {
+                       if (verbose >= 2 && array_list->devname)
+                               fprintf(stderr, Name
+                                       ": Name differs from %s.\n",
+                                       array_list->devname);
+                       continue;
+               }
+               if (array_list->devices &&
+                   !match_oneof(array_list->devices, devname)) {
+                       if (verbose >= 2 && array_list->devname)
+                               fprintf(stderr, Name
+                                       ": Not a listed device for %s.\n",
+                                       array_list->devname);
+                       continue;
+               }
+               if (array_list->super_minor != UnSet &&
+                   array_list->super_minor != info->array.md_minor) {
+                       if (verbose >= 2 && array_list->devname)
+                               fprintf(stderr, Name
+                                       ": Different super-minor to %s.\n",
+                                       array_list->devname);
+                       continue;
+               }
+               if (!array_list->uuid_set &&
+                   !array_list->name[0] &&
+                   !array_list->devices &&
+                   array_list->super_minor == UnSet) {
+                       if (verbose >= 2 && array_list->devname)
+                               fprintf(stderr, Name
+                                       ": %s doesn't have any identifying information.\n",
+                                       array_list->devname);
+                       continue;
+               }
+               /* FIXME, should I check raid_disks and level too?? */
+
+               if (match) {
+                       if (verbose >= 0) {
+                               if (match->devname && array_list->devname)
+                                       fprintf(stderr, Name
+                                               ": we match both %s and %s - cannot decide which to use.\n",
+                                               match->devname, array_list->devname);
+                               else
+                                       fprintf(stderr, Name
+                                               ": multiple lines in mdadm.conf match\n");
+                       }
+                       *rvp = 2;
+                       match = NULL;
+                       break;
+               }
+               match = array_list;
+       }
+       return match;
+}
+
 static void find_reject(int mdfd, struct supertype *st, struct mdinfo *sra,
                        int number, __u64 events, int verbose,
                        char *array_name)
@@ -708,6 +739,7 @@ static int count_active(struct supertype *st, int mdfd, char **availp,
                                cnt = 1; cnt1 = 0;
                                memset(avail, 0, info.disk.raid_disk);
                                max_events = info.events;
+                               avail[info.disk.raid_disk] = 2;
                                st->ss->getinfo_super(st, bestinfo, NULL);
                        }
                }
@@ -827,7 +859,7 @@ static int array_try_spare(char *devname, int *dfdp, struct dev_policy *pol,
                /* add current device to chosen array as a spare */
                int mdfd = open_dev(devname2devnum(chosen->sys_name));
                if (mdfd >= 0) {
-                       struct mddev_dev_s devlist;
+                       struct mddev_dev devlist;
                        char devname[20];
                        devlist.next = NULL;
                        devlist.used = 0;
@@ -1088,7 +1120,7 @@ int IncrementalScan(int verbose)
         */
        struct map_ent *mapl = NULL;
        struct map_ent *me;
-       mddev_ident_t devs, mddev;
+       struct mddev_ident *devs, *mddev;
        int rv = 0;
 
        map_read(&mapl);
@@ -1182,17 +1214,49 @@ static char *container2devname(char *devname)
        return mdname;
 }
 
-int Incremental_container(struct supertype *st, char *devname, int verbose,
-                         int runstop, int autof, int trustworthy)
+static int Incremental_container(struct supertype *st, char *devname,
+                                char *homehost, int verbose,
+                                int runstop, int autof)
 {
        /* Collect the contents of this container and for each
         * array, choose a device name and assemble the array.
         */
 
-       struct mdinfo *list = st->ss->container_content(st);
+       struct mdinfo *list;
        struct mdinfo *ra;
        struct map_ent *map = NULL;
+       struct mdinfo info;
+       int trustworthy;
+       struct mddev_ident *match;
+       int rv = 0;
+
+       memset(&info, 0, sizeof(info));
+       st->ss->getinfo_super(st, &info, NULL);
+
+       if ((runstop > 0 && info.container_enough >= 0) ||
+           info.container_enough > 0)
+               /* pass */;
+       else {
+               if (verbose)
+                       fprintf(stderr, Name ": not enough devices to start the container\n");
+               return 0;
+       }
+
+       match = search_mdstat(st, &info, devname, verbose, &rv);
+       if (match == NULL && rv == 2)
+               return rv;
 
+       /* Need to compute 'trustworthy' */
+       if (match)
+               trustworthy = LOCAL;
+       else if (st->ss->match_home(st, homehost) == 1)
+               trustworthy = LOCAL;
+       else if (st->ss->match_home(st, "any") == 1)
+               trustworthy = LOCAL;
+       else
+               trustworthy = FOREIGN;
+
+       list = st->ss->container_content(st, NULL);
        if (map_lock(&map))
                fprintf(stderr, Name ": failed to get exclusive lock on "
                        "mapfile\n");
@@ -1201,7 +1265,7 @@ int Incremental_container(struct supertype *st, char *devname, int verbose,
                int mdfd;
                char chosen_name[1024];
                struct map_ent *mp;
-               struct mddev_ident_s *match = NULL;
+               struct mddev_ident *match = NULL;
 
                mp = map_by_uuid(&map, ra->uuid);
 
@@ -1217,7 +1281,7 @@ int Incremental_container(struct supertype *st, char *devname, int verbose,
                         * member == ra->text_version after second slash.
                         */
                        char *sub = strchr(ra->text_version+1, '/');
-                       struct mddev_ident_s *array_list;
+                       struct mddev_ident *array_list;
                        if (sub) {
                                sub++;
                                array_list = conf_get_ident(NULL);
@@ -1287,16 +1351,22 @@ int Incremental_container(struct supertype *st, char *devname, int verbose,
  * raid arrays, and if so first fail (if needed) and then remove the device.
  *
  * @devname - The device we want to remove
+ * @id_path - name as found in /dev/disk/by-path for this device
  *
  * Note: the device name must be a kernel name like "sda", so
  * that we can find it in /proc/mdstat
  */
-int IncrementalRemove(char *devname, int verbose)
+int IncrementalRemove(char *devname, char *id_path, int verbose)
 {
        int mdfd;
        int rv;
        struct mdstat_ent *ent;
-       struct mddev_dev_s devlist;
+       struct mddev_dev devlist;
+
+       if (!id_path)
+               dprintf(Name ": incremental removal without --path <id_path> "
+                       "lacks the possibility to re-add new device in this "
+                       "port\n");
 
        if (strchr(devname, '/')) {
                fprintf(stderr, Name ": incremental removal requires a "