diff options
| author | Benjamin LaHaise <bcrl@kvack.org> | 2005-06-23 03:10:27 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-23 12:45:34 -0400 |
| commit | 63e6880918e75dcb92d60aff218a76e063a471ef (patch) | |
| tree | 059a00899bdf96b255e2b60d6cf91968a9af485a | |
| parent | 4452ea509e29df2f019bed2f7a1e0f5eea092b26 (diff) | |
[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>
| -rw-r--r-- | fs/read_write.c | 20 |
1 files changed, 18 insertions, 2 deletions
diff --git a/fs/read_write.c b/fs/read_write.c index c4c2bee373ed..9292f5fa4d62 100644 --- a/fs/read_write.c +++ b/fs/read_write.c | |||
| @@ -203,6 +203,16 @@ Einval: | |||
| 203 | return -EINVAL; | 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 | ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos) | 216 | ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos) |
| 207 | { | 217 | { |
| 208 | struct kiocb kiocb; | 218 | struct kiocb kiocb; |
| @@ -210,7 +220,10 @@ ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *pp | |||
| 210 | 220 | ||
| 211 | init_sync_kiocb(&kiocb, filp); | 221 | init_sync_kiocb(&kiocb, filp); |
| 212 | kiocb.ki_pos = *ppos; | 222 | kiocb.ki_pos = *ppos; |
| 213 | ret = filp->f_op->aio_read(&kiocb, buf, len, kiocb.ki_pos); | 223 | while (-EIOCBRETRY == |
| 224 | (ret = filp->f_op->aio_read(&kiocb, buf, len, kiocb.ki_pos))) | ||
| 225 | wait_on_retry_sync_kiocb(&kiocb); | ||
| 226 | |||
| 214 | if (-EIOCBQUEUED == ret) | 227 | if (-EIOCBQUEUED == ret) |
| 215 | ret = wait_on_sync_kiocb(&kiocb); | 228 | ret = wait_on_sync_kiocb(&kiocb); |
| 216 | *ppos = kiocb.ki_pos; | 229 | *ppos = kiocb.ki_pos; |
| @@ -258,7 +271,10 @@ ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, lof | |||
| 258 | 271 | ||
| 259 | init_sync_kiocb(&kiocb, filp); | 272 | init_sync_kiocb(&kiocb, filp); |
| 260 | kiocb.ki_pos = *ppos; | 273 | kiocb.ki_pos = *ppos; |
| 261 | ret = filp->f_op->aio_write(&kiocb, buf, len, kiocb.ki_pos); | 274 | while (-EIOCBRETRY == |
| 275 | (ret = filp->f_op->aio_write(&kiocb, buf, len, kiocb.ki_pos))) | ||
| 276 | wait_on_retry_sync_kiocb(&kiocb); | ||
| 277 | |||
| 262 | if (-EIOCBQUEUED == ret) | 278 | if (-EIOCBQUEUED == ret) |
| 263 | ret = wait_on_sync_kiocb(&kiocb); | 279 | ret = wait_on_sync_kiocb(&kiocb); |
| 264 | *ppos = kiocb.ki_pos; | 280 | *ppos = kiocb.ki_pos; |
