Skip to content

Commit

Permalink
raid5: set write hint for PPL
Browse files Browse the repository at this point in the history
When the Partial Parity Log is enabled, circular buffer is used to store
PPL data. Each write to RAID device causes overwrite of data in this buffer
so some write_hint can be set to those request to help drives handle
garbage collection. This patch adds new sysfs attribute which can be used
to specify which write_hint should be assigned to PPL.

Acked-by: Guoqing Jiang <gqjiang@suse.com>
Signed-off-by: Mariusz Dabrowski <mariusz.dabrowski@intel.com>
Signed-off-by: Song Liu <songliubraving@fb.com>
  • Loading branch information
Mariusz Dabrowski authored and Song Liu committed Mar 12, 2019
1 parent 9205e44 commit a596d08
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 0 deletions.
3 changes: 3 additions & 0 deletions Documentation/admin-guide/md.rst
Original file line number Diff line number Diff line change
Expand Up @@ -756,3 +756,6 @@ These currently include:
The cache mode for raid5. raid5 could include an extra disk for
caching. The mode can be "write-throuth" and "write-back". The
default is "write-through".

ppl_write_hint
NVMe stream ID to be set for each PPL write request.
1 change: 1 addition & 0 deletions drivers/md/raid5-log.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ extern void ppl_stripe_write_finished(struct stripe_head *sh);
extern int ppl_modify_log(struct r5conf *conf, struct md_rdev *rdev, bool add);
extern void ppl_quiesce(struct r5conf *conf, int quiesce);
extern int ppl_handle_flush_request(struct r5l_log *log, struct bio *bio);
extern struct md_sysfs_entry ppl_write_hint;

static inline bool raid5_has_log(struct r5conf *conf)
{
Expand Down
63 changes: 63 additions & 0 deletions drivers/md/raid5-ppl.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <linux/raid/md_p.h>
#include "md.h"
#include "raid5.h"
#include "raid5-log.h"

/*
* PPL consists of a 4KB header (struct ppl_header) and at least 128KB for
Expand Down Expand Up @@ -116,6 +117,8 @@ struct ppl_conf {
/* stripes to retry if failed to allocate io_unit */
struct list_head no_mem_stripes;
spinlock_t no_mem_stripes_lock;

unsigned short write_hint;
};

struct ppl_log {
Expand Down Expand Up @@ -476,6 +479,7 @@ static void ppl_submit_iounit(struct ppl_io_unit *io)
bio_set_dev(bio, log->rdev->bdev);
bio->bi_iter.bi_sector = log->next_io_sector;
bio_add_page(bio, io->header_page, PAGE_SIZE, 0);
bio->bi_write_hint = ppl_conf->write_hint;

pr_debug("%s: log->current_io_sector: %llu\n", __func__,
(unsigned long long)log->next_io_sector);
Expand Down Expand Up @@ -505,6 +509,7 @@ static void ppl_submit_iounit(struct ppl_io_unit *io)
bio = bio_alloc_bioset(GFP_NOIO, BIO_MAX_PAGES,
&ppl_conf->bs);
bio->bi_opf = prev->bi_opf;
bio->bi_write_hint = prev->bi_write_hint;
bio_copy_dev(bio, prev);
bio->bi_iter.bi_sector = bio_end_sector(prev);
bio_add_page(bio, sh->ppl_page, PAGE_SIZE, 0);
Expand Down Expand Up @@ -1409,6 +1414,7 @@ int ppl_init_log(struct r5conf *conf)
atomic64_set(&ppl_conf->seq, 0);
INIT_LIST_HEAD(&ppl_conf->no_mem_stripes);
spin_lock_init(&ppl_conf->no_mem_stripes_lock);
ppl_conf->write_hint = RWF_WRITE_LIFE_NOT_SET;

if (!mddev->external) {
ppl_conf->signature = ~crc32c_le(~0, mddev->uuid, sizeof(mddev->uuid));
Expand Down Expand Up @@ -1503,3 +1509,60 @@ int ppl_modify_log(struct r5conf *conf, struct md_rdev *rdev, bool add)

return ret;
}

static ssize_t
ppl_write_hint_show(struct mddev *mddev, char *buf)
{
size_t ret = 0;
struct r5conf *conf;
struct ppl_conf *ppl_conf = NULL;

spin_lock(&mddev->lock);
conf = mddev->private;
if (conf && raid5_has_ppl(conf))
ppl_conf = conf->log_private;
ret = sprintf(buf, "%d\n", ppl_conf ? ppl_conf->write_hint : 0);
spin_unlock(&mddev->lock);

return ret;
}

static ssize_t
ppl_write_hint_store(struct mddev *mddev, const char *page, size_t len)
{
struct r5conf *conf;
struct ppl_conf *ppl_conf;
int err = 0;
unsigned short new;

if (len >= PAGE_SIZE)
return -EINVAL;
if (kstrtou16(page, 10, &new))
return -EINVAL;

err = mddev_lock(mddev);
if (err)
return err;

conf = mddev->private;
if (!conf) {
err = -ENODEV;
} else if (raid5_has_ppl(conf)) {
ppl_conf = conf->log_private;
if (!ppl_conf)
err = -EINVAL;
else
ppl_conf->write_hint = new;
} else {
err = -EINVAL;
}

mddev_unlock(mddev);

return err ?: len;
}

struct md_sysfs_entry
ppl_write_hint = __ATTR(ppl_write_hint, S_IRUGO | S_IWUSR,
ppl_write_hint_show,
ppl_write_hint_store);
1 change: 1 addition & 0 deletions drivers/md/raid5.c
Original file line number Diff line number Diff line change
Expand Up @@ -6660,6 +6660,7 @@ static struct attribute *raid5_attrs[] = {
&raid5_skip_copy.attr,
&raid5_rmw_level.attr,
&r5c_journal_mode.attr,
&ppl_write_hint.attr,
NULL,
};
static struct attribute_group raid5_attrs_group = {
Expand Down

0 comments on commit a596d08

Please sign in to comment.