aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/md.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r--drivers/md/md.c90
1 files changed, 51 insertions, 39 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 86dfbc361cc0..3a2710a2e104 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -3309,6 +3309,7 @@ array_state_show(mddev_t *mddev, char *page)
3309} 3309}
3310 3310
3311static int do_md_stop(mddev_t * mddev, int ro, int is_open); 3311static int do_md_stop(mddev_t * mddev, int ro, int is_open);
3312static int md_set_readonly(mddev_t * mddev, int is_open);
3312static int do_md_run(mddev_t * mddev); 3313static int do_md_run(mddev_t * mddev);
3313static int restart_array(mddev_t *mddev); 3314static int restart_array(mddev_t *mddev);
3314 3315
@@ -3339,7 +3340,7 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
3339 break; /* not supported yet */ 3340 break; /* not supported yet */
3340 case readonly: 3341 case readonly:
3341 if (mddev->pers) 3342 if (mddev->pers)
3342 err = do_md_stop(mddev, 1, 0); 3343 err = md_set_readonly(mddev, 0);
3343 else { 3344 else {
3344 mddev->ro = 1; 3345 mddev->ro = 1;
3345 set_disk_ro(mddev->gendisk, 1); 3346 set_disk_ro(mddev->gendisk, 1);
@@ -3349,7 +3350,7 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
3349 case read_auto: 3350 case read_auto:
3350 if (mddev->pers) { 3351 if (mddev->pers) {
3351 if (mddev->ro == 0) 3352 if (mddev->ro == 0)
3352 err = do_md_stop(mddev, 1, 0); 3353 err = md_set_readonly(mddev, 0);
3353 else if (mddev->ro == 1) 3354 else if (mddev->ro == 1)
3354 err = restart_array(mddev); 3355 err = restart_array(mddev);
3355 if (err == 0) { 3356 if (err == 0) {
@@ -4641,9 +4642,34 @@ static void md_stop(mddev_t *mddev)
4641 4642
4642} 4643}
4643 4644
4645static int md_set_readonly(mddev_t *mddev, int is_open)
4646{
4647 int err = 0;
4648 mutex_lock(&mddev->open_mutex);
4649 if (atomic_read(&mddev->openers) > is_open) {
4650 printk("md: %s still in use.\n",mdname(mddev));
4651 err = -EBUSY;
4652 goto out;
4653 }
4654 if (mddev->pers) {
4655 md_stop_writes(mddev);
4656
4657 err = -ENXIO;
4658 if (mddev->ro==1)
4659 goto out;
4660 mddev->ro = 1;
4661 set_disk_ro(mddev->gendisk, 1);
4662 clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
4663 sysfs_notify_dirent(mddev->sysfs_state);
4664 err = 0;
4665 }
4666out:
4667 mutex_unlock(&mddev->open_mutex);
4668 return err;
4669}
4670
4644/* mode: 4671/* mode:
4645 * 0 - completely stop and dis-assemble array 4672 * 0 - completely stop and dis-assemble array
4646 * 1 - switch to readonly
4647 * 2 - stop but do not disassemble array 4673 * 2 - stop but do not disassemble array
4648 */ 4674 */
4649static int do_md_stop(mddev_t * mddev, int mode, int is_open) 4675static int do_md_stop(mddev_t * mddev, int mode, int is_open)
@@ -4660,45 +4686,33 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
4660 4686
4661 md_stop_writes(mddev); 4687 md_stop_writes(mddev);
4662 4688
4663 switch(mode) { 4689 if (mddev->ro)
4664 case 1: /* readonly */ 4690 set_disk_ro(disk, 0);
4665 err = -ENXIO;
4666 if (mddev->ro==1)
4667 goto out;
4668 mddev->ro = 1;
4669 break;
4670 case 0: /* disassemble */
4671 case 2: /* stop */
4672 if (mddev->ro)
4673 set_disk_ro(disk, 0);
4674 4691
4675 md_stop(mddev); 4692 md_stop(mddev);
4676 mddev->queue->merge_bvec_fn = NULL; 4693 mddev->queue->merge_bvec_fn = NULL;
4677 mddev->queue->unplug_fn = NULL; 4694 mddev->queue->unplug_fn = NULL;
4678 mddev->queue->backing_dev_info.congested_fn = NULL; 4695 mddev->queue->backing_dev_info.congested_fn = NULL;
4679 4696
4680 /* tell userspace to handle 'inactive' */ 4697 /* tell userspace to handle 'inactive' */
4681 sysfs_notify_dirent(mddev->sysfs_state); 4698 sysfs_notify_dirent(mddev->sysfs_state);
4682 4699
4683 list_for_each_entry(rdev, &mddev->disks, same_set) 4700 list_for_each_entry(rdev, &mddev->disks, same_set)
4684 if (rdev->raid_disk >= 0) { 4701 if (rdev->raid_disk >= 0) {
4685 char nm[20]; 4702 char nm[20];
4686 sprintf(nm, "rd%d", rdev->raid_disk); 4703 sprintf(nm, "rd%d", rdev->raid_disk);
4687 sysfs_remove_link(&mddev->kobj, nm); 4704 sysfs_remove_link(&mddev->kobj, nm);
4688 } 4705 }
4689 4706
4690 set_capacity(disk, 0); 4707 set_capacity(disk, 0);
4691 revalidate_disk(disk); 4708 revalidate_disk(disk);
4692 4709
4693 if (mddev->ro) 4710 if (mddev->ro)
4694 mddev->ro = 0; 4711 mddev->ro = 0;
4695 } 4712
4696 if (mode == 1)
4697 set_disk_ro(disk, 1);
4698 clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); 4713 clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
4699 err = 0; 4714 err = 0;
4700 } 4715 }
4701out:
4702 mutex_unlock(&mddev->open_mutex); 4716 mutex_unlock(&mddev->open_mutex);
4703 if (err) 4717 if (err)
4704 return err; 4718 return err;
@@ -4724,9 +4738,7 @@ out:
4724 if (mddev->hold_active == UNTIL_STOP) 4738 if (mddev->hold_active == UNTIL_STOP)
4725 mddev->hold_active = 0; 4739 mddev->hold_active = 0;
4726 4740
4727 } else if (mddev->pers) 4741 }
4728 printk(KERN_INFO "md: %s switched to read-only mode.\n",
4729 mdname(mddev));
4730 err = 0; 4742 err = 0;
4731 blk_integrity_unregister(disk); 4743 blk_integrity_unregister(disk);
4732 md_new_event(mddev); 4744 md_new_event(mddev);
@@ -5724,7 +5736,7 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
5724 goto done_unlock; 5736 goto done_unlock;
5725 5737
5726 case STOP_ARRAY_RO: 5738 case STOP_ARRAY_RO:
5727 err = do_md_stop(mddev, 1, 1); 5739 err = md_set_readonly(mddev, 1);
5728 goto done_unlock; 5740 goto done_unlock;
5729 5741
5730 case BLKROSET: 5742 case BLKROSET:
@@ -7140,7 +7152,7 @@ static int md_notify_reboot(struct notifier_block *this,
7140 * appears to still be in use. Hence 7152 * appears to still be in use. Hence
7141 * the '100'. 7153 * the '100'.
7142 */ 7154 */
7143 do_md_stop(mddev, 1, 100); 7155 md_set_readonly(mddev, 100);
7144 mddev_unlock(mddev); 7156 mddev_unlock(mddev);
7145 } 7157 }
7146 /* 7158 /*