aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2006-10-03 04:15:53 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-03 11:04:18 -0400
commitc04be0aa82ff535e3676ab3e573957bdeef41879 (patch)
tree8481ab270218bed246eb02b3ba04a4b84d4e90d0
parent11ce99e625fe2718ad2682bfdd99070b337e6252 (diff)
[PATCH] md: Improve locking around error handling
The error handling routines don't use proper locking, and so two concurrent errors could trigger a problem. So: - use test-and-set and test-and-clear to synchonise the In_sync bits with the ->degraded count - use the spinlock to protect updates to the degraded count (could use an atomic_t but that would be a bigger change in code, and isn't really justified) - remove un-necessary locking in raid5 Signed-off-by: Neil Brown <neilb@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--drivers/md/raid1.c16
-rw-r--r--drivers/md/raid10.c12
-rw-r--r--drivers/md/raid5.c20
3 files changed, 31 insertions, 17 deletions
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 3fc9ec239478..99c4e031c7f1 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -959,14 +959,16 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev)
959 * normal single drive 959 * normal single drive
960 */ 960 */
961 return; 961 return;
962 if (test_bit(In_sync, &rdev->flags)) { 962 if (test_and_clear_bit(In_sync, &rdev->flags)) {
963 unsigned long flags;
964 spin_lock_irqsave(&conf->device_lock, flags);
963 mddev->degraded++; 965 mddev->degraded++;
966 spin_unlock_irqrestore(&conf->device_lock, flags);
964 /* 967 /*
965 * if recovery is running, make sure it aborts. 968 * if recovery is running, make sure it aborts.
966 */ 969 */
967 set_bit(MD_RECOVERY_ERR, &mddev->recovery); 970 set_bit(MD_RECOVERY_ERR, &mddev->recovery);
968 } 971 }
969 clear_bit(In_sync, &rdev->flags);
970 set_bit(Faulty, &rdev->flags); 972 set_bit(Faulty, &rdev->flags);
971 set_bit(MD_CHANGE_DEVS, &mddev->flags); 973 set_bit(MD_CHANGE_DEVS, &mddev->flags);
972 printk(KERN_ALERT "raid1: Disk failure on %s, disabling device. \n" 974 printk(KERN_ALERT "raid1: Disk failure on %s, disabling device. \n"
@@ -1022,9 +1024,11 @@ static int raid1_spare_active(mddev_t *mddev)
1022 mdk_rdev_t *rdev = conf->mirrors[i].rdev; 1024 mdk_rdev_t *rdev = conf->mirrors[i].rdev;
1023 if (rdev 1025 if (rdev
1024 && !test_bit(Faulty, &rdev->flags) 1026 && !test_bit(Faulty, &rdev->flags)
1025 && !test_bit(In_sync, &rdev->flags)) { 1027 && !test_and_set_bit(In_sync, &rdev->flags)) {
1028 unsigned long flags;
1029 spin_lock_irqsave(&conf->device_lock, flags);
1026 mddev->degraded--; 1030 mddev->degraded--;
1027 set_bit(In_sync, &rdev->flags); 1031 spin_unlock_irqrestore(&conf->device_lock, flags);
1028 } 1032 }
1029 } 1033 }
1030 1034
@@ -2048,7 +2052,7 @@ static int raid1_reshape(mddev_t *mddev)
2048 mirror_info_t *newmirrors; 2052 mirror_info_t *newmirrors;
2049 conf_t *conf = mddev_to_conf(mddev); 2053 conf_t *conf = mddev_to_conf(mddev);
2050 int cnt, raid_disks; 2054 int cnt, raid_disks;
2051 2055 unsigned long flags;
2052 int d, d2; 2056 int d, d2;
2053 2057
2054 /* Cannot change chunk_size, layout, or level */ 2058 /* Cannot change chunk_size, layout, or level */
@@ -2107,7 +2111,9 @@ static int raid1_reshape(mddev_t *mddev)
2107 kfree(conf->poolinfo); 2111 kfree(conf->poolinfo);
2108 conf->poolinfo = newpoolinfo; 2112 conf->poolinfo = newpoolinfo;
2109 2113
2114 spin_lock_irqsave(&conf->device_lock, flags);
2110 mddev->degraded += (raid_disks - conf->raid_disks); 2115 mddev->degraded += (raid_disks - conf->raid_disks);
2116 spin_unlock_irqrestore(&conf->device_lock, flags);
2111 conf->raid_disks = mddev->raid_disks = raid_disks; 2117 conf->raid_disks = mddev->raid_disks = raid_disks;
2112 mddev->delta_disks = 0; 2118 mddev->delta_disks = 0;
2113 2119
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 233a4faede94..64f8016ab740 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -950,14 +950,16 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev)
950 * really dead" tests... 950 * really dead" tests...
951 */ 951 */
952 return; 952 return;
953 if (test_bit(In_sync, &rdev->flags)) { 953 if (test_and_clear_bit(In_sync, &rdev->flags)) {
954 unsigned long flags;
955 spin_lock_irqsave(&conf->device_lock, flags);
954 mddev->degraded++; 956 mddev->degraded++;
957 spin_unlock_irqrestore(&conf->device_lock, flags);
955 /* 958 /*
956 * if recovery is running, make sure it aborts. 959 * if recovery is running, make sure it aborts.
957 */ 960 */
958 set_bit(MD_RECOVERY_ERR, &mddev->recovery); 961 set_bit(MD_RECOVERY_ERR, &mddev->recovery);
959 } 962 }
960 clear_bit(In_sync, &rdev->flags);
961 set_bit(Faulty, &rdev->flags); 963 set_bit(Faulty, &rdev->flags);
962 set_bit(MD_CHANGE_DEVS, &mddev->flags); 964 set_bit(MD_CHANGE_DEVS, &mddev->flags);
963 printk(KERN_ALERT "raid10: Disk failure on %s, disabling device. \n" 965 printk(KERN_ALERT "raid10: Disk failure on %s, disabling device. \n"
@@ -1033,9 +1035,11 @@ static int raid10_spare_active(mddev_t *mddev)
1033 tmp = conf->mirrors + i; 1035 tmp = conf->mirrors + i;
1034 if (tmp->rdev 1036 if (tmp->rdev
1035 && !test_bit(Faulty, &tmp->rdev->flags) 1037 && !test_bit(Faulty, &tmp->rdev->flags)
1036 && !test_bit(In_sync, &tmp->rdev->flags)) { 1038 && !test_and_set_bit(In_sync, &tmp->rdev->flags)) {
1039 unsigned long flags;
1040 spin_lock_irqsave(&conf->device_lock, flags);
1037 mddev->degraded--; 1041 mddev->degraded--;
1038 set_bit(In_sync, &tmp->rdev->flags); 1042 spin_unlock_irqrestore(&conf->device_lock, flags);
1039 } 1043 }
1040 } 1044 }
1041 1045
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 46fd651539fe..6cea9c9a98e2 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -636,7 +636,6 @@ static int raid5_end_write_request (struct bio *bi, unsigned int bytes_done,
636 struct stripe_head *sh = bi->bi_private; 636 struct stripe_head *sh = bi->bi_private;
637 raid5_conf_t *conf = sh->raid_conf; 637 raid5_conf_t *conf = sh->raid_conf;
638 int disks = sh->disks, i; 638 int disks = sh->disks, i;
639 unsigned long flags;
640 int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags); 639 int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags);
641 640
642 if (bi->bi_size) 641 if (bi->bi_size)
@@ -654,7 +653,6 @@ static int raid5_end_write_request (struct bio *bi, unsigned int bytes_done,
654 return 0; 653 return 0;
655 } 654 }
656 655
657 spin_lock_irqsave(&conf->device_lock, flags);
658 if (!uptodate) 656 if (!uptodate)
659 md_error(conf->mddev, conf->disks[i].rdev); 657 md_error(conf->mddev, conf->disks[i].rdev);
660 658
@@ -662,8 +660,7 @@ static int raid5_end_write_request (struct bio *bi, unsigned int bytes_done,
662 660
663 clear_bit(R5_LOCKED, &sh->dev[i].flags); 661 clear_bit(R5_LOCKED, &sh->dev[i].flags);
664 set_bit(STRIPE_HANDLE, &sh->state); 662 set_bit(STRIPE_HANDLE, &sh->state);
665 __release_stripe(conf, sh); 663 release_stripe(sh);
666 spin_unlock_irqrestore(&conf->device_lock, flags);
667 return 0; 664 return 0;
668} 665}
669 666
@@ -697,9 +694,11 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev)
697 694
698 if (!test_bit(Faulty, &rdev->flags)) { 695 if (!test_bit(Faulty, &rdev->flags)) {
699 set_bit(MD_CHANGE_DEVS, &mddev->flags); 696 set_bit(MD_CHANGE_DEVS, &mddev->flags);
700 if (test_bit(In_sync, &rdev->flags)) { 697 if (test_and_clear_bit(In_sync, &rdev->flags)) {
698 unsigned long flags;
699 spin_lock_irqsave(&conf->device_lock, flags);
701 mddev->degraded++; 700 mddev->degraded++;
702 clear_bit(In_sync, &rdev->flags); 701 spin_unlock_irqrestore(&conf->device_lock, flags);
703 /* 702 /*
704 * if recovery was running, make sure it aborts. 703 * if recovery was running, make sure it aborts.
705 */ 704 */
@@ -3418,9 +3417,11 @@ static int raid5_spare_active(mddev_t *mddev)
3418 tmp = conf->disks + i; 3417 tmp = conf->disks + i;
3419 if (tmp->rdev 3418 if (tmp->rdev
3420 && !test_bit(Faulty, &tmp->rdev->flags) 3419 && !test_bit(Faulty, &tmp->rdev->flags)
3421 && !test_bit(In_sync, &tmp->rdev->flags)) { 3420 && !test_and_set_bit(In_sync, &tmp->rdev->flags)) {
3421 unsigned long flags;
3422 spin_lock_irqsave(&conf->device_lock, flags);
3422 mddev->degraded--; 3423 mddev->degraded--;
3423 set_bit(In_sync, &tmp->rdev->flags); 3424 spin_unlock_irqrestore(&conf->device_lock, flags);
3424 } 3425 }
3425 } 3426 }
3426 print_raid5_conf(conf); 3427 print_raid5_conf(conf);
@@ -3556,6 +3557,7 @@ static int raid5_start_reshape(mddev_t *mddev)
3556 struct list_head *rtmp; 3557 struct list_head *rtmp;
3557 int spares = 0; 3558 int spares = 0;
3558 int added_devices = 0; 3559 int added_devices = 0;
3560 unsigned long flags;
3559 3561
3560 if (mddev->degraded || 3562 if (mddev->degraded ||
3561 test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) 3563 test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
@@ -3597,7 +3599,9 @@ static int raid5_start_reshape(mddev_t *mddev)
3597 break; 3599 break;
3598 } 3600 }
3599 3601
3602 spin_lock_irqsave(&conf->device_lock, flags);
3600 mddev->degraded = (conf->raid_disks - conf->previous_raid_disks) - added_devices; 3603 mddev->degraded = (conf->raid_disks - conf->previous_raid_disks) - added_devices;
3604 spin_unlock_irqrestore(&conf->device_lock, flags);
3601 mddev->raid_disks = conf->raid_disks; 3605 mddev->raid_disks = conf->raid_disks;
3602 mddev->reshape_position = 0; 3606 mddev->reshape_position = 0;
3603 set_bit(MD_CHANGE_DEVS, &mddev->flags); 3607 set_bit(MD_CHANGE_DEVS, &mddev->flags);