Skip to content

Commit

Permalink
Merge branch 'md-fixes' of https://github.com/liu-song-6/linux into f…
Browse files Browse the repository at this point in the history
…or-linus

Pull MD fix from Song.

* 'md-fixes' of https://github.com/liu-song-6/linux:
  md: fix for divide error in status_resync
  • Loading branch information
axboe committed Jun 18, 2019
2 parents 4569180 + 9642fa7 commit 440078d
Showing 1 changed file with 22 additions and 14 deletions.
36 changes: 22 additions & 14 deletions drivers/md/md.c
Original file line number Diff line number Diff line change
Expand Up @@ -7607,9 +7607,9 @@ static void status_unused(struct seq_file *seq)
static int status_resync(struct seq_file *seq, struct mddev *mddev)
{
sector_t max_sectors, resync, res;
unsigned long dt, db;
sector_t rt;
int scale;
unsigned long dt, db = 0;
sector_t rt, curr_mark_cnt, resync_mark_cnt;
int scale, recovery_active;
unsigned int per_milli;

if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) ||
Expand Down Expand Up @@ -7698,22 +7698,30 @@ static int status_resync(struct seq_file *seq, struct mddev *mddev)
* db: blocks written from mark until now
* rt: remaining time
*
* rt is a sector_t, so could be 32bit or 64bit.
* So we divide before multiply in case it is 32bit and close
* to the limit.
* We scale the divisor (db) by 32 to avoid losing precision
* near the end of resync when the number of remaining sectors
* is close to 'db'.
* We then divide rt by 32 after multiplying by db to compensate.
* The '+1' avoids division by zero if db is very small.
* rt is a sector_t, which is always 64bit now. We are keeping
* the original algorithm, but it is not really necessary.
*
* Original algorithm:
* So we divide before multiply in case it is 32bit and close
* to the limit.
* We scale the divisor (db) by 32 to avoid losing precision
* near the end of resync when the number of remaining sectors
* is close to 'db'.
* We then divide rt by 32 after multiplying by db to compensate.
* The '+1' avoids division by zero if db is very small.
*/
dt = ((jiffies - mddev->resync_mark) / HZ);
if (!dt) dt++;
db = (mddev->curr_mark_cnt - atomic_read(&mddev->recovery_active))
- mddev->resync_mark_cnt;

curr_mark_cnt = mddev->curr_mark_cnt;
recovery_active = atomic_read(&mddev->recovery_active);
resync_mark_cnt = mddev->resync_mark_cnt;

if (curr_mark_cnt >= (recovery_active + resync_mark_cnt))
db = curr_mark_cnt - (recovery_active + resync_mark_cnt);

rt = max_sectors - resync; /* number of remaining sectors */
sector_div(rt, db/32+1);
rt = div64_u64(rt, db/32+1);
rt *= dt;
rt >>= 5;

Expand Down

0 comments on commit 440078d

Please sign in to comment.