[PATCH v2 13/23] NFSv4: Dispatch CB_NOTIFY_DEVICEID CHANGE to an in-place refresh
Benjamin Coddington <[email protected]>
| Newsgroups | org.kernel.vger.linux-nfs |
|---|---|
| Message-ID | <596a4de4f3ff57c628b616623a8c01e730706090.1787327939.git.bcodding@hammerspace.com> |
nfs4_callback_devicenotify() treated CHANGE identically to DELETE: both only unhashed the cached device, so references pinned under live layouts kept sending I/O to the old mapping until the layouts were freed. Per RFC 8881 Section 12.2.10, CHANGE exists precisely so a server can change a mapping without recalling the layouts. For CHANGE, after unhashing the stale cache entry (so re-resolution cannot re-pin it), invoke the layout driver's re-resolve walker. The walker does not install the new mapping itself: it un-pins the stale node so the next I/O to that stripe re-resolves and fetches the new one, while I/O already in flight completes on the old node through its own reference. DELETE is unchanged, and drivers without a reresolve_deviceid hook see no change. Re-resolution is best effort. A lookup that hit the cache just before the unhash can still install that node after the walk has passed the stripe, and the walk skips nothing else; such a stripe keeps the old mapping until the next notification. Nothing is left inconsistent by that -- the old mapping is a valid address the server published -- so the race is tolerated rather than serialised against. Assisted-by: Claude:claude-fable-5 Signed-off-by: Benjamin Coddington <[email protected]> --- fs/nfs/callback_proc.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c index 10f2354ba304..64c994790d3f 100644 --- a/fs/nfs/callback_proc.c +++ b/fs/nfs/callback_proc.c @@ -390,7 +390,16 @@ __be32 nfs4_callback_devicenotify(void *argp, void *resp, if (!ld) 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). + */ nfs4_delete_deviceid(ld, cps->clp, &dev->cbd_dev_id); + if (dev->cbd_notify_type == NOTIFY_DEVICEID4_CHANGE) + pnfs_layout_reresolve_deviceid_byclid(cps->clp, ld, + &dev->cbd_dev_id, + dev->cbd_immediate); } pnfs_put_layoutdriver(ld); out: -- 2.53.0