diff options
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r-- | drivers/md/md.c | 90 |
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 | ||
3311 | static int do_md_stop(mddev_t * mddev, int ro, int is_open); | 3311 | static int do_md_stop(mddev_t * mddev, int ro, int is_open); |
3312 | static int md_set_readonly(mddev_t * mddev, int is_open); | ||
3312 | static int do_md_run(mddev_t * mddev); | 3313 | static int do_md_run(mddev_t * mddev); |
3313 | static int restart_array(mddev_t *mddev); | 3314 | static 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 | ||
4645 | static 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 | } | ||
4666 | out: | ||
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 | */ |
4649 | static int do_md_stop(mddev_t * mddev, int mode, int is_open) | 4675 | static 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 | } |
4701 | out: | ||
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 | /* |