summaryrefslogtreecommitdiff
path: root/include/linux
diff options
context:
space:
mode:
authorBenjamin Coddington <ben.coddington@hammerspace.com>2026-09-15 08:22:18 -0400
committerAnna Schumaker <anna.schumaker@hammerspace.com>2026-10-05 09:46:44 -0400
commit1507df1d0bfd723e93eddcc800629acac1ec401c (patch)
treee90e76eef75b31a855c7a6aaf12bd709acc58117 /include/linux
parente1c7a4f94139cf2c49896653e3f1e6c4f25cff35 (diff)
pNFS: Discard a GETDEVICEINFO reply that raced a CHANGE notification
RFC 8881 Section 18.40.4: a GETDEVICEINFO reply in flight while the server changes the device mapping may carry the pre-change mapping; if it is inserted into the cache after the CHANGE notification unhashed the stale entry, the client re-caches stale data. Track a change epoch, bumped when a CHANGE notification is processed before the stale entry is unhashed. nfs4_find_get_deviceid() snapshots the epoch before issuing GETDEVICEINFO and, serialized against the unhash by nfs4_deviceid_lock at insert time, discards the reply and refetches if the epoch moved. A stale insert that instead precedes the unhash is removed by the unhash itself, so the cache does not retain the pre-change entry either way; a reference already handed to a caller in that ordering is dropped by the re-resolve walk instead. The refetch is bounded. The epoch is bumped once per CHANGE entry -- that is, at a rate the server chooses -- so an unbounded retry would let a server drive GETDEVICEINFO traffic without limit, and each discarded node can carry a DS client teardown and reconnect with it. After NFS4_DEVICEID_FETCH_RETRIES attempts the reply is accepted. That is safe because discarding is an optimisation rather than a correctness requirement: it avoids caching a mapping already known to be superseded, but before this patch the client cached whatever the reply carried, so the bounded case is no worse than the previous behaviour and a mapping that really is stale is corrected by the notification that follows. The epoch lives on the nfs_client, so a CHANGE delivered on one server's callback channel does not force an unrelated server's in-flight lookup to discard its reply and refetch. Mounts that share an nfs_client do share the counter; the deviceid cache is keyed per client ID, so that is the granularity the race is defined at. Assisted-by: Claude:claude-fable-5 Signed-off-by: Benjamin Coddington <bcodding@hammerspace.com> Signed-off-by: Anna Schumaker <anna.schumaker@hammerspace.com>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/nfs_fs_sb.h2
1 files changed, 2 insertions, 0 deletions
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index 3e6bae7e5221..482daf1fa4b0 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -74,6 +74,8 @@ struct nfs_client {
u64 cl_clientid; /* constant */
nfs4_verifier cl_confirm; /* Clientid verifier */
unsigned long cl_state;
+ /* bumped on each CB_NOTIFY_DEVICEID CHANGE for this client */
+ atomic_t cl_deviceid_change_epoch;
spinlock_t cl_lock;