On Mon, 15 Jan 2007, David Brownell wrote: > On Friday 12 January 2007 2:12 pm, Alan Stern wrote: > > > On the other hand, I did find (another) bug in the async I/O handling in > > inode.c. If you aren't using the AIO code in usb.c then it shouldn't > > affect you, but you might want to give it a try anyway. > > Alan, could you explain what the bug here is? ISTR that the policy > for those retry routines is to always put the request. I know that > you removed that some time ago, and that it re-appeared with a recent > update to change the AIO interface ... but the original code had no > leaks, and this change seems likely to create one.
On the contrary, this isn't a leak (i.e., permanent loss of memory caused by failure to release a reference). Just the opposite -- it is memory corruption caused by decrementing a refcount inappropriately and thus allowing a data structure to be freed while it is still in use. I really have no idea what has changed and what hasn't. Looking through some old kernel trees, it's apparent that the ep_aio_read_retry() did change between 2.6.18 and 2.6.19, reintroducing the aio_put_req() call and thereby reverting the earlier bugfix. That's a pity; I don't enjoy finding & fixing refcount bugs, and I enjoy even less having to fix the same bug twice. > (Unless the AIO > core changed incompatibly ... but I'd have expected that the person > who updated this code to reflect the "new" API would get that right.) I also can't explain the AIO policy/interface/API -- because as far as I can tell, it is completely undocumented! There's nothing to go by except the source code for the AIO core. Here are the relevant extracts from fs/aio.c: static int __aio_run_iocbs(struct kioctx *ctx) { ... while (!list_empty(&run_list)) { iocb = list_entry(run_list.next, struct kiocb, ki_run_list); list_del(&iocb->ki_run_list); /* * Hold an extra reference while retrying i/o. */ iocb->ki_users++; /* grab extra reference */ aio_run_iocb(iocb); if (__aio_put_req(ctx, iocb)) /* drop extra ref */ put_ioctx(ctx); } ... } So the core acquires and releases its own reference around the call of the ki_wait method. static ssize_t aio_run_iocb(struct kiocb *iocb) { ... if (!(retry = iocb->ki_retry)) { printk("aio_run_iocb: iocb->ki_retry = NULL\n"); return 0; } ... BUG_ON(current->io_wait != NULL); current->io_wait = &iocb->ki_wait; ret = retry(iocb); current->io_wait = NULL; if (ret != -EIOCBRETRY && ret != -EIOCBQUEUED) { BUG_ON(!list_empty(&iocb->ki_wait.task_list)); aio_complete(iocb, ret, 0); } ... } So the core does not expect the ki_retry method to change iocb's refcount. Alan Stern ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys - and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV _______________________________________________ linux-usb-devel@lists.sourceforge.net To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel