I have added support for AIO in my driver (the .aio_read , .aio_write calls in kernelland, libaio in userland) and looking at various sources I cannot find if in my aio_read, .aio_write calls I can just store a pointer to the iovector argument (in the assumption that this memory will remain untouched till after eg aio_complete is called), or that I need to deep copy over the iovector data structures.
static ssize_t aio_read( struct kiocb *iocb, const struct iovec *iovec, unsigned long nr_segs, loff_t pos );
static ssize_t aio_write( struct kiocb *iocb, const struct iovec *iovec, unsigned long nr_segs, loff_t pos );
Looking at the implementation of \drivers\usb\gadget\inode.c as an example, it seems they just copy the pointer in the ep_aio_rwtail function which has:
priv->iv = iv;
But when I try doing something similar it very regularly happens the data in the iovector has been "corrupted" by the time I process it.
Eg in the aio_read/write calls I log
iovector located at addr:0xbf1ebf04
segment 0: base: 0x76dbb468 len:512
But then when I do the real work in a kernel thread (after attaching to the user space mm) I logged the following:
iovector located at addr:0xbf1ebf04
segment 0: base: 0x804e00c8 len:-1088503900
This is with a very simple test case where I only submit 1 asynchronous command in my user application.
To make things more interesting: I have the corruption about 80% of the time on a 3.13 kernel.
But I never saw it before on a 3.9 kernel (but I only used it for a short while before I upgraded to 3.13, and now reverted back as a sanity cnheck and tried a dozen times or so). ( An example run with a 3.9 kernel has twice
iovector located at addr:0xbf9ee054
segment 0: base: 0x76e28468 len:512)
Does this ring any bells ?
(The other possibility is that I am corrupting these addresses/lengths myself of course, but it is strange that I never had this with a 3.9)
EDIT: To answer my own question after reviewing the 3.13 code for linux aio (which has changed significantly wrt the 3.9 that was working), in fs\aio.c you have:
static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode,
char __user *buf, bool compat)
{
...
struct iovec inline_vec, *iovec = &inline_vec;
...
ret = rw_op(req, iovec, nr_segs, req->ki_pos);
...
}
So this iovec structure is just on stack, and it will be lost as soon as the aio_read/write function exits.
And the gadget framework contains a bug (at least for 3.13) in \drivers\usb\gadget\inode.c...