Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] aio: fix do_sync_(read|write) to properly handle aio retries

When do_sync_(read|write) encounters an aio method that makes use of the
retry mechanism, they fail to correctly retry the operation. This fixes
that by adding the appropriate sleep and retry mechanism.

Signed-off-by: Benjamin LaHaise <benjamin.c.lahaise@intel.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Benjamin LaHaise and committed by
Linus Torvalds
63e68809 4452ea50

+18 -2
+18 -2
fs/read_write.c
··· 203 203 return -EINVAL; 204 204 } 205 205 206 + static void wait_on_retry_sync_kiocb(struct kiocb *iocb) 207 + { 208 + set_current_state(TASK_UNINTERRUPTIBLE); 209 + if (!kiocbIsKicked(iocb)) 210 + schedule(); 211 + else 212 + kiocbClearKicked(iocb); 213 + __set_current_state(TASK_RUNNING); 214 + } 215 + 206 216 ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos) 207 217 { 208 218 struct kiocb kiocb; ··· 220 210 221 211 init_sync_kiocb(&kiocb, filp); 222 212 kiocb.ki_pos = *ppos; 223 - ret = filp->f_op->aio_read(&kiocb, buf, len, kiocb.ki_pos); 213 + while (-EIOCBRETRY == 214 + (ret = filp->f_op->aio_read(&kiocb, buf, len, kiocb.ki_pos))) 215 + wait_on_retry_sync_kiocb(&kiocb); 216 + 224 217 if (-EIOCBQUEUED == ret) 225 218 ret = wait_on_sync_kiocb(&kiocb); 226 219 *ppos = kiocb.ki_pos; ··· 271 258 272 259 init_sync_kiocb(&kiocb, filp); 273 260 kiocb.ki_pos = *ppos; 274 - ret = filp->f_op->aio_write(&kiocb, buf, len, kiocb.ki_pos); 261 + while (-EIOCBRETRY == 262 + (ret = filp->f_op->aio_write(&kiocb, buf, len, kiocb.ki_pos))) 263 + wait_on_retry_sync_kiocb(&kiocb); 264 + 275 265 if (-EIOCBQUEUED == ret) 276 266 ret = wait_on_sync_kiocb(&kiocb); 277 267 *ppos = kiocb.ki_pos;