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

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