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; |