cleanup block-style layouts exports
Subsystems (5)
Chuck Lever
maintainerv3 cover cleanup block-style layouts exports
From: Chuck Lever <[email protected]>
Following up on https://lore.kernel.org/linux-nfs/[email protected]/#r
Here is the current version of Christoph's patches that are in nfsd-testing. Christian prefers to see them taken through the VFS tree. Once the patches are applied there, I will rebase nfsd-next and nfsd-testing on that tree and drop these.
Christoph Hellwig (4):
nfsd/blocklayout: always ignore loca_time_modify
exportfs: split out the ops for layout-based block device access
exportfs: don't pass struct iattr to ->commit_blocks exportfs,nfsd: rework checking for layout-based block device access
support
MAINTAINERS | 2 +- fs/nfsd/blocklayout.c | 37 +++++++------- fs/nfsd/export.c | 3 +- fs/nfsd/nfs4layouts.c | 29 ++++------- fs/xfs/xfs_export.c | 4 +- fs/xfs/xfs_pnfs.c | 44 ++++++++++++----- fs/xfs/xfs_pnfs.h | 11 ++--- include/linux/exportfs.h | 25 ++++------ include/linux/exportfs_block.h | 88 ++++++++++++++++++++++++++++++++++ 9 files changed, 162 insertions(+), 81 deletions(-) create mode 100644 include/linux/exportfs_block.h
Signature · 1 line
2.53.0
Chuck Lever
maintainerPATCH v3 1/4 nfsd/blocklayout: always ignore loca_time_modify
From: Christoph Hellwig <[email protected]>
RFC 8881 Section 18.42 makes it clear that the client provided timestamp is a "may" condition, and clients that want to force a specific timestamp should send a separate SETATTR in the compound.
Since commit b82f92d5dd1a ("fs: have setattr_copy handle multigrain timestamps appropriately") the ia_mtime value is ignored by file systems using multi-grain timestamps like XFS, which is the only file system supporting blocklayout exports right now, so make that explicit in NFSD as well.
--- fs/nfsd/blocklayout.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-)
fs/nfsd/blocklayout.c +10 -5
@@ -179,15 +179,20 @@ static __be32 nfsd4_block_commit_blocks(struct inode *inode, struct nfsd4_layoutcommit *lcp, struct iomap *iomaps, int nr_iomaps) { - struct timespec64 mtime = inode_get_mtime(inode); struct iattr iattr = { .ia_valid = 0 };int error; -if (lcp->lc_mtime.tv_nsec ==UTIME_NOW || -timespec64_compare (&lcp->lc_mtime, &mtime) <0 ) - lcp->lc_mtime =current_time (inode); +/* +* This ignores the client provided mtime in loca_time_modify, as a +* fully client specified mtime doesn't really fit into the Linux +* multi-grain timestamp architecture. +* +* RFC 8881 Section 18.42 makes it clear that the client provided +* timestamp is a "may" condition, and clients that want to force a +* specific timestamp should send a separate SETATTR in the compound. +*/ iattr.ia_valid |=ATTR_ATIME |ATTR_CTIME |ATTR_MTIME ; - iattr.ia_atime = iattr.ia_ctime = iattr.ia_mtime = lcp->lc_mtime; + iattr.ia_atime = iattr.ia_ctime = iattr.ia_mtime =current_time (inode);if (lcp->lc_size_chg) { iattr.ia_valid |=ATTR_SIZE ;
Signature · 1 line
2.53.0
Christoph Hellwig
reviewerRe: [PATCH v3 1/4] nfsd/blocklayout: always ignore loca_time_modify
I got two resends of my series without cover letters in my inbox. Was this just an accident in sending out some internal tree?
Chuck Lever
maintainerRe: [PATCH v3 1/4] nfsd/blocklayout: always ignore loca_time_modify
Quoted 2 lines · Christoph Hellwig
I got two resends of my series without cover letters in my inbox. Was this just an accident in sending out some internal tree?
The first resend picked up the wrong patch set, and was a mistake.
The purpose of the second resend was to transfer ownership of this series to Christian, including fixes and forward porting changes. The cover letter was not included in the repost because it is not committed to the new branch.
Signature · 1 line
Chuck Lever
Chuck Lever
maintainerPATCH v3 2/4 exportfs: split out the ops for layout-based block device access
In reply to Chuck LeverFrom: Christoph Hellwig <[email protected]>
The support to grant layouts for direct block device access works at a very different layer than the rest of exports. Split the methods for it into a separate struct, and move that into a separate header to better split things out. The pointer to the new operation vector is kept in export_operations to avoid bloating the super_block.
--- MAINTAINERS | 2 +- fs/nfsd/blocklayout.c | 14 ++++++------ fs/nfsd/nfs4layouts.c | 9 ++++---- fs/xfs/xfs_export.c | 4 +--- fs/xfs/xfs_pnfs.c | 12 ++++++++--- fs/xfs/xfs_pnfs.h | 11 +++++----- include/linux/exportfs.h | 25 +++++++--------------- include/linux/exportfs_block.h | 39 ++++++++++++++++++++++++++++++++++ 8 files changed, 74 insertions(+), 42 deletions(-) create mode 100644 include/linux/exportfs_block.h
MAINTAINERS +1 -1
@@ -9892,7 +9892,7 @@ S: Supported F: Documentation/filesystems/nfs/exporting.rst F: fs/exportfs/ F: fs/fhandle.c -F: include/linux/exportfs.h +F: include/linux/exportfs*.h FILESYSTEMS [IDMAPPED MOUNTS] M: Christian Brauner <[email protected]>
fs/nfsd/blocklayout.c +7 -7
@@ -2,7 +2,7 @@/* * Copyright (c) 2014-2016 Christoph Hellwig. */ -#include <linux/exportfs.h> +#include <linux/exportfs_block.h> #include <linux/iomap.h> #include <linux/slab.h> #include <linux/pr.h>
@@ -32,8 +32,8 @@ nfsd4_block_map_extent(struct inode *inode, const struct svc_fh *fhp,u32 device_generation =0 ;int error; - error = sb->s_export_op->map_blocks (inode, offset, length, &iomap, - iomode !=IOMODE_READ , &device_generation); + error = sb->s_export_op->block_ops->map_blocks (inode, offset, length, + &iomap, iomode !=IOMODE_READ , &device_generation);if (error) {if (error == -ENXIO )return nfserr_layoutunavailable;
@@ -199,8 +199,8 @@ nfsd4_block_commit_blocks(struct inode *inode, struct nfsd4_layoutcommit *lcp, iattr.ia_size = lcp->lc_newsize; } - error = inode->i_sb->s_export_op->commit_blocks (inode, iomaps, - nr_iomaps, &iattr); + error = inode->i_sb->s_export_op->block_ops->commit_blocks (inode, + iomaps, nr_iomaps, &iattr);kfree (iomaps);return nfserrno (error); }
@@ -223,8 +223,8 @@ nfsd4_block_get_device_info_simple(struct super_block *sb, b->type =PNFS_BLOCK_VOLUME_SIMPLE ; b->simple.sig_len =PNFS_BLOCK_UUID_LEN ; -return sb->s_export_op->get_uuid (sb, b->simple.sig, &b->simple.sig_len, - &b->simple.offset); +return sb->s_export_op->block_ops->get_uuid (sb, b->simple.sig, + &b->simple.sig_len, &b->simple.offset); } static __be32
fs/nfsd/nfs4layouts.c +4 -5
@@ -3,6 +3,7 @@* Copyright (c) 2014 Christoph Hellwig. */ #include <linux/blkdev.h> +#include <linux/exportfs_block.h> #include <linux/kmod.h> #include <linux/file.h> #include <linux/jhash.h>
@@ -129,6 +130,7 @@ void nfsd4_setup_layout_type(struct svc_export *exp) {#if defined(CONFIG_NFSD_BLOCKLAYOUT ) || defined(CONFIG_NFSD_SCSILAYOUT )struct super_block *sb = exp->ex_path.mnt->mnt_sb; +const struct exportfs_block_ops *bops = sb->s_export_op->block_ops;#endif if (!(exp->ex_flags &NFSEXP_PNFS ))
@@ -138,14 +140,11 @@ void nfsd4_setup_layout_type(struct svc_export *exp) exp->ex_layout_types |=1 <<LAYOUT_FLEX_FILES ;#endif #ifdef CONFIG_NFSD_BLOCKLAYOUT -if (sb->s_export_op->get_uuid && - sb->s_export_op->map_blocks && - sb->s_export_op->commit_blocks) +if (bops && bops->get_uuid && bops->map_blocks && bops->commit_blocks) exp->ex_layout_types |=1 <<LAYOUT_BLOCK_VOLUME ;#endif #ifdef CONFIG_NFSD_SCSILAYOUT -if (sb->s_export_op->map_blocks && - sb->s_export_op->commit_blocks && +if (bops && bops->map_blocks && bops->commit_blocks && sb->s_bdev && sb->s_bdev->bd_disk->fops->pr_ops && sb->s_bdev->bd_disk->fops->get_unique_id)
fs/xfs/xfs_export.c +1 -3
@@ -244,8 +244,6 @@ const struct export_operations xfs_export_operations = { .get_parent = xfs_fs_get_parent, .commit_metadata = xfs_fs_nfs_commit_metadata, #ifdef CONFIG_EXPORTFS_BLOCK_OPS - .get_uuid = xfs_fs_get_uuid, - .map_blocks = xfs_fs_map_blocks, - .commit_blocks = xfs_fs_commit_blocks, + .block_ops = &xfs_export_block_ops,#endif };
fs/xfs/xfs_pnfs.c +9 -3
@@ -49,7 +49,7 @@ xfs_break_leased_layouts(* Get a unique ID including its location so that the client can identify * the exported device. */ -int +static int xfs_fs_get_uuid( struct super_block *sb, u8 *buf,
@@ -104,7 +104,7 @@ xfs_fs_map_update_inode(/* * Get a layout for the pNFS client. */ -int +static int xfs_fs_map_blocks( struct inode *inode, loff_t offset,
@@ -252,7 +252,7 @@ xfs_pnfs_validate_isize(* to manually flush the cache here similar to what the fsync code path does * for datasyncs on files that have no dirty metadata. */ -int +static int xfs_fs_commit_blocks( struct inode *inode, struct iomap *maps,
@@ -332,3 +332,9 @@ xfs_fs_commit_blocks(xfs_iunlock (ip,XFS_IOLOCK_EXCL );return error; } + +const struct exportfs_block_ops xfs_export_block_ops = { + .get_uuid = xfs_fs_get_uuid, + .map_blocks = xfs_fs_map_blocks, + .commit_blocks = xfs_fs_commit_blocks, +};
fs/xfs/xfs_pnfs.h +5 -6
@@ -2,13 +2,9 @@#ifndef _XFS_PNFS_H#define _XFS_PNFS_H 1 -#ifdef CONFIG_EXPORTFS_BLOCK_OPS -int xfs_fs_get_uuid (struct super_block *sb,u8 *buf,u32 *len,u64 *offset); -int xfs_fs_map_blocks (struct inode *inode,loff_t offset,u64 length, -struct iomap *iomap,bool write,u32 *device_generation); -int xfs_fs_commit_blocks (struct inode *inode,struct iomap *maps,int nr_maps, -struct iattr *iattr); +#include <linux/exportfs_block.h> +#ifdef CONFIG_EXPORTFS_BLOCK_OPS int xfs_break_leased_layouts (struct inode *inode,uint *iolock,bool *did_unlock);#else
@@ -18,4 +14,7 @@ xfs_break_leased_layouts(struct inode *inode, uint *iolock, bool *did_unlock)return 0 ; }#endif /* CONFIG_EXPORTFS_BLOCK_OPS */ + +extern const struct exportfs_block_ops xfs_export_block_ops; +#endif /* _XFS_PNFS_H */
include/linux/exportfs.h +8 -17
@@ -6,9 +6,8 @@#include <linux/path.h> struct dentry ; -struct iattr ; +struct exportfs_block_ops ;struct inode ; -struct iomap ;struct super_block ;struct vfsmount ;
@@ -260,19 +259,13 @@ struct handle_to_path_ctx {* @commit_metadata: * @commit_metadata should commit metadata changes to stable storage. * -* @get_uuid: -* Get a filesystem unique signature exposed to clients. -* -* @map_blocks: -* Map and, if necessary, allocate blocks for a layout. -* -* @commit_blocks: -* Commit blocks in a layout once the client is done with them. -* * @flags: * Allows the filesystem to communicate to nfsd that it may want to do things * differently when dealing with it. * +* @block_ops: +* Operations for layout grants to block on the underlying device. +* * Locking rules: * get_parent is called with child->d_inode->i_rwsem down * get_name is not (which is possibly inconsistent)
@@ -290,12 +283,6 @@ struct export_operations {struct dentry * (*get_parent)(struct dentry *child);int (*commit_metadata)(struct inode *inode); -int (*get_uuid)(struct super_block *sb,u8 *buf,u32 *len,u64 *offset); -int (*map_blocks)(struct inode *inode,loff_t offset, -u64 len,struct iomap *iomap, -bool write,u32 *device_generation); -int (*commit_blocks)(struct inode *inode,struct iomap *iomaps, -int nr_iomaps,struct iattr *iattr);int (*permission)(struct handle_to_path_ctx *ctx,unsigned int oflags);struct file * (*open)(const struct path *path,unsigned int oflags);#define EXPORT_OP_NOWCC (0x1)/* don't collect v3 wcc data */
@@ -308,6 +295,10 @@ struct export_operations {#define EXPORT_OP_FLUSH_ON_CLOSE (0x20)/* fs flushes file data on close */ #define EXPORT_OP_NOLOCKS (0x40)/* no file locking support */ unsigned long flags; + +#ifdef CONFIG_EXPORTFS_BLOCK_OPS +const struct exportfs_block_ops *block_ops; +#endif };/**
include/linux/exportfs_block.h new file +39 -0
@@ -0,0 +1,39 @@ +/* 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/types.h> + +struct iattr ; +struct inode ; +struct iomap ; +struct super_block ; + +struct exportfs_block_ops { +/* +* 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,struct iattr *iattr); +}; + +#endif /* LINUX_EXPORTFS_BLOCK_H */
Signature · 1 line
2.53.0
Chuck Lever
maintainerPATCH v3 3/4 exportfs: don't pass struct iattr to ->commit_blocks
In reply to Chuck LeverFrom: Christoph Hellwig <[email protected]>
The only thing ->commit_blocks really needs is the new size, with a magic -1 placeholder 0 for "do not change the size" because it only ever extends the size.
--- fs/nfsd/blocklayout.c | 12 ++---------- fs/xfs/xfs_pnfs.c | 19 ++++++++++--------- include/linux/exportfs_block.h | 3 +-- 3 files changed, 13 insertions(+), 21 deletions(-)
fs/nfsd/blocklayout.c +2 -10
@@ -179,7 +179,6 @@ static __be32 nfsd4_block_commit_blocks(struct inode *inode, struct nfsd4_layoutcommit *lcp, struct iomap *iomaps, int nr_iomaps) { - struct iattr iattr = { .ia_valid = 0 }; int error;/*
@@ -191,16 +190,9 @@ nfsd4_block_commit_blocks(struct inode *inode, struct nfsd4_layoutcommit *lcp,* timestamp is a "may" condition, and clients that want to force a * specific timestamp should send a separate SETATTR in the compound. */ - iattr.ia_valid |=ATTR_ATIME |ATTR_CTIME |ATTR_MTIME ; - iattr.ia_atime = iattr.ia_ctime = iattr.ia_mtime =current_time (inode); - -if (lcp->lc_size_chg) { - iattr.ia_valid |=ATTR_SIZE ; - iattr.ia_size = lcp->lc_newsize; - } - error = inode->i_sb->s_export_op->block_ops->commit_blocks (inode, - iomaps, nr_iomaps, &iattr); + iomaps, nr_iomaps, + lcp->lc_size_chg ? lcp->lc_newsize :0 );kfree (iomaps);return nfserrno (error); }
fs/xfs/xfs_pnfs.c +10 -9
@@ -257,23 +257,22 @@ xfs_fs_commit_blocks(struct inode *inode, struct iomap *maps, int nr_maps, - struct iattr *iattr) + loff_t new_size) { struct xfs_inode *ip = XFS_I(inode);struct xfs_mount *mp = ip->i_mount;struct xfs_trans *tp; +struct timespec64 now;bool update_isize = false;int error, i;loff_t size; -ASSERT (iattr->ia_valid & (ATTR_ATIME |ATTR_CTIME |ATTR_MTIME )); -xfs_ilock (ip,XFS_IOLOCK_EXCL ); size =i_size_read (inode); -if ((iattr->ia_valid &ATTR_SIZE ) && iattr->ia_size > size) { +if (new_size > size) { update_isize = true; - size = iattr->ia_size; + size = new_size; }for (i =0 ; i < nr_maps; i++) {
@@ -318,11 +317,13 @@ xfs_fs_commit_blocks(xfs_trans_ijoin (tp, ip,XFS_ILOCK_EXCL );xfs_trans_log_inode (tp, ip,XFS_ILOG_CORE ); -ASSERT (!(iattr->ia_valid & (ATTR_UID |ATTR_GID ))); -setattr_copy (&nop_mnt_idmap, inode, iattr); + now =inode_set_ctime_current (inode); +inode_set_atime_to_ts (inode, now); +inode_set_mtime_to_ts (inode, now); +if (update_isize) { -i_size_write (inode, iattr->ia_size); - ip->i_disk_size = iattr->ia_size; +i_size_write (inode, new_size); + ip->i_disk_size = new_size; }xfs_trans_set_sync (tp);
include/linux/exportfs_block.h +1 -2
@@ -9,7 +9,6 @@#include <linux/types.h> -struct iattr ;struct inode ;struct iomap ;struct super_block ;
@@ -33,7 +32,7 @@ struct exportfs_block_ops {* the client. */ int (*commit_blocks)(struct inode *inode,struct iomap *iomaps, - int nr_iomaps, struct iattr *iattr); + int nr_iomaps, loff_t new_size); };#endif /* LINUX_EXPORTFS_BLOCK_H */
Signature · 1 line
2.53.0
Chuck Lever
maintainerPATCH v3 4/4 exportfs,nfsd: rework checking for layout-based block device access support
In reply to Chuck LeverFrom: Christoph Hellwig <[email protected]>
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.
--- fs/nfsd/export.c | 3 +- fs/nfsd/nfs4layouts.c | 26 +++++------------ fs/xfs/xfs_pnfs.c | 13 +++++++++ include/linux/exportfs_block.h | 52 +++++++++++++++++++++++++++++++++- 4 files changed, 73 insertions(+), 21 deletions(-)
fs/nfsd/export.c +2 -1
@@ -1435,7 +1435,8 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) goto out4; err =0 ; -nfsd4_setup_layout_type (&exp); +if (exp.ex_flags &NFSEXP_PNFS ) +nfsd4_setup_layout_type (&exp); } expp =svc_export_lookup (&exp);
fs/nfsd/nfs4layouts.c +7 -19
@@ -2,7 +2,6 @@/* * Copyright (c) 2014 Christoph Hellwig. */ -#include <linux/blkdev.h> #include <linux/exportfs_block.h> #include <linux/kmod.h> #include <linux/file.h>
@@ -128,28 +127,17 @@ nfsd4_set_deviceid(struct nfsd4_deviceid *id, const struct svc_fh *fhp,void nfsd4_setup_layout_type (struct svc_export *exp) { -#if defined(CONFIG_NFSD_BLOCKLAYOUT ) || defined(CONFIG_NFSD_SCSILAYOUT )struct super_block *sb = exp->ex_path.mnt->mnt_sb; -const struct exportfs_block_ops *bops = sb->s_export_op->block_ops; -#endif +expfs_block_layouts_t block_supported =exportfs_layouts_supported (sb); -if (!(exp->ex_flags &NFSEXP_PNFS )) -return ; - -#ifdef CONFIG_NFSD_FLEXFILELAYOUT - exp->ex_layout_types |=1 <<LAYOUT_FLEX_FILES ; -#endif -#ifdef CONFIG_NFSD_BLOCKLAYOUT -if (bops && bops->get_uuid && bops->map_blocks && bops->commit_blocks) +if (IS_ENABLED (CONFIG_NFSD_FLEXFILELAYOUT )) + exp->ex_layout_types |=1 <<LAYOUT_FLEX_FILES ; +if (IS_ENABLED (CONFIG_NFSD_BLOCKLAYOUT ) && + (block_supported &EXPFS_BLOCK_IN_BAND_ID )) exp->ex_layout_types |=1 <<LAYOUT_BLOCK_VOLUME ; -#endif -#ifdef CONFIG_NFSD_SCSILAYOUT -if (bops && bops->map_blocks && bops->commit_blocks && - sb->s_bdev && - sb->s_bdev->bd_disk->fops->pr_ops && - sb->s_bdev->bd_disk->fops->get_unique_id) +if (IS_ENABLED (CONFIG_NFSD_SCSILAYOUT ) && + (block_supported &EXPFS_BLOCK_OUT_OF_BAND_ID )) exp->ex_layout_types |=1 <<LAYOUT_SCSI ; -#endif }void nfsd4_close_layout (struct nfs4_layout_stateid *ls)
fs/xfs/xfs_pnfs.c +13 -0
@@ -13,6 +13,7 @@#include "xfs_bmap.h" #include "xfs_iomap.h" #include "xfs_pnfs.h" +#include <linux/exportfs_block.h> /* * Ensure that we do not have any outstanding pNFS layouts that can be used by
@@ -45,6 +46,17 @@ xfs_break_leased_layouts(return error; } +static expfs_block_layouts_t +xfs_fs_layouts_supported ( +struct super_block *sb) +{ +expfs_block_layouts_t supported =EXPFS_BLOCK_IN_BAND_ID ; + +if (exportfs_bdev_supports_out_of_band_id (sb->s_bdev)) + supported |=EXPFS_BLOCK_OUT_OF_BAND_ID ; +return supported; +} +/* * Get a unique ID including its location so that the client can identify * the exported device.
@@ -335,6 +347,7 @@ xfs_fs_commit_blocks( }const struct exportfs_block_ops xfs_export_block_ops = { + .layouts_supported = xfs_fs_layouts_supported, .get_uuid = xfs_fs_get_uuid, .map_blocks = xfs_fs_map_blocks, .commit_blocks = xfs_fs_commit_blocks,
include/linux/exportfs_block.h +51 -1
68 lines not on this page · raw message
Signature · 1 line
2.53.0
Christian Brauner
AppliedQuoted 10 lines · Chuck Lever
From: Chuck Lever <[email protected]>
Following up on https://lore.kernel.org/linux-nfs/[email protected]/#r
Here is the current version of Christoph's patches that are in nfsd-testing. Christian prefers to see them taken through the VFS tree. Once the patches are applied there, I will rebase nfsd-next and nfsd-testing on that tree and drop these.
[...]
The branch is stable in case anyone wants to rely on it.
---
Applied to the vfs-7.2.exportfs branch of the vfs/vfs.git tree. Patches in the vfs-7.2.exportfs branch should appear in linux-next soon.
Please report any outstanding bugs that were missed during review in a new review to the original patch series allowing us to drop it.
It's encouraged to provide Acked-bys and Reviewed-bys even though the patch has now been applied. If possible patch trailers will be updated.
Note that commit hashes shown below are subject to change due to rebase, trailer updates or similar. If in doubt, please check the listed branch.
tree: https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git branch: vfs-7.2.exportfs
[1/4] nfsd/blocklayout: always ignore loca_time_modify
https://git.kernel.org/vfs/vfs/c/0d9ff5c4219f [2/4] exportfs: split out the ops for layout-based block device access https://git.kernel.org/vfs/vfs/c/d5758c31a81b [3/4] exportfs: don't pass struct iattr to ->commit_blocks https://git.kernel.org/vfs/vfs/c/61eb48f51585 [4/4] exportfs,nfsd: rework checking for layout-based block device access support https://git.kernel.org/vfs/vfs/c/da9baa5470dc