diff options
| author | Benjamin Coddington <ben.coddington@hammerspace.com> | 2026-09-15 08:22:22 -0400 |
|---|---|---|
| committer | Anna Schumaker <anna.schumaker@hammerspace.com> | 2026-10-05 09:46:45 -0400 |
| commit | db485e06253e355f3a2fd1feb94f14bf7ec360ff (patch) | |
| tree | 4d0cd7032c13f332f38cb8f9d9ad14955c32722e /fs/nfs | |
| parent | 14286f49f0b87129656acc54a825a64b8c9744b3 (diff) | |
NFSv4/pnfs: Dispatch CB_NOTIFY_DEVICEID DELETE to race recovery
Turn on the RFC 8881 Section 18.40.4 DELETE handling: a DELETE for a
deviceID that no live layout references keeps today's cheap behavior
(drop the cached device, no state-manager wake). A DELETE for a
deviceID that live layouts still reference is deferred to the state
manager, which TEST_STATEIDs the referring layouts, recovers revoked
ones, and confirms or refutes the delete with GETDEVICEINFO.
The deferred case no longer unhashes the device immediately: if the
recovery concludes the DELETE was erroneous (the deviceID still
exists and a referring layout is still valid), the client keeps
using the cached device.
Re-arm the state manager afterwards, as the delegation return above it
does. The recovery issues synchronous RPCs, and a manager thread that
starts and exits while it runs clears NFS4CLNT_RUN_MANAGER on its way
out.
Bump the deviceid change epoch for both notification types rather
than only for CHANGE. A GETDEVICEINFO whose reply is already in
flight can otherwise re-cache a device the notification has just
invalidated; that is as true of a delete as of a change, and Section
18.40.4 opens by describing the race for the delete case.
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 'fs/nfs')
| -rw-r--r-- | fs/nfs/callback_proc.c | 24 | ||||
| -rw-r--r-- | fs/nfs/nfs4state.c | 4 |
2 files changed, 18 insertions, 10 deletions
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c index ea8c558b07b6..c9b71dbae9ea 100644 --- a/fs/nfs/callback_proc.c +++ b/fs/nfs/callback_proc.c @@ -392,19 +392,25 @@ __be32 nfs4_callback_devicenotify(void *argp, void *resp, continue; } /* - * Unhash the cached device first so re-resolution cannot - * re-pin the stale node, then re-point any references - * pinned under live layouts (RFC 8881 Section 12.2.10). - * The epoch bump lets an in-flight GETDEVICEINFO detect - * that its reply may predate the change. + * Bump the epoch before touching the cache so a + * GETDEVICEINFO already in flight can detect that it + * predates the notification. A referenced DELETE may be + * racing revocation, so defer it to the state manager -- + * this thread cannot issue fore-channel RPCs. */ - if (dev->cbd_notify_type == NOTIFY_DEVICEID4_CHANGE) - nfs4_deviceid_bump_change_epoch(cps->clp); - nfs4_delete_deviceid(ld, cps->clp, &dev->cbd_dev_id); - if (dev->cbd_notify_type == NOTIFY_DEVICEID4_CHANGE) + nfs4_deviceid_bump_change_epoch(cps->clp); + if (dev->cbd_notify_type == NOTIFY_DEVICEID4_CHANGE) { + nfs4_delete_deviceid(ld, cps->clp, &dev->cbd_dev_id); pnfs_layout_reresolve_deviceid_byclid(cps->clp, ld, &dev->cbd_dev_id, dev->cbd_immediate); + } else if (pnfs_layout_deviceid_referenced_byclid(cps->clp, + ld, &dev->cbd_dev_id)) { + pnfs_deviceid_delete_mark(cps->clp, ld, + &dev->cbd_dev_id); + } else { + nfs4_delete_deviceid(ld, cps->clp, &dev->cbd_dev_id); + } } pnfs_put_layoutdriver(ld); out: diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 4c085c00abb1..b5d6daa2c416 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -2670,8 +2670,10 @@ static void nfs4_state_manager(struct nfs_client *clp) } nfs4_layoutreturn_any_run(clp); if (test_and_clear_bit(NFS4CLNT_DEVICEID_DELETE, - &clp->cl_state)) + &clp->cl_state)) { nfs4_deviceid_delete_recover_run(clp); + set_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state); + } clear_bit(NFS4CLNT_RECALL_RUNNING, &clp->cl_state); } |
