aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSong Liu <songliubraving@fb.com>2017-07-31 17:52:26 -0400
committerShaohua Li <shli@fb.com>2017-08-08 10:42:36 -0400
commitb44886c54a999771060371c3a05d5fedfc7e2102 (patch)
tree6803f9f24871193e61cecde1e21132006eac6d27
parent81fe48e9aa00bdd509bd3c37a76d1132da6b9f09 (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.c21
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 */
2541int r5c_journal_mode_set(struct mddev *mddev, int mode) 2541int 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]);