Files
linux-stable-mirror/include/linux/exportfs_block.h
T
Christoph Hellwig da9baa5470 exportfs,nfsd: rework checking for layout-based block device access support
Currently NFSD hard codes checking support for block-style layouts.
Lift the checks into a file system-helper and provide a exportfs-level
helper to implement the typical checks.

This prepares for supporting block layout export of multiple devices
per file system.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Link: https://patch.msgid.link/20260423181854.743150-5-cel@kernel.org
Signed-off-by: Christian Brauner <brauner@kernel.org>
2026-05-11 11:11:48 +02:00

89 lines
2.5 KiB
C

/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2014-2026 Christoph Hellwig.
*
* Support for exportfs-based layout grants for direct block device access.
*/
#ifndef LINUX_EXPORTFS_BLOCK_H
#define LINUX_EXPORTFS_BLOCK_H 1
#include <linux/blkdev.h>
#include <linux/exportfs.h>
#include <linux/fs.h>
struct inode;
struct iomap;
struct super_block;
/*
* There are the two types of block-style layout support:
* - In-band implies a device identified by a unique cookie inside the actual
* device address space checked by the ->get_uuid method as used by the pNFS
* block layout. This is a bit dangerous and deprecated.
* - Out of band implies identification by out of band unique identifiers
* specified by the storage protocol, which is much safer and used by the
* pNFS SCSI/NVMe layouts.
*/
typedef unsigned int __bitwise expfs_block_layouts_t;
#define EXPFS_BLOCK_FLAG(__bit) \
((__force expfs_block_layouts_t)(1u << __bit))
#define EXPFS_BLOCK_IN_BAND_ID EXPFS_BLOCK_FLAG(0)
#define EXPFS_BLOCK_OUT_OF_BAND_ID EXPFS_BLOCK_FLAG(1)
struct exportfs_block_ops {
/*
* Returns the EXPFS_BLOCK_* bitmap of supported layout types.
*/
expfs_block_layouts_t (*layouts_supported)(struct super_block *sb);
/*
* Get the in-band device unique signature exposed to clients.
*/
int (*get_uuid)(struct super_block *sb, u8 *buf, u32 *len, u64 *offset);
/*
* Map blocks for direct block access.
* If @write is %true, also allocate the blocks for the range if needed.
*/
int (*map_blocks)(struct inode *inode, loff_t offset, u64 len,
struct iomap *iomap, bool write,
u32 *device_generation);
/*
* Commit blocks previously handed out by ->map_blocks and written to by
* the client.
*/
int (*commit_blocks)(struct inode *inode, struct iomap *iomaps,
int nr_iomaps, loff_t new_size);
};
static inline bool
exportfs_bdev_supports_out_of_band_id(struct block_device *bdev)
{
return bdev->bd_disk->fops->pr_ops &&
bdev->bd_disk->fops->get_unique_id;
}
#ifdef CONFIG_EXPORTFS_BLOCK_OPS
static inline expfs_block_layouts_t
exportfs_layouts_supported(struct super_block *sb)
{
const struct exportfs_block_ops *bops = sb->s_export_op->block_ops;
if (!bops ||
!bops->layouts_supported ||
WARN_ON_ONCE(!bops->map_blocks) ||
WARN_ON_ONCE(!bops->commit_blocks))
return 0;
return bops->layouts_supported(sb);
}
#else
static inline expfs_block_layouts_t
exportfs_layouts_supported(struct super_block *sb)
{
return 0;
}
#endif /* CONFIG_EXPORTFS_BLOCK_OPS */
#endif /* LINUX_EXPORTFS_BLOCK_H */