cleanup block-style layouts exports v3
Subsystems (7)
Chuck Lever
maintainercover cleanup block-style layouts exports v3
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 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
Chuck Lever
maintainerPATCH 1/1 NFSD: Put cache get-reqs dump attrs under reply
In reply to Chuck LeverFrom: Chuck Lever <[email protected]>
The new get-reqs dump operations added to sunrpc_cache.yaml and nfsd.yaml place the "requests" nested attribute under dump.request. A netlink dump carries an empty request; its payload travels back in the reply. Because the spec names no reply attributes, the YNL C code generator synthesizes a forward reference to a <op>_rsp struct that is never defined, breaking any consumer of these specs.
This first surfaced when Thorsten Leemhuis built tools/net/ynl against -next:
nfsd-user.h:746: error: field 'obj' has incomplete type
struct nfsd_svc_export_get_reqs_rsp obj ...
nfsd-user.h:826: error: field 'obj' has incomplete type
struct nfsd_expkey_get_reqs_rsp obj ...
nfsd-user.c:1211: error: 'nfsd_svc_export_get_reqs_rsp_parse'
undeclared
sunrpc_cache.yaml has the same defect in ip-map-get-reqs and unix-gid-get-reqs, but nfsd.yaml errors out first in the Makefile's alphabetical build order and hides the sunrpc failures.
These bugs were introduced by incorrect merge conflict resolution.
--- Documentation/netlink/specs/nfsd.yaml | 4 +-- Documentation/netlink/specs/sunrpc_cache.yaml | 4 +-- fs/nfsd/netlink.c | 26 +++++-------------- net/sunrpc/netlink.c | 26 +++++-------------- 4 files changed, 16 insertions(+), 44 deletions(-)
Documentation/netlink/specs/nfsd.yaml +2 -2
@@ -445,7 +445,7 @@ operations: attribute-set: svc-export-reqs flags: [admin-perm] dump: - request: + reply: attributes: - requests -
@@ -463,7 +463,7 @@ operations: attribute-set: expkey-reqs flags: [admin-perm] dump: - request: + reply: attributes: - requests -
Documentation/netlink/specs/sunrpc_cache.yaml +2 -2
@@ -101,7 +101,7 @@ operations: attribute-set: ip-map-reqs flags: [admin-perm] dump: - request: + reply: attributes: - requests -
@@ -119,7 +119,7 @@ operations: attribute-set: unix-gid-reqs flags: [admin-perm] dump: - request: + reply: attributes: - requests -
fs/nfsd/netlink.c +6 -20
@@ -88,21 +88,11 @@ static const struct nla_policy nfsd_pool_mode_set_nl_policy[NFSD_A_POOL_MODE_MOD [NFSD_A_POOL_MODE_MODE] = { .type = NLA_NUL_STRING, }, }; -/* NFSD_CMD_SVC_EXPORT_GET_REQS - dump */ -static const struct nla_policy nfsd_svc_export_get_reqs_nl_policy[NFSD_A_SVC_EXPORT_REQS_REQUESTS +1 ] = { - [NFSD_A_SVC_EXPORT_REQS_REQUESTS ] =NLA_POLICY_NESTED (nfsd_svc_export_nl_policy), -}; -/* NFSD_CMD_SVC_EXPORT_SET_REQS - do */ static const struct nla_policy nfsd_svc_export_set_reqs_nl_policy[NFSD_A_SVC_EXPORT_REQS_REQUESTS +1 ] = { [NFSD_A_SVC_EXPORT_REQS_REQUESTS ] =NLA_POLICY_NESTED (nfsd_svc_export_nl_policy), }; -/* NFSD_CMD_EXPKEY_GET_REQS - dump */ -static const struct nla_policy nfsd_expkey_get_reqs_nl_policy[NFSD_A_EXPKEY_REQS_REQUESTS +1 ] = { - [NFSD_A_EXPKEY_REQS_REQUESTS ] =NLA_POLICY_NESTED (nfsd_expkey_nl_policy), -}; -/* NFSD_CMD_EXPKEY_SET_REQS - do */ static const struct nla_policy nfsd_expkey_set_reqs_nl_policy[NFSD_A_EXPKEY_REQS_REQUESTS +1 ] = { [NFSD_A_EXPKEY_REQS_REQUESTS ] =NLA_POLICY_NESTED (nfsd_expkey_nl_policy),
@@ -184,11 +174,9 @@ static const struct genl_split_ops nfsd_nl_ops[] = { .flags = GENL_CMD_CAP_DO, }, { - .cmd = NFSD_CMD_SVC_EXPORT_GET_REQS, - .dumpit = nfsd_nl_svc_export_get_reqs_dumpit, - .policy = nfsd_svc_export_get_reqs_nl_policy, - .maxattr = NFSD_A_SVC_EXPORT_REQS_REQUESTS, - .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DUMP, + .cmd = NFSD_CMD_SVC_EXPORT_GET_REQS, + .dumpit = nfsd_nl_svc_export_get_reqs_dumpit, + .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DUMP, }, { .cmd = NFSD_CMD_SVC_EXPORT_SET_REQS,
@@ -198,11 +186,9 @@ static const struct genl_split_ops nfsd_nl_ops[] = { .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, }, { - .cmd = NFSD_CMD_EXPKEY_GET_REQS, - .dumpit = nfsd_nl_expkey_get_reqs_dumpit, - .policy = nfsd_expkey_get_reqs_nl_policy, - .maxattr = NFSD_A_EXPKEY_REQS_REQUESTS, - .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DUMP, + .cmd = NFSD_CMD_EXPKEY_GET_REQS, + .dumpit = nfsd_nl_expkey_get_reqs_dumpit, + .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DUMP, }, { .cmd = NFSD_CMD_EXPKEY_SET_REQS,
net/sunrpc/netlink.c +6 -20
@@ -29,21 +29,11 @@ const struct nla_policy sunrpc_unix_gid_nl_policy[SUNRPC_A_UNIX_GID_EXPIRY + 1] [SUNRPC_A_UNIX_GID_EXPIRY] = { .type = NLA_U64, }, }; -/* SUNRPC_CMD_IP_MAP_GET_REQS - dump */ -static const struct nla_policy sunrpc_ip_map_get_reqs_nl_policy[SUNRPC_A_IP_MAP_REQS_REQUESTS +1 ] = { - [SUNRPC_A_IP_MAP_REQS_REQUESTS ] =NLA_POLICY_NESTED (sunrpc_ip_map_nl_policy), -}; -/* SUNRPC_CMD_IP_MAP_SET_REQS - do */ static const struct nla_policy sunrpc_ip_map_set_reqs_nl_policy[SUNRPC_A_IP_MAP_REQS_REQUESTS +1 ] = { [SUNRPC_A_IP_MAP_REQS_REQUESTS ] =NLA_POLICY_NESTED (sunrpc_ip_map_nl_policy), }; -/* SUNRPC_CMD_UNIX_GID_GET_REQS - dump */ -static const struct nla_policy sunrpc_unix_gid_get_reqs_nl_policy[SUNRPC_A_UNIX_GID_REQS_REQUESTS +1 ] = { - [SUNRPC_A_UNIX_GID_REQS_REQUESTS ] =NLA_POLICY_NESTED (sunrpc_unix_gid_nl_policy), -}; -/* SUNRPC_CMD_UNIX_GID_SET_REQS - do */ static const struct nla_policy sunrpc_unix_gid_set_reqs_nl_policy[SUNRPC_A_UNIX_GID_REQS_REQUESTS +1 ] = { [SUNRPC_A_UNIX_GID_REQS_REQUESTS ] =NLA_POLICY_NESTED (sunrpc_unix_gid_nl_policy),
@@ -57,11 +47,9 @@ static const struct nla_policy sunrpc_cache_flush_nl_policy[SUNRPC_A_CACHE_FLUSH/* Ops table for sunrpc */ static const struct genl_split_ops sunrpc_nl_ops[] = { { - .cmd =SUNRPC_CMD_IP_MAP_GET_REQS , - .dumpit = sunrpc_nl_ip_map_get_reqs_dumpit, - .policy = sunrpc_ip_map_get_reqs_nl_policy, - .maxattr =SUNRPC_A_IP_MAP_REQS_REQUESTS , - .flags =GENL_ADMIN_PERM |GENL_CMD_CAP_DUMP , + .cmd =SUNRPC_CMD_IP_MAP_GET_REQS , + .dumpit = sunrpc_nl_ip_map_get_reqs_dumpit, + .flags =GENL_ADMIN_PERM |GENL_CMD_CAP_DUMP , }, { .cmd =SUNRPC_CMD_IP_MAP_SET_REQS ,
@@ -71,11 +59,9 @@ static const struct genl_split_ops sunrpc_nl_ops[] = { .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, }, { - .cmd = SUNRPC_CMD_UNIX_GID_GET_REQS, - .dumpit = sunrpc_nl_unix_gid_get_reqs_dumpit, - .policy = sunrpc_unix_gid_get_reqs_nl_policy, - .maxattr = SUNRPC_A_UNIX_GID_REQS_REQUESTS, - .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DUMP, + .cmd = SUNRPC_CMD_UNIX_GID_GET_REQS, + .dumpit = sunrpc_nl_unix_gid_get_reqs_dumpit, + .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DUMP, }, { .cmd = SUNRPC_CMD_UNIX_GID_SET_REQS,
Signature · 1 line
2.53.0
Re: [PATCH] NFSD: Put cache get-reqs dump attrs under reply
Quoted 1 line · Chuck Lever
From: Chuck Lever <[email protected]>
Damn it. Ignore this, I will try again.
Signature · 1 line
Chuck Lever
Re: [PATCH] NFSD: Put cache get-reqs dump attrs under reply
In reply to Chuck LeverQuoted 183 lines · Chuck Lever
From: Chuck Lever <[email protected]>
The new get-reqs dump operations added to
sunrpc_cache.yamlandnfsd.yamlplace the "requests" nested attribute under dump.request. A netlink dump carries an empty request; its payload travels back in the reply. Because the spec names no reply attributes, the YNL C code generator synthesizes a forward reference to a <op>_rsp struct that is never defined, breaking any consumer of these specs.This first surfaced when Thorsten Leemhuis built
tools/net/ynlagainst -next:nfsd-user.h:746: error: field 'obj' has incomplete type
structnfsd_svc_export_get_reqs_rspobj ...
nfsd-user.h:826: error: field 'obj' has incomplete type
structnfsd_expkey_get_reqs_rspobj ...
nfsd-user.c:1211: error: 'nfsd_svc_export_get_reqs_rsp_parse'
undeclared
sunrpc_cache.yamlhas the same defect in ip-map-get-reqs and unix-gid-get-reqs, butnfsd.yamlerrors out first in the Makefile's alphabetical build order and hides the sunrpc failures.These bugs were introduced by incorrect merge conflict resolution.
Reported-by Thorsten Leemhuis <[email protected]>Fixes 1045ccf519ce30 ("sunrpc: add netlink upcall for the auth.unix.ip cache")Signed-off-by Chuck Lever <[email protected]>--- Documentation/netlink/specs/nfsd.yaml | 4 +-- Documentation/netlink/specs/sunrpc_cache.yaml | 4 +-- fs/nfsd/netlink.c | 26 +++++-------------- net/sunrpc/netlink.c | 26 +++++-------------- 4 files changed, 16 insertions(+), 44 deletions(-)Documentation/netlink/specs/nfsd.yaml +2
-2@@ -445,7 +445,7 @@ operations: attribute-set: svc-export-reqs flags: [admin-perm] dump: - request: + reply: attributes: - requests -@@ -463,7 +463,7 @@ operations: attribute-set: expkey-reqs flags: [admin-perm] dump: - request: + reply: attributes: - requests -Documentation/netlink/specs/sunrpc_cache.yaml +2
-2@@ -101,7 +101,7 @@ operations: attribute-set: ip-map-reqs flags: [admin-perm] dump: - request: + reply: attributes: - requests -@@ -119,7 +119,7 @@ operations: attribute-set: unix-gid-reqs flags: [admin-perm] dump: - request: + reply: attributes: - requests -fs/nfsd/netlink.c +6
-20@@ -88,21 +88,11 @@ static const struct nla_policy nfsd_pool_mode_set_nl_policy[NFSD_A_POOL_MODE_MOD [NFSD_A_POOL_MODE_MODE] = { .type = NLA_NUL_STRING, }, }; -/* NFSD_CMD_SVC_EXPORT_GET_REQS - dump */ -static const struct nla_policy nfsd_svc_export_get_reqs_nl_policy[NFSD_A_SVC_EXPORT_REQS_REQUESTS +1 ] = { - [NFSD_A_SVC_EXPORT_REQS_REQUESTS ] =NLA_POLICY_NESTED (nfsd_svc_export_nl_policy), -}; -/* NFSD_CMD_SVC_EXPORT_SET_REQS - do */ static const struct nla_policy nfsd_svc_export_set_reqs_nl_policy[NFSD_A_SVC_EXPORT_REQS_REQUESTS +1 ] = { [NFSD_A_SVC_EXPORT_REQS_REQUESTS ] =NLA_POLICY_NESTED (nfsd_svc_export_nl_policy), }; -/* NFSD_CMD_EXPKEY_GET_REQS - dump */ -static const struct nla_policy nfsd_expkey_get_reqs_nl_policy[NFSD_A_EXPKEY_REQS_REQUESTS +1 ] = { - [NFSD_A_EXPKEY_REQS_REQUESTS ] =NLA_POLICY_NESTED (nfsd_expkey_nl_policy), -}; -/* NFSD_CMD_EXPKEY_SET_REQS - do */ static const struct nla_policy nfsd_expkey_set_reqs_nl_policy[NFSD_A_EXPKEY_REQS_REQUESTS +1 ] = { [NFSD_A_EXPKEY_REQS_REQUESTS ] =NLA_POLICY_NESTED (nfsd_expkey_nl_policy),@@ -184,11 +174,9 @@ static const struct genl_split_ops nfsd_nl_ops[] = { .flags = GENL_CMD_CAP_DO, }, { - .cmd = NFSD_CMD_SVC_EXPORT_GET_REQS, - .dumpit = nfsd_nl_svc_export_get_reqs_dumpit, - .policy = nfsd_svc_export_get_reqs_nl_policy, - .maxattr = NFSD_A_SVC_EXPORT_REQS_REQUESTS, - .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DUMP, + .cmd = NFSD_CMD_SVC_EXPORT_GET_REQS, + .dumpit = nfsd_nl_svc_export_get_reqs_dumpit, + .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DUMP, }, { .cmd = NFSD_CMD_SVC_EXPORT_SET_REQS,@@ -198,11 +186,9 @@ static const struct genl_split_ops nfsd_nl_ops[] = { .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, }, { - .cmd = NFSD_CMD_EXPKEY_GET_REQS, - .dumpit = nfsd_nl_expkey_get_reqs_dumpit, - .policy = nfsd_expkey_get_reqs_nl_policy, - .maxattr = NFSD_A_EXPKEY_REQS_REQUESTS, - .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DUMP, + .cmd = NFSD_CMD_EXPKEY_GET_REQS, + .dumpit = nfsd_nl_expkey_get_reqs_dumpit, + .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DUMP, }, { .cmd = NFSD_CMD_EXPKEY_SET_REQS,net/sunrpc/netlink.c +3
-16@@ -29,21 +29,11 @@ const struct nla_policy sunrpc_unix_gid_nl_policy[SUNRPC_A_UNIX_GID_EXPIRY + 1] [SUNRPC_A_UNIX_GID_EXPIRY] = { .type = NLA_U64, }, }; -/* SUNRPC_CMD_IP_MAP_GET_REQS - dump */ -static const struct nla_policy sunrpc_ip_map_get_reqs_nl_policy[SUNRPC_A_IP_MAP_REQS_REQUESTS +1 ] = { - [SUNRPC_A_IP_MAP_REQS_REQUESTS ] =NLA_POLICY_NESTED (sunrpc_ip_map_nl_policy), -}; -/* SUNRPC_CMD_IP_MAP_SET_REQS - do */ static const struct nla_policy sunrpc_ip_map_set_reqs_nl_policy[SUNRPC_A_IP_MAP_REQS_REQUESTS +1 ] = { [SUNRPC_A_IP_MAP_REQS_REQUESTS ] =NLA_POLICY_NESTED (sunrpc_ip_map_nl_policy), }; -/* SUNRPC_CMD_UNIX_GID_GET_REQS - dump */ -static const struct nla_policy sunrpc_unix_gid_get_reqs_nl_policy[SUNRPC_A_UNIX_GID_REQS_REQUESTS +1 ] = { - [SUNRPC_A_UNIX_GID_REQS_REQUESTS ] =NLA_POLICY_NESTED (sunrpc_unix_gid_nl_policy), -}; -/* SUNRPC_CMD_UNIX_GID_SET_REQS - do */ static const struct nla_policy sunrpc_unix_gid_set_reqs_nl_policy[SUNRPC_A_UNIX_GID_REQS_REQUESTS +1 ] = { [SUNRPC_A_UNIX_GID_REQS_REQUESTS ] =NLA_POLICY_NESTED (sunrpc_unix_gid_nl_policy),@@ -57,11 +47,9 @@ static const struct nla_policy sunrpc_cache_flush_nl_policy[SUNRPC_A_CACHE_FLUSH/* Ops table for sunrpc */ static const struct genl_split_ops sunrpc_nl_ops[] = { { - .cmd =SUNRPC_CMD_IP_MAP_GET_REQS , - .dumpit = sunrpc_nl_ip_map_get_reqs_dumpit, - .policy = sunrpc_ip_map_get_reqs_nl_policy, - .maxattr =SUNRPC_A_IP_MAP_REQS_REQUESTS , - .flags =GENL_ADMIN_PERM |GENL_CMD_CAP_DUMP , + .cmd =SUNRPC_CMD_IP_MAP_GET_REQS , + .dumpit = sunrpc_nl_ip_map_get_reqs_dumpit, + .flags =GENL_ADMIN_PERM |GENL_CMD_CAP_DUMP , }, { .cmd =SUNRPC_CMD_IP_MAP_SET_REQS ,@@ -71,11 +59,9 @@ static const struct genl_split_ops sunrpc_nl_ops[] = { .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, }, { - .cmd = SUNRPC_CMD_UNIX_GID_GET_REQS,
net/sunrpc/netlink.c static const struct genl_split_ops sunrpc_nl_ops[] = { · line 67
Quoted 10 lines
net/sunrpc/netlink.c +3
-4- .dumpit = sunrpc_nl_unix_gid_get_reqs_dumpit, - .policy = sunrpc_unix_gid_get_reqs_nl_policy, - .maxattr = SUNRPC_A_UNIX_GID_REQS_REQUESTS, - .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DUMP, + .cmd = SUNRPC_CMD_UNIX_GID_GET_REQS, + .dumpit = sunrpc_nl_unix_gid_get_reqs_dumpit, + .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DUMP, }, { .cmd = SUNRPC_CMD_UNIX_GID_SET_REQS,
Chuck Lever
maintainerPATCH 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 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 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