Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+43 −36
Original line number Diff line number Diff line
@@ -220,6 +220,29 @@ static inline void put_ioctx(struct kioctx *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
 *	Allocates and initializes an ioctx.  Returns an ERR_PTR if it failed.
 */
@@ -290,25 +313,19 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
 */
static void kill_ctx(struct kioctx *ctx)
{
	int (*cancel)(struct kiocb *, struct io_event *);
	struct task_struct *tsk = current;
	DECLARE_WAITQUEUE(wait, tsk);
	struct io_event res;
	struct kiocb *req;

	spin_lock_irq(&ctx->ctx_lock);
	ctx->dead = 1;
	while (!list_empty(&ctx->active_reqs)) {
		struct list_head *pos = ctx->active_reqs.next;
		struct kiocb *iocb = list_kiocb(pos);
		list_del_init(&iocb->ki_list);
		cancel = iocb->ki_cancel;
		kiocbSetCancelled(iocb);
		if (cancel) {
			iocb->ki_users++;
			spin_unlock_irq(&ctx->ctx_lock);
			cancel(iocb, &res);
			spin_lock_irq(&ctx->ctx_lock);
		}
		req = list_first_entry(&ctx->active_reqs,
					struct kiocb, ki_list);

		list_del_init(&req->ki_list);
		kiocb_cancel(ctx, req, &res);
	}

	if (!ctx->reqs_active)
@@ -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,
		struct io_event __user *, result)
{
	int (*cancel)(struct kiocb *iocb, struct io_event *res);
	struct io_event res;
	struct kioctx *ctx;
	struct kiocb *kiocb;
	u32 key;
@@ -1431,32 +1448,22 @@ SYSCALL_DEFINE3(io_cancel, aio_context_t, ctx_id, struct iocb __user *, iocb,
		return -EINVAL;

	spin_lock_irq(&ctx->ctx_lock);
	ret = -EAGAIN;

	kiocb = lookup_kiocb(ctx, iocb, key);
	if (kiocb && kiocb->ki_cancel) {
		cancel = kiocb->ki_cancel;
		kiocb->ki_users ++;
		kiocbSetCancelled(kiocb);
	} else
		cancel = NULL;
	if (kiocb)
		ret = kiocb_cancel(ctx, kiocb, &res);
	else
		ret = -EINVAL;

	spin_unlock_irq(&ctx->ctx_lock);

	if (NULL != cancel) {
		struct io_event tmp;
		pr_debug("calling cancel\n");
		memset(&tmp, 0, sizeof(tmp));
		tmp.obj = (u64)(unsigned long)kiocb->ki_obj.user;
		tmp.data = kiocb->ki_user_data;
		ret = cancel(kiocb, &tmp);
	if (!ret) {
		/* Cancellation succeeded -- copy the result
		 * into the user's buffer.
		 */
			if (copy_to_user(result, &tmp, sizeof(tmp)))
		if (copy_to_user(result, &res, sizeof(res)))
			ret = -EFAULT;
	}
	} else
		ret = -EINVAL;

	put_ioctx(ctx);