Blame SOURCES/0073-Manage-imsm-Write-metadata-before-add.patch

d805ba
From 12724c018c964596aa277489fd287d5c3506361a Mon Sep 17 00:00:00 2001
d805ba
From: Tkaczyk Mariusz <mariusz.tkaczyk@intel.com>
d805ba
Date: Fri, 17 Apr 2020 13:55:55 +0200
d805ba
Subject: [RHEL7.9 PATCH 73/77] Manage, imsm: Write metadata before add
d805ba
d805ba
New drive in container always appears as spare. Manager is able to
d805ba
handle that, and queues appropriative update to monitor.
d805ba
No update from mdadm side has to be processed, just insert the drive and
d805ba
ping the mdmon. Metadata has to be written if no mdmon is running (case
d805ba
for Raid0 or container without arrays).
d805ba
d805ba
If bare drive is added very early on startup (by custom bare rule),
d805ba
there is possiblity that mdmon was not restarted after switch root. Old
d805ba
one is not able to handle new drive. New one fails because there is
d805ba
drive without metadata in container and metadata cannot be loaded.
d805ba
d805ba
To prevent this, write spare metadata before adding device
d805ba
to container. Mdmon will overwrite it (same case as spare migration,
d805ba
if drive appears it writes the most recent metadata).
d805ba
Metadata has to be written only on new drive before sysfs_add_disk(),
d805ba
don't race with mdmon if running.
d805ba
d805ba
Signed-off-by: Tkaczyk Mariusz <mariusz.tkaczyk@intel.com>
d805ba
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
d805ba
---
d805ba
 Manage.c      |  6 +-----
d805ba
 super-intel.c | 66 ++++++++++++++++++++++++++++++++++++++---------------------
d805ba
 2 files changed, 44 insertions(+), 28 deletions(-)
d805ba
d805ba
diff --git a/Manage.c b/Manage.c
d805ba
index b22c396..0a5f09b 100644
d805ba
--- a/Manage.c
d805ba
+++ b/Manage.c
d805ba
@@ -994,17 +994,13 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv,
d805ba
 
d805ba
 		Kill(dv->devname, NULL, 0, -1, 0);
d805ba
 		dfd = dev_open(dv->devname, O_RDWR | O_EXCL|O_DIRECT);
d805ba
-		if (mdmon_running(tst->container_devnm))
d805ba
-			tst->update_tail = &tst->updates;
d805ba
 		if (tst->ss->add_to_super(tst, &disc, dfd,
d805ba
 					  dv->devname, INVALID_SECTORS)) {
d805ba
 			close(dfd);
d805ba
 			close(container_fd);
d805ba
 			return -1;
d805ba
 		}
d805ba
-		if (tst->update_tail)
d805ba
-			flush_metadata_updates(tst);
d805ba
-		else
d805ba
+		if (!mdmon_running(tst->container_devnm))
d805ba
 			tst->ss->sync_metadata(tst);
d805ba
 
d805ba
 		sra = sysfs_read(container_fd, NULL, 0);
d805ba
diff --git a/super-intel.c b/super-intel.c
d805ba
index 562a58c..3a73d2b 100644
d805ba
--- a/super-intel.c
d805ba
+++ b/super-intel.c
d805ba
@@ -5809,6 +5809,9 @@ int mark_spare(struct dl *disk)
d805ba
 	return ret_val;
d805ba
 }
d805ba
 
d805ba
+
d805ba
+static int write_super_imsm_spare(struct intel_super *super, struct dl *d);
d805ba
+
d805ba
 static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk,
d805ba
 			     int fd, char *devname,
d805ba
 			     unsigned long long data_offset)
d805ba
@@ -5938,9 +5941,13 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk,
d805ba
 		dd->next = super->disk_mgmt_list;
d805ba
 		super->disk_mgmt_list = dd;
d805ba
 	} else {
d805ba
+		/* this is called outside of mdmon
d805ba
+		 * write initial spare metadata
d805ba
+		 * mdmon will overwrite it.
d805ba
+		 */
d805ba
 		dd->next = super->disks;
d805ba
 		super->disks = dd;
d805ba
-		super->updates_pending++;
d805ba
+		write_super_imsm_spare(super, dd);
d805ba
 	}
d805ba
 
d805ba
 	return 0;
d805ba
@@ -5979,15 +5986,15 @@ static union {
d805ba
 	struct imsm_super anchor;
d805ba
 } spare_record __attribute__ ((aligned(MAX_SECTOR_SIZE)));
d805ba
 
d805ba
-/* spare records have their own family number and do not have any defined raid
d805ba
- * devices
d805ba
- */
d805ba
-static int write_super_imsm_spares(struct intel_super *super, int doclose)
d805ba
+
d805ba
+static int write_super_imsm_spare(struct intel_super *super, struct dl *d)
d805ba
 {
d805ba
 	struct imsm_super *mpb = super->anchor;
d805ba
 	struct imsm_super *spare = &spare_record.anchor;
d805ba
 	__u32 sum;
d805ba
-	struct dl *d;
d805ba
+
d805ba
+	if (d->index != -1)
d805ba
+		return 1;
d805ba
 
d805ba
 	spare->mpb_size = __cpu_to_le32(sizeof(struct imsm_super));
d805ba
 	spare->generation_num = __cpu_to_le32(1UL);
d805ba
@@ -6000,28 +6007,41 @@ static int write_super_imsm_spares(struct intel_super *super, int doclose)
d805ba
 	snprintf((char *) spare->sig, MAX_SIGNATURE_LENGTH,
d805ba
 		 MPB_SIGNATURE MPB_VERSION_RAID0);
d805ba
 
d805ba
-	for (d = super->disks; d; d = d->next) {
d805ba
-		if (d->index != -1)
d805ba
-			continue;
d805ba
+	spare->disk[0] = d->disk;
d805ba
+	if (__le32_to_cpu(d->disk.total_blocks_hi) > 0)
d805ba
+		spare->attributes |= MPB_ATTRIB_2TB_DISK;
d805ba
 
d805ba
-		spare->disk[0] = d->disk;
d805ba
-		if (__le32_to_cpu(d->disk.total_blocks_hi) > 0)
d805ba
-			spare->attributes |= MPB_ATTRIB_2TB_DISK;
d805ba
+	if (super->sector_size == 4096)
d805ba
+		convert_to_4k_imsm_disk(&spare->disk[0]);
d805ba
 
d805ba
-		if (super->sector_size == 4096)
d805ba
-			convert_to_4k_imsm_disk(&spare->disk[0]);
d805ba
+	sum = __gen_imsm_checksum(spare);
d805ba
+	spare->family_num = __cpu_to_le32(sum);
d805ba
+	spare->orig_family_num = 0;
d805ba
+	sum = __gen_imsm_checksum(spare);
d805ba
+	spare->check_sum = __cpu_to_le32(sum);
d805ba
 
d805ba
-		sum = __gen_imsm_checksum(spare);
d805ba
-		spare->family_num = __cpu_to_le32(sum);
d805ba
-		spare->orig_family_num = 0;
d805ba
-		sum = __gen_imsm_checksum(spare);
d805ba
-		spare->check_sum = __cpu_to_le32(sum);
d805ba
+	if (store_imsm_mpb(d->fd, spare)) {
d805ba
+		pr_err("failed for device %d:%d %s\n",
d805ba
+			d->major, d->minor, strerror(errno));
d805ba
+		return 1;
d805ba
+	}
d805ba
+
d805ba
+	return 0;
d805ba
+}
d805ba
+/* spare records have their own family number and do not have any defined raid
d805ba
+ * devices
d805ba
+ */
d805ba
+static int write_super_imsm_spares(struct intel_super *super, int doclose)
d805ba
+{
d805ba
+	struct dl *d;
d805ba
+
d805ba
+	for (d = super->disks; d; d = d->next) {
d805ba
+		if (d->index != -1)
d805ba
+			continue;
d805ba
 
d805ba
-		if (store_imsm_mpb(d->fd, spare)) {
d805ba
-			pr_err("failed for device %d:%d %s\n",
d805ba
-				d->major, d->minor, strerror(errno));
d805ba
+		if (write_super_imsm_spare(super, d))
d805ba
 			return 1;
d805ba
-		}
d805ba
+
d805ba
 		if (doclose) {
d805ba
 			close(d->fd);
d805ba
 			d->fd = -1;
d805ba
-- 
d805ba
2.7.5
d805ba