Hi,
I am trying to collapse all the vectored and AIO operations
to a single set of file-operations. My initial posting, is
available here:
http://marc.theaimsgroup.com/?l=linux-kernel&m=113889673116697&w=2
As part of this work, I changed aio_read()/aio_write()
methods to take a vector, so I can drop readv/writev methods.
I was trying to fix usb/gadget/inode.c ep_aio_read()/ep_aio_write()
to support vector. I am hoping some one can help me, since I
don't understand the code well enough :(
For my first (dumb) pass, I just loop through all the vectors.
Does this look right ? Does vectorizing these makes sense at all ?
Please let me know, how this can be optimized. (BTW, I just included
only usb/gadget related patch here - if some one wants to see the whole
thing, I can post it here).
Thanks,
Badari
===================================================================
--- linux-2.6.16-rc1.quilt.orig/Documentation/filesystems/vfs.txt 2006-02-01 16:36:55.000000000 -0800
+++ linux-2.6.16-rc1.quilt/Documentation/filesystems/vfs.txt 2006-02-01 16:38:14.000000000 -0800
@@ -526,9 +526,9 @@
struct file_operations {
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
- ssize_t (*aio_read) (struct kiocb *, char __user *, size_t, loff_t);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
- ssize_t (*aio_write) (struct kiocb *, const char __user *, size_t, loff_t);
+ ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
+ ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
int (*readdir) (struct file *, void *, filldir_t);
unsigned int (*poll) (struct file *, struct poll_table_struct *);
int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
Index: linux-2.6.16-rc1.quilt/drivers/usb/gadget/inode.c
===================================================================
--- linux-2.6.16-rc1.quilt.orig/drivers/usb/gadget/inode.c 2006-02-01 16:16:50.000000000 -0800
+++ linux-2.6.16-rc1.quilt/drivers/usb/gadget/inode.c 2006-02-02 16:37:46.000000000 -0800
@@ -675,36 +675,60 @@
}
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 *iv,
+ unsigned long count, loff_t o)
{
struct ep_data *epdata = iocb->ki_filp->private_data;
char *buf;
+ size_t len;
+ int i = 0;
+ ssize_t ret;
if (unlikely(epdata->desc.bEndpointAddress & USB_DIR_IN))
return -EINVAL;
- buf = kmalloc(len, GFP_KERNEL);
- if (unlikely(!buf))
- return -ENOMEM;
- iocb->ki_retry = ep_aio_read_retry;
- return ep_aio_rwtail(iocb, buf, len, epdata, ubuf);
+
+ while (i++ < count) {
+ len = iv->iov_len;
+ buf = kmalloc(len, GFP_KERNEL);
+ if (unlikely(!buf))
+ return -ENOMEM;
+ iocb->ki_retry = ep_aio_read_retry;
+ ret = ep_aio_rwtail(iocb, buf, len, epdata, iv->iov_base);
+ if ((ret < 0) && (ret != -EIOCBQUEUED))
+ break;
+ iv++;
+ }
+ return ret;
}
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 *iv,
+ unsigned long count, loff_t o)
{
struct ep_data *epdata = iocb->ki_filp->private_data;
char *buf;
+ size_t len;
+ int i = 0;
+ ssize_t ret;
if (unlikely(!(epdata->desc.bEndpointAddress & USB_DIR_IN)))
return -EINVAL;
- buf = kmalloc(len, GFP_KERNEL);
- if (unlikely(!buf))
- return -ENOMEM;
- if (unlikely(copy_from_user(buf, ubuf, len) != 0)) {
- kfree(buf);
- return -EFAULT;
+
+ while (i++ < count) {
+ len = iv->iov_len;
+ buf = kmalloc(len, GFP_KERNEL);
+ if (unlikely(!buf))
+ return -ENOMEM;
+ if (unlikely(copy_from_user(buf, iv->iov_base, len) != 0)) {
+ kfree(buf);
+ return -EFAULT;
+ }
+ ret = ep_aio_rwtail(iocb, buf, len, epdata, NULL);
+ if ((ret < 0) && (ret != -EIOCBQUEUED))
+ break;
+ iv++;
}
- return ep_aio_rwtail(iocb, buf, len, epdata, NULL);
+ return ret;
}
/*----------------------------------------------------------------------*/