diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2007-01-17 02:28:48 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-02-07 18:44:39 -0500 |
commit | 49631ca7f3e2fd05186028b453fa27f75b830de7 (patch) | |
tree | b8fb89f0ef0a32c94c259d0fc6ab9bc40a828419 /drivers | |
parent | ce46794f77f698eaf3b80922fafac5a9379085e0 (diff) |
USB: gadgetfs AIO tweaks
This patch (as837) fixes several mistakes in the AIO interface of the
gadgetfs driver:
The ki_retry method is not supposed to do a put on the kiocb.
The extra call to aio_put_req() causes memory corruption.
(Note: This call was removed before, by patch as691, and then
mysteriously re-introduced later.)
Even if a read transfer is cancelled, we can and should send
to the user all the data that did manage to get transferred.
Testing for AIO cancellation in the I/O completion handler
is both racy and (now) unnecessary. aio_complete() does its
own checking, in a safe manner.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/gadget/inode.c | 16 |
1 files changed, 7 insertions, 9 deletions
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index 1c5e1ee7e36b..34296e79edcf 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c | |||
@@ -576,7 +576,6 @@ static ssize_t ep_aio_read_retry(struct kiocb *iocb) | |||
576 | } | 576 | } |
577 | kfree(priv->buf); | 577 | kfree(priv->buf); |
578 | kfree(priv); | 578 | kfree(priv); |
579 | aio_put_req(iocb); | ||
580 | return len; | 579 | return len; |
581 | } | 580 | } |
582 | 581 | ||
@@ -590,18 +589,17 @@ static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req) | |||
590 | spin_lock(&epdata->dev->lock); | 589 | spin_lock(&epdata->dev->lock); |
591 | priv->req = NULL; | 590 | priv->req = NULL; |
592 | priv->epdata = NULL; | 591 | priv->epdata = NULL; |
593 | if (priv->iv == NULL | 592 | |
594 | || unlikely(req->actual == 0) | 593 | /* if this was a write or a read returning no data then we |
595 | || unlikely(kiocbIsCancelled(iocb))) { | 594 | * don't need to copy anything to userspace, so we can |
595 | * complete the aio request immediately. | ||
596 | */ | ||
597 | if (priv->iv == NULL || unlikely(req->actual == 0)) { | ||
596 | kfree(req->buf); | 598 | kfree(req->buf); |
597 | kfree(priv); | 599 | kfree(priv); |
598 | iocb->private = NULL; | 600 | iocb->private = NULL; |
599 | /* aio_complete() reports bytes-transferred _and_ faults */ | 601 | /* aio_complete() reports bytes-transferred _and_ faults */ |
600 | if (unlikely(kiocbIsCancelled(iocb))) | 602 | aio_complete(iocb, req->actual ? req->actual : req->status, |
601 | aio_put_req(iocb); | ||
602 | else | ||
603 | aio_complete(iocb, | ||
604 | req->actual ? req->actual : req->status, | ||
605 | req->status); | 603 | req->status); |
606 | } else { | 604 | } else { |
607 | /* retry() won't report both; so we hide some faults */ | 605 | /* retry() won't report both; so we hide some faults */ |