raid5: set write hint for PPL

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>
This commit is contained in:
Mariusz Dabrowski 2019-02-18 15:04:09 +01:00 committed by Song Liu
parent 9205e44916
commit a596d08677
4 changed files with 68 additions and 0 deletions

View file

@ -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.

View file

@ -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)
{

View file

@ -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
@ -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 {
@ -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);
@ -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);
@ -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));
@ -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);

View file

@ -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 = {