Skip to content

Commit

Permalink
md: improve the is_mddev_idle test fix
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
neilbrown authored and Linus Torvalds committed Jul 17, 2007
1 parent df968c4 commit 713f6ab
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 14 deletions.
35 changes: 22 additions & 13 deletions drivers/md/md.c
Original file line number Diff line number Diff line change
Expand Up @@ -5091,28 +5091,37 @@ static int is_mddev_idle(mddev_t *mddev)
mdk_rdev_t * rdev;
struct list_head *tmp;
int idle;
unsigned long curr_events;
long curr_events;

idle = 1;
ITERATE_RDEV(mddev,rdev,tmp) {
struct gendisk *disk = rdev->bdev->bd_contains->bd_disk;
curr_events = disk_stat_read(disk, sectors[0]) +
disk_stat_read(disk, sectors[1]) -
atomic_read(&disk->sync_io);
/* The difference between curr_events and last_events
* will be affected by any new non-sync IO (making
* curr_events bigger) and any difference in the amount of
* in-flight syncio (making current_events bigger or smaller)
* The amount in-flight is currently limited to
* 32*64K in raid1/10 and 256*PAGE_SIZE in raid5/6
* which is at most 4096 sectors.
* These numbers are fairly fragile and should be made
* more robust, probably by enforcing the
* 'window size' that md_do_sync sort-of uses.
/* sync IO will cause sync_io to increase before the disk_stats
* as sync_io is counted when a request starts, and
* disk_stats is counted when it completes.
* So resync activity will cause curr_events to be smaller than
* when there was no such activity.
* non-sync IO will cause disk_stat to increase without
* increasing sync_io so curr_events will (eventually)
* be larger than it was before. Once it becomes
* substantially larger, the test below will cause
* the array to appear non-idle, and resync will slow
* down.
* If there is a lot of outstanding resync activity when
* we set last_event to curr_events, then all that activity
* completing might cause the array to appear non-idle
* and resync will be slowed down even though there might
* not have been non-resync activity. This will only
* happen once though. 'last_events' will soon reflect
* the state where there is little or no outstanding
* resync requests, and further resync activity will
* always make curr_events less than last_events.
*
* Note: the following is an unsigned comparison.
*/
if ((long)curr_events - (long)rdev->last_events > 4096) {
if (curr_events - rdev->last_events > 4096) {
rdev->last_events = curr_events;
idle = 0;
}
Expand Down
2 changes: 1 addition & 1 deletion include/linux/raid/md_k.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ struct mdk_rdev_s

sector_t size; /* Device size (in blocks) */
mddev_t *mddev; /* RAID array if running */
unsigned long last_events; /* IO event timestamp */
long last_events; /* IO event timestamp */

struct block_device *bdev; /* block device handle */

Expand Down

0 comments on commit 713f6ab

Please sign in to comment.