Change a argument of disk_map_sector_rcu() to hd_part->start_sect from req->__sector
PATCH 1/2 Change a argument of disk_map_sector_rcu() to hd_part->start_sect from req->__sector
From: Yasuaki Ishimatsu <[email protected]>
PROBLEM:
The previous patch does not fix the problem completely, since the problem occurs on following case.
When sdX region is between sdX1 partition and sdX2 partition, a sdX region's I/O is merged sdX1 partition's I/O or sdX2 partition's I/O.
1. sdX region is between sdX1 partition and sdX2 partition
sdX1 partition sdX region sdX1 partition
|----------------|------------|----------------|
2. issue a sdX region's I/O and increment a in_flight of sdX
sdX1 partition sdX region sdX1 partition
|----------------|------------|----------------|
<- I/O ->3. issue a sdX1 partition's I/O
sdX1 partition sdX region sdX1 partition
|----------------|------------|----------------|
<- I/O -> <- I/O ->4. merge a sdX1 partition's I/O and a sdX region's I/O, since the previous patch cannot care this case.
sdX1 partition sdX region sdX1 partition
|----------------|------------|----------------|
<- I/O ->5. finish a I/O and decrement a in_flight of sdX1 even though it was not incremented
HOW TO FIX:
The patch fixes avobe case by changing a argument of disk_map_sector_rcu().
The problem also is caused by merging different partition's I/Os. But, it is not easy to fix, when I/O is sdX region. So the patch allows step 4, when I/O is only sdX region. But, it does not change a result of disk_map_sector_rcu() by using partition's start sector ot original I/O , even if the I/O is merged.
--- block/blk-core.c | 10 ++++++---- block/blk-merge.c | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-)
block/blk-core.c +6 -4
@@ -64,11 +64,13 @@ static void drive_stat_acct(struct requereturn ; cpu =part_stat_lock (); - part =disk_map_sector_rcu (rq->rq_disk,blk_rq_pos (rq)); -if (!new_io) +if (!new_io) { + part =disk_map_sector_rcu (rq->rq_disk,blk_rq_part_sector (rq));part_stat_inc (cpu, part, merges[rw]); + }else { + part =disk_map_sector_rcu (rq->rq_disk,blk_rq_pos (rq));part_round_stats (cpu, part);part_inc_in_flight (part, rw); rq->__part_start_sect = part->start_sect;
@@ -1778,7 +1780,7 @@ static void blk_account_io_completion(stint cpu; cpu =part_stat_lock (); - part =disk_map_sector_rcu (req->rq_disk,blk_rq_pos (req)); + part =disk_map_sector_rcu (req->rq_disk,blk_rq_part_sector (req));part_stat_add (cpu, part, sectors[rw], bytes >>9 );part_stat_unlock (); }
@@ -1798,7 +1800,7 @@ static void blk_account_io_done(struct rint cpu; cpu =part_stat_lock (); - part =disk_map_sector_rcu (req->rq_disk,blk_rq_pos (req)); + part =disk_map_sector_rcu (req->rq_disk,blk_rq_part_sector (req));part_stat_inc (cpu, part, ios[rw]);part_stat_add (cpu, part, ticks[rw], duration);
block/blk-merge.c +1 -1
@@ -356,7 +356,7 @@ static void blk_account_io_merge(structint cpu; cpu =part_stat_lock (); - part =disk_map_sector_rcu (req->rq_disk,blk_rq_pos (req)); + part =disk_map_sector_rcu (req->rq_disk,blk_rq_part_sector (req));part_round_stats (cpu, part);part_dec_in_flight (part,rq_data_dir (req));