Re: [PATCH] raid5: set write hint for PPL

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 





On 2/13/19 6:50 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>
---
  Documentation/admin-guide/md.rst |  3 +++
  drivers/md/raid5-ppl.c           |  3 +++
  drivers/md/raid5.c               | 50 ++++++++++++++++++++++++++++++++++++++++
  drivers/md/raid5.h               |  1 +
  4 files changed, 57 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-ppl.c b/drivers/md/raid5-ppl.c
index 3a7c36326589..46af40960ad2 100644
--- a/drivers/md/raid5-ppl.c
+++ b/drivers/md/raid5-ppl.c
@@ -440,6 +440,7 @@ static void ppl_submit_iounit(struct ppl_io_unit *io)
  	struct ppl_header *pplhdr = page_address(io->header_page);
  	struct bio *bio = &io->bio;
  	struct stripe_head *sh;
+	struct r5conf *r5_conf = ppl_conf->mddev->private;
  	int i;
bio->bi_private = io;
@@ -476,6 +477,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 = r5_conf->ppl_write_hint;
pr_debug("%s: log->current_io_sector: %llu\n", __func__,
  	    (unsigned long long)log->next_io_sector);
@@ -505,6 +507,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);
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index cecea901ab8c..2b2039b89445 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -6652,6 +6652,53 @@ raid5_group_thread_cnt = __ATTR(group_thread_cnt, S_IRUGO | S_IWUSR,
  				raid5_show_group_thread_cnt,
  				raid5_store_group_thread_cnt);
+static ssize_t
+raid5_show_ppl_write_hint(struct mddev *mddev, char *buf)
+{
+	size_t ret = 0;
+	struct r5conf *conf;
+
+	spin_lock(&mddev->lock);
+	conf = mddev->private;
+	if (conf)
+		ret = sprintf(buf, "%d\n", conf->ppl_write_hint);
+	spin_unlock(&mddev->lock);
+
+	return ret;
+}
+
+static ssize_t
+raid5_store_ppl_write_hint(struct mddev *mddev, const char *page, size_t len)
+{
+	struct r5conf *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
+		conf->ppl_write_hint = new;
+
+	mddev_unlock(mddev);
+
+	return err ?: len;
+}
+
+static struct md_sysfs_entry
+raid5_ppl_write_hint = __ATTR(ppl_write_hint, S_IRUGO | S_IWUSR,
+			      raid5_show_ppl_write_hint,
+			      raid5_store_ppl_write_hint);
+
  static struct attribute *raid5_attrs[] =  {
  	&raid5_stripecache_size.attr,
  	&raid5_stripecache_active.attr,
@@ -6660,6 +6707,7 @@ static struct attribute *raid5_attrs[] =  {
  	&raid5_skip_copy.attr,
  	&raid5_rmw_level.attr,
  	&r5c_journal_mode.attr,
+	&raid5_ppl_write_hint.attr,
  	NULL,
  };

Maybe it is better move raid5_ppl_write_hint related things to raid5-ppl.c just like r5c_journal_mode.

  static struct attribute_group raid5_attrs_group = {
@@ -7104,6 +7152,8 @@ static struct r5conf *setup_conf(struct mddev *mddev)
  		goto abort;
  	}
+ conf->ppl_write_hint = RWF_WRITE_LIFE_NOT_SET;
+
  	return conf;
abort:
diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h
index 8474c224127b..8ff1c06cf5d4 100644
--- a/drivers/md/raid5.h
+++ b/drivers/md/raid5.h
@@ -577,6 +577,7 @@ struct r5conf {
  	int			raid_disks;
  	int			max_nr_stripes;
  	int			min_nr_stripes;
+	unsigned short		ppl_write_hint;

Seems ppl_conf is the better place for ppl_write_hint.

Thanks,
Guoqing



[Index of Archives]     [Linux RAID Wiki]     [ATA RAID]     [Linux SCSI Target Infrastructure]     [Linux Block]     [Linux IDE]     [Linux SCSI]     [Linux Hams]     [Device Mapper]     [Device Mapper Cryptographics]     [Kernel]     [Linux Admin]     [Linux Net]     [GFS]     [RPM]     [git]     [Yosemite Forum]


  Powered by Linux