Prep work for bio cancellation. At least initially, we don't want to
implement a callback that has to chase down all the state (multiple
bios/requests) associated with the iocb; a simple flag will suffice.

Signed-off-by: Kent Overstreet <koverstr...@google.com>
---
 drivers/usb/gadget/inode.c |  7 +----
 fs/aio.c                   | 76 +++++++++++++++++++++-------------------------
 include/linux/aio.h        |  5 +++
 3 files changed, 41 insertions(+), 47 deletions(-)

diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index fd1bf4a..e5e2210 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -528,19 +528,14 @@ static void ep_aio_cancel(struct kiocb *iocb)
 {
        struct kiocb_priv       *priv = iocb->private;
        struct ep_data          *epdata;
-       int                     value;
 
        local_irq_disable();
        epdata = priv->epdata;
        // spin_lock(&epdata->dev->lock);
        if (likely(epdata && epdata->ep && priv->req))
-               value = usb_ep_dequeue (epdata->ep, priv->req);
-       else
-               value = -EINVAL;
+               usb_ep_dequeue (epdata->ep, priv->req);
        // spin_unlock(&epdata->dev->lock);
        local_irq_enable();
-
-       return value;
 }
 
 static ssize_t ep_copy_to_user(struct kiocb_priv *priv)
diff --git a/fs/aio.c b/fs/aio.c
index 4b9bfb5..f5f27bd 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -242,48 +242,34 @@ static int aio_setup_ring(struct kioctx *ctx)
 
 void kiocb_set_cancel_fn(struct kiocb *req, kiocb_cancel_fn *cancel)
 {
-       struct kioctx *ctx = req->ki_ctx;
-       unsigned long flags;
-
-       spin_lock_irqsave(&ctx->ctx_lock, flags);
+       kiocb_cancel_fn *p, *old = req->ki_cancel;
 
-       if (!req->ki_list.next)
-               list_add(&req->ki_list, &ctx->active_reqs);
-
-       req->ki_cancel = cancel;
+       do {
+               if (old == KIOCB_CANCELLED) {
+                       cancel(req);
+                       return;
+               }
 
-       spin_unlock_irqrestore(&ctx->ctx_lock, flags);
+               p = old;
+               old = cmpxchg(&req->ki_cancel, old, cancel);
+       } while (old != p);
 }
 EXPORT_SYMBOL(kiocb_set_cancel_fn);
 
-static int kiocb_cancel(struct kioctx *ctx, struct kiocb *kiocb)
+static void kiocb_cancel(struct kioctx *ctx, struct kiocb *req)
 {
-       kiocb_cancel_fn *old, *cancel;
-       int ret = -EINVAL;
-
-       /*
-        * Don't want to set kiocb->ki_cancel = KIOCB_CANCELLED unless it
-        * actually has a cancel function, hence the cmpxchg()
-        */
-
-       cancel = ACCESS_ONCE(kiocb->ki_cancel);
-       do {
-               if (!cancel || cancel == KIOCB_CANCELLED)
-                       return ret;
-
-               old = cancel;
-               cancel = cmpxchg(&kiocb->ki_cancel, old, KIOCB_CANCELLED);
-       } while (cancel != old);
-
-       atomic_inc(&kiocb->ki_users);
-       spin_unlock_irq(&ctx->ctx_lock);
+       kiocb_cancel_fn *cancel;
 
-       ret = cancel(kiocb);
+       cancel = xchg(&req->ki_cancel, KIOCB_CANCELLED);
+       if (cancel && cancel != KIOCB_CANCELLED) {
+               atomic_inc(&req->ki_users);
+               spin_unlock_irq(&ctx->ctx_lock);
 
-       spin_lock_irq(&ctx->ctx_lock);
-       aio_put_req(kiocb);
+               cancel(req);
 
-       return ret;
+               spin_lock_irq(&ctx->ctx_lock);
+               aio_put_req(req);
+       }
 }
 
 static void free_ioctx_rcu(struct rcu_head *head)
@@ -1126,6 +1112,10 @@ rw_common:
 
                req->ki_nbytes = ret;
 
+               spin_lock_irq(&req->ki_ctx->ctx_lock);
+               list_add(&req->ki_list, &req->ki_ctx->active_reqs);
+               spin_unlock_irq(&req->ki_ctx->ctx_lock);
+
                /* XXX: move/kill - rw_verify_area()? */
                /* This matches the pread()/pwrite() logic */
                if (req->ki_pos < 0) {
@@ -1141,6 +1131,10 @@ rw_common:
                if (!file->f_op->aio_fsync)
                        return -EINVAL;
 
+               spin_lock_irq(&req->ki_ctx->ctx_lock);
+               list_add(&req->ki_list, &req->ki_ctx->active_reqs);
+               spin_unlock_irq(&req->ki_ctx->ctx_lock);
+
                ret = file->f_op->aio_fsync(req, 1);
                break;
 
@@ -1148,6 +1142,10 @@ rw_common:
                if (!file->f_op->aio_fsync)
                        return -EINVAL;
 
+               spin_lock_irq(&req->ki_ctx->ctx_lock);
+               list_add(&req->ki_list, &req->ki_ctx->active_reqs);
+               spin_unlock_irq(&req->ki_ctx->ctx_lock);
+
                ret = file->f_op->aio_fsync(req, 0);
                break;
 
@@ -1363,14 +1361,8 @@ SYSCALL_DEFINE3(io_cancel, aio_context_t, ctx_id, struct 
iocb __user *, iocb,
        spin_lock_irq(&ctx->ctx_lock);
 
        kiocb = lookup_kiocb(ctx, iocb, key);
-       if (kiocb)
-               ret = kiocb_cancel(ctx, kiocb);
-       else
-               ret = -EINVAL;
-
-       spin_unlock_irq(&ctx->ctx_lock);
-
-       if (!ret) {
+       if (kiocb) {
+               kiocb_cancel(ctx, kiocb);
                /*
                 * The result argument is no longer used - the io_event is
                 * always delivered via the ring buffer. -EINPROGRESS indicates
@@ -1379,6 +1371,8 @@ SYSCALL_DEFINE3(io_cancel, aio_context_t, ctx_id, struct 
iocb __user *, iocb,
                ret = -EINPROGRESS;
        }
 
+       spin_unlock_irq(&ctx->ctx_lock);
+
        put_ioctx(ctx);
 
        return ret;
diff --git a/include/linux/aio.h b/include/linux/aio.h
index 7340f77..d9686f1 100644
--- a/include/linux/aio.h
+++ b/include/linux/aio.h
@@ -65,6 +65,11 @@ struct kiocb {
        struct eventfd_ctx      *ki_eventfd;
 };
 
+static inline bool kiocb_cancelled(struct kiocb *kiocb)
+{
+       return kiocb->ki_cancel == KIOCB_CANCELLED;
+}
+
 static inline bool is_sync_kiocb(struct kiocb *kiocb)
 {
        return kiocb->ki_ctx == NULL;
-- 
1.7.12

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to