|
|
dd3a91 |
commit fbfdcb06dc5b1dcb227b0394f174faa2df734700
|
|
|
dd3a91 |
Author: Alexey Obitotskiy <aleksey.obitotskiy@intel.com>
|
|
|
dd3a91 |
Date: Tue May 9 12:25:46 2017 +0200
|
|
|
dd3a91 |
|
|
|
dd3a91 |
Allow more spare selection criteria
|
|
|
dd3a91 |
|
|
|
dd3a91 |
Disks can be moved across containers in order to be used as a spare
|
|
|
dd3a91 |
drive for reubild. At the moment the only requirement checked for such
|
|
|
dd3a91 |
disk is its size (if it matches donor expectations). In order to
|
|
|
dd3a91 |
introduce more criteria rename corresponding superswitch method to more
|
|
|
dd3a91 |
generic name and move function parameter to a structure. This change is
|
|
|
dd3a91 |
a big edit but it doesn't introduce any changes in code logic, it just
|
|
|
dd3a91 |
updates function naming and parameters.
|
|
|
dd3a91 |
|
|
|
dd3a91 |
Signed-off-by: Alexey Obitotskiy <aleksey.obitotskiy@intel.com>
|
|
|
dd3a91 |
Signed-off-by: Tomasz Majchrzak <tomasz.majchrzak@intel.com>
|
|
|
dd3a91 |
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
|
|
|
dd3a91 |
|
|
|
dd3a91 |
diff --git a/Incremental.c b/Incremental.c
|
|
|
dd3a91 |
index 680d318..fe9d644 100644
|
|
|
dd3a91 |
--- a/Incremental.c
|
|
|
dd3a91 |
+++ b/Incremental.c
|
|
|
dd3a91 |
@@ -867,7 +867,7 @@ static int array_try_spare(char *devname, int *dfdp, struct dev_policy *pol,
|
|
|
dd3a91 |
struct domainlist *dl = NULL;
|
|
|
dd3a91 |
struct mdinfo *sra;
|
|
|
dd3a91 |
unsigned long long devsize;
|
|
|
dd3a91 |
- unsigned long long component_size = 0;
|
|
|
dd3a91 |
+ struct spare_criteria sc = {0};
|
|
|
dd3a91 |
|
|
|
dd3a91 |
if (is_subarray(mp->metadata))
|
|
|
dd3a91 |
continue;
|
|
|
dd3a91 |
@@ -936,7 +936,8 @@ static int array_try_spare(char *devname, int *dfdp, struct dev_policy *pol,
|
|
|
dd3a91 |
}
|
|
|
dd3a91 |
if (st3->ss->load_container &&
|
|
|
dd3a91 |
!st3->ss->load_container(st3, mdfd, mp->path)) {
|
|
|
dd3a91 |
- component_size = st3->ss->min_acceptable_spare_size(st3);
|
|
|
dd3a91 |
+ if (st3->ss->get_spare_criteria)
|
|
|
dd3a91 |
+ st3->ss->get_spare_criteria(st3, &sc);
|
|
|
dd3a91 |
st3->ss->free_super(st3);
|
|
|
dd3a91 |
}
|
|
|
dd3a91 |
free(st3);
|
|
|
dd3a91 |
@@ -947,7 +948,7 @@ static int array_try_spare(char *devname, int *dfdp, struct dev_policy *pol,
|
|
|
b7f731 |
sra->devs ? sra->devs->data_offset :
|
|
|
b7f731 |
INVALID_SECTORS) <
|
|
|
b7f731 |
sra->component_size) ||
|
|
|
dd3a91 |
- (sra->component_size == 0 && devsize < component_size)) {
|
|
|
dd3a91 |
+ (sra->component_size == 0 && devsize < sc.min_size)) {
|
|
|
dd3a91 |
if (verbose > 1)
|
|
|
dd3a91 |
pr_err("not adding %s to %s as it is too small\n",
|
|
|
dd3a91 |
devname, mp->path);
|
|
|
dd3a91 |
@@ -1624,12 +1625,15 @@ static int Incremental_container(struct supertype *st, char *devname,
|
|
|
dd3a91 |
struct supertype *sst =
|
|
|
dd3a91 |
super_imsm.match_metadata_desc("imsm");
|
|
|
dd3a91 |
struct mdinfo *sinfo;
|
|
|
dd3a91 |
- unsigned long long min_size = 0;
|
|
|
dd3a91 |
- if (st->ss->min_acceptable_spare_size)
|
|
|
dd3a91 |
- min_size = st->ss->min_acceptable_spare_size(st);
|
|
|
dd3a91 |
+
|
|
|
dd3a91 |
if (!sst->ss->load_container(sst, sfd, NULL)) {
|
|
|
dd3a91 |
+ struct spare_criteria sc = {0};
|
|
|
dd3a91 |
+
|
|
|
dd3a91 |
+ if (st->ss->get_spare_criteria)
|
|
|
dd3a91 |
+ st->ss->get_spare_criteria(st, &sc);
|
|
|
dd3a91 |
+
|
|
|
dd3a91 |
close(sfd);
|
|
|
dd3a91 |
- sinfo = container_choose_spares(sst, min_size,
|
|
|
dd3a91 |
+ sinfo = container_choose_spares(sst, &sc,
|
|
|
dd3a91 |
domains, NULL,
|
|
|
dd3a91 |
st->ss->name, 0);
|
|
|
dd3a91 |
sst->ss->free_super(sst);
|
|
|
dd3a91 |
diff --git a/Monitor.c b/Monitor.c
|
|
|
dd3a91 |
index ec643d4..9a2baad 100644
|
|
|
dd3a91 |
--- a/Monitor.c
|
|
|
dd3a91 |
+++ b/Monitor.c
|
|
|
dd3a91 |
@@ -723,13 +723,14 @@ static int add_new_arrays(struct mdstat_ent *mdstat, struct state **statelist,
|
|
|
dd3a91 |
return new_found;
|
|
|
dd3a91 |
}
|
|
|
dd3a91 |
|
|
|
dd3a91 |
-static int get_min_spare_size_required(struct state *st, unsigned long long *sizep)
|
|
|
dd3a91 |
+static int get_required_spare_criteria(struct state *st,
|
|
|
dd3a91 |
+ struct spare_criteria *sc)
|
|
|
dd3a91 |
{
|
|
|
dd3a91 |
int fd;
|
|
|
dd3a91 |
|
|
|
dd3a91 |
if (!st->metadata ||
|
|
|
dd3a91 |
- !st->metadata->ss->min_acceptable_spare_size) {
|
|
|
dd3a91 |
- *sizep = 0;
|
|
|
dd3a91 |
+ !st->metadata->ss->get_spare_criteria) {
|
|
|
dd3a91 |
+ sc->min_size = 0;
|
|
|
dd3a91 |
return 0;
|
|
|
dd3a91 |
}
|
|
|
dd3a91 |
|
|
|
dd3a91 |
@@ -743,7 +744,8 @@ static int get_min_spare_size_required(struct state *st, unsigned long long *siz
|
|
|
dd3a91 |
close(fd);
|
|
|
dd3a91 |
if (!st->metadata->sb)
|
|
|
dd3a91 |
return 1;
|
|
|
dd3a91 |
- *sizep = st->metadata->ss->min_acceptable_spare_size(st->metadata);
|
|
|
dd3a91 |
+
|
|
|
dd3a91 |
+ st->metadata->ss->get_spare_criteria(st->metadata, sc);
|
|
|
dd3a91 |
st->metadata->ss->free_super(st->metadata);
|
|
|
dd3a91 |
|
|
|
dd3a91 |
return 0;
|
|
|
dd3a91 |
@@ -775,7 +777,7 @@ static int check_donor(struct state *from, struct state *to)
|
|
|
dd3a91 |
}
|
|
|
dd3a91 |
|
|
|
dd3a91 |
static dev_t choose_spare(struct state *from, struct state *to,
|
|
|
dd3a91 |
- struct domainlist *domlist, unsigned long long min_size)
|
|
|
dd3a91 |
+ struct domainlist *domlist, struct spare_criteria *sc)
|
|
|
dd3a91 |
{
|
|
|
dd3a91 |
int d;
|
|
|
dd3a91 |
dev_t dev = 0;
|
|
|
dd3a91 |
@@ -790,9 +792,9 @@ static dev_t choose_spare(struct state *from, struct state *to,
|
|
|
dd3a91 |
test_partition_from_id(from->devid[d]))
|
|
|
dd3a91 |
continue;
|
|
|
dd3a91 |
|
|
|
dd3a91 |
- if (min_size &&
|
|
|
dd3a91 |
+ if (sc->min_size &&
|
|
|
dd3a91 |
dev_size_from_id(from->devid[d], &dev_size) &&
|
|
|
dd3a91 |
- dev_size < min_size)
|
|
|
dd3a91 |
+ dev_size < sc->min_size)
|
|
|
dd3a91 |
continue;
|
|
|
dd3a91 |
|
|
|
dd3a91 |
pol = devid_policy(from->devid[d]);
|
|
|
dd3a91 |
@@ -809,7 +811,7 @@ static dev_t choose_spare(struct state *from, struct state *to,
|
|
|
dd3a91 |
|
|
|
dd3a91 |
static dev_t container_choose_spare(struct state *from, struct state *to,
|
|
|
dd3a91 |
struct domainlist *domlist,
|
|
|
dd3a91 |
- unsigned long long min_size, int active)
|
|
|
dd3a91 |
+ struct spare_criteria *sc, int active)
|
|
|
dd3a91 |
{
|
|
|
dd3a91 |
/* This is similar to choose_spare, but we cannot trust devstate,
|
|
|
dd3a91 |
* so we need to read the metadata instead
|
|
|
dd3a91 |
@@ -860,7 +862,7 @@ static dev_t container_choose_spare(struct state *from, struct state *to,
|
|
|
dd3a91 |
}
|
|
|
dd3a91 |
|
|
|
dd3a91 |
/* We only need one spare so full list not needed */
|
|
|
dd3a91 |
- list = container_choose_spares(st, min_size, domlist, from->spare_group,
|
|
|
dd3a91 |
+ list = container_choose_spares(st, sc, domlist, from->spare_group,
|
|
|
dd3a91 |
to->metadata->ss->name, 1);
|
|
|
dd3a91 |
if (list) {
|
|
|
dd3a91 |
struct mdinfo *disks = list->devs;
|
|
|
dd3a91 |
@@ -876,6 +878,7 @@ static void try_spare_migration(struct state *statelist, struct alert_info *info
|
|
|
dd3a91 |
{
|
|
|
dd3a91 |
struct state *from;
|
|
|
dd3a91 |
struct state *st;
|
|
|
dd3a91 |
+ struct spare_criteria sc;
|
|
|
dd3a91 |
|
|
|
dd3a91 |
link_containers_with_subarrays(statelist);
|
|
|
dd3a91 |
for (st = statelist; st; st = st->next)
|
|
|
dd3a91 |
@@ -884,7 +887,6 @@ static void try_spare_migration(struct state *statelist, struct alert_info *info
|
|
|
dd3a91 |
struct domainlist *domlist = NULL;
|
|
|
dd3a91 |
int d;
|
|
|
dd3a91 |
struct state *to = st;
|
|
|
dd3a91 |
- unsigned long long min_size;
|
|
|
dd3a91 |
|
|
|
dd3a91 |
if (to->parent_devnm[0] && !to->parent)
|
|
|
dd3a91 |
/* subarray monitored without parent container
|
|
|
dd3a91 |
@@ -895,14 +897,14 @@ static void try_spare_migration(struct state *statelist, struct alert_info *info
|
|
|
dd3a91 |
/* member of a container */
|
|
|
dd3a91 |
to = to->parent;
|
|
|
dd3a91 |
|
|
|
dd3a91 |
- if (get_min_spare_size_required(to, &min_size))
|
|
|
dd3a91 |
+ if (get_required_spare_criteria(to, &sc))
|
|
|
dd3a91 |
continue;
|
|
|
dd3a91 |
if (to->metadata->ss->external) {
|
|
|
dd3a91 |
/* We must make sure there is
|
|
|
dd3a91 |
* no suitable spare in container already.
|
|
|
dd3a91 |
* If there is we don't add more */
|
|
|
dd3a91 |
dev_t devid = container_choose_spare(
|
|
|
dd3a91 |
- to, to, NULL, min_size, st->active);
|
|
|
dd3a91 |
+ to, to, NULL, &sc, st->active);
|
|
|
dd3a91 |
if (devid > 0)
|
|
|
dd3a91 |
continue;
|
|
|
dd3a91 |
}
|
|
|
dd3a91 |
@@ -925,10 +927,10 @@ static void try_spare_migration(struct state *statelist, struct alert_info *info
|
|
|
dd3a91 |
continue;
|
|
|
dd3a91 |
if (from->metadata->ss->external)
|
|
|
dd3a91 |
devid = container_choose_spare(
|
|
|
dd3a91 |
- from, to, domlist, min_size, 0);
|
|
|
dd3a91 |
+ from, to, domlist, &sc, 0);
|
|
|
dd3a91 |
else
|
|
|
dd3a91 |
devid = choose_spare(from, to, domlist,
|
|
|
dd3a91 |
- min_size);
|
|
|
dd3a91 |
+ &sc);
|
|
|
dd3a91 |
if (devid > 0
|
|
|
dd3a91 |
&& move_spare(from->devname, to->devname, devid)) {
|
|
|
dd3a91 |
alert("MoveSpare", to->devname, from->devname, info);
|
|
|
dd3a91 |
diff --git a/mdadm.h b/mdadm.h
|
|
|
dd3a91 |
index a92feb2..8da7fd3 100644
|
|
|
dd3a91 |
--- a/mdadm.h
|
|
|
dd3a91 |
+++ b/mdadm.h
|
|
|
dd3a91 |
@@ -361,6 +361,10 @@ struct createinfo {
|
|
|
dd3a91 |
struct supertype *supertype;
|
|
|
dd3a91 |
};
|
|
|
dd3a91 |
|
|
|
dd3a91 |
+struct spare_criteria {
|
|
|
dd3a91 |
+ unsigned long long min_size;
|
|
|
dd3a91 |
+};
|
|
|
dd3a91 |
+
|
|
|
dd3a91 |
enum mode {
|
|
|
dd3a91 |
ASSEMBLE=1,
|
|
|
dd3a91 |
BUILD,
|
|
|
dd3a91 |
@@ -940,11 +944,13 @@ extern struct superswitch {
|
|
|
dd3a91 |
*/
|
|
|
dd3a91 |
__u64 (*avail_size)(struct supertype *st, __u64 size,
|
|
|
dd3a91 |
unsigned long long data_offset);
|
|
|
dd3a91 |
- /* This is similar to 'avail_size' in purpose, but is used for
|
|
|
dd3a91 |
- * containers for which there is no 'component size' to compare.
|
|
|
dd3a91 |
- * This reports that whole-device size which is a minimum
|
|
|
dd3a91 |
+ /*
|
|
|
dd3a91 |
+ * Return spare criteria for array:
|
|
|
dd3a91 |
+ * - minimum disk size can be used in array;
|
|
|
dd3a91 |
+ * Return values: 0 - for success and -EINVAL on error.
|
|
|
dd3a91 |
*/
|
|
|
dd3a91 |
- unsigned long long (*min_acceptable_spare_size)(struct supertype *st);
|
|
|
dd3a91 |
+ int (*get_spare_criteria)(struct supertype *st,
|
|
|
dd3a91 |
+ struct spare_criteria *sc);
|
|
|
dd3a91 |
/* Find somewhere to put a bitmap - possibly auto-size it - and
|
|
|
dd3a91 |
* update the metadata to record this. The array may be newly
|
|
|
dd3a91 |
* created, in which case data_size may be updated, or it might
|
|
|
dd3a91 |
@@ -1507,7 +1513,7 @@ extern int assemble_container_content(struct supertype *st, int mdfd,
|
|
|
dd3a91 |
#define INCR_ALREADY 4
|
|
|
dd3a91 |
#define INCR_YES 8
|
|
|
dd3a91 |
extern struct mdinfo *container_choose_spares(struct supertype *st,
|
|
|
dd3a91 |
- unsigned long long min_size,
|
|
|
dd3a91 |
+ struct spare_criteria *criteria,
|
|
|
dd3a91 |
struct domainlist *domlist,
|
|
|
dd3a91 |
char *spare_group,
|
|
|
dd3a91 |
const char *metadata, int get_one);
|
|
|
dd3a91 |
diff --git a/super-intel.c b/super-intel.c
|
|
|
dd3a91 |
index e88fe82..be973f8 100644
|
|
|
dd3a91 |
--- a/super-intel.c
|
|
|
dd3a91 |
+++ b/super-intel.c
|
|
|
dd3a91 |
@@ -1383,37 +1383,44 @@ static __u32 imsm_min_reserved_sectors(struct intel_super *super)
|
|
|
dd3a91 |
return (remainder < rv) ? remainder : rv;
|
|
|
dd3a91 |
}
|
|
|
dd3a91 |
|
|
|
dd3a91 |
-/* Return minimum size of a spare that can be used in this array*/
|
|
|
dd3a91 |
-static unsigned long long min_acceptable_spare_size_imsm(struct supertype *st)
|
|
|
dd3a91 |
+/*
|
|
|
dd3a91 |
+ * Return minimum size of a spare and sector size
|
|
|
dd3a91 |
+ * that can be used in this array
|
|
|
dd3a91 |
+ */
|
|
|
dd3a91 |
+int get_spare_criteria_imsm(struct supertype *st, struct spare_criteria *c)
|
|
|
dd3a91 |
{
|
|
|
dd3a91 |
struct intel_super *super = st->sb;
|
|
|
dd3a91 |
struct dl *dl;
|
|
|
dd3a91 |
struct extent *e;
|
|
|
dd3a91 |
int i;
|
|
|
dd3a91 |
- unsigned long long rv = 0;
|
|
|
dd3a91 |
+ unsigned long long size = 0;
|
|
|
dd3a91 |
+
|
|
|
dd3a91 |
+ c->min_size = 0;
|
|
|
dd3a91 |
|
|
|
dd3a91 |
if (!super)
|
|
|
dd3a91 |
- return rv;
|
|
|
dd3a91 |
+ return -EINVAL;
|
|
|
dd3a91 |
/* find first active disk in array */
|
|
|
dd3a91 |
dl = super->disks;
|
|
|
dd3a91 |
while (dl && (is_failed(&dl->disk) || dl->index == -1))
|
|
|
dd3a91 |
dl = dl->next;
|
|
|
dd3a91 |
if (!dl)
|
|
|
dd3a91 |
- return rv;
|
|
|
dd3a91 |
+ return -EINVAL;
|
|
|
dd3a91 |
/* find last lba used by subarrays */
|
|
|
dd3a91 |
e = get_extents(super, dl);
|
|
|
dd3a91 |
if (!e)
|
|
|
dd3a91 |
- return rv;
|
|
|
dd3a91 |
+ return -EINVAL;
|
|
|
dd3a91 |
for (i = 0; e[i].size; i++)
|
|
|
dd3a91 |
continue;
|
|
|
dd3a91 |
if (i > 0)
|
|
|
dd3a91 |
- rv = e[i-1].start + e[i-1].size;
|
|
|
dd3a91 |
+ size = e[i-1].start + e[i-1].size;
|
|
|
dd3a91 |
free(e);
|
|
|
dd3a91 |
|
|
|
dd3a91 |
/* add the amount of space needed for metadata */
|
|
|
dd3a91 |
- rv = rv + imsm_min_reserved_sectors(super);
|
|
|
dd3a91 |
+ size += imsm_min_reserved_sectors(super);
|
|
|
dd3a91 |
+
|
|
|
dd3a91 |
+ c->min_size = size * 512;
|
|
|
dd3a91 |
|
|
|
dd3a91 |
- return rv * 512;
|
|
|
dd3a91 |
+ return 0;
|
|
|
dd3a91 |
}
|
|
|
dd3a91 |
|
|
|
dd3a91 |
static int is_gen_migration(struct imsm_dev *dev);
|
|
|
dd3a91 |
@@ -10817,8 +10824,10 @@ static int imsm_reshape_is_allowed_on_container(struct supertype *st,
|
|
|
dd3a91 |
*/
|
|
|
dd3a91 |
static struct mdinfo *get_spares_for_grow(struct supertype *st)
|
|
|
dd3a91 |
{
|
|
|
dd3a91 |
- unsigned long long min_size = min_acceptable_spare_size_imsm(st);
|
|
|
dd3a91 |
- return container_choose_spares(st, min_size, NULL, NULL, NULL, 0);
|
|
|
dd3a91 |
+ struct spare_criteria sc;
|
|
|
dd3a91 |
+
|
|
|
dd3a91 |
+ get_spare_criteria_imsm(st, &sc);
|
|
|
dd3a91 |
+ return container_choose_spares(st, &sc, NULL, NULL, NULL, 0);
|
|
|
dd3a91 |
}
|
|
|
dd3a91 |
|
|
|
dd3a91 |
/******************************************************************************
|
|
|
dd3a91 |
@@ -11853,7 +11862,7 @@ struct superswitch super_imsm = {
|
|
|
dd3a91 |
.update_super = update_super_imsm,
|
|
|
dd3a91 |
|
|
|
dd3a91 |
.avail_size = avail_size_imsm,
|
|
|
dd3a91 |
- .min_acceptable_spare_size = min_acceptable_spare_size_imsm,
|
|
|
dd3a91 |
+ .get_spare_criteria = get_spare_criteria_imsm,
|
|
|
dd3a91 |
|
|
|
dd3a91 |
.compare_super = compare_super_imsm,
|
|
|
dd3a91 |
|
|
|
dd3a91 |
diff --git a/util.c b/util.c
|
|
|
dd3a91 |
index 11ff2cc..8b3c67d 100644
|
|
|
dd3a91 |
--- a/util.c
|
|
|
dd3a91 |
+++ b/util.c
|
|
|
dd3a91 |
@@ -2107,7 +2107,7 @@ int experimental(void)
|
|
|
dd3a91 |
* if spare_group given add it to domains of each spare
|
|
|
dd3a91 |
* metadata allows to test domains using metadata of destination array */
|
|
|
dd3a91 |
struct mdinfo *container_choose_spares(struct supertype *st,
|
|
|
dd3a91 |
- unsigned long long min_size,
|
|
|
dd3a91 |
+ struct spare_criteria *criteria,
|
|
|
dd3a91 |
struct domainlist *domlist,
|
|
|
dd3a91 |
char *spare_group,
|
|
|
dd3a91 |
const char *metadata, int get_one)
|
|
|
dd3a91 |
@@ -2131,9 +2131,9 @@ struct mdinfo *container_choose_spares(struct supertype *st,
|
|
|
dd3a91 |
unsigned long long dev_size;
|
|
|
dd3a91 |
dev_t dev = makedev(d->disk.major,d->disk.minor);
|
|
|
dd3a91 |
|
|
|
dd3a91 |
- if (!min_size ||
|
|
|
dd3a91 |
+ if (!criteria->min_size ||
|
|
|
dd3a91 |
(dev_size_from_id(dev, &dev_size) &&
|
|
|
dd3a91 |
- dev_size >= min_size))
|
|
|
dd3a91 |
+ dev_size >= criteria->min_size))
|
|
|
dd3a91 |
found = 1;
|
|
|
dd3a91 |
/* check if domain matches */
|
|
|
dd3a91 |
if (found && domlist) {
|