dcavalca / rpms / mdadm

Forked from rpms/mdadm 3 years ago
Clone

Blame SOURCES/super1ppl-support.patch

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