]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Monitor: Allow metadata to set minimum size for spare to migrate in.
authorAnna Czarnowska <anna.czarnowska@intel.com>
Mon, 22 Nov 2010 09:58:07 +0000 (20:58 +1100)
committerNeilBrown <neilb@suse.de>
Mon, 22 Nov 2010 09:58:07 +0000 (20:58 +1100)
Signed-off-by: Anna Czarnowska <anna.czarnowska@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
Monitor.c
mdadm.h
super-intel.c

index 793087e0a37c94224e7ccf438e2c286b6d19c514..b907cf2d9142745da5a19c1a6fb95a072f05b266 100644 (file)
--- a/Monitor.c
+++ b/Monitor.c
@@ -681,12 +681,33 @@ static int add_new_arrays(struct mdstat_ent *mdstat, struct state *statelist,
        return new_found;
 }
 
+unsigned long long min_spare_size_required(struct state *st)
+{
+       int fd;
+       unsigned long long rv = 0;
+
+       if (!st->metadata ||
+           !st->metadata->ss->min_acceptable_spare_size)
+               return rv;
+
+       fd = open(st->devname, O_RDONLY);
+       if (fd < 0)
+               return 0;
+       st->metadata->ss->load_super(st->metadata, fd, st->devname);
+       close(fd);
+       rv = st->metadata->ss->min_acceptable_spare_size(st->metadata);
+       st->metadata->ss->free_super(st->metadata);
+
+       return rv;
+}
+
 static int move_spare(struct state *from, struct state *to,
                      struct domainlist *domlist,
                      struct alert_info *info)
 {
        struct mddev_dev devlist;
        char devname[20];
+       unsigned long long min_size;
 
        /* try to remove and add */
        int fd1 = open(to->devname, O_RDONLY);
@@ -698,10 +719,19 @@ static int move_spare(struct state *from, struct state *to,
                if (fd2>=0) close(fd2);
                return 0;
        }
+       min_size = min_spare_size_required(to);
        for (d = from->raid; dev < 0 && d < MaxDisks; d++) {
                if (from->devid[d] > 0 &&
                    from->devstate[d] == 0) {
-                       struct dev_policy *pol = devnum_policy(from->devid[d]);
+                       struct dev_policy *pol;
+                       unsigned long long dev_size;
+
+                       if (min_size &&
+                           dev_size_from_id(from->devid[d], &dev_size) &&
+                           dev_size < min_size)
+                               continue;
+
+                       pol = devnum_policy(from->devid[d]);
                        pol_add(&pol, pol_domain, from->spare_group, NULL);
                        if (domain_test(domlist, pol, to->metadata->ss->name))
                            dev = from->devid[d];
diff --git a/mdadm.h b/mdadm.h
index 83152f7df87586fe3f75a01db47a4fcfe2508fe0..25d2bca3192d33d7bfd42a6bb2a0a839caa344f8 100644 (file)
--- a/mdadm.h
+++ b/mdadm.h
@@ -608,6 +608,7 @@ extern struct superswitch {
        int (*load_container)(struct supertype *st, int fd, char *devname);
        struct supertype * (*match_metadata_desc)(char *arg);
        __u64 (*avail_size)(struct supertype *st, __u64 size);
+       unsigned long long (*min_acceptable_spare_size)(struct supertype *st);
        int (*add_internal_bitmap)(struct supertype *st, int *chunkp,
                                   int delay, int write_behind,
                                   unsigned long long size, int may_change, int major);
index b736e4fb45d93c1588eb8c5b8e836b47d1fd373c..805ee9975c9d8db65cb11d321736841b3c9ea398 100644 (file)
@@ -647,6 +647,37 @@ static int is_failed(struct imsm_disk *disk)
        return (disk->status & FAILED_DISK) == FAILED_DISK;
 }
 
+/* Return minimum size of a spare that can be used in this array*/
+static unsigned long long min_acceptable_spare_size_imsm(struct supertype *st)
+{
+       struct intel_super *super = st->sb;
+       struct dl *dl;
+       struct extent *e;
+       int i;
+       unsigned long long rv = 0;
+
+       if (!super)
+               return rv;
+       /* find first active disk in array */
+       dl = super->disks;
+       while (dl && (is_failed(&dl->disk) || dl->index == -1))
+               dl = dl->next;
+       if (!dl)
+               return rv;
+       /* find last lba used by subarrays */
+       e = get_extents(super, dl);
+       if (!e)
+               return rv;
+       for (i = 0; e[i].size; i++)
+               continue;
+       if (i > 0)
+               rv = e[i-1].start + e[i-1].size;
+       free(e);
+       /* add the amount of space needed for metadata */
+       rv = rv + MPB_SECTOR_CNT + IMSM_RESERVED_SECTORS;
+       return rv * 512;
+}
+
 #ifndef MDASSEMBLE
 static __u64 blocks_per_migr_unit(struct imsm_dev *dev);
 
@@ -5628,6 +5659,7 @@ struct superswitch super_imsm = {
        .update_super   = update_super_imsm,
 
        .avail_size     = avail_size_imsm,
+       .min_acceptable_spare_size = min_acceptable_spare_size_imsm,
 
        .compare_super  = compare_super_imsm,