Previous patch got rid of kiocb->ki_users; this was done by having kiocb_cancel()/aio_complete() explicitly synchronize with each other. The new rule is that when a driver calls aio_complete(), after aio_complete() returns ki_cancel cannot be running and it's safe to dispose of kiocb->priv. But, this means ki_cancel() won't be able to call aio_complete() itself, or aio_complete() will deadlock. So, update the driver. Signed-off-by: Kent Overstreet <koverstreet@xxxxxxxxxx> Cc: Zach Brown <zab@xxxxxxxxxx> Cc: Felipe Balbi <balbi@xxxxxx> Cc: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> Cc: Mark Fasheh <mfasheh@xxxxxxxx> Cc: Joel Becker <jlbec@xxxxxxxxxxxx> Cc: Rusty Russell <rusty@xxxxxxxxxxxxxxx> Cc: Jens Axboe <axboe@xxxxxxxxx> Cc: Asai Thambi S P <asamymuthupa@xxxxxxxxxx> Cc: Selvan Mani <smani@xxxxxxxxxx> Cc: Sam Bradshaw <sbradshaw@xxxxxxxxxx> Cc: Jeff Moyer <jmoyer@xxxxxxxxxx> Cc: Al Viro <viro@xxxxxxxxxxxxxxxxxx> Cc: Benjamin LaHaise <bcrl@xxxxxxxxx> --- drivers/usb/gadget/inode.c | 61 +++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 33 deletions(-) diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index f255ad7..69adb87 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c @@ -522,6 +522,7 @@ struct kiocb_priv { const struct iovec *iv; unsigned long nr_segs; unsigned actual; + int status; }; static int ep_aio_cancel(struct kiocb *iocb) @@ -577,14 +578,26 @@ static void ep_user_copy_worker(struct work_struct *work) struct kiocb_priv *priv = container_of(work, struct kiocb_priv, work); struct mm_struct *mm = priv->mm; struct kiocb *iocb = priv->iocb; - size_t ret; - use_mm(mm); - ret = ep_copy_to_user(priv); - unuse_mm(mm); + if (priv->iv && priv->actual) { + size_t ret; + + use_mm(mm); + ret = ep_copy_to_user(priv); + unuse_mm(mm); + + if (!priv->status) + priv->status = ret; + /* + * completing the iocb can drop the ctx and mm, don't touch mm + * after + */ + } - /* completing the iocb can drop the ctx and mm, don't touch mm after */ - aio_complete(iocb, ret, ret); + + /* aio_complete() reports bytes-transferred _and_ faults */ + aio_complete(iocb, priv->actual ? priv->actual : priv->status, + priv->status); kfree(priv->buf); kfree(priv); @@ -596,36 +609,18 @@ static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req) struct kiocb_priv *priv = iocb->private; struct ep_data *epdata = priv->epdata; - /* lock against disconnect (and ideally, cancel) */ - spin_lock(&epdata->dev->lock); - priv->req = NULL; - priv->epdata = NULL; - - /* if this was a write or a read returning no data then we - * don't need to copy anything to userspace, so we can - * complete the aio request immediately. - */ - if (priv->iv == NULL || unlikely(req->actual == 0)) { - kfree(req->buf); - kfree(priv); - iocb->private = NULL; - /* aio_complete() reports bytes-transferred _and_ faults */ - aio_complete(iocb, req->actual ? req->actual : req->status, - req->status); - } else { - /* ep_copy_to_user() won't report both; we hide some faults */ - if (unlikely(0 != req->status)) - DBG(epdata->dev, "%s fault %d len %d\n", - ep->name, req->status, req->actual); - - priv->buf = req->buf; - priv->actual = req->actual; - schedule_work(&priv->work); - } - spin_unlock(&epdata->dev->lock); + priv->buf = req->buf; + priv->actual = req->actual; + priv->status = req->status; usb_ep_free_request(ep, req); put_ep(epdata); + + if ((priv->iv && priv->actual) || + iocb->ki_cancel == KIOCB_CANCELLING) + schedule_work(&priv->work); + else + ep_user_copy_worker(&priv->work); } static ssize_t -- 1.8.2.1 -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html