]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - Incremental.c
IMSM - allow assembling any imsm array even without OROM.
[thirdparty/mdadm.git] / Incremental.c
index 9f7f54c7e36202fa3a8afa24f75e771ff34bdc31..bc23a885d5e404358646eb2f4a5b0c8d35b40336 100644 (file)
@@ -2,7 +2,7 @@
  * Incremental.c - support --incremental.  Part of:
  * mdadm - manage Linux "md" devices aka RAID arrays.
  *
- * Copyright (C) 2006-2009 Neil Brown <neilb@suse.de>
+ * Copyright (C) 2006-2012 Neil Brown <neilb@suse.de>
  *
  *
  *    This program is free software; you can redistribute it and/or modify
@@ -116,7 +116,7 @@ int Incremental(char *devname, struct context *c,
                                devname);
                return rv;
        }
-       dfd = dev_open(devname, O_RDONLY|O_EXCL);
+       dfd = dev_open(devname, O_RDONLY);
        if (dfd < 0) {
                if (c->verbose >= 0)
                        pr_err("cannot open %s: %s.\n",
@@ -127,6 +127,8 @@ int Incremental(char *devname, struct context *c,
        if (must_be_container(dfd)) {
                if (!st)
                        st = super_by_fd(dfd, NULL);
+               if (st)
+                       st->ignore_hw_compat = 1;
                if (st && st->ss->load_container)
                        rv = st->ss->load_container(st, dfd, NULL);
 
@@ -185,6 +187,7 @@ int Incremental(char *devname, struct context *c,
                               st, c->verbose);
                goto out;
        }
+       st->ignore_hw_compat = 1;
        if (st->ss->compare_super == NULL ||
            st->ss->load_super(st, dfd, NULL)) {
                if (c->verbose >= 0)
@@ -227,7 +230,6 @@ int Incremental(char *devname, struct context *c,
        else
                trustworthy = FOREIGN;
 
-
        if (!match && !conf_test_metadata(st->ss->name, policy,
                                          (trustworthy == LOCAL))) {
                if (c->verbose >= 1)
@@ -271,6 +273,22 @@ int Incremental(char *devname, struct context *c,
        if (map_lock(&map))
                pr_err("failed to get exclusive lock on "
                        "mapfile\n");
+       /* Now check we can get O_EXCL.  If not, probably "mdadm -A" has
+        * taken over
+        */
+       dfd = dev_open(devname, O_RDONLY|O_EXCL);
+       if (dfd < 0) {
+               if (c->verbose >= 0)
+                       pr_err("cannot reopen %s: %s.\n",
+                               devname, strerror(errno));
+               goto out_unlock;
+       }
+       /* Cannot hold it open while we add the device to the array,
+        * so we must release the O_EXCL and depend on the map_lock()
+        */
+       close(dfd);
+       dfd = -1;
+
        mp = map_by_uuid(&map, info.uuid);
        if (mp)
                mdfd = open_dev(mp->devnum);
@@ -307,7 +325,7 @@ int Incremental(char *devname, struct context *c,
                }
                sra = sysfs_read(mdfd, -1, (GET_DEVS | GET_STATE |
                                            GET_OFFSET | GET_SIZE));
-       
+
                if (!sra || !sra->devs || sra->devs->disk.raid_disk >= 0) {
                        /* It really should be 'none' - must be old buggy
                         * kernel, and mdadm -I may not be able to complete.
@@ -337,7 +355,7 @@ int Incremental(char *devname, struct context *c,
 
                sra = sysfs_read(mdfd, -1, (GET_DEVS | GET_STATE |
                                            GET_OFFSET | GET_SIZE));
-       
+
                if (mp->path)
                        strcpy(chosen_name, mp->path);
                else
@@ -424,7 +442,7 @@ int Incremental(char *devname, struct context *c,
                info.array.working_disks = 0;
                for (d = sra->devs; d; d=d->next)
                        info.array.working_disks ++;
-                       
+
        }
 
        /* 7/ Is there enough devices to possibly start the array? */
@@ -436,7 +454,7 @@ int Incremental(char *devname, struct context *c,
                if (c->verbose >= 0)
                        pr_err("container %s now has %d device%s\n",
                               chosen_name, info.array.working_disks,
-                              info.array.working_disks==1?"":"s");
+                              info.array.working_disks == 1?"":"s");
                wait_for(chosen_name, mdfd);
                if (st->ss->external)
                        devnum = fd2devnum(mdfd);
@@ -495,6 +513,14 @@ int Incremental(char *devname, struct context *c,
        if (c->runstop > 0 || active_disks >= info.array.working_disks) {
                struct mdinfo *dsk;
                /* Let's try to start it */
+
+               if (info.reshape_active && !(info.reshape_active & RESHAPE_NO_BACKUP)) {
+                       fprintf(stderr, Name
+                               ": %s: This array is being reshaped and cannot be started\n"
+                               "      by --incremental.  Please use --assemble\n",
+                               chosen_name);
+                       goto out;
+               }
                if (match && match->bitmap_file) {
                        int bmfd = open(match->bitmap_file, O_RDWR);
                        if (bmfd < 0) {
@@ -618,6 +644,7 @@ static int count_active(struct supertype *st, struct mdinfo *sra,
        /* count how many devices in sra think they are active */
        struct mdinfo *d;
        int cnt = 0;
+       int replcnt = 0;
        __u64 max_events = 0;
        char *avail = NULL;
        int *best = NULL;
@@ -632,7 +659,7 @@ static int count_active(struct supertype *st, struct mdinfo *sra,
 
        for (d = sra->devs ; d ; d = d->next)
                numdevs++;
-       for (d = sra->devs, devnum=0 ; d ; d = d->next, devnum++) {
+       for (d = sra->devs, devnum = 0 ; d ; d = d->next, devnum++) {
                char dn[30];
                int dfd;
                int ok;
@@ -680,7 +707,7 @@ static int count_active(struct supertype *st, struct mdinfo *sra,
                        else if (info.events == max_events+1) {
                                int i;
                                max_events = info.events;
-                               for (i=0; i < raid_disks; i++)
+                               for (i = 0; i < raid_disks; i++)
                                        if (avail[i])
                                                avail[i]--;
                                avail[info.disk.raid_disk] = 2;
@@ -693,7 +720,8 @@ static int count_active(struct supertype *st, struct mdinfo *sra,
                                best[info.disk.raid_disk] = devnum;
                                st->ss->getinfo_super(st, bestinfo, NULL);
                        }
-               }
+               } else if (info.disk.state & (1<<MD_DISK_REPLACEMENT))
+                       replcnt++;
                st->ss->free_super(st);
        }
        if (!avail)
@@ -720,7 +748,7 @@ static int count_active(struct supertype *st, struct mdinfo *sra,
        }
        free(best);
        free(devmap);
-       return cnt;
+       return cnt + replcnt;
 }
 
 /* test if container has degraded member(s) */
@@ -824,7 +852,7 @@ static int array_try_spare(char *devname, int *dfdp, struct dev_policy *pol,
                if (st == NULL) {
                        int i;
                        st2 = NULL;
-                       for(i=0; !st2 && superlist[i]; i++)
+                       for(i = 0; !st2 && superlist[i]; i++)
                                st2 = superlist[i]->match_metadata_desc(
                                        sra->text_version);
                        if (!st2) {
@@ -868,7 +896,11 @@ static int array_try_spare(char *devname, int *dfdp, struct dev_policy *pol,
                        close(mdfd);
                }
                if ((sra->component_size > 0 &&
-                    st2->ss->avail_size(st2, devsize) < sra->component_size)
+                    st2->ss->avail_size(st2, devsize,
+                                        sra->devs
+                                        ? sra->devs->data_offset
+                                        : INVALID_SECTORS)
+                    < sra->component_size)
                    ||
                    (sra->component_size == 0 && devsize < component_size)) {
                        if (verbose > 1)
@@ -1282,6 +1314,9 @@ int IncrementalScan(int verbose)
                                               me->path, strerror(errno));
                        }
                }
+               /* FIXME check for reshape_active and consider not
+                * starting array.
+                */
                sra = sysfs_read(mdfd, 0, 0);
                if (sra) {
                        if (sysfs_set_str(sra, NULL,
@@ -1314,7 +1349,7 @@ static char *container2devname(char *devname)
        } else {
                int uuid[4];
                struct map_ent *mp, *map = NULL;
-                                       
+
                if (!parse_uuid(devname, uuid))
                        return mdname;
                mp = map_by_uuid(&map, uuid);