|
@@ -64,13 +64,27 @@ static void drive_stat_acct(struct request *rq, int new_io)
|
|
|
return;
|
|
|
|
|
|
cpu = part_stat_lock();
|
|
|
- part = disk_map_sector_rcu(rq->rq_disk, blk_rq_pos(rq));
|
|
|
|
|
|
- if (!new_io)
|
|
|
+ if (!new_io) {
|
|
|
+ part = rq->part;
|
|
|
part_stat_inc(cpu, part, merges[rw]);
|
|
|
- else {
|
|
|
+ } else {
|
|
|
+ part = disk_map_sector_rcu(rq->rq_disk, blk_rq_pos(rq));
|
|
|
+ if (!kref_test_and_get(&part->ref)) {
|
|
|
+ /*
|
|
|
+ * The partition is already being removed,
|
|
|
+ * the request will be accounted on the disk only
|
|
|
+ *
|
|
|
+ * We take a reference on disk->part0 although that
|
|
|
+ * partition will never be deleted, so we can treat
|
|
|
+ * it as any other partition.
|
|
|
+ */
|
|
|
+ part = &rq->rq_disk->part0;
|
|
|
+ kref_get(&part->ref);
|
|
|
+ }
|
|
|
part_round_stats(cpu, part);
|
|
|
part_inc_in_flight(part, rw);
|
|
|
+ rq->part = part;
|
|
|
}
|
|
|
|
|
|
part_stat_unlock();
|
|
@@ -128,6 +142,7 @@ void blk_rq_init(struct request_queue *q, struct request *rq)
|
|
|
rq->ref_count = 1;
|
|
|
rq->start_time = jiffies;
|
|
|
set_start_time_ns(rq);
|
|
|
+ rq->part = NULL;
|
|
|
}
|
|
|
EXPORT_SYMBOL(blk_rq_init);
|
|
|
|
|
@@ -1776,7 +1791,7 @@ static void blk_account_io_completion(struct request *req, unsigned int bytes)
|
|
|
int cpu;
|
|
|
|
|
|
cpu = part_stat_lock();
|
|
|
- part = disk_map_sector_rcu(req->rq_disk, blk_rq_pos(req));
|
|
|
+ part = req->part;
|
|
|
part_stat_add(cpu, part, sectors[rw], bytes >> 9);
|
|
|
part_stat_unlock();
|
|
|
}
|
|
@@ -1796,13 +1811,14 @@ static void blk_account_io_done(struct request *req)
|
|
|
int cpu;
|
|
|
|
|
|
cpu = part_stat_lock();
|
|
|
- part = disk_map_sector_rcu(req->rq_disk, blk_rq_pos(req));
|
|
|
+ part = req->part;
|
|
|
|
|
|
part_stat_inc(cpu, part, ios[rw]);
|
|
|
part_stat_add(cpu, part, ticks[rw], duration);
|
|
|
part_round_stats(cpu, part);
|
|
|
part_dec_in_flight(part, rw);
|
|
|
|
|
|
+ kref_put(&part->ref, __delete_partition);
|
|
|
part_stat_unlock();
|
|
|
}
|
|
|
}
|