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

Commit 26d36301 authored by Trond Myklebust's avatar Trond Myklebust Committed by Anna Schumaker
Browse files

NFSv4.1: Ensure we call FREE_STATEID if needed on close/delegreturn/locku



If a server returns NFS4ERR_ADMIN_REVOKED, NFS4ERR_DELEG_REVOKED
or NFS4ERR_EXPIRED on a call to close, open_downgrade, delegreturn, or
locku, we should call FREE_STATEID before attempting to recover.

Signed-off-by: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
Tested-by: default avatarOleg Drokin <green@linuxhacker.ru>
Signed-off-by: default avatarAnna Schumaker <Anna.Schumaker@Netapp.com>
parent f0b0bf88
Loading
Loading
Loading
Loading
+40 −3
Original line number Diff line number Diff line
@@ -328,6 +328,33 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent
	kunmap_atomic(start);
}

static void nfs4_test_and_free_stateid(struct nfs_server *server,
		nfs4_stateid *stateid,
		struct rpc_cred *cred)
{
	const struct nfs4_minor_version_ops *ops = server->nfs_client->cl_mvops;

	ops->test_and_free_expired(server, stateid, cred);
}

static void __nfs4_free_revoked_stateid(struct nfs_server *server,
		nfs4_stateid *stateid,
		struct rpc_cred *cred)
{
	stateid->type = NFS4_REVOKED_STATEID_TYPE;
	nfs4_test_and_free_stateid(server, stateid, cred);
}

static void nfs4_free_revoked_stateid(struct nfs_server *server,
		const nfs4_stateid *stateid,
		struct rpc_cred *cred)
{
	nfs4_stateid tmp;

	nfs4_stateid_copy(&tmp, stateid);
	__nfs4_free_revoked_stateid(server, &tmp, cred);
}

static long nfs4_update_delay(long *timeout)
{
	long ret;
@@ -2985,9 +3012,12 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
			break;
		case -NFS4ERR_ADMIN_REVOKED:
		case -NFS4ERR_STALE_STATEID:
		case -NFS4ERR_EXPIRED:
			nfs4_free_revoked_stateid(server,
					&calldata->arg.stateid,
					task->tk_msg.rpc_cred);
		case -NFS4ERR_OLD_STATEID:
		case -NFS4ERR_BAD_STATEID:
		case -NFS4ERR_EXPIRED:
			if (!nfs4_stateid_match(&calldata->arg.stateid,
						&state->open_stateid)) {
				rpc_restart_call_prepare(task);
@@ -5479,10 +5509,13 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata)
		renew_lease(data->res.server, data->timestamp);
	case -NFS4ERR_ADMIN_REVOKED:
	case -NFS4ERR_DELEG_REVOKED:
	case -NFS4ERR_EXPIRED:
		nfs4_free_revoked_stateid(data->res.server,
				data->args.stateid,
				task->tk_msg.rpc_cred);
	case -NFS4ERR_BAD_STATEID:
	case -NFS4ERR_OLD_STATEID:
	case -NFS4ERR_STALE_STATEID:
	case -NFS4ERR_EXPIRED:
		task->tk_status = 0;
		if (data->roc)
			pnfs_roc_set_barrier(data->inode, data->roc_barrier);
@@ -5726,10 +5759,14 @@ static void nfs4_locku_done(struct rpc_task *task, void *data)
			if (nfs4_update_lock_stateid(calldata->lsp,
					&calldata->res.stateid))
				break;
		case -NFS4ERR_ADMIN_REVOKED:
		case -NFS4ERR_EXPIRED:
			nfs4_free_revoked_stateid(calldata->server,
					&calldata->arg.stateid,
					task->tk_msg.rpc_cred);
		case -NFS4ERR_BAD_STATEID:
		case -NFS4ERR_OLD_STATEID:
		case -NFS4ERR_STALE_STATEID:
		case -NFS4ERR_EXPIRED:
			if (!nfs4_stateid_match(&calldata->arg.stateid,
						&calldata->lsp->ls_stateid))
				rpc_restart_call_prepare(task);