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.c56
1 files changed, 32 insertions, 24 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 09be637d52cb..0f4a70c43ffc 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -3573,7 +3573,8 @@ suspend_lo_store(mddev_t *mddev, const char *buf, size_t len)
3573 char *e; 3573 char *e;
3574 unsigned long long new = simple_strtoull(buf, &e, 10); 3574 unsigned long long new = simple_strtoull(buf, &e, 10);
3575 3575
3576 if (mddev->pers->quiesce == NULL) 3576 if (mddev->pers == NULL ||
3577 mddev->pers->quiesce == NULL)
3577 return -EINVAL; 3578 return -EINVAL;
3578 if (buf == e || (*e && *e != '\n')) 3579 if (buf == e || (*e && *e != '\n'))
3579 return -EINVAL; 3580 return -EINVAL;
@@ -3601,7 +3602,8 @@ suspend_hi_store(mddev_t *mddev, const char *buf, size_t len)
3601 char *e; 3602 char *e;
3602 unsigned long long new = simple_strtoull(buf, &e, 10); 3603 unsigned long long new = simple_strtoull(buf, &e, 10);
3603 3604
3604 if (mddev->pers->quiesce == NULL) 3605 if (mddev->pers == NULL ||
3606 mddev->pers->quiesce == NULL)
3605 return -EINVAL; 3607 return -EINVAL;
3606 if (buf == e || (*e && *e != '\n')) 3608 if (buf == e || (*e && *e != '\n'))
3607 return -EINVAL; 3609 return -EINVAL;
@@ -3844,11 +3846,9 @@ static int md_alloc(dev_t dev, char *name)
3844 flush_scheduled_work(); 3846 flush_scheduled_work();
3845 3847
3846 mutex_lock(&disks_mutex); 3848 mutex_lock(&disks_mutex);
3847 if (mddev->gendisk) { 3849 error = -EEXIST;
3848 mutex_unlock(&disks_mutex); 3850 if (mddev->gendisk)
3849 mddev_put(mddev); 3851 goto abort;
3850 return -EEXIST;
3851 }
3852 3852
3853 if (name) { 3853 if (name) {
3854 /* Need to ensure that 'name' is not a duplicate. 3854 /* Need to ensure that 'name' is not a duplicate.
@@ -3860,17 +3860,15 @@ static int md_alloc(dev_t dev, char *name)
3860 if (mddev2->gendisk && 3860 if (mddev2->gendisk &&
3861 strcmp(mddev2->gendisk->disk_name, name) == 0) { 3861 strcmp(mddev2->gendisk->disk_name, name) == 0) {
3862 spin_unlock(&all_mddevs_lock); 3862 spin_unlock(&all_mddevs_lock);
3863 return -EEXIST; 3863 goto abort;
3864 } 3864 }
3865 spin_unlock(&all_mddevs_lock); 3865 spin_unlock(&all_mddevs_lock);
3866 } 3866 }
3867 3867
3868 error = -ENOMEM;
3868 mddev->queue = blk_alloc_queue(GFP_KERNEL); 3869 mddev->queue = blk_alloc_queue(GFP_KERNEL);
3869 if (!mddev->queue) { 3870 if (!mddev->queue)
3870 mutex_unlock(&disks_mutex); 3871 goto abort;
3871 mddev_put(mddev);
3872 return -ENOMEM;
3873 }
3874 mddev->queue->queuedata = mddev; 3872 mddev->queue->queuedata = mddev;
3875 3873
3876 /* Can be unlocked because the queue is new: no concurrency */ 3874 /* Can be unlocked because the queue is new: no concurrency */
@@ -3880,11 +3878,9 @@ static int md_alloc(dev_t dev, char *name)
3880 3878
3881 disk = alloc_disk(1 << shift); 3879 disk = alloc_disk(1 << shift);
3882 if (!disk) { 3880 if (!disk) {
3883 mutex_unlock(&disks_mutex);
3884 blk_cleanup_queue(mddev->queue); 3881 blk_cleanup_queue(mddev->queue);
3885 mddev->queue = NULL; 3882 mddev->queue = NULL;
3886 mddev_put(mddev); 3883 goto abort;
3887 return -ENOMEM;
3888 } 3884 }
3889 disk->major = MAJOR(mddev->unit); 3885 disk->major = MAJOR(mddev->unit);
3890 disk->first_minor = unit << shift; 3886 disk->first_minor = unit << shift;
@@ -3906,16 +3902,22 @@ static int md_alloc(dev_t dev, char *name)
3906 mddev->gendisk = disk; 3902 mddev->gendisk = disk;
3907 error = kobject_init_and_add(&mddev->kobj, &md_ktype, 3903 error = kobject_init_and_add(&mddev->kobj, &md_ktype,
3908 &disk_to_dev(disk)->kobj, "%s", "md"); 3904 &disk_to_dev(disk)->kobj, "%s", "md");
3909 mutex_unlock(&disks_mutex); 3905 if (error) {
3910 if (error) 3906 /* This isn't possible, but as kobject_init_and_add is marked
3907 * __must_check, we must do something with the result
3908 */
3911 printk(KERN_WARNING "md: cannot register %s/md - name in use\n", 3909 printk(KERN_WARNING "md: cannot register %s/md - name in use\n",
3912 disk->disk_name); 3910 disk->disk_name);
3913 else { 3911 error = 0;
3912 }
3913 abort:
3914 mutex_unlock(&disks_mutex);
3915 if (!error) {
3914 kobject_uevent(&mddev->kobj, KOBJ_ADD); 3916 kobject_uevent(&mddev->kobj, KOBJ_ADD);
3915 mddev->sysfs_state = sysfs_get_dirent(mddev->kobj.sd, "array_state"); 3917 mddev->sysfs_state = sysfs_get_dirent(mddev->kobj.sd, "array_state");
3916 } 3918 }
3917 mddev_put(mddev); 3919 mddev_put(mddev);
3918 return 0; 3920 return error;
3919} 3921}
3920 3922
3921static struct kobject *md_probe(dev_t dev, int *part, void *data) 3923static struct kobject *md_probe(dev_t dev, int *part, void *data)
@@ -6334,10 +6336,16 @@ void md_do_sync(mddev_t *mddev)
6334 sysfs_notify(&mddev->kobj, NULL, "sync_completed"); 6336 sysfs_notify(&mddev->kobj, NULL, "sync_completed");
6335 } 6337 }
6336 6338
6337 if (j >= mddev->resync_max) 6339 while (j >= mddev->resync_max && !kthread_should_stop()) {
6338 wait_event(mddev->recovery_wait, 6340 /* As this condition is controlled by user-space,
6339 mddev->resync_max > j 6341 * we can block indefinitely, so use '_interruptible'
6340 || kthread_should_stop()); 6342 * to avoid triggering warnings.
6343 */
6344 flush_signals(current); /* just in case */
6345 wait_event_interruptible(mddev->recovery_wait,
6346 mddev->resync_max > j
6347 || kthread_should_stop());
6348 }
6341 6349
6342 if (kthread_should_stop()) 6350 if (kthread_should_stop())
6343 goto interrupted; 6351 goto interrupted;