Blame SOURCES/add-ppl-and-no-ppl-options-for-update.patch

dd3a91
commit e6e9dd3f1b255f9921ebc023c1e5b65601a637e2
dd3a91
Author: Artur Paszkiewicz <artur.paszkiewicz@intel.com>
dd3a91
Date:   Wed Mar 29 11:54:19 2017 +0200
dd3a91
dd3a91
    Add 'ppl' and 'no-ppl' options for --update=
dd3a91
    
dd3a91
    This can be used with --assemble for super1 and with --update-subarray
dd3a91
    for imsm to enable or disable PPL in the metadata.
dd3a91
    
dd3a91
    Signed-off-by: Artur Paszkiewicz <artur.paszkiewicz@intel.com>
dd3a91
    Signed-off-by: Jes Sorensen <Jes.Sorensen@gmail.com>
dd3a91
dd3a91
diff --git a/Assemble.c b/Assemble.c
dd3a91
index c098420..6a6a56b 100644
dd3a91
--- a/Assemble.c
dd3a91
+++ b/Assemble.c
dd3a91
@@ -602,6 +602,12 @@ static int load_devices(struct devs *devices, char *devmap,
dd3a91
 			if (strcmp(c->update, "uuid") == 0 && !ident->uuid_set)
dd3a91
 				random_uuid((__u8 *)ident->uuid);
dd3a91
 
dd3a91
+			if (strcmp(c->update, "ppl") == 0 &&
dd3a91
+			    ident->bitmap_fd >= 0) {
dd3a91
+				pr_err("PPL is not compatible with bitmap\n");
dd3a91
+				return -1;
dd3a91
+			}
dd3a91
+
dd3a91
 			dfd = dev_open(devname,
dd3a91
 				       tmpdev->disposition == 'I'
dd3a91
 				       ? O_RDWR : (O_RDWR|O_EXCL));
dd3a91
diff --git a/mdadm.8.in b/mdadm.8.in
dd3a91
index cad5db5..1178ed9 100644
dd3a91
--- a/mdadm.8.in
dd3a91
+++ b/mdadm.8.in
dd3a91
@@ -1176,6 +1176,8 @@ argument given to this flag can be one of
dd3a91
 .BR no\-bitmap ,
dd3a91
 .BR bbl ,
dd3a91
 .BR no\-bbl ,
dd3a91
+.BR ppl ,
dd3a91
+.BR no\-ppl ,
dd3a91
 .BR metadata ,
dd3a91
 or
dd3a91
 .BR super\-minor .
dd3a91
@@ -1316,6 +1318,16 @@ option will cause any reservation of space for a bad block list to be
dd3a91
 removed.  If the bad block list contains entries, this will fail, as
dd3a91
 removing the list could cause data corruption.
dd3a91
 
dd3a91
+The
dd3a91
+.B ppl
dd3a91
+option will enable PPL for a RAID5 array and reserve space for PPL on each
dd3a91
+device. There must be enough free space between the data and superblock and a
dd3a91
+write-intent bitmap or journal must not be used.
dd3a91
+
dd3a91
+The
dd3a91
+.B no\-ppl
dd3a91
+option will disable PPL in the superblock.
dd3a91
+
dd3a91
 .TP
dd3a91
 .BR \-\-freeze\-reshape
dd3a91
 Option is intended to be used in start-up scripts during initrd boot phase.
dd3a91
@@ -2327,9 +2339,11 @@ superblock field in the subarray.  Similar to updating an array in
dd3a91
 .B \-U
dd3a91
 or
dd3a91
 .B \-\-update=
dd3a91
-option.  Currently only
dd3a91
-.B name
dd3a91
-is supported.
dd3a91
+option. The supported options are
dd3a91
+.BR name ,
dd3a91
+.B ppl
dd3a91
+and
dd3a91
+.BR no\-ppl .
dd3a91
 
dd3a91
 The
dd3a91
 .B name
dd3a91
@@ -2340,6 +2354,13 @@ re\-assembled.  If updating
dd3a91
 would change the UUID of an active subarray this operation is blocked,
dd3a91
 and the command will end in an error.
dd3a91
 
dd3a91
+The
dd3a91
+.B ppl
dd3a91
+and
dd3a91
+.B no\-ppl
dd3a91
+options enable and disable PPL in the metadata. Currently supported only for
dd3a91
+IMSM subarrays.
dd3a91
+
dd3a91
 .TP
dd3a91
 .B \-\-examine
dd3a91
 The device should be a component of an md array.
dd3a91
diff --git a/mdadm.c b/mdadm.c
dd3a91
index d4e8286..6edf3ab 100644
dd3a91
--- a/mdadm.c
dd3a91
+++ b/mdadm.c
dd3a91
@@ -769,6 +769,10 @@ int main(int argc, char *argv[])
dd3a91
 				continue;
dd3a91
 			if (strcmp(c.update, "force-no-bbl") == 0)
dd3a91
 				continue;
dd3a91
+			if (strcmp(c.update, "ppl") == 0)
dd3a91
+				continue;
dd3a91
+			if (strcmp(c.update, "no-ppl") == 0)
dd3a91
+				continue;
dd3a91
 			if (strcmp(c.update, "metadata") == 0)
dd3a91
 				continue;
dd3a91
 			if (strcmp(c.update, "revert-reshape") == 0)
dd3a91
@@ -802,7 +806,7 @@ int main(int argc, char *argv[])
dd3a91
 		"     'sparc2.2', 'super-minor', 'uuid', 'name', 'nodes', 'resync',\n"
dd3a91
 		"     'summaries', 'homehost', 'home-cluster', 'byteorder', 'devicesize',\n"
dd3a91
 		"     'no-bitmap', 'metadata', 'revert-reshape'\n"
dd3a91
-		"     'bbl', 'no-bbl', 'force-no-bbl'\n"
dd3a91
+		"     'bbl', 'no-bbl', 'force-no-bbl', 'ppl', 'no-ppl'\n"
dd3a91
 				);
