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

Commit 63e4863f authored by J. Bruce Fields's avatar J. Bruce Fields
Browse files

nfsd4: make recall callback an asynchronous rpc



As with the probe, this removes the need for another kthread.

Signed-off-by: default avatarJ. Bruce Fields <bfields@citi.umich.edu>
parent 3aea09dc
Loading
Loading
Loading
Loading
+49 −25
Original line number Diff line number Diff line
@@ -494,45 +494,69 @@ nfsd4_probe_callback(struct nfs4_client *clp)
	do_probe_callback(clp);
}

/*
 * called with dp->dl_count inc'ed.
 */
void
nfsd4_cb_recall(struct nfs4_delegation *dp)
static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata)
{
	struct nfs4_delegation *dp = calldata;
	struct nfs4_client *clp = dp->dl_client;
	struct rpc_clnt *clnt = clp->cl_cb_conn.cb_client;
	struct rpc_message msg = {
		.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_RECALL],
		.rpc_argp = dp,
		.rpc_cred = clp->cl_cb_conn.cb_cred
	};
	int status = 0;

	dp->dl_retries = 1;
	status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT);
	while (dp->dl_retries--) {
		switch (status) {
	switch (task->tk_status) {
	case -EIO:
		/* Network partition? */
		atomic_set(&clp->cl_cb_conn.cb_set, 0);
		warn_no_callback_path(clp, task->tk_status);
	case -EBADHANDLE:
	case -NFS4ERR_BAD_STATEID:
		/* Race: client probably got cb_recall
		 * before open reply granting delegation */
		break;
	default:
				goto out_put_cred;
		/* success, or error we can't handle */
		return;
	}
	if (dp->dl_retries--) {
		rpc_delay(task, 2*HZ);
		task->tk_status = 0;
		rpc_restart_call(task);
	} else {
		atomic_set(&clp->cl_cb_conn.cb_set, 0);
		warn_no_callback_path(clp, task->tk_status);
	}
		ssleep(2);
		status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT);
}
out_put_cred:

static void nfsd4_cb_recall_release(void *calldata)
{
	struct nfs4_delegation *dp = calldata;
	struct nfs4_client *clp = dp->dl_client;

	nfs4_put_delegation(dp);
	put_nfs4_client(clp);
}

static const struct rpc_call_ops nfsd4_cb_recall_ops = {
	.rpc_call_done = nfsd4_cb_recall_done,
	.rpc_release = nfsd4_cb_recall_release,
};

/*
	 * Success or failure, now we're either waiting for lease expiration
	 * or deleg_return.
 * called with dp->dl_count inc'ed.
 */
void
nfsd4_cb_recall(struct nfs4_delegation *dp)
{
	struct nfs4_client *clp = dp->dl_client;
	struct rpc_clnt *clnt = clp->cl_cb_conn.cb_client;
	struct rpc_message msg = {
		.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_RECALL],
		.rpc_argp = dp,
		.rpc_cred = clp->cl_cb_conn.cb_cred
	};
	int status;

	dp->dl_retries = 1;
	status = rpc_call_async(clnt, &msg, RPC_TASK_SOFT,
				&nfsd4_cb_recall_ops, dp);
	if (status) {
		put_nfs4_client(clp);
		nfs4_put_delegation(dp);
	return;
	}
}
+3 −25
Original line number Diff line number Diff line
@@ -2059,19 +2059,6 @@ nfs4_file_downgrade(struct file *filp, unsigned int share_access)
	}
}

/*
 * Recall a delegation
 */
static int
do_recall(void *__dp)
{
	struct nfs4_delegation *dp = __dp;

	dp->dl_file->fi_had_conflict = true;
	nfsd4_cb_recall(dp);
	return 0;
}

/*
 * Spawn a thread to perform a recall on the delegation represented
 * by the lease (file_lock)
@@ -2084,7 +2071,6 @@ static
void nfsd_break_deleg_cb(struct file_lock *fl)
{
	struct nfs4_delegation *dp = (struct nfs4_delegation *)fl->fl_owner;
	struct task_struct *t;

	dprintk("NFSD nfsd_break_deleg_cb: dp %p fl %p\n",dp,fl);
	if (!dp)
@@ -2112,16 +2098,8 @@ void nfsd_break_deleg_cb(struct file_lock *fl)
	 */
	fl->fl_break_time = 0;

	t = kthread_run(do_recall, dp, "%s", "nfs4_cb_recall");
	if (IS_ERR(t)) {
		struct nfs4_client *clp = dp->dl_client;

		printk(KERN_INFO "NFSD: Callback thread failed for "
			"for client (clientid %08x/%08x)\n",
			clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
		put_nfs4_client(dp->dl_client);
		nfs4_put_delegation(dp);
	}
	dp->dl_file->fi_had_conflict = true;
	nfsd4_cb_recall(dp);
}

/*