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:
parent
9205e44916
commit
a596d08677
4 changed files with 68 additions and 0 deletions
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 = {
|
||||
|
|
Loading…
Reference in a new issue