diff options
author | NeilBrown <neilb@suse.de> | 2007-07-17 07:06:12 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-17 13:23:15 -0400 |
commit | 713f6ab18b0e7d39f14401362bfe8015b1aedde1 (patch) | |
tree | fc6ef865d09de1ec816ed96860ffc27dd48d837b /drivers/md/md.c | |
parent | df968c4e8d809deb2602fb0e8db758f26a4006b9 (diff) |
md: improve the is_mddev_idle test fix
Don't use 'unsigned' variable to track sync vs non-sync IO, as the only thing
we want to do with them is a signed comparison, and fix up the comment which
had become quite wrong.
Signed-off-by: Neil Brown <neilb@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r-- | drivers/md/md.c | 35 |
1 files changed, 22 insertions, 13 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index 3d5a6beb333b..bae42331182d 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -5091,7 +5091,7 @@ static int is_mddev_idle(mddev_t *mddev) | |||
5091 | mdk_rdev_t * rdev; | 5091 | mdk_rdev_t * rdev; |
5092 | struct list_head *tmp; | 5092 | struct list_head *tmp; |
5093 | int idle; | 5093 | int idle; |
5094 | unsigned long curr_events; | 5094 | long curr_events; |
5095 | 5095 | ||
5096 | idle = 1; | 5096 | idle = 1; |
5097 | ITERATE_RDEV(mddev,rdev,tmp) { | 5097 | ITERATE_RDEV(mddev,rdev,tmp) { |
@@ -5099,20 +5099,29 @@ static int is_mddev_idle(mddev_t *mddev) | |||
5099 | curr_events = disk_stat_read(disk, sectors[0]) + | 5099 | curr_events = disk_stat_read(disk, sectors[0]) + |
5100 | disk_stat_read(disk, sectors[1]) - | 5100 | disk_stat_read(disk, sectors[1]) - |
5101 | atomic_read(&disk->sync_io); | 5101 | atomic_read(&disk->sync_io); |
5102 | /* The difference between curr_events and last_events | 5102 | /* sync IO will cause sync_io to increase before the disk_stats |
5103 | * will be affected by any new non-sync IO (making | 5103 | * as sync_io is counted when a request starts, and |
5104 | * curr_events bigger) and any difference in the amount of | 5104 | * disk_stats is counted when it completes. |
5105 | * in-flight syncio (making current_events bigger or smaller) | 5105 | * So resync activity will cause curr_events to be smaller than |
5106 | * The amount in-flight is currently limited to | 5106 | * when there was no such activity. |
5107 | * 32*64K in raid1/10 and 256*PAGE_SIZE in raid5/6 | 5107 | * non-sync IO will cause disk_stat to increase without |
5108 | * which is at most 4096 sectors. | 5108 | * increasing sync_io so curr_events will (eventually) |
5109 | * These numbers are fairly fragile and should be made | 5109 | * be larger than it was before. Once it becomes |
5110 | * more robust, probably by enforcing the | 5110 | * substantially larger, the test below will cause |
5111 | * 'window size' that md_do_sync sort-of uses. | 5111 | * the array to appear non-idle, and resync will slow |
5112 | * down. | ||
5113 | * If there is a lot of outstanding resync activity when | ||
5114 | * we set last_event to curr_events, then all that activity | ||
5115 | * completing might cause the array to appear non-idle | ||
5116 | * and resync will be slowed down even though there might | ||
5117 | * not have been non-resync activity. This will only | ||
5118 | * happen once though. 'last_events' will soon reflect | ||
5119 | * the state where there is little or no outstanding | ||
5120 | * resync requests, and further resync activity will | ||
5121 | * always make curr_events less than last_events. | ||
5112 | * | 5122 | * |
5113 | * Note: the following is an unsigned comparison. | ||
5114 | */ | 5123 | */ |
5115 | if ((long)curr_events - (long)rdev->last_events > 4096) { | 5124 | if (curr_events - rdev->last_events > 4096) { |
5116 | rdev->last_events = curr_events; | 5125 | rdev->last_events = curr_events; |
5117 | idle = 0; | 5126 | idle = 0; |
5118 | } | 5127 | } |