Skip to content

Commit

Permalink
iosched: prevent aliased requests from starving other I/O
Browse files Browse the repository at this point in the history
Hi, Jens,

If you recall, I posted an RFC patch for this back in July of last year:
http://lkml.org/lkml/2010/7/13/279

The basic problem is that a process can issue a never-ending stream of
async direct I/Os to the same sector on a device, thus starving out
other I/O in the system (due to the way the alias handling works in both
cfq and deadline).  The solution I proposed back then was to start
dispatching from the fifo after a certain number of aliases had been
dispatched.  Vivek asked why we had to treat aliases differently at all,
and I never had a good answer.  So, I put together a simple patch which
allows aliases to be added to the rb tree (it adds them to the right,
though that doesn't matter as the order isn't guaranteed anyway).  I
think this is the preferred solution, as it doesn't break up time slices
in CFQ or batches in deadline.  I've tested it, and it does solve the
starvation issue.  Let me know what you think.

Cheers,
Jeff

Signed-off-by: Jeff Moyer <jmoyer@redhat.com>
Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
  • Loading branch information
JeffMoyer authored and gokhanmoral committed Jun 13, 2012
1 parent 775a7a8 commit 00b63bf
Show file tree
Hide file tree
Showing 5 changed files with 7 additions and 23 deletions.
9 changes: 2 additions & 7 deletions block/cfq-iosched.c
Expand Up @@ -1502,16 +1502,11 @@ static void cfq_add_rq_rb(struct request *rq)
{
struct cfq_queue *cfqq = RQ_CFQQ(rq);
struct cfq_data *cfqd = cfqq->cfqd;
struct request *__alias, *prev;
struct request *prev;

cfqq->queued[rq_is_sync(rq)]++;

/*
* looks a little odd, but the first insert might return an alias.
* if that happens, put the alias on the dispatch list
*/
while ((__alias = elv_rb_add(&cfqq->sort_list, rq)) != NULL)
cfq_dispatch_insert(cfqd->queue, __alias);
elv_rb_add(&cfqq->sort_list, rq);

if (!cfq_cfqq_on_rr(cfqq))
cfq_add_cfqq_rr(cfqd, cfqq);
Expand Down
4 changes: 1 addition & 3 deletions block/deadline-iosched.c
Expand Up @@ -77,10 +77,8 @@ static void
deadline_add_rq_rb(struct deadline_data *dd, struct request *rq)
{
struct rb_root *root = deadline_rb_root(dd, rq);
struct request *__alias;

while (unlikely(__alias = elv_rb_add(root, rq)))
deadline_move_request(dd, __alias);
elv_rb_add(root, rq);
}

static inline void
Expand Down
7 changes: 2 additions & 5 deletions block/elevator.c
Expand Up @@ -353,7 +353,7 @@ static struct request *elv_rqhash_find(struct request_queue *q, sector_t offset)
* RB-tree support functions for inserting/lookup/removal of requests
* in a sorted RB tree.
*/
struct request *elv_rb_add(struct rb_root *root, struct request *rq)
void elv_rb_add(struct rb_root *root, struct request *rq)
{
struct rb_node **p = &root->rb_node;
struct rb_node *parent = NULL;
Expand All @@ -365,15 +365,12 @@ struct request *elv_rb_add(struct rb_root *root, struct request *rq)

if (blk_rq_pos(rq) < blk_rq_pos(__rq))
p = &(*p)->rb_left;
else if (blk_rq_pos(rq) > blk_rq_pos(__rq))
else if (blk_rq_pos(rq) >= blk_rq_pos(__rq))
p = &(*p)->rb_right;
else
return __rq;
}

rb_link_node(&rq->rb_node, parent, p);
rb_insert_color(&rq->rb_node, root);
return NULL;
}
EXPORT_SYMBOL(elv_rb_add);

Expand Down
8 changes: 1 addition & 7 deletions block/vr-iosched.c
Expand Up @@ -73,13 +73,7 @@ return q->elevator->elevator_data;
static void
vr_add_rq_rb(struct vr_data *vd, struct request *rq)
{
struct request *alias = elv_rb_add(&vd->sort_list, rq);

if (unlikely(alias)) {
vr_move_request(vd, alias);
alias = elv_rb_add(&vd->sort_list, rq);
BUG_ON(alias);
}
elv_rb_add(&vd->sort_list, rq);

if (blk_rq_pos(rq) >= vd->last_sector) {
if (!vd->next_rq || blk_rq_pos(vd->next_rq) > blk_rq_pos(rq))
Expand Down
2 changes: 1 addition & 1 deletion include/linux/elevator.h
Expand Up @@ -146,7 +146,7 @@ extern struct request *elv_rb_latter_request(struct request_queue *, struct requ
/*
* rb support functions.
*/
extern struct request *elv_rb_add(struct rb_root *, struct request *);
extern void elv_rb_add(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);

Expand Down

0 comments on commit 00b63bf

Please sign in to comment.