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