[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:
Badari Pulavarty 2006-09-30 23:28:46 -07:00 • committed by Linus Torvalds
commit 027445c372
22 changed files with 242 additions and 191 deletions

View file

@ -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);
}
/*----------------------------------------------------------------------*/