Skip to content

Commit

Permalink
md: Runtime support for multiple ppls
Browse files Browse the repository at this point in the history
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 <pawel.baldysiak@intel.com>
Signed-off-by: Artur Paszkiewicz <artur.paszkiewicz@intel.com>
Signed-off-by: Shaohua Li <shli@fb.com>
  • Loading branch information
Pawel Baldysiak authored and Shaohua Li committed Aug 28, 2017
1 parent 8a8e6f8 commit ddc0882
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 9 deletions.
16 changes: 13 additions & 3 deletions drivers/md/md.c
Original file line number Diff line number Diff line change
Expand Up @@ -1536,7 +1536,8 @@ static int super_1_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_
} else if (sb->bblog_offset != 0)
rdev->badblocks.shift = 0;

if (le32_to_cpu(sb->feature_map) & MD_FEATURE_PPL) {
if ((le32_to_cpu(sb->feature_map) &
(MD_FEATURE_PPL | MD_FEATURE_MULTIPLE_PPLS))) {
rdev->ppl.offset = (__s16)le16_to_cpu(sb->ppl.offset);
rdev->ppl.size = le16_to_cpu(sb->ppl.size);
rdev->ppl.sector = rdev->sb_start + rdev->ppl.offset;
Expand Down Expand Up @@ -1655,10 +1656,15 @@ static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev)
if (le32_to_cpu(sb->feature_map) & MD_FEATURE_JOURNAL)
set_bit(MD_HAS_JOURNAL, &mddev->flags);

if (le32_to_cpu(sb->feature_map) & MD_FEATURE_PPL) {
if (le32_to_cpu(sb->feature_map) &
(MD_FEATURE_PPL | MD_FEATURE_MULTIPLE_PPLS)) {
if (le32_to_cpu(sb->feature_map) &
(MD_FEATURE_BITMAP_OFFSET | MD_FEATURE_JOURNAL))
return -EINVAL;
if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_PPL) &&
(le32_to_cpu(sb->feature_map) &
MD_FEATURE_MULTIPLE_PPLS))
return -EINVAL;
set_bit(MD_HAS_PPL, &mddev->flags);
}
} else if (mddev->pers == NULL) {
Expand Down Expand Up @@ -1875,7 +1881,11 @@ static void super_1_sync(struct mddev *mddev, struct md_rdev *rdev)
sb->feature_map |= cpu_to_le32(MD_FEATURE_JOURNAL);

if (test_bit(MD_HAS_PPL, &mddev->flags)) {
sb->feature_map |= cpu_to_le32(MD_FEATURE_PPL);
if (test_bit(MD_HAS_MULTIPLE_PPLS, &mddev->flags))
sb->feature_map |=
cpu_to_le32(MD_FEATURE_MULTIPLE_PPLS);
else
sb->feature_map |= cpu_to_le32(MD_FEATURE_PPL);
sb->ppl.offset = cpu_to_le16(rdev->ppl.offset);
sb->ppl.size = cpu_to_le16(rdev->ppl.size);
}
Expand Down
1 change: 1 addition & 0 deletions drivers/md/md.h
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ enum mddev_flags {
* never cause the array to become failed.
*/
MD_HAS_PPL, /* The raid array has PPL feature set */
MD_HAS_MULTIPLE_PPLS, /* The raid array has multiple PPLs feature set */
};

enum mddev_sb_flags {
Expand Down
3 changes: 2 additions & 1 deletion drivers/md/raid0.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
((1L << MD_HAS_JOURNAL) | \
(1L << MD_JOURNAL_CLEAN) | \
(1L << MD_FAILFAST_SUPPORTED) |\
(1L << MD_HAS_PPL))
(1L << MD_HAS_PPL) | \
(1L << MD_HAS_MULTIPLE_PPLS))

static int raid0_congested(struct mddev *mddev, int bits)
{
Expand Down
3 changes: 2 additions & 1 deletion drivers/md/raid1.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@
#define UNSUPPORTED_MDDEV_FLAGS \
((1L << MD_HAS_JOURNAL) | \
(1L << MD_JOURNAL_CLEAN) | \
(1L << MD_HAS_PPL))
(1L << MD_HAS_PPL) | \
(1L << MD_HAS_MULTIPLE_PPLS))

/*
* Number of guaranteed r1bios in case of extreme VM load:
Expand Down
43 changes: 40 additions & 3 deletions drivers/md/raid5-ppl.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@
* The current io_unit accepting new stripes is always at the end of the list.
*/

#define PPL_SPACE_SIZE (128 * 1024)

struct ppl_conf {
struct mddev *mddev;

Expand Down Expand Up @@ -122,6 +124,10 @@ struct ppl_log {
* always at the end of io_list */
spinlock_t io_list_lock;
struct list_head io_list; /* all io_units of this log */

sector_t next_io_sector;
unsigned int entry_space;
bool use_multippl;
};

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

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

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

/* Rewind the buffer if current PPL is larger then remaining space */
if (log->use_multippl &&
log->rdev->ppl.sector + log->rdev->ppl.size - log->next_io_sector <
(PPL_HEADER_SIZE + io->pp_size) >> 9)
log->next_io_sector = log->rdev->ppl.sector;


bio->bi_end_io = ppl_log_endio;
bio->bi_opf = REQ_OP_WRITE | REQ_FUA;
bio->bi_bdev = log->rdev->bdev;
bio->bi_iter.bi_sector = log->rdev->ppl.sector;
bio->bi_iter.bi_sector = log->next_io_sector;
bio_add_page(bio, io->header_page, PAGE_SIZE, 0);

pr_debug("%s: log->current_io_sector: %llu\n", __func__,
(unsigned long long)log->next_io_sector);

if (log->use_multippl)
log->next_io_sector += (PPL_HEADER_SIZE + io->pp_size) >> 9;

list_for_each_entry(sh, &io->stripe_list, log_list) {
/* entries for full stripe writes have no partial parity */
if (test_bit(STRIPE_FULL_WRITE, &sh->state))
Expand Down Expand Up @@ -1031,6 +1049,7 @@ static int ppl_load(struct ppl_conf *ppl_conf)
static void __ppl_exit_log(struct ppl_conf *ppl_conf)
{
clear_bit(MD_HAS_PPL, &ppl_conf->mddev->flags);
clear_bit(MD_HAS_MULTIPLE_PPLS, &ppl_conf->mddev->flags);

kfree(ppl_conf->child_logs);

Expand Down Expand Up @@ -1099,6 +1118,22 @@ static int ppl_validate_rdev(struct md_rdev *rdev)
return 0;
}

static void ppl_init_child_log(struct ppl_log *log, struct md_rdev *rdev)
{
if ((rdev->ppl.size << 9) >= (PPL_SPACE_SIZE +
PPL_HEADER_SIZE) * 2) {
log->use_multippl = true;
set_bit(MD_HAS_MULTIPLE_PPLS,
&log->ppl_conf->mddev->flags);
log->entry_space = PPL_SPACE_SIZE;
} else {
log->use_multippl = false;
log->entry_space = (log->rdev->ppl.size << 9) -
PPL_HEADER_SIZE;
}
log->next_io_sector = rdev->ppl.sector;
}

int ppl_init_log(struct r5conf *conf)
{
struct ppl_conf *ppl_conf;
Expand Down Expand Up @@ -1196,6 +1231,7 @@ int ppl_init_log(struct r5conf *conf)
q = bdev_get_queue(rdev->bdev);
if (test_bit(QUEUE_FLAG_WC, &q->queue_flags))
need_cache_flush = true;
ppl_init_child_log(log, rdev);
}
}

Expand Down Expand Up @@ -1261,6 +1297,7 @@ int ppl_modify_log(struct r5conf *conf, struct md_rdev *rdev, bool add)
if (!ret) {
log->rdev = rdev;
ret = ppl_write_empty_header(log);
ppl_init_child_log(log, rdev);
}
} else {
log->rdev = NULL;
Expand Down
1 change: 1 addition & 0 deletions drivers/md/raid5.c
Original file line number Diff line number Diff line change
Expand Up @@ -7236,6 +7236,7 @@ static int raid5_run(struct mddev *mddev)
pr_warn("md/raid:%s: using journal device and PPL not allowed - disabling PPL\n",
mdname(mddev));
clear_bit(MD_HAS_PPL, &mddev->flags);
clear_bit(MD_HAS_MULTIPLE_PPLS, &mddev->flags);
}

if (mddev->private == NULL)
Expand Down
4 changes: 3 additions & 1 deletion include/uapi/linux/raid/md_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -324,9 +324,10 @@ struct mdp_superblock_1 {
#define MD_FEATURE_RECOVERY_BITMAP 128 /* recovery that is happening
* is guided by bitmap.
*/
#define MD_FEATURE_CLUSTERED 256 /* clustered MD */
#define MD_FEATURE_CLUSTERED 256 /* clustered MD */
#define MD_FEATURE_JOURNAL 512 /* support write cache */
#define MD_FEATURE_PPL 1024 /* support PPL */
#define MD_FEATURE_MULTIPLE_PPLS 2048 /* support for multiple PPLs */
#define MD_FEATURE_ALL (MD_FEATURE_BITMAP_OFFSET \
|MD_FEATURE_RECOVERY_OFFSET \
|MD_FEATURE_RESHAPE_ACTIVE \
Expand All @@ -338,6 +339,7 @@ struct mdp_superblock_1 {
|MD_FEATURE_CLUSTERED \
|MD_FEATURE_JOURNAL \
|MD_FEATURE_PPL \
|MD_FEATURE_MULTIPLE_PPLS \
)

struct r5l_payload_header {
Expand Down

0 comments on commit ddc0882

Please sign in to comment.