453 lines
12 KiB
Diff
453 lines
12 KiB
Diff
|
From 8a4ce2c053866ac97feb436c4c85a54446ee0016 Mon Sep 17 00:00:00 2001
|
||
|
From: Logan Gunthorpe <logang@deltatee.com>
|
||
|
Date: Wed, 1 Mar 2023 13:41:31 -0700
|
||
|
Subject: [PATCH 101/120] Create: Factor out add_disks() helpers
|
||
|
|
||
|
The Create function is massive with a very large number of variables.
|
||
|
Reading and understanding the function is almost impossible. To help
|
||
|
with this, factor out the two pass loop that adds the disks to the array.
|
||
|
|
||
|
This moves about 160 lines into three new helper functions and removes
|
||
|
a bunch of local variables from the main Create function. The main new
|
||
|
helper function add_disks() does the two pass loop and calls into
|
||
|
add_disk_to_super() and update_metadata(). Factoring out the
|
||
|
latter two helpers also helps to reduce a ton of indentation.
|
||
|
|
||
|
No functional changes intended.
|
||
|
|
||
|
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
|
||
|
Acked-by: Kinga Tanska <kinga.tanska@linux.intel.com>
|
||
|
Reviewed-by: Xiao Ni <xni@redhat.com>
|
||
|
Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com>
|
||
|
Acked-by: Coly Li <colyli@suse.de>
|
||
|
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
|
||
|
---
|
||
|
Create.c | 382 +++++++++++++++++++++++++++++++------------------------
|
||
|
1 file changed, 213 insertions(+), 169 deletions(-)
|
||
|
|
||
|
diff --git a/Create.c b/Create.c
|
||
|
index 8ded81dc..6a044664 100644
|
||
|
--- a/Create.c
|
||
|
+++ b/Create.c
|
||
|
@@ -91,6 +91,214 @@ int default_layout(struct supertype *st, int level, int verbose)
|
||
|
return layout;
|
||
|
}
|
||
|
|
||
|
+static int add_disk_to_super(int mdfd, struct shape *s, struct context *c,
|
||
|
+ struct supertype *st, struct mddev_dev *dv,
|
||
|
+ struct mdinfo *info, int have_container, int major_num)
|
||
|
+{
|
||
|
+ dev_t rdev;
|
||
|
+ int fd;
|
||
|
+
|
||
|
+ if (dv->disposition == 'j') {
|
||
|
+ info->disk.raid_disk = MD_DISK_ROLE_JOURNAL;
|
||
|
+ info->disk.state = (1<<MD_DISK_JOURNAL);
|
||
|
+ } else if (info->disk.raid_disk < s->raiddisks) {
|
||
|
+ info->disk.state = (1<<MD_DISK_ACTIVE) |
|
||
|
+ (1<<MD_DISK_SYNC);
|
||
|
+ } else {
|
||
|
+ info->disk.state = 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (dv->writemostly == FlagSet) {
|
||
|
+ if (major_num == BITMAP_MAJOR_CLUSTERED) {
|
||
|
+ pr_err("Can not set %s --write-mostly with a clustered bitmap\n",dv->devname);
|
||
|
+ return 1;
|
||
|
+ } else {
|
||
|
+ info->disk.state |= (1<<MD_DISK_WRITEMOSTLY);
|
||
|
+ }
|
||
|
+
|
||
|
+ }
|
||
|
+
|
||
|
+ if (dv->failfast == FlagSet)
|
||
|
+ info->disk.state |= (1<<MD_DISK_FAILFAST);
|
||
|
+
|
||
|
+ if (have_container) {
|
||
|
+ fd = -1;
|
||
|
+ } else {
|
||
|
+ if (st->ss->external && st->container_devnm[0])
|
||
|
+ fd = open(dv->devname, O_RDWR);
|
||
|
+ else
|
||
|
+ fd = open(dv->devname, O_RDWR|O_EXCL);
|
||
|
+
|
||
|
+ if (fd < 0) {
|
||
|
+ pr_err("failed to open %s after earlier success - aborting\n",
|
||
|
+ dv->devname);
|
||
|
+ return 1;
|
||
|
+ }
|
||
|
+ if (!fstat_is_blkdev(fd, dv->devname, &rdev))
|
||
|
+ return 1;
|
||
|
+ info->disk.major = major(rdev);
|
||
|
+ info->disk.minor = minor(rdev);
|
||
|
+ }
|
||
|
+ if (fd >= 0)
|
||
|
+ remove_partitions(fd);
|
||
|
+ if (st->ss->add_to_super(st, &info->disk, fd, dv->devname,
|
||
|
+ dv->data_offset)) {
|
||
|
+ ioctl(mdfd, STOP_ARRAY, NULL);
|
||
|
+ return 1;
|
||
|
+ }
|
||
|
+ st->ss->getinfo_super(st, info, NULL);
|
||
|
+
|
||
|
+ if (have_container && c->verbose > 0)
|
||
|
+ pr_err("Using %s for device %d\n",
|
||
|
+ map_dev(info->disk.major, info->disk.minor, 0),
|
||
|
+ info->disk.number);
|
||
|
+
|
||
|
+ if (!have_container) {
|
||
|
+ /* getinfo_super might have lost these ... */
|
||
|
+ info->disk.major = major(rdev);
|
||
|
+ info->disk.minor = minor(rdev);
|
||
|
+ }
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int update_metadata(int mdfd, struct shape *s, struct supertype *st,
|
||
|
+ struct map_ent **map, struct mdinfo *info,
|
||
|
+ char *chosen_name)
|
||
|
+{
|
||
|
+ struct mdinfo info_new;
|
||
|
+ struct map_ent *me = NULL;
|
||
|
+
|
||
|
+ /* check to see if the uuid has changed due to these
|
||
|
+ * metadata changes, and if so update the member array
|
||
|
+ * and container uuid. Note ->write_init_super clears
|
||
|
+ * the subarray cursor such that ->getinfo_super once
|
||
|
+ * again returns container info.
|
||
|
+ */
|
||
|
+ st->ss->getinfo_super(st, &info_new, NULL);
|
||
|
+ if (st->ss->external && is_container(s->level) &&
|
||
|
+ !same_uuid(info_new.uuid, info->uuid, 0)) {
|
||
|
+ map_update(map, fd2devnm(mdfd),
|
||
|
+ info_new.text_version,
|
||
|
+ info_new.uuid, chosen_name);
|
||
|
+ me = map_by_devnm(map, st->container_devnm);
|
||
|
+ }
|
||
|
+
|
||
|
+ if (st->ss->write_init_super(st)) {
|
||
|
+ st->ss->free_super(st);
|
||
|
+ return 1;
|
||
|
+ }
|
||
|
+
|
||
|
+ /*
|
||
|
+ * Before activating the array, perform extra steps
|
||
|
+ * required to configure the internal write-intent
|
||
|
+ * bitmap.
|
||
|
+ */
|
||
|
+ if (info_new.consistency_policy == CONSISTENCY_POLICY_BITMAP &&
|
||
|
+ st->ss->set_bitmap && st->ss->set_bitmap(st, info)) {
|
||
|
+ st->ss->free_super(st);
|
||
|
+ return 1;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* update parent container uuid */
|
||
|
+ if (me) {
|
||
|
+ char *path = xstrdup(me->path);
|
||
|
+
|
||
|
+ st->ss->getinfo_super(st, &info_new, NULL);
|
||
|
+ map_update(map, st->container_devnm, info_new.text_version,
|
||
|
+ info_new.uuid, path);
|
||
|
+ free(path);
|
||
|
+ }
|
||
|
+
|
||
|
+ flush_metadata_updates(st);
|
||
|
+ st->ss->free_super(st);
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int add_disks(int mdfd, struct mdinfo *info, struct shape *s,
|
||
|
+ struct context *c, struct supertype *st,
|
||
|
+ struct map_ent **map, struct mddev_dev *devlist,
|
||
|
+ int total_slots, int have_container, int insert_point,
|
||
|
+ int major_num, char *chosen_name)
|
||
|
+{
|
||
|
+ struct mddev_dev *moved_disk = NULL;
|
||
|
+ int pass, raid_disk_num, dnum;
|
||
|
+ struct mddev_dev *dv;
|
||
|
+ struct mdinfo *infos;
|
||
|
+ int ret = 0;
|
||
|
+
|
||
|
+ infos = xmalloc(sizeof(*infos) * total_slots);
|
||
|
+ enable_fds(total_slots);
|
||
|
+ for (pass = 1; pass <= 2; pass++) {
|
||
|
+ for (dnum = 0, raid_disk_num = 0, dv = devlist; dv;
|
||
|
+ dv = (dv->next) ? (dv->next) : moved_disk, dnum++) {
|
||
|
+ if (dnum >= total_slots)
|
||
|
+ abort();
|
||
|
+ if (dnum == insert_point) {
|
||
|
+ raid_disk_num += 1;
|
||
|
+ moved_disk = dv;
|
||
|
+ continue;
|
||
|
+ }
|
||
|
+ if (strcasecmp(dv->devname, "missing") == 0) {
|
||
|
+ raid_disk_num += 1;
|
||
|
+ continue;
|
||
|
+ }
|
||
|
+ if (have_container)
|
||
|
+ moved_disk = NULL;
|
||
|
+ if (have_container && dnum < total_slots - 1)
|
||
|
+ /* repeatedly use the container */
|
||
|
+ moved_disk = dv;
|
||
|
+
|
||
|
+ switch(pass) {
|
||
|
+ case 1:
|
||
|
+ infos[dnum] = *info;
|
||
|
+ infos[dnum].disk.number = dnum;
|
||
|
+ infos[dnum].disk.raid_disk = raid_disk_num++;
|
||
|
+
|
||
|
+ if (dv->disposition == 'j')
|
||
|
+ raid_disk_num--;
|
||
|
+
|
||
|
+ ret = add_disk_to_super(mdfd, s, c, st, dv,
|
||
|
+ &infos[dnum], have_container,
|
||
|
+ major_num);
|
||
|
+ if (ret)
|
||
|
+ goto out;
|
||
|
+
|
||
|
+ break;
|
||
|
+ case 2:
|
||
|
+ infos[dnum].errors = 0;
|
||
|
+
|
||
|
+ ret = add_disk(mdfd, st, info, &infos[dnum]);
|
||
|
+ if (ret) {
|
||
|
+ pr_err("ADD_NEW_DISK for %s failed: %s\n",
|
||
|
+ dv->devname, strerror(errno));
|
||
|
+ if (errno == EINVAL &&
|
||
|
+ info->array.level == 0) {
|
||
|
+ pr_err("Possibly your kernel doesn't support RAID0 layouts.\n");
|
||
|
+ pr_err("Either upgrade, or use --layout=dangerous\n");
|
||
|
+ }
|
||
|
+ goto out;
|
||
|
+ }
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ if (!have_container &&
|
||
|
+ dv == moved_disk && dnum != insert_point) break;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (pass == 1) {
|
||
|
+ ret = update_metadata(mdfd, s, st, map, info,
|
||
|
+ chosen_name);
|
||
|
+ if (ret)
|
||
|
+ goto out;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+out:
|
||
|
+ free(infos);
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
int Create(struct supertype *st, char *mddev,
|
||
|
char *name, int *uuid,
|
||
|
int subdevs, struct mddev_dev *devlist,
|
||
|
@@ -117,7 +325,7 @@ int Create(struct supertype *st, char *mddev,
|
||
|
unsigned long long minsize = 0, maxsize = 0;
|
||
|
char *mindisc = NULL;
|
||
|
char *maxdisc = NULL;
|
||
|
- int dnum, raid_disk_num;
|
||
|
+ int dnum;
|
||
|
struct mddev_dev *dv;
|
||
|
dev_t rdev;
|
||
|
int fail = 0, warn = 0;
|
||
|
@@ -126,14 +334,13 @@ int Create(struct supertype *st, char *mddev,
|
||
|
int missing_disks = 0;
|
||
|
int insert_point = subdevs * 2; /* where to insert a missing drive */
|
||
|
int total_slots;
|
||
|
- int pass;
|
||
|
int rv;
|
||
|
int bitmap_fd;
|
||
|
int have_container = 0;
|
||
|
int container_fd = -1;
|
||
|
int need_mdmon = 0;
|
||
|
unsigned long long bitmapsize;
|
||
|
- struct mdinfo info, *infos;
|
||
|
+ struct mdinfo info;
|
||
|
int did_default = 0;
|
||
|
int do_default_layout = 0;
|
||
|
int do_default_chunk = 0;
|
||
|
@@ -869,174 +1076,11 @@ int Create(struct supertype *st, char *mddev,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
- infos = xmalloc(sizeof(*infos) * total_slots);
|
||
|
- enable_fds(total_slots);
|
||
|
- for (pass = 1; pass <= 2; pass++) {
|
||
|
- struct mddev_dev *moved_disk = NULL; /* the disk that was moved out of the insert point */
|
||
|
-
|
||
|
- for (dnum = 0, raid_disk_num = 0, dv = devlist; dv;
|
||
|
- dv = (dv->next) ? (dv->next) : moved_disk, dnum++) {
|
||
|
- int fd;
|
||
|
- struct mdinfo *inf = &infos[dnum];
|
||
|
-
|
||
|
- if (dnum >= total_slots)
|
||
|
- abort();
|
||
|
- if (dnum == insert_point) {
|
||
|
- raid_disk_num += 1;
|
||
|
- moved_disk = dv;
|
||
|
- continue;
|
||
|
- }
|
||
|
- if (strcasecmp(dv->devname, "missing") == 0) {
|
||
|
- raid_disk_num += 1;
|
||
|
- continue;
|
||
|
- }
|
||
|
- if (have_container)
|
||
|
- moved_disk = NULL;
|
||
|
- if (have_container && dnum < info.array.raid_disks - 1)
|
||
|
- /* repeatedly use the container */
|
||
|
- moved_disk = dv;
|
||
|
-
|
||
|
- switch(pass) {
|
||
|
- case 1:
|
||
|
- *inf = info;
|
||
|
-
|
||
|
- inf->disk.number = dnum;
|
||
|
- inf->disk.raid_disk = raid_disk_num++;
|
||
|
-
|
||
|
- if (dv->disposition == 'j') {
|
||
|
- inf->disk.raid_disk = MD_DISK_ROLE_JOURNAL;
|
||
|
- inf->disk.state = (1<<MD_DISK_JOURNAL);
|
||
|
- raid_disk_num--;
|
||
|
- } else if (inf->disk.raid_disk < s->raiddisks)
|
||
|
- inf->disk.state = (1<<MD_DISK_ACTIVE) |
|
||
|
- (1<<MD_DISK_SYNC);
|
||
|
- else
|
||
|
- inf->disk.state = 0;
|
||
|
-
|
||
|
- if (dv->writemostly == FlagSet) {
|
||
|
- if (major_num == BITMAP_MAJOR_CLUSTERED) {
|
||
|
- pr_err("Can not set %s --write-mostly with a clustered bitmap\n",dv->devname);
|
||
|
- goto abort_locked;
|
||
|
- } else
|
||
|
- inf->disk.state |= (1<<MD_DISK_WRITEMOSTLY);
|
||
|
- }
|
||
|
- if (dv->failfast == FlagSet)
|
||
|
- inf->disk.state |= (1<<MD_DISK_FAILFAST);
|
||
|
-
|
||
|
- if (have_container)
|
||
|
- fd = -1;
|
||
|
- else {
|
||
|
- if (st->ss->external &&
|
||
|
- st->container_devnm[0])
|
||
|
- fd = open(dv->devname, O_RDWR);
|
||
|
- else
|
||
|
- fd = open(dv->devname, O_RDWR|O_EXCL);
|
||
|
-
|
||
|
- if (fd < 0) {
|
||
|
- pr_err("failed to open %s after earlier success - aborting\n",
|
||
|
- dv->devname);
|
||
|
- goto abort_locked;
|
||
|
- }
|
||
|
- if (!fstat_is_blkdev(fd, dv->devname, &rdev))
|
||
|
- goto abort_locked;
|
||
|
- inf->disk.major = major(rdev);
|
||
|
- inf->disk.minor = minor(rdev);
|
||
|
- }
|
||
|
- if (fd >= 0)
|
||
|
- remove_partitions(fd);
|
||
|
- if (st->ss->add_to_super(st, &inf->disk,
|
||
|
- fd, dv->devname,
|
||
|
- dv->data_offset)) {
|
||
|
- ioctl(mdfd, STOP_ARRAY, NULL);
|
||
|
- goto abort_locked;
|
||
|
- }
|
||
|
- st->ss->getinfo_super(st, inf, NULL);
|
||
|
-
|
||
|
- if (have_container && c->verbose > 0)
|
||
|
- pr_err("Using %s for device %d\n",
|
||
|
- map_dev(inf->disk.major,
|
||
|
- inf->disk.minor,
|
||
|
- 0), dnum);
|
||
|
-
|
||
|
- if (!have_container) {
|
||
|
- /* getinfo_super might have lost these ... */
|
||
|
- inf->disk.major = major(rdev);
|
||
|
- inf->disk.minor = minor(rdev);
|
||
|
- }
|
||
|
- break;
|
||
|
- case 2:
|
||
|
- inf->errors = 0;
|
||
|
-
|
||
|
- rv = add_disk(mdfd, st, &info, inf);
|
||
|
-
|
||
|
- if (rv) {
|
||
|
- pr_err("ADD_NEW_DISK for %s failed: %s\n",
|
||
|
- dv->devname, strerror(errno));
|
||
|
- if (errno == EINVAL &&
|
||
|
- info.array.level == 0) {
|
||
|
- pr_err("Possibly your kernel doesn't support RAID0 layouts.\n");
|
||
|
- pr_err("Either upgrade, or use --layout=dangerous\n");
|
||
|
- }
|
||
|
- goto abort_locked;
|
||
|
- }
|
||
|
- break;
|
||
|
- }
|
||
|
- if (!have_container &&
|
||
|
- dv == moved_disk && dnum != insert_point) break;
|
||
|
- }
|
||
|
- if (pass == 1) {
|
||
|
- struct mdinfo info_new;
|
||
|
- struct map_ent *me = NULL;
|
||
|
-
|
||
|
- /* check to see if the uuid has changed due to these
|
||
|
- * metadata changes, and if so update the member array
|
||
|
- * and container uuid. Note ->write_init_super clears
|
||
|
- * the subarray cursor such that ->getinfo_super once
|
||
|
- * again returns container info.
|
||
|
- */
|
||
|
- st->ss->getinfo_super(st, &info_new, NULL);
|
||
|
- if (st->ss->external && !is_container(s->level) &&
|
||
|
- !same_uuid(info_new.uuid, info.uuid, 0)) {
|
||
|
- map_update(&map, fd2devnm(mdfd),
|
||
|
- info_new.text_version,
|
||
|
- info_new.uuid, chosen_name);
|
||
|
- me = map_by_devnm(&map, st->container_devnm);
|
||
|
- }
|
||
|
-
|
||
|
- if (st->ss->write_init_super(st)) {
|
||
|
- st->ss->free_super(st);
|
||
|
- goto abort_locked;
|
||
|
- }
|
||
|
- /*
|
||
|
- * Before activating the array, perform extra steps
|
||
|
- * required to configure the internal write-intent
|
||
|
- * bitmap.
|
||
|
- */
|
||
|
- if (info_new.consistency_policy ==
|
||
|
- CONSISTENCY_POLICY_BITMAP &&
|
||
|
- st->ss->set_bitmap &&
|
||
|
- st->ss->set_bitmap(st, &info)) {
|
||
|
- st->ss->free_super(st);
|
||
|
- goto abort_locked;
|
||
|
- }
|
||
|
-
|
||
|
- /* update parent container uuid */
|
||
|
- if (me) {
|
||
|
- char *path = xstrdup(me->path);
|
||
|
-
|
||
|
- st->ss->getinfo_super(st, &info_new, NULL);
|
||
|
- map_update(&map, st->container_devnm,
|
||
|
- info_new.text_version,
|
||
|
- info_new.uuid, path);
|
||
|
- free(path);
|
||
|
- }
|
||
|
+ if (add_disks(mdfd, &info, s, c, st, &map, devlist, total_slots,
|
||
|
+ have_container, insert_point, major_num, chosen_name))
|
||
|
+ goto abort_locked;
|
||
|
|
||
|
- flush_metadata_updates(st);
|
||
|
- st->ss->free_super(st);
|
||
|
- }
|
||
|
- }
|
||
|
map_unlock(&map);
|
||
|
- free(infos);
|
||
|
|
||
|
if (is_container(s->level)) {
|
||
|
/* No need to start. But we should signal udev to
|
||
|
--
|
||
|
2.38.1
|
||
|
|