|
|
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,
|