]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - Assemble.c
Enable bitmap support for external metadata
[thirdparty/mdadm.git] / Assemble.c
index 5a907c14aa4e333613891e69825d45ee3b842b94..5c6aca9253ac8da062b254847410ee2729562b45 100644 (file)
@@ -269,7 +269,7 @@ static int select_devices(struct mddev_dev *devlist,
                        if (auto_assem || !inargv)
                                /* Ignore unrecognised devices during auto-assembly */
                                goto loop;
-                       if (ident->uuid_set || ident->name[0] ||
+                       if (ident->name[0] ||
                            ident->super_minor != UnSet)
                                /* Ignore unrecognised device if looking for
                                 * specific array */
@@ -281,6 +281,8 @@ static int select_devices(struct mddev_dev *devlist,
                                st->ss->free_super(st);
                        dev_policy_free(pol);
                        domain_free(domains);
+                       if (tst)
+                               tst->ss->free_super(tst);
                        return -1;
                }
 
@@ -433,7 +435,7 @@ static int select_devices(struct mddev_dev *devlist,
 
                        if (st->ss != tst->ss ||
                            st->minor_version != tst->minor_version ||
-                           st->ss->compare_super(st, tst) != 0) {
+                           st->ss->compare_super(st, tst, 1) != 0) {
                                /* Some mismatch. If exactly one array matches this host,
                                 * we can resolve on that one.
                                 * Or, if we are auto assembling, we just ignore the second
@@ -576,6 +578,7 @@ static int load_devices(struct devs *devices, char *devmap,
                struct supertype *tst;
                int i;
                int dfd;
+               int disk_state;
 
                if (tmpdev->used != 1)
                        continue;
@@ -592,6 +595,9 @@ static int load_devices(struct devs *devices, char *devmap,
                        if (strcmp(c->update, "ppl") == 0 &&
                            ident->bitmap_fd >= 0) {
                                pr_err("PPL is not compatible with bitmap\n");
+                               close(mdfd);
+                               free(devices);
+                               free(devmap);
                                return -1;
                        }
 
@@ -706,7 +712,9 @@ static int load_devices(struct devs *devices, char *devmap,
                devices[devcnt].i.disk.major = major(stb.st_rdev);
                devices[devcnt].i.disk.minor = minor(stb.st_rdev);
 
-               if (devices[devcnt].i.disk.state == 6) {
+               disk_state = devices[devcnt].i.disk.state & ~((1<<MD_DISK_FAILFAST) |
+                                                             (1<<MD_DISK_WRITEMOSTLY));
+               if (disk_state == ((1<<MD_DISK_ACTIVE) | (1<<MD_DISK_SYNC))) {
                        if (most_recent < 0 ||
                            devices[devcnt].i.events
                            > devices[most_recent].i.events) {
@@ -871,7 +879,7 @@ static int force_array(struct mdinfo *content,
                current_events = devices[chosen_drive].i.events;
        add_another:
                if (c->verbose >= 0)
-                       pr_err("forcing event count in %s(%d) from %d upto %d\n",
+                       pr_err("forcing event count in %s(%d) from %d up to %d\n",
                               devices[chosen_drive].devname,
                               devices[chosen_drive].i.disk.raid_disk,
                               (int)(devices[chosen_drive].i.events),
@@ -1023,6 +1031,11 @@ static int start_array(int mdfd,
                                pr_err("failed to add %s to %s: %s\n",
                                       devices[j].devname, mddev,
                                       strerror(errno));
+                               if (errno == EINVAL && content->array.level == 0 &&
+                                   content->array.layout != 0) {
+                                       cont_err("Possibly your kernel doesn't support RAID0 layouts.\n");
+                                       cont_err("Please upgrade.\n");
+                               }
                                if (i < content->array.raid_disks * 2 ||
                                    i == bestcnt)
                                        okcnt--;
@@ -1055,9 +1068,12 @@ static int start_array(int mdfd,
                               mddev, okcnt + sparecnt + journalcnt,
                               okcnt + sparecnt + journalcnt == 1 ? "" : "s");
                        if (okcnt < (unsigned)content->array.raid_disks)
-                               fprintf(stderr, " (out of %d)",
+                               fprintf(stderr, " (out of %d)\n",
                                        content->array.raid_disks);
-                       fprintf(stderr, "\n");
+                       else {
+                               fprintf(stderr, "\n");
+                               sysfs_rules_apply(mddev, content);
+                       }
                }
 
                if (st->ss->validate_container) {
@@ -1131,6 +1147,7 @@ static int start_array(int mdfd,
                        rv = ioctl(mdfd, RUN_ARRAY, NULL);
                reopen_mddev(mdfd); /* drop O_EXCL */
                if (rv == 0) {
+                       sysfs_rules_apply(mddev, content);
                        if (c->verbose >= 0) {
                                pr_err("%s has been started with %d drive%s",
                                       mddev, okcnt, okcnt==1?"":"s");
@@ -1208,6 +1225,9 @@ static int start_array(int mdfd,
                        return 0;
                }
                pr_err("failed to RUN_ARRAY %s: %s\n", mddev, strerror(errno));
+               if (errno == 524 /* ENOTSUP */ &&
+                   content->array.level == 0 && content->array.layout == 0)
+                       cont_err("Please use --update=layout-original or --update=layout-alternate\n");
 
                if (!enough(content->array.level, content->array.raid_disks,
                            content->array.layout, 1, avail))
@@ -1346,9 +1366,6 @@ int Assemble(struct supertype *st, char *mddev,
        char chosen_name[1024];
        struct map_ent *map = NULL;
        struct map_ent *mp;
-       int locked = 0;
-       struct mdp_superblock_1 *sb;
-       bitmap_super_t *bms;
 
        /*
         * If any subdevs are listed, then any that don't
@@ -1379,12 +1396,6 @@ try_again:
         * set of devices failed.  Those are now marked as ->used==2 and
         * we ignore them and try again
         */
-       if (locked)
-               /*
-                * if come back try_again is called, then need to unlock first,
-                * and lock again since the metadate is re-read.
-                */
-               cluster_release_dlmlock();
        if (!st && ident->st)
                st = ident->st;
        if (c->verbose>0)
@@ -1402,14 +1413,6 @@ try_again:
        if (!st || !st->sb || !content)
                return 2;
 
-       sb = st->sb;
-       bms = (bitmap_super_t*)(((char*)sb) + 4096);
-       if (sb && bms->version == BITMAP_MAJOR_CLUSTERED) {
-               locked = cluster_get_dlmlock();
-               if (locked != 1)
-                       return 1;
-       }
-
        /* We have a full set of devices - we now need to find the
         * array device.
         * However there is a risk that we are racing with "mdadm -I"
@@ -1479,6 +1482,10 @@ try_again:
                                name = content->name;
                        break;
                }
+               if (mddev && map_by_name(&map, mddev) != NULL) {
+                       pr_err("Cannot create device with %s because is in use\n", mddev);
+                       goto out;
+               }
                if (!auto_assem)
                        /* If the array is listed in mdadm.conf or on
                         * command line, then we trust the name
@@ -1540,8 +1547,6 @@ try_again:
                err = assemble_container_content(st, mdfd, content, c,
                                                 chosen_name, NULL);
                close(mdfd);
-               if (locked == 1)
-                       cluster_release_dlmlock();
                return err;
        }
 
@@ -1553,6 +1558,11 @@ try_again:
                              &most_recent, &bestcnt, &best, inargv);
        if (devcnt < 0) {
                mdfd = -3;
+               /*
+                * devices is already freed in load_devices, so set devices
+                * to NULL to avoid double free devices.
+                */
+               devices = NULL;
                goto out;
        }
 
@@ -1713,6 +1723,9 @@ try_again:
                else
                        desired_state = (1<<MD_DISK_ACTIVE) | (1<<MD_DISK_SYNC);
 
+               desired_state |= devices[j].i.disk.state & ((1<<MD_DISK_FAILFAST) |
+                                                           (1<<MD_DISK_WRITEMOSTLY));
+
                if (!devices[j].uptodate)
                        continue;
 
@@ -1886,8 +1899,6 @@ out:
                close(mdfd);
 
        /* '2' means 'OK, but not started yet' */
-       if (locked == 1)
-               cluster_release_dlmlock();
        if (rv == -1) {
                free(devices);
                return 1;
@@ -2023,6 +2034,15 @@ int assemble_container_content(struct supertype *st, int mdfd,
                        free(avail);
                        return err;
                }
+       } else if (c->force) {
+               /* Set the array as 'clean' so that we can proceed with starting
+                * it even if we don't have all devices. Mdmon doesn't care
+                * if the dirty flag is set in metadata, it will start managing
+                * it anyway.
+                * This is really important for raid456 (RWH case), other levels
+                * are started anyway.
+                */
+               content->array.state |= 1;
        }
 
        if (enough(content->array.level, content->array.raid_disks,
@@ -2042,22 +2062,45 @@ int assemble_container_content(struct supertype *st, int mdfd,
        }
        free(avail);
 
-       if (c->runstop <= 0 &&
-           (working + preexist + expansion) <
-           content->array.working_disks) {
-               if (c->export && result)
-                       *result |= INCR_UNSAFE;
-               else if (c->verbose >= 0) {
-                       pr_err("%s assembled with %d device%s",
-                              chosen_name, preexist + working,
-                              preexist + working == 1 ? "":"s");
-                       if (preexist)
-                               fprintf(stderr, " (%d new)", working);
-                       fprintf(stderr, " but not safe to start\n");
+       if ((working + preexist + expansion) < content->array.working_disks) {
+               if (c->runstop <= 0) {
+                       if (c->export && result)
+                               *result |= INCR_UNSAFE;
+                       else if (c->verbose >= 0) {
+                               pr_err("%s assembled with %d device%s",
+                                       chosen_name, preexist + working,
+                                       preexist + working == 1 ? "":"s");
+                               if (preexist)
+                                       fprintf(stderr, " (%d new)", working);
+                               fprintf(stderr, " but not safe to start\n");
+                               if (c->force)
+                                       pr_err("Consider --run to start array as degraded.\n");
+                       }
+                       return 1;
+               } else if (content->array.level >= 4 &&
+                          content->array.level <= 6 &&
+                          content->resync_start != MaxSector &&
+                          c->force) {
+                       /* Don't inform the kernel that the array is not
+                        * clean and requires resync.
+                        */
+                       content->resync_start = MaxSector;
+                       err = sysfs_set_num(content, NULL, "resync_start",
+                                           MaxSector);
+                       if (err)
+                               return 1;
+                       pr_err("%s array state forced to clean. It may cause data corruption.\n",
+                               chosen_name);
                }
-               return 1;
        }
 
+       /*
+        * Before activating the array, perform extra steps required
+        * to configure the internal write-intent bitmap.
+        */
+       if (content->consistency_policy == CONSISTENCY_POLICY_BITMAP &&
+           st->ss->set_bitmap)
+               st->ss->set_bitmap(st, content);
 
        if (start_reshape) {
                int spare = content->array.raid_disks + expansion;
@@ -2066,8 +2109,22 @@ int assemble_container_content(struct supertype *st, int mdfd,
                                   spare, &c->backup_file, c->verbose) == 1)
                        return 1;
 
-               err = sysfs_set_str(content, NULL,
-                                   "array_state", "readonly");
+               if (content->reshape_progress == 0) {
+                       /* If reshape progress is 0 - we are assembling the
+                        * array that was stopped, before reshape has started.
+                        * Array needs to be started as active, Grow_continue()
+                        * will start the reshape.
+                        */
+                       sysfs_set_num(content, NULL, "reshape_position",
+                                     MaxSector);
+                       err = sysfs_set_str(content, NULL,
+                                           "array_state", "active");
+                       sysfs_set_num(content, NULL, "reshape_position", 0);
+               } else {
+                       err = sysfs_set_str(content, NULL,
+                                           "array_state", "readonly");
+               }
+
                if (err)
                        return 1;
 
@@ -2121,10 +2178,12 @@ int assemble_container_content(struct supertype *st, int mdfd,
                        pr_err("array %s now has %d device%s",
                               chosen_name, working + preexist,
                               working + preexist == 1 ? "":"s");
-               else
+               else {
+                       sysfs_rules_apply(chosen_name, content);
                        pr_err("Started %s with %d device%s",
                               chosen_name, working + preexist,
                               working + preexist == 1 ? "":"s");
+               }
                if (preexist)
                        fprintf(stderr, " (%d new)", working);
                if (expansion)