Blame SOURCES/0053-super1-report-truncated-device.patch

c3a0e9
From 171e9743881edf2dfb163ddff483566fbf913ccd Mon Sep 17 00:00:00 2001
c3a0e9
From: NeilBrown <neilb@suse.de>
c3a0e9
Date: Fri, 26 Aug 2022 08:55:56 +1000
91179e
Subject: [PATCH 53/83] super1: report truncated device
c3a0e9
c3a0e9
When the metadata is at the start of the device, it is possible that it
c3a0e9
describes a device large than the one it is actually stored on.  When
c3a0e9
this happens, report it loudly in --examine.
c3a0e9
c3a0e9
....
c3a0e9
   Unused Space : before=1968 sectors, after=-2047 sectors DEVICE TOO SMALL
c3a0e9
          State : clean TRUNCATED DEVICE
c3a0e9
....
c3a0e9
c3a0e9
Also report in --assemble so that the failure which the kernel will
c3a0e9
report will be explained.
c3a0e9
c3a0e9
mdadm: Device /dev/sdb is not large enough for data described in superblock
c3a0e9
mdadm: no RAID superblock on /dev/sdb
c3a0e9
mdadm: /dev/sdb has no superblock - assembly aborted
c3a0e9
c3a0e9
Scenario can be demonstrated as follows:
c3a0e9
c3a0e9
mdadm: Note: this array has metadata at the start and
c3a0e9
    may not be suitable as a boot device.  If you plan to
c3a0e9
    store '/boot' on this device please ensure that
c3a0e9
    your boot-loader understands md/v1.x metadata, or use
c3a0e9
    --metadata=0.90
c3a0e9
mdadm: Defaulting to version 1.2 metadata
c3a0e9
mdadm: array /dev/md/test started.
c3a0e9
mdadm: stopped /dev/md/test
c3a0e9
   Unused Space : before=1968 sectors, after=-2047 sectors DEVICE TOO SMALL
c3a0e9
          State : clean TRUNCATED DEVICE
c3a0e9
   Unused Space : before=1968 sectors, after=-2047 sectors DEVICE TOO SMALL
c3a0e9
          State : clean TRUNCATED DEVICE
c3a0e9
c3a0e9
Signed-off-by: NeilBrown <neilb@suse.de>
c3a0e9
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
c3a0e9
---
c3a0e9
 super1.c | 35 ++++++++++++++++++++++++++++-------
c3a0e9
 1 file changed, 28 insertions(+), 7 deletions(-)
c3a0e9
c3a0e9
diff --git a/super1.c b/super1.c
c3a0e9
index 71af860c..58345e68 100644
c3a0e9
--- a/super1.c
c3a0e9
+++ b/super1.c
c3a0e9
@@ -406,12 +406,18 @@ static void examine_super1(struct supertype *st, char *homehost)
c3a0e9
 
c3a0e9
 	st->ss->getinfo_super(st, &info, NULL);
c3a0e9
 	if (info.space_after != 1 &&
c3a0e9
-	    !(__le32_to_cpu(sb->feature_map) & MD_FEATURE_NEW_OFFSET))
c3a0e9
-		printf("   Unused Space : before=%llu sectors, after=%llu sectors\n",
c3a0e9
-		       info.space_before, info.space_after);
c3a0e9
-
c3a0e9
-	printf("          State : %s\n",
c3a0e9
-	       (__le64_to_cpu(sb->resync_offset)+1)? "active":"clean");
c3a0e9
+	    !(__le32_to_cpu(sb->feature_map) & MD_FEATURE_NEW_OFFSET)) {
c3a0e9
+		printf("   Unused Space : before=%llu sectors, ",
c3a0e9
+		       info.space_before);
c3a0e9
+		if (info.space_after < INT64_MAX)
c3a0e9
+			printf("after=%llu sectors\n", info.space_after);
c3a0e9
+		else
c3a0e9
+			printf("after=-%llu sectors DEVICE TOO SMALL\n",
c3a0e9
+			       UINT64_MAX - info.space_after);
c3a0e9
+	}
c3a0e9
+	printf("          State : %s%s\n",
c3a0e9
+	       (__le64_to_cpu(sb->resync_offset)+1) ? "active":"clean",
c3a0e9
+	       (info.space_after > INT64_MAX)       ? " TRUNCATED DEVICE" : "");
c3a0e9
 	printf("    Device UUID : ");
c3a0e9
 	for (i=0; i<16; i++) {
c3a0e9
 		if ((i&3)==0 && i != 0)
c3a0e9
@@ -2206,6 +2212,7 @@ static int load_super1(struct supertype *st, int fd, char *devname)
c3a0e9
 		tst.ss = &super;;
c3a0e9
 		for (tst.minor_version = 0; tst.minor_version <= 2;
c3a0e9
 		     tst.minor_version++) {
c3a0e9
+			tst.ignore_hw_compat = st->ignore_hw_compat;
c3a0e9
 			switch(load_super1(&tst, fd, devname)) {
c3a0e9
 			case 0: super = tst.sb;
c3a0e9
 				if (bestvers == -1 ||
c3a0e9
@@ -2312,7 +2319,6 @@ static int load_super1(struct supertype *st, int fd, char *devname)
c3a0e9
 		free(super);
c3a0e9
 		return 2;
c3a0e9
 	}
c3a0e9
-	st->sb = super;
c3a0e9
 
c3a0e9
 	bsb = (struct bitmap_super_s *)(((char*)super)+MAX_SB_SIZE);
c3a0e9
 
c3a0e9
@@ -2322,6 +2328,21 @@ static int load_super1(struct supertype *st, int fd, char *devname)
c3a0e9
 	if (st->data_offset == INVALID_SECTORS)
c3a0e9
 		st->data_offset = __le64_to_cpu(super->data_offset);
c3a0e9
 
c3a0e9
+	if (st->minor_version >= 1 &&
c3a0e9
+	    st->ignore_hw_compat == 0 &&
c3a0e9
+	    (dsize < (__le64_to_cpu(super->data_offset) +
c3a0e9
+		      __le64_to_cpu(super->size))
c3a0e9
+	     ||
c3a0e9
+	     dsize < (__le64_to_cpu(super->data_offset) +
c3a0e9
+		      __le64_to_cpu(super->data_size)))) {
c3a0e9
+		if (devname)
c3a0e9
+			pr_err("Device %s is not large enough for data described in superblock\n",
c3a0e9
+			       devname);
c3a0e9
+		free(super);
c3a0e9
+		return 2;
c3a0e9
+	}
c3a0e9
+	st->sb = super;
c3a0e9
+
c3a0e9
 	/* Now check on the bitmap superblock */
c3a0e9
 	if ((__le32_to_cpu(super->feature_map)&MD_FEATURE_BITMAP_OFFSET) == 0)
c3a0e9
 		return 0;
c3a0e9
-- 
c3a0e9
2.38.1
c3a0e9