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.c140
1 files changed, 85 insertions, 55 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 05febfd9f071..6c06e825cff5 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -1296,27 +1296,17 @@ static struct super_type super_types[] = {
1296 .sync_super = super_1_sync, 1296 .sync_super = super_1_sync,
1297 }, 1297 },
1298}; 1298};
1299
1300static mdk_rdev_t * match_dev_unit(mddev_t *mddev, mdk_rdev_t *dev)
1301{
1302 struct list_head *tmp;
1303 mdk_rdev_t *rdev;
1304
1305 ITERATE_RDEV(mddev,rdev,tmp)
1306 if (rdev->bdev->bd_contains == dev->bdev->bd_contains)
1307 return rdev;
1308
1309 return NULL;
1310}
1311 1299
1312static int match_mddev_units(mddev_t *mddev1, mddev_t *mddev2) 1300static int match_mddev_units(mddev_t *mddev1, mddev_t *mddev2)
1313{ 1301{
1314 struct list_head *tmp; 1302 struct list_head *tmp, *tmp2;
1315 mdk_rdev_t *rdev; 1303 mdk_rdev_t *rdev, *rdev2;
1316 1304
1317 ITERATE_RDEV(mddev1,rdev,tmp) 1305 ITERATE_RDEV(mddev1,rdev,tmp)
1318 if (match_dev_unit(mddev2, rdev)) 1306 ITERATE_RDEV(mddev2, rdev2, tmp2)
1319 return 1; 1307 if (rdev->bdev->bd_contains ==
1308 rdev2->bdev->bd_contains)
1309 return 1;
1320 1310
1321 return 0; 1311 return 0;
1322} 1312}
@@ -1325,8 +1315,7 @@ static LIST_HEAD(pending_raid_disks);
1325 1315
1326static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) 1316static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
1327{ 1317{
1328 mdk_rdev_t *same_pdev; 1318 char b[BDEVNAME_SIZE];
1329 char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
1330 struct kobject *ko; 1319 struct kobject *ko;
1331 char *s; 1320 char *s;
1332 1321
@@ -1342,14 +1331,6 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
1342 else 1331 else
1343 mddev->size = rdev->size; 1332 mddev->size = rdev->size;
1344 } 1333 }
1345 same_pdev = match_dev_unit(mddev, rdev);
1346 if (same_pdev)
1347 printk(KERN_WARNING
1348 "%s: WARNING: %s appears to be on the same physical"
1349 " disk as %s. True\n protection against single-disk"
1350 " failure might be compromised.\n",
1351 mdname(mddev), bdevname(rdev->bdev,b),
1352 bdevname(same_pdev->bdev,b2));
1353 1334
1354 /* Verify rdev->desc_nr is unique. 1335 /* Verify rdev->desc_nr is unique.
1355 * If it is -1, assign a free number, else 1336 * If it is -1, assign a free number, else
@@ -3109,6 +3090,36 @@ static int do_md_run(mddev_t * mddev)
3109 return -EINVAL; 3090 return -EINVAL;
3110 } 3091 }
3111 3092
3093 if (pers->sync_request) {
3094 /* Warn if this is a potentially silly
3095 * configuration.
3096 */
3097 char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
3098 mdk_rdev_t *rdev2;
3099 struct list_head *tmp2;
3100 int warned = 0;
3101 ITERATE_RDEV(mddev, rdev, tmp) {
3102 ITERATE_RDEV(mddev, rdev2, tmp2) {
3103 if (rdev < rdev2 &&
3104 rdev->bdev->bd_contains ==
3105 rdev2->bdev->bd_contains) {
3106 printk(KERN_WARNING
3107 "%s: WARNING: %s appears to be"
3108 " on the same physical disk as"
3109 " %s.\n",
3110 mdname(mddev),
3111 bdevname(rdev->bdev,b),
3112 bdevname(rdev2->bdev,b2));
3113 warned = 1;
3114 }
3115 }
3116 }
3117 if (warned)
3118 printk(KERN_WARNING
3119 "True protection against single-disk"
3120 " failure might be compromised.\n");
3121 }
3122
3112 mddev->recovery = 0; 3123 mddev->recovery = 0;
3113 mddev->resync_max_sectors = mddev->size << 1; /* may be over-ridden by personality */ 3124 mddev->resync_max_sectors = mddev->size << 1; /* may be over-ridden by personality */
3114 mddev->barriers_work = 1; 3125 mddev->barriers_work = 1;
@@ -3311,6 +3322,9 @@ static int do_md_stop(mddev_t * mddev, int mode)
3311 set_disk_ro(disk, 0); 3322 set_disk_ro(disk, 0);
3312 blk_queue_make_request(mddev->queue, md_fail_request); 3323 blk_queue_make_request(mddev->queue, md_fail_request);
3313 mddev->pers->stop(mddev); 3324 mddev->pers->stop(mddev);
3325 mddev->queue->merge_bvec_fn = NULL;
3326 mddev->queue->unplug_fn = NULL;
3327 mddev->queue->issue_flush_fn = NULL;
3314 if (mddev->pers->sync_request) 3328 if (mddev->pers->sync_request)
3315 sysfs_remove_group(&mddev->kobj, &md_redundancy_group); 3329 sysfs_remove_group(&mddev->kobj, &md_redundancy_group);
3316 3330
@@ -5343,6 +5357,44 @@ void md_do_sync(mddev_t *mddev)
5343EXPORT_SYMBOL_GPL(md_do_sync); 5357EXPORT_SYMBOL_GPL(md_do_sync);
5344 5358
5345 5359
5360static int remove_and_add_spares(mddev_t *mddev)
5361{
5362 mdk_rdev_t *rdev;
5363 struct list_head *rtmp;
5364 int spares = 0;
5365
5366 ITERATE_RDEV(mddev,rdev,rtmp)
5367 if (rdev->raid_disk >= 0 &&
5368 (test_bit(Faulty, &rdev->flags) ||
5369 ! test_bit(In_sync, &rdev->flags)) &&
5370 atomic_read(&rdev->nr_pending)==0) {
5371 if (mddev->pers->hot_remove_disk(
5372 mddev, rdev->raid_disk)==0) {
5373 char nm[20];
5374 sprintf(nm,"rd%d", rdev->raid_disk);
5375 sysfs_remove_link(&mddev->kobj, nm);
5376 rdev->raid_disk = -1;
5377 }
5378 }
5379
5380 if (mddev->degraded) {
5381 ITERATE_RDEV(mddev,rdev,rtmp)
5382 if (rdev->raid_disk < 0
5383 && !test_bit(Faulty, &rdev->flags)) {
5384 rdev->recovery_offset = 0;
5385 if (mddev->pers->hot_add_disk(mddev,rdev)) {
5386 char nm[20];
5387 sprintf(nm, "rd%d", rdev->raid_disk);
5388 sysfs_create_link(&mddev->kobj,
5389 &rdev->kobj, nm);
5390 spares++;
5391 md_new_event(mddev);
5392 } else
5393 break;
5394 }
5395 }
5396 return spares;
5397}
5346/* 5398/*
5347 * This routine is regularly called by all per-raid-array threads to 5399 * This routine is regularly called by all per-raid-array threads to
5348 * deal with generic issues like resync and super-block update. 5400 * deal with generic issues like resync and super-block update.
@@ -5397,7 +5449,7 @@ void md_check_recovery(mddev_t *mddev)
5397 return; 5449 return;
5398 5450
5399 if (mddev_trylock(mddev)) { 5451 if (mddev_trylock(mddev)) {
5400 int spares =0; 5452 int spares = 0;
5401 5453
5402 spin_lock_irq(&mddev->write_lock); 5454 spin_lock_irq(&mddev->write_lock);
5403 if (mddev->safemode && !atomic_read(&mddev->writes_pending) && 5455 if (mddev->safemode && !atomic_read(&mddev->writes_pending) &&
@@ -5460,35 +5512,13 @@ void md_check_recovery(mddev_t *mddev)
5460 * Spare are also removed and re-added, to allow 5512 * Spare are also removed and re-added, to allow
5461 * the personality to fail the re-add. 5513 * the personality to fail the re-add.
5462 */ 5514 */
5463 ITERATE_RDEV(mddev,rdev,rtmp)
5464 if (rdev->raid_disk >= 0 &&
5465 (test_bit(Faulty, &rdev->flags) || ! test_bit(In_sync, &rdev->flags)) &&
5466 atomic_read(&rdev->nr_pending)==0) {
5467 if (mddev->pers->hot_remove_disk(mddev, rdev->raid_disk)==0) {
5468 char nm[20];
5469 sprintf(nm,"rd%d", rdev->raid_disk);
5470 sysfs_remove_link(&mddev->kobj, nm);
5471 rdev->raid_disk = -1;
5472 }
5473 }
5474
5475 if (mddev->degraded) {
5476 ITERATE_RDEV(mddev,rdev,rtmp)
5477 if (rdev->raid_disk < 0
5478 && !test_bit(Faulty, &rdev->flags)) {
5479 rdev->recovery_offset = 0;
5480 if (mddev->pers->hot_add_disk(mddev,rdev)) {
5481 char nm[20];
5482 sprintf(nm, "rd%d", rdev->raid_disk);
5483 sysfs_create_link(&mddev->kobj, &rdev->kobj, nm);
5484 spares++;
5485 md_new_event(mddev);
5486 } else
5487 break;
5488 }
5489 }
5490 5515
5491 if (spares) { 5516 if (mddev->reshape_position != MaxSector) {
5517 if (mddev->pers->check_reshape(mddev) != 0)
5518 /* Cannot proceed */
5519 goto unlock;
5520 set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
5521 } else if ((spares = remove_and_add_spares(mddev))) {
5492 clear_bit(MD_RECOVERY_SYNC, &mddev->recovery); 5522 clear_bit(MD_RECOVERY_SYNC, &mddev->recovery);
5493 clear_bit(MD_RECOVERY_CHECK, &mddev->recovery); 5523 clear_bit(MD_RECOVERY_CHECK, &mddev->recovery);
5494 } else if (mddev->recovery_cp < MaxSector) { 5524 } else if (mddev->recovery_cp < MaxSector) {