block: enumify ELEVATOR_*_MERGE
Switch these constants to an enum, and make let the compiler ensure that all callers of blk_try_merge and elv_merge handle all potential values. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Jens Axboe <axboe@fb.com>
This commit is contained in:
Родитель
6cf7677f1a
Коммит
34fe7c0540
|
@ -1511,12 +1511,11 @@ bool blk_attempt_plug_merge(struct request_queue *q, struct bio *bio,
|
||||||
{
|
{
|
||||||
struct blk_plug *plug;
|
struct blk_plug *plug;
|
||||||
struct request *rq;
|
struct request *rq;
|
||||||
bool ret = false;
|
|
||||||
struct list_head *plug_list;
|
struct list_head *plug_list;
|
||||||
|
|
||||||
plug = current->plug;
|
plug = current->plug;
|
||||||
if (!plug)
|
if (!plug)
|
||||||
goto out;
|
return false;
|
||||||
*request_count = 0;
|
*request_count = 0;
|
||||||
|
|
||||||
if (q->mq_ops)
|
if (q->mq_ops)
|
||||||
|
@ -1525,7 +1524,7 @@ bool blk_attempt_plug_merge(struct request_queue *q, struct bio *bio,
|
||||||
plug_list = &plug->list;
|
plug_list = &plug->list;
|
||||||
|
|
||||||
list_for_each_entry_reverse(rq, plug_list, queuelist) {
|
list_for_each_entry_reverse(rq, plug_list, queuelist) {
|
||||||
int el_ret;
|
bool merged = false;
|
||||||
|
|
||||||
if (rq->q == q) {
|
if (rq->q == q) {
|
||||||
(*request_count)++;
|
(*request_count)++;
|
||||||
|
@ -1541,19 +1540,22 @@ bool blk_attempt_plug_merge(struct request_queue *q, struct bio *bio,
|
||||||
if (rq->q != q || !blk_rq_merge_ok(rq, bio))
|
if (rq->q != q || !blk_rq_merge_ok(rq, bio))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
el_ret = blk_try_merge(rq, bio);
|
switch (blk_try_merge(rq, bio)) {
|
||||||
if (el_ret == ELEVATOR_BACK_MERGE) {
|
case ELEVATOR_BACK_MERGE:
|
||||||
ret = bio_attempt_back_merge(q, rq, bio);
|
merged = bio_attempt_back_merge(q, rq, bio);
|
||||||
if (ret)
|
break;
|
||||||
break;
|
case ELEVATOR_FRONT_MERGE:
|
||||||
} else if (el_ret == ELEVATOR_FRONT_MERGE) {
|
merged = bio_attempt_front_merge(q, rq, bio);
|
||||||
ret = bio_attempt_front_merge(q, rq, bio);
|
break;
|
||||||
if (ret)
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (merged)
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
out:
|
|
||||||
return ret;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int blk_plug_queued_count(struct request_queue *q)
|
unsigned int blk_plug_queued_count(struct request_queue *q)
|
||||||
|
@ -1595,7 +1597,7 @@ void init_request_from_bio(struct request *req, struct bio *bio)
|
||||||
static blk_qc_t blk_queue_bio(struct request_queue *q, struct bio *bio)
|
static blk_qc_t blk_queue_bio(struct request_queue *q, struct bio *bio)
|
||||||
{
|
{
|
||||||
struct blk_plug *plug;
|
struct blk_plug *plug;
|
||||||
int el_ret, where = ELEVATOR_INSERT_SORT;
|
int where = ELEVATOR_INSERT_SORT;
|
||||||
struct request *req, *free;
|
struct request *req, *free;
|
||||||
unsigned int request_count = 0;
|
unsigned int request_count = 0;
|
||||||
unsigned int wb_acct;
|
unsigned int wb_acct;
|
||||||
|
@ -1633,27 +1635,29 @@ static blk_qc_t blk_queue_bio(struct request_queue *q, struct bio *bio)
|
||||||
|
|
||||||
spin_lock_irq(q->queue_lock);
|
spin_lock_irq(q->queue_lock);
|
||||||
|
|
||||||
el_ret = elv_merge(q, &req, bio);
|
switch (elv_merge(q, &req, bio)) {
|
||||||
if (el_ret == ELEVATOR_BACK_MERGE) {
|
case ELEVATOR_BACK_MERGE:
|
||||||
if (bio_attempt_back_merge(q, req, bio)) {
|
if (!bio_attempt_back_merge(q, req, bio))
|
||||||
elv_bio_merged(q, req, bio);
|
break;
|
||||||
free = attempt_back_merge(q, req);
|
elv_bio_merged(q, req, bio);
|
||||||
if (!free)
|
free = attempt_back_merge(q, req);
|
||||||
elv_merged_request(q, req, el_ret);
|
if (free)
|
||||||
else
|
__blk_put_request(q, free);
|
||||||
__blk_put_request(q, free);
|
else
|
||||||
goto out_unlock;
|
elv_merged_request(q, req, ELEVATOR_BACK_MERGE);
|
||||||
}
|
goto out_unlock;
|
||||||
} else if (el_ret == ELEVATOR_FRONT_MERGE) {
|
case ELEVATOR_FRONT_MERGE:
|
||||||
if (bio_attempt_front_merge(q, req, bio)) {
|
if (!bio_attempt_front_merge(q, req, bio))
|
||||||
elv_bio_merged(q, req, bio);
|
break;
|
||||||
free = attempt_front_merge(q, req);
|
elv_bio_merged(q, req, bio);
|
||||||
if (!free)
|
free = attempt_front_merge(q, req);
|
||||||
elv_merged_request(q, req, el_ret);
|
if (free)
|
||||||
else
|
__blk_put_request(q, free);
|
||||||
__blk_put_request(q, free);
|
else
|
||||||
goto out_unlock;
|
elv_merged_request(q, req, ELEVATOR_FRONT_MERGE);
|
||||||
}
|
goto out_unlock;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
get_rq:
|
get_rq:
|
||||||
|
|
|
@ -801,7 +801,7 @@ bool blk_rq_merge_ok(struct request *rq, struct bio *bio)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int blk_try_merge(struct request *rq, struct bio *bio)
|
enum elv_merge blk_try_merge(struct request *rq, struct bio *bio)
|
||||||
{
|
{
|
||||||
if (blk_rq_pos(rq) + blk_rq_sectors(rq) == bio->bi_iter.bi_sector)
|
if (blk_rq_pos(rq) + blk_rq_sectors(rq) == bio->bi_iter.bi_sector)
|
||||||
return ELEVATOR_BACK_MERGE;
|
return ELEVATOR_BACK_MERGE;
|
||||||
|
|
|
@ -238,30 +238,29 @@ bool blk_mq_sched_try_merge(struct request_queue *q, struct bio *bio,
|
||||||
struct request **merged_request)
|
struct request **merged_request)
|
||||||
{
|
{
|
||||||
struct request *rq;
|
struct request *rq;
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = elv_merge(q, &rq, bio);
|
switch (elv_merge(q, &rq, bio)) {
|
||||||
if (ret == ELEVATOR_BACK_MERGE) {
|
case ELEVATOR_BACK_MERGE:
|
||||||
if (!blk_mq_sched_allow_merge(q, rq, bio))
|
if (!blk_mq_sched_allow_merge(q, rq, bio))
|
||||||
return false;
|
return false;
|
||||||
if (bio_attempt_back_merge(q, rq, bio)) {
|
if (!bio_attempt_back_merge(q, rq, bio))
|
||||||
*merged_request = attempt_back_merge(q, rq);
|
return false;
|
||||||
if (!*merged_request)
|
*merged_request = attempt_back_merge(q, rq);
|
||||||
elv_merged_request(q, rq, ret);
|
if (!*merged_request)
|
||||||
return true;
|
elv_merged_request(q, rq, ELEVATOR_BACK_MERGE);
|
||||||
}
|
return true;
|
||||||
} else if (ret == ELEVATOR_FRONT_MERGE) {
|
case ELEVATOR_FRONT_MERGE:
|
||||||
if (!blk_mq_sched_allow_merge(q, rq, bio))
|
if (!blk_mq_sched_allow_merge(q, rq, bio))
|
||||||
return false;
|
return false;
|
||||||
if (bio_attempt_front_merge(q, rq, bio)) {
|
if (!bio_attempt_front_merge(q, rq, bio))
|
||||||
*merged_request = attempt_front_merge(q, rq);
|
return false;
|
||||||
if (!*merged_request)
|
*merged_request = attempt_front_merge(q, rq);
|
||||||
elv_merged_request(q, rq, ret);
|
if (!*merged_request)
|
||||||
return true;
|
elv_merged_request(q, rq, ELEVATOR_FRONT_MERGE);
|
||||||
}
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(blk_mq_sched_try_merge);
|
EXPORT_SYMBOL_GPL(blk_mq_sched_try_merge);
|
||||||
|
|
||||||
|
|
|
@ -763,7 +763,7 @@ static bool blk_mq_attempt_merge(struct request_queue *q,
|
||||||
int checked = 8;
|
int checked = 8;
|
||||||
|
|
||||||
list_for_each_entry_reverse(rq, &ctx->rq_list, queuelist) {
|
list_for_each_entry_reverse(rq, &ctx->rq_list, queuelist) {
|
||||||
int el_ret;
|
bool merged = false;
|
||||||
|
|
||||||
if (!checked--)
|
if (!checked--)
|
||||||
break;
|
break;
|
||||||
|
@ -771,26 +771,22 @@ static bool blk_mq_attempt_merge(struct request_queue *q,
|
||||||
if (!blk_rq_merge_ok(rq, bio))
|
if (!blk_rq_merge_ok(rq, bio))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
el_ret = blk_try_merge(rq, bio);
|
switch (blk_try_merge(rq, bio)) {
|
||||||
if (el_ret == ELEVATOR_NO_MERGE)
|
case ELEVATOR_BACK_MERGE:
|
||||||
|
if (blk_mq_sched_allow_merge(q, rq, bio))
|
||||||
|
merged = bio_attempt_back_merge(q, rq, bio);
|
||||||
|
break;
|
||||||
|
case ELEVATOR_FRONT_MERGE:
|
||||||
|
if (blk_mq_sched_allow_merge(q, rq, bio))
|
||||||
|
merged = bio_attempt_front_merge(q, rq, bio);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!blk_mq_sched_allow_merge(q, rq, bio))
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (el_ret == ELEVATOR_BACK_MERGE) {
|
|
||||||
if (bio_attempt_back_merge(q, rq, bio)) {
|
|
||||||
ctx->rq_merged++;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
} else if (el_ret == ELEVATOR_FRONT_MERGE) {
|
|
||||||
if (bio_attempt_front_merge(q, rq, bio)) {
|
|
||||||
ctx->rq_merged++;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (merged)
|
||||||
|
ctx->rq_merged++;
|
||||||
|
return merged;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -215,7 +215,7 @@ int blk_attempt_req_merge(struct request_queue *q, struct request *rq,
|
||||||
void blk_recalc_rq_segments(struct request *rq);
|
void blk_recalc_rq_segments(struct request *rq);
|
||||||
void blk_rq_set_mixed_merge(struct request *rq);
|
void blk_rq_set_mixed_merge(struct request *rq);
|
||||||
bool blk_rq_merge_ok(struct request *rq, struct bio *bio);
|
bool blk_rq_merge_ok(struct request *rq, struct bio *bio);
|
||||||
int blk_try_merge(struct request *rq, struct bio *bio);
|
enum elv_merge blk_try_merge(struct request *rq, struct bio *bio);
|
||||||
|
|
||||||
void blk_queue_congestion_threshold(struct request_queue *q);
|
void blk_queue_congestion_threshold(struct request_queue *q);
|
||||||
|
|
||||||
|
|
|
@ -2528,7 +2528,7 @@ static void cfq_remove_request(struct request *rq)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cfq_merge(struct request_queue *q, struct request **req,
|
static enum elv_merge cfq_merge(struct request_queue *q, struct request **req,
|
||||||
struct bio *bio)
|
struct bio *bio)
|
||||||
{
|
{
|
||||||
struct cfq_data *cfqd = q->elevator->elevator_data;
|
struct cfq_data *cfqd = q->elevator->elevator_data;
|
||||||
|
@ -2544,7 +2544,7 @@ static int cfq_merge(struct request_queue *q, struct request **req,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cfq_merged_request(struct request_queue *q, struct request *req,
|
static void cfq_merged_request(struct request_queue *q, struct request *req,
|
||||||
int type)
|
enum elv_merge type)
|
||||||
{
|
{
|
||||||
if (type == ELEVATOR_FRONT_MERGE) {
|
if (type == ELEVATOR_FRONT_MERGE) {
|
||||||
struct cfq_queue *cfqq = RQ_CFQQ(req);
|
struct cfq_queue *cfqq = RQ_CFQQ(req);
|
||||||
|
|
|
@ -120,12 +120,11 @@ static void deadline_remove_request(struct request_queue *q, struct request *rq)
|
||||||
deadline_del_rq_rb(dd, rq);
|
deadline_del_rq_rb(dd, rq);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static enum elv_merge
|
||||||
deadline_merge(struct request_queue *q, struct request **req, struct bio *bio)
|
deadline_merge(struct request_queue *q, struct request **req, struct bio *bio)
|
||||||
{
|
{
|
||||||
struct deadline_data *dd = q->elevator->elevator_data;
|
struct deadline_data *dd = q->elevator->elevator_data;
|
||||||
struct request *__rq;
|
struct request *__rq;
|
||||||
int ret;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* check for front merge
|
* check for front merge
|
||||||
|
@ -138,20 +137,17 @@ deadline_merge(struct request_queue *q, struct request **req, struct bio *bio)
|
||||||
BUG_ON(sector != blk_rq_pos(__rq));
|
BUG_ON(sector != blk_rq_pos(__rq));
|
||||||
|
|
||||||
if (elv_bio_merge_ok(__rq, bio)) {
|
if (elv_bio_merge_ok(__rq, bio)) {
|
||||||
ret = ELEVATOR_FRONT_MERGE;
|
*req = __rq;
|
||||||
goto out;
|
return ELEVATOR_FRONT_MERGE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ELEVATOR_NO_MERGE;
|
return ELEVATOR_NO_MERGE;
|
||||||
out:
|
|
||||||
*req = __rq;
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void deadline_merged_request(struct request_queue *q,
|
static void deadline_merged_request(struct request_queue *q,
|
||||||
struct request *req, int type)
|
struct request *req, enum elv_merge type)
|
||||||
{
|
{
|
||||||
struct deadline_data *dd = q->elevator->elevator_data;
|
struct deadline_data *dd = q->elevator->elevator_data;
|
||||||
|
|
||||||
|
|
|
@ -427,11 +427,11 @@ void elv_dispatch_add_tail(struct request_queue *q, struct request *rq)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(elv_dispatch_add_tail);
|
EXPORT_SYMBOL(elv_dispatch_add_tail);
|
||||||
|
|
||||||
int elv_merge(struct request_queue *q, struct request **req, struct bio *bio)
|
enum elv_merge elv_merge(struct request_queue *q, struct request **req,
|
||||||
|
struct bio *bio)
|
||||||
{
|
{
|
||||||
struct elevator_queue *e = q->elevator;
|
struct elevator_queue *e = q->elevator;
|
||||||
struct request *__rq;
|
struct request *__rq;
|
||||||
int ret;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Levels of merges:
|
* Levels of merges:
|
||||||
|
@ -446,7 +446,8 @@ int elv_merge(struct request_queue *q, struct request **req, struct bio *bio)
|
||||||
* First try one-hit cache.
|
* First try one-hit cache.
|
||||||
*/
|
*/
|
||||||
if (q->last_merge && elv_bio_merge_ok(q->last_merge, bio)) {
|
if (q->last_merge && elv_bio_merge_ok(q->last_merge, bio)) {
|
||||||
ret = blk_try_merge(q->last_merge, bio);
|
enum elv_merge ret = blk_try_merge(q->last_merge, bio);
|
||||||
|
|
||||||
if (ret != ELEVATOR_NO_MERGE) {
|
if (ret != ELEVATOR_NO_MERGE) {
|
||||||
*req = q->last_merge;
|
*req = q->last_merge;
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -514,7 +515,8 @@ bool elv_attempt_insert_merge(struct request_queue *q, struct request *rq)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void elv_merged_request(struct request_queue *q, struct request *rq, int type)
|
void elv_merged_request(struct request_queue *q, struct request *rq,
|
||||||
|
enum elv_merge type)
|
||||||
{
|
{
|
||||||
struct elevator_queue *e = q->elevator;
|
struct elevator_queue *e = q->elevator;
|
||||||
|
|
||||||
|
|
|
@ -121,7 +121,7 @@ static void deadline_remove_request(struct request_queue *q, struct request *rq)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dd_request_merged(struct request_queue *q, struct request *req,
|
static void dd_request_merged(struct request_queue *q, struct request *req,
|
||||||
int type)
|
enum elv_merge type)
|
||||||
{
|
{
|
||||||
struct deadline_data *dd = q->elevator->elevator_data;
|
struct deadline_data *dd = q->elevator->elevator_data;
|
||||||
|
|
||||||
|
|
|
@ -9,12 +9,21 @@
|
||||||
struct io_cq;
|
struct io_cq;
|
||||||
struct elevator_type;
|
struct elevator_type;
|
||||||
|
|
||||||
typedef int (elevator_merge_fn) (struct request_queue *, struct request **,
|
/*
|
||||||
|
* Return values from elevator merger
|
||||||
|
*/
|
||||||
|
enum elv_merge {
|
||||||
|
ELEVATOR_NO_MERGE = 0,
|
||||||
|
ELEVATOR_FRONT_MERGE = 1,
|
||||||
|
ELEVATOR_BACK_MERGE = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum elv_merge (elevator_merge_fn) (struct request_queue *, struct request **,
|
||||||
struct bio *);
|
struct bio *);
|
||||||
|
|
||||||
typedef void (elevator_merge_req_fn) (struct request_queue *, struct request *, struct request *);
|
typedef void (elevator_merge_req_fn) (struct request_queue *, struct request *, struct request *);
|
||||||
|
|
||||||
typedef void (elevator_merged_fn) (struct request_queue *, struct request *, int);
|
typedef void (elevator_merged_fn) (struct request_queue *, struct request *, enum elv_merge);
|
||||||
|
|
||||||
typedef int (elevator_allow_bio_merge_fn) (struct request_queue *,
|
typedef int (elevator_allow_bio_merge_fn) (struct request_queue *,
|
||||||
struct request *, struct bio *);
|
struct request *, struct bio *);
|
||||||
|
@ -87,7 +96,7 @@ struct elevator_mq_ops {
|
||||||
bool (*allow_merge)(struct request_queue *, struct request *, struct bio *);
|
bool (*allow_merge)(struct request_queue *, struct request *, struct bio *);
|
||||||
bool (*bio_merge)(struct blk_mq_hw_ctx *, struct bio *);
|
bool (*bio_merge)(struct blk_mq_hw_ctx *, struct bio *);
|
||||||
int (*request_merge)(struct request_queue *q, struct request **, struct bio *);
|
int (*request_merge)(struct request_queue *q, struct request **, struct bio *);
|
||||||
void (*request_merged)(struct request_queue *, struct request *, int);
|
void (*request_merged)(struct request_queue *, struct request *, enum elv_merge);
|
||||||
void (*requests_merged)(struct request_queue *, struct request *, struct request *);
|
void (*requests_merged)(struct request_queue *, struct request *, struct request *);
|
||||||
struct request *(*get_request)(struct request_queue *, unsigned int, struct blk_mq_alloc_data *);
|
struct request *(*get_request)(struct request_queue *, unsigned int, struct blk_mq_alloc_data *);
|
||||||
void (*put_request)(struct request *);
|
void (*put_request)(struct request *);
|
||||||
|
@ -166,10 +175,12 @@ extern void elv_dispatch_sort(struct request_queue *, struct request *);
|
||||||
extern void elv_dispatch_add_tail(struct request_queue *, struct request *);
|
extern void elv_dispatch_add_tail(struct request_queue *, struct request *);
|
||||||
extern void elv_add_request(struct request_queue *, struct request *, int);
|
extern void elv_add_request(struct request_queue *, struct request *, int);
|
||||||
extern void __elv_add_request(struct request_queue *, struct request *, int);
|
extern void __elv_add_request(struct request_queue *, struct request *, int);
|
||||||
extern int elv_merge(struct request_queue *, struct request **, struct bio *);
|
extern enum elv_merge elv_merge(struct request_queue *, struct request **,
|
||||||
|
struct bio *);
|
||||||
extern void elv_merge_requests(struct request_queue *, struct request *,
|
extern void elv_merge_requests(struct request_queue *, struct request *,
|
||||||
struct request *);
|
struct request *);
|
||||||
extern void elv_merged_request(struct request_queue *, struct request *, int);
|
extern void elv_merged_request(struct request_queue *, struct request *,
|
||||||
|
enum elv_merge);
|
||||||
extern void elv_bio_merged(struct request_queue *q, struct request *,
|
extern void elv_bio_merged(struct request_queue *q, struct request *,
|
||||||
struct bio *);
|
struct bio *);
|
||||||
extern bool elv_attempt_insert_merge(struct request_queue *, struct request *);
|
extern bool elv_attempt_insert_merge(struct request_queue *, struct request *);
|
||||||
|
@ -218,13 +229,6 @@ extern void elv_rb_add(struct rb_root *, struct request *);
|
||||||
extern void elv_rb_del(struct rb_root *, struct request *);
|
extern void elv_rb_del(struct rb_root *, struct request *);
|
||||||
extern struct request *elv_rb_find(struct rb_root *, sector_t);
|
extern struct request *elv_rb_find(struct rb_root *, sector_t);
|
||||||
|
|
||||||
/*
|
|
||||||
* Return values from elevator merger
|
|
||||||
*/
|
|
||||||
#define ELEVATOR_NO_MERGE 0
|
|
||||||
#define ELEVATOR_FRONT_MERGE 1
|
|
||||||
#define ELEVATOR_BACK_MERGE 2
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Insertion selection
|
* Insertion selection
|
||||||
*/
|
*/
|
||||||
|
|
Загрузка…
Ссылка в новой задаче