[AIO] fix sync iocb use of retry mechanism When the sync infrastructure is used to run a retry using read/write, we need to correctly use the buffer offset and byte counts from the iocb on subsequent calls to the aio method. Signed-off-by: Benjamin LaHaise diff -purN --exclude=description 57_intr_cancel/fs/aio.c 59_fix_sync_iocbs/fs/aio.c --- 57_intr_cancel/fs/aio.c 2005-08-08 17:15:41.000000000 -0400 +++ 59_fix_sync_iocbs/fs/aio.c 2005-08-08 17:15:47.000000000 -0400 @@ -1319,7 +1319,7 @@ asmlinkage long sys_io_destroy(aio_conte * Default retry method for aio_read (also used for first time submit) * Responsible for updating iocb state as retries progress */ -static ssize_t aio_pread(struct kiocb *iocb) +ssize_t aio_pread(struct kiocb *iocb) { struct file *file = iocb->ki_filp; struct address_space *mapping = file->f_mapping; @@ -1358,7 +1358,7 @@ static ssize_t aio_pread(struct kiocb *i * Default retry method for aio_write (also used for first time submit) * Responsible for updating iocb state as retries progress */ -static ssize_t aio_pwrite(struct kiocb *iocb) +ssize_t aio_pwrite(struct kiocb *iocb) { struct file *file = iocb->ki_filp; ssize_t ret = 0; diff -purN --exclude=description 57_intr_cancel/fs/read_write.c 59_fix_sync_iocbs/fs/read_write.c --- 57_intr_cancel/fs/read_write.c 2005-08-08 17:15:45.000000000 -0400 +++ 59_fix_sync_iocbs/fs/read_write.c 2005-08-08 17:15:47.000000000 -0400 @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -205,7 +206,7 @@ Einval: static long wait_on_retry_sync_kiocb(struct kiocb *iocb) { - long (*cancel)(struct kiocb *, struct io_event *); + int (*cancel)(struct kiocb *, struct io_event *); long ret = 0; set_current_state(kiocbIsIntr(iocb) ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); @@ -217,17 +218,20 @@ static long wait_on_retry_sync_kiocb(str /* If we were interrupted by a signal, issue a cancel to allow the * operation to clean up. */ - cancel = iocb->ki_cancel; - if (kiocbIsIntr(iocb) && signal_pending(current) && cancel) { + if (kiocbIsIntr(iocb) && signal_pending(current) && + (cancel = iocb->ki_cancel)) { struct io_event dummy_event; dummy_event.res = 0; if (!cancel(iocb, &dummy_event)) { ret = dummy_event.res; if (!ret) printk(KERN_DEBUG "wait_on_retry_sync_kiocb: ki_cancel method %p is buggy\n", cancel); + goto out; } } kiocbClearIntr(iocb); + ret = iocb->ki_retry(iocb); +out: __set_current_state(TASK_RUNNING); return ret; } @@ -239,15 +243,14 @@ ssize_t do_sync_read(struct file *filp, init_sync_kiocb(&kiocb, filp); kiocb.ki_pos = *ppos; - while (-EIOCBRETRY == - (ret = filp->f_op->aio_read(&kiocb, buf, len, kiocb.ki_pos))) { + kiocb.ki_retry = aio_pread; + kiocb.ki_buf = buf; + kiocb.ki_nbytes = len; + kiocb.ki_left = len; + ret = filp->f_op->aio_read(&kiocb, buf, len, *ppos); + while (ret == -EIOCBRETRY) ret = wait_on_retry_sync_kiocb(&kiocb); - if (ret) - break; - } - if (-EIOCBQUEUED == ret) - ret = wait_on_sync_kiocb(&kiocb); BUG_ON(!list_empty(&kiocb.ki_wait.task_list)); *ppos = kiocb.ki_pos; return ret; @@ -294,15 +297,14 @@ ssize_t do_sync_write(struct file *filp, init_sync_kiocb(&kiocb, filp); kiocb.ki_pos = *ppos; - while (-EIOCBRETRY == - (ret = filp->f_op->aio_write(&kiocb, buf, len, kiocb.ki_pos))) { + kiocb.ki_retry = aio_pwrite; + kiocb.ki_buf = (void *)buf; + kiocb.ki_nbytes = len; + kiocb.ki_left = len; + ret = filp->f_op->aio_write(&kiocb, buf, len, kiocb.ki_pos); + while (ret == -EIOCBRETRY) ret = wait_on_retry_sync_kiocb(&kiocb); - if (ret) - break; - } - if (-EIOCBQUEUED == ret) - ret = wait_on_sync_kiocb(&kiocb); BUG_ON(!list_empty(&kiocb.ki_wait.task_list)); *ppos = kiocb.ki_pos; return ret; diff -purN --exclude=description 57_intr_cancel/include/linux/aio.h 59_fix_sync_iocbs/include/linux/aio.h --- 57_intr_cancel/include/linux/aio.h 2005-08-08 17:15:42.000000000 -0400 +++ 59_fix_sync_iocbs/include/linux/aio.h 2005-08-08 17:15:47.000000000 -0400 @@ -169,6 +169,8 @@ extern void FASTCALL(exit_aio(struct mm_ extern struct kioctx *lookup_ioctx(unsigned long ctx_id); extern int FASTCALL(io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, struct iocb *iocb)); +extern ssize_t aio_pread(struct kiocb *iocb); +extern ssize_t aio_pwrite(struct kiocb *iocb); /* semi private, but used by the 32bit emulations: */ struct kioctx *lookup_ioctx(unsigned long ctx_id);