Commit 631fc9ea authored by J. Bruce Fields's avatar J. Bruce Fields

nfsd4: allow removing clients not holding state

RFC 5661 actually says we should allow an exchange_id to remove a
matching client, even if the exchange_id comes from a different
principal, *if* the victim client lacks any state.
Signed-off-by: default avatarJ. Bruce Fields <bfields@redhat.com>
parent 136e658d
......@@ -1508,6 +1508,19 @@ nfsd4_set_ex_flags(struct nfs4_client *new, struct nfsd4_exchange_id *clid)
clid->flags = new->cl_exchange_flags;
}
static bool client_has_state(struct nfs4_client *clp)
{
/*
* Note clp->cl_openowners check isn't quite right: there's no
* need to count owners without stateid's.
*
* Also note we should probably be using this in 4.0 case too.
*/
return list_empty(&clp->cl_openowners)
&& list_empty(&clp->cl_delegations)
&& list_empty(&clp->cl_sessions);
}
__be32
nfsd4_exchange_id(struct svc_rqst *rqstp,
struct nfsd4_compound_state *cstate,
......@@ -1576,8 +1589,11 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
goto out_copy;
}
if (!creds_match) { /* case 3 */
status = nfserr_clid_inuse;
goto out;
if (client_has_state(conf)) {
status = nfserr_clid_inuse;
goto out;
}
goto expire_client;
}
if (verfs_match) { /* case 2 */
exid->flags |= EXCHGID4_FLAG_CONFIRMED_R;
......@@ -1585,6 +1601,7 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
goto out_copy;
}
/* case 5, client reboot */
expire_client:
expire_client(conf);
goto out_new;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment