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.c27
1 files changed, 16 insertions, 11 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index df1230af02cd..43d033d9a05a 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -4172,9 +4172,11 @@ static int get_bitmap_file(mddev_t * mddev, void __user * arg)
4172 char *ptr, *buf = NULL; 4172 char *ptr, *buf = NULL;
4173 int err = -ENOMEM; 4173 int err = -ENOMEM;
4174 4174
4175 md_allow_write(mddev); 4175 if (md_allow_write(mddev))
4176 file = kmalloc(sizeof(*file), GFP_NOIO);
4177 else
4178 file = kmalloc(sizeof(*file), GFP_KERNEL);
4176 4179
4177 file = kmalloc(sizeof(*file), GFP_KERNEL);
4178 if (!file) 4180 if (!file)
4179 goto out; 4181 goto out;
4180 4182
@@ -5667,15 +5669,18 @@ void md_write_end(mddev_t *mddev)
5667 * may proceed without blocking. It is important to call this before 5669 * may proceed without blocking. It is important to call this before
5668 * attempting a GFP_KERNEL allocation while holding the mddev lock. 5670 * attempting a GFP_KERNEL allocation while holding the mddev lock.
5669 * Must be called with mddev_lock held. 5671 * Must be called with mddev_lock held.
5672 *
5673 * In the ->external case MD_CHANGE_CLEAN can not be cleared until mddev->lock
5674 * is dropped, so return -EAGAIN after notifying userspace.
5670 */ 5675 */
5671void md_allow_write(mddev_t *mddev) 5676int md_allow_write(mddev_t *mddev)
5672{ 5677{
5673 if (!mddev->pers) 5678 if (!mddev->pers)
5674 return; 5679 return 0;
5675 if (mddev->ro) 5680 if (mddev->ro)
5676 return; 5681 return 0;
5677 if (!mddev->pers->sync_request) 5682 if (!mddev->pers->sync_request)
5678 return; 5683 return 0;
5679 5684
5680 spin_lock_irq(&mddev->write_lock); 5685 spin_lock_irq(&mddev->write_lock);
5681 if (mddev->in_sync) { 5686 if (mddev->in_sync) {
@@ -5686,14 +5691,14 @@ void md_allow_write(mddev_t *mddev)
5686 mddev->safemode = 1; 5691 mddev->safemode = 1;
5687 spin_unlock_irq(&mddev->write_lock); 5692 spin_unlock_irq(&mddev->write_lock);
5688 md_update_sb(mddev, 0); 5693 md_update_sb(mddev, 0);
5689
5690 sysfs_notify(&mddev->kobj, NULL, "array_state"); 5694 sysfs_notify(&mddev->kobj, NULL, "array_state");
5691 /* wait for the dirty state to be recorded in the metadata */
5692 wait_event(mddev->sb_wait,
5693 !test_bit(MD_CHANGE_CLEAN, &mddev->flags) &&
5694 !test_bit(MD_CHANGE_PENDING, &mddev->flags));
5695 } else 5695 } else
5696 spin_unlock_irq(&mddev->write_lock); 5696 spin_unlock_irq(&mddev->write_lock);
5697
5698 if (test_bit(MD_CHANGE_CLEAN, &mddev->flags))
5699 return -EAGAIN;
5700 else
5701 return 0;
5697} 5702}
5698EXPORT_SYMBOL_GPL(md_allow_write); 5703EXPORT_SYMBOL_GPL(md_allow_write);
5699 5704