On Wednesday 28 April 2010 22:31:49 Andrew Morton wrote:
I've written the driver code which implements a zero-copy DMA char device. It
has aio_read() and aio_write() methods which return -EIOCBQUEUED after the
successful preparation of the buffers described by kiocb and posting it to the
descriptor chain. When the descriptors are processed, the DMA engine raises
the interrupt and the cleanup work is done in the handler, including
aio_complete() for the completed kiocbs.
This works fine, however, there is a problem with canceling the queued
requests, espesially on io_destroy() syscall. Since there is no simple way to
remove single kiocb from the descriptor chain, I'm removing all of them from
the queue using aio_complete() or aio_put_req() in the ki_cancel() callback
routine of my driver. The main problem is the reference counting in
aio_cancel_all():
if (cancel) {
iocb->ki_users++;
spin_unlock_irq(&ctx->ctx_lock);
cancel(iocb, &res);
spin_lock_irq(&ctx->ctx_lock);
}
Here the iocb->ki_users gets incremented which already has the value 1 at this
point (after the io_submit_one() completion) and it's never released (). So I
have to call aio_put_req() twice for the given kiocb (this seems to be the
hack to me) or I'll end up with the unkillable process stuck in
wait_for_all_aios() at the io_schedule(). I've posted the patches where I've
added aio_put_req() but I think it needs more testing. So, I've tried another
approach (hack) - requeue the kiocb with kick_iocb() before calling
aio_put_req() in the ki_cancel() callback (that's because aio_run_iocb() takes
some special actions for the canceled kiocbs). And I've found out that
kick_iocb() fails because aio_run_iocb() does this:
iocb->ki_run_list.next = iocb->ki_run_list.prev = NULL;
and only reinitializes iocb->ki_run_list when iocb->ki_retry() returns
-EIOCBRETRY but kick_iocb() is exported and looks like intended for usage
(though not recommended).
The only place where I've found the similar approach to AIO in the device
driver is drivers/usb/gadget/inode.c.
Sorry, I've forgotten this.
Signed-off-by: Sergey Temerkhanov <temerkhanov@cifronik.ru>
Regards, Sergey Temerkhanov,
Cifronic ZAO
--