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>
struct domainlist *dl = NULL;
struct mdinfo *sra;
unsigned long long devsize;
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;
if (is_subarray(mp->metadata))
continue;
}
if (st3->ss->load_container &&
!st3->ss->load_container(st3, mdfd, mp->path)) {
}
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);
st3->ss->free_super(st3);
}
free(st3);
sra->devs ? sra->devs->data_offset :
INVALID_SECTORS) <
sra->component_size) ||
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);
if (verbose > 1)
pr_err("not adding %s to %s as it is too small\n",
devname, mp->path);
struct supertype *sst =
super_imsm.match_metadata_desc("imsm");
struct mdinfo *sinfo;
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)) {
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);
+
- sinfo = container_choose_spares(sst, min_size,
+ sinfo = container_choose_spares(sst, &sc,
domains, NULL,
st->ss->name, 0);
sst->ss->free_super(sst);
domains, NULL,
st->ss->name, 0);
sst->ss->free_super(sst);
-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 ||
{
int fd;
if (!st->metadata ||
- !st->metadata->ss->min_acceptable_spare_size) {
- *sizep = 0;
+ !st->metadata->ss->get_spare_criteria) {
+ sc->min_size = 0;
close(fd);
if (!st->metadata->sb)
return 1;
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;
st->metadata->ss->free_super(st->metadata);
return 0;
}
static dev_t choose_spare(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)
test_partition_from_id(from->devid[d]))
continue;
test_partition_from_id(from->devid[d]))
continue;
dev_size_from_id(from->devid[d], &dev_size) &&
dev_size_from_id(from->devid[d], &dev_size) &&
+ dev_size < sc->min_size)
continue;
pol = devid_policy(from->devid[d]);
continue;
pol = devid_policy(from->devid[d]);
static dev_t container_choose_spare(struct state *from, struct state *to,
struct domainlist *domlist,
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
{
/* This is similar to choose_spare, but we cannot trust devstate,
* so we need to read the metadata instead
}
/* We only need one spare so full list not needed */
}
/* 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;
to->metadata->ss->name, 1);
if (list) {
struct mdinfo *disks = list->devs;
{
struct state *from;
struct state *st;
{
struct state *from;
struct state *st;
+ struct spare_criteria sc;
link_containers_with_subarrays(statelist);
for (st = statelist; st; st = st->next)
link_containers_with_subarrays(statelist);
for (st = statelist; st; st = st->next)
struct domainlist *domlist = NULL;
int d;
struct state *to = st;
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
if (to->parent_devnm[0] && !to->parent)
/* subarray monitored without parent container
/* member of a container */
to = to->parent;
/* 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(
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;
}
if (devid > 0)
continue;
}
continue;
if (from->metadata->ss->external)
devid = container_choose_spare(
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,
else
devid = choose_spare(from, to, domlist,
if (devid > 0
&& move_spare(from->devname, to->devname, devid)) {
alert("MoveSpare", to->devname, from->devname, info);
if (devid > 0
&& move_spare(from->devname, to->devname, devid)) {
alert("MoveSpare", to->devname, from->devname, info);
struct supertype *supertype;
};
struct supertype *supertype;
};
+struct spare_criteria {
+ unsigned long long min_size;
+};
+
enum mode {
ASSEMBLE=1,
BUILD,
enum mode {
ASSEMBLE=1,
BUILD,
*/
__u64 (*avail_size)(struct supertype *st, __u64 size,
unsigned long long data_offset);
*/
__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
/* 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
#define INCR_ALREADY 4
#define INCR_YES 8
extern struct mdinfo *container_choose_spares(struct supertype *st,
#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);
struct domainlist *domlist,
char *spare_group,
const char *metadata, int get_one);
return (remainder < rv) ? remainder : rv;
}
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;
{
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;
/* find first active disk in array */
dl = super->disks;
while (dl && (is_failed(&dl->disk) || dl->index == -1))
dl = dl->next;
if (!dl)
/* find first active disk in array */
dl = super->disks;
while (dl && (is_failed(&dl->disk) || dl->index == -1))
dl = dl->next;
if (!dl)
/* find last lba used by subarrays */
e = get_extents(super, dl);
if (!e)
/* find last lba used by subarrays */
e = get_extents(super, dl);
if (!e)
for (i = 0; e[i].size; i++)
continue;
if (i > 0)
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 */
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;
}
static int is_gen_migration(struct imsm_dev *dev);
}
static int is_gen_migration(struct imsm_dev *dev);
*/
static struct mdinfo *get_spares_for_grow(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);
}
/******************************************************************************
}
/******************************************************************************
.update_super = update_super_imsm,
.avail_size = avail_size_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,
.compare_super = compare_super_imsm,
* 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,
* 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)
struct domainlist *domlist,
char *spare_group,
const char *metadata, int get_one)
unsigned long long dev_size;
dev_t dev = makedev(d->disk.major,d->disk.minor);
unsigned long long dev_size;
dev_t dev = makedev(d->disk.major,d->disk.minor);
+ if (!criteria->min_size ||
(dev_size_from_id(dev, &dev_size) &&
(dev_size_from_id(dev, &dev_size) &&
+ dev_size >= criteria->min_size))
found = 1;
/* check if domain matches */
if (found && domlist) {
found = 1;
/* check if domain matches */
if (found && domlist) {