850cf2857b
- SLE15 continues to use mdadm-4.0, synchronize mdadm package from SLE12-SP3 to SLE15, re-order all patches. - Rename the following patches, they are deleted and re-add in next part of patches 0001-Generic-support-for-consistency-policy-and-PPL.patch 0002-Detail-show-consistency-policy.patch 0002-The-mdcheck-script-now-adds-messages-to-the-system.patch 0003-imsm-PPL-support.patch 0004-super1-PPL-support.patch 0005-Add-ppl-and-no-ppl-options-for-update.patch 0006-Grow-support-consistency-policy-change.patch 0007-udev-md-raid-assembly.rules-Skip-non-ready-devices.patch 0008-Retry-HOT_REMOVE_DISK-a-few-times.patch 0009-Introduce-sys_hot_remove_disk.patch 0010-Add-force-flag-to-hot_remove_disk.patch 0011-Detail-handle-non-existent-arrays-better.patch - Synchronize patches from mdadm of SLE12-SP3, the above renamed patches are re-add here, 0001-Makefile-Fix-date-to-be-output-in-ISO-format.patch 0002-imsm-fix-missing-error-message-during-migration.patch 0003-Fix-oddity-where-mdadm-did-not-recognise-a-relative-.patch 0004-mdadm-check-the-nodes-when-operate-clustered-array.patch 0005-examine-tidy-up-some-code.patch 0006-mdadm-add-man-page-for-symlinks.patch 0007-mdadm-add-checking-clustered-bitmap-in-assemble-mode.patch 0008-mdadm-Add-Wimplicit-fallthrough-0-in-Makefile.patch 0009-mdadm-Specify-enough-length-when-write-to-buffer.patch 0010-mdadm-it-doesn-t-make-sense-to-set-bitmap-twice.patch 0011-mdadm-Monitor-Fix-NULL-pointer-dereference-when-stat.patch 0012-Replace-snprintf-with-strncpy-at-some-places-to-avoi.patch OBS-URL: https://build.opensuse.org/request/show/517978 OBS-URL: https://build.opensuse.org/package/show/Base:System/mdadm?expand=0&rev=150
344 lines
11 KiB
Diff
344 lines
11 KiB
Diff
From fbfdcb06dc5b1dcb227b0394f174faa2df734700 Mon Sep 17 00:00:00 2001
|
|
From: Alexey Obitotskiy <aleksey.obitotskiy@intel.com>
|
|
Date: Tue, 9 May 2017 12:25:46 +0200
|
|
Subject: [PATCH] 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>
|
|
---
|
|
Incremental.c | 18 +++++++++++-------
|
|
Monitor.c | 30 ++++++++++++++++--------------
|
|
mdadm.h | 16 +++++++++++-----
|
|
super-intel.c | 33 +++++++++++++++++++++------------
|
|
util.c | 6 +++---
|
|
5 files changed, 62 insertions(+), 41 deletions(-)
|
|
|
|
Index: mdadm/Incremental.c
|
|
===================================================================
|
|
--- mdadm.orig/Incremental.c
|
|
+++ mdadm/Incremental.c
|
|
@@ -889,7 +889,7 @@ static int array_try_spare(char *devname
|
|
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;
|
|
@@ -958,7 +958,8 @@ static int array_try_spare(char *devname
|
|
}
|
|
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);
|
|
@@ -969,9 +970,8 @@ static int array_try_spare(char *devname
|
|
sra->devs
|
|
? sra->devs->data_offset
|
|
: INVALID_SECTORS)
|
|
- < sra->component_size)
|
|
- ||
|
|
- (sra->component_size == 0 && devsize < component_size)) {
|
|
+ < sra->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);
|
|
@@ -1655,12 +1655,15 @@ static int Incremental_container(struct
|
|
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);
|
|
Index: mdadm/Monitor.c
|
|
===================================================================
|
|
--- mdadm.orig/Monitor.c
|
|
+++ mdadm/Monitor.c
|
|
@@ -746,13 +746,14 @@ static int add_new_arrays(struct mdstat_
|
|
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;
|
|
}
|
|
|
|
@@ -766,7 +767,8 @@ static int get_min_spare_size_required(s
|
|
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;
|
|
@@ -798,7 +800,7 @@ static int check_donor(struct state *fro
|
|
}
|
|
|
|
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;
|
|
@@ -813,9 +815,9 @@ static dev_t choose_spare(struct state *
|
|
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]);
|
|
@@ -832,7 +834,7 @@ static dev_t choose_spare(struct state *
|
|
|
|
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
|
|
@@ -883,7 +885,7 @@ static dev_t container_choose_spare(stru
|
|
}
|
|
|
|
/* 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;
|
|
@@ -899,6 +901,7 @@ static void try_spare_migration(struct s
|
|
{
|
|
struct state *from;
|
|
struct state *st;
|
|
+ struct spare_criteria sc;
|
|
|
|
link_containers_with_subarrays(statelist);
|
|
for (st = statelist; st; st = st->next)
|
|
@@ -907,7 +910,6 @@ static void try_spare_migration(struct s
|
|
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
|
|
@@ -918,14 +920,14 @@ static void try_spare_migration(struct s
|
|
/* 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;
|
|
}
|
|
@@ -948,10 +950,10 @@ static void try_spare_migration(struct s
|
|
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);
|
|
Index: mdadm/mdadm.h
|
|
===================================================================
|
|
--- mdadm.orig/mdadm.h
|
|
+++ mdadm/mdadm.h
|
|
@@ -351,6 +351,10 @@ struct createinfo {
|
|
struct supertype *supertype;
|
|
};
|
|
|
|
+struct spare_criteria {
|
|
+ unsigned long long min_size;
|
|
+};
|
|
+
|
|
enum mode {
|
|
ASSEMBLE=1,
|
|
BUILD,
|
|
@@ -929,11 +933,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
|
|
@@ -1491,7 +1497,7 @@ extern int assemble_container_content(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);
|
|
Index: mdadm/super-intel.c
|
|
===================================================================
|
|
--- mdadm.orig/super-intel.c
|
|
+++ mdadm/super-intel.c
|
|
@@ -1386,37 +1386,44 @@ static __u32 imsm_min_reserved_sectors(s
|
|
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);
|
|
@@ -10868,8 +10875,10 @@ static int imsm_reshape_is_allowed_on_co
|
|
*/
|
|
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);
|
|
}
|
|
|
|
/******************************************************************************
|
|
@@ -11908,7 +11917,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,
|
|
|
|
Index: mdadm/util.c
|
|
===================================================================
|
|
--- mdadm.orig/util.c
|
|
+++ mdadm/util.c
|
|
@@ -2083,7 +2083,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)
|
|
@@ -2107,9 +2107,9 @@ struct mdinfo *container_choose_spares(s
|
|
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) {
|