dd3a91
 			exit(outf == stdout ? 0 : 2);
dd3a91
 
dd3a91
diff --git a/super-intel.c b/super-intel.c
dd3a91
index 87fec8b..785488a 100644
dd3a91
--- a/super-intel.c
dd3a91
+++ b/super-intel.c
dd3a91
@@ -451,6 +451,7 @@ enum imsm_update_type {
dd3a91
 	update_general_migration_checkpoint,
dd3a91
 	update_size_change,
dd3a91
 	update_prealloc_badblocks_mem,
dd3a91
+	update_rwh_policy,
dd3a91
 };
dd3a91
 
dd3a91
 struct imsm_update_activate_spare {
dd3a91
@@ -543,6 +544,12 @@ struct imsm_update_prealloc_bb_mem {
dd3a91
 	enum imsm_update_type type;
dd3a91
 };
dd3a91
 
dd3a91
+struct imsm_update_rwh_policy {
dd3a91
+	enum imsm_update_type type;
dd3a91
+	int new_policy;
dd3a91
+	int dev_idx;
dd3a91
+};
dd3a91
+
dd3a91
 static const char *_sys_dev_type[] = {
dd3a91
 	[SYS_DEV_UNKNOWN] = "Unknown",
dd3a91
 	[SYS_DEV_SAS] = "SAS",
dd3a91
@@ -7373,6 +7380,34 @@ static int update_subarray_imsm(struct supertype *st, char *subarray,
dd3a91
 			}
dd3a91
 			super->updates_pending++;
dd3a91
 		}
dd3a91
+	} else if (strcmp(update, "ppl") == 0 ||
dd3a91
+		   strcmp(update, "no-ppl") == 0) {
dd3a91
+		int new_policy;
dd3a91
+		char *ep;
dd3a91
+		int vol = strtoul(subarray, &ep, 10);
dd3a91
+
dd3a91
+		if (*ep != '\0' || vol >= super->anchor->num_raid_devs)
dd3a91
+			return 2;
dd3a91
+
dd3a91
+		if (strcmp(update, "ppl") == 0)
dd3a91
+			new_policy = RWH_DISTRIBUTED;
dd3a91
+		else
dd3a91
+			new_policy = RWH_OFF;
dd3a91
+
dd3a91
+		if (st->update_tail) {
dd3a91
+			struct imsm_update_rwh_policy *u = xmalloc(sizeof(*u));
dd3a91
+
dd3a91
+			u->type = update_rwh_policy;
dd3a91
+			u->dev_idx = vol;
dd3a91
+			u->new_policy = new_policy;
dd3a91
+			append_metadata_update(st, u, sizeof(*u));
dd3a91
+		} else {
dd3a91
+			struct imsm_dev *dev;
dd3a91
+
dd3a91
+			dev = get_imsm_dev(super, vol);
dd3a91
+			dev->rwh_policy = new_policy;
dd3a91
+			super->updates_pending++;
dd3a91
+		}
dd3a91
 	} else
dd3a91
 		return 2;
dd3a91
 
dd3a91
@@ -9599,6 +9634,21 @@ static void imsm_process_update(struct supertype *st,
dd3a91
 	}
dd3a91
 	case update_prealloc_badblocks_mem:
dd3a91
 		break;
