}
EXPORT_SYMBOL(elv_try_last_merge);
-struct elevator_type *elevator_find(const char *name)
+static struct elevator_type *elevator_find(const char *name)
{
struct elevator_type *e = NULL;
struct list_head *entry;
kfree(e);
}
-int elevator_global_init(void)
-{
- return 0;
-}
-
int elv_merge(request_queue_t *q, struct request **req, struct bio *bio)
{
elevator_t *e = q->elevator;
e->ops->elevator_merge_req_fn(q, rq, next);
}
-void elv_requeue_request(request_queue_t *q, struct request *rq)
+/*
+ * For careful internal use by the block layer. Essentially the same as
+ * a requeue in that it tells the io scheduler that this request is not
+ * active in the driver or hardware anymore, but we don't want the request
+ * added back to the scheduler. Function is not exported.
+ */
+void elv_deactivate_request(request_queue_t *q, struct request *rq)
{
+ elevator_t *e = q->elevator;
+
/*
* it already went through dequeue, we need to decrement the
* in_flight count again
if (blk_account_rq(rq))
q->in_flight--;
+ rq->flags &= ~REQ_STARTED;
+
+ if (e->ops->elevator_deactivate_req_fn)
+ e->ops->elevator_deactivate_req_fn(q, rq);
+}
+
+void elv_requeue_request(request_queue_t *q, struct request *rq)
+{
+ elv_deactivate_request(q, rq);
+
+ /*
+ * if this is the flush, requeue the original instead and drop the flush
+ */
+ if (rq->flags & REQ_BAR_FLUSH) {
+ clear_bit(QUEUE_FLAG_FLUSH, &q->queue_flags);
+ rq = rq->end_io_data;
+ }
+
/*
* if iosched has an explicit requeue hook, then use that. otherwise
* just put the request at the front of the queue
int nrq = q->rq.count[READ] + q->rq.count[WRITE]
- q->in_flight;
- if (nrq == q->unplug_thresh)
+ if (nrq >= q->unplug_thresh)
__generic_unplug_device(q);
}
} else
static inline struct request *__elv_next_request(request_queue_t *q)
{
- return q->elevator->ops->elevator_next_req_fn(q);
+ struct request *rq = q->elevator->ops->elevator_next_req_fn(q);
+
+ /*
+ * if this is a barrier write and the device has to issue a
+ * flush sequence to support it, check how far we are
+ */
+ if (rq && blk_fs_request(rq) && blk_barrier_rq(rq)) {
+ BUG_ON(q->ordered == QUEUE_ORDERED_NONE);
+
+ if (q->ordered == QUEUE_ORDERED_FLUSH &&
+ !blk_barrier_preflush(rq))
+ rq = blk_start_pre_flush(q, rq);
+ }
+
+ return rq;
}
struct request *elv_next_request(request_queue_t *q)
return len;
}
-module_init(elevator_global_init);
-
EXPORT_SYMBOL(elv_add_request);
EXPORT_SYMBOL(__elv_add_request);
EXPORT_SYMBOL(elv_requeue_request);