diff options
author | Jens Axboe <jens.axboe@oracle.com> | 2006-12-20 11:04:12 +0100 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2006-12-20 11:04:12 +0100 |
commit | da775265021b61d5eb81df155e36cb0810f6df53 (patch) | |
tree | f7b28991b281a8c581bd3ab0bb470e158ae2206f /block/elevator.c | |
parent | 8e5cfc45e7527eb5c8a9a22d56a7b9227e7c0913 (diff) |
[PATCH] cfq-iosched: don't allow sync merges across queues
Currently we allow any merge, even if the io originates from different
processes. This can cause really bad starvation and unfairness, if those
ios happen to be synchronous (reads or direct writes).
So add a allow_merge hook to the io scheduler ops, so an io scheduler can
help decide whether a bio/process combination may be merged with an
existing request.
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'block/elevator.c')
-rw-r--r-- | block/elevator.c | 26 |
1 files changed, 22 insertions, 4 deletions
diff --git a/block/elevator.c b/block/elevator.c index c0063f345c5..62c7a3069d3 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -51,6 +51,21 @@ static const int elv_hash_shift = 6; #define ELV_ON_HASH(rq) (!hlist_unhashed(&(rq)->hash)) /* + * Query io scheduler to see if the current process issuing bio may be + * merged with rq. + */ +static int elv_iosched_allow_merge(struct request *rq, struct bio *bio) +{ + request_queue_t *q = rq->q; + elevator_t *e = q->elevator; + + if (e->ops->elevator_allow_merge_fn) + return e->ops->elevator_allow_merge_fn(q, rq, bio); + + return 1; +} + +/* * can we safely merge with this request? */ inline int elv_rq_merge_ok(struct request *rq, struct bio *bio) @@ -65,12 +80,15 @@ inline int elv_rq_merge_ok(struct request *rq, struct bio *bio) return 0; /* - * same device and no special stuff set, merge is ok + * must be same device and not a special request */ - if (rq->rq_disk == bio->bi_bdev->bd_disk && !rq->special) - return 1; + if (rq->rq_disk != bio->bi_bdev->bd_disk || !rq->special) + return 0; - return 0; + if (!elv_iosched_allow_merge(rq, bio)) + return 0; + + return 1; } EXPORT_SYMBOL(elv_rq_merge_ok); |