dd3a91
+	case update_rwh_policy: {
dd3a91
+		struct imsm_update_rwh_policy *u = (void *)update->buf;
dd3a91
+		int target = u->dev_idx;
dd3a91
+		struct imsm_dev *dev = get_imsm_dev(super, target);
dd3a91
+		if (!dev) {
dd3a91
+			dprintf("could not find subarray-%d\n", target);
dd3a91
+			break;
dd3a91
+		}
dd3a91
+
dd3a91
+		if (dev->rwh_policy != u->new_policy) {
dd3a91
+			dev->rwh_policy = u->new_policy;
dd3a91
+			super->updates_pending++;
dd3a91
+		}
dd3a91
+		break;
dd3a91
+	}
dd3a91
 	default:
dd3a91
 		pr_err("error: unsuported process update type:(type: %d)\n",	type);
dd3a91
 	}
dd3a91
@@ -9844,6 +9894,11 @@ static int imsm_prepare_update(struct supertype *st,
dd3a91
 		super->extra_space += sizeof(struct bbm_log) -
dd3a91
 			get_imsm_bbm_log_size(super->bbm_log);
dd3a91
 		break;
dd3a91
+	case update_rwh_policy: {
dd3a91
+		if (update->len < (int)sizeof(struct imsm_update_rwh_policy))
dd3a91
+			return 0;
dd3a91
+		break;
dd3a91
+	}
dd3a91
 	default:
dd3a91
 		return 0;
dd3a91
 	}
dd3a91
diff --git a/super1.c b/super1.c
dd3a91
index 409b6c3..e76f777 100644
dd3a91
--- a/super1.c
dd3a91
+++ b/super1.c
dd3a91
@@ -1325,6 +1325,55 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
dd3a91
 		sb->bblog_size = 0;
dd3a91
 		sb->bblog_shift = 0;
dd3a91
 		sb->bblog_offset = 0;
dd3a91
+	} else if (strcmp(update, "ppl") == 0) {
dd3a91
+		unsigned long long sb_offset = __le64_to_cpu(sb->super_offset);
dd3a91
+		unsigned long long data_offset = __le64_to_cpu(sb->data_offset);
dd3a91
+		unsigned long long data_size = __le64_to_cpu(sb->data_size);
dd3a91
+		long bb_offset = __le32_to_cpu(sb->bblog_offset);
dd3a91
+		int space;
dd3a91
+		int optimal_space;
dd3a91
+		int offset;
dd3a91
+
dd3a91
+		if (sb->feature_map & __cpu_to_le32(MD_FEATURE_BITMAP_OFFSET)) {
dd3a91
+			pr_err("Cannot add PPL to array with bitmap\n");
dd3a91
+			return -2;
dd3a91
+		}
dd3a91
+
dd3a91
+		if (sb->feature_map & __cpu_to_le32(MD_FEATURE_JOURNAL)) {
dd3a91
+			pr_err("Cannot add PPL to array with journal\n");
dd3a91
+			return -2;
dd3a91
+		}
dd3a91
+
dd3a91
+		if (sb_offset < data_offset) {
dd3a91
+			if (bb_offset)
dd3a91
+				space = bb_offset - 8;
dd3a91
+			else
dd3a91
+				space = data_offset - sb_offset - 8;
dd3a91
+			offset = 8;
dd3a91
+		} else {
dd3a91
+			offset = -(sb_offset - data_offset - data_size);
dd3a91
+			if (offset < INT16_MIN)
dd3a91
+				offset = INT16_MIN;
dd3a91
+			space = -(offset - bb_offset);
dd3a91
+		}
dd3a91
+
dd3a91
+		if (space < (PPL_HEADER_SIZE >> 9) + 8) {
dd3a91
+			pr_err("Not enough space to add ppl\n");
dd3a91
+			return -2;
dd3a91
+		}
dd3a91
+
dd3a91
+		optimal_space = choose_ppl_space(__le32_to_cpu(sb->chunksize));
dd3a91
+
dd3a91
+		if (space > optimal_space)
dd3a91
+			space = optimal_space;
dd3a91
+		if (space > UINT16_MAX)
dd3a91
+			space = UINT16_MAX;
dd3a91
+
dd3a91
+		sb->ppl.offset = __cpu_to_le16(offset);
dd3a91
+		sb->ppl.size = __cpu_to_le16(space);
dd3a91
+		sb->feature_map |= __cpu_to_le32(MD_FEATURE_PPL);
dd3a91
+	} else if (strcmp(update, "no-ppl") == 0) {
dd3a91
+		sb->feature_map &= ~ __cpu_to_le32(MD_FEATURE_PPL);
dd3a91
 	} else if (strcmp(update, "name") == 0) {
dd3a91
 		if (info->name[0] == 0)
dd3a91
 			sprintf(info->name, "%d", info->array.md_minor);