aboutsummaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
authorJeff Moyer <jmoyer@redhat.com>2011-06-02 15:19:05 -0400
committerJens Axboe <jaxboe@fusionio.com>2011-06-02 15:19:05 -0400
commit796d5116c407690b14fd5bda136aa67a39e7061a (patch)
treebb0522aacb0a923e6636c82aff143df95ea1d730 /block
parent1fa7b6a29c61358cc2ca6f64cef4aa0e1a7ca74c (diff)
iosched: prevent aliased requests from starving other I/O
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>
Diffstat (limited to 'block')
-rw-r--r--block/cfq-iosched.c9
-rw-r--r--block/deadline-iosched.c4
-rw-r--r--block/elevator.c7
3 files changed, 5 insertions, 15 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 7c52d6888924..a2fb14bb1402 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -1501,16 +1501,11 @@ static void cfq_add_rq_rb(struct request *rq)
1501{ 1501{
1502 struct cfq_queue *cfqq = RQ_CFQQ(rq); 1502 struct cfq_queue *cfqq = RQ_CFQQ(rq);
1503 struct cfq_data *cfqd = cfqq->cfqd; 1503 struct cfq_data *cfqd = cfqq->cfqd;
1504 struct request *__alias, *prev; 1504 struct request *prev;
1505 1505
1506 cfqq->queued[rq_is_sync(rq)]++; 1506 cfqq->queued[rq_is_sync(rq)]++;
1507 1507
1508 /* 1508 elv_rb_add(&cfqq->sort_list, rq);
1509 * looks a little odd, but the first insert might return an alias.
1510 * if that happens, put the alias on the dispatch list
1511 */
1512 while ((__alias = elv_rb_add(&cfqq->sort_list, rq)) != NULL)
1513 cfq_dispatch_insert(cfqd->queue, __alias);
1514 1509
1515 if (!cfq_cfqq_on_rr(cfqq)) 1510 if (!cfq_cfqq_on_rr(cfqq))
1516 cfq_add_cfqq_rr(cfqd, cfqq); 1511 cfq_add_cfqq_rr(cfqd, cfqq);
diff --git a/block/deadline-iosched.c b/block/deadline-iosched.c
index 5139c0ea1864..c644137d9cd6 100644
--- a/block/deadline-iosched.c
+++ b/block/deadline-iosched.c
@@ -77,10 +77,8 @@ static void
77deadline_add_rq_rb(struct deadline_data *dd, struct request *rq) 77deadline_add_rq_rb(struct deadline_data *dd, struct request *rq)
78{ 78{
79 struct rb_root *root = deadline_rb_root(dd, rq); 79 struct rb_root *root = deadline_rb_root(dd, rq);
80 struct request *__alias;
81 80
82 while (unlikely(__alias = elv_rb_add(root, rq))) 81 elv_rb_add(root, rq);
83 deadline_move_request(dd, __alias);
84} 82}
85 83
86static inline void 84static inline void
diff --git a/block/elevator.c b/block/elevator.c
index b0b38ce0dcb6..a3b64bc71d88 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -353,7 +353,7 @@ static struct request *elv_rqhash_find(struct request_queue *q, sector_t offset)
353 * RB-tree support functions for inserting/lookup/removal of requests 353 * RB-tree support functions for inserting/lookup/removal of requests
354 * in a sorted RB tree. 354 * in a sorted RB tree.
355 */ 355 */
356struct request *elv_rb_add(struct rb_root *root, struct request *rq) 356void elv_rb_add(struct rb_root *root, struct request *rq)
357{ 357{
358 struct rb_node **p = &root->rb_node; 358 struct rb_node **p = &root->rb_node;
359 struct rb_node *parent = NULL; 359 struct rb_node *parent = NULL;
@@ -365,15 +365,12 @@ struct request *elv_rb_add(struct rb_root *root, struct request *rq)
365 365
366 if (blk_rq_pos(rq) < blk_rq_pos(__rq)) 366 if (blk_rq_pos(rq) < blk_rq_pos(__rq))
367 p = &(*p)->rb_left; 367 p = &(*p)->rb_left;
368 else if (blk_rq_pos(rq) > blk_rq_pos(__rq)) 368 else if (blk_rq_pos(rq) >= blk_rq_pos(__rq))
369 p = &(*p)->rb_right; 369 p = &(*p)->rb_right;
370 else
371 return __rq;
372 } 370 }
373 371
374 rb_link_node(&rq->rb_node, parent, p); 372 rb_link_node(&rq->rb_node, parent, p);
375 rb_insert_color(&rq->rb_node, root); 373 rb_insert_color(&rq->rb_node, root);
376 return NULL;
377} 374}
378EXPORT_SYMBOL(elv_rb_add); 375EXPORT_SYMBOL(elv_rb_add);
379 376