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: Jerome Marchand <jmarchan@redhat.com> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
This commit is contained in:
committed by
Jens Axboe
parent
6c7e8cee6a
commit
26308eab69
@@ -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);
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
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;
|
||||||
|
10
block/blk.h
10
block/blk.h
@@ -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)
|
|||||||
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 *);
|
|||||||
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
|
||||||
|
Reference in New Issue
Block a user