void elv_requeue_request(request_queue_t *q, struct request *rq)
{
+ /*
+ * it already went through dequeue, we need to decrement the
+ * in_flight count again
+ */
+ if (blk_account_rq(rq))
+ q->in_flight--;
+
/*
* if iosched has an explicit requeue hook, then use that. otherwise
* just put the request at the front of the queue
{
elevator_t *e = &q->elevator;
+ /*
+ * the time frame between a request being removed from the lists
+ * and to it is freed is accounted as io that is in progress at
+ * the driver side. note that we only account requests that the
+ * driver has seen (REQ_STARTED set), to avoid false accounting
+ * for request-request merges
+ */
+ if (blk_account_rq(rq))
+ q->in_flight++;
+
/*
* the main clearing point for q->last_merge is on retrieval of
* request by driver (it calls elv_next_request()), but it _can_
{
elevator_t *e = &q->elevator;
+ /*
+ * request is released from the driver, io must be done
+ */
+ if (blk_account_rq(rq))
+ q->in_flight--;
+
if (e->elevator_completed_req_fn)
e->elevator_completed_req_fn(q, rq);
}
__blk_put_request(q, freereq);
if (blk_queue_plugged(q)) {
- int nr_queued = q->rq.count[READ] + q->rq.count[WRITE];
+ int nrq = q->rq.count[READ] + q->rq.count[WRITE] - q->in_flight;
- if (nr_queued == q->unplug_thresh || bio_sync(bio))
+ if (nrq == q->unplug_thresh || bio_sync(bio))
__generic_unplug_device(q);
}
spin_unlock_irq(q->queue_lock);
atomic_t refcnt;
+ unsigned int in_flight;
+
/*
* sg stuff
*/
#define blk_fs_request(rq) ((rq)->flags & REQ_CMD)
#define blk_pc_request(rq) ((rq)->flags & REQ_BLOCK_PC)
#define blk_noretry_request(rq) ((rq)->flags & REQ_FAILFAST)
+#define blk_rq_started(rq) ((rq)->flags & REQ_STARTED)
+
+#define blk_account_rq(rq) (blk_rq_started(rq) && blk_fs_request(rq))
#define blk_pm_suspend_request(rq) ((rq)->flags & REQ_PM_SUSPEND)
#define blk_pm_resume_request(rq) ((rq)->flags & REQ_PM_RESUME)