diff options
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r-- | drivers/md/md.c | 65 |
1 files changed, 32 insertions, 33 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index 4ad5cc4e63e8..8fda38d23e38 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -5181,32 +5181,6 @@ static int restart_array(struct mddev *mddev) | |||
5181 | return 0; | 5181 | return 0; |
5182 | } | 5182 | } |
5183 | 5183 | ||
5184 | /* similar to deny_write_access, but accounts for our holding a reference | ||
5185 | * to the file ourselves */ | ||
5186 | static int deny_bitmap_write_access(struct file * file) | ||
5187 | { | ||
5188 | struct inode *inode = file->f_mapping->host; | ||
5189 | |||
5190 | spin_lock(&inode->i_lock); | ||
5191 | if (atomic_read(&inode->i_writecount) > 1) { | ||
5192 | spin_unlock(&inode->i_lock); | ||
5193 | return -ETXTBSY; | ||
5194 | } | ||
5195 | atomic_set(&inode->i_writecount, -1); | ||
5196 | spin_unlock(&inode->i_lock); | ||
5197 | |||
5198 | return 0; | ||
5199 | } | ||
5200 | |||
5201 | void restore_bitmap_write_access(struct file *file) | ||
5202 | { | ||
5203 | struct inode *inode = file->f_mapping->host; | ||
5204 | |||
5205 | spin_lock(&inode->i_lock); | ||
5206 | atomic_set(&inode->i_writecount, 1); | ||
5207 | spin_unlock(&inode->i_lock); | ||
5208 | } | ||
5209 | |||
5210 | static void md_clean(struct mddev *mddev) | 5184 | static void md_clean(struct mddev *mddev) |
5211 | { | 5185 | { |
5212 | mddev->array_sectors = 0; | 5186 | mddev->array_sectors = 0; |
@@ -5427,7 +5401,6 @@ static int do_md_stop(struct mddev * mddev, int mode, | |||
5427 | 5401 | ||
5428 | bitmap_destroy(mddev); | 5402 | bitmap_destroy(mddev); |
5429 | if (mddev->bitmap_info.file) { | 5403 | if (mddev->bitmap_info.file) { |
5430 | restore_bitmap_write_access(mddev->bitmap_info.file); | ||
5431 | fput(mddev->bitmap_info.file); | 5404 | fput(mddev->bitmap_info.file); |
5432 | mddev->bitmap_info.file = NULL; | 5405 | mddev->bitmap_info.file = NULL; |
5433 | } | 5406 | } |
@@ -5979,7 +5952,7 @@ abort_export: | |||
5979 | 5952 | ||
5980 | static int set_bitmap_file(struct mddev *mddev, int fd) | 5953 | static int set_bitmap_file(struct mddev *mddev, int fd) |
5981 | { | 5954 | { |
5982 | int err; | 5955 | int err = 0; |
5983 | 5956 | ||
5984 | if (mddev->pers) { | 5957 | if (mddev->pers) { |
5985 | if (!mddev->pers->quiesce) | 5958 | if (!mddev->pers->quiesce) |
@@ -5991,6 +5964,7 @@ static int set_bitmap_file(struct mddev *mddev, int fd) | |||
5991 | 5964 | ||
5992 | 5965 | ||
5993 | if (fd >= 0) { | 5966 | if (fd >= 0) { |
5967 | struct inode *inode; | ||
5994 | if (mddev->bitmap) | 5968 | if (mddev->bitmap) |
5995 | return -EEXIST; /* cannot add when bitmap is present */ | 5969 | return -EEXIST; /* cannot add when bitmap is present */ |
5996 | mddev->bitmap_info.file = fget(fd); | 5970 | mddev->bitmap_info.file = fget(fd); |
@@ -6001,10 +5975,21 @@ static int set_bitmap_file(struct mddev *mddev, int fd) | |||
6001 | return -EBADF; | 5975 | return -EBADF; |
6002 | } | 5976 | } |
6003 | 5977 | ||
6004 | err = deny_bitmap_write_access(mddev->bitmap_info.file); | 5978 | inode = mddev->bitmap_info.file->f_mapping->host; |
6005 | if (err) { | 5979 | if (!S_ISREG(inode->i_mode)) { |
5980 | printk(KERN_ERR "%s: error: bitmap file must be a regular file\n", | ||
5981 | mdname(mddev)); | ||
5982 | err = -EBADF; | ||
5983 | } else if (!(mddev->bitmap_info.file->f_mode & FMODE_WRITE)) { | ||
5984 | printk(KERN_ERR "%s: error: bitmap file must open for write\n", | ||
5985 | mdname(mddev)); | ||
5986 | err = -EBADF; | ||
5987 | } else if (atomic_read(&inode->i_writecount) != 1) { | ||
6006 | printk(KERN_ERR "%s: error: bitmap file is already in use\n", | 5988 | printk(KERN_ERR "%s: error: bitmap file is already in use\n", |
6007 | mdname(mddev)); | 5989 | mdname(mddev)); |
5990 | err = -EBUSY; | ||
5991 | } | ||
5992 | if (err) { | ||
6008 | fput(mddev->bitmap_info.file); | 5993 | fput(mddev->bitmap_info.file); |
6009 | mddev->bitmap_info.file = NULL; | 5994 | mddev->bitmap_info.file = NULL; |
6010 | return err; | 5995 | return err; |
@@ -6027,10 +6012,8 @@ static int set_bitmap_file(struct mddev *mddev, int fd) | |||
6027 | mddev->pers->quiesce(mddev, 0); | 6012 | mddev->pers->quiesce(mddev, 0); |
6028 | } | 6013 | } |
6029 | if (fd < 0) { | 6014 | if (fd < 0) { |
6030 | if (mddev->bitmap_info.file) { | 6015 | if (mddev->bitmap_info.file) |
6031 | restore_bitmap_write_access(mddev->bitmap_info.file); | ||
6032 | fput(mddev->bitmap_info.file); | 6016 | fput(mddev->bitmap_info.file); |
6033 | } | ||
6034 | mddev->bitmap_info.file = NULL; | 6017 | mddev->bitmap_info.file = NULL; |
6035 | } | 6018 | } |
6036 | 6019 | ||
@@ -7182,11 +7165,14 @@ static int md_seq_open(struct inode *inode, struct file *file) | |||
7182 | return error; | 7165 | return error; |
7183 | } | 7166 | } |
7184 | 7167 | ||
7168 | static int md_unloading; | ||
7185 | static unsigned int mdstat_poll(struct file *filp, poll_table *wait) | 7169 | static unsigned int mdstat_poll(struct file *filp, poll_table *wait) |
7186 | { | 7170 | { |
7187 | struct seq_file *seq = filp->private_data; | 7171 | struct seq_file *seq = filp->private_data; |
7188 | int mask; | 7172 | int mask; |
7189 | 7173 | ||
7174 | if (md_unloading) | ||
7175 | return POLLIN|POLLRDNORM|POLLERR|POLLPRI;; | ||
7190 | poll_wait(filp, &md_event_waiters, wait); | 7176 | poll_wait(filp, &md_event_waiters, wait); |
7191 | 7177 | ||
7192 | /* always allow read */ | 7178 | /* always allow read */ |
@@ -8672,6 +8658,7 @@ static __exit void md_exit(void) | |||
8672 | { | 8658 | { |
8673 | struct mddev *mddev; | 8659 | struct mddev *mddev; |
8674 | struct list_head *tmp; | 8660 | struct list_head *tmp; |
8661 | int delay = 1; | ||
8675 | 8662 | ||
8676 | blk_unregister_region(MKDEV(MD_MAJOR,0), 1U << MINORBITS); | 8663 | blk_unregister_region(MKDEV(MD_MAJOR,0), 1U << MINORBITS); |
8677 | blk_unregister_region(MKDEV(mdp_major,0), 1U << MINORBITS); | 8664 | blk_unregister_region(MKDEV(mdp_major,0), 1U << MINORBITS); |
@@ -8680,7 +8667,19 @@ static __exit void md_exit(void) | |||
8680 | unregister_blkdev(mdp_major, "mdp"); | 8667 | unregister_blkdev(mdp_major, "mdp"); |
8681 | unregister_reboot_notifier(&md_notifier); | 8668 | unregister_reboot_notifier(&md_notifier); |
8682 | unregister_sysctl_table(raid_table_header); | 8669 | unregister_sysctl_table(raid_table_header); |
8670 | |||
8671 | /* We cannot unload the modules while some process is | ||
8672 | * waiting for us in select() or poll() - wake them up | ||
8673 | */ | ||
8674 | md_unloading = 1; | ||
8675 | while (waitqueue_active(&md_event_waiters)) { | ||
8676 | /* not safe to leave yet */ | ||
8677 | wake_up(&md_event_waiters); | ||
8678 | msleep(delay); | ||
8679 | delay += delay; | ||
8680 | } | ||
8683 | remove_proc_entry("mdstat", NULL); | 8681 | remove_proc_entry("mdstat", NULL); |
8682 | |||
8684 | for_each_mddev(mddev, tmp) { | 8683 | for_each_mddev(mddev, tmp) { |
8685 | export_array(mddev); | 8684 | export_array(mddev); |
8686 | mddev->hold_active = 0; | 8685 | mddev->hold_active = 0; |