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

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

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
Loading
Loading
Loading
Loading
+19 −2
Original line number Diff line number Diff line
@@ -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,15 +1589,19 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
			goto out_copy;
		}
		if (!creds_match) { /* case 3 */
			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;
	}