git.openpandora.org
/
pandora-kernel.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
aio: fix io_setup/io_destroy race
[pandora-kernel.git]
/
fs
/
aio.c
diff --git
a/fs/aio.c
b/fs/aio.c
index
78c514c
..
f6578cb
100644
(file)
--- a/
fs/aio.c
+++ b/
fs/aio.c
@@
-273,7
+273,7
@@
static struct kioctx *ioctx_alloc(unsigned nr_events)
mm = ctx->mm = current->mm;
atomic_inc(&mm->mm_count);
mm = ctx->mm = current->mm;
atomic_inc(&mm->mm_count);
- atomic_set(&ctx->users,
1
);
+ atomic_set(&ctx->users,
2
);
spin_lock_init(&ctx->ctx_lock);
spin_lock_init(&ctx->ring_info.ring_lock);
init_waitqueue_head(&ctx->wait);
spin_lock_init(&ctx->ctx_lock);
spin_lock_init(&ctx->ring_info.ring_lock);
init_waitqueue_head(&ctx->wait);
@@
-476,14
+476,23
@@
static void kiocb_batch_init(struct kiocb_batch *batch, long total)
batch->count = total;
}
batch->count = total;
}
-static void kiocb_batch_free(struct kiocb_batch *batch)
+static void kiocb_batch_free(struct kioc
tx *ctx, struct kioc
b_batch *batch)
{
struct kiocb *req, *n;
{
struct kiocb *req, *n;
+ if (list_empty(&batch->head))
+ return;
+
+ spin_lock_irq(&ctx->ctx_lock);
list_for_each_entry_safe(req, n, &batch->head, ki_batch) {
list_del(&req->ki_batch);
list_for_each_entry_safe(req, n, &batch->head, ki_batch) {
list_del(&req->ki_batch);
+ list_del(&req->ki_list);
kmem_cache_free(kiocb_cachep, req);
kmem_cache_free(kiocb_cachep, req);
+ ctx->reqs_active--;
}
}
+ if (unlikely(!ctx->reqs_active && ctx->dead))
+ wake_up_all(&ctx->wait);
+ spin_unlock_irq(&ctx->ctx_lock);
}
/*
}
/*
@@
-1329,10
+1338,10
@@
SYSCALL_DEFINE2(io_setup, unsigned, nr_events, aio_context_t __user *, ctxp)
ret = PTR_ERR(ioctx);
if (!IS_ERR(ioctx)) {
ret = put_user(ioctx->user_id, ctxp);
ret = PTR_ERR(ioctx);
if (!IS_ERR(ioctx)) {
ret = put_user(ioctx->user_id, ctxp);
- if (!ret)
+ if (!ret) {
+ put_ioctx(ioctx);
return 0;
return 0;
-
- get_ioctx(ioctx); /* io_destroy() expects us to hold a ref */
+ }
io_destroy(ioctx);
}
io_destroy(ioctx);
}
@@
-1742,7
+1751,7
@@
long do_io_submit(aio_context_t ctx_id, long nr,
}
blk_finish_plug(&plug);
}
blk_finish_plug(&plug);
- kiocb_batch_free(&batch);
+ kiocb_batch_free(
ctx,
&batch);
put_ioctx(ctx);
return i ? i : ret;
}
put_ioctx(ctx);
return i ? i : ret;
}