mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 18:41:58 +09:00
md: introduce md_ro_state
[ Upstream commit f97a5528b2 ]
Introduce md_ro_state for mddev->ro, so it is easy to understand.
Signed-off-by: Ye Bin <yebin10@huawei.com>
Signed-off-by: Song Liu <song@kernel.org>
Stable-dep-of: c9f7cb5b2bc9 ("md: don't leave 'MD_RECOVERY_FROZEN' in error path of md_set_readonly()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
a38c1e766f
commit
5255ded034
152
drivers/md/md.c
152
drivers/md/md.c
@@ -93,6 +93,18 @@ static int remove_and_add_spares(struct mddev *mddev,
|
|||||||
struct md_rdev *this);
|
struct md_rdev *this);
|
||||||
static void mddev_detach(struct mddev *mddev);
|
static void mddev_detach(struct mddev *mddev);
|
||||||
|
|
||||||
|
enum md_ro_state {
|
||||||
|
MD_RDWR,
|
||||||
|
MD_RDONLY,
|
||||||
|
MD_AUTO_READ,
|
||||||
|
MD_MAX_STATE
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool md_is_rdwr(struct mddev *mddev)
|
||||||
|
{
|
||||||
|
return (mddev->ro == MD_RDWR);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Default number of read corrections we'll attempt on an rdev
|
* Default number of read corrections we'll attempt on an rdev
|
||||||
* before ejecting it from the array. We divide the read error
|
* before ejecting it from the array. We divide the read error
|
||||||
@@ -444,7 +456,7 @@ static void md_submit_bio(struct bio *bio)
|
|||||||
if (!bio)
|
if (!bio)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (mddev->ro == 1 && unlikely(rw == WRITE)) {
|
if (mddev->ro == MD_RDONLY && unlikely(rw == WRITE)) {
|
||||||
if (bio_sectors(bio) != 0)
|
if (bio_sectors(bio) != 0)
|
||||||
bio->bi_status = BLK_STS_IOERR;
|
bio->bi_status = BLK_STS_IOERR;
|
||||||
bio_endio(bio);
|
bio_endio(bio);
|
||||||
@@ -2643,7 +2655,7 @@ void md_update_sb(struct mddev *mddev, int force_change)
|
|||||||
int any_badblocks_changed = 0;
|
int any_badblocks_changed = 0;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
if (mddev->ro) {
|
if (!md_is_rdwr(mddev)) {
|
||||||
if (force_change)
|
if (force_change)
|
||||||
set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
|
set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
|
||||||
return;
|
return;
|
||||||
@@ -3909,7 +3921,7 @@ level_store(struct mddev *mddev, const char *buf, size_t len)
|
|||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
rv = -EROFS;
|
rv = -EROFS;
|
||||||
if (mddev->ro)
|
if (!md_is_rdwr(mddev))
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
|
||||||
/* request to change the personality. Need to ensure:
|
/* request to change the personality. Need to ensure:
|
||||||
@@ -4115,7 +4127,7 @@ layout_store(struct mddev *mddev, const char *buf, size_t len)
|
|||||||
if (mddev->pers) {
|
if (mddev->pers) {
|
||||||
if (mddev->pers->check_reshape == NULL)
|
if (mddev->pers->check_reshape == NULL)
|
||||||
err = -EBUSY;
|
err = -EBUSY;
|
||||||
else if (mddev->ro)
|
else if (!md_is_rdwr(mddev))
|
||||||
err = -EROFS;
|
err = -EROFS;
|
||||||
else {
|
else {
|
||||||
mddev->new_layout = n;
|
mddev->new_layout = n;
|
||||||
@@ -4224,7 +4236,7 @@ chunk_size_store(struct mddev *mddev, const char *buf, size_t len)
|
|||||||
if (mddev->pers) {
|
if (mddev->pers) {
|
||||||
if (mddev->pers->check_reshape == NULL)
|
if (mddev->pers->check_reshape == NULL)
|
||||||
err = -EBUSY;
|
err = -EBUSY;
|
||||||
else if (mddev->ro)
|
else if (!md_is_rdwr(mddev))
|
||||||
err = -EROFS;
|
err = -EROFS;
|
||||||
else {
|
else {
|
||||||
mddev->new_chunk_sectors = n >> 9;
|
mddev->new_chunk_sectors = n >> 9;
|
||||||
@@ -4347,13 +4359,13 @@ array_state_show(struct mddev *mddev, char *page)
|
|||||||
|
|
||||||
if (mddev->pers && !test_bit(MD_NOT_READY, &mddev->flags)) {
|
if (mddev->pers && !test_bit(MD_NOT_READY, &mddev->flags)) {
|
||||||
switch(mddev->ro) {
|
switch(mddev->ro) {
|
||||||
case 1:
|
case MD_RDONLY:
|
||||||
st = readonly;
|
st = readonly;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case MD_AUTO_READ:
|
||||||
st = read_auto;
|
st = read_auto;
|
||||||
break;
|
break;
|
||||||
case 0:
|
case MD_RDWR:
|
||||||
spin_lock(&mddev->lock);
|
spin_lock(&mddev->lock);
|
||||||
if (test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags))
|
if (test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags))
|
||||||
st = write_pending;
|
st = write_pending;
|
||||||
@@ -4389,7 +4401,8 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len)
|
|||||||
int err = 0;
|
int err = 0;
|
||||||
enum array_state st = match_word(buf, array_states);
|
enum array_state st = match_word(buf, array_states);
|
||||||
|
|
||||||
if (mddev->pers && (st == active || st == clean) && mddev->ro != 1) {
|
if (mddev->pers && (st == active || st == clean) &&
|
||||||
|
mddev->ro != MD_RDONLY) {
|
||||||
/* don't take reconfig_mutex when toggling between
|
/* don't take reconfig_mutex when toggling between
|
||||||
* clean and active
|
* clean and active
|
||||||
*/
|
*/
|
||||||
@@ -4433,23 +4446,23 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len)
|
|||||||
if (mddev->pers)
|
if (mddev->pers)
|
||||||
err = md_set_readonly(mddev, NULL);
|
err = md_set_readonly(mddev, NULL);
|
||||||
else {
|
else {
|
||||||
mddev->ro = 1;
|
mddev->ro = MD_RDONLY;
|
||||||
set_disk_ro(mddev->gendisk, 1);
|
set_disk_ro(mddev->gendisk, 1);
|
||||||
err = do_md_run(mddev);
|
err = do_md_run(mddev);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case read_auto:
|
case read_auto:
|
||||||
if (mddev->pers) {
|
if (mddev->pers) {
|
||||||
if (mddev->ro == 0)
|
if (md_is_rdwr(mddev))
|
||||||
err = md_set_readonly(mddev, NULL);
|
err = md_set_readonly(mddev, NULL);
|
||||||
else if (mddev->ro == 1)
|
else if (mddev->ro == MD_RDONLY)
|
||||||
err = restart_array(mddev);
|
err = restart_array(mddev);
|
||||||
if (err == 0) {
|
if (err == 0) {
|
||||||
mddev->ro = 2;
|
mddev->ro = MD_AUTO_READ;
|
||||||
set_disk_ro(mddev->gendisk, 0);
|
set_disk_ro(mddev->gendisk, 0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mddev->ro = 2;
|
mddev->ro = MD_AUTO_READ;
|
||||||
err = do_md_run(mddev);
|
err = do_md_run(mddev);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -4474,7 +4487,7 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len)
|
|||||||
wake_up(&mddev->sb_wait);
|
wake_up(&mddev->sb_wait);
|
||||||
err = 0;
|
err = 0;
|
||||||
} else {
|
} else {
|
||||||
mddev->ro = 0;
|
mddev->ro = MD_RDWR;
|
||||||
set_disk_ro(mddev->gendisk, 0);
|
set_disk_ro(mddev->gendisk, 0);
|
||||||
err = do_md_run(mddev);
|
err = do_md_run(mddev);
|
||||||
}
|
}
|
||||||
@@ -4775,7 +4788,7 @@ action_show(struct mddev *mddev, char *page)
|
|||||||
if (test_bit(MD_RECOVERY_FROZEN, &recovery))
|
if (test_bit(MD_RECOVERY_FROZEN, &recovery))
|
||||||
type = "frozen";
|
type = "frozen";
|
||||||
else if (test_bit(MD_RECOVERY_RUNNING, &recovery) ||
|
else if (test_bit(MD_RECOVERY_RUNNING, &recovery) ||
|
||||||
(!mddev->ro && test_bit(MD_RECOVERY_NEEDED, &recovery))) {
|
(md_is_rdwr(mddev) && test_bit(MD_RECOVERY_NEEDED, &recovery))) {
|
||||||
if (test_bit(MD_RECOVERY_RESHAPE, &recovery))
|
if (test_bit(MD_RECOVERY_RESHAPE, &recovery))
|
||||||
type = "reshape";
|
type = "reshape";
|
||||||
else if (test_bit(MD_RECOVERY_SYNC, &recovery)) {
|
else if (test_bit(MD_RECOVERY_SYNC, &recovery)) {
|
||||||
@@ -4861,11 +4874,11 @@ action_store(struct mddev *mddev, const char *page, size_t len)
|
|||||||
set_bit(MD_RECOVERY_REQUESTED, &mddev->recovery);
|
set_bit(MD_RECOVERY_REQUESTED, &mddev->recovery);
|
||||||
set_bit(MD_RECOVERY_SYNC, &mddev->recovery);
|
set_bit(MD_RECOVERY_SYNC, &mddev->recovery);
|
||||||
}
|
}
|
||||||
if (mddev->ro == 2) {
|
if (mddev->ro == MD_AUTO_READ) {
|
||||||
/* A write to sync_action is enough to justify
|
/* A write to sync_action is enough to justify
|
||||||
* canceling read-auto mode
|
* canceling read-auto mode
|
||||||
*/
|
*/
|
||||||
mddev->ro = 0;
|
mddev->ro = MD_RDWR;
|
||||||
md_wakeup_thread(mddev->sync_thread);
|
md_wakeup_thread(mddev->sync_thread);
|
||||||
}
|
}
|
||||||
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
|
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
|
||||||
@@ -5093,8 +5106,7 @@ max_sync_store(struct mddev *mddev, const char *buf, size_t len)
|
|||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
|
||||||
err = -EBUSY;
|
err = -EBUSY;
|
||||||
if (max < mddev->resync_max &&
|
if (max < mddev->resync_max && md_is_rdwr(mddev) &&
|
||||||
mddev->ro == 0 &&
|
|
||||||
test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
|
test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
|
||||||
@@ -5829,8 +5841,8 @@ int md_run(struct mddev *mddev)
|
|||||||
continue;
|
continue;
|
||||||
sync_blockdev(rdev->bdev);
|
sync_blockdev(rdev->bdev);
|
||||||
invalidate_bdev(rdev->bdev);
|
invalidate_bdev(rdev->bdev);
|
||||||
if (mddev->ro != 1 && rdev_read_only(rdev)) {
|
if (mddev->ro != MD_RDONLY && rdev_read_only(rdev)) {
|
||||||
mddev->ro = 1;
|
mddev->ro = MD_RDONLY;
|
||||||
if (mddev->gendisk)
|
if (mddev->gendisk)
|
||||||
set_disk_ro(mddev->gendisk, 1);
|
set_disk_ro(mddev->gendisk, 1);
|
||||||
}
|
}
|
||||||
@@ -5938,8 +5950,8 @@ int md_run(struct mddev *mddev)
|
|||||||
|
|
||||||
mddev->ok_start_degraded = start_dirty_degraded;
|
mddev->ok_start_degraded = start_dirty_degraded;
|
||||||
|
|
||||||
if (start_readonly && mddev->ro == 0)
|
if (start_readonly && md_is_rdwr(mddev))
|
||||||
mddev->ro = 2; /* read-only, but switch on first write */
|
mddev->ro = MD_AUTO_READ; /* read-only, but switch on first write */
|
||||||
|
|
||||||
err = pers->run(mddev);
|
err = pers->run(mddev);
|
||||||
if (err)
|
if (err)
|
||||||
@@ -6017,8 +6029,8 @@ int md_run(struct mddev *mddev)
|
|||||||
mddev->sysfs_action = sysfs_get_dirent_safe(mddev->kobj.sd, "sync_action");
|
mddev->sysfs_action = sysfs_get_dirent_safe(mddev->kobj.sd, "sync_action");
|
||||||
mddev->sysfs_completed = sysfs_get_dirent_safe(mddev->kobj.sd, "sync_completed");
|
mddev->sysfs_completed = sysfs_get_dirent_safe(mddev->kobj.sd, "sync_completed");
|
||||||
mddev->sysfs_degraded = sysfs_get_dirent_safe(mddev->kobj.sd, "degraded");
|
mddev->sysfs_degraded = sysfs_get_dirent_safe(mddev->kobj.sd, "degraded");
|
||||||
} else if (mddev->ro == 2) /* auto-readonly not meaningful */
|
} else if (mddev->ro == MD_AUTO_READ)
|
||||||
mddev->ro = 0;
|
mddev->ro = MD_RDWR;
|
||||||
|
|
||||||
atomic_set(&mddev->max_corr_read_errors,
|
atomic_set(&mddev->max_corr_read_errors,
|
||||||
MD_DEFAULT_MAX_CORRECTED_READ_ERRORS);
|
MD_DEFAULT_MAX_CORRECTED_READ_ERRORS);
|
||||||
@@ -6036,7 +6048,7 @@ int md_run(struct mddev *mddev)
|
|||||||
if (rdev->raid_disk >= 0)
|
if (rdev->raid_disk >= 0)
|
||||||
sysfs_link_rdev(mddev, rdev); /* failure here is OK */
|
sysfs_link_rdev(mddev, rdev); /* failure here is OK */
|
||||||
|
|
||||||
if (mddev->degraded && !mddev->ro)
|
if (mddev->degraded && md_is_rdwr(mddev))
|
||||||
/* This ensures that recovering status is reported immediately
|
/* This ensures that recovering status is reported immediately
|
||||||
* via sysfs - until a lack of spares is confirmed.
|
* via sysfs - until a lack of spares is confirmed.
|
||||||
*/
|
*/
|
||||||
@@ -6128,7 +6140,7 @@ static int restart_array(struct mddev *mddev)
|
|||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
if (!mddev->pers)
|
if (!mddev->pers)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (!mddev->ro)
|
if (md_is_rdwr(mddev))
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
@@ -6147,7 +6159,7 @@ static int restart_array(struct mddev *mddev)
|
|||||||
return -EROFS;
|
return -EROFS;
|
||||||
|
|
||||||
mddev->safemode = 0;
|
mddev->safemode = 0;
|
||||||
mddev->ro = 0;
|
mddev->ro = MD_RDWR;
|
||||||
set_disk_ro(disk, 0);
|
set_disk_ro(disk, 0);
|
||||||
pr_debug("md: %s switched to read-write mode.\n", mdname(mddev));
|
pr_debug("md: %s switched to read-write mode.\n", mdname(mddev));
|
||||||
/* Kick recovery or resync if necessary */
|
/* Kick recovery or resync if necessary */
|
||||||
@@ -6174,7 +6186,7 @@ static void md_clean(struct mddev *mddev)
|
|||||||
mddev->clevel[0] = 0;
|
mddev->clevel[0] = 0;
|
||||||
mddev->flags = 0;
|
mddev->flags = 0;
|
||||||
mddev->sb_flags = 0;
|
mddev->sb_flags = 0;
|
||||||
mddev->ro = 0;
|
mddev->ro = MD_RDWR;
|
||||||
mddev->metadata_type[0] = 0;
|
mddev->metadata_type[0] = 0;
|
||||||
mddev->chunk_sectors = 0;
|
mddev->chunk_sectors = 0;
|
||||||
mddev->ctime = mddev->utime = 0;
|
mddev->ctime = mddev->utime = 0;
|
||||||
@@ -6226,7 +6238,7 @@ static void __md_stop_writes(struct mddev *mddev)
|
|||||||
}
|
}
|
||||||
md_bitmap_flush(mddev);
|
md_bitmap_flush(mddev);
|
||||||
|
|
||||||
if (mddev->ro == 0 &&
|
if (md_is_rdwr(mddev) &&
|
||||||
((!mddev->in_sync && !mddev_is_clustered(mddev)) ||
|
((!mddev->in_sync && !mddev_is_clustered(mddev)) ||
|
||||||
mddev->sb_flags)) {
|
mddev->sb_flags)) {
|
||||||
/* mark array as shutdown cleanly */
|
/* mark array as shutdown cleanly */
|
||||||
@@ -6340,9 +6352,9 @@ static int md_set_readonly(struct mddev *mddev, struct block_device *bdev)
|
|||||||
__md_stop_writes(mddev);
|
__md_stop_writes(mddev);
|
||||||
|
|
||||||
err = -ENXIO;
|
err = -ENXIO;
|
||||||
if (mddev->ro==1)
|
if (mddev->ro == MD_RDONLY)
|
||||||
goto out;
|
goto out;
|
||||||
mddev->ro = 1;
|
mddev->ro = MD_RDONLY;
|
||||||
set_disk_ro(mddev->gendisk, 1);
|
set_disk_ro(mddev->gendisk, 1);
|
||||||
clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
|
clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
|
||||||
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
|
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
|
||||||
@@ -6399,7 +6411,7 @@ static int do_md_stop(struct mddev *mddev, int mode,
|
|||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
if (mddev->pers) {
|
if (mddev->pers) {
|
||||||
if (mddev->ro)
|
if (!md_is_rdwr(mddev))
|
||||||
set_disk_ro(disk, 0);
|
set_disk_ro(disk, 0);
|
||||||
|
|
||||||
__md_stop_writes(mddev);
|
__md_stop_writes(mddev);
|
||||||
@@ -6416,8 +6428,8 @@ static int do_md_stop(struct mddev *mddev, int mode,
|
|||||||
mutex_unlock(&mddev->open_mutex);
|
mutex_unlock(&mddev->open_mutex);
|
||||||
mddev->changed = 1;
|
mddev->changed = 1;
|
||||||
|
|
||||||
if (mddev->ro)
|
if (!md_is_rdwr(mddev))
|
||||||
mddev->ro = 0;
|
mddev->ro = MD_RDWR;
|
||||||
} else
|
} else
|
||||||
mutex_unlock(&mddev->open_mutex);
|
mutex_unlock(&mddev->open_mutex);
|
||||||
/*
|
/*
|
||||||
@@ -7232,7 +7244,7 @@ static int update_size(struct mddev *mddev, sector_t num_sectors)
|
|||||||
if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) ||
|
if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) ||
|
||||||
mddev->sync_thread)
|
mddev->sync_thread)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
if (mddev->ro)
|
if (!md_is_rdwr(mddev))
|
||||||
return -EROFS;
|
return -EROFS;
|
||||||
|
|
||||||
rdev_for_each(rdev, mddev) {
|
rdev_for_each(rdev, mddev) {
|
||||||
@@ -7262,7 +7274,7 @@ static int update_raid_disks(struct mddev *mddev, int raid_disks)
|
|||||||
/* change the number of raid disks */
|
/* change the number of raid disks */
|
||||||
if (mddev->pers->check_reshape == NULL)
|
if (mddev->pers->check_reshape == NULL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (mddev->ro)
|
if (!md_is_rdwr(mddev))
|
||||||
return -EROFS;
|
return -EROFS;
|
||||||
if (raid_disks <= 0 ||
|
if (raid_disks <= 0 ||
|
||||||
(mddev->max_disks && raid_disks >= mddev->max_disks))
|
(mddev->max_disks && raid_disks >= mddev->max_disks))
|
||||||
@@ -7686,26 +7698,25 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
|
|||||||
* The remaining ioctls are changing the state of the
|
* The remaining ioctls are changing the state of the
|
||||||
* superblock, so we do not allow them on read-only arrays.
|
* superblock, so we do not allow them on read-only arrays.
|
||||||
*/
|
*/
|
||||||
if (mddev->ro && mddev->pers) {
|
if (!md_is_rdwr(mddev) && mddev->pers) {
|
||||||
if (mddev->ro == 2) {
|
if (mddev->ro != MD_AUTO_READ) {
|
||||||
mddev->ro = 0;
|
|
||||||
sysfs_notify_dirent_safe(mddev->sysfs_state);
|
|
||||||
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
|
|
||||||
/* mddev_unlock will wake thread */
|
|
||||||
/* If a device failed while we were read-only, we
|
|
||||||
* need to make sure the metadata is updated now.
|
|
||||||
*/
|
|
||||||
if (test_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags)) {
|
|
||||||
mddev_unlock(mddev);
|
|
||||||
wait_event(mddev->sb_wait,
|
|
||||||
!test_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags) &&
|
|
||||||
!test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags));
|
|
||||||
mddev_lock_nointr(mddev);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
err = -EROFS;
|
err = -EROFS;
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
mddev->ro = MD_RDWR;
|
||||||
|
sysfs_notify_dirent_safe(mddev->sysfs_state);
|
||||||
|
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
|
||||||
|
/* mddev_unlock will wake thread */
|
||||||
|
/* If a device failed while we were read-only, we
|
||||||
|
* need to make sure the metadata is updated now.
|
||||||
|
*/
|
||||||
|
if (test_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags)) {
|
||||||
|
mddev_unlock(mddev);
|
||||||
|
wait_event(mddev->sb_wait,
|
||||||
|
!test_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags) &&
|
||||||
|
!test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags));
|
||||||
|
mddev_lock_nointr(mddev);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
@@ -7791,11 +7802,11 @@ static int md_set_read_only(struct block_device *bdev, bool ro)
|
|||||||
* Transitioning to read-auto need only happen for arrays that call
|
* Transitioning to read-auto need only happen for arrays that call
|
||||||
* md_write_start and which are not ready for writes yet.
|
* md_write_start and which are not ready for writes yet.
|
||||||
*/
|
*/
|
||||||
if (!ro && mddev->ro == 1 && mddev->pers) {
|
if (!ro && mddev->ro == MD_RDONLY && mddev->pers) {
|
||||||
err = restart_array(mddev);
|
err = restart_array(mddev);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
mddev->ro = 2;
|
mddev->ro = MD_AUTO_READ;
|
||||||
}
|
}
|
||||||
|
|
||||||
out_unlock:
|
out_unlock:
|
||||||
@@ -8269,9 +8280,9 @@ static int md_seq_show(struct seq_file *seq, void *v)
|
|||||||
seq_printf(seq, "%s : %sactive", mdname(mddev),
|
seq_printf(seq, "%s : %sactive", mdname(mddev),
|
||||||
mddev->pers ? "" : "in");
|
mddev->pers ? "" : "in");
|
||||||
if (mddev->pers) {
|
if (mddev->pers) {
|
||||||
if (mddev->ro==1)
|
if (mddev->ro == MD_RDONLY)
|
||||||
seq_printf(seq, " (read-only)");
|
seq_printf(seq, " (read-only)");
|
||||||
if (mddev->ro==2)
|
if (mddev->ro == MD_AUTO_READ)
|
||||||
seq_printf(seq, " (auto-read-only)");
|
seq_printf(seq, " (auto-read-only)");
|
||||||
seq_printf(seq, " %s", mddev->pers->name);
|
seq_printf(seq, " %s", mddev->pers->name);
|
||||||
}
|
}
|
||||||
@@ -8530,10 +8541,10 @@ bool md_write_start(struct mddev *mddev, struct bio *bi)
|
|||||||
if (bio_data_dir(bi) != WRITE)
|
if (bio_data_dir(bi) != WRITE)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
BUG_ON(mddev->ro == 1);
|
BUG_ON(mddev->ro == MD_RDONLY);
|
||||||
if (mddev->ro == 2) {
|
if (mddev->ro == MD_AUTO_READ) {
|
||||||
/* need to switch to read/write */
|
/* need to switch to read/write */
|
||||||
mddev->ro = 0;
|
mddev->ro = MD_RDWR;
|
||||||
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
|
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
|
||||||
md_wakeup_thread(mddev->thread);
|
md_wakeup_thread(mddev->thread);
|
||||||
md_wakeup_thread(mddev->sync_thread);
|
md_wakeup_thread(mddev->sync_thread);
|
||||||
@@ -8584,7 +8595,7 @@ void md_write_inc(struct mddev *mddev, struct bio *bi)
|
|||||||
{
|
{
|
||||||
if (bio_data_dir(bi) != WRITE)
|
if (bio_data_dir(bi) != WRITE)
|
||||||
return;
|
return;
|
||||||
WARN_ON_ONCE(mddev->in_sync || mddev->ro);
|
WARN_ON_ONCE(mddev->in_sync || !md_is_rdwr(mddev));
|
||||||
percpu_ref_get(&mddev->writes_pending);
|
percpu_ref_get(&mddev->writes_pending);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(md_write_inc);
|
EXPORT_SYMBOL(md_write_inc);
|
||||||
@@ -8690,7 +8701,7 @@ void md_allow_write(struct mddev *mddev)
|
|||||||
{
|
{
|
||||||
if (!mddev->pers)
|
if (!mddev->pers)
|
||||||
return;
|
return;
|
||||||
if (mddev->ro)
|
if (!md_is_rdwr(mddev))
|
||||||
return;
|
return;
|
||||||
if (!mddev->pers->sync_request)
|
if (!mddev->pers->sync_request)
|
||||||
return;
|
return;
|
||||||
@@ -8738,7 +8749,7 @@ void md_do_sync(struct md_thread *thread)
|
|||||||
if (test_bit(MD_RECOVERY_DONE, &mddev->recovery) ||
|
if (test_bit(MD_RECOVERY_DONE, &mddev->recovery) ||
|
||||||
test_bit(MD_RECOVERY_WAIT, &mddev->recovery))
|
test_bit(MD_RECOVERY_WAIT, &mddev->recovery))
|
||||||
return;
|
return;
|
||||||
if (mddev->ro) {/* never try to sync a read-only array */
|
if (!md_is_rdwr(mddev)) {/* never try to sync a read-only array */
|
||||||
set_bit(MD_RECOVERY_INTR, &mddev->recovery);
|
set_bit(MD_RECOVERY_INTR, &mddev->recovery);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -9207,9 +9218,9 @@ static int remove_and_add_spares(struct mddev *mddev,
|
|||||||
if (test_bit(Faulty, &rdev->flags))
|
if (test_bit(Faulty, &rdev->flags))
|
||||||
continue;
|
continue;
|
||||||
if (!test_bit(Journal, &rdev->flags)) {
|
if (!test_bit(Journal, &rdev->flags)) {
|
||||||
if (mddev->ro &&
|
if (!md_is_rdwr(mddev) &&
|
||||||
! (rdev->saved_raid_disk >= 0 &&
|
!(rdev->saved_raid_disk >= 0 &&
|
||||||
!test_bit(Bitmap_sync, &rdev->flags)))
|
!test_bit(Bitmap_sync, &rdev->flags)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
rdev->recovery_offset = 0;
|
rdev->recovery_offset = 0;
|
||||||
@@ -9307,7 +9318,8 @@ void md_check_recovery(struct mddev *mddev)
|
|||||||
flush_signals(current);
|
flush_signals(current);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mddev->ro && !test_bit(MD_RECOVERY_NEEDED, &mddev->recovery))
|
if (!md_is_rdwr(mddev) &&
|
||||||
|
!test_bit(MD_RECOVERY_NEEDED, &mddev->recovery))
|
||||||
return;
|
return;
|
||||||
if ( ! (
|
if ( ! (
|
||||||
(mddev->sb_flags & ~ (1<<MD_SB_CHANGE_PENDING)) ||
|
(mddev->sb_flags & ~ (1<<MD_SB_CHANGE_PENDING)) ||
|
||||||
@@ -9326,7 +9338,7 @@ void md_check_recovery(struct mddev *mddev)
|
|||||||
if (!mddev->external && mddev->safemode == 1)
|
if (!mddev->external && mddev->safemode == 1)
|
||||||
mddev->safemode = 0;
|
mddev->safemode = 0;
|
||||||
|
|
||||||
if (mddev->ro) {
|
if (!md_is_rdwr(mddev)) {
|
||||||
struct md_rdev *rdev;
|
struct md_rdev *rdev;
|
||||||
if (!mddev->external && mddev->in_sync)
|
if (!mddev->external && mddev->in_sync)
|
||||||
/* 'Blocked' flag not needed as failed devices
|
/* 'Blocked' flag not needed as failed devices
|
||||||
|
|||||||
Reference in New Issue
Block a user