Skip to content

Commit

Permalink
nfsd4: allow removing clients not holding state
Browse files Browse the repository at this point in the history
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: J. Bruce Fields <[email protected]>
  • Loading branch information
J. Bruce Fields committed Jun 1, 2012
1 parent 136e658 commit 631fc9e
Showing 1 changed file with 19 additions and 2 deletions.
21 changes: 19 additions & 2 deletions fs/nfsd/nfs4state.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -1576,15 +1589,19 @@ 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;
new = conf;
goto out_copy;
}
/* case 5, client reboot */
expire_client:
expire_client(conf);
goto out_new;
}
Expand Down

0 comments on commit 631fc9e

Please sign in to comment.