Skip to content

Commit eea1bf3

Browse files
committed
md: Fix is_mddev_idle test (again).
There are two problems with is_mddev_idle. 1/ sync_io is 'atomic_t' and hence 'int'. curr_events and all the rest are 'long'. So if sync_io were to wrap on a 64bit host, the value of curr_events would go very negative suddenly, and take a very long time to return to positive. So do all calculations as 'int'. That gives us plenty of precision for what we need. 2/ To initialise rdev->last_events we simply call is_mddev_idle, on the assumption that it will make sure that last_events is in a suitable range. It used to do this, but now it does not. So now we need to be more explicit about initialisation. Signed-off-by: NeilBrown <neilb@suse.de>
1 parent 99adcd9 commit eea1bf3

File tree

2 files changed

+9
-9
lines changed

2 files changed

+9
-9
lines changed

drivers/md/md.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5716,19 +5716,19 @@ int unregister_md_personality(struct mdk_personality *p)
57165716
return 0;
57175717
}
57185718

5719-
static int is_mddev_idle(mddev_t *mddev)
5719+
static int is_mddev_idle(mddev_t *mddev, int init)
57205720
{
57215721
mdk_rdev_t * rdev;
57225722
int idle;
5723-
long curr_events;
5723+
int curr_events;
57245724

57255725
idle = 1;
57265726
rcu_read_lock();
57275727
rdev_for_each_rcu(rdev, mddev) {
57285728
struct gendisk *disk = rdev->bdev->bd_contains->bd_disk;
5729-
curr_events = part_stat_read(&disk->part0, sectors[0]) +
5730-
part_stat_read(&disk->part0, sectors[1]) -
5731-
atomic_read(&disk->sync_io);
5729+
curr_events = (int)part_stat_read(&disk->part0, sectors[0]) +
5730+
(int)part_stat_read(&disk->part0, sectors[1]) -
5731+
atomic_read(&disk->sync_io);
57325732
/* sync IO will cause sync_io to increase before the disk_stats
57335733
* as sync_io is counted when a request starts, and
57345734
* disk_stats is counted when it completes.
@@ -5751,7 +5751,7 @@ static int is_mddev_idle(mddev_t *mddev)
57515751
* always make curr_events less than last_events.
57525752
*
57535753
*/
5754-
if (curr_events - rdev->last_events > 4096) {
5754+
if (init || curr_events - rdev->last_events > 64) {
57555755
rdev->last_events = curr_events;
57565756
idle = 0;
57575757
}
@@ -5994,7 +5994,7 @@ void md_do_sync(mddev_t *mddev)
59945994
"(but not more than %d KB/sec) for %s.\n",
59955995
speed_max(mddev), desc);
59965996

5997-
is_mddev_idle(mddev); /* this also initializes IO event counters */
5997+
is_mddev_idle(mddev, 1); /* this initializes IO event counters */
59985998

59995999
io_sectors = 0;
60006000
for (m = 0; m < SYNC_MARKS; m++) {
@@ -6096,7 +6096,7 @@ void md_do_sync(mddev_t *mddev)
60966096

60976097
if (currspeed > speed_min(mddev)) {
60986098
if ((currspeed > speed_max(mddev)) ||
6099-
!is_mddev_idle(mddev)) {
6099+
!is_mddev_idle(mddev, 0)) {
61006100
msleep(500);
61016101
goto repeat;
61026102
}

include/linux/raid/md_k.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ struct mdk_rdev_s
5151

5252
sector_t size; /* Device size (in blocks) */
5353
mddev_t *mddev; /* RAID array if running */
54-
long last_events; /* IO event timestamp */
54+
int last_events; /* IO event timestamp */
5555

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

0 commit comments

Comments
 (0)