aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeil Brown <neilb@suse.de>2008-07-11 08:02:22 -0400
committerNeil Brown <neilb@suse.de>2008-07-11 08:02:22 -0400
commitdf5b20cf68f9c90204c5fd36b7b090635cee3cdf (patch)
treed3d5690609085352485e8ddcc1650833df4be224
parent26ef379f53993b1da3c19b63257cd47e1d9cd672 (diff)
md: Better control of when do_md_stop is allowed to stop the array.
do_md_stop check the number of active users before allowing the array to be stopped. Two problems: 1/ it assumes the request is coming through an open file descriptor (via ioctl) so it allows for that. This is not always the case. 2/ it doesn't do the check it the array hasn't been activated. This is not good for cases when we use an inactive array to hold some devices in a container. Signed-off-by: Neil Brown <neilb@suse.de>
-rw-r--r--drivers/md/md.c29
1 files changed, 15 insertions, 14 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 328e247e2bf5..4c4c79da72b9 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -2688,7 +2688,7 @@ array_state_show(mddev_t *mddev, char *page)
2688 return sprintf(page, "%s\n", array_states[st]); 2688 return sprintf(page, "%s\n", array_states[st]);
2689} 2689}
2690 2690
2691static int do_md_stop(mddev_t * mddev, int ro); 2691static int do_md_stop(mddev_t * mddev, int ro, int is_open);
2692static int do_md_run(mddev_t * mddev); 2692static int do_md_run(mddev_t * mddev);
2693static int restart_array(mddev_t *mddev); 2693static int restart_array(mddev_t *mddev);
2694 2694
@@ -2704,14 +2704,14 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
2704 /* stopping an active array */ 2704 /* stopping an active array */
2705 if (atomic_read(&mddev->active) > 1) 2705 if (atomic_read(&mddev->active) > 1)
2706 return -EBUSY; 2706 return -EBUSY;
2707 err = do_md_stop(mddev, 0); 2707 err = do_md_stop(mddev, 0, 0);
2708 break; 2708 break;
2709 case inactive: 2709 case inactive:
2710 /* stopping an active array */ 2710 /* stopping an active array */
2711 if (mddev->pers) { 2711 if (mddev->pers) {
2712 if (atomic_read(&mddev->active) > 1) 2712 if (atomic_read(&mddev->active) > 1)
2713 return -EBUSY; 2713 return -EBUSY;
2714 err = do_md_stop(mddev, 2); 2714 err = do_md_stop(mddev, 2, 0);
2715 } else 2715 } else
2716 err = 0; /* already inactive */ 2716 err = 0; /* already inactive */
2717 break; 2717 break;
@@ -2719,7 +2719,7 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
2719 break; /* not supported yet */ 2719 break; /* not supported yet */
2720 case readonly: 2720 case readonly:
2721 if (mddev->pers) 2721 if (mddev->pers)
2722 err = do_md_stop(mddev, 1); 2722 err = do_md_stop(mddev, 1, 0);
2723 else { 2723 else {
2724 mddev->ro = 1; 2724 mddev->ro = 1;
2725 set_disk_ro(mddev->gendisk, 1); 2725 set_disk_ro(mddev->gendisk, 1);
@@ -2729,7 +2729,7 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
2729 case read_auto: 2729 case read_auto:
2730 if (mddev->pers) { 2730 if (mddev->pers) {
2731 if (mddev->ro != 1) 2731 if (mddev->ro != 1)
2732 err = do_md_stop(mddev, 1); 2732 err = do_md_stop(mddev, 1, 0);
2733 else 2733 else
2734 err = restart_array(mddev); 2734 err = restart_array(mddev);
2735 if (err == 0) { 2735 if (err == 0) {
@@ -3818,16 +3818,17 @@ static void restore_bitmap_write_access(struct file *file)
3818 * 1 - switch to readonly 3818 * 1 - switch to readonly
3819 * 2 - stop but do not disassemble array 3819 * 2 - stop but do not disassemble array
3820 */ 3820 */
3821static int do_md_stop(mddev_t * mddev, int mode) 3821static int do_md_stop(mddev_t * mddev, int mode, int is_open)
3822{ 3822{
3823 int err = 0; 3823 int err = 0;
3824 struct gendisk *disk = mddev->gendisk; 3824 struct gendisk *disk = mddev->gendisk;
3825 3825
3826 if (atomic_read(&mddev->active) > 1 + is_open) {
3827 printk("md: %s still in use.\n",mdname(mddev));
3828 return -EBUSY;
3829 }
3830
3826 if (mddev->pers) { 3831 if (mddev->pers) {
3827 if (atomic_read(&mddev->active)>2) {
3828 printk("md: %s still in use.\n",mdname(mddev));
3829 return -EBUSY;
3830 }
3831 3832
3832 if (mddev->sync_thread) { 3833 if (mddev->sync_thread) {
3833 set_bit(MD_RECOVERY_FROZEN, &mddev->recovery); 3834 set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
@@ -3976,7 +3977,7 @@ static void autorun_array(mddev_t *mddev)
3976 err = do_md_run (mddev); 3977 err = do_md_run (mddev);
3977 if (err) { 3978 if (err) {
3978 printk(KERN_WARNING "md: do_md_run() returned %d\n", err); 3979 printk(KERN_WARNING "md: do_md_run() returned %d\n", err);
3979 do_md_stop (mddev, 0); 3980 do_md_stop (mddev, 0, 0);
3980 } 3981 }
3981} 3982}
3982 3983
@@ -4931,11 +4932,11 @@ static int md_ioctl(struct inode *inode, struct file *file,
4931 goto done_unlock; 4932 goto done_unlock;
4932 4933
4933 case STOP_ARRAY: 4934 case STOP_ARRAY:
4934 err = do_md_stop (mddev, 0); 4935 err = do_md_stop (mddev, 0, 1);
4935 goto done_unlock; 4936 goto done_unlock;
4936 4937
4937 case STOP_ARRAY_RO: 4938 case STOP_ARRAY_RO:
4938 err = do_md_stop (mddev, 1); 4939 err = do_md_stop (mddev, 1, 1);
4939 goto done_unlock; 4940 goto done_unlock;
4940 4941
4941 } 4942 }
@@ -6226,7 +6227,7 @@ static int md_notify_reboot(struct notifier_block *this,
6226 6227
6227 for_each_mddev(mddev, tmp) 6228 for_each_mddev(mddev, tmp)
6228 if (mddev_trylock(mddev)) { 6229 if (mddev_trylock(mddev)) {
6229 do_md_stop (mddev, 1); 6230 do_md_stop (mddev, 1, 0);
6230 mddev_unlock(mddev); 6231 mddev_unlock(mddev);
6231 } 6232 }
6232 /* 6233 /*