Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 63e68809 authored by Benjamin LaHaise's avatar Benjamin LaHaise Committed by Linus Torvalds
Browse files

[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: default avatarBenjamin LaHaise <benjamin.c.lahaise@intel.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 4452ea50
Loading
Loading
Loading
Loading
+18 −2
Original line number Diff line number Diff line
@@ -203,6 +203,16 @@ int rw_verify_area(int read_write, struct file *file, loff_t *ppos, size_t count
	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;