Skip to content

Commit ddc0882

Browse files
pbaldysishligit
authored andcommitted
md: Runtime support for multiple ppls
Increase PPL area to 1MB and use it as circular buffer to store PPL. The entry with highest generation number is the latest one. If PPL to be written is larger then space left in a buffer, rewind the buffer to the start (don't wrap it). Signed-off-by: Pawel Baldysiak <[email protected]> Signed-off-by: Artur Paszkiewicz <[email protected]> Signed-off-by: Shaohua Li <[email protected]>
1 parent 8a8e6f8 commit ddc0882

File tree

7 files changed

+62
-9
lines changed

7 files changed

+62
-9
lines changed

drivers/md/md.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1536,7 +1536,8 @@ static int super_1_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_
15361536
} else if (sb->bblog_offset != 0)
15371537
rdev->badblocks.shift = 0;
15381538

1539-
if (le32_to_cpu(sb->feature_map) & MD_FEATURE_PPL) {
1539+
if ((le32_to_cpu(sb->feature_map) &
1540+
(MD_FEATURE_PPL | MD_FEATURE_MULTIPLE_PPLS))) {
15401541
rdev->ppl.offset = (__s16)le16_to_cpu(sb->ppl.offset);
15411542
rdev->ppl.size = le16_to_cpu(sb->ppl.size);
15421543
rdev->ppl.sector = rdev->sb_start + rdev->ppl.offset;
@@ -1655,10 +1656,15 @@ static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev)
16551656
if (le32_to_cpu(sb->feature_map) & MD_FEATURE_JOURNAL)
16561657
set_bit(MD_HAS_JOURNAL, &mddev->flags);
16571658

1658-
if (le32_to_cpu(sb->feature_map) & MD_FEATURE_PPL) {
1659+
if (le32_to_cpu(sb->feature_map) &
1660+
(MD_FEATURE_PPL | MD_FEATURE_MULTIPLE_PPLS)) {
16591661
if (le32_to_cpu(sb->feature_map) &
16601662
(MD_FEATURE_BITMAP_OFFSET | MD_FEATURE_JOURNAL))
16611663
return -EINVAL;
1664+
if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_PPL) &&
1665+
(le32_to_cpu(sb->feature_map) &
1666+
MD_FEATURE_MULTIPLE_PPLS))
1667+
return -EINVAL;
16621668
set_bit(MD_HAS_PPL, &mddev->flags);
16631669
}
16641670
} else if (mddev->pers == NULL) {
@@ -1875,7 +1881,11 @@ static void super_1_sync(struct mddev *mddev, struct md_rdev *rdev)
18751881
sb->feature_map |= cpu_to_le32(MD_FEATURE_JOURNAL);
18761882

18771883
if (test_bit(MD_HAS_PPL, &mddev->flags)) {
1878-
sb->feature_map |= cpu_to_le32(MD_FEATURE_PPL);
1884+
if (test_bit(MD_HAS_MULTIPLE_PPLS, &mddev->flags))
1885+
sb->feature_map |=
1886+
cpu_to_le32(MD_FEATURE_MULTIPLE_PPLS);
1887+
else
1888+
sb->feature_map |= cpu_to_le32(MD_FEATURE_PPL);
18791889
sb->ppl.offset = cpu_to_le16(rdev->ppl.offset);
18801890
sb->ppl.size = cpu_to_le16(rdev->ppl.size);
18811891
}

drivers/md/md.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ enum mddev_flags {
236236
* never cause the array to become failed.
237237
*/
238238
MD_HAS_PPL, /* The raid array has PPL feature set */
239+
MD_HAS_MULTIPLE_PPLS, /* The raid array has multiple PPLs feature set */
239240
};
240241

241242
enum mddev_sb_flags {

drivers/md/raid0.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@
3030
((1L << MD_HAS_JOURNAL) | \
3131
(1L << MD_JOURNAL_CLEAN) | \
3232
(1L << MD_FAILFAST_SUPPORTED) |\
33-
(1L << MD_HAS_PPL))
33+
(1L << MD_HAS_PPL) | \
34+
(1L << MD_HAS_MULTIPLE_PPLS))
3435

3536
static int raid0_congested(struct mddev *mddev, int bits)
3637
{

drivers/md/raid1.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@
4848
#define UNSUPPORTED_MDDEV_FLAGS \
4949
((1L << MD_HAS_JOURNAL) | \
5050
(1L << MD_JOURNAL_CLEAN) | \
51-
(1L << MD_HAS_PPL))
51+
(1L << MD_HAS_PPL) | \
52+
(1L << MD_HAS_MULTIPLE_PPLS))
5253

5354
/*
5455
* Number of guaranteed r1bios in case of extreme VM load:

drivers/md/raid5-ppl.c

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@
8787
* The current io_unit accepting new stripes is always at the end of the list.
8888
*/
8989

90+
#define PPL_SPACE_SIZE (128 * 1024)
91+
9092
struct ppl_conf {
9193
struct mddev *mddev;
9294

@@ -122,6 +124,10 @@ struct ppl_log {
122124
* always at the end of io_list */
123125
spinlock_t io_list_lock;
124126
struct list_head io_list; /* all io_units of this log */
127+
128+
sector_t next_io_sector;
129+
unsigned int entry_space;
130+
bool use_multippl;
125131
};
126132

127133
#define PPL_IO_INLINE_BVECS 32
@@ -264,13 +270,12 @@ static int ppl_log_stripe(struct ppl_log *log, struct stripe_head *sh)
264270
int i;
265271
sector_t data_sector = 0;
266272
int data_disks = 0;
267-
unsigned int entry_space = (log->rdev->ppl.size << 9) - PPL_HEADER_SIZE;
268273
struct r5conf *conf = sh->raid_conf;
269274

270275
pr_debug("%s: stripe: %llu\n", __func__, (unsigned long long)sh->sector);
271276

272277
/* check if current io_unit is full */
273-
if (io && (io->pp_size == entry_space ||
278+
if (io && (io->pp_size == log->entry_space ||
274279
io->entries_count == PPL_HDR_MAX_ENTRIES)) {
275280
pr_debug("%s: add io_unit blocked by seq: %llu\n",
276281
__func__, io->seq);
@@ -451,12 +456,25 @@ static void ppl_submit_iounit(struct ppl_io_unit *io)
451456
pplhdr->entries_count = cpu_to_le32(io->entries_count);
452457
pplhdr->checksum = cpu_to_le32(~crc32c_le(~0, pplhdr, PPL_HEADER_SIZE));
453458

459+
/* Rewind the buffer if current PPL is larger then remaining space */
460+
if (log->use_multippl &&
461+
log->rdev->ppl.sector + log->rdev->ppl.size - log->next_io_sector <
462+
(PPL_HEADER_SIZE + io->pp_size) >> 9)
463+
log->next_io_sector = log->rdev->ppl.sector;
464+
465+
454466
bio->bi_end_io = ppl_log_endio;
455467
bio->bi_opf = REQ_OP_WRITE | REQ_FUA;
456468
bio->bi_bdev = log->rdev->bdev;
457-
bio->bi_iter.bi_sector = log->rdev->ppl.sector;
469+
bio->bi_iter.bi_sector = log->next_io_sector;
458470
bio_add_page(bio, io->header_page, PAGE_SIZE, 0);
459471

472+
pr_debug("%s: log->current_io_sector: %llu\n", __func__,
473+
(unsigned long long)log->next_io_sector);
474+
475+
if (log->use_multippl)
476+
log->next_io_sector += (PPL_HEADER_SIZE + io->pp_size) >> 9;
477+
460478
list_for_each_entry(sh, &io->stripe_list, log_list) {
461479
/* entries for full stripe writes have no partial parity */
462480
if (test_bit(STRIPE_FULL_WRITE, &sh->state))
@@ -1031,6 +1049,7 @@ static int ppl_load(struct ppl_conf *ppl_conf)
10311049
static void __ppl_exit_log(struct ppl_conf *ppl_conf)
10321050
{
10331051
clear_bit(MD_HAS_PPL, &ppl_conf->mddev->flags);
1052+
clear_bit(MD_HAS_MULTIPLE_PPLS, &ppl_conf->mddev->flags);
10341053

10351054
kfree(ppl_conf->child_logs);
10361055

@@ -1099,6 +1118,22 @@ static int ppl_validate_rdev(struct md_rdev *rdev)
10991118
return 0;
11001119
}
11011120

1121+
static void ppl_init_child_log(struct ppl_log *log, struct md_rdev *rdev)
1122+
{
1123+
if ((rdev->ppl.size << 9) >= (PPL_SPACE_SIZE +
1124+
PPL_HEADER_SIZE) * 2) {
1125+
log->use_multippl = true;
1126+
set_bit(MD_HAS_MULTIPLE_PPLS,
1127+
&log->ppl_conf->mddev->flags);
1128+
log->entry_space = PPL_SPACE_SIZE;
1129+
} else {
1130+
log->use_multippl = false;
1131+
log->entry_space = (log->rdev->ppl.size << 9) -
1132+
PPL_HEADER_SIZE;
1133+
}
1134+
log->next_io_sector = rdev->ppl.sector;
1135+
}
1136+
11021137
int ppl_init_log(struct r5conf *conf)
11031138
{
11041139
struct ppl_conf *ppl_conf;
@@ -1196,6 +1231,7 @@ int ppl_init_log(struct r5conf *conf)
11961231
q = bdev_get_queue(rdev->bdev);
11971232
if (test_bit(QUEUE_FLAG_WC, &q->queue_flags))
11981233
need_cache_flush = true;
1234+
ppl_init_child_log(log, rdev);
11991235
}
12001236
}
12011237

@@ -1261,6 +1297,7 @@ int ppl_modify_log(struct r5conf *conf, struct md_rdev *rdev, bool add)
12611297
if (!ret) {
12621298
log->rdev = rdev;
12631299
ret = ppl_write_empty_header(log);
1300+
ppl_init_child_log(log, rdev);
12641301
}
12651302
} else {
12661303
log->rdev = NULL;

drivers/md/raid5.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7236,6 +7236,7 @@ static int raid5_run(struct mddev *mddev)
72367236
pr_warn("md/raid:%s: using journal device and PPL not allowed - disabling PPL\n",
72377237
mdname(mddev));
72387238
clear_bit(MD_HAS_PPL, &mddev->flags);
7239+
clear_bit(MD_HAS_MULTIPLE_PPLS, &mddev->flags);
72397240
}
72407241

72417242
if (mddev->private == NULL)

include/uapi/linux/raid/md_p.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,9 +324,10 @@ struct mdp_superblock_1 {
324324
#define MD_FEATURE_RECOVERY_BITMAP 128 /* recovery that is happening
325325
* is guided by bitmap.
326326
*/
327-
#define MD_FEATURE_CLUSTERED 256 /* clustered MD */
327+
#define MD_FEATURE_CLUSTERED 256 /* clustered MD */
328328
#define MD_FEATURE_JOURNAL 512 /* support write cache */
329329
#define MD_FEATURE_PPL 1024 /* support PPL */
330+
#define MD_FEATURE_MULTIPLE_PPLS 2048 /* support for multiple PPLs */
330331
#define MD_FEATURE_ALL (MD_FEATURE_BITMAP_OFFSET \
331332
|MD_FEATURE_RECOVERY_OFFSET \
332333
|MD_FEATURE_RESHAPE_ACTIVE \
@@ -338,6 +339,7 @@ struct mdp_superblock_1 {
338339
|MD_FEATURE_CLUSTERED \
339340
|MD_FEATURE_JOURNAL \
340341
|MD_FEATURE_PPL \
342+
|MD_FEATURE_MULTIPLE_PPLS \
341343
)
342344

343345
struct r5l_payload_header {

0 commit comments

Comments
 (0)