Commit 8922e16c authored by Tejun Heo's avatar Tejun Heo Committed by Jens Axboe

[PATCH] 01/05 Implement generic dispatch queue

Implements generic dispatch queue which can replace all
dispatch queues implemented by each iosched.  This reduces
code duplication, eases enforcing semantics over dispatch
queue, and simplifies specific ioscheds.
Signed-off-by: default avatarTejun Heo <htejun@gmail.com>
Signed-off-by: default avatarJens Axboe <axboe@suse.de>
parent 2824bc93
This diff is collapsed.
...@@ -353,6 +353,8 @@ static void blk_pre_flush_end_io(struct request *flush_rq) ...@@ -353,6 +353,8 @@ static void blk_pre_flush_end_io(struct request *flush_rq)
struct request *rq = flush_rq->end_io_data; struct request *rq = flush_rq->end_io_data;
request_queue_t *q = rq->q; request_queue_t *q = rq->q;
elv_completed_request(q, flush_rq);
rq->flags |= REQ_BAR_PREFLUSH; rq->flags |= REQ_BAR_PREFLUSH;
if (!flush_rq->errors) if (!flush_rq->errors)
...@@ -369,6 +371,8 @@ static void blk_post_flush_end_io(struct request *flush_rq) ...@@ -369,6 +371,8 @@ static void blk_post_flush_end_io(struct request *flush_rq)
struct request *rq = flush_rq->end_io_data; struct request *rq = flush_rq->end_io_data;
request_queue_t *q = rq->q; request_queue_t *q = rq->q;
elv_completed_request(q, flush_rq);
rq->flags |= REQ_BAR_POSTFLUSH; rq->flags |= REQ_BAR_POSTFLUSH;
q->end_flush_fn(q, flush_rq); q->end_flush_fn(q, flush_rq);
...@@ -408,8 +412,6 @@ struct request *blk_start_pre_flush(request_queue_t *q, struct request *rq) ...@@ -408,8 +412,6 @@ struct request *blk_start_pre_flush(request_queue_t *q, struct request *rq)
if (!list_empty(&rq->queuelist)) if (!list_empty(&rq->queuelist))
blkdev_dequeue_request(rq); blkdev_dequeue_request(rq);
elv_deactivate_request(q, rq);
flush_rq->end_io_data = rq; flush_rq->end_io_data = rq;
flush_rq->end_io = blk_pre_flush_end_io; flush_rq->end_io = blk_pre_flush_end_io;
...@@ -1040,6 +1042,7 @@ EXPORT_SYMBOL(blk_queue_invalidate_tags); ...@@ -1040,6 +1042,7 @@ EXPORT_SYMBOL(blk_queue_invalidate_tags);
static char *rq_flags[] = { static char *rq_flags[] = {
"REQ_RW", "REQ_RW",
"REQ_FAILFAST", "REQ_FAILFAST",
"REQ_SORTED",
"REQ_SOFTBARRIER", "REQ_SOFTBARRIER",
"REQ_HARDBARRIER", "REQ_HARDBARRIER",
"REQ_CMD", "REQ_CMD",
...@@ -2456,6 +2459,8 @@ static void __blk_put_request(request_queue_t *q, struct request *req) ...@@ -2456,6 +2459,8 @@ static void __blk_put_request(request_queue_t *q, struct request *req)
if (unlikely(--req->ref_count)) if (unlikely(--req->ref_count))
return; return;
elv_completed_request(q, req);
req->rq_status = RQ_INACTIVE; req->rq_status = RQ_INACTIVE;
req->rl = NULL; req->rl = NULL;
...@@ -2466,8 +2471,6 @@ static void __blk_put_request(request_queue_t *q, struct request *req) ...@@ -2466,8 +2471,6 @@ static void __blk_put_request(request_queue_t *q, struct request *req)
if (rl) { if (rl) {
int rw = rq_data_dir(req); int rw = rq_data_dir(req);
elv_completed_request(q, req);
BUG_ON(!list_empty(&req->queuelist)); BUG_ON(!list_empty(&req->queuelist));
blk_free_request(q, req); blk_free_request(q, req);
...@@ -2477,14 +2480,14 @@ static void __blk_put_request(request_queue_t *q, struct request *req) ...@@ -2477,14 +2480,14 @@ static void __blk_put_request(request_queue_t *q, struct request *req)
void blk_put_request(struct request *req) void blk_put_request(struct request *req)
{ {
unsigned long flags;
request_queue_t *q = req->q;
/* /*
* if req->rl isn't set, this request didnt originate from the * Gee, IDE calls in w/ NULL q. Fix IDE and remove the
* block layer, so it's safe to just disregard it * following if (q) test.
*/ */
if (req->rl) { if (q) {
unsigned long flags;
request_queue_t *q = req->q;
spin_lock_irqsave(q->queue_lock, flags); spin_lock_irqsave(q->queue_lock, flags);
__blk_put_request(q, req); __blk_put_request(q, req);
spin_unlock_irqrestore(q->queue_lock, flags); spin_unlock_irqrestore(q->queue_lock, flags);
......
...@@ -203,6 +203,7 @@ struct request { ...@@ -203,6 +203,7 @@ struct request {
enum rq_flag_bits { enum rq_flag_bits {
__REQ_RW, /* not set, read. set, write */ __REQ_RW, /* not set, read. set, write */
__REQ_FAILFAST, /* no low level driver retries */ __REQ_FAILFAST, /* no low level driver retries */
__REQ_SORTED, /* elevator knows about this request */
__REQ_SOFTBARRIER, /* may not be passed by ioscheduler */ __REQ_SOFTBARRIER, /* may not be passed by ioscheduler */
__REQ_HARDBARRIER, /* may not be passed by drive either */ __REQ_HARDBARRIER, /* may not be passed by drive either */
__REQ_CMD, /* is a regular fs rw request */ __REQ_CMD, /* is a regular fs rw request */
...@@ -235,6 +236,7 @@ enum rq_flag_bits { ...@@ -235,6 +236,7 @@ enum rq_flag_bits {
#define REQ_RW (1 << __REQ_RW) #define REQ_RW (1 << __REQ_RW)
#define REQ_FAILFAST (1 << __REQ_FAILFAST) #define REQ_FAILFAST (1 << __REQ_FAILFAST)
#define REQ_SORTED (1 << __REQ_SORTED)
#define REQ_SOFTBARRIER (1 << __REQ_SOFTBARRIER) #define REQ_SOFTBARRIER (1 << __REQ_SOFTBARRIER)
#define REQ_HARDBARRIER (1 << __REQ_HARDBARRIER) #define REQ_HARDBARRIER (1 << __REQ_HARDBARRIER)
#define REQ_CMD (1 << __REQ_CMD) #define REQ_CMD (1 << __REQ_CMD)
...@@ -332,6 +334,13 @@ struct request_queue ...@@ -332,6 +334,13 @@ struct request_queue
prepare_flush_fn *prepare_flush_fn; prepare_flush_fn *prepare_flush_fn;
end_flush_fn *end_flush_fn; end_flush_fn *end_flush_fn;
/*
* Dispatch queue sorting
*/
sector_t last_sector;
struct request *boundary_rq;
unsigned int max_back_kb;
/* /*
* Auto-unplugging state * Auto-unplugging state
*/ */
...@@ -454,6 +463,7 @@ enum { ...@@ -454,6 +463,7 @@ enum {
#define blk_pm_request(rq) \ #define blk_pm_request(rq) \
((rq)->flags & (REQ_PM_SUSPEND | REQ_PM_RESUME)) ((rq)->flags & (REQ_PM_SUSPEND | REQ_PM_RESUME))
#define blk_sorted_rq(rq) ((rq)->flags & REQ_SORTED)
#define blk_barrier_rq(rq) ((rq)->flags & REQ_HARDBARRIER) #define blk_barrier_rq(rq) ((rq)->flags & REQ_HARDBARRIER)
#define blk_barrier_preflush(rq) ((rq)->flags & REQ_BAR_PREFLUSH) #define blk_barrier_preflush(rq) ((rq)->flags & REQ_BAR_PREFLUSH)
#define blk_barrier_postflush(rq) ((rq)->flags & REQ_BAR_POSTFLUSH) #define blk_barrier_postflush(rq) ((rq)->flags & REQ_BAR_POSTFLUSH)
...@@ -611,12 +621,7 @@ extern void end_request(struct request *req, int uptodate); ...@@ -611,12 +621,7 @@ extern void end_request(struct request *req, int uptodate);
static inline void blkdev_dequeue_request(struct request *req) static inline void blkdev_dequeue_request(struct request *req)
{ {
BUG_ON(list_empty(&req->queuelist)); elv_dequeue_request(req->q, req);
list_del_init(&req->queuelist);
if (req->rl)
elv_remove_request(req->q, req);
} }
/* /*
......
...@@ -8,18 +8,17 @@ typedef void (elevator_merge_req_fn) (request_queue_t *, struct request *, struc ...@@ -8,18 +8,17 @@ typedef void (elevator_merge_req_fn) (request_queue_t *, struct request *, struc
typedef void (elevator_merged_fn) (request_queue_t *, struct request *); typedef void (elevator_merged_fn) (request_queue_t *, struct request *);
typedef struct request *(elevator_next_req_fn) (request_queue_t *); typedef int (elevator_dispatch_fn) (request_queue_t *, int);
typedef void (elevator_add_req_fn) (request_queue_t *, struct request *, int); typedef void (elevator_add_req_fn) (request_queue_t *, struct request *);
typedef int (elevator_queue_empty_fn) (request_queue_t *); typedef int (elevator_queue_empty_fn) (request_queue_t *);
typedef void (elevator_remove_req_fn) (request_queue_t *, struct request *);
typedef void (elevator_requeue_req_fn) (request_queue_t *, struct request *);
typedef struct request *(elevator_request_list_fn) (request_queue_t *, struct request *); typedef struct request *(elevator_request_list_fn) (request_queue_t *, struct request *);
typedef void (elevator_completed_req_fn) (request_queue_t *, struct request *); typedef void (elevator_completed_req_fn) (request_queue_t *, struct request *);
typedef int (elevator_may_queue_fn) (request_queue_t *, int, struct bio *); typedef int (elevator_may_queue_fn) (request_queue_t *, int, struct bio *);
typedef int (elevator_set_req_fn) (request_queue_t *, struct request *, struct bio *, int); typedef int (elevator_set_req_fn) (request_queue_t *, struct request *, struct bio *, int);
typedef void (elevator_put_req_fn) (request_queue_t *, struct request *); typedef void (elevator_put_req_fn) (request_queue_t *, struct request *);
typedef void (elevator_activate_req_fn) (request_queue_t *, struct request *);
typedef void (elevator_deactivate_req_fn) (request_queue_t *, struct request *); typedef void (elevator_deactivate_req_fn) (request_queue_t *, struct request *);
typedef int (elevator_init_fn) (request_queue_t *, elevator_t *); typedef int (elevator_init_fn) (request_queue_t *, elevator_t *);
...@@ -31,10 +30,9 @@ struct elevator_ops ...@@ -31,10 +30,9 @@ struct elevator_ops
elevator_merged_fn *elevator_merged_fn; elevator_merged_fn *elevator_merged_fn;
elevator_merge_req_fn *elevator_merge_req_fn; elevator_merge_req_fn *elevator_merge_req_fn;
elevator_next_req_fn *elevator_next_req_fn; elevator_dispatch_fn *elevator_dispatch_fn;
elevator_add_req_fn *elevator_add_req_fn; elevator_add_req_fn *elevator_add_req_fn;
elevator_remove_req_fn *elevator_remove_req_fn; elevator_activate_req_fn *elevator_activate_req_fn;
elevator_requeue_req_fn *elevator_requeue_req_fn;
elevator_deactivate_req_fn *elevator_deactivate_req_fn; elevator_deactivate_req_fn *elevator_deactivate_req_fn;
elevator_queue_empty_fn *elevator_queue_empty_fn; elevator_queue_empty_fn *elevator_queue_empty_fn;
...@@ -81,15 +79,15 @@ struct elevator_queue ...@@ -81,15 +79,15 @@ struct elevator_queue
/* /*
* block elevator interface * block elevator interface
*/ */
extern void elv_dispatch_insert(request_queue_t *, struct request *, int);
extern void elv_add_request(request_queue_t *, struct request *, int, int); extern void elv_add_request(request_queue_t *, struct request *, int, int);
extern void __elv_add_request(request_queue_t *, struct request *, int, int); extern void __elv_add_request(request_queue_t *, struct request *, int, int);
extern int elv_merge(request_queue_t *, struct request **, struct bio *); extern int elv_merge(request_queue_t *, struct request **, struct bio *);
extern void elv_merge_requests(request_queue_t *, struct request *, extern void elv_merge_requests(request_queue_t *, struct request *,
struct request *); struct request *);
extern void elv_merged_request(request_queue_t *, struct request *); extern void elv_merged_request(request_queue_t *, struct request *);
extern void elv_remove_request(request_queue_t *, struct request *); extern void elv_dequeue_request(request_queue_t *, struct request *);
extern void elv_requeue_request(request_queue_t *, struct request *); extern void elv_requeue_request(request_queue_t *, struct request *);
extern void elv_deactivate_request(request_queue_t *, struct request *);
extern int elv_queue_empty(request_queue_t *); extern int elv_queue_empty(request_queue_t *);
extern struct request *elv_next_request(struct request_queue *q); extern struct request *elv_next_request(struct request_queue *q);
extern struct request *elv_former_request(request_queue_t *, struct request *); extern struct request *elv_former_request(request_queue_t *, struct request *);
......
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