Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a596d086 authored by Mariusz Dabrowski's avatar Mariusz Dabrowski Committed by Song Liu
Browse files

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: default avatarGuoqing Jiang <gqjiang@suse.com>
Signed-off-by: default avatarMariusz Dabrowski <mariusz.dabrowski@intel.com>
Signed-off-by: default avatarSong Liu <songliubraving@fb.com>
parent 9205e449
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -756,3 +756,6 @@ These currently include:
      The cache mode for raid5. raid5 could include an extra disk for
      The cache mode for raid5. raid5 could include an extra disk for
      caching. The mode can be "write-throuth" and "write-back". The
      caching. The mode can be "write-throuth" and "write-back". The
      default is "write-through".
      default is "write-through".

  ppl_write_hint
      NVMe stream ID to be set for each PPL write request.
+1 −0
Original line number Original line Diff line number Diff line
@@ -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 int ppl_modify_log(struct r5conf *conf, struct md_rdev *rdev, bool add);
extern void ppl_quiesce(struct r5conf *conf, int quiesce);
extern void ppl_quiesce(struct r5conf *conf, int quiesce);
extern int ppl_handle_flush_request(struct r5l_log *log, struct bio *bio);
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)
static inline bool raid5_has_log(struct r5conf *conf)
{
{
+63 −0
Original line number Original line Diff line number Diff line
@@ -21,6 +21,7 @@
#include <linux/raid/md_p.h>
#include <linux/raid/md_p.h>
#include "md.h"
#include "md.h"
#include "raid5.h"
#include "raid5.h"
#include "raid5-log.h"


/*
/*
 * PPL consists of a 4KB header (struct ppl_header) and at least 128KB for
 * 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 */
	/* stripes to retry if failed to allocate io_unit */
	struct list_head no_mem_stripes;
	struct list_head no_mem_stripes;
	spinlock_t no_mem_stripes_lock;
	spinlock_t no_mem_stripes_lock;

	unsigned short write_hint;
};
};


struct ppl_log {
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_set_dev(bio, log->rdev->bdev);
	bio->bi_iter.bi_sector = log->next_io_sector;
	bio->bi_iter.bi_sector = log->next_io_sector;
	bio_add_page(bio, io->header_page, PAGE_SIZE, 0);
	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__,
	pr_debug("%s: log->current_io_sector: %llu\n", __func__,
	    (unsigned long long)log->next_io_sector);
	    (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,
			bio = bio_alloc_bioset(GFP_NOIO, BIO_MAX_PAGES,
					       &ppl_conf->bs);
					       &ppl_conf->bs);
			bio->bi_opf = prev->bi_opf;
			bio->bi_opf = prev->bi_opf;
			bio->bi_write_hint = prev->bi_write_hint;
			bio_copy_dev(bio, prev);
			bio_copy_dev(bio, prev);
			bio->bi_iter.bi_sector = bio_end_sector(prev);
			bio->bi_iter.bi_sector = bio_end_sector(prev);
			bio_add_page(bio, sh->ppl_page, PAGE_SIZE, 0);
			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);
	atomic64_set(&ppl_conf->seq, 0);
	INIT_LIST_HEAD(&ppl_conf->no_mem_stripes);
	INIT_LIST_HEAD(&ppl_conf->no_mem_stripes);
	spin_lock_init(&ppl_conf->no_mem_stripes_lock);
	spin_lock_init(&ppl_conf->no_mem_stripes_lock);
	ppl_conf->write_hint = RWF_WRITE_LIFE_NOT_SET;


	if (!mddev->external) {
	if (!mddev->external) {
		ppl_conf->signature = ~crc32c_le(~0, mddev->uuid, sizeof(mddev->uuid));
		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;
	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 −0
Original line number Original line Diff line number Diff line
@@ -6660,6 +6660,7 @@ static struct attribute *raid5_attrs[] = {
	&raid5_skip_copy.attr,
	&raid5_skip_copy.attr,
	&raid5_rmw_level.attr,
	&raid5_rmw_level.attr,
	&r5c_journal_mode.attr,
	&r5c_journal_mode.attr,
	&ppl_write_hint.attr,
	NULL,
	NULL,
};
};
static struct attribute_group raid5_attrs_group = {
static struct attribute_group raid5_attrs_group = {