Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

NeilBrown and committed by
Linus Torvalds
713f6ab1 df968c4e

+23 -14
+22 -13
drivers/md/md.c
··· 5091 5091 mdk_rdev_t * rdev; 5092 5092 struct list_head *tmp; 5093 5093 int idle; 5094 - unsigned long curr_events; 5094 + long curr_events; 5095 5095 5096 5096 idle = 1; 5097 5097 ITERATE_RDEV(mddev,rdev,tmp) { ··· 5099 5099 curr_events = disk_stat_read(disk, sectors[0]) + 5100 5100 disk_stat_read(disk, sectors[1]) - 5101 5101 atomic_read(&disk->sync_io); 5102 - /* The difference between curr_events and last_events 5103 - * will be affected by any new non-sync IO (making 5104 - * curr_events bigger) and any difference in the amount of 5105 - * in-flight syncio (making current_events bigger or smaller) 5106 - * The amount in-flight is currently limited to 5107 - * 32*64K in raid1/10 and 256*PAGE_SIZE in raid5/6 5108 - * which is at most 4096 sectors. 5109 - * These numbers are fairly fragile and should be made 5110 - * more robust, probably by enforcing the 5111 - * 'window size' that md_do_sync sort-of uses. 5102 + /* sync IO will cause sync_io to increase before the disk_stats 5103 + * as sync_io is counted when a request starts, and 5104 + * disk_stats is counted when it completes. 5105 + * So resync activity will cause curr_events to be smaller than 5106 + * when there was no such activity. 5107 + * non-sync IO will cause disk_stat to increase without 5108 + * increasing sync_io so curr_events will (eventually) 5109 + * be larger than it was before. Once it becomes 5110 + * substantially larger, the test below will cause 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 5125 rdev->last_events = curr_events; 5117 5126 idle = 0; 5118 5127 }
+1 -1
include/linux/raid/md_k.h
··· 51 51 52 52 sector_t size; /* Device size (in blocks) */ 53 53 mddev_t *mddev; /* RAID array if running */ 54 - unsigned long last_events; /* IO event timestamp */ 54 + long last_events; /* IO event timestamp */ 55 55 56 56 struct block_device *bdev; /* block device handle */ 57 57