diff options
author | Song Liu <songliubraving@fb.com> | 2017-07-31 17:52:26 -0400 |
---|---|---|
committer | Shaohua Li <shli@fb.com> | 2017-08-08 10:42:36 -0400 |
commit | b44886c54a999771060371c3a05d5fedfc7e2102 (patch) | |
tree | 6803f9f24871193e61cecde1e21132006eac6d27 | |
parent | 81fe48e9aa00bdd509bd3c37a76d1132da6b9f09 (diff) |
md/r5cache: call mddev_lock/unlock() in r5c_journal_mode_set
In r5c_journal_mode_set(), it is necessary to call mddev_lock()
before accessing conf and conf->log. Otherwise, the conf->log
may change (and become NULL).
Shaohua: fix unlock in failure cases
Signed-off-by: Song Liu <songliubraving@fb.com>
Signed-off-by: Shaohua Li <shli@fb.com>
-rw-r--r-- | drivers/md/raid5-cache.c | 21 |
1 files changed, 15 insertions, 6 deletions
diff --git a/drivers/md/raid5-cache.c b/drivers/md/raid5-cache.c index bfa1e907c472..ce98414a6e34 100644 --- a/drivers/md/raid5-cache.c +++ b/drivers/md/raid5-cache.c | |||
@@ -2540,23 +2540,32 @@ static ssize_t r5c_journal_mode_show(struct mddev *mddev, char *page) | |||
2540 | */ | 2540 | */ |
2541 | int r5c_journal_mode_set(struct mddev *mddev, int mode) | 2541 | int r5c_journal_mode_set(struct mddev *mddev, int mode) |
2542 | { | 2542 | { |
2543 | struct r5conf *conf = mddev->private; | 2543 | struct r5conf *conf; |
2544 | struct r5l_log *log = conf->log; | 2544 | int err; |
2545 | |||
2546 | if (!log) | ||
2547 | return -ENODEV; | ||
2548 | 2545 | ||
2549 | if (mode < R5C_JOURNAL_MODE_WRITE_THROUGH || | 2546 | if (mode < R5C_JOURNAL_MODE_WRITE_THROUGH || |
2550 | mode > R5C_JOURNAL_MODE_WRITE_BACK) | 2547 | mode > R5C_JOURNAL_MODE_WRITE_BACK) |
2551 | return -EINVAL; | 2548 | return -EINVAL; |
2552 | 2549 | ||
2550 | err = mddev_lock(mddev); | ||
2551 | if (err) | ||
2552 | return err; | ||
2553 | conf = mddev->private; | ||
2554 | if (!conf || !conf->log) { | ||
2555 | mddev_unlock(mddev); | ||
2556 | return -ENODEV; | ||
2557 | } | ||
2558 | |||
2553 | if (raid5_calc_degraded(conf) > 0 && | 2559 | if (raid5_calc_degraded(conf) > 0 && |
2554 | mode == R5C_JOURNAL_MODE_WRITE_BACK) | 2560 | mode == R5C_JOURNAL_MODE_WRITE_BACK) { |
2561 | mddev_unlock(mddev); | ||
2555 | return -EINVAL; | 2562 | return -EINVAL; |
2563 | } | ||
2556 | 2564 | ||
2557 | mddev_suspend(mddev); | 2565 | mddev_suspend(mddev); |
2558 | conf->log->r5c_journal_mode = mode; | 2566 | conf->log->r5c_journal_mode = mode; |
2559 | mddev_resume(mddev); | 2567 | mddev_resume(mddev); |
2568 | mddev_unlock(mddev); | ||
2560 | 2569 | ||
2561 | pr_debug("md/raid:%s: setting r5c cache mode to %d: %s\n", | 2570 | pr_debug("md/raid:%s: setting r5c cache mode to %d: %s\n", |
2562 | mdname(mddev), mode, r5c_journal_mode_str[mode]); | 2571 | mdname(mddev), mode, r5c_journal_mode_str[mode]); |