]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - Assemble.c
get_info_super: report which other devices are thought to be working/failed.
[thirdparty/mdadm.git] / Assemble.c
index afd4e60a283f7cfb641463e200775bda04b701b8..0900f26a16bcab9d87181fc6feab75498c9ca8fb 100644 (file)
@@ -230,6 +230,7 @@ int Assemble(struct supertype *st, char *mddev,
                int dfd;
                struct stat stb;
                struct supertype *tst = dup_super(st);
+               struct dev_policy *pol = NULL;
 
                if (tmpdev->used > 1) continue;
 
@@ -262,10 +263,16 @@ int Assemble(struct supertype *st, char *mddev,
                        tmpdev->used = 2;
                } else if (tst->ss->load_super(tst,dfd, NULL)) {
                        if (report_missmatch)
-                               fprintf( stderr, Name ": no RAID superblock on %s\n",
-                                        devname);
+                               fprintf(stderr, Name ": no RAID superblock on %s\n",
+                                       devname);
+               } else if (tst->ss->compare_super == NULL) {
+                       if (report_missmatch)
+                               fprintf(stderr, Name ": Cannot assemble %s metadata on %s\n",
+                                       tst->ss->name, devname);
+                       tst->ss->free_super(tst);
+                       tmpdev->used = 2;
                } else if (auto_assem && st == NULL &&
-                          !conf_test_metadata(tst->ss->name,
+                          !conf_test_metadata(tst->ss->name, (pol = devnum_policy(stb.st_rdev)),
                                               tst->ss->match_home(tst, homehost) == 1)) {
                        if (report_missmatch)
                                fprintf(stderr, Name ": %s has metadata type %s for which "
@@ -276,7 +283,7 @@ int Assemble(struct supertype *st, char *mddev,
                } else {
                        content = &info;
                        memset(content, 0, sizeof(*content));
-                       tst->ss->getinfo_super(tst, content);
+                       tst->ss->getinfo_super(tst, content, NULL);
                }
                if (dfd >= 0) close(dfd);
 
@@ -397,6 +404,7 @@ int Assemble(struct supertype *st, char *mddev,
                                devname);
                        if (st)
                                st->ss->free_super(st);
+                       dev_policy_free(pol);
                        return 1;
                }
 
@@ -418,6 +426,7 @@ int Assemble(struct supertype *st, char *mddev,
                                content = NULL;
                                if (auto_assem)
                                        goto loop;
+                               dev_policy_free(pol);
                                return 1;
                        }
                        if (ident->member && ident->member[0]) {
@@ -441,6 +450,7 @@ int Assemble(struct supertype *st, char *mddev,
                                        "only device given: confused and aborting\n",
                                        devname);
                                st->ss->free_super(st);
+                               dev_policy_free(pol);
                                return 1;
                        }
                        if (verbose > 0)
@@ -490,12 +500,15 @@ int Assemble(struct supertype *st, char *mddev,
                                devname);
                        tst->ss->free_super(tst);
                        st->ss->free_super(st);
+                       dev_policy_free(pol);
                        return 1;
                }
 
                tmpdev->used = 1;
 
        loop:
+               dev_policy_free(pol);
+               pol = NULL;
                if (tmpdev->content)
                        goto next_member;
                if (tst)
@@ -507,7 +520,7 @@ int Assemble(struct supertype *st, char *mddev,
 
        /* Now need to open the array device.  Use create_mddev */
        if (content == &info)
-               st->ss->getinfo_super(st, content);
+               st->ss->getinfo_super(st, content, NULL);
 
        trustworthy = FOREIGN;
        name = content->name;
@@ -602,6 +615,7 @@ int Assemble(struct supertype *st, char *mddev,
                        /* prepare useful information in info structures */
                        struct stat stb2;
                        struct supertype *tst;
+                       int err;
                        fstat(mdfd, &stb2);
 
                        if (strcmp(update, "uuid")==0 &&
@@ -629,28 +643,39 @@ int Assemble(struct supertype *st, char *mddev,
                                close(mdfd);
                                return 1;
                        }
-                       tst->ss->getinfo_super(tst, content);
+                       tst->ss->getinfo_super(tst, content, NULL);
 
                        memcpy(content->uuid, ident->uuid, 16);
                        strcpy(content->name, ident->name);
                        content->array.md_minor = minor(stb2.st_rdev);
 
-                       tst->ss->update_super(tst, content, update,
-                                             devname, verbose,
-                                             ident->uuid_set, homehost);
+                       if (strcmp(update, "byteorder") == 0)
+                               err = 0;
+                       else
+                               err = tst->ss->update_super(tst, content, update,
+                                                           devname, verbose,
+                                                           ident->uuid_set,
+                                                           homehost);
+                       if (err < 0) {
+                               fprintf(stderr,
+                                       Name ": --update=%s not understood"
+                                       " for %s metadata\n",
+                                       update, tst->ss->name);
+                               tst->ss->free_super(tst);
+                               free(tst);
+                               close(mdfd);
+                               close(dfd);
+                               return 1;
+                       }
                        if (strcmp(update, "uuid")==0 &&
                            !ident->uuid_set) {
                                ident->uuid_set = 1;
                                memcpy(ident->uuid, content->uuid, 16);
                        }
-                       if (dfd < 0)
-                               fprintf(stderr, Name ": Cannot open %s for superblock update\n",
-                                       devname);
-                       else if (tst->ss->store_super(tst, dfd))
+                       if (tst->ss->store_super(tst, dfd))
                                fprintf(stderr, Name ": Could not re-write superblock on %s.\n",
                                        devname);
-                       if (dfd >= 0)
-                               close(dfd);
+                       close(dfd);
 
                        if (strcmp(update, "uuid")==0 &&
                            ident->bitmap_fd >= 0 && !bitmap_done) {
@@ -679,7 +704,7 @@ int Assemble(struct supertype *st, char *mddev,
                                close(mdfd);
                                return 1;
                        }
-                       tst->ss->getinfo_super(tst, content);
+                       tst->ss->getinfo_super(tst, content, NULL);
                        tst->ss->free_super(tst);
                        close(dfd);
                }
@@ -773,7 +798,7 @@ int Assemble(struct supertype *st, char *mddev,
        if (update && strcmp(update, "byteorder")==0)
                st->minor_version = 90;
 
-       st->ss->getinfo_super(st, content);
+       st->ss->getinfo_super(st, content, NULL);
        clean = content->array.state & 1;
 
        /* now we have some devices that might be suitable.
@@ -930,7 +955,7 @@ int Assemble(struct supertype *st, char *mddev,
                close(mdfd);
                return 1;
        }
-       st->ss->getinfo_super(st, content);
+       st->ss->getinfo_super(st, content, NULL);
 #ifndef MDASSEMBLE
        sysfs_init(content, mdfd, 0);
 #endif
@@ -1189,6 +1214,29 @@ int Assemble(struct supertype *st, char *mddev,
                                                                      (4 * content->array.chunk_size / 4096) + 1);
                                        }
                                }
+                               if (okcnt < (unsigned)content->array.raid_disks) {
+                                       /* If any devices did not get added
+                                        * because the kernel rejected them based
+                                        * on event count, try adding them
+                                        * again providing the action policy is
+                                        * 're-add' or greater.  The bitmap
+                                        * might allow them to be included, or
+                                        * they will become spares.
+                                        */
+                                       for (i = 0; i <= bestcnt; i++) {
+                                               int j = best[i];
+                                               if (j >= 0 && !devices[j].uptodate) {
+                                                       if (!disk_action_allows(&devices[j].i, st->ss->name, act_re_add))
+                                                               continue;
+                                                       rv = add_disk(mdfd, st, content,
+                                                                     &devices[j].i);
+                                                       if (rv == 0 && verbose >= 0)
+                                                               fprintf(stderr,
+                                                                       Name ": %s has been re-added.\n",
+                                                                       devices[j].devname);
+                                               }
+                                       }
+                               }
                                wait_for(mddev, mdfd);
                                close(mdfd);
                                if (auto_assem) {