diff options
author | Song Liu <songliubraving@fb.com> | 2015-10-09 00:54:13 -0400 |
---|---|---|
committer | NeilBrown <neilb@suse.com> | 2015-10-31 22:48:29 -0400 |
commit | 339421def582abb14c2217aa8c8f28bb2e299174 (patch) | |
tree | ffb4662582ae9357408d90d83a2e816923b055a3 /drivers/md/md.c | |
parent | f2076e7d0643d15b11db979acc7cffd2e8d69e77 (diff) |
MD: when RAID journal is missing/faulty, block RESTART_ARRAY_RW
When RAID-4/5/6 array suffers from missing journal device, we put
the array in read only state. We should not allow trasition to
read-write states (clean and active) before replacing journal device.
Signed-off-by: Song Liu <songliubraving@fb.com>
Signed-off-by: Shaohua Li <shli@fb.com>
Signed-off-by: NeilBrown <neilb@suse.com>
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r-- | drivers/md/md.c | 27 |
1 files changed, 25 insertions, 2 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index b5057596b630..08a4034351de 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -3970,7 +3970,9 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len) | |||
3970 | break; | 3970 | break; |
3971 | case clean: | 3971 | case clean: |
3972 | if (mddev->pers) { | 3972 | if (mddev->pers) { |
3973 | restart_array(mddev); | 3973 | err = restart_array(mddev); |
3974 | if (err) | ||
3975 | break; | ||
3974 | spin_lock(&mddev->lock); | 3976 | spin_lock(&mddev->lock); |
3975 | if (atomic_read(&mddev->writes_pending) == 0) { | 3977 | if (atomic_read(&mddev->writes_pending) == 0) { |
3976 | if (mddev->in_sync == 0) { | 3978 | if (mddev->in_sync == 0) { |
@@ -3988,7 +3990,9 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len) | |||
3988 | break; | 3990 | break; |
3989 | case active: | 3991 | case active: |
3990 | if (mddev->pers) { | 3992 | if (mddev->pers) { |
3991 | restart_array(mddev); | 3993 | err = restart_array(mddev); |
3994 | if (err) | ||
3995 | break; | ||
3992 | clear_bit(MD_CHANGE_PENDING, &mddev->flags); | 3996 | clear_bit(MD_CHANGE_PENDING, &mddev->flags); |
3993 | wake_up(&mddev->sb_wait); | 3997 | wake_up(&mddev->sb_wait); |
3994 | err = 0; | 3998 | err = 0; |
@@ -5351,6 +5355,25 @@ static int restart_array(struct mddev *mddev) | |||
5351 | return -EINVAL; | 5355 | return -EINVAL; |
5352 | if (!mddev->ro) | 5356 | if (!mddev->ro) |
5353 | return -EBUSY; | 5357 | return -EBUSY; |
5358 | if (test_bit(MD_HAS_JOURNAL, &mddev->flags)) { | ||
5359 | struct md_rdev *rdev; | ||
5360 | bool has_journal = false; | ||
5361 | |||
5362 | rcu_read_lock(); | ||
5363 | rdev_for_each_rcu(rdev, mddev) { | ||
5364 | if (test_bit(Journal, &rdev->flags) && | ||
5365 | !test_bit(Faulty, &rdev->flags)) { | ||
5366 | has_journal = true; | ||
5367 | break; | ||
5368 | } | ||
5369 | } | ||
5370 | rcu_read_unlock(); | ||
5371 | |||
5372 | /* Don't restart rw with journal missing/faulty */ | ||
5373 | if (!has_journal) | ||
5374 | return -EINVAL; | ||
5375 | } | ||
5376 | |||
5354 | mddev->safemode = 0; | 5377 | mddev->safemode = 0; |
5355 | mddev->ro = 0; | 5378 | mddev->ro = 0; |
5356 | set_disk_ro(disk, 0); | 5379 | set_disk_ro(disk, 0); |