|
@@ -203,6 +203,16 @@ Einval:
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
+static void wait_on_retry_sync_kiocb(struct kiocb *iocb)
|
|
|
+{
|
|
|
+ set_current_state(TASK_UNINTERRUPTIBLE);
|
|
|
+ if (!kiocbIsKicked(iocb))
|
|
|
+ schedule();
|
|
|
+ else
|
|
|
+ kiocbClearKicked(iocb);
|
|
|
+ __set_current_state(TASK_RUNNING);
|
|
|
+}
|
|
|
+
|
|
|
ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
|
|
|
{
|
|
|
struct kiocb kiocb;
|
|
@@ -210,7 +220,10 @@ ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *pp
|
|
|
|
|
|
init_sync_kiocb(&kiocb, filp);
|
|
|
kiocb.ki_pos = *ppos;
|
|
|
- ret = filp->f_op->aio_read(&kiocb, buf, len, kiocb.ki_pos);
|
|
|
+ while (-EIOCBRETRY ==
|
|
|
+ (ret = filp->f_op->aio_read(&kiocb, buf, len, kiocb.ki_pos)))
|
|
|
+ wait_on_retry_sync_kiocb(&kiocb);
|
|
|
+
|
|
|
if (-EIOCBQUEUED == ret)
|
|
|
ret = wait_on_sync_kiocb(&kiocb);
|
|
|
*ppos = kiocb.ki_pos;
|
|
@@ -258,7 +271,10 @@ ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, lof
|
|
|
|
|
|
init_sync_kiocb(&kiocb, filp);
|
|
|
kiocb.ki_pos = *ppos;
|
|
|
- ret = filp->f_op->aio_write(&kiocb, buf, len, kiocb.ki_pos);
|
|
|
+ while (-EIOCBRETRY ==
|
|
|
+ (ret = filp->f_op->aio_write(&kiocb, buf, len, kiocb.ki_pos)))
|
|
|
+ wait_on_retry_sync_kiocb(&kiocb);
|
|
|
+
|
|
|
if (-EIOCBQUEUED == ret)
|
|
|
ret = wait_on_sync_kiocb(&kiocb);
|
|
|
*ppos = kiocb.ki_pos;
|