* [PATCH v6] NFSD: Track SCSI Persistent Registration Fencing per Client with xarray
@ 2026-01-08 14:44 Chuck Lever
2026-01-08 16:14 ` Christoph Hellwig
2026-01-08 18:26 ` Chuck Lever
0 siblings, 2 replies; 3+ messages in thread
From: Chuck Lever @ 2026-01-08 14:44 UTC (permalink / raw)
To: NeilBrown, Jeff Layton, Olga Kornievskaia, Dai Ngo, Tom Talpey,
Christoph Hellwig
Cc: linux-nfs
From: Dai Ngo <dai.ngo@oracle.com>
When a client holding pNFS SCSI layouts becomes unresponsive, the
server revokes access by preempting the client's SCSI persistent
reservation key. A layout recall is issued for each layout the
client holds; if the client fails to respond, each recall triggers
a fence operation. The first preempt for a given device succeeds
and removes the client's key registration. Subsequent preempts for
the same device fail because the key is no longer registered.
Update the NFS server to handle SCSI persistent registration
fencing on a per-client and per-device basis by utilizing an
xarray associated with the nfs4_client structure.
Each xarray entry is indexed by the dev_t of a block device
registered by the client. The entry maintains a flag indicating
whether this device has already been fenced for the corresponding
client.
When the server issues a persistent registration key to a client,
it creates a new xarray entry at the dev_t index with the fenced
flag initialized to 0.
Before performing a fence via nfsd4_scsi_fence_client, the server
checks the corresponding entry using the device's dev_t. If the
fenced flag is already set, the fence operation is skipped;
otherwise, the flag is set to 1 and fencing proceeds.
The xarray is destroyed when the nfs4_client is released in
__destroy_client.
Signed-off-by: Dai Ngo <dai.ngo@oracle.com>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/nfsd/blocklayout.c | 41 +++++++++++++++++++++++++++++++++++++++++
fs/nfsd/nfs4state.c | 6 ++++++
fs/nfsd/state.h | 3 +++
3 files changed, 50 insertions(+)
V2:
. Replace xa_store with xas_set_mark and xas_get_mark to avoid
memory allocation in nfsd4_scsi_fence_client.
. Remove cl_fence_lock, use xa_lock instead.
V3:
. handle xa_store error.
. add xa_lock and xa_unlock when calling xas_clear_mark
V4:
. rename cl_fenced_devs to cl_dev_fences
. add comment in nfsd4_block_get_device_info_scsi
V5:
. Take a stab at a proper problem statement
. Handle failures of pr_register / pr_reserve correctly
. Remove usage of possibly stale xa_state data
. Avoid looping when pr_preempt fails
. Fix usage of #ifdef CONFIG_SCSILAYOUT
V6:
. Use xa_insert() instead of xa_store()
. Add check for PR_STS_RETRY_PATH_FAILURE
diff --git a/fs/nfsd/blocklayout.c b/fs/nfsd/blocklayout.c
index afa16d7a8013..60304bca1bb6 100644
--- a/fs/nfsd/blocklayout.c
+++ b/fs/nfsd/blocklayout.c
@@ -342,6 +342,17 @@ nfsd4_block_get_device_info_scsi(struct super_block *sb,
goto out_free_dev;
}
+ /*
+ * Add the device if it does not already exist in the xarray. This
+ * logic prevents adding more entries to cl_dev_fences than there
+ * are exported devices on the server. XA_MARK_0 tracks whether the
+ * device has been fenced.
+ */
+ ret = xa_insert(&clp->cl_dev_fences, sb->s_bdev->bd_dev,
+ XA_ZERO_ENTRY, GFP_KERNEL);
+ if (ret < 0 && ret != -EBUSY)
+ goto out_free_dev;
+
ret = ops->pr_register(sb->s_bdev, 0, NFSD_MDS_PR_KEY, true);
if (ret) {
pr_err("pNFS: failed to register key for device %s.\n",
@@ -399,11 +410,41 @@ nfsd4_scsi_fence_client(struct nfs4_layout_stateid *ls, struct nfsd_file *file)
{
struct nfs4_client *clp = ls->ls_stid.sc_client;
struct block_device *bdev = file->nf_file->f_path.mnt->mnt_sb->s_bdev;
+ struct xarray *xa = &clp->cl_dev_fences;
int status;
+ bool skip;
+
+ xa_lock(xa);
+ skip = xa_get_mark(xa, bdev->bd_dev, XA_MARK_0);
+ if (!skip)
+ __xa_set_mark(xa, bdev->bd_dev, XA_MARK_0);
+ xa_unlock(xa);
+ if (skip)
+ return;
status = bdev->bd_disk->fops->pr_ops->pr_preempt(bdev, NFSD_MDS_PR_KEY,
nfsd4_scsi_pr_key(clp),
PR_EXCLUSIVE_ACCESS_REG_ONLY, true);
+ /*
+ * Reset to allow retry only when the command could not have
+ * reached the device. Negative status means a local error
+ * (e.g., -ENOMEM) prevented the command from being sent.
+ * PR_STS_PATH_FAILED, PR_STS_PATH_FAST_FAILED, and
+ * PR_STS_RETRY_PATH_FAILURE indicate transport path failures
+ * before device delivery.
+ *
+ * For all other errors, the command may have reached the device
+ * and the preempt may have succeeded. Avoid resetting, since
+ * retrying a successful preempt returns PR_STS_IOERR or
+ * PR_STS_RESERVATION_CONFLICT, which would cause an infinite
+ * retry loop.
+ */
+ if (status < 0 ||
+ status == PR_STS_PATH_FAILED ||
+ status == PR_STS_PATH_FAST_FAILED ||
+ status == PR_STS_RETRY_PATH_FAILURE)
+ xa_clear_mark(xa, bdev->bd_dev, XA_MARK_0);
+
trace_nfsd_pnfs_fence(clp, bdev->bd_disk->disk_name, status);
}
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index ea4d6eff0d2f..4fc94f2de7ba 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -2382,6 +2382,9 @@ static struct nfs4_client *alloc_client(struct xdr_netobj name,
INIT_LIST_HEAD(&clp->cl_revoked);
#ifdef CONFIG_NFSD_PNFS
INIT_LIST_HEAD(&clp->cl_lo_states);
+#endif
+#ifdef CONFIG_NFSD_SCSILAYOUT
+ xa_init(&clp->cl_dev_fences);
#endif
INIT_LIST_HEAD(&clp->async_copies);
spin_lock_init(&clp->async_lock);
@@ -2538,6 +2541,9 @@ __destroy_client(struct nfs4_client *clp)
svc_xprt_put(clp->cl_cb_conn.cb_xprt);
atomic_add_unless(&nn->nfs4_client_count, -1, 0);
nfsd4_dec_courtesy_client_count(nn, clp);
+#ifdef CONFIG_NFSD_SCSILAYOUT
+ xa_destroy(&clp->cl_dev_fences);
+#endif
free_client(clp);
wake_up_all(&expiry_wq);
}
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index 508b7e36d846..037f4ccd2e87 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -527,6 +527,9 @@ struct nfs4_client {
struct nfsd4_cb_recall_any *cl_ra;
time64_t cl_ra_time;
+#ifdef CONFIG_NFSD_SCSILAYOUT
+ struct xarray cl_dev_fences;
+#endif
};
/* struct nfs4_client_reset
--
2.52.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH v6] NFSD: Track SCSI Persistent Registration Fencing per Client with xarray
2026-01-08 14:44 [PATCH v6] NFSD: Track SCSI Persistent Registration Fencing per Client with xarray Chuck Lever
@ 2026-01-08 16:14 ` Christoph Hellwig
2026-01-08 18:26 ` Chuck Lever
1 sibling, 0 replies; 3+ messages in thread
From: Christoph Hellwig @ 2026-01-08 16:14 UTC (permalink / raw)
To: Chuck Lever
Cc: NeilBrown, Jeff Layton, Olga Kornievskaia, Dai Ngo, Tom Talpey,
Christoph Hellwig, linux-nfs
Looks good:
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH v6] NFSD: Track SCSI Persistent Registration Fencing per Client with xarray
2026-01-08 14:44 [PATCH v6] NFSD: Track SCSI Persistent Registration Fencing per Client with xarray Chuck Lever
2026-01-08 16:14 ` Christoph Hellwig
@ 2026-01-08 18:26 ` Chuck Lever
1 sibling, 0 replies; 3+ messages in thread
From: Chuck Lever @ 2026-01-08 18:26 UTC (permalink / raw)
To: NeilBrown, Jeff Layton, Olga Kornievskaia, Dai Ngo, Tom Talpey,
Christoph Hellwig, Chuck Lever
Cc: linux-nfs
From: Chuck Lever <chuck.lever@oracle.com>
On Thu, 08 Jan 2026 09:44:21 -0500, Chuck Lever wrote:
> When a client holding pNFS SCSI layouts becomes unresponsive, the
> server revokes access by preempting the client's SCSI persistent
> reservation key. A layout recall is issued for each layout the
> client holds; if the client fails to respond, each recall triggers
> a fence operation. The first preempt for a given device succeeds
> and removes the client's key registration. Subsequent preempts for
> the same device fail because the key is no longer registered.
>
> [...]
Applied to nfsd-testing, thanks!
[1/1] NFSD: Track SCSI Persistent Registration Fencing per Client with xarray
commit: d0eb03e22c6ab956dc9c91c7a1b04b02556987c9
--
Chuck Lever
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-01-08 18:26 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-08 14:44 [PATCH v6] NFSD: Track SCSI Persistent Registration Fencing per Client with xarray Chuck Lever
2026-01-08 16:14 ` Christoph Hellwig
2026-01-08 18:26 ` Chuck Lever
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.