From: Chris Mason aio.c | 39 +++++++++++++++++++++++++++++++++++---- 1 files changed, 35 insertions(+), 4 deletions(-) --- aio/fs/aio.c 2004-06-21 13:35:34.024355464 -0700 +++ aio-context-stall/fs/aio.c 2004-06-21 13:50:59.246700288 -0700 @@ -367,6 +367,7 @@ void fastcall __put_ioctx(struct kioctx if (unlikely(ctx->reqs_active)) BUG(); + cancel_delayed_work(&ctx->wq); flush_workqueue(aio_wq); aio_free_ring(ctx); mmdrop(ctx->mm); @@ -788,6 +789,22 @@ static int __aio_run_iocbs(struct kioctx return 0; } +static void aio_queue_work(struct kioctx * ctx) +{ + unsigned long timeout; + /* + * if someone is waiting, get the work started right + * away, otherwise, use a longer delay + */ + smp_mb(); + if (waitqueue_active(&ctx->wait)) + timeout = 1; + else + timeout = HZ/10; + queue_delayed_work(aio_wq, &ctx->wq, timeout); +} + + /* * aio_run_iocbs: * Process all pending retries queued on the ioctx @@ -804,8 +821,18 @@ static inline void aio_run_iocbs(struct requeue = __aio_run_iocbs(ctx); spin_unlock_irq(&ctx->ctx_lock); if (requeue) - queue_work(aio_wq, &ctx->wq); + aio_queue_work(ctx); +} +/* + * just like aio_run_iocbs, but keeps running them until + * the list stays empty + */ +static inline void aio_run_all_iocbs(struct kioctx *ctx) +{ + spin_lock_irq(&ctx->ctx_lock); + while( __aio_run_iocbs(ctx)); + spin_unlock_irq(&ctx->ctx_lock); } /* @@ -830,6 +857,9 @@ static void aio_kick_handler(void *data) unuse_mm(ctx->mm); spin_unlock_irq(&ctx->ctx_lock); set_fs(oldfs); + /* + * we're in a worker thread already, don't use queue_delayed_work, + */ if (requeue) queue_work(aio_wq, &ctx->wq); } @@ -852,7 +882,7 @@ void queue_kicked_iocb(struct kiocb *ioc run = __queue_kicked_iocb(iocb); spin_unlock_irqrestore(&ctx->ctx_lock, flags); if (run) { - queue_delayed_work(aio_wq, &ctx->wq, HZ/10); + aio_queue_work(ctx); aio_wakeups++; } } @@ -1119,7 +1149,7 @@ retry: /* racey check, but it gets redone */ if (!retry && unlikely(!list_empty(&ctx->run_list))) { retry = 1; - aio_run_iocbs(ctx); + aio_run_all_iocbs(ctx); goto retry; } @@ -1522,7 +1552,8 @@ int fastcall io_submit_one(struct kioctx spin_lock_irq(&ctx->ctx_lock); list_add_tail(&req->ki_run_list, &ctx->run_list); - __aio_run_iocbs(ctx); + /* drain the run list */ + while(__aio_run_iocbs(ctx)); spin_unlock_irq(&ctx->ctx_lock); aio_put_req(req); /* drop extra ref to req */ return 0;