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

Commit 78e470c2 authored by Heinz Mauelshagen's avatar Heinz Mauelshagen Committed by Mike Snitzer
Browse files

md: add raid4/5/6 journal mode switching API



Commit 2ded3703 ("md/r5cache: State machine for raid5-cache write
back mode") added support for "write-back" caching on the raid journal
device.

In order to allow the dm-raid target to switch between the available
"write-through" and "write-back" modes, provide a new
r5c_journal_mode_set() API.

Use the new API in existing r5c_journal_mode_store()

Signed-off-by: default avatarHeinz Mauelshagen <heinzm@redhat.com>
Acked-by: default avatarShaohua Li <shli@fb.com>
Signed-off-by: default avatarMike Snitzer <snitzer@redhat.com>
parent ff3af92b
Loading
Loading
Loading
Loading
+34 −28
Original line number Diff line number Diff line
@@ -53,16 +53,6 @@
 */
#define R5L_POOL_SIZE	4

/*
 * r5c journal modes of the array: write-back or write-through.
 * write-through mode has identical behavior as existing log only
 * implementation.
 */
enum r5c_journal_mode {
	R5C_JOURNAL_MODE_WRITE_THROUGH = 0,
	R5C_JOURNAL_MODE_WRITE_BACK = 1,
};

static char *r5c_journal_mode_str[] = {"write-through",
				       "write-back"};
/*
@@ -2327,40 +2317,56 @@ static ssize_t r5c_journal_mode_show(struct mddev *mddev, char *page)
	return ret;
}

static ssize_t r5c_journal_mode_store(struct mddev *mddev,
				      const char *page, size_t length)
/*
 * Set journal cache mode on @mddev (external API initially needed by dm-raid).
 *
 * @mode as defined in 'enum r5c_journal_mode'.
 *
 */
int r5c_journal_mode_set(struct mddev *mddev, int mode)
{
	struct r5conf *conf = mddev->private;
	struct r5l_log *log = conf->log;
	int val = -1, i;
	int len = length;

	if (!log)
		return -ENODEV;

	if (len && page[len - 1] == '\n')
		len -= 1;
	for (i = 0; i < ARRAY_SIZE(r5c_journal_mode_str); i++)
		if (strlen(r5c_journal_mode_str[i]) == len &&
		    strncmp(page, r5c_journal_mode_str[i], len) == 0) {
			val = i;
			break;
		}
	if (val < R5C_JOURNAL_MODE_WRITE_THROUGH ||
	    val > R5C_JOURNAL_MODE_WRITE_BACK)
	if (mode < R5C_JOURNAL_MODE_WRITE_THROUGH ||
	    mode > R5C_JOURNAL_MODE_WRITE_BACK)
		return -EINVAL;

	if (raid5_calc_degraded(conf) > 0 &&
	    val == R5C_JOURNAL_MODE_WRITE_BACK)
	    mode == R5C_JOURNAL_MODE_WRITE_BACK)
		return -EINVAL;

	mddev_suspend(mddev);
	conf->log->r5c_journal_mode = val;
	conf->log->r5c_journal_mode = mode;
	mddev_resume(mddev);

	pr_debug("md/raid:%s: setting r5c cache mode to %d: %s\n",
		 mdname(mddev), val, r5c_journal_mode_str[val]);
	return length;
		 mdname(mddev), mode, r5c_journal_mode_str[mode]);
	return 0;
}
EXPORT_SYMBOL(r5c_journal_mode_set);

static ssize_t r5c_journal_mode_store(struct mddev *mddev,
				      const char *page, size_t length)
{
	int mode = ARRAY_SIZE(r5c_journal_mode_str);
	size_t len = length;

	if (len < 2)
		return -EINVAL;

	if (page[len - 1] == '\n')
		len--;

	while (mode--)
		if (strlen(r5c_journal_mode_str[mode]) == len &&
		    !strncmp(page, r5c_journal_mode_str[mode], len))
			break;

	return r5c_journal_mode_set(mddev, mode) ?: length;
}

struct md_sysfs_entry
+11 −0
Original line number Diff line number Diff line
@@ -547,6 +547,16 @@ struct r5worker_group {
	int stripes_cnt;
};

/*
 * r5c journal modes of the array: write-back or write-through.
 * write-through mode has identical behavior as existing log only
 * implementation.
 */
enum r5c_journal_mode {
	R5C_JOURNAL_MODE_WRITE_THROUGH = 0,
	R5C_JOURNAL_MODE_WRITE_BACK = 1,
};

enum r5_cache_state {
	R5_INACTIVE_BLOCKED,	/* release of inactive stripes blocked,
				 * waiting for 25% to be free
@@ -795,4 +805,5 @@ extern void r5c_check_cached_full_stripe(struct r5conf *conf);
extern struct md_sysfs_entry r5c_journal_mode;
extern void r5c_update_on_rdev_error(struct mddev *mddev);
extern bool r5c_big_stripe_cached(struct r5conf *conf, sector_t sect);
extern int r5c_journal_mode_set(struct mddev *mddev, int journal_mode);
#endif