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