mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 11:11:45 -04:00
[PATCH] Vectorize aio_read/aio_write fileop methods
This patch vectorizes aio_read() and aio_write() methods to prepare for collapsing all aio & vectored operations into one interface - which is aio_read()/aio_write(). Signed-off-by: Badari Pulavarty <[email protected]> Signed-off-by: Christoph Hellwig <[email protected]> Cc: Michael Holzheu <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
This commit is contained in:
parent
9ea0f9499d
commit
027445c372
22 changed files with 242 additions and 191 deletions
|
|
@ -533,7 +533,8 @@ struct kiocb_priv {
|
|||
struct usb_request *req;
|
||||
struct ep_data *epdata;
|
||||
void *buf;
|
||||
char __user *ubuf; /* NULL for writes */
|
||||
const struct iovec *iv;
|
||||
unsigned long nr_segs;
|
||||
unsigned actual;
|
||||
};
|
||||
|
||||
|
|
@ -561,17 +562,32 @@ static int ep_aio_cancel(struct kiocb *iocb, struct io_event *e)
|
|||
static ssize_t ep_aio_read_retry(struct kiocb *iocb)
|
||||
{
|
||||
struct kiocb_priv *priv = iocb->private;
|
||||
ssize_t status = priv->actual;
|
||||
ssize_t len, total;
|
||||
int i;
|
||||
|
||||
/* we "retry" to get the right mm context for this: */
|
||||
status = copy_to_user(priv->ubuf, priv->buf, priv->actual);
|
||||
if (unlikely(0 != status))
|
||||
status = -EFAULT;
|
||||
else
|
||||
status = priv->actual;
|
||||
kfree(priv->buf);
|
||||
kfree(priv);
|
||||
return status;
|
||||
/* we "retry" to get the right mm context for this: */
|
||||
|
||||
/* copy stuff into user buffers */
|
||||
total = priv->actual;
|
||||
len = 0;
|
||||
for (i=0; i < priv->nr_segs; i++) {
|
||||
ssize_t this = min((ssize_t)(priv->iv[i].iov_len), total);
|
||||
|
||||
if (copy_to_user(priv->iv[i].iov_base, priv->buf, this)) {
|
||||
if (len == 0)
|
||||
len = -EFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
total -= this;
|
||||
len += this;
|
||||
if (total == 0)
|
||||
break;
|
||||
}
|
||||
kfree(priv->buf);
|
||||
kfree(priv);
|
||||
aio_put_req(iocb);
|
||||
return len;
|
||||
}
|
||||
|
||||
static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req)
|
||||
|
|
@ -584,7 +600,7 @@ static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req)
|
|||
spin_lock(&epdata->dev->lock);
|
||||
priv->req = NULL;
|
||||
priv->epdata = NULL;
|
||||
if (priv->ubuf == NULL
|
||||
if (priv->iv == NULL
|
||||
|| unlikely(req->actual == 0)
|
||||
|| unlikely(kiocbIsCancelled(iocb))) {
|
||||
kfree(req->buf);
|
||||
|
|
@ -619,7 +635,8 @@ ep_aio_rwtail(
|
|||
char *buf,
|
||||
size_t len,
|
||||
struct ep_data *epdata,
|
||||
char __user *ubuf
|
||||
const struct iovec *iv,
|
||||
unsigned long nr_segs
|
||||
)
|
||||
{
|
||||
struct kiocb_priv *priv;
|
||||
|
|
@ -634,7 +651,8 @@ fail:
|
|||
return value;
|
||||
}
|
||||
iocb->private = priv;
|
||||
priv->ubuf = ubuf;
|
||||
priv->iv = iv;
|
||||
priv->nr_segs = nr_segs;
|
||||
|
||||
value = get_ready_ep(iocb->ki_filp->f_flags, epdata);
|
||||
if (unlikely(value < 0)) {
|
||||
|
|
@ -674,41 +692,53 @@ fail:
|
|||
kfree(priv);
|
||||
put_ep(epdata);
|
||||
} else
|
||||
value = (ubuf ? -EIOCBRETRY : -EIOCBQUEUED);
|
||||
value = (iv ? -EIOCBRETRY : -EIOCBQUEUED);
|
||||
return value;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
ep_aio_read(struct kiocb *iocb, char __user *ubuf, size_t len, loff_t o)
|
||||
ep_aio_read(struct kiocb *iocb, const struct iovec *iov,
|
||||
unsigned long nr_segs, loff_t o)
|
||||
{
|
||||
struct ep_data *epdata = iocb->ki_filp->private_data;
|
||||
char *buf;
|
||||
|
||||
if (unlikely(epdata->desc.bEndpointAddress & USB_DIR_IN))
|
||||
return -EINVAL;
|
||||
buf = kmalloc(len, GFP_KERNEL);
|
||||
|
||||
buf = kmalloc(iocb->ki_left, GFP_KERNEL);
|
||||
if (unlikely(!buf))
|
||||
return -ENOMEM;
|
||||
|
||||
iocb->ki_retry = ep_aio_read_retry;
|
||||
return ep_aio_rwtail(iocb, buf, len, epdata, ubuf);
|
||||
return ep_aio_rwtail(iocb, buf, iocb->ki_left, epdata, iov, nr_segs);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
ep_aio_write(struct kiocb *iocb, const char __user *ubuf, size_t len, loff_t o)
|
||||
ep_aio_write(struct kiocb *iocb, const struct iovec *iov,
|
||||
unsigned long nr_segs, loff_t o)
|
||||
{
|
||||
struct ep_data *epdata = iocb->ki_filp->private_data;
|
||||
char *buf;
|
||||
size_t len = 0;
|
||||
int i = 0;
|
||||
|
||||
if (unlikely(!(epdata->desc.bEndpointAddress & USB_DIR_IN)))
|
||||
return -EINVAL;
|
||||
buf = kmalloc(len, GFP_KERNEL);
|
||||
|
||||
buf = kmalloc(iocb->ki_left, GFP_KERNEL);
|
||||
if (unlikely(!buf))
|
||||
return -ENOMEM;
|
||||
if (unlikely(copy_from_user(buf, ubuf, len) != 0)) {
|
||||
kfree(buf);
|
||||
return -EFAULT;
|
||||
|
||||
for (i=0; i < nr_segs; i++) {
|
||||
if (unlikely(copy_from_user(&buf[len], iov[i].iov_base,
|
||||
iov[i].iov_len) != 0)) {
|
||||
kfree(buf);
|
||||
return -EFAULT;
|
||||
}
|
||||
len += iov[i].iov_len;
|
||||
}
|
||||
return ep_aio_rwtail(iocb, buf, len, epdata, NULL);
|
||||
return ep_aio_rwtail(iocb, buf, len, epdata, NULL, 0);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
|
|
|||
Loading…
Reference in a new issue