Blame SOURCES/super1ppl-support.patch

dd3a91
commit e97a7cd011345e5dead736de51b33968da49d876
dd3a91
Author: Artur Paszkiewicz <artur.paszkiewicz@intel.com>
dd3a91
Date:   Wed Mar 29 11:54:18 2017 +0200
dd3a91
dd3a91
    super1: PPL support
dd3a91
    
dd3a91
    Enable creating and assembling raid5 arrays with PPL for 1.x metadata.
dd3a91
    
dd3a91
    When creating, reserve enough space for PPL and store its size and
dd3a91
    location in the superblock and set MD_FEATURE_PPL bit. Write an initial
dd3a91
    empty header in the PPL area on each device. PPL is stored in the
dd3a91
    metadata region reserved for internal write-intent bitmap, so don't
dd3a91
    allow using bitmap and PPL together.
dd3a91
    
dd3a91
    While at it, fix two endianness issues in write_empty_r5l_meta_block()
dd3a91
    and write_init_super1().
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 8e55b49..c098420 100644
dd3a91
--- a/Assemble.c
dd3a91
+++ b/Assemble.c
dd3a91
@@ -962,6 +962,9 @@ static int start_array(int mdfd,
dd3a91
 		c->readonly = 1;
dd3a91
 	}
dd3a91
 
dd3a91
+	if (content->consistency_policy == CONSISTENCY_POLICY_PPL)
dd3a91
+		clean = 1;
dd3a91
+
dd3a91
 	rv = set_array_info(mdfd, st, content);
dd3a91
 	if (rv && !err_ok) {
dd3a91
 		pr_err("failed to set array info for %s: %s\n",
dd3a91
diff --git a/Create.c b/Create.c
dd3a91
index 4080bf6..10e7d10 100644
dd3a91
--- a/Create.c
dd3a91
+++ b/Create.c
dd3a91
@@ -524,6 +524,8 @@ int Create(struct supertype *st, char *mddev,
dd3a91
 	if (!s->bitmap_file &&
dd3a91
 	    s->level >= 1 &&
dd3a91
 	    st->ss->add_internal_bitmap &&
dd3a91
+	    (s->consistency_policy != CONSISTENCY_POLICY_RESYNC &&
dd3a91
+	     s->consistency_policy != CONSISTENCY_POLICY_PPL) &&
dd3a91
 	    (s->write_behind || s->size > 100*1024*1024ULL)) {
dd3a91
 		if (c->verbose > 0)
dd3a91
 			pr_err("automatically enabling write-intent bitmap on large array\n");
dd3a91
diff --git a/Grow.c b/Grow.c
dd3a91
index e22661c..a849012 100755
dd3a91
--- a/Grow.c
dd3a91
+++ b/Grow.c
dd3a91
@@ -290,6 +290,7 @@ int Grow_addbitmap(char *devname, int fd, struct context *c, struct shape *s)
dd3a91
 	int major = BITMAP_MAJOR_HI;
dd3a91
 	int vers = md_get_version(fd);
dd3a91
 	unsigned long long bitmapsize, array_size;
dd3a91
+	struct mdinfo *mdi;
dd3a91
 
dd3a91
 	if (vers < 9003) {
dd3a91
 		major = BITMAP_MAJOR_HOSTENDIAN;
dd3a91
@@ -389,12 +390,23 @@ int Grow_addbitmap(char *devname, int fd, struct context *c, struct shape *s)
dd3a91
 		free(st);
dd3a91
 		return 1;
dd3a91
 	}
dd3a91
+
dd3a91
+	mdi = sysfs_read(fd, NULL, GET_CONSISTENCY_POLICY);
dd3a91
+	if (mdi) {
dd3a91
+		if (mdi->consistency_policy == CONSISTENCY_POLICY_PPL) {
dd3a91
+			pr_err("Cannot add bitmap to array with PPL\n");
dd3a91
+			free(mdi);
dd3a91
+			free(st);
dd3a91
+			return 1;
dd3a91
+		}
dd3a91
+		free(mdi);
dd3a91
+	}
dd3a91
+
dd3a91
 	if (strcmp(s->bitmap_file, "internal") == 0 ||
dd3a91
 	    strcmp(s->bitmap_file, "clustered") == 0) {
dd3a91
 		int rv;
dd3a91
 		int d;
dd3a91
 		int offset_setable = 0;
dd3a91
-		struct mdinfo *mdi;
dd3a91
 		if (st->ss->add_internal_bitmap == NULL) {
dd3a91
 			pr_err("Internal bitmaps not supported with %s metadata\n", st->ss->name);
dd3a91
 			return 1;
dd3a91
@@ -446,6 +458,7 @@ int Grow_addbitmap(char *devname, int fd, struct context *c, struct shape *s)
dd3a91
 			sysfs_init(mdi, fd, NULL);
dd3a91
 			rv = sysfs_set_num_signed(mdi, NULL, "bitmap/location",
dd3a91
 						  mdi->bitmap_offset);
dd3a91
+			free(mdi);
dd3a91
 		} else {
dd3a91
 			if (strcmp(s->bitmap_file, "clustered") == 0)
dd3a91
 				array.state |= (1 << MD_SB_CLUSTERED);
dd3a91
diff --git a/Incremental.c b/Incremental.c
dd3a91
index 0f507bb..81afc7e 100644
dd3a91
--- a/Incremental.c
dd3a91
+++ b/Incremental.c
dd3a91
@@ -528,6 +528,9 @@ int Incremental(struct mddev_dev *devlist, struct context *c,
dd3a91
 
dd3a91
 	journal_device_missing = (info.journal_device_required) && (info.journal_clean == 0);
dd3a91
 
dd3a91
+	if (info.consistency_policy == CONSISTENCY_POLICY_PPL)
dd3a91
+		info.array.state |= 1;
dd3a91
+
dd3a91
 	if (enough(info.array.level, info.array.raid_disks,
dd3a91
 		   info.array.layout, info.array.state & 1,
dd3a91
 		   avail) == 0) {
dd3a91
diff --git a/mdadm.h b/mdadm.h
dd3a91
index d222cc3..2c7066d 100644
dd3a91
--- a/mdadm.h
dd3a91
+++ b/mdadm.h
dd3a91
@@ -302,6 +302,7 @@ struct mdinfo {
dd3a91
 	long			bitmap_offset;	/* 0 == none, 1 == a file */
dd3a91
 	unsigned int		ppl_size;
dd3a91
 	unsigned long long	ppl_sector;
dd3a91
+	int			ppl_offset;
dd3a91
 	unsigned long		safe_mode_delay; /* ms delay to mark clean */
dd3a91
 	int			new_level, delta_disks, new_layout, new_chunk;
dd3a91
 	int			errors;
dd3a91
diff --git a/super1.c b/super1.c
dd3a91
index 8df17a1..409b6c3 100644
dd3a91
--- a/super1.c
dd3a91
+++ b/super1.c
dd3a91
@@ -48,10 +48,18 @@ struct mdp_superblock_1 {
dd3a91
 
dd3a91
 	__u32	chunksize;	/* in 512byte sectors */
dd3a91
 	__u32	raid_disks;
dd3a91
-	__u32	bitmap_offset;	/* sectors after start of superblock that bitmap starts
dd3a91
-				 * NOTE: signed, so bitmap can be before superblock
dd3a91
-				 * only meaningful of feature_map[0] is set.
dd3a91
-				 */
dd3a91
+	union {
dd3a91
+		__u32	bitmap_offset;	/* sectors after start of superblock that bitmap starts
dd3a91
+					 * NOTE: signed, so bitmap can be before superblock
dd3a91
+					 * only meaningful of feature_map[0] is set.
dd3a91
+					 */
dd3a91
+
dd3a91
+		/* only meaningful when feature_map[MD_FEATURE_PPL] is set */
dd3a91
+		struct {
dd3a91
+			__s16 offset; /* sectors from start of superblock that ppl starts */
dd3a91
+			__u16 size; /* ppl size in sectors */
dd3a91
+		} ppl;
dd3a91
+	};
dd3a91
 
dd3a91
 	/* These are only valid with feature bit '4' */
dd3a91
 	__u32	new_level;	/* new level we are reshaping to		*/
dd3a91
@@ -131,6 +139,7 @@ struct misc_dev_info {
dd3a91
 #define	MD_FEATURE_NEW_OFFSET		64 /* new_offset must be honoured */
dd3a91
 #define	MD_FEATURE_BITMAP_VERSIONED	256 /* bitmap version number checked properly */
dd3a91
 #define	MD_FEATURE_JOURNAL		512 /* support write journal */
dd3a91
+#define	MD_FEATURE_PPL			1024 /* support PPL */
dd3a91
 #define	MD_FEATURE_ALL			(MD_FEATURE_BITMAP_OFFSET	\
dd3a91
 					|MD_FEATURE_RECOVERY_OFFSET	\
dd3a91
 					|MD_FEATURE_RESHAPE_ACTIVE	\
dd3a91
@@ -140,6 +149,7 @@ struct misc_dev_info {
dd3a91
 					|MD_FEATURE_NEW_OFFSET		\
dd3a91
 					|MD_FEATURE_BITMAP_VERSIONED	\
dd3a91
 					|MD_FEATURE_JOURNAL		\
dd3a91
+					|MD_FEATURE_PPL			\
dd3a91
 					)
dd3a91
 
dd3a91
 #ifndef MDASSEMBLE
dd3a91
@@ -289,6 +299,11 @@ static int awrite(struct align_fd *afd, void *buf, int len)
dd3a91
 	return len;
dd3a91
 }
dd3a91
 
dd3a91
+static inline unsigned int choose_ppl_space(int chunk)
dd3a91
+{
dd3a91
+	return (PPL_HEADER_SIZE >> 9) + (chunk > 128*2 ? chunk : 128*2);
dd3a91
+}
dd3a91
+
dd3a91
 #ifndef MDASSEMBLE
dd3a91
 static void examine_super1(struct supertype *st, char *homehost)
dd3a91
 {
dd3a91
@@ -392,6 +407,10 @@ static void examine_super1(struct supertype *st, char *homehost)
dd3a91
 	if (sb->feature_map & __cpu_to_le32(MD_FEATURE_BITMAP_OFFSET)) {
dd3a91
 		printf("Internal Bitmap : %ld sectors from superblock\n",
dd3a91
 		       (long)(int32_t)__le32_to_cpu(sb->bitmap_offset));
dd3a91
+	} else if (sb->feature_map & __cpu_to_le32(MD_FEATURE_PPL)) {
dd3a91
+		printf("            PPL : %u sectors at offset %d sectors from superblock\n",
dd3a91
+		       __le16_to_cpu(sb->ppl.size),
dd3a91
+		       __le16_to_cpu(sb->ppl.offset));
dd3a91
 	}
dd3a91
 	if (sb->feature_map & __cpu_to_le32(MD_FEATURE_RESHAPE_ACTIVE)) {
dd3a91
 		printf("  Reshape pos'n : %llu%s\n", (unsigned long long)__le64_to_cpu(sb->reshape_position)/2,
dd3a91
@@ -934,10 +953,16 @@ static void getinfo_super1(struct supertype *st, struct mdinfo *info, char *map)
dd3a91
 	if (__le32_to_cpu(bsb->nodes) > 1)
dd3a91
 		info->array.state |= (1 << MD_SB_CLUSTERED);
dd3a91
 
dd3a91
+	super_offset = __le64_to_cpu(sb->super_offset);
dd3a91
 	info->data_offset = __le64_to_cpu(sb->data_offset);
dd3a91
 	info->component_size = __le64_to_cpu(sb->size);
dd3a91
-	if (sb->feature_map & __le32_to_cpu(MD_FEATURE_BITMAP_OFFSET))
dd3a91
+	if (sb->feature_map & __le32_to_cpu(MD_FEATURE_BITMAP_OFFSET)) {
dd3a91
 		info->bitmap_offset = (int32_t)__le32_to_cpu(sb->bitmap_offset);
dd3a91
+	} else if (sb->feature_map & __le32_to_cpu(MD_FEATURE_PPL)) {
dd3a91
+		info->ppl_offset = __le16_to_cpu(sb->ppl.offset);
dd3a91
+		info->ppl_size = __le16_to_cpu(sb->ppl.size);
dd3a91
+		info->ppl_sector = super_offset + info->ppl_offset;
dd3a91
+	}
dd3a91
 
dd3a91
 	info->disk.major = 0;
dd3a91
 	info->disk.minor = 0;
dd3a91
@@ -948,7 +973,6 @@ static void getinfo_super1(struct supertype *st, struct mdinfo *info, char *map)
dd3a91
 	else
dd3a91
 		role = __le16_to_cpu(sb->dev_roles[__le32_to_cpu(sb->dev_number)]);
dd3a91
 
dd3a91
-	super_offset = __le64_to_cpu(sb->super_offset);
dd3a91
 	if (info->array.level <= 0)
dd3a91
 		data_size = __le64_to_cpu(sb->data_size);
dd3a91
 	else
dd3a91
@@ -965,8 +989,8 @@ static void getinfo_super1(struct supertype *st, struct mdinfo *info, char *map)
dd3a91
 				end = bboffset;
dd3a91
 		}
dd3a91
 
dd3a91
-		if (super_offset + info->bitmap_offset < end)
dd3a91
-			end = super_offset + info->bitmap_offset;
dd3a91
+		if (super_offset + info->bitmap_offset + info->ppl_offset < end)
dd3a91
+			end = super_offset + info->bitmap_offset + info->ppl_offset;
dd3a91
 
dd3a91
 		if (info->data_offset + data_size < end)
dd3a91
 			info->space_after = end - data_size - info->data_offset;
dd3a91
@@ -982,6 +1006,11 @@ static void getinfo_super1(struct supertype *st, struct mdinfo *info, char *map)
dd3a91
 			bmend += size;
dd3a91
 			if (bmend > earliest)
dd3a91
 				earliest = bmend;
dd3a91
+		} else if (info->ppl_offset > 0) {
dd3a91
+			unsigned long long pplend = info->ppl_offset +
dd3a91
+						    info->ppl_size;
dd3a91
+			if (pplend > earliest)
dd3a91
+				earliest = pplend;
dd3a91
 		}
dd3a91
 		if (sb->bblog_offset && sb->bblog_size) {
dd3a91
 			unsigned long long bbend = super_offset;
dd3a91
@@ -1075,8 +1104,20 @@ static void getinfo_super1(struct supertype *st, struct mdinfo *info, char *map)
dd3a91
 	}
dd3a91
 
dd3a91
 	info->array.working_disks = working;
dd3a91
-	if (sb->feature_map & __le32_to_cpu(MD_FEATURE_JOURNAL))
dd3a91
+
dd3a91
+	if (sb->feature_map & __le32_to_cpu(MD_FEATURE_JOURNAL)) {
dd3a91
 		info->journal_device_required = 1;
dd3a91
+		info->consistency_policy = CONSISTENCY_POLICY_JOURNAL;
dd3a91
+	} else if (sb->feature_map & __le32_to_cpu(MD_FEATURE_PPL)) {
dd3a91
+		info->consistency_policy = CONSISTENCY_POLICY_PPL;
dd3a91
+	} else if (sb->feature_map & __le32_to_cpu(MD_FEATURE_BITMAP_OFFSET)) {
dd3a91
+		info->consistency_policy = CONSISTENCY_POLICY_BITMAP;
dd3a91
+	} else if (info->array.level <= 0) {
dd3a91
+		info->consistency_policy = CONSISTENCY_POLICY_NONE;
dd3a91
+	} else {
dd3a91
+		info->consistency_policy = CONSISTENCY_POLICY_RESYNC;
dd3a91
+	}
dd3a91
+
dd3a91
 	info->journal_clean = 0;
dd3a91
 }
dd3a91
 
dd3a91
@@ -1239,6 +1280,9 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
dd3a91
 		if (sb->feature_map & __cpu_to_le32(MD_FEATURE_BITMAP_OFFSET)) {
dd3a91
 			bitmap_offset = (long)__le32_to_cpu(sb->bitmap_offset);
dd3a91
 			bm_sectors = calc_bitmap_size(bms, 4096) >> 9;
dd3a91
+		} else if (sb->feature_map & __cpu_to_le32(MD_FEATURE_PPL)) {
dd3a91
+			bitmap_offset = (long)__le16_to_cpu(sb->ppl.offset);
dd3a91
+			bm_sectors = (long)__le16_to_cpu(sb->ppl.size);
dd3a91
 		}
dd3a91
 #endif
dd3a91
 		if (sb_offset < data_offset) {
dd3a91
@@ -1472,6 +1516,9 @@ static int init_super1(struct supertype *st, mdu_array_info_t *info,
dd3a91
 
dd3a91
 	memset(sb->dev_roles, 0xff, MAX_SB_SIZE - sizeof(struct mdp_superblock_1));
dd3a91
 
dd3a91
+	if (s->consistency_policy == CONSISTENCY_POLICY_PPL)
dd3a91
+		sb->feature_map |= __cpu_to_le32(MD_FEATURE_PPL);
dd3a91
+
dd3a91
 	return 1;
dd3a91
 }
dd3a91
 
dd3a91
@@ -1645,10 +1692,49 @@ static unsigned long choose_bm_space(unsigned long devsize)
dd3a91
 
dd3a91
 static void free_super1(struct supertype *st);
dd3a91
 
dd3a91
-#define META_BLOCK_SIZE 4096
dd3a91
+#ifndef MDASSEMBLE
dd3a91
+
dd3a91
 __u32 crc32c_le(__u32 crc, unsigned char const *p, size_t len);
dd3a91
 
dd3a91
-#ifndef MDASSEMBLE
dd3a91
+static int write_init_ppl1(struct supertype *st, struct mdinfo *info, int fd)
dd3a91
+{
dd3a91
+	struct mdp_superblock_1 *sb = st->sb;
dd3a91
+	void *buf;
dd3a91
+	struct ppl_header *ppl_hdr;
dd3a91
+	int ret;
dd3a91
+
dd3a91
+	ret = posix_memalign(&buf, 4096, PPL_HEADER_SIZE);
dd3a91
+	if (ret) {
dd3a91
+		pr_err("Failed to allocate PPL header buffer\n");
dd3a91
+		return ret;
dd3a91
+	}
dd3a91
+
dd3a91
+	memset(buf, 0, PPL_HEADER_SIZE);
dd3a91
+	ppl_hdr = buf;
dd3a91
+	memset(ppl_hdr->reserved, 0xff, PPL_HDR_RESERVED);
dd3a91
+	ppl_hdr->signature = __cpu_to_le32(~crc32c_le(~0, sb->set_uuid,
dd3a91
+						      sizeof(sb->set_uuid)));
dd3a91
+	ppl_hdr->checksum = __cpu_to_le32(~crc32c_le(~0, buf, PPL_HEADER_SIZE));
dd3a91
+
dd3a91
+	if (lseek64(fd, info->ppl_sector * 512, SEEK_SET) < 0) {
dd3a91
+		ret = errno;
dd3a91
+		perror("Failed to seek to PPL header location");
dd3a91
+	}
dd3a91
+
dd3a91
+	if (!ret && write(fd, buf, PPL_HEADER_SIZE) != PPL_HEADER_SIZE) {
dd3a91
+		ret = errno;
dd3a91
+		perror("Write PPL header failed");
dd3a91
+	}
dd3a91
+
dd3a91
+	if (!ret)
dd3a91
+		fsync(fd);
dd3a91
+
dd3a91
+	free(buf);
dd3a91
+	return ret;
dd3a91
+}
dd3a91
+
dd3a91
+#define META_BLOCK_SIZE 4096
dd3a91
+
dd3a91
 static int write_empty_r5l_meta_block(struct supertype *st, int fd)
dd3a91
 {
dd3a91
 	struct r5l_meta_block *mb;
dd3a91
@@ -1675,7 +1761,7 @@ static int write_empty_r5l_meta_block(struct supertype *st, int fd)
dd3a91
 	crc = crc32c_le(crc, (void *)mb, META_BLOCK_SIZE);
dd3a91
 	mb->checksum = crc;
dd3a91
 
dd3a91
-	if (lseek64(fd, (sb->data_offset) * 512, 0) < 0LL) {
dd3a91
+	if (lseek64(fd, __le64_to_cpu(sb->data_offset) * 512, 0) < 0LL) {
dd3a91
 		pr_err("cannot seek to offset of the meta block\n");
dd3a91
 		goto fail_to_write;
dd3a91
 	}
dd3a91
@@ -1708,7 +1794,7 @@ static int write_init_super1(struct supertype *st)
dd3a91
 
dd3a91
 	for (di = st->info; di; di = di->next) {
dd3a91
 		if (di->disk.state & (1 << MD_DISK_JOURNAL))
dd3a91
-			sb->feature_map |= MD_FEATURE_JOURNAL;
dd3a91
+			sb->feature_map |= __cpu_to_le32(MD_FEATURE_JOURNAL);
dd3a91
 	}
dd3a91
 
dd3a91
 	for (di = st->info; di; di = di->next) {
dd3a91
@@ -1783,6 +1869,21 @@ static int write_init_super1(struct supertype *st)
dd3a91
 					(((char *)sb) + MAX_SB_SIZE);
dd3a91
 			bm_space = calc_bitmap_size(bms, 4096) >> 9;
dd3a91
 			bm_offset = (long)__le32_to_cpu(sb->bitmap_offset);
dd3a91
+		} else if (sb->feature_map & __cpu_to_le32(MD_FEATURE_PPL)) {
dd3a91
+			bm_space = choose_ppl_space(__le32_to_cpu(sb->chunksize));
dd3a91
+			if (bm_space > UINT16_MAX)
dd3a91
+				bm_space = UINT16_MAX;
dd3a91
+			if (st->minor_version == 0) {
dd3a91
+				bm_offset = -bm_space - 8;
dd3a91
+				if (bm_offset < INT16_MIN) {
dd3a91
+					bm_offset = INT16_MIN;
dd3a91
+					bm_space = -bm_offset - 8;
dd3a91
+				}
dd3a91
+			} else {
dd3a91
+				bm_offset = 8;
dd3a91
+			}
dd3a91
+			sb->ppl.offset = __cpu_to_le16(bm_offset);
dd3a91
+			sb->ppl.size = __cpu_to_le16(bm_space);
dd3a91
 		} else {
dd3a91
 			bm_space = choose_bm_space(array_size);
dd3a91
 			bm_offset = 8;
dd3a91
@@ -1854,8 +1955,17 @@ static int write_init_super1(struct supertype *st)
dd3a91
 				goto error_out;
dd3a91
 		}
dd3a91
 
dd3a91
-		if (rv == 0 && (__le32_to_cpu(sb->feature_map) & 1))
dd3a91
+		if (rv == 0 &&
dd3a91
+		    (__le32_to_cpu(sb->feature_map) & MD_FEATURE_BITMAP_OFFSET)) {
dd3a91
 			rv = st->ss->write_bitmap(st, di->fd, NodeNumUpdate);
dd3a91
+		} else if (rv == 0 &&
dd3a91
+			 (__le32_to_cpu(sb->feature_map) & MD_FEATURE_PPL)) {
dd3a91
+			struct mdinfo info;
dd3a91
+
dd3a91
+			st->ss->getinfo_super(st, &info, NULL);
dd3a91
+			rv = st->ss->write_init_ppl(st, &info, di->fd);
dd3a91
+		}
dd3a91
+
dd3a91
 		close(di->fd);
dd3a91
 		di->fd = -1;
dd3a91
 		if (rv)
dd3a91
@@ -2123,11 +2233,13 @@ static __u64 avail_size1(struct supertype *st, __u64 devsize,
dd3a91
 		return 0;
dd3a91
 
dd3a91
 #ifndef MDASSEMBLE
dd3a91
-	if (__le32_to_cpu(super->feature_map)&MD_FEATURE_BITMAP_OFFSET) {
dd3a91
+	if (__le32_to_cpu(super->feature_map) & MD_FEATURE_BITMAP_OFFSET) {
dd3a91
 		/* hot-add. allow for actual size of bitmap */
dd3a91
 		struct bitmap_super_s *bsb;
dd3a91
 		bsb = (struct bitmap_super_s *)(((char*)super)+MAX_SB_SIZE);
dd3a91
 		bmspace = calc_bitmap_size(bsb, 4096) >> 9;
dd3a91
+	} else if (__le32_to_cpu(super->feature_map) & MD_FEATURE_PPL) {
dd3a91
+		bmspace = __le16_to_cpu(super->ppl.size);
dd3a91
 	}
dd3a91
 #endif
dd3a91
 	/* Allow space for bad block log */
dd3a91
@@ -2530,8 +2642,9 @@ static int validate_geometry1(struct supertype *st, int level,
dd3a91
 		return 0;
dd3a91
 	}
dd3a91
 
dd3a91
-	/* creating:  allow suitable space for bitmap */
dd3a91
-	bmspace = choose_bm_space(devsize);
dd3a91
+	/* creating:  allow suitable space for bitmap or PPL */
dd3a91
+	bmspace = consistency_policy == CONSISTENCY_POLICY_PPL ?
dd3a91
+		  choose_ppl_space((*chunk)*2) : choose_bm_space(devsize);
dd3a91
 
dd3a91
 	if (data_offset == INVALID_SECTORS)
dd3a91
 		data_offset = st->data_offset;
dd3a91
@@ -2566,7 +2679,7 @@ static int validate_geometry1(struct supertype *st, int level,
dd3a91
 	switch(st->minor_version) {
dd3a91
 	case 0: /* metadata at end.  Round down and subtract space to reserve */
dd3a91
 		devsize = (devsize & ~(4ULL*2-1));
dd3a91
-		/* space for metadata, bblog, bitmap */
dd3a91
+		/* space for metadata, bblog, bitmap/ppl */
dd3a91
 		devsize -= 8*2 + 8 + bmspace;
dd3a91
 		break;
dd3a91
 	case 1:
dd3a91
@@ -2642,6 +2755,7 @@ struct superswitch super1 = {
dd3a91
 	.add_to_super = add_to_super1,
dd3a91
 	.examine_badblocks = examine_badblocks_super1,
dd3a91
 	.copy_metadata = copy_metadata1,
dd3a91
+	.write_init_ppl = write_init_ppl1,
dd3a91
 #endif
dd3a91
 	.match_home = match_home1,
dd3a91
 	.uuid_from_super = uuid_from_super1,