[AIO] move aio_put_req() for cancellation into sys_io_cancel Cancellation of kiocbs should do the reference counting in the higher layer to avoid module unload races. Fix this by putting the aio_put_req() calls into the higher layer cancellation code. Also, kiocbSetCancelled() is already done by the higher level aio code and does not need to be done within the ki_cancel method. Signed-off-by: Benjamin LaHaise diff -purN --exclude=description 30_aio_write/drivers/usb/gadget/inode.c 35_cancel_aio_put_req/drivers/usb/gadget/inode.c --- 30_aio_write/drivers/usb/gadget/inode.c 2005-08-04 15:55:46.000000000 -0400 +++ 35_cancel_aio_put_req/drivers/usb/gadget/inode.c 2005-08-08 17:15:34.000000000 -0400 @@ -540,7 +540,6 @@ static int ep_aio_cancel(struct kiocb *i local_irq_disable(); epdata = priv->epdata; // spin_lock(&epdata->dev->lock); - kiocbSetCancelled(iocb); if (likely(epdata && epdata->ep && priv->req)) value = usb_ep_dequeue (epdata->ep, priv->req); else @@ -548,7 +547,6 @@ static int ep_aio_cancel(struct kiocb *i // spin_unlock(&epdata->dev->lock); local_irq_enable(); - aio_put_req(iocb); return value; } @@ -586,10 +584,7 @@ static void ep_aio_complete(struct usb_e kfree(priv); iocb->private = NULL; /* aio_complete() reports bytes-transferred _and_ faults */ - if (unlikely(kiocbIsCancelled(iocb))) - aio_put_req(iocb); - else - aio_complete(iocb, + aio_complete(iocb, req->actual ? req->actual : req->status, req->status); } else { diff -purN --exclude=description 30_aio_write/fs/aio.c 35_cancel_aio_put_req/fs/aio.c --- 30_aio_write/fs/aio.c 2005-08-04 15:55:50.000000000 -0400 +++ 35_cancel_aio_put_req/fs/aio.c 2005-08-08 17:15:34.000000000 -0400 @@ -1668,6 +1668,12 @@ asmlinkage long sys_io_cancel(aio_contex if (copy_to_user(result, &tmp, sizeof(tmp))) ret = -EFAULT; } + /* If the cancellation was successful, we must discard the + * reference held for completion of the iocb. + */ + if (!ret) + aio_put_req(kiocb); + aio_put_req(kiocb); } else printk(KERN_DEBUG "iocb has no cancel operation\n");