diff options
author | Heinz Mauelshagen <heinzm@redhat.com> | 2017-03-22 12:44:37 -0400 |
---|---|---|
committer | Mike Snitzer <snitzer@redhat.com> | 2017-03-27 11:13:47 -0400 |
commit | 78e470c26f524f4706c2555613b9641d85190cbe (patch) | |
tree | dfc665acd9116cb93a2c11809758c13352950b62 | |
parent | ff3af92b4461be773337111daea80bb91b2cd545 (diff) |
md: add raid4/5/6 journal mode switching API
Commit 2ded370373a4 ("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: Heinz Mauelshagen <heinzm@redhat.com>
Acked-by: Shaohua Li <shli@fb.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
-rw-r--r-- | drivers/md/raid5-cache.c | 62 | ||||
-rw-r--r-- | drivers/md/raid5.h | 11 |
2 files changed, 45 insertions, 28 deletions
diff --git a/drivers/md/raid5-cache.c b/drivers/md/raid5-cache.c index 3f307be01b10..218b6f37da85 100644 --- a/drivers/md/raid5-cache.c +++ b/drivers/md/raid5-cache.c | |||
@@ -53,16 +53,6 @@ | |||
53 | */ | 53 | */ |
54 | #define R5L_POOL_SIZE 4 | 54 | #define R5L_POOL_SIZE 4 |
55 | 55 | ||
56 | /* | ||
57 | * r5c journal modes of the array: write-back or write-through. | ||
58 | * write-through mode has identical behavior as existing log only | ||
59 | * implementation. | ||
60 | */ | ||
61 | enum r5c_journal_mode { | ||
62 | R5C_JOURNAL_MODE_WRITE_THROUGH = 0, | ||
63 | R5C_JOURNAL_MODE_WRITE_BACK = 1, | ||
64 | }; | ||
65 | |||
66 | static char *r5c_journal_mode_str[] = {"write-through", | 56 | static char *r5c_journal_mode_str[] = {"write-through", |
67 | "write-back"}; | 57 | "write-back"}; |
68 | /* | 58 | /* |
@@ -2327,40 +2317,56 @@ static ssize_t r5c_journal_mode_show(struct mddev *mddev, char *page) | |||
2327 | return ret; | 2317 | return ret; |
2328 | } | 2318 | } |
2329 | 2319 | ||
2330 | static ssize_t r5c_journal_mode_store(struct mddev *mddev, | 2320 | /* |
2331 | const char *page, size_t length) | 2321 | * Set journal cache mode on @mddev (external API initially needed by dm-raid). |
2322 | * | ||
2323 | * @mode as defined in 'enum r5c_journal_mode'. | ||
2324 | * | ||
2325 | */ | ||
2326 | int r5c_journal_mode_set(struct mddev *mddev, int mode) | ||
2332 | { | 2327 | { |
2333 | struct r5conf *conf = mddev->private; | 2328 | struct r5conf *conf = mddev->private; |
2334 | struct r5l_log *log = conf->log; | 2329 | struct r5l_log *log = conf->log; |
2335 | int val = -1, i; | ||
2336 | int len = length; | ||
2337 | 2330 | ||
2338 | if (!log) | 2331 | if (!log) |
2339 | return -ENODEV; | 2332 | return -ENODEV; |
2340 | 2333 | ||
2341 | if (len && page[len - 1] == '\n') | 2334 | if (mode < R5C_JOURNAL_MODE_WRITE_THROUGH || |
2342 | len -= 1; | 2335 | mode > R5C_JOURNAL_MODE_WRITE_BACK) |
2343 | for (i = 0; i < ARRAY_SIZE(r5c_journal_mode_str); i++) | ||
2344 | if (strlen(r5c_journal_mode_str[i]) == len && | ||
2345 | strncmp(page, r5c_journal_mode_str[i], len) == 0) { | ||
2346 | val = i; | ||
2347 | break; | ||
2348 | } | ||
2349 | if (val < R5C_JOURNAL_MODE_WRITE_THROUGH || | ||
2350 | val > R5C_JOURNAL_MODE_WRITE_BACK) | ||
2351 | return -EINVAL; | 2336 | return -EINVAL; |
2352 | 2337 | ||
2353 | if (raid5_calc_degraded(conf) > 0 && | 2338 | if (raid5_calc_degraded(conf) > 0 && |
2354 | val == R5C_JOURNAL_MODE_WRITE_BACK) | 2339 | mode == R5C_JOURNAL_MODE_WRITE_BACK) |
2355 | return -EINVAL; | 2340 | return -EINVAL; |
2356 | 2341 | ||
2357 | mddev_suspend(mddev); | 2342 | mddev_suspend(mddev); |
2358 | conf->log->r5c_journal_mode = val; | 2343 | conf->log->r5c_journal_mode = mode; |
2359 | mddev_resume(mddev); | 2344 | mddev_resume(mddev); |
2360 | 2345 | ||
2361 | pr_debug("md/raid:%s: setting r5c cache mode to %d: %s\n", | 2346 | pr_debug("md/raid:%s: setting r5c cache mode to %d: %s\n", |
2362 | mdname(mddev), val, r5c_journal_mode_str[val]); | 2347 | mdname(mddev), mode, r5c_journal_mode_str[mode]); |
2363 | return length; | 2348 | return 0; |
2349 | } | ||
2350 | EXPORT_SYMBOL(r5c_journal_mode_set); | ||
2351 | |||
2352 | static ssize_t r5c_journal_mode_store(struct mddev *mddev, | ||
2353 | const char *page, size_t length) | ||
2354 | { | ||
2355 | int mode = ARRAY_SIZE(r5c_journal_mode_str); | ||
2356 | size_t len = length; | ||
2357 | |||
2358 | if (len < 2) | ||
2359 | return -EINVAL; | ||
2360 | |||
2361 | if (page[len - 1] == '\n') | ||
2362 | len--; | ||
2363 | |||
2364 | while (mode--) | ||
2365 | if (strlen(r5c_journal_mode_str[mode]) == len && | ||
2366 | !strncmp(page, r5c_journal_mode_str[mode], len)) | ||
2367 | break; | ||
2368 | |||
2369 | return r5c_journal_mode_set(mddev, mode) ?: length; | ||
2364 | } | 2370 | } |
2365 | 2371 | ||
2366 | struct md_sysfs_entry | 2372 | struct md_sysfs_entry |
diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h index 4bb27b97bf6b..ec8ca15774d7 100644 --- a/drivers/md/raid5.h +++ b/drivers/md/raid5.h | |||
@@ -547,6 +547,16 @@ struct r5worker_group { | |||
547 | int stripes_cnt; | 547 | int stripes_cnt; |
548 | }; | 548 | }; |
549 | 549 | ||
550 | /* | ||
551 | * r5c journal modes of the array: write-back or write-through. | ||
552 | * write-through mode has identical behavior as existing log only | ||
553 | * implementation. | ||
554 | */ | ||
555 | enum r5c_journal_mode { | ||
556 | R5C_JOURNAL_MODE_WRITE_THROUGH = 0, | ||
557 | R5C_JOURNAL_MODE_WRITE_BACK = 1, | ||
558 | }; | ||
559 | |||
550 | enum r5_cache_state { | 560 | enum r5_cache_state { |
551 | R5_INACTIVE_BLOCKED, /* release of inactive stripes blocked, | 561 | R5_INACTIVE_BLOCKED, /* release of inactive stripes blocked, |
552 | * waiting for 25% to be free | 562 | * waiting for 25% to be free |
@@ -795,4 +805,5 @@ extern void r5c_check_cached_full_stripe(struct r5conf *conf); | |||
795 | extern struct md_sysfs_entry r5c_journal_mode; | 805 | extern struct md_sysfs_entry r5c_journal_mode; |
796 | extern void r5c_update_on_rdev_error(struct mddev *mddev); | 806 | extern void r5c_update_on_rdev_error(struct mddev *mddev); |
797 | extern bool r5c_big_stripe_cached(struct r5conf *conf, sector_t sect); | 807 | extern bool r5c_big_stripe_cached(struct r5conf *conf, sector_t sect); |
808 | extern int r5c_journal_mode_set(struct mddev *mddev, int journal_mode); | ||
798 | #endif | 809 | #endif |