summaryrefslogtreecommitdiff
path: root/tools/testing/selftests/nfsd
AgeCommit message (Collapse)Author
11 daysselftests/nfsd: exercise the userspace-rpcbind listener_set flagJeff Layton
Cover the flag that moves rpcbind registration to the caller. rpcb_userspace_no_traffic is the one that matters. The errno says nothing about whether the kernel talked to rpcbind, but the stub counters do: a request that carries the flag must leave both at zero, which is what shows that svc_bind() and svc_register() were both skipped. The rest cover the reply and the ownership rule: - rpcb_userspace_reply. The ack flag, a non-empty program list, and the listener that came up. nfslocalio is hidden, so it must be absent. - rpcb_userspace_no_v4_udp. NFSv3 must be offered and must not carry no-udp; NFSv4 carries it, or the test skips where v4 is not built. - rpcb_userspace_nfsacl_follows_nfs. CONFIG_NFSD_V3_ACL is invisible to the test, so assert only that nfsacl v3 implies nfs v3. - rpcb_userspace_busy and rpcb_userspace_busy_reverse. Ownership cannot change under a live serv, in either direction. - rpcb_userspace_unflagged_teardown and its reverse. Teardown destroys the serv, so it is exempt from that rule in both directions. The follow-on listener_set is what proves the old serv went away rather than merely losing its listeners. - rpcb_userspace_portlist_busy. The legacy portlist add-fd write is refused against a flagged serv and still works against a kernel-owned one. nfsdfs is mounted in the test's netns, so the write cannot reach the host's nfsd. - rpcb_userspace_teardown. Create and destroy a flagged serv three times, then confirm that a kernel-owned serv still reaches rpcbind. An unbalanced rpcb_put_local() would break the last step. - rpcb_userspace_many_listeners. Forty listeners, which is more than GENLMSG_DEFAULT_SIZE would have held. A reply sized from that constant instead of from its contents returns -EMSGSIZE with every listener already up. genl_request_reply() grew an attribute argument, because listener_set now answers with a reply message rather than a bare ack. listener_set_rpcb() checks nlmsg_len against the recv() count before parsing. Forty listeners fit in its buffer, but a reply near NFSD_NL_LISTENER_MAX would not, and the parse loops trust nlmsg_len. Assisted-by: LLM Signed-off-by: Jeff Layton <jlayton@kernel.org> Link: https://patch.msgid.link/20260915-nfsd-norpcb-v3-5-3c60d49ade02@kernel.org Signed-off-by: Chuck Lever <cel@kernel.org>
2026-10-04selftests/nfsd: check that listener removal asks rpcbind onceJeff Layton
Cover the teardown side of the same rule. Remove one listener, then three, with the stub silent, and compare what it saw. Three removals must not cost three timeouts. Both measurements also pay the svc_unregister() sweep that nfsd_destroy_serv() runs once the last listener is gone, so that cancels out of the comparison. The listeners are registered with the stub answering, so each one has an entry to remove. Assisted-by: LLM Signed-off-by: Jeff Layton <jlayton@kernel.org> Link: https://patch.msgid.link/20260901-nfsd-nl-hang-v5-15-a540d86668b0@kernel.org Signed-off-by: Chuck Lever <cel@kernel.org>
2026-10-04selftests/nfsd: check that listener_set asks rpcbind onceJeff Layton
Cover the change that stops a listener_set request from registering after rpcbind stops answering. RPCB_STUB_SILENT is new. It reads a call and writes nothing back, so the kernel waits out its own timeout. RPCB_STUB_REFUSE cannot serve here: a refusal is an answer, and the count ignores it on purpose. Every procedure but the NULL one is silenced, so an unregistration goes unanswered as well. The NULL one has to be answered: rpcb_create_af_local() builds its client without RPC_CLNT_CREATE_NOPING, so rpc_create() pings at creation. Silencing that ping too would fail the AF_LOCAL client, send rpcb_create_local() on to the loopback client of rpcb_create_local_net(), and leave the stub seeing one call per request no matter how many listeners it carried. - rpcb_stop_after_failure. Ask for one listener, then for three, and compare what the stub saw. Three entries must not cost three times as much. - rpcb_silent_set_complete. The entry that finds rpcbind silent is the one that pays the timeout, and with v3 enabled it is the only entry whose listener would be lost. Require that a three-entry request brings up all three, succeeds, and warns. - rpcb_v4_only_bounded. The case that needs the count rather than a failed listener. version_set_only() makes the server v4-only, so vs_rpcb_optnl discards every error and every listener comes up. Require that the listeners are present, that the ack warns about them, and that three entries do not cost three round trips. - rpcb_retry_next_request. The stop lasts for one request. After the stub starts to answer, the next request must reach rpcbind again. The counts these tests compare include the unregistrations that the teardown between the two measurements issues. The preceding patches bound that direction too, so the sweeps stay at one timeout rather than one per program and version. version_set_only() is new. NFSD_CMD_VERSION_SET clears every version before it reads the request, so one nest leaves the server v4-only. It returns -EBUSY once a serv exists, so the test calls it first. Assisted-by: LLM Signed-off-by: Jeff Layton <jlayton@kernel.org> Link: https://patch.msgid.link/20260901-nfsd-nl-hang-v5-14-a540d86668b0@kernel.org Signed-off-by: Chuck Lever <cel@kernel.org>
2026-10-04selftests/nfsd: add a per-netns rpcbind stub and the listener round-tripsJeff Layton
The creation of a listener registers with rpcbind. svc_xprt_create_from_sa() passes flags of 0, so pmap_register is true in svc_setup_socket(). A fresh netns has no rpcbind. Every registration therefore waits out the local rpcbind timeout, once for each program and version, and the registration failure then takes the listener down. The host's rpcbind is not an option either. svc_rpcb_setup() opens with a call to svc_unregister(), which would clear the host's nfsd entries. Serve rpcbind from inside the namespace instead. The abstract AF_LOCAL name that the kernel tries first is per-netns, because unix_find_abstract() takes a struct net. Bind "\0/run/rpcbind.sock" and fork a minimal responder: - the responder never decodes arguments. The NULL procedure gets an empty success, and SET and UNSET get TRUE. - the responder answers RPCBVERS_4 as well as RPCBVERS_2. A v4 refusal makes __svc_rpcb_register6() return -EAFNOSUPPORT, which would leave every IPv6 listener unregistered. - the responder counts accepted connections and received calls in a page that it shares with the test, and reads its mode from that page on every call. The mode lives there rather than in the child so that a test can change it with a serv already up: killing and restarting the stub would close the connection the kernel holds, and rpcb_register_call() issues UNSET over AF_LOCAL with RPC_TASK_NOCONNECT, so the next call would fail at once with -ENOTCONN instead of waiting out a timeout. - PR_SET_PDEATHSIG plus an explicit kill in FIXTURE_TEARDOWN make sure that no stub outlives its test. With the stub in place, add the tests that need a serv. These cover the create, add and remove paths and the LISTENER_GET round trips: tcp, udp, several listeners at once, an idempotent re-set, the removal of a subset, the destruction of a serv from an empty list, and IPv6. Two more tests cover the empty-list request and the -EBUSY refusal after THREADS_SET has started threads. The netlink socket asks for NETLINK_EXT_ACK, so that the tests can read the extack message. It also asks for NETLINK_CAP_ACK, so that the kernel does not echo the request back and the TLVs sit at a fixed offset. FIXTURE_TEARDOWN drops whatever a test left running. A listener holds a reference to the netns, and that netns outlives the test process. Threads pin the listeners. Anything left up therefore leaks the namespace. Several of these tests exist to catch a revert, not to describe the interface. The errno alone shows none of them: - val_reject_keeps_listeners. An unknown transport name ends in -EPROTONOSUPPORT either way, because svc_xprt_create_from_sa() returns that error too. The difference is the state that it leaves. Without the up-front check, nfsd_nl_listener_set_doit() has already destroyed the listeners that did not match by the time the name fails. - val_bad_transport. This test now also requires that the stub saw no traffic. A request that reaches svc_xprt_create_from_sa() has run nfsd_create_serv(). svc_bind() then pings rpcbind at client creation and sweeps stale entries with svc_unregister(). Silence at the stub is therefore what shows that the kernel refused the request up front. - val_second_entry_bad. This test now also sends a LISTENER_GET. svc_xprt_create_from_sa() also returns -EAFNOSUPPORT for the bad entry, and the doit keeps the listeners that it did create. The well-formed tcp entry ahead of it would otherwise still be up. - sem_register_refused. This test puts the stub in a mode that answers RPCBPROC_SET with FALSE. rpcb_register_call() turns that answer into -EACCES, svc_register() then fails, and svc_setup_socket() creates no listener. The bare errno does not show that, because a bind can return -EACCES too, so the test reads the listener set back and requires that it is empty. - sem_create_failure_extack. This test squats on the port first, so the listener cannot bind. The extack must then name the transport that failed. - func_empty_destroys. This test uses the connection count. LISTENER_GET replies empty both for a destroyed serv and for a live serv with no permsocks. But only nfsd_destroy_serv() reaches svc_xprt_destroy_all(..., unregister=true) -> svc_rpcb_cleanup() -> rpcb_put_local(), which drops the last user and shuts the local client down. The next serv has to connect again. - sem_busy_on_change and sem_busy_on_remove read the listeners back, because -EBUSY says nothing about what the doit did before it returned. find_listener() matches the address as well as the transport, the family and the port. Every listener here is created on loopback, so a reply that names 0.0.0.0 has to fail. Assisted-by: LLM Signed-off-by: Jeff Layton <jlayton@kernel.org> Link: https://patch.msgid.link/20260901-nfsd-nl-hang-v5-13-a540d86668b0@kernel.org Signed-off-by: Chuck Lever <cel@kernel.org>
2026-10-04selftests/nfsd: exercise listener_set request validationJeff Layton
Add regression tests for the NFSD_CMD_LISTENER_SET checks that nfsd_nl_validate_listeners() runs before the code takes nfsd_mutex. The tests cover a bad transport name, an absent transport name, a missing address, a truncated or unsupported sockaddr, a bad address family, a malformed entry behind a well-formed one, and more than NFSD_NL_LISTENER_MAX entries. One more test sends a LISTENER_GET to an empty netns. None of these requests reach nfsd_create_serv(), so nothing here creates a serv or registers with rpcbind. The tests that do need a serv come next, with a stub. The tests use kselftest_harness.h, so each test runs in its own net and mount namespace. /run is masked there. unix_find_bsd() resolves by inode and takes no struct net, so a connect to "/var/run/rpcbind.sock" from this netns would otherwise reach the rpcbind on the host. svc_rpcb_setup() opens with a call to svc_unregister(), which would then clear the host's nfsd registrations. The config fragment must therefore cover the fixture as well as nfsd: NAMESPACES and NET_NS for the unshare(), SHMEM and TMPFS for the mask, and UNIX for the AF_LOCAL rpcbind client. Without them, every test skips. Add the new directory to the NFSD MAINTAINERS entry, which does not cover tools/testing/selftests/ today. Assisted-by: LLM Signed-off-by: Jeff Layton <jlayton@kernel.org> Link: https://patch.msgid.link/20260901-nfsd-nl-hang-v5-12-a540d86668b0@kernel.org Signed-off-by: Chuck Lever <cel@kernel.org>