dcavalca / rpms / mdadm

Forked from rpms/mdadm 3 years ago
Clone

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

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