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

Commit 06f814a3 authored by Trond Myklebust's avatar Trond Myklebust
Browse files

NFSv4: Make locku use the new RPC "wait on completion" interface.

parent 44c28873
Loading
Loading
Loading
Loading
+36 −29
Original line number Diff line number Diff line
@@ -206,6 +206,17 @@ static int nfs4_call_async(struct rpc_clnt *clnt,
	return 0;
}

static int nfs4_wait_for_completion_rpc_task(struct rpc_task *task)
{
	sigset_t oldset;
	int ret;

	rpc_clnt_sigmask(task->tk_client, &oldset);
	ret = rpc_wait_for_completion_task(task);
	rpc_clnt_sigunmask(task->tk_client, &oldset);
	return ret;
}

static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid, int open_flags)
{
	struct inode *inode = state->inode;
@@ -2867,31 +2878,23 @@ struct nfs4_unlockdata {
	struct nfs_lockres res;
	struct nfs4_lock_state *lsp;
	struct nfs_open_context *ctx;
	atomic_t refcount;
	struct completion completion;
};

static void nfs4_locku_release_calldata(struct nfs4_unlockdata *calldata)
static void nfs4_locku_release_calldata(void *data)
{
	if (atomic_dec_and_test(&calldata->refcount)) {
	struct nfs4_unlockdata *calldata = data;
	nfs_free_seqid(calldata->luargs.seqid);
	nfs4_put_lock_state(calldata->lsp);
	put_nfs_open_context(calldata->ctx);
	kfree(calldata);
}
}

static void nfs4_locku_complete(void *data)
{
	struct nfs4_unlockdata *calldata = data;
	complete(&calldata->completion);
	nfs4_locku_release_calldata(calldata);
}

static void nfs4_locku_done(struct rpc_task *task, void *data)
{
	struct nfs4_unlockdata *calldata = data;

	if (RPC_ASSASSINATED(task))
		return;
	nfs_increment_lock_seqid(task->tk_status, calldata->luargs.seqid);
	switch (task->tk_status) {
		case 0:
@@ -2935,7 +2938,7 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data)
static const struct rpc_call_ops nfs4_locku_ops = {
	.rpc_call_prepare = nfs4_locku_prepare,
	.rpc_call_done = nfs4_locku_done,
	.rpc_release = nfs4_locku_complete,
	.rpc_release = nfs4_locku_release_calldata,
};

static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request)
@@ -2944,26 +2947,28 @@ static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *
	struct inode *inode = state->inode;
	struct nfs_server *server = NFS_SERVER(inode);
	struct nfs4_lock_state *lsp;
	int status;
	struct rpc_task *task;
	int status = 0;

	/* Is this a delegated lock? */
	if (test_bit(NFS_DELEGATED_STATE, &state->flags))
		return do_vfs_lock(request->fl_file, request);
		goto out;

	status = nfs4_set_lock_state(state, request);
	if (status != 0)
		return status;
		goto out;
	lsp = request->fl_u.nfs4_fl.owner;
	/* We might have lost the locks! */
	if ((lsp->ls_flags & NFS_LOCK_INITIALIZED) == 0)
		return 0;
		goto out;
	status = -ENOMEM;
	calldata = kmalloc(sizeof(*calldata), GFP_KERNEL);
	if (calldata == NULL)
		return -ENOMEM;
		goto out;
	calldata->luargs.seqid = nfs_alloc_seqid(&lsp->ls_seqid);
	if (calldata->luargs.seqid == NULL) {
		kfree(calldata);
		return -ENOMEM;
		goto out;
	}
	calldata->luargs.stateid = &lsp->ls_stateid;
	calldata->arg.fh = NFS_FH(inode);
@@ -2978,14 +2983,16 @@ static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *
	/* Ensure we don't close file until we're done freeing locks! */
	calldata->ctx = get_nfs_open_context((struct nfs_open_context*)request->fl_file->private_data);

	atomic_set(&calldata->refcount, 2);
	init_completion(&calldata->completion);

	status = nfs4_call_async(NFS_SERVER(inode)->client, &nfs4_locku_ops, calldata);
	if (status == 0)
		wait_for_completion_interruptible(&calldata->completion);
	do_vfs_lock(request->fl_file, request);
	task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_locku_ops, calldata);
	if (!IS_ERR(task)) {
		status = nfs4_wait_for_completion_rpc_task(task);
		rpc_release_task(task);
	} else {
		status = PTR_ERR(task);
		nfs4_locku_release_calldata(calldata);
	}
out:
	do_vfs_lock(request->fl_file, request);
	return status;
}