diff options
Diffstat (limited to 'fs')
-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; |