diff options
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r-- | drivers/md/md.c | 58 |
1 files changed, 47 insertions, 11 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index 6c06e825cff5..509171ca7fa8 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -1318,6 +1318,7 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) | |||
1318 | char b[BDEVNAME_SIZE]; | 1318 | char b[BDEVNAME_SIZE]; |
1319 | struct kobject *ko; | 1319 | struct kobject *ko; |
1320 | char *s; | 1320 | char *s; |
1321 | int err; | ||
1321 | 1322 | ||
1322 | if (rdev->mddev) { | 1323 | if (rdev->mddev) { |
1323 | MD_BUG(); | 1324 | MD_BUG(); |
@@ -1352,20 +1353,35 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) | |||
1352 | while ( (s=strchr(rdev->kobj.k_name, '/')) != NULL) | 1353 | while ( (s=strchr(rdev->kobj.k_name, '/')) != NULL) |
1353 | *s = '!'; | 1354 | *s = '!'; |
1354 | 1355 | ||
1355 | list_add(&rdev->same_set, &mddev->disks); | ||
1356 | rdev->mddev = mddev; | 1356 | rdev->mddev = mddev; |
1357 | printk(KERN_INFO "md: bind<%s>\n", b); | 1357 | printk(KERN_INFO "md: bind<%s>\n", b); |
1358 | 1358 | ||
1359 | rdev->kobj.parent = &mddev->kobj; | 1359 | rdev->kobj.parent = &mddev->kobj; |
1360 | kobject_add(&rdev->kobj); | 1360 | if ((err = kobject_add(&rdev->kobj))) |
1361 | goto fail; | ||
1361 | 1362 | ||
1362 | if (rdev->bdev->bd_part) | 1363 | if (rdev->bdev->bd_part) |
1363 | ko = &rdev->bdev->bd_part->kobj; | 1364 | ko = &rdev->bdev->bd_part->kobj; |
1364 | else | 1365 | else |
1365 | ko = &rdev->bdev->bd_disk->kobj; | 1366 | ko = &rdev->bdev->bd_disk->kobj; |
1366 | sysfs_create_link(&rdev->kobj, ko, "block"); | 1367 | if ((err = sysfs_create_link(&rdev->kobj, ko, "block"))) { |
1368 | kobject_del(&rdev->kobj); | ||
1369 | goto fail; | ||
1370 | } | ||
1371 | list_add(&rdev->same_set, &mddev->disks); | ||
1367 | bd_claim_by_disk(rdev->bdev, rdev, mddev->gendisk); | 1372 | bd_claim_by_disk(rdev->bdev, rdev, mddev->gendisk); |
1368 | return 0; | 1373 | return 0; |
1374 | |||
1375 | fail: | ||
1376 | printk(KERN_WARNING "md: failed to register dev-%s for %s\n", | ||
1377 | b, mdname(mddev)); | ||
1378 | return err; | ||
1379 | } | ||
1380 | |||
1381 | static void delayed_delete(struct work_struct *ws) | ||
1382 | { | ||
1383 | mdk_rdev_t *rdev = container_of(ws, mdk_rdev_t, del_work); | ||
1384 | kobject_del(&rdev->kobj); | ||
1369 | } | 1385 | } |
1370 | 1386 | ||
1371 | static void unbind_rdev_from_array(mdk_rdev_t * rdev) | 1387 | static void unbind_rdev_from_array(mdk_rdev_t * rdev) |
@@ -1380,7 +1396,12 @@ static void unbind_rdev_from_array(mdk_rdev_t * rdev) | |||
1380 | printk(KERN_INFO "md: unbind<%s>\n", bdevname(rdev->bdev,b)); | 1396 | printk(KERN_INFO "md: unbind<%s>\n", bdevname(rdev->bdev,b)); |
1381 | rdev->mddev = NULL; | 1397 | rdev->mddev = NULL; |
1382 | sysfs_remove_link(&rdev->kobj, "block"); | 1398 | sysfs_remove_link(&rdev->kobj, "block"); |
1383 | kobject_del(&rdev->kobj); | 1399 | |
1400 | /* We need to delay this, otherwise we can deadlock when | ||
1401 | * writing to 'remove' to "dev/state" | ||
1402 | */ | ||
1403 | INIT_WORK(&rdev->del_work, delayed_delete); | ||
1404 | schedule_work(&rdev->del_work); | ||
1384 | } | 1405 | } |
1385 | 1406 | ||
1386 | /* | 1407 | /* |
@@ -2966,7 +2987,9 @@ static struct kobject *md_probe(dev_t dev, int *part, void *data) | |||
2966 | mddev->kobj.k_name = NULL; | 2987 | mddev->kobj.k_name = NULL; |
2967 | snprintf(mddev->kobj.name, KOBJ_NAME_LEN, "%s", "md"); | 2988 | snprintf(mddev->kobj.name, KOBJ_NAME_LEN, "%s", "md"); |
2968 | mddev->kobj.ktype = &md_ktype; | 2989 | mddev->kobj.ktype = &md_ktype; |
2969 | kobject_register(&mddev->kobj); | 2990 | if (kobject_register(&mddev->kobj)) |
2991 | printk(KERN_WARNING "md: cannot register %s/md - name in use\n", | ||
2992 | disk->disk_name); | ||
2970 | return NULL; | 2993 | return NULL; |
2971 | } | 2994 | } |
2972 | 2995 | ||
@@ -3144,9 +3167,12 @@ static int do_md_run(mddev_t * mddev) | |||
3144 | bitmap_destroy(mddev); | 3167 | bitmap_destroy(mddev); |
3145 | return err; | 3168 | return err; |
3146 | } | 3169 | } |
3147 | if (mddev->pers->sync_request) | 3170 | if (mddev->pers->sync_request) { |
3148 | sysfs_create_group(&mddev->kobj, &md_redundancy_group); | 3171 | if (sysfs_create_group(&mddev->kobj, &md_redundancy_group)) |
3149 | else if (mddev->ro == 2) /* auto-readonly not meaningful */ | 3172 | printk(KERN_WARNING |
3173 | "md: cannot register extra attributes for %s\n", | ||
3174 | mdname(mddev)); | ||
3175 | } else if (mddev->ro == 2) /* auto-readonly not meaningful */ | ||
3150 | mddev->ro = 0; | 3176 | mddev->ro = 0; |
3151 | 3177 | ||
3152 | atomic_set(&mddev->writes_pending,0); | 3178 | atomic_set(&mddev->writes_pending,0); |
@@ -3160,7 +3186,9 @@ static int do_md_run(mddev_t * mddev) | |||
3160 | if (rdev->raid_disk >= 0) { | 3186 | if (rdev->raid_disk >= 0) { |
3161 | char nm[20]; | 3187 | char nm[20]; |
3162 | sprintf(nm, "rd%d", rdev->raid_disk); | 3188 | sprintf(nm, "rd%d", rdev->raid_disk); |
3163 | sysfs_create_link(&mddev->kobj, &rdev->kobj, nm); | 3189 | if (sysfs_create_link(&mddev->kobj, &rdev->kobj, nm)) |
3190 | printk("md: cannot register %s for %s\n", | ||
3191 | nm, mdname(mddev)); | ||
3164 | } | 3192 | } |
3165 | 3193 | ||
3166 | set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); | 3194 | set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); |
@@ -3325,6 +3353,7 @@ static int do_md_stop(mddev_t * mddev, int mode) | |||
3325 | mddev->queue->merge_bvec_fn = NULL; | 3353 | mddev->queue->merge_bvec_fn = NULL; |
3326 | mddev->queue->unplug_fn = NULL; | 3354 | mddev->queue->unplug_fn = NULL; |
3327 | mddev->queue->issue_flush_fn = NULL; | 3355 | mddev->queue->issue_flush_fn = NULL; |
3356 | mddev->queue->backing_dev_info.congested_fn = NULL; | ||
3328 | if (mddev->pers->sync_request) | 3357 | if (mddev->pers->sync_request) |
3329 | sysfs_remove_group(&mddev->kobj, &md_redundancy_group); | 3358 | sysfs_remove_group(&mddev->kobj, &md_redundancy_group); |
3330 | 3359 | ||
@@ -3371,6 +3400,9 @@ static int do_md_stop(mddev_t * mddev, int mode) | |||
3371 | sysfs_remove_link(&mddev->kobj, nm); | 3400 | sysfs_remove_link(&mddev->kobj, nm); |
3372 | } | 3401 | } |
3373 | 3402 | ||
3403 | /* make sure all delayed_delete calls have finished */ | ||
3404 | flush_scheduled_work(); | ||
3405 | |||
3374 | export_array(mddev); | 3406 | export_array(mddev); |
3375 | 3407 | ||
3376 | mddev->array_size = 0; | 3408 | mddev->array_size = 0; |
@@ -5385,8 +5417,12 @@ static int remove_and_add_spares(mddev_t *mddev) | |||
5385 | if (mddev->pers->hot_add_disk(mddev,rdev)) { | 5417 | if (mddev->pers->hot_add_disk(mddev,rdev)) { |
5386 | char nm[20]; | 5418 | char nm[20]; |
5387 | sprintf(nm, "rd%d", rdev->raid_disk); | 5419 | sprintf(nm, "rd%d", rdev->raid_disk); |
5388 | sysfs_create_link(&mddev->kobj, | 5420 | if (sysfs_create_link(&mddev->kobj, |
5389 | &rdev->kobj, nm); | 5421 | &rdev->kobj, nm)) |
5422 | printk(KERN_WARNING | ||
5423 | "md: cannot register " | ||
5424 | "%s for %s\n", | ||
5425 | nm, mdname(mddev)); | ||
5390 | spares++; | 5426 | spares++; |
5391 | md_new_event(mddev); | 5427 | md_new_event(mddev); |
5392 | } else | 5428 | } else |