* [PATCH] nfs/blocklayout: allow pNFS SCSI layout without pNFS block layout
@ 2026-08-27 19:45 Scott Mayhew
2026-08-31 7:03 ` Christoph Hellwig
0 siblings, 1 reply; 2+ messages in thread
From: Scott Mayhew @ 2026-08-27 19:45 UTC (permalink / raw)
To: trondmy, anna; +Cc: linux-nfs
The pNFS block-volume layout (LAYOUT_BLOCK_VOLUME, RFC 5663) and the pNFS
SCSI layout (LAYOUT_SCSI, RFC 8154) are built from a single blocklayout
driver. Until now CONFIG_PNFS_BLOCK was an unprompted symbol that pulled
in both layout types whenever NFS_V4 and BLK_DEV_DM were enabled, so a
kernel could not offer SCSI layout without also enabling block layout and
device-mapper.
Split the two into separate, independently selectable options. Both types
share almost the entire driver (read/write path, extent tree, and the
device tree including the composite SLICE/CONCAT/STRIPE volume types), so
keep a single blocklayoutdriver module and compile only the type-specific
pieces in or out:
- block.c SIMPLE volume parsing, which resolves the device via the
userspace pipefs daemon (rpc_pipefs.c) - block only.
- scsi.c SCSI leaf volume parsing and persistent-reservation
register/unregister - SCSI only.
The remaining type-specific call sites in the shared core are guarded with
IS_ENABLED() so the reference to a not-built symbol is eliminated, and the
now cross-file helpers (bl_map_simple, bl_parse_simple, bl_parse_scsi,
bl_register_scsi, bl_unregister_scsi) are made global with prototypes in
blocklayout.h.
CONFIG_PNFS_BLOCK and CONFIG_PNFS_SCSI_LAYOUT are now prompted booleans
that only select which volume types are compiled in. Module linkage is
carried by a single internal tristate, CONFIG_PNFS_BLOCK_LAYOUT_DRIVER,
which follows NFS_V4; making the two options booleans avoids a y/m mismatch
where a built-in composite would silently drop a module-only object. SCSI
layout defaults on and no longer depends on BLK_DEV_DM; block layout now
defaults off.
blocklayout.h no longer includes device-mapper.h (it was unused); it
includes blkdev.h for the block_device/sector_t/BLK_OPEN_* definitions used
in the header.
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Scott Mayhew <smayhew@redhat.com>
---
fs/nfs/Kconfig | 20 ++-
fs/nfs/Makefile | 2 +-
fs/nfs/blocklayout/Makefile | 12 +-
fs/nfs/blocklayout/block.c | 40 ++++++
fs/nfs/blocklayout/blocklayout.c | 43 ++++---
fs/nfs/blocklayout/blocklayout.h | 14 ++-
fs/nfs/blocklayout/dev.c | 209 +++----------------------------
fs/nfs/blocklayout/scsi.c | 175 ++++++++++++++++++++++++++
8 files changed, 300 insertions(+), 215 deletions(-)
create mode 100644 fs/nfs/blocklayout/block.c
create mode 100644 fs/nfs/blocklayout/scsi.c
diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig
index 6bb30543eff0..9166ac623ba8 100644
--- a/fs/nfs/Kconfig
+++ b/fs/nfs/Kconfig
@@ -122,9 +122,27 @@ config PNFS_FILE_LAYOUT
default NFS_V4
config PNFS_BLOCK
- tristate
+ bool "pNFS block layout support"
depends on NFS_V4 && BLK_DEV_DM
+ default n
+ help
+ Enable support for the pNFS block-volume layout type (RFC 5663).
+
+config PNFS_SCSI_LAYOUT
+ bool "pNFS SCSI layout support"
+ depends on NFS_V4
default NFS_V4
+ help
+ Enable support for the pNFS SCSI layout type (RFC 8154). This does
+ not require device-mapper and can be enabled without PNFS_BLOCK.
+
+# Internal: the shared block/scsi layout driver module, built when either layout
+# type is enabled. The two options above are booleans that only select which
+# volume types are compiled in; this symbol is the single modularity knob and
+# follows NFS_V4, so the composite module never lands in both obj-y and obj-m.
+config PNFS_BLOCK_LAYOUT_DRIVER
+ tristate
+ default NFS_V4 if PNFS_BLOCK || PNFS_SCSI_LAYOUT
config PNFS_FLEXFILE_LAYOUT
tristate
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index c895521f27f3..49c06b759b60 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -34,5 +34,5 @@ nfsv4-$(CONFIG_NFS_V4_0) += nfs40client.o nfs40proc.o
nfsv4-$(CONFIG_NFS_V4_2) += nfs42proc.o nfs42xattr.o
obj-$(CONFIG_PNFS_FILE_LAYOUT) += filelayout/
-obj-$(CONFIG_PNFS_BLOCK) += blocklayout/
+obj-$(CONFIG_PNFS_BLOCK_LAYOUT_DRIVER) += blocklayout/
obj-$(CONFIG_PNFS_FLEXFILE_LAYOUT) += flexfilelayout/
diff --git a/fs/nfs/blocklayout/Makefile b/fs/nfs/blocklayout/Makefile
index 7668a1bfb5fa..832012d1c1fc 100644
--- a/fs/nfs/blocklayout/Makefile
+++ b/fs/nfs/blocklayout/Makefile
@@ -2,6 +2,14 @@
#
# Makefile for the pNFS block layout driver kernel module
#
-obj-$(CONFIG_PNFS_BLOCK) += blocklayoutdriver.o
+obj-$(CONFIG_PNFS_BLOCK_LAYOUT_DRIVER) += blocklayoutdriver.o
-blocklayoutdriver-y += blocklayout.o dev.o extent_tree.o rpc_pipefs.o
+# Shared core: device tree incl. composite SLICE/CONCAT/STRIPE volumes (used by
+# both layout types), extent tree, common layout ops, init/exit.
+blocklayoutdriver-y += blocklayout.o dev.o extent_tree.o
+
+# Block-layout-specific: SIMPLE volumes resolved via the userspace pipefs daemon.
+blocklayoutdriver-$(CONFIG_PNFS_BLOCK) += block.o rpc_pipefs.o
+
+# SCSI-layout-specific: SCSI leaf volume parse and PR register/unregister.
+blocklayoutdriver-$(CONFIG_PNFS_SCSI_LAYOUT) += scsi.o
diff --git a/fs/nfs/blocklayout/block.c b/fs/nfs/blocklayout/block.c
new file mode 100644
index 000000000000..530373a71c98
--- /dev/null
+++ b/fs/nfs/blocklayout/block.c
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2014-2016 Christoph Hellwig.
+ */
+#include <linux/blkdev.h>
+#include <linux/nfs4.h>
+#include <linux/nfs_fs.h>
+#include <linux/nfs_xdr.h>
+
+#include "blocklayout.h"
+
+#define NFSDBG_FACILITY NFSDBG_PNFS_LD
+
+int
+bl_parse_simple(struct nfs_server *server, struct pnfs_block_dev *d,
+ struct pnfs_block_volume *volumes, int idx, gfp_t gfp_mask)
+{
+ struct pnfs_block_volume *v = &volumes[idx];
+ struct file *bdev_file;
+ dev_t dev;
+
+ dev = bl_resolve_deviceid(server, v, gfp_mask);
+ if (!dev)
+ return -EIO;
+
+ bdev_file = bdev_file_open_by_dev(dev, BLK_OPEN_READ | BLK_OPEN_WRITE,
+ NULL, NULL);
+ if (IS_ERR(bdev_file)) {
+ printk(KERN_WARNING "pNFS: failed to open device %d:%d (%ld)\n",
+ MAJOR(dev), MINOR(dev), PTR_ERR(bdev_file));
+ return PTR_ERR(bdev_file);
+ }
+ d->bdev_file = bdev_file;
+ d->len = bdev_nr_bytes(file_bdev(bdev_file));
+ d->map = bl_map_simple;
+
+ printk(KERN_INFO "pNFS: using block device %s\n",
+ file_bdev(bdev_file)->bd_disk->disk_name);
+ return 0;
+}
diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c
index d54a141a89b3..8f85849d3e05 100644
--- a/fs/nfs/blocklayout/blocklayout.c
+++ b/fs/nfs/blocklayout/blocklayout.c
@@ -1005,27 +1005,33 @@ static struct pnfs_layoutdriver_type scsilayout_type = {
static int __init nfs4blocklayout_init(void)
{
- int ret;
+ int ret = 0;
dprintk("%s: NFSv4 Block Layout Driver Registering...\n", __func__);
- ret = bl_init_pipefs();
- if (ret)
- goto out;
+ if (IS_ENABLED(CONFIG_PNFS_BLOCK)) {
+ ret = bl_init_pipefs();
+ if (ret)
+ goto out;
- ret = pnfs_register_layoutdriver(&blocklayout_type);
- if (ret)
- goto out_cleanup_pipe;
+ ret = pnfs_register_layoutdriver(&blocklayout_type);
+ if (ret)
+ goto out_cleanup_pipe;
+ }
- ret = pnfs_register_layoutdriver(&scsilayout_type);
- if (ret)
- goto out_unregister_block;
+ if (IS_ENABLED(CONFIG_PNFS_SCSI_LAYOUT)) {
+ ret = pnfs_register_layoutdriver(&scsilayout_type);
+ if (ret)
+ goto out_unregister_block;
+ }
return 0;
out_unregister_block:
- pnfs_unregister_layoutdriver(&blocklayout_type);
+ if (IS_ENABLED(CONFIG_PNFS_BLOCK))
+ pnfs_unregister_layoutdriver(&blocklayout_type);
out_cleanup_pipe:
- bl_cleanup_pipefs();
+ if (IS_ENABLED(CONFIG_PNFS_BLOCK))
+ bl_cleanup_pipefs();
out:
return ret;
}
@@ -1035,13 +1041,20 @@ static void __exit nfs4blocklayout_exit(void)
dprintk("%s: NFSv4 Block Layout Driver Unregistering...\n",
__func__);
- pnfs_unregister_layoutdriver(&scsilayout_type);
- pnfs_unregister_layoutdriver(&blocklayout_type);
- bl_cleanup_pipefs();
+ if (IS_ENABLED(CONFIG_PNFS_SCSI_LAYOUT))
+ pnfs_unregister_layoutdriver(&scsilayout_type);
+ if (IS_ENABLED(CONFIG_PNFS_BLOCK)) {
+ pnfs_unregister_layoutdriver(&blocklayout_type);
+ bl_cleanup_pipefs();
+ }
}
+#if IS_ENABLED(CONFIG_PNFS_BLOCK)
MODULE_ALIAS("nfs-layouttype4-3");
+#endif
+#if IS_ENABLED(CONFIG_PNFS_SCSI_LAYOUT)
MODULE_ALIAS("nfs-layouttype4-5");
+#endif
module_init(nfs4blocklayout_init);
module_exit(nfs4blocklayout_exit);
diff --git a/fs/nfs/blocklayout/blocklayout.h b/fs/nfs/blocklayout/blocklayout.h
index 6da40ca19570..07740bbfeb67 100644
--- a/fs/nfs/blocklayout/blocklayout.h
+++ b/fs/nfs/blocklayout/blocklayout.h
@@ -32,7 +32,7 @@
#ifndef FS_NFS_NFS4BLOCKLAYOUT_H
#define FS_NFS_NFS4BLOCKLAYOUT_H
-#include <linux/device-mapper.h>
+#include <linux/blkdev.h>
#include <linux/nfs_fs.h>
#include <linux/sunrpc/rpc_pipe_fs.h>
@@ -182,6 +182,18 @@ bool bl_register_dev(struct pnfs_block_dev *d);
struct nfs4_deviceid_node *bl_alloc_deviceid_node(struct nfs_server *server,
struct pnfs_device *pdev, gfp_t gfp_mask);
void bl_free_deviceid_node(struct nfs4_deviceid_node *d);
+bool bl_map_simple(struct pnfs_block_dev *dev, u64 offset,
+ struct pnfs_block_dev_map *map);
+
+/* block.c */
+int bl_parse_simple(struct nfs_server *server, struct pnfs_block_dev *d,
+ struct pnfs_block_volume *volumes, int idx, gfp_t gfp_mask);
+
+/* scsi.c */
+int bl_parse_scsi(struct nfs_server *server, struct pnfs_block_dev *d,
+ struct pnfs_block_volume *volumes, int idx, gfp_t gfp_mask);
+bool bl_register_scsi(struct pnfs_block_dev *dev);
+void bl_unregister_scsi(struct pnfs_block_dev *dev);
/* extent_tree.c */
int ext_tree_insert(struct pnfs_block_layout *bl,
diff --git a/fs/nfs/blocklayout/dev.c b/fs/nfs/blocklayout/dev.c
index 368d20daf67b..897e3022da3d 100644
--- a/fs/nfs/blocklayout/dev.c
+++ b/fs/nfs/blocklayout/dev.c
@@ -4,48 +4,14 @@
*/
#include <linux/sunrpc/svc.h>
#include <linux/blkdev.h>
-#include <linux/fs_struct.h>
#include <linux/nfs4.h>
#include <linux/nfs_fs.h>
#include <linux/nfs_xdr.h>
-#include <linux/pr.h>
#include "blocklayout.h"
-#include "../nfs4trace.h"
#define NFSDBG_FACILITY NFSDBG_PNFS_LD
-static void bl_unregister_scsi(struct pnfs_block_dev *dev)
-{
- struct block_device *bdev = file_bdev(dev->bdev_file);
- const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
- int status;
-
- status = ops->pr_register(bdev, dev->pr_key, 0, false);
- if (status)
- trace_bl_pr_key_unreg_err(bdev, dev->pr_key, status);
- else
- trace_bl_pr_key_unreg(bdev, dev->pr_key);
-}
-
-static bool bl_register_scsi(struct pnfs_block_dev *dev)
-{
- struct block_device *bdev = file_bdev(dev->bdev_file);
- const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
- int status;
-
- if (test_and_set_bit(PNFS_BDEV_REGISTERED, &dev->flags))
- return true;
-
- status = ops->pr_register(bdev, 0, dev->pr_key, true);
- if (status) {
- trace_bl_pr_key_reg_err(bdev, dev->pr_key, status);
- return false;
- }
- trace_bl_pr_key_reg(bdev, dev->pr_key);
- return true;
-}
-
static void bl_unregister_dev(struct pnfs_block_dev *dev)
{
u32 i;
@@ -56,7 +22,8 @@ static void bl_unregister_dev(struct pnfs_block_dev *dev)
return;
}
- if (dev->type == PNFS_BLOCK_VOLUME_SCSI &&
+ if (IS_ENABLED(CONFIG_PNFS_SCSI_LAYOUT) &&
+ dev->type == PNFS_BLOCK_VOLUME_SCSI &&
test_and_clear_bit(PNFS_BDEV_REGISTERED, &dev->flags))
bl_unregister_scsi(dev);
}
@@ -76,7 +43,8 @@ bool bl_register_dev(struct pnfs_block_dev *dev)
return true;
}
- if (dev->type == PNFS_BLOCK_VOLUME_SCSI)
+ if (IS_ENABLED(CONFIG_PNFS_SCSI_LAYOUT) &&
+ dev->type == PNFS_BLOCK_VOLUME_SCSI)
return bl_register_scsi(dev);
return true;
}
@@ -222,7 +190,7 @@ nfs4_block_decode_volume(struct xdr_stream *xdr, struct pnfs_block_volume *b)
return 0;
}
-static bool bl_map_simple(struct pnfs_block_dev *dev, u64 offset,
+bool bl_map_simple(struct pnfs_block_dev *dev, u64 offset,
struct pnfs_block_dev_map *map)
{
map->start = dev->start;
@@ -291,162 +259,6 @@ bl_parse_deviceid(struct nfs_server *server, struct pnfs_block_dev *d,
struct pnfs_block_volume *volumes, int idx, gfp_t gfp_mask);
-static int
-bl_parse_simple(struct nfs_server *server, struct pnfs_block_dev *d,
- struct pnfs_block_volume *volumes, int idx, gfp_t gfp_mask)
-{
- struct pnfs_block_volume *v = &volumes[idx];
- struct file *bdev_file;
- dev_t dev;
-
- dev = bl_resolve_deviceid(server, v, gfp_mask);
- if (!dev)
- return -EIO;
-
- bdev_file = bdev_file_open_by_dev(dev, BLK_OPEN_READ | BLK_OPEN_WRITE,
- NULL, NULL);
- if (IS_ERR(bdev_file)) {
- printk(KERN_WARNING "pNFS: failed to open device %d:%d (%ld)\n",
- MAJOR(dev), MINOR(dev), PTR_ERR(bdev_file));
- return PTR_ERR(bdev_file);
- }
- d->bdev_file = bdev_file;
- d->len = bdev_nr_bytes(file_bdev(bdev_file));
- d->map = bl_map_simple;
-
- printk(KERN_INFO "pNFS: using block device %s\n",
- file_bdev(bdev_file)->bd_disk->disk_name);
- return 0;
-}
-
-static bool
-bl_validate_designator(struct pnfs_block_volume *v)
-{
- switch (v->scsi.designator_type) {
- case PS_DESIGNATOR_EUI64:
- if (v->scsi.code_set != PS_CODE_SET_BINARY)
- return false;
-
- if (v->scsi.designator_len != 8 &&
- v->scsi.designator_len != 10 &&
- v->scsi.designator_len != 16)
- return false;
-
- return true;
- case PS_DESIGNATOR_NAA:
- if (v->scsi.code_set != PS_CODE_SET_BINARY)
- return false;
-
- if (v->scsi.designator_len != 8 &&
- v->scsi.designator_len != 16)
- return false;
-
- return true;
- case PS_DESIGNATOR_T10:
- case PS_DESIGNATOR_NAME:
- pr_err("pNFS: unsupported designator "
- "(code set %d, type %d, len %d.\n",
- v->scsi.code_set,
- v->scsi.designator_type,
- v->scsi.designator_len);
- return false;
- default:
- pr_err("pNFS: invalid designator "
- "(code set %d, type %d, len %d.\n",
- v->scsi.code_set,
- v->scsi.designator_type,
- v->scsi.designator_len);
- return false;
- }
-}
-
-static struct file *
-bl_open_path(struct pnfs_block_volume *v, const char *prefix)
-{
- struct file *bdev_file;
- const char *devname __free(kfree) = NULL;
-
- devname = kasprintf(GFP_KERNEL, "/dev/disk/by-id/%s%*phN",
- prefix, v->scsi.designator_len, v->scsi.designator);
- if (!devname)
- return ERR_PTR(-ENOMEM);
-
- if (tsk_is_kthread(current)) {
- scoped_with_init_fs()
- bdev_file = bdev_file_open_by_path(devname,
- BLK_OPEN_READ | BLK_OPEN_WRITE,
- NULL, NULL);
- } else {
- bdev_file = bdev_file_open_by_path(devname,
- BLK_OPEN_READ | BLK_OPEN_WRITE, NULL, NULL);
- }
- if (IS_ERR(bdev_file)) {
- dprintk("failed to open device %s (%ld)\n",
- devname, PTR_ERR(bdev_file));
- } else {
- pr_info("pNFS: using block device %s\n",
- file_bdev(bdev_file)->bd_disk->disk_name);
- }
-
- return bdev_file;
-}
-
-static int
-bl_parse_scsi(struct nfs_server *server, struct pnfs_block_dev *d,
- struct pnfs_block_volume *volumes, int idx, gfp_t gfp_mask)
-{
- struct pnfs_block_volume *v = &volumes[idx];
- struct block_device *bdev;
- const struct pr_ops *ops;
- struct file *bdev_file;
- int error;
-
- if (!bl_validate_designator(v))
- return -EINVAL;
-
- /*
- * Try to open the RH/Fedora specific dm-mpath udev path first, as the
- * wwn- links will only point to the first discovered SCSI device there.
- * On other distributions like Debian, the default SCSI by-id path will
- * point to the dm-multipath device if one exists.
- */
- bdev_file = bl_open_path(v, "dm-uuid-mpath-0x");
- if (IS_ERR(bdev_file))
- bdev_file = bl_open_path(v, "wwn-0x");
- if (IS_ERR(bdev_file))
- bdev_file = bl_open_path(v, "nvme-eui.");
- if (IS_ERR(bdev_file)) {
- pr_warn("pNFS: no device found for volume %*phN\n",
- v->scsi.designator_len, v->scsi.designator);
- return PTR_ERR(bdev_file);
- }
- d->bdev_file = bdev_file;
- bdev = file_bdev(bdev_file);
-
- d->len = bdev_nr_bytes(bdev);
- d->map = bl_map_simple;
- d->pr_key = v->scsi.pr_key;
-
- if (d->len == 0) {
- error = -ENODEV;
- goto out_blkdev_put;
- }
-
- ops = bdev->bd_disk->fops->pr_ops;
- if (!ops) {
- pr_err("pNFS: block device %s does not support reservations.",
- bdev->bd_disk->disk_name);
- error = -EINVAL;
- goto out_blkdev_put;
- }
-
- return 0;
-
-out_blkdev_put:
- fput(d->bdev_file);
- return error;
-}
-
static int
bl_parse_slice(struct nfs_server *server, struct pnfs_block_dev *d,
struct pnfs_block_volume *volumes, int idx, gfp_t gfp_mask)
@@ -529,7 +341,9 @@ bl_parse_deviceid(struct nfs_server *server, struct pnfs_block_dev *d,
switch (d->type) {
case PNFS_BLOCK_VOLUME_SIMPLE:
- return bl_parse_simple(server, d, volumes, idx, gfp_mask);
+ if (IS_ENABLED(CONFIG_PNFS_BLOCK))
+ return bl_parse_simple(server, d, volumes, idx, gfp_mask);
+ break;
case PNFS_BLOCK_VOLUME_SLICE:
return bl_parse_slice(server, d, volumes, idx, gfp_mask);
case PNFS_BLOCK_VOLUME_CONCAT:
@@ -537,11 +351,16 @@ bl_parse_deviceid(struct nfs_server *server, struct pnfs_block_dev *d,
case PNFS_BLOCK_VOLUME_STRIPE:
return bl_parse_stripe(server, d, volumes, idx, gfp_mask);
case PNFS_BLOCK_VOLUME_SCSI:
- return bl_parse_scsi(server, d, volumes, idx, gfp_mask);
+ if (IS_ENABLED(CONFIG_PNFS_SCSI_LAYOUT))
+ return bl_parse_scsi(server, d, volumes, idx, gfp_mask);
+ break;
default:
dprintk("unsupported volume type: %d\n", d->type);
return -EIO;
}
+
+ dprintk("unsupported volume type: %d\n", d->type);
+ return -EIO;
}
struct nfs4_deviceid_node *
diff --git a/fs/nfs/blocklayout/scsi.c b/fs/nfs/blocklayout/scsi.c
new file mode 100644
index 000000000000..2a691e5be9a2
--- /dev/null
+++ b/fs/nfs/blocklayout/scsi.c
@@ -0,0 +1,175 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2014-2016 Christoph Hellwig.
+ */
+#include <linux/sunrpc/svc.h>
+#include <linux/blkdev.h>
+#include <linux/fs_struct.h>
+#include <linux/nfs4.h>
+#include <linux/nfs_fs.h>
+#include <linux/nfs_xdr.h>
+#include <linux/pr.h>
+
+#include "blocklayout.h"
+#include "../nfs4trace.h"
+
+#define NFSDBG_FACILITY NFSDBG_PNFS_LD
+
+void bl_unregister_scsi(struct pnfs_block_dev *dev)
+{
+ struct block_device *bdev = file_bdev(dev->bdev_file);
+ const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
+ int status;
+
+ status = ops->pr_register(bdev, dev->pr_key, 0, false);
+ if (status)
+ trace_bl_pr_key_unreg_err(bdev, dev->pr_key, status);
+ else
+ trace_bl_pr_key_unreg(bdev, dev->pr_key);
+}
+
+bool bl_register_scsi(struct pnfs_block_dev *dev)
+{
+ struct block_device *bdev = file_bdev(dev->bdev_file);
+ const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
+ int status;
+
+ if (test_and_set_bit(PNFS_BDEV_REGISTERED, &dev->flags))
+ return true;
+
+ status = ops->pr_register(bdev, 0, dev->pr_key, true);
+ if (status) {
+ trace_bl_pr_key_reg_err(bdev, dev->pr_key, status);
+ return false;
+ }
+ trace_bl_pr_key_reg(bdev, dev->pr_key);
+ return true;
+}
+
+static bool
+bl_validate_designator(struct pnfs_block_volume *v)
+{
+ switch (v->scsi.designator_type) {
+ case PS_DESIGNATOR_EUI64:
+ if (v->scsi.code_set != PS_CODE_SET_BINARY)
+ return false;
+
+ if (v->scsi.designator_len != 8 &&
+ v->scsi.designator_len != 10 &&
+ v->scsi.designator_len != 16)
+ return false;
+
+ return true;
+ case PS_DESIGNATOR_NAA:
+ if (v->scsi.code_set != PS_CODE_SET_BINARY)
+ return false;
+
+ if (v->scsi.designator_len != 8 &&
+ v->scsi.designator_len != 16)
+ return false;
+
+ return true;
+ case PS_DESIGNATOR_T10:
+ case PS_DESIGNATOR_NAME:
+ pr_err("pNFS: unsupported designator "
+ "(code set %d, type %d, len %d.\n",
+ v->scsi.code_set,
+ v->scsi.designator_type,
+ v->scsi.designator_len);
+ return false;
+ default:
+ pr_err("pNFS: invalid designator "
+ "(code set %d, type %d, len %d.\n",
+ v->scsi.code_set,
+ v->scsi.designator_type,
+ v->scsi.designator_len);
+ return false;
+ }
+}
+
+static struct file *
+bl_open_path(struct pnfs_block_volume *v, const char *prefix)
+{
+ struct file *bdev_file;
+ const char *devname __free(kfree) = NULL;
+
+ devname = kasprintf(GFP_KERNEL, "/dev/disk/by-id/%s%*phN",
+ prefix, v->scsi.designator_len, v->scsi.designator);
+ if (!devname)
+ return ERR_PTR(-ENOMEM);
+
+ if (tsk_is_kthread(current)) {
+ scoped_with_init_fs()
+ bdev_file = bdev_file_open_by_path(devname,
+ BLK_OPEN_READ | BLK_OPEN_WRITE,
+ NULL, NULL);
+ } else {
+ bdev_file = bdev_file_open_by_path(devname,
+ BLK_OPEN_READ | BLK_OPEN_WRITE, NULL, NULL);
+ }
+ if (IS_ERR(bdev_file)) {
+ dprintk("failed to open device %s (%ld)\n",
+ devname, PTR_ERR(bdev_file));
+ } else {
+ pr_info("pNFS: using block device %s\n",
+ file_bdev(bdev_file)->bd_disk->disk_name);
+ }
+
+ return bdev_file;
+}
+
+int
+bl_parse_scsi(struct nfs_server *server, struct pnfs_block_dev *d,
+ struct pnfs_block_volume *volumes, int idx, gfp_t gfp_mask)
+{
+ struct pnfs_block_volume *v = &volumes[idx];
+ struct block_device *bdev;
+ const struct pr_ops *ops;
+ struct file *bdev_file;
+ int error;
+
+ if (!bl_validate_designator(v))
+ return -EINVAL;
+
+ /*
+ * Try to open the RH/Fedora specific dm-mpath udev path first, as the
+ * wwn- links will only point to the first discovered SCSI device there.
+ * On other distributions like Debian, the default SCSI by-id path will
+ * point to the dm-multipath device if one exists.
+ */
+ bdev_file = bl_open_path(v, "dm-uuid-mpath-0x");
+ if (IS_ERR(bdev_file))
+ bdev_file = bl_open_path(v, "wwn-0x");
+ if (IS_ERR(bdev_file))
+ bdev_file = bl_open_path(v, "nvme-eui.");
+ if (IS_ERR(bdev_file)) {
+ pr_warn("pNFS: no device found for volume %*phN\n",
+ v->scsi.designator_len, v->scsi.designator);
+ return PTR_ERR(bdev_file);
+ }
+ d->bdev_file = bdev_file;
+ bdev = file_bdev(bdev_file);
+
+ d->len = bdev_nr_bytes(bdev);
+ d->map = bl_map_simple;
+ d->pr_key = v->scsi.pr_key;
+
+ if (d->len == 0) {
+ error = -ENODEV;
+ goto out_blkdev_put;
+ }
+
+ ops = bdev->bd_disk->fops->pr_ops;
+ if (!ops) {
+ pr_err("pNFS: block device %s does not support reservations.",
+ bdev->bd_disk->disk_name);
+ error = -EINVAL;
+ goto out_blkdev_put;
+ }
+
+ return 0;
+
+out_blkdev_put:
+ fput(d->bdev_file);
+ return error;
+}
--
2.55.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH] nfs/blocklayout: allow pNFS SCSI layout without pNFS block layout
2026-08-27 19:45 [PATCH] nfs/blocklayout: allow pNFS SCSI layout without pNFS block layout Scott Mayhew
@ 2026-08-31 7:03 ` Christoph Hellwig
0 siblings, 0 replies; 2+ messages in thread
From: Christoph Hellwig @ 2026-08-31 7:03 UTC (permalink / raw)
To: Scott Mayhew; +Cc: trondmy, anna, linux-nfs
Supporting SCSI layout with block layout makes totaly sense, but please
do it without all the gracious renaming and annoying AI slop commit log.
Take a look at show nfsd handled this with CONFIG_NFSD_BLOCKLAYOUT and
CONFIG_NFSD_SCSILAYOUT as that is the model that applies here as well.
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-08-31 7:03 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-27 19:45 [PATCH] nfs/blocklayout: allow pNFS SCSI layout without pNFS block layout Scott Mayhew
2026-08-31 7:03 ` Christoph Hellwig
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox