Commit 906b973c authored by Kent Overstreet's avatar Kent Overstreet Committed by Linus Torvalds

aio: add kiocb_cancel()

Minor refactoring, to get rid of some duplicated code

[akpm@linux-foundation.org: fix warning]
Signed-off-by: default avatarKent Overstreet <koverstreet@google.com>
Cc: Zach Brown <zab@redhat.com>
Cc: Felipe Balbi <balbi@ti.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Mark Fasheh <mfasheh@suse.com>
Cc: Joel Becker <jlbec@evilplan.org>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Asai Thambi S P <asamymuthupa@micron.com>
Cc: Selvan Mani <smani@micron.com>
Cc: Sam Bradshaw <sbradshaw@micron.com>
Acked-by: default avatarJeff Moyer <jmoyer@redhat.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Benjamin LaHaise <bcrl@kvack.org>
Reviewed-by: default avatar"Theodore Ts'o" <tytso@mit.edu>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 2d68449e
...@@ -220,6 +220,29 @@ static inline void put_ioctx(struct kioctx *kioctx) ...@@ -220,6 +220,29 @@ static inline void put_ioctx(struct kioctx *kioctx)
__put_ioctx(kioctx); __put_ioctx(kioctx);
} }
static int kiocb_cancel(struct kioctx *ctx, struct kiocb *kiocb,
struct io_event *res)
{
int (*cancel)(struct kiocb *, struct io_event *);
int ret = -EINVAL;
cancel = kiocb->ki_cancel;
kiocbSetCancelled(kiocb);
if (cancel) {
kiocb->ki_users++;
spin_unlock_irq(&ctx->ctx_lock);
memset(res, 0, sizeof(*res));
res->obj = (u64)(unsigned long)kiocb->ki_obj.user;
res->data = kiocb->ki_user_data;
ret = cancel(kiocb, res);
spin_lock_irq(&ctx->ctx_lock);
}
return ret;
}
/* ioctx_alloc /* ioctx_alloc
* Allocates and initializes an ioctx. Returns an ERR_PTR if it failed. * Allocates and initializes an ioctx. Returns an ERR_PTR if it failed.
*/ */
...@@ -290,25 +313,19 @@ static struct kioctx *ioctx_alloc(unsigned nr_events) ...@@ -290,25 +313,19 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
*/ */
static void kill_ctx(struct kioctx *ctx) static void kill_ctx(struct kioctx *ctx)
{ {
int (*cancel)(struct kiocb *, struct io_event *);
struct task_struct *tsk = current; struct task_struct *tsk = current;
DECLARE_WAITQUEUE(wait, tsk); DECLARE_WAITQUEUE(wait, tsk);
struct io_event res; struct io_event res;
struct kiocb *req;
spin_lock_irq(&ctx->ctx_lock); spin_lock_irq(&ctx->ctx_lock);
ctx->dead = 1; ctx->dead = 1;
while (!list_empty(&ctx->active_reqs)) { while (!list_empty(&ctx->active_reqs)) {
struct list_head *pos = ctx->active_reqs.next; req = list_first_entry(&ctx->active_reqs,
struct kiocb *iocb = list_kiocb(pos); struct kiocb, ki_list);
list_del_init(&iocb->ki_list);
cancel = iocb->ki_cancel; list_del_init(&req->ki_list);
kiocbSetCancelled(iocb); kiocb_cancel(ctx, req, &res);
if (cancel) {
iocb->ki_users++;
spin_unlock_irq(&ctx->ctx_lock);
cancel(iocb, &res);
spin_lock_irq(&ctx->ctx_lock);
}
} }
if (!ctx->reqs_active) if (!ctx->reqs_active)
...@@ -1416,7 +1433,7 @@ static struct kiocb *lookup_kiocb(struct kioctx *ctx, struct iocb __user *iocb, ...@@ -1416,7 +1433,7 @@ static struct kiocb *lookup_kiocb(struct kioctx *ctx, struct iocb __user *iocb,
SYSCALL_DEFINE3(io_cancel, aio_context_t, ctx_id, struct iocb __user *, iocb, SYSCALL_DEFINE3(io_cancel, aio_context_t, ctx_id, struct iocb __user *, iocb,
struct io_event __user *, result) struct io_event __user *, result)
{ {
int (*cancel)(struct kiocb *iocb, struct io_event *res); struct io_event res;
struct kioctx *ctx; struct kioctx *ctx;
struct kiocb *kiocb; struct kiocb *kiocb;
u32 key; u32 key;
...@@ -1431,32 +1448,22 @@ SYSCALL_DEFINE3(io_cancel, aio_context_t, ctx_id, struct iocb __user *, iocb, ...@@ -1431,32 +1448,22 @@ SYSCALL_DEFINE3(io_cancel, aio_context_t, ctx_id, struct iocb __user *, iocb,
return -EINVAL; return -EINVAL;
spin_lock_irq(&ctx->ctx_lock); spin_lock_irq(&ctx->ctx_lock);
ret = -EAGAIN;
kiocb = lookup_kiocb(ctx, iocb, key); kiocb = lookup_kiocb(ctx, iocb, key);
if (kiocb && kiocb->ki_cancel) { if (kiocb)
cancel = kiocb->ki_cancel; ret = kiocb_cancel(ctx, kiocb, &res);
kiocb->ki_users ++; else
kiocbSetCancelled(kiocb); ret = -EINVAL;
} else
cancel = NULL;
spin_unlock_irq(&ctx->ctx_lock); spin_unlock_irq(&ctx->ctx_lock);
if (NULL != cancel) { if (!ret) {
struct io_event tmp; /* Cancellation succeeded -- copy the result
pr_debug("calling cancel\n"); * into the user's buffer.
memset(&tmp, 0, sizeof(tmp)); */
tmp.obj = (u64)(unsigned long)kiocb->ki_obj.user; if (copy_to_user(result, &res, sizeof(res)))
tmp.data = kiocb->ki_user_data; ret = -EFAULT;
ret = cancel(kiocb, &tmp); }
if (!ret) {
/* Cancellation succeeded -- copy the result
* into the user's buffer.
*/
if (copy_to_user(result, &tmp, sizeof(tmp)))
ret = -EFAULT;
}
} else
ret = -EINVAL;
put_ioctx(ctx); put_ioctx(ctx);
......
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