diff options
author | J. Bruce Fields <bfields@redhat.com> | 2012-05-14 15:57:23 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2012-05-31 20:29:55 -0400 |
commit | 631fc9ea05c97e5d1d14ea58a7347be4857d09da (patch) | |
tree | 58c003e19609e7adf678bc9e197011ad2803c67e /fs/nfsd | |
parent | 136e658d621f71b67982dda51a2327830146ef9d (diff) |
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: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd')
-rw-r--r-- | fs/nfsd/nfs4state.c | 21 |
1 files changed, 19 insertions, 2 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 491f13a70db1..5415550a63a9 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -1508,6 +1508,19 @@ nfsd4_set_ex_flags(struct nfs4_client *new, struct nfsd4_exchange_id *clid) | |||
1508 | clid->flags = new->cl_exchange_flags; | 1508 | clid->flags = new->cl_exchange_flags; |
1509 | } | 1509 | } |
1510 | 1510 | ||
1511 | static bool client_has_state(struct nfs4_client *clp) | ||
1512 | { | ||
1513 | /* | ||
1514 | * Note clp->cl_openowners check isn't quite right: there's no | ||
1515 | * need to count owners without stateid's. | ||
1516 | * | ||
1517 | * Also note we should probably be using this in 4.0 case too. | ||
1518 | */ | ||
1519 | return list_empty(&clp->cl_openowners) | ||
1520 | && list_empty(&clp->cl_delegations) | ||
1521 | && list_empty(&clp->cl_sessions); | ||
1522 | } | ||
1523 | |||
1511 | __be32 | 1524 | __be32 |
1512 | nfsd4_exchange_id(struct svc_rqst *rqstp, | 1525 | nfsd4_exchange_id(struct svc_rqst *rqstp, |
1513 | struct nfsd4_compound_state *cstate, | 1526 | struct nfsd4_compound_state *cstate, |
@@ -1576,8 +1589,11 @@ nfsd4_exchange_id(struct svc_rqst *rqstp, | |||
1576 | goto out_copy; | 1589 | goto out_copy; |
1577 | } | 1590 | } |
1578 | if (!creds_match) { /* case 3 */ | 1591 | if (!creds_match) { /* case 3 */ |
1579 | status = nfserr_clid_inuse; | 1592 | if (client_has_state(conf)) { |
1580 | goto out; | 1593 | status = nfserr_clid_inuse; |
1594 | goto out; | ||
1595 | } | ||
1596 | goto expire_client; | ||
1581 | } | 1597 | } |
1582 | if (verfs_match) { /* case 2 */ | 1598 | if (verfs_match) { /* case 2 */ |
1583 | exid->flags |= EXCHGID4_FLAG_CONFIRMED_R; | 1599 | exid->flags |= EXCHGID4_FLAG_CONFIRMED_R; |
@@ -1585,6 +1601,7 @@ nfsd4_exchange_id(struct svc_rqst *rqstp, | |||
1585 | goto out_copy; | 1601 | goto out_copy; |
1586 | } | 1602 | } |
1587 | /* case 5, client reboot */ | 1603 | /* case 5, client reboot */ |
1604 | expire_client: | ||
1588 | expire_client(conf); | 1605 | expire_client(conf); |
1589 | goto out_new; | 1606 | goto out_new; |
1590 | } | 1607 | } |