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

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