]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - Assemble.c
Fix possible crash if bitmap metadata is bad.
[thirdparty/mdadm.git] / Assemble.c
index 5ed2dc1c8a3b7e8b57846c1ae4f0cc92db1ff6b2..ab8faeddf1d142cfa448d76859c51619f27cecfa 100644 (file)
@@ -367,7 +367,8 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
                tmpdev->used = 1;
 
        loop:
-               tst->ss->free_super(tst);
+               if (tst)
+                       tst->ss->free_super(tst);
        }
 
        if (mdfd < 0) {
@@ -385,9 +386,9 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
                if (c) c++; else c= info.name;
                if (isdigit(*c) && ((ident->autof & 7)==4 || (ident->autof&7)==6))
                        /* /dev/md/d0 style for partitionable */
-                       asprintf(&mddev, "/dev/md/d%s", c);
+                       xasprintf(&mddev, "/dev/md/d%s", c);
                else
-                       asprintf(&mddev, "/dev/md/%s", c);
+                       xasprintf(&mddev, "/dev/md/%s", c);
                mdfd = open_mddev(mddev, ident->autof);
                if (mdfd < 0) {
                        st->ss->free_super(st);
@@ -568,17 +569,18 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
                devcnt++;
        }
 
-       if (update && strcmp(update, "byteorder")==0)
-               st->minor_version = 90;
-
        if (devcnt == 0) {
                fprintf(stderr, Name ": no devices found for %s\n",
                        mddev);
-               st->ss->free_super(st);
+               if (st)
+                       st->ss->free_super(st);
                if (must_close) close(mdfd);
                return 1;
        }
 
+       if (update && strcmp(update, "byteorder")==0)
+               st->minor_version = 90;
+
        st->ss->getinfo_super(st, &info);
        clean = info.array.state & 1;
 
@@ -630,7 +632,6 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
                        int j = best[i];
                        if (j>=0 &&
                            !devices[j].uptodate &&
-                           devices[j].i.events > 0 &&
                            (chosen_drive < 0 ||
                             devices[j].i.events
                             > devices[chosen_drive].i.events))
@@ -654,7 +655,7 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
                        continue;
                }
                tst = dup_super(st);
-               if (tst->ss->load_super(st,fd, NULL)) {
+               if (tst->ss->load_super(tst,fd, NULL)) {
                        close(fd);
                        fprintf(stderr, Name ": RAID superblock disappeared from %s - not updating.\n",
                                devices[chosen_drive].devname);
@@ -688,7 +689,6 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
                        int j = best[i];
                        if (j >= 0 &&
                            !devices[j].uptodate &&
-                           devices[j].i.events > 0 &&
                            devices[j].i.events == current_events) {
                                chosen_drive = j;
                                goto add_another;
@@ -749,6 +749,8 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
                        continue;
 
                devices[j].i.disk.state = desired_state;
+               if (!(devices[j].i.array.state & 1))
+                       clean = 0;
 
                if (st->ss->update_super(st, &devices[j].i, "assemble", NULL,
                                         verbose, 0, NULL)) {
@@ -932,6 +934,20 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
                                                fprintf(stderr, " and %d spare%s", sparecnt, sparecnt==1?"":"s");
                                        fprintf(stderr, ".\n");
                                }
+                               if (info.reshape_active &&
+                                   info.array.level >= 4 &&
+                                   info.array.level <= 6) {
+                                       /* might need to increase the size
+                                        * of the stripe cache - default is 256
+                                        */
+                                       if (256 < 4 * (info.array.chunk_size/4096)) {
+                                               struct mdinfo *sra = sysfs_read(mdfd, 0, 0);
+                                               if (sra)
+                                                       sysfs_set_num(sra, NULL,
+                                                                     "stripe_cache_size",
+                                                                     (4 * info.array.chunk_size / 4096) + 1);
+                                       }
+                               }
                                if (must_close) {
                                        int usecs = 1;
                                        close(mdfd);