aio: Wake all waiters when destroying ctx
PATCH 1/1 aio: Wake all waiters when destroying ctx
From: Roland Dreier <[email protected]>
The test program below will hang because io_getevents() uses add_wait_queue_exclusive(), which means the wake_up() in io_destroy() only wakes up one of the threads. Fix this by using wake_up_all() in the aio code paths where we want to make sure no one gets stuck.
// t.c -- compile with gcc -lpthread -laio t.c
#include <libaio.h>
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
static const int nthr = 2;
void *getev(void *ctx)
{
struct io_event ev;
io_getevents(ctx, 1, 1, &ev, NULL);
printf("io_getevents returned\n");
return NULL;
}
int main(int argc, char *argv[])
{
io_context_t ctx = 0;
pthread_t thread[nthr];
int i;
io_setup(1024, &ctx);
for (i = 0; i < nthr; ++i)
pthread_create(&thread[i], NULL, getev, ctx);
sleep(1);
io_destroy(ctx);
for (i = 0; i < nthr; ++i)
pthread_join(thread[i], NULL);
return 0;
}--- fs/aio.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
fs/aio.c +2 -2
@@ -520,7 +520,7 @@ static inline void really_put_req(struct kioctx *ctx, struct kiocb *req) ctx->reqs_active--;if (unlikely (!ctx->reqs_active && ctx->dead)) -wake_up (&ctx->wait); +wake_up_all (&ctx->wait); }static void aio_fput_routine (struct work_struct *data)
@@ -1229,7 +1229,7 @@ static void io_destroy(struct kioctx *ioctx)* by other CPUs at this point. Right now, we rely on the * locking done by the above calls to ensure this consistency. */ -wake_up (&ioctx->wait); +wake_up_all (&ioctx->wait);put_ioctx (ioctx);/* once for the lookup */ }
Quoted 6 lines · Roland Dreier
From: Roland Dreier <[email protected]>
The test program below will hang because
io_getevents()usesadd_wait_queue_exclusive(), which means thewake_up()inio_destroy()only wakes up one of the threads. Fix this by usingwake_up_all()in the aio code paths where we want to make sure no one gets stuck.
[snip]
Quoted 20 lines
Cc <[email protected]>Signed-off-by Roland Dreier <[email protected]>--- fs/aio.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)fs/aio.c +1
-1@@ -520,7 +520,7 @@ static inline void really_put_req(struct kioctx *ctx, struct kiocb *req) ctx->reqs_active--;if (unlikely (!ctx->reqs_active && ctx->dead)) -wake_up (&ctx->wait); +wake_up_all (&ctx->wait); }static void aio_fput_routine (struct work_struct *data)
fs/aio.c static void io_destroy(struct kioctx *ioctx) · line 1235
Quoted 8 lines
fs/aio.c +1
-1@@ -1229,7 +1229,7 @@ static void io_destroy(struct kioctx *ioctx)* by other CPUs at this point. Right now, we rely on the * locking done by the above calls to ensure this consistency. */ -wake_up (&ioctx->wait); +wake_up_all (&ioctx->wait);put_ioctx (ioctx);/* once for the lookup */ }
Thanks, Roland, this looks good.
Quoted 42 lines · On Fri, 11 Mar 2011 09:21:46 -0500 Jeff Moyer <[email protected]> wrote:
Quoted 6 lines · Roland Dreier
From: Roland Dreier <[email protected]>
The test program below will hang because
io_getevents()usesadd_wait_queue_exclusive(), which means thewake_up()inio_destroy()only wakes up one of the threads. Fix this by usingwake_up_all()in the aio code paths where we want to make sure no one gets stuck.[snip]
Quoted 20 lines
Cc <[email protected]>Signed-off-by Roland Dreier <[email protected]>--- fs/aio.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)fs/aio.c +1
-1@@ -520,7 +520,7 @@ static inline void really_put_req(struct kioctx *ctx, struct kiocb *req) ctx->reqs_active--;if (unlikely (!ctx->reqs_active && ctx->dead)) -wake_up (&ctx->wait); +wake_up_all (&ctx->wait); }static void aio_fput_routine (struct work_struct *data)fs/aio.c static void io_destroy(struct kioctx *ioctx) · line 1235
Quoted 8 lines
fs/aio.c +1
-1@@ -1229,7 +1229,7 @@ static void io_destroy(struct kioctx *ioctx)* by other CPUs at this point. Right now, we rely on the * locking done by the above calls to ensure this consistency. */ -wake_up (&ioctx->wait); +wake_up_all (&ioctx->wait);put_ioctx (ioctx);/* once for the lookup */ }Thanks, Roland, this looks good.
Quoted 1 line
Reviewed-by Jeff Moyer <[email protected]>
It's a fairly old bug (yes?) and we're presumably close to 2.6.38. So I scheduled the fix for 2.6.39 marked for backporting into 2.6.38.x and earlier.
That may have been a bit over-cautious - feel free to argue ;)
Quoted 3 lines · Andrew Morton
It's a fairly old bug (yes?) and we're presumably close to 2.6.38. So I scheduled the fix for 2.6.39 marked for backporting into 2.6.38.x and earlier.
Yes, AFAICT it's been there approximately forever.
I agree that this is 2.6.39 stuff, and I included the stable@ cc so it gets into 2.6.38.1. Seems like the best course.
- R.