Commit 068b52c1 authored by Suparna Bhattacharya's avatar Suparna Bhattacharya Committed by Linus Torvalds

[PATCH] AIO: Splice runlist for fairness across io contexts

This patch tries be a little fairer across multiple io contexts in handling
retries, helping make sure progress happens uniformly across different io
contexts (especially if they are acting on independent queues).

It splices the ioctx runlist before processing it in __aio_run_iocbs.  If
new iocbs get added to the ctx in meantime, it queues a fresh workqueue
entry instead of handling them righaway, so that other ioctxs' retries get
a chance to be processed before the newer entries in the queue.

This might make a difference in a situation where retries are getting
queued very fast on one ioctx, while the workqueue entry for another ioctx
is stuck behind it.  I've only seen this occasionally earlier and can't
recreate it consistently, but may be worth including anyway.
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 63b05203
...@@ -769,13 +769,15 @@ static ssize_t aio_run_iocb(struct kiocb *iocb) ...@@ -769,13 +769,15 @@ static ssize_t aio_run_iocb(struct kiocb *iocb)
* Assumes it is operating within the aio issuer's mm * Assumes it is operating within the aio issuer's mm
* context. Expects to be called with ctx->ctx_lock held * context. Expects to be called with ctx->ctx_lock held
*/ */
static void __aio_run_iocbs(struct kioctx *ctx) static int __aio_run_iocbs(struct kioctx *ctx)
{ {
struct kiocb *iocb; struct kiocb *iocb;
int count = 0; int count = 0;
LIST_HEAD(run_list);
while (!list_empty(&ctx->run_list)) { list_splice_init(&ctx->run_list, &run_list);
iocb = list_entry(ctx->run_list.next, struct kiocb, while (!list_empty(&run_list)) {
iocb = list_entry(run_list.next, struct kiocb,
ki_run_list); ki_run_list);
list_del(&iocb->ki_run_list); list_del(&iocb->ki_run_list);
/* /*
...@@ -788,6 +790,9 @@ static void __aio_run_iocbs(struct kioctx *ctx) ...@@ -788,6 +790,9 @@ static void __aio_run_iocbs(struct kioctx *ctx)
count++; count++;
} }
aio_run++; aio_run++;
if (!list_empty(&ctx->run_list))
return 1;
return 0;
} }
/* /*
...@@ -799,9 +804,15 @@ static void __aio_run_iocbs(struct kioctx *ctx) ...@@ -799,9 +804,15 @@ static void __aio_run_iocbs(struct kioctx *ctx)
*/ */
static inline void aio_run_iocbs(struct kioctx *ctx) static inline void aio_run_iocbs(struct kioctx *ctx)
{ {
int requeue;
spin_lock_irq(&ctx->ctx_lock); spin_lock_irq(&ctx->ctx_lock);
__aio_run_iocbs(ctx);
spin_unlock_irq(&ctx->ctx_lock); requeue = __aio_run_iocbs(ctx);
spin_unlock_irq(&ctx->ctx_lock);
if (requeue)
queue_work(aio_wq, &ctx->wq);
} }
/* /*
...@@ -817,14 +828,17 @@ static void aio_kick_handler(void *data) ...@@ -817,14 +828,17 @@ static void aio_kick_handler(void *data)
{ {
struct kioctx *ctx = data; struct kioctx *ctx = data;
mm_segment_t oldfs = get_fs(); mm_segment_t oldfs = get_fs();
int requeue;
set_fs(USER_DS); set_fs(USER_DS);
use_mm(ctx->mm); use_mm(ctx->mm);
spin_lock_irq(&ctx->ctx_lock); spin_lock_irq(&ctx->ctx_lock);
__aio_run_iocbs(ctx); requeue =__aio_run_iocbs(ctx);
unuse_mm(ctx->mm); unuse_mm(ctx->mm);
spin_unlock_irq(&ctx->ctx_lock); spin_unlock_irq(&ctx->ctx_lock);
set_fs(oldfs); set_fs(oldfs);
if (requeue)
queue_work(aio_wq, &ctx->wq);
} }
......
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