diff options
author | Neil Brown <neilb@suse.de> | 2008-07-11 08:02:22 -0400 |
---|---|---|
committer | Neil Brown <neilb@suse.de> | 2008-07-11 08:02:22 -0400 |
commit | df5b20cf68f9c90204c5fd36b7b090635cee3cdf (patch) | |
tree | d3d5690609085352485e8ddcc1650833df4be224 /drivers/md | |
parent | 26ef379f53993b1da3c19b63257cd47e1d9cd672 (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>
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/md.c | 29 |
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 | ||
2691 | static int do_md_stop(mddev_t * mddev, int ro); | 2691 | static int do_md_stop(mddev_t * mddev, int ro, int is_open); |
2692 | static int do_md_run(mddev_t * mddev); | 2692 | static int do_md_run(mddev_t * mddev); |
2693 | static int restart_array(mddev_t *mddev); | 2693 | static 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 | */ |
3821 | static int do_md_stop(mddev_t * mddev, int mode) | 3821 | static 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 | /* |