static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata)
{
	struct nfs4_delegation *dp = calldata;
	struct nfs4_client *clp = dp->dl_client;

	nfsd4_cb_done(task, calldata);

	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:
		/* success, or error we can't handle */
		goto done;
	}
	if (dp->dl_retries--) {
		rpc_delay(task, 2*HZ);
		task->tk_status = 0;
		rpc_restart_call(task);
		return;
	} else {
		atomic_set(&clp->cl_cb_conn.cb_set, 0);
		warn_no_callback_path(clp, task->tk_status);
	}
done:
	kfree(task->tk_msg.rpc_argp);
}
Exemple #2
0
static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata)
{
	struct nfsd4_callback *cb = calldata;
	struct nfs4_delegation *dp = container_of(cb, struct nfs4_delegation, dl_recall);
	struct nfs4_client *clp = dp->dl_client;
	struct rpc_clnt *current_rpc_client = clp->cl_cb_client;

	nfsd4_cb_done(task, calldata);

	if (current_rpc_client == NULL) {
		/* We're shutting down; give up. */
		/* XXX: err, or is it ok just to fall through
		 * and rpc_restart_call? */
		return;
	}

	switch (task->tk_status) {
	case 0:
		return;
	case -EBADHANDLE:
	case -NFS4ERR_BAD_STATEID:
		/* Race: client probably got cb_recall
		 * before open reply granting delegation */
		break;
	default:
		/* Network partition? */
		atomic_set(&clp->cl_cb_set, 0);
		warn_no_callback_path(clp, task->tk_status);
		if (current_rpc_client != task->tk_client) {
			/* queue a callback on the new connection: */
			atomic_inc(&dp->dl_count);
			nfsd4_cb_recall(dp);
			return;
		}
	}
	if (dp->dl_retries--) {
		rpc_delay(task, 2*HZ);
		task->tk_status = 0;
		rpc_restart_call_prepare(task);
		return;
	} else {
		atomic_set(&clp->cl_cb_set, 0);
		warn_no_callback_path(clp, task->tk_status);
	}
}