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.
358 lines
10 KiB
358 lines
10 KiB
1 month ago
|
From f656201188d73cdc2726265f1348f8ffbf7587be Mon Sep 17 00:00:00 2001
|
||
|
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||
|
Date: Thu, 29 Feb 2024 12:52:06 +0100
|
||
|
Subject: [PATCH 22/41] mdadm: drop get_required_spare_criteria()
|
||
|
|
||
|
Only IMSM implements get_spare_criteria, so load_super() in
|
||
|
get_required_spare_criteria() is dead code. It is moved inside
|
||
|
metadata handler, because only IMSM implements it.
|
||
|
|
||
|
Give possibility to provide devnode to be opened. With that we can hide
|
||
|
load_container() used only to fill spare criteria inside handler
|
||
|
and simplify implementation in generic code.
|
||
|
|
||
|
Add helper function for testing spare criteria in Incremental and
|
||
|
error messages.
|
||
|
|
||
|
File descriptor in get_spare_criteria_imsm() is always opened on purpose.
|
||
|
New functionality added in next patches will require it. For the same
|
||
|
reason, function is moved to other place.
|
||
|
|
||
|
No functional changes.
|
||
|
|
||
|
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||
|
---
|
||
|
Incremental.c | 77 ++++++++++++++++++++++----------
|
||
|
Monitor.c | 35 +++------------
|
||
|
mdadm.h | 5 +--
|
||
|
super-intel.c | 120 +++++++++++++++++++++++++++++++++-----------------
|
||
|
4 files changed, 140 insertions(+), 97 deletions(-)
|
||
|
|
||
|
diff --git a/Incremental.c b/Incremental.c
|
||
|
index 2b5a5859..66c2cc86 100644
|
||
|
--- a/Incremental.c
|
||
|
+++ b/Incremental.c
|
||
|
@@ -833,6 +833,53 @@ container_members_max_degradation(struct map_ent *map, struct map_ent *me)
|
||
|
return max_degraded;
|
||
|
}
|
||
|
|
||
|
+/**
|
||
|
+ * incremental_external_test_spare_criteria() - helper to test spare criteria.
|
||
|
+ * @st: supertype, must be not NULL, it is duplicated here.
|
||
|
+ * @container_devnm: devnm of the container.
|
||
|
+ * @disk_fd: file descriptor of device to tested.
|
||
|
+ * @verbose: verbose flag.
|
||
|
+ *
|
||
|
+ * The function is used on new drive verification path to check if it can be added to external
|
||
|
+ * container. To test spare criteria, metadata must be loaded. It duplicates super to not mess in
|
||
|
+ * original one.
|
||
|
+ * Function is executed if superblock supports get_spare_criteria(), otherwise success is returned.
|
||
|
+ */
|
||
|
+mdadm_status_t incremental_external_test_spare_criteria(struct supertype *st, char *container_devnm,
|
||
|
+ int disk_fd, int verbose)
|
||
|
+{
|
||
|
+ mdadm_status_t rv = MDADM_STATUS_ERROR;
|
||
|
+ char container_devname[PATH_MAX];
|
||
|
+ struct spare_criteria sc = {0};
|
||
|
+ struct supertype *dup;
|
||
|
+
|
||
|
+ if (!st->ss->get_spare_criteria)
|
||
|
+ return MDADM_STATUS_SUCCESS;
|
||
|
+
|
||
|
+ dup = dup_super(st);
|
||
|
+ snprintf(container_devname, PATH_MAX, "/dev/%s", container_devnm);
|
||
|
+
|
||
|
+ if (dup->ss->get_spare_criteria(dup, container_devname, &sc) != 0) {
|
||
|
+ if (verbose > 1)
|
||
|
+ pr_err("Failed to get spare criteria for %s\n", container_devname);
|
||
|
+ goto out;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!disk_fd_matches_criteria(disk_fd, &sc)) {
|
||
|
+ if (verbose > 1)
|
||
|
+ pr_err("Disk does not match spare criteria for %s\n", container_devname);
|
||
|
+ goto out;
|
||
|
+ }
|
||
|
+
|
||
|
+ rv = MDADM_STATUS_SUCCESS;
|
||
|
+
|
||
|
+out:
|
||
|
+ dup->ss->free_super(dup);
|
||
|
+ free(dup);
|
||
|
+
|
||
|
+ return rv;
|
||
|
+}
|
||
|
+
|
||
|
static int array_try_spare(char *devname, int *dfdp, struct dev_policy *pol,
|
||
|
struct map_ent *target, int bare,
|
||
|
struct supertype *st, int verbose)
|
||
|
@@ -873,8 +920,7 @@ static int array_try_spare(char *devname, int *dfdp, struct dev_policy *pol,
|
||
|
struct supertype *st2;
|
||
|
struct domainlist *dl = NULL;
|
||
|
struct mdinfo *sra;
|
||
|
- unsigned long long devsize, freesize = 0;
|
||
|
- struct spare_criteria sc = {0};
|
||
|
+ unsigned long long freesize = 0;
|
||
|
|
||
|
if (is_subarray(mp->metadata))
|
||
|
continue;
|
||
|
@@ -925,34 +971,19 @@ static int array_try_spare(char *devname, int *dfdp, struct dev_policy *pol,
|
||
|
if (sra->array.failed_disks == -1)
|
||
|
sra->array.failed_disks = container_members_max_degradation(map, mp);
|
||
|
|
||
|
- get_dev_size(dfd, NULL, &devsize);
|
||
|
if (sra->component_size == 0) {
|
||
|
- /* true for containers, here we must read superblock
|
||
|
- * to obtain minimum spare size */
|
||
|
- struct supertype *st3 = dup_super(st2);
|
||
|
- int mdfd = open_dev(mp->devnm);
|
||
|
- if (mdfd < 0) {
|
||
|
- free(st3);
|
||
|
+ /* true for containers */
|
||
|
+ if (incremental_external_test_spare_criteria(st2, mp->devnm, dfd, verbose))
|
||
|
goto next;
|
||
|
- }
|
||
|
- if (st3->ss->load_container &&
|
||
|
- !st3->ss->load_container(st3, mdfd, mp->path)) {
|
||
|
- if (st3->ss->get_spare_criteria)
|
||
|
- st3->ss->get_spare_criteria(st3, &sc);
|
||
|
- st3->ss->free_super(st3);
|
||
|
- }
|
||
|
- free(st3);
|
||
|
- close(mdfd);
|
||
|
}
|
||
|
- if ((sra->component_size > 0 &&
|
||
|
- st2->ss->validate_geometry(st2, sra->array.level, sra->array.layout,
|
||
|
+
|
||
|
+ if (sra->component_size > 0 &&
|
||
|
+ st2->ss->validate_geometry(st2, sra->array.level, sra->array.layout,
|
||
|
sra->array.raid_disks, &sra->array.chunk_size,
|
||
|
sra->component_size,
|
||
|
sra->devs ? sra->devs->data_offset : INVALID_SECTORS,
|
||
|
devname, &freesize, sra->consistency_policy,
|
||
|
- 0) &&
|
||
|
- freesize < sra->component_size) ||
|
||
|
- (sra->component_size == 0 && devsize < sc.min_size)) {
|
||
|
+ 0) && freesize < sra->component_size) {
|
||
|
if (verbose > 1)
|
||
|
pr_err("not adding %s to %s as it is too small\n",
|
||
|
devname, mp->path);
|
||
|
diff --git a/Monitor.c b/Monitor.c
|
||
|
index 1ece8712..6b4560ae 100644
|
||
|
--- a/Monitor.c
|
||
|
+++ b/Monitor.c
|
||
|
@@ -1008,34 +1008,6 @@ static int add_new_arrays(struct mdstat_ent *mdstat, struct state **statelist)
|
||
|
return new_found;
|
||
|
}
|
||
|
|
||
|
-static int get_required_spare_criteria(struct state *st,
|
||
|
- struct spare_criteria *sc)
|
||
|
-{
|
||
|
- int fd;
|
||
|
-
|
||
|
- if (!st->metadata || !st->metadata->ss->get_spare_criteria) {
|
||
|
- sc->min_size = 0;
|
||
|
- sc->sector_size = 0;
|
||
|
- return 0;
|
||
|
- }
|
||
|
-
|
||
|
- fd = open(st->devname, O_RDONLY);
|
||
|
- if (fd < 0)
|
||
|
- return 1;
|
||
|
- if (st->metadata->ss->external)
|
||
|
- st->metadata->ss->load_container(st->metadata, fd, st->devname);
|
||
|
- else
|
||
|
- st->metadata->ss->load_super(st->metadata, fd, st->devname);
|
||
|
- close(fd);
|
||
|
- if (!st->metadata->sb)
|
||
|
- return 1;
|
||
|
-
|
||
|
- st->metadata->ss->get_spare_criteria(st->metadata, sc);
|
||
|
- st->metadata->ss->free_super(st->metadata);
|
||
|
-
|
||
|
- return 0;
|
||
|
-}
|
||
|
-
|
||
|
static int check_donor(struct state *from, struct state *to)
|
||
|
{
|
||
|
struct state *sub;
|
||
|
@@ -1178,8 +1150,11 @@ static void try_spare_migration(struct state *statelist)
|
||
|
/* member of a container */
|
||
|
to = to->parent;
|
||
|
|
||
|
- if (get_required_spare_criteria(to, &sc))
|
||
|
- continue;
|
||
|
+ if (to->metadata->ss->get_spare_criteria)
|
||
|
+ if (to->metadata->ss->get_spare_criteria(to->metadata, to->devname,
|
||
|
+ &sc))
|
||
|
+ continue;
|
||
|
+
|
||
|
if (to->metadata->ss->external) {
|
||
|
/* We must make sure there is
|
||
|
* no suitable spare in container already.
|
||
|
diff --git a/mdadm.h b/mdadm.h
|
||
|
index e8abd730..cbc586f5 100644
|
||
|
--- a/mdadm.h
|
||
|
+++ b/mdadm.h
|
||
|
@@ -1116,10 +1116,9 @@ extern struct superswitch {
|
||
|
* Return spare criteria for array:
|
||
|
* - minimum disk size can be used in array;
|
||
|
* - sector size can be used in array.
|
||
|
- * Return values: 0 - for success and -EINVAL on error.
|
||
|
*/
|
||
|
- int (*get_spare_criteria)(struct supertype *st,
|
||
|
- struct spare_criteria *sc);
|
||
|
+ mdadm_status_t (*get_spare_criteria)(struct supertype *st, char *mddev_path,
|
||
|
+ 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
|
||
|
diff --git a/super-intel.c b/super-intel.c
|
||
|
index 39ec4754..7ad391ac 100644
|
||
|
--- a/super-intel.c
|
||
|
+++ b/super-intel.c
|
||
|
@@ -1736,46 +1736,6 @@ static __u32 imsm_min_reserved_sectors(struct intel_super *super)
|
||
|
return (remainder < rv) ? remainder : rv;
|
||
|
}
|
||
|
|
||
|
-/*
|
||
|
- * 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 size = 0;
|
||
|
-
|
||
|
- if (!super)
|
||
|
- 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 -EINVAL;
|
||
|
- /* find last lba used by subarrays */
|
||
|
- e = get_extents(super, dl, 0);
|
||
|
- if (!e)
|
||
|
- return -EINVAL;
|
||
|
- for (i = 0; e[i].size; i++)
|
||
|
- continue;
|
||
|
- if (i > 0)
|
||
|
- size = e[i-1].start + e[i-1].size;
|
||
|
- free(e);
|
||
|
-
|
||
|
- /* add the amount of space needed for metadata */
|
||
|
- size += imsm_min_reserved_sectors(super);
|
||
|
-
|
||
|
- c->min_size = size * 512;
|
||
|
- c->sector_size = super->sector_size;
|
||
|
- c->criteria_set = true;
|
||
|
-
|
||
|
- return 0;
|
||
|
-}
|
||
|
-
|
||
|
static bool is_gen_migration(struct imsm_dev *dev);
|
||
|
|
||
|
#define IMSM_4K_DIV 8
|
||
|
@@ -11295,6 +11255,84 @@ static const char *imsm_get_disk_controller_domain(const char *path)
|
||
|
return drv;
|
||
|
}
|
||
|
|
||
|
+/**
|
||
|
+ * get_spare_criteria_imsm() - set spare criteria.
|
||
|
+ * @st: supertype.
|
||
|
+ * @mddev_path: path to md device devnode, it must be container.
|
||
|
+ * @c: spare_criteria struct to fill, not NULL.
|
||
|
+ *
|
||
|
+ * If superblock is not loaded, use mddev_path to load_container. It must be given in this case.
|
||
|
+ * Filles size and sector size accordingly to superblock.
|
||
|
+ */
|
||
|
+mdadm_status_t get_spare_criteria_imsm(struct supertype *st, char *mddev_path,
|
||
|
+ struct spare_criteria *c)
|
||
|
+{
|
||
|
+ mdadm_status_t ret = MDADM_STATUS_ERROR;
|
||
|
+ bool free_superblock = false;
|
||
|
+ unsigned long long size = 0;
|
||
|
+ struct intel_super *super;
|
||
|
+ struct extent *e;
|
||
|
+ struct dl *dl;
|
||
|
+ int i;
|
||
|
+
|
||
|
+ /* If no superblock and no mddev_path, we cannot load superblock. */
|
||
|
+ assert(st->sb || mddev_path);
|
||
|
+
|
||
|
+ if (mddev_path) {
|
||
|
+ int fd = open(mddev_path, O_RDONLY);
|
||
|
+
|
||
|
+ if (!is_fd_valid(fd))
|
||
|
+ return MDADM_STATUS_ERROR;
|
||
|
+
|
||
|
+ if (!st->sb) {
|
||
|
+ if (load_container_imsm(st, fd, st->devnm)) {
|
||
|
+ close(fd);
|
||
|
+ return MDADM_STATUS_ERROR;
|
||
|
+ }
|
||
|
+ free_superblock = true;
|
||
|
+ }
|
||
|
+ close(fd);
|
||
|
+ }
|
||
|
+
|
||
|
+ super = st->sb;
|
||
|
+
|
||
|
+ /* find first active disk in array */
|
||
|
+ dl = super->disks;
|
||
|
+ while (dl && (is_failed(&dl->disk) || dl->index == -1))
|
||
|
+ dl = dl->next;
|
||
|
+
|
||
|
+ if (!dl)
|
||
|
+ goto out;
|
||
|
+
|
||
|
+ /* find last lba used by subarrays */
|
||
|
+ e = get_extents(super, dl, 0);
|
||
|
+ if (!e)
|
||
|
+ goto out;
|
||
|
+
|
||
|
+ for (i = 0; e[i].size; i++)
|
||
|
+ continue;
|
||
|
+ if (i > 0)
|
||
|
+ size = e[i - 1].start + e[i - 1].size;
|
||
|
+ free(e);
|
||
|
+
|
||
|
+ /* add the amount of space needed for metadata */
|
||
|
+ size += imsm_min_reserved_sectors(super);
|
||
|
+
|
||
|
+ c->min_size = size * 512;
|
||
|
+ c->sector_size = super->sector_size;
|
||
|
+ c->criteria_set = true;
|
||
|
+ ret = MDADM_STATUS_SUCCESS;
|
||
|
+
|
||
|
+out:
|
||
|
+ if (free_superblock)
|
||
|
+ free_super_imsm(st);
|
||
|
+
|
||
|
+ if (ret != MDADM_STATUS_SUCCESS)
|
||
|
+ c->criteria_set = false;
|
||
|
+
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
static char *imsm_find_array_devnm_by_subdev(int subdev, char *container)
|
||
|
{
|
||
|
static char devnm[32];
|
||
|
@@ -11425,7 +11463,7 @@ static struct mdinfo *get_spares_for_grow(struct supertype *st)
|
||
|
{
|
||
|
struct spare_criteria sc;
|
||
|
|
||
|
- get_spare_criteria_imsm(st, &sc);
|
||
|
+ get_spare_criteria_imsm(st, NULL, &sc);
|
||
|
return container_choose_spares(st, &sc, NULL, NULL, NULL, 0);
|
||
|
}
|
||
|
|
||
|
--
|
||
|
2.40.1
|
||
|
|