From: Anna Czarnowska Date: Mon, 22 Nov 2010 09:58:07 +0000 (+1100) Subject: Monitor: Allow metadata to set minimum size for spare to migrate in. X-Git-Tag: mdadm-3.2~250 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=80e7f8c31a514b02d227a083cb2bcb34f70c0eee;p=thirdparty%2Fmdadm.git Monitor: Allow metadata to set minimum size for spare to migrate in. Signed-off-by: Anna Czarnowska Signed-off-by: NeilBrown --- diff --git a/Monitor.c b/Monitor.c index 793087e0..b907cf2d 100644 --- 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 83152f7d..25d2bca3 100644 --- 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); diff --git a/super-intel.c b/super-intel.c index b736e4fb..805ee997 100644 --- a/super-intel.c +++ b/super-intel.c @@ -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,