[PATCH 10/21] NFSv4/flexfiles: Implement in-place device re-resolve on CHANGE
Benjamin Coddington <ben.coddington-F/[email protected]>
| Newsgroups | gmane.linux.nfs |
|---|---|
| Message-ID | <aeb34a04237d832d3741f5b80e198639e3df9b14.1786653063.git.bcodding@hammerspace.com> |
Implement the reresolve_deviceid hook: walk the layout's mirrors and, for every stripe whose raw deviceid matches the changed one, exchange the pinned device node out for NULL. In-flight I/O completes on the old node through its own reference; the next I/O to the stripe re-resolves via ff_layout_get_mirror_ds() and picks up the server's new mapping with a fresh GETDEVICEINFO. The un-pinned references are handed back on the walker's list to be put outside the locks. Matching uses the raw deviceid decoded from the layout (dss[].devid), so stripes whose node was never resolved, or already exchanged, are untouched. Nothing dispatches CHANGE to the walker yet: no behavior change. Assisted-by: Claude:claude-fable-5 Signed-off-by: Benjamin Coddington <bcodding-F/[email protected]> --- fs/nfs/flexfilelayout/flexfilelayout.c | 36 ++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c index dfc0c298ab4b..bb27bbea6c95 100644 --- a/fs/nfs/flexfilelayout/flexfilelayout.c +++ b/fs/nfs/flexfilelayout/flexfilelayout.c @@ -2505,6 +2505,41 @@ static void ff_layout_cancel_io(struct pnfs_layout_segment *lseg) } } +/* + * The server changed the mapping for deviceid @id (CB_NOTIFY_DEVICEID + * CHANGE). Un-pin every stripe device node resolved from @id in @lo's + * mirrors: in-flight I/O completes on the old node via its own + * reference, and the next I/O to the stripe re-resolves, picking up the + * new mapping with a fresh GETDEVICEINFO (the stale cache entry has + * already been unhashed). + * + * Called under @lo's inode i_lock; the un-pinned references are handed + * to the caller on @head to put outside the lock. + */ +static void ff_layout_reresolve_deviceid(struct pnfs_layout_hdr *lo, + const struct nfs4_deviceid *id, + bool immediate, + struct list_head *head) +{ + struct nfs4_flexfile_layout *flo = FF_LAYOUT_FROM_HDR(lo); + struct nfs4_ff_layout_mirror *mirror; + struct nfs4_ff_layout_ds *old; + u32 dss_id; + + list_for_each_entry(mirror, &flo->mirrors, mirrors) { + for (dss_id = 0; dss_id < mirror->dss_count; dss_id++) { + if (memcmp(&mirror->dss[dss_id].devid, id, + sizeof(*id)) != 0) + continue; + old = unrcu_pointer( + xchg(&mirror->dss[dss_id].mirror_ds, NULL)); + if (IS_ERR_OR_NULL(old)) + continue; + list_add(&old->id_node.put_list, head); + } + } +} + static struct pnfs_ds_commit_info * ff_layout_get_ds_info(struct inode *inode) { @@ -3088,6 +3123,7 @@ static struct pnfs_layoutdriver_type flexfilelayout_type = { .pg_write_ops = &ff_layout_pg_write_ops, .get_ds_info = ff_layout_get_ds_info, .free_deviceid_node = ff_layout_free_deviceid_node, + .reresolve_deviceid = ff_layout_reresolve_deviceid, .read_pagelist = ff_layout_read_pagelist, .write_pagelist = ff_layout_write_pagelist, .alloc_deviceid_node = ff_layout_alloc_deviceid_node, -- 2.53.0