Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+4 −9
Original line number Diff line number Diff line
@@ -64,12 +64,11 @@ static struct workqueue_struct *kblockd_workqueue;

static void drive_stat_acct(struct request *rq, int new_io)
{
	struct gendisk *disk = rq->rq_disk;
	struct hd_struct *part;
	int rw = rq_data_dir(rq);
	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;

	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)
{
	struct gendisk *disk = req->rq_disk;

	if (!disk || !blk_do_io_stat(disk->queue))
	if (!blk_do_io_stat(req))
		return;

	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)
{
	struct gendisk *disk = req->rq_disk;

	if (!disk || !blk_do_io_stat(disk->queue))
	if (!blk_do_io_stat(req))
		return;

	/*
@@ -1711,7 +1706,7 @@ static void blk_account_io_done(struct request *req)
		int cpu;

		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_add(cpu, part, ticks[rw], duration);
+17 −12
Original line number Diff line number Diff line
@@ -338,6 +338,22 @@ static int ll_merge_requests_fn(struct request_queue *q, struct request *req,
	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
 */
@@ -386,18 +402,7 @@ static int attempt_merge(struct request_queue *q, struct request *req,

	elv_merge_requests(q, req, next);

	if (req->rq_disk) {
		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();
	}
	blk_account_io_merge(req);

	req->ioprio = ioprio_best(req->ioprio, next->ioprio);
	if (blk_rq_cpu_valid(next))
+4 −0
Original line number Diff line number Diff line
@@ -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);

	spin_lock_irq(q->queue_lock);
	elv_quisce_start(q);

	if (stats)
		queue_flag_set(QUEUE_FLAG_IO_STAT, q);
	else
		queue_flag_clear(QUEUE_FLAG_IO_STAT, q);

	elv_quisce_end(q);
	spin_unlock_irq(q->queue_lock);

	return ret;
+6 −4
Original line number Diff line number Diff line
@@ -112,12 +112,14 @@ static inline int blk_cpu_to_group(int cpu)
#endif
}

static inline int blk_do_io_stat(struct request_queue *q)
static inline int blk_do_io_stat(struct request *rq)
{
	if (q)
		return blk_queue_io_stat(q);
	struct gendisk *disk = rq->rq_disk;

	if (!disk || !disk->queue)
		return 0;

	return blk_queue_io_stat(disk->queue) && (rq->cmd_flags & REQ_ELVPRIV);
}

#endif
+1 −1
Original line number Diff line number Diff line
@@ -573,7 +573,7 @@ void elv_requeue_request(struct request_queue *q, struct request *rq)
	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;
	while (q->elevator->ops->elevator_dispatch_fn(q, 1))
Loading