Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+19 -2
+19 -2
fs/nfsd/nfs4state.c
··· 1508 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 1524 __be32 1512 1525 nfsd4_exchange_id(struct svc_rqst *rqstp, 1513 1526 struct nfsd4_compound_state *cstate, ··· 1589 1576 goto out_copy; 1590 1577 } 1591 1578 if (!creds_match) { /* case 3 */ 1592 - status = nfserr_clid_inuse; 1593 - goto out; 1579 + if (client_has_state(conf)) { 1580 + status = nfserr_clid_inuse; 1581 + goto out; 1582 + } 1583 + goto expire_client; 1594 1584 } 1595 1585 if (verfs_match) { /* case 2 */ 1596 1586 exid->flags |= EXCHGID4_FLAG_CONFIRMED_R; ··· 1601 1585 goto out_copy; 1602 1586 } 1603 1587 /* case 5, client reboot */ 1588 + expire_client: 1604 1589 expire_client(conf); 1605 1590 goto out_new; 1606 1591 }