dcavalca / rpms / mdadm

Forked from rpms/mdadm 3 years ago
Clone

Blame SOURCES/imsm-validate-multiple-ppls-during-assemble.patch

2c1b57
From 44b6b87610281a4add36a1addd7630095dc8a545 Mon Sep 17 00:00:00 2001
2c1b57
From: Pawel Baldysiak <pawel.baldysiak@intel.com>
2c1b57
Date: Thu, 28 Sep 2017 14:41:10 +0200
2c1b57
Subject: [PATCH 04/12] imsm: validate multiple ppls during assemble
2c1b57
2c1b57
Change validation algorithm to check validity of multiple ppls that
2c1b57
are stored in PPL area.
2c1b57
2c1b57
If read error occurs during - treat the all PPLs as invalid -
2c1b57
there is no guarantee that this one was not latest. If the header CRC is
2c1b57
incorrect - assume that there are no further PPLs in PPL area.
2c1b57
2c1b57
If whole PPL area was written at least once - there is a possibility that
2c1b57
old PPL (with lower generation number) will follow the recent one
2c1b57
(with higest generation number). Compare those generation numbers to check
2c1b57
which PPL is latest.
2c1b57
2c1b57
Signed-off-by: Pawel Baldysiak <pawel.baldysiak@intel.com>
2c1b57
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
2c1b57
---
2c1b57
 super-intel.c | 71 +++++++++++++++++++++++++++++++++++++++--------------------
2c1b57
 1 file changed, 47 insertions(+), 24 deletions(-)
2c1b57
2c1b57
diff --git a/super-intel.c b/super-intel.c
2c1b57
index 347838e..56dec36 100644
2c1b57
--- a/super-intel.c
2c1b57
+++ b/super-intel.c
2c1b57
@@ -6106,11 +6106,14 @@ static int validate_ppl_imsm(struct supertype *st, struct mdinfo *info,
2c1b57
 	struct imsm_dev *dev;
2c1b57
 	struct imsm_map *map;
2c1b57
 	__u32 idx;
2c1b57
+	unsigned int i;
2c1b57
+	unsigned long long ppl_offset = 0;
2c1b57
+	unsigned long long prev_gen_num = 0;
2c1b57
 
2c1b57
 	if (disk->disk.raid_disk < 0)
2c1b57
 		return 0;
2c1b57
 
2c1b57
-	if (posix_memalign(&buf, 4096, PPL_HEADER_SIZE)) {
2c1b57
+	if (posix_memalign(&buf, MAX_SECTOR_SIZE, PPL_HEADER_SIZE)) {
2c1b57
 		pr_err("Failed to allocate PPL header buffer\n");
2c1b57
 		return -1;
2c1b57
 	}
2c1b57
@@ -6123,34 +6126,54 @@ static int validate_ppl_imsm(struct supertype *st, struct mdinfo *info,
2c1b57
 	if (!d || d->index < 0 || is_failed(&d->disk))
2c1b57
 		goto out;
2c1b57
 
2c1b57
-	if (lseek64(d->fd, info->ppl_sector * 512, SEEK_SET) < 0) {
2c1b57
-		perror("Failed to seek to PPL header location");
2c1b57
-		ret = -1;
2c1b57
-		goto out;
2c1b57
-	}
2c1b57
+	ret = 1;
2c1b57
+	while (ppl_offset < MULTIPLE_PPL_AREA_SIZE_IMSM) {
2c1b57
+		dprintf("Checking potential PPL at offset: %llu\n", ppl_offset);
2c1b57
 
2c1b57
-	if (read(d->fd, buf, PPL_HEADER_SIZE) != PPL_HEADER_SIZE) {
2c1b57
-		perror("Read PPL header failed");
2c1b57
-		ret = -1;
2c1b57
-		goto out;
2c1b57
-	}
2c1b57
+		if (lseek64(d->fd, info->ppl_sector * 512 + ppl_offset,
2c1b57
+			    SEEK_SET) < 0) {
2c1b57
+			perror("Failed to seek to PPL header location");
2c1b57
+			ret = -1;
2c1b57
+			goto out;
2c1b57
+		}
2c1b57
 
2c1b57
-	ppl_hdr = buf;
2c1b57
+		if (read(d->fd, buf, PPL_HEADER_SIZE) != PPL_HEADER_SIZE) {
2c1b57
+			perror("Read PPL header failed");
2c1b57
+			ret = -1;
2c1b57
+			goto out;
2c1b57
+		}
2c1b57
 
2c1b57
-	crc = __le32_to_cpu(ppl_hdr->checksum);
2c1b57
-	ppl_hdr->checksum = 0;
2c1b57
+		ppl_hdr = buf;
2c1b57
 
2c1b57
-	if (crc != ~crc32c_le(~0, buf, PPL_HEADER_SIZE)) {
2c1b57
-		dprintf("Wrong PPL header checksum on %s\n",
2c1b57
-			d->devname);
2c1b57
-		ret = 1;
2c1b57
-	}
2c1b57
+		crc = __le32_to_cpu(ppl_hdr->checksum);
2c1b57
+		ppl_hdr->checksum = 0;
2c1b57
+
2c1b57
+		if (crc != ~crc32c_le(~0, buf, PPL_HEADER_SIZE)) {
2c1b57
+			dprintf("Wrong PPL header checksum on %s\n",
2c1b57
+				d->devname);
2c1b57
+			goto out;
2c1b57
+		}
2c1b57
+
2c1b57
+		if (prev_gen_num > __le64_to_cpu(ppl_hdr->generation)) {
2c1b57
+			/* previous was newest, it was already checked */
2c1b57
+			goto out;
2c1b57
+		}
2c1b57
+
2c1b57
+		if ((__le32_to_cpu(ppl_hdr->signature) !=
2c1b57
+			      super->anchor->orig_family_num)) {
2c1b57
+			dprintf("Wrong PPL header signature on %s\n",
2c1b57
+				d->devname);
2c1b57
+			ret = 1;
2c1b57
+			goto out;
2c1b57
+		}
2c1b57
+
2c1b57
+		ret = 0;
2c1b57
+		prev_gen_num = __le64_to_cpu(ppl_hdr->generation);
2c1b57
 
2c1b57
-	if (!ret && (__le32_to_cpu(ppl_hdr->signature) !=
2c1b57
-		      super->anchor->orig_family_num)) {
2c1b57
-		dprintf("Wrong PPL header signature on %s\n",
2c1b57
-			d->devname);
2c1b57
-		ret = 1;
2c1b57
+		ppl_offset += PPL_HEADER_SIZE;
2c1b57
+		for (i = 0; i < __le32_to_cpu(ppl_hdr->entries_count); i++)
2c1b57
+			ppl_offset +=
2c1b57
+				   __le32_to_cpu(ppl_hdr->entries[i].pp_size);
2c1b57
 	}
2c1b57
 
2c1b57
 out:
2c1b57
-- 
2c1b57
2.7.4
2c1b57