Commit 26308eab authored by Jerome Marchand's avatar Jerome Marchand Committed by Jens Axboe

block: fix inconsistency in I/O stat accounting code

This forces in_flight to be zero when turning off or on the I/O stat
accounting and stops updating I/O stats in attempt_merge() when
accounting is turned off.
Signed-off-by: default avatarJerome Marchand <jmarchan@redhat.com>
Signed-off-by: default avatarJens Axboe <jens.axboe@oracle.com>
parent 6c7e8cee
...@@ -64,12 +64,11 @@ static struct workqueue_struct *kblockd_workqueue; ...@@ -64,12 +64,11 @@ static struct workqueue_struct *kblockd_workqueue;
static void drive_stat_acct(struct request *rq, int new_io) static void drive_stat_acct(struct request *rq, int new_io)
{ {
struct gendisk *disk = rq->rq_disk;
struct hd_struct *part; struct hd_struct *part;
int rw = rq_data_dir(rq); int rw = rq_data_dir(rq);
int cpu; int cpu;
if (!blk_fs_request(rq) || !disk || !blk_do_io_stat(disk->queue)) if (!blk_fs_request(rq) || !blk_do_io_stat(rq))
return; return;
cpu = part_stat_lock(); cpu = part_stat_lock();
...@@ -1675,9 +1674,7 @@ EXPORT_SYMBOL(blkdev_dequeue_request); ...@@ -1675,9 +1674,7 @@ EXPORT_SYMBOL(blkdev_dequeue_request);
static void blk_account_io_completion(struct request *req, unsigned int bytes) static void blk_account_io_completion(struct request *req, unsigned int bytes)
{ {
struct gendisk *disk = req->rq_disk; if (!blk_do_io_stat(req))
if (!disk || !blk_do_io_stat(disk->queue))
return; return;
if (blk_fs_request(req)) { if (blk_fs_request(req)) {
...@@ -1694,9 +1691,7 @@ static void blk_account_io_completion(struct request *req, unsigned int bytes) ...@@ -1694,9 +1691,7 @@ static void blk_account_io_completion(struct request *req, unsigned int bytes)
static void blk_account_io_done(struct request *req) static void blk_account_io_done(struct request *req)
{ {
struct gendisk *disk = req->rq_disk; if (!blk_do_io_stat(req))
if (!disk || !blk_do_io_stat(disk->queue))
return; return;
/* /*
...@@ -1711,7 +1706,7 @@ static void blk_account_io_done(struct request *req) ...@@ -1711,7 +1706,7 @@ static void blk_account_io_done(struct request *req)
int cpu; int cpu;
cpu = part_stat_lock(); cpu = part_stat_lock();
part = disk_map_sector_rcu(disk, req->sector); part = disk_map_sector_rcu(req->rq_disk, req->sector);
part_stat_inc(cpu, part, ios[rw]); part_stat_inc(cpu, part, ios[rw]);
part_stat_add(cpu, part, ticks[rw], duration); part_stat_add(cpu, part, ticks[rw], duration);
......
...@@ -338,6 +338,22 @@ static int ll_merge_requests_fn(struct request_queue *q, struct request *req, ...@@ -338,6 +338,22 @@ static int ll_merge_requests_fn(struct request_queue *q, struct request *req,
return 1; return 1;
} }
static void blk_account_io_merge(struct request *req)
{
if (blk_do_io_stat(req)) {
struct hd_struct *part;
int cpu;
cpu = part_stat_lock();
part = disk_map_sector_rcu(req->rq_disk, req->sector);
part_round_stats(cpu, part);
part_dec_in_flight(part);
part_stat_unlock();
}
}
/* /*
* Has to be called with the request spinlock acquired * Has to be called with the request spinlock acquired
*/ */
...@@ -386,18 +402,7 @@ static int attempt_merge(struct request_queue *q, struct request *req, ...@@ -386,18 +402,7 @@ static int attempt_merge(struct request_queue *q, struct request *req,
elv_merge_requests(q, req, next); elv_merge_requests(q, req, next);
if (req->rq_disk) { blk_account_io_merge(req);
struct hd_struct *part;
int cpu;
cpu = part_stat_lock();
part = disk_map_sector_rcu(req->rq_disk, req->sector);
part_round_stats(cpu, part);
part_dec_in_flight(part);
part_stat_unlock();
}
req->ioprio = ioprio_best(req->ioprio, next->ioprio); req->ioprio = ioprio_best(req->ioprio, next->ioprio);
if (blk_rq_cpu_valid(next)) if (blk_rq_cpu_valid(next))
......
...@@ -209,10 +209,14 @@ static ssize_t queue_iostats_store(struct request_queue *q, const char *page, ...@@ -209,10 +209,14 @@ static ssize_t queue_iostats_store(struct request_queue *q, const char *page,
ssize_t ret = queue_var_store(&stats, page, count); ssize_t ret = queue_var_store(&stats, page, count);
spin_lock_irq(q->queue_lock); spin_lock_irq(q->queue_lock);
elv_quisce_start(q);
if (stats) if (stats)
queue_flag_set(QUEUE_FLAG_IO_STAT, q); queue_flag_set(QUEUE_FLAG_IO_STAT, q);
else else
queue_flag_clear(QUEUE_FLAG_IO_STAT, q); queue_flag_clear(QUEUE_FLAG_IO_STAT, q);
elv_quisce_end(q);
spin_unlock_irq(q->queue_lock); spin_unlock_irq(q->queue_lock);
return ret; return ret;
......
...@@ -112,12 +112,14 @@ static inline int blk_cpu_to_group(int cpu) ...@@ -112,12 +112,14 @@ static inline int blk_cpu_to_group(int cpu)
#endif #endif
} }
static inline int blk_do_io_stat(struct request_queue *q) static inline int blk_do_io_stat(struct request *rq)
{ {
if (q) struct gendisk *disk = rq->rq_disk;
return blk_queue_io_stat(q);
return 0; if (!disk || !disk->queue)
return 0;
return blk_queue_io_stat(disk->queue) && (rq->cmd_flags & REQ_ELVPRIV);
} }
#endif #endif
...@@ -573,7 +573,7 @@ void elv_requeue_request(struct request_queue *q, struct request *rq) ...@@ -573,7 +573,7 @@ void elv_requeue_request(struct request_queue *q, struct request *rq)
elv_insert(q, rq, ELEVATOR_INSERT_REQUEUE); elv_insert(q, rq, ELEVATOR_INSERT_REQUEUE);
} }
static void elv_drain_elevator(struct request_queue *q) void elv_drain_elevator(struct request_queue *q)
{ {
static int printed; static int printed;
while (q->elevator->ops->elevator_dispatch_fn(q, 1)) while (q->elevator->ops->elevator_dispatch_fn(q, 1))
......
...@@ -116,6 +116,7 @@ extern void elv_abort_queue(struct request_queue *); ...@@ -116,6 +116,7 @@ extern void elv_abort_queue(struct request_queue *);
extern void elv_completed_request(struct request_queue *, struct request *); extern void elv_completed_request(struct request_queue *, struct request *);
extern int elv_set_request(struct request_queue *, struct request *, gfp_t); extern int elv_set_request(struct request_queue *, struct request *, gfp_t);
extern void elv_put_request(struct request_queue *, struct request *); extern void elv_put_request(struct request_queue *, struct request *);
extern void elv_drain_elevator(struct request_queue *);
/* /*
* io scheduler registration * io scheduler registration
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment