> On Mar 6, 2019, at 11:46 PM, Dabrowski, Mariusz <mariusz.dabrowski@xxxxxxxxx> wrote: > > On 2/18/19 3:04 PM, Mariusz Dabrowski wrote: >> 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. >> >> Signed-off-by: Mariusz Dabrowski <mariusz.dabrowski@xxxxxxxxx> >> --- >> v2: moved ppl_write_hint releated stuff from raid5.c to raid5-ppl.c >> >> Documentation/admin-guide/md.rst | 3 ++ >> drivers/md/raid5-log.h | 1 + >> drivers/md/raid5-ppl.c | 63 ++++++++++++++++++++++++++++++++++++++++ >> drivers/md/raid5.c | 1 + >> 4 files changed, 68 insertions(+) >> >> diff --git a/Documentation/admin-guide/md.rst b/Documentation/admin-guide/md.rst >> index 84de718f24a4..3c51084ffd37 100644 >> --- a/Documentation/admin-guide/md.rst >> +++ b/Documentation/admin-guide/md.rst >> @@ -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. >> diff --git a/drivers/md/raid5-log.h b/drivers/md/raid5-log.h >> index bfb811407061..43c714a8798c 100644 >> --- a/drivers/md/raid5-log.h >> +++ b/drivers/md/raid5-log.h >> @@ -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) >> { >> diff --git a/drivers/md/raid5-ppl.c b/drivers/md/raid5-ppl.c >> index 3a7c36326589..f2b3020c2ac8 100644 >> --- a/drivers/md/raid5-ppl.c >> +++ b/drivers/md/raid5-ppl.c >> @@ -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); >> diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c >> index cecea901ab8c..09562d7cc080 100644 >> --- a/drivers/md/raid5.c >> +++ b/drivers/md/raid5.c >> @@ -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 = { >> > > Ping Sorry for the delay. I somehow missed this one during vacation. Guoqing, could you please give "Acked-by" or "Reviewed-by" on this? Thanks, Song