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

Commit bc8a309e authored by Weston Andros Adamson's avatar Weston Andros Adamson Committed by Trond Myklebust
Browse files

nfs: fix nonblocking calls to nfs_page_group_lock



nfs_page_group_lock was calling wait_on_bit_lock even when told not to
block. Fix by first trying test_and_set_bit, followed by wait_on_bit_lock
if and only if blocking is allowed.  Return -EAGAIN if nonblocking and the
test_and_set of the bit was already locked.

Signed-off-by: default avatarWeston Andros Adamson <dros@primarydata.com>
Reviewed-by: default avatarPeng Tao <tao.peng@primarydata.com>
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
parent fd2f3a06
Loading
Loading
Loading
Loading
+13 −8
Original line number Diff line number Diff line
@@ -143,23 +143,28 @@ nfs_iocounter_wait(struct nfs_io_counter *c)
 *
 * this lock must be held if modifying the page group list
 *
 * returns result from wait_on_bit_lock: 0 on success, < 0 on error
 * return 0 on success, < 0 on error: -EDELAY if nonblocking or the
 * result from wait_on_bit_lock
 *
 * NOTE: calling with nonblock=false should always have set the
 *       lock bit (see fs/buffer.c and other uses of wait_on_bit_lock
 *       with TASK_UNINTERRUPTIBLE), so there is no need to check the result.
 */
int
nfs_page_group_lock(struct nfs_page *req, bool nonblock)
{
	struct nfs_page *head = req->wb_head;
	int ret;

	WARN_ON_ONCE(head != head->wb_head);

	do {
		ret = wait_on_bit_lock(&head->wb_flags, PG_HEADLOCK,
	if (!test_and_set_bit(PG_HEADLOCK, &head->wb_flags))
		return 0;

	if (!nonblock)
		return wait_on_bit_lock(&head->wb_flags, PG_HEADLOCK,
				TASK_UNINTERRUPTIBLE);
	} while (!nonblock && ret != 0);

	WARN_ON_ONCE(ret > 0);
	return ret;
	return -EAGAIN;
}

/*