* [RFC PATCH 00/11] NFS/NFSD: nfs4_acl passthru for NFSv4 reexport
@ 2026-02-19 22:13 Mike Snitzer
2026-02-19 22:13 ` [RFC PATCH 01/11] exportfs: add ability to advertise NFSv4 ACL passthru support Mike Snitzer
` (12 more replies)
0 siblings, 13 replies; 20+ messages in thread
From: Mike Snitzer @ 2026-02-19 22:13 UTC (permalink / raw)
To: Chuck Lever, Jeff Layton, Trond Myklebust, Anna Schumaker; +Cc: linux-nfs
Hi,
This patchset aims to enable NFS v4.1 ACLs to be fully supported from
an NFS v4.1 client to an NFSD v4.1 export that reexports NFS v4.2
filesystem which has full support for NFS v4.1 ACLs (DACL and SACL).
The first 6 patches focus on nfs4_acl passthru enablement (primarily
for NFSD), patch 7 adds 4.1 nfs4_acl passthru support (DACL and SACL),
patch 8 optimizes particular nfs4_acl passthru implementation in NFSD
to skip memcpy if nfs4_acl passthru isn't needed, patches 9-11 offer
the corresponding required NFSv4 client changes.
This work is based on the NFS and NFSD code that has been merged
during the 7.0 merge window.
This patchset is marked as RFC because I expect there will be
suggestions for possible NFSD implementation improvements.
All review appreciated, thanks.
Mike
Mike Snitzer (11):
exportfs: add ability to advertise NFSv4 ACL passthru support
NFSD: factor out nfsd_supports_nfs4_acl() to nfsd/acl.h
NFS/NFSD: data structure enablement for nfs4_acl passthru support
NFSD: prepare to support SETACL nfs4_acl passthru
NFSD: add NFS4 reexport support for SETACL nfs4_acl passthru
NFSD: add NFS4 reexport support for GETACL nfs4_acl passthru
NFSD: add NFS4ACL_DACL and NFS4ACL_SACL passthru support
NFSD: avoid extra nfs4_acl passthru work unless needed
NFSv4: add reexport support for SETACL nfs4_acl passthru
NFSv4: add reexport support for GETACL nfs4_acl passthru
NFSv4: set EXPORT_OP_NFSV4_ACL_PASSTHRU flag
fs/nfs/export.c | 23 ++++-
fs/nfs/nfs4proc.c | 112 +++++++++++++++-------
fs/nfs/nfs4xdr.c | 2 +-
fs/nfsd/acl.h | 11 ++-
fs/nfsd/nfs4acl.c | 69 +++++++++++++-
fs/nfsd/nfs4proc.c | 32 +++++--
fs/nfsd/nfs4xdr.c | 194 +++++++++++++++++++++++++++++++++------
fs/nfsd/nfsd.h | 5 +-
fs/nfsd/xdr4.h | 2 +
include/linux/exportfs.h | 22 +++++
include/linux/nfs4.h | 23 ++++-
include/linux/nfs_xdr.h | 11 +--
include/linux/nfsacl.h | 7 ++
13 files changed, 431 insertions(+), 82 deletions(-)
--
2.44.0
^ permalink raw reply [flat|nested] 20+ messages in thread
* [RFC PATCH 01/11] exportfs: add ability to advertise NFSv4 ACL passthru support
2026-02-19 22:13 [RFC PATCH 00/11] NFS/NFSD: nfs4_acl passthru for NFSv4 reexport Mike Snitzer
@ 2026-02-19 22:13 ` Mike Snitzer
2026-02-19 22:13 ` [RFC PATCH 02/11] NFSD: factor out nfsd_supports_nfs4_acl() to nfsd/acl.h Mike Snitzer
` (11 subsequent siblings)
12 siblings, 0 replies; 20+ messages in thread
From: Mike Snitzer @ 2026-02-19 22:13 UTC (permalink / raw)
To: Chuck Lever, Jeff Layton, Trond Myklebust, Anna Schumaker; +Cc: linux-nfs
From: Mike Snitzer <snitzer@hammerspace.com>
Add EXPORT_OP_NFSV4_ACL_PASSTHRU flag that an export should set if
relevant new methods are added to export_operations (e.g. .setacl and
.getacl which will be added in future commits).
NFSD will use exportfs_may_passthru_nfs4acl() to check for this flag
before passing nfs4_acl thru to exported FS (using new methods in
export_operations).
Signed-off-by: Mike Snitzer <snitzer@hammerspace.com>
---
include/linux/exportfs.h | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h
index 9369a607224c..0262c9258b34 100644
--- a/include/linux/exportfs.h
+++ b/include/linux/exportfs.h
@@ -247,6 +247,7 @@ 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 */
+#define EXPORT_OP_NFSV4_ACL_PASSTHRU (0x80) /* fs MAY handle NFSv4 ACL passthru */
unsigned long flags;
};
@@ -262,6 +263,18 @@ exportfs_cannot_lock(const struct export_operations *export_ops)
return export_ops->flags & EXPORT_OP_NOLOCKS;
}
+/**
+ * exportfs_may_passthru_nfs4acl() - check if export MAY passthru NFSv4 ACLs
+ * @export_ops: the nfs export operations to check
+ *
+ * Returns true if the export MAY support NFSv4 ACL passthru.
+ */
+static inline bool
+exportfs_may_passthru_nfs4acl(const struct export_operations *export_ops)
+{
+ return export_ops->flags & EXPORT_OP_NFSV4_ACL_PASSTHRU;
+}
+
extern int exportfs_encode_inode_fh(struct inode *inode, struct fid *fid,
int *max_len, struct inode *parent,
int flags);
--
2.44.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [RFC PATCH 02/11] NFSD: factor out nfsd_supports_nfs4_acl() to nfsd/acl.h
2026-02-19 22:13 [RFC PATCH 00/11] NFS/NFSD: nfs4_acl passthru for NFSv4 reexport Mike Snitzer
2026-02-19 22:13 ` [RFC PATCH 01/11] exportfs: add ability to advertise NFSv4 ACL passthru support Mike Snitzer
@ 2026-02-19 22:13 ` Mike Snitzer
2026-02-19 22:13 ` [RFC PATCH 03/11] NFS/NFSD: data structure enablement for nfs4_acl passthru support Mike Snitzer
` (10 subsequent siblings)
12 siblings, 0 replies; 20+ messages in thread
From: Mike Snitzer @ 2026-02-19 22:13 UTC (permalink / raw)
To: Chuck Lever, Jeff Layton, Trond Myklebust, Anna Schumaker; +Cc: linux-nfs
From: Mike Snitzer <snitzer@hammerspace.com>
Check both IS_POSIXACL() and exportfs_may_passthru_nfs4acl() to
prepare for passing through nfs4_acl directly to NFSv4 filesystem
(NFSv4 will set EXPORT_OP_NFSV4_ACL_PASSTHRU flag in later commit).
Signed-off-by: Mike Snitzer <snitzer@hammerspace.com>
---
fs/nfsd/acl.h | 8 ++++++++
fs/nfsd/nfs4proc.c | 2 +-
fs/nfsd/nfs4xdr.c | 6 +++---
3 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/fs/nfsd/acl.h b/fs/nfsd/acl.h
index 2003523d0e65..699a3b19bdb8 100644
--- a/fs/nfsd/acl.h
+++ b/fs/nfsd/acl.h
@@ -35,6 +35,8 @@
#ifndef LINUX_NFS4_ACL_H
#define LINUX_NFS4_ACL_H
+#include <linux/exportfs.h>
+
struct nfs4_acl;
struct svc_fh;
struct svc_rqst;
@@ -51,4 +53,10 @@ __be32 nfsd4_acl_to_attr(enum nfs_ftype4 type, struct nfs4_acl *acl,
struct nfsd_attrs *attr);
void sort_pacl_range(struct posix_acl *pacl, int start, int end);
+static inline bool nfsd_supports_nfs4_acl(struct dentry *dentry)
+{
+ return IS_POSIXACL(d_inode(dentry)) ||
+ exportfs_may_passthru_nfs4acl(dentry->d_sb->s_export_op);
+}
+
#endif /* LINUX_NFS4_ACL_H */
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 293d149332e4..9a21e94a4215 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -89,7 +89,7 @@ check_attr_support(struct nfsd4_compound_state *cstate, u32 *bmval,
if (!nfsd_attrs_supported(cstate->minorversion, bmval))
return nfserr_attrnotsupp;
- if ((bmval[0] & FATTR4_WORD0_ACL) && !IS_POSIXACL(d_inode(dentry)))
+ if ((bmval[0] & FATTR4_WORD0_ACL) && !nfsd_supports_nfs4_acl(dentry))
return nfserr_attrnotsupp;
if ((bmval[2] & (FATTR4_WORD2_POSIX_DEFAULT_ACL |
FATTR4_WORD2_POSIX_ACCESS_ACL)) &&
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index aca3a1906f40..f048245b8592 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -3195,7 +3195,7 @@ static __be32 nfsd4_encode_fattr4_supported_attrs(struct xdr_stream *xdr,
u32 supp[3];
memcpy(supp, nfsd_suppattrs[minorversion], sizeof(supp));
- if (!IS_POSIXACL(d_inode(args->dentry)))
+ if (!nfsd_supports_nfs4_acl(args->dentry))
supp[0] &= ~FATTR4_WORD0_ACL;
if (!args->contextsupport)
supp[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
@@ -3328,7 +3328,7 @@ static __be32 nfsd4_encode_fattr4_aclsupport(struct xdr_stream *xdr,
u32 mask;
mask = 0;
- if (IS_POSIXACL(d_inode(args->dentry)))
+ if (nfsd_supports_nfs4_acl(args->dentry))
mask = ACL4_SUPPORT_ALLOW_ACL | ACL4_SUPPORT_DENY_ACL;
return nfsd4_encode_uint32_t(xdr, mask);
}
@@ -3600,7 +3600,7 @@ static __be32 nfsd4_encode_fattr4_suppattr_exclcreat(struct xdr_stream *xdr,
u32 supp[3];
memcpy(supp, nfsd_suppattrs[resp->cstate.minorversion], sizeof(supp));
- if (!IS_POSIXACL(d_inode(args->dentry)))
+ if (!nfsd_supports_nfs4_acl(args->dentry))
supp[0] &= ~FATTR4_WORD0_ACL;
if (!args->contextsupport)
supp[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
--
2.44.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [RFC PATCH 03/11] NFS/NFSD: data structure enablement for nfs4_acl passthru support
2026-02-19 22:13 [RFC PATCH 00/11] NFS/NFSD: nfs4_acl passthru for NFSv4 reexport Mike Snitzer
2026-02-19 22:13 ` [RFC PATCH 01/11] exportfs: add ability to advertise NFSv4 ACL passthru support Mike Snitzer
2026-02-19 22:13 ` [RFC PATCH 02/11] NFSD: factor out nfsd_supports_nfs4_acl() to nfsd/acl.h Mike Snitzer
@ 2026-02-19 22:13 ` Mike Snitzer
2026-02-19 22:13 ` [RFC PATCH 04/11] NFSD: prepare to support SETACL nfs4_acl passthru Mike Snitzer
` (9 subsequent siblings)
12 siblings, 0 replies; 20+ messages in thread
From: Mike Snitzer @ 2026-02-19 22:13 UTC (permalink / raw)
To: Chuck Lever, Jeff Layton, Trond Myklebust, Anna Schumaker; +Cc: linux-nfs
From: Mike Snitzer <snitzer@hammerspace.com>
Add setacl and getacl to export_operations structure. Both of these
methods allow NFSD to pass an nfs4_acl structure to exported
filesystem.
Update the nfs4_acl structure to allow for dual use of the new
nfs4_acl passthru support in addition to its existing usage. This
duality is reflected through use of a union, but the xdr_buf payload
is used to initialize all members in the union needed for passthru (in
a later NFSD commit).
Move nfs4_acl_type structure to include/linux/nfsacl.h so that it can
be used by NFS and NFSD.
Signed-off-by: Mike Snitzer <snitzer@hammerspace.com>
---
include/linux/exportfs.h | 9 +++++++++
include/linux/nfs4.h | 23 +++++++++++++++++++++--
include/linux/nfs_xdr.h | 7 -------
include/linux/nfsacl.h | 7 +++++++
4 files changed, 37 insertions(+), 9 deletions(-)
diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h
index 0262c9258b34..e73e7ba5ef45 100644
--- a/include/linux/exportfs.h
+++ b/include/linux/exportfs.h
@@ -10,6 +10,7 @@ struct inode;
struct iomap;
struct super_block;
struct vfsmount;
+struct nfs4_acl;
/* limit the handle size to NFSv4 handle size now */
#define MAX_HANDLE_SZ 128
@@ -215,6 +216,12 @@ struct fid {
* commit_metadata:
* @commit_metadata should commit metadata changes to stable storage.
*
+ * setacl:
+ * @setacl will use the nfs4_acl @acl to establish the acl using SETATTR.
+ *
+ * getacl:
+ * @getacl will use the nfs4_acl @acl to retrieve the acl using GETATTR.
+ *
* Locking rules:
* get_parent is called with child->d_inode->i_mutex down
* get_name is not (which is possibly inconsistent)
@@ -238,6 +245,8 @@ struct export_operations {
bool write, u32 *device_generation);
int (*commit_blocks)(struct inode *inode, struct iomap *iomaps,
int nr_iomaps, struct iattr *iattr);
+ int (*setacl)(struct inode *inode, struct nfs4_acl *acl);
+ int (*getacl)(struct inode *inode, struct nfs4_acl *acl);
#define EXPORT_OP_NOWCC (0x1) /* don't collect v3 wcc data */
#define EXPORT_OP_NOSUBTREECHK (0x2) /* no subtree checking */
#define EXPORT_OP_CLOSE_BEFORE_UNLINK (0x4) /* close files before unlink */
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
index 147a4d178c12..28c10edeea5b 100644
--- a/include/linux/nfs4.h
+++ b/include/linux/nfs4.h
@@ -16,6 +16,7 @@
#include <linux/list.h>
#include <linux/uidgid.h>
#include <uapi/linux/nfs4.h>
+#include <linux/sunrpc/xdr.h>
#include <linux/sunrpc/msg_prot.h>
#include <linux/sunrpc/xdrgen/nfs4_1.h>
@@ -38,8 +39,26 @@ struct nfs4_ace {
};
struct nfs4_acl {
- uint32_t naces;
- struct nfs4_ace aces[];
+ union {
+ struct {
+ /*
+ * Payload to use for deferred decode into
+ * pages once ACL passthru is required
+ * (which uses abnormal members below).
+ */
+ struct xdr_buf payload;
+ /* Normal counted list of ACEs */
+ uint32_t naces;
+ struct nfs4_ace aces[];
+ } __attribute__ ((packed));
+ struct {
+ /* Abnormal counted list of pages */
+ uint32_t type;
+ uint32_t len;
+ uint32_t pgbase;
+ struct page *pages[];
+ } __attribute__ ((packed));
+ };
};
#define NFS4_MAXLABELLEN 2048
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 2b30af613bab..65dbe7c05346 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -827,13 +827,6 @@ struct nfs_setattrargs {
const struct nfs4_label *label;
};
-enum nfs4_acl_type {
- NFS4ACL_NONE = 0,
- NFS4ACL_ACL,
- NFS4ACL_DACL,
- NFS4ACL_SACL,
-};
-
struct nfs_setaclargs {
struct nfs4_sequence_args seq_args;
struct nfs_fh * fh;
diff --git a/include/linux/nfsacl.h b/include/linux/nfsacl.h
index 8e76a79cdc6a..a1941dc56db0 100644
--- a/include/linux/nfsacl.h
+++ b/include/linux/nfsacl.h
@@ -22,6 +22,13 @@
#define NFS_ACL_MAX_ENTRIES_INLINE (5)
#define NFS_ACL_INLINE_BUFSIZE ((2*(2+3*NFS_ACL_MAX_ENTRIES_INLINE)) << 2)
+enum nfs4_acl_type {
+ NFS4ACL_NONE = 0,
+ NFS4ACL_ACL,
+ NFS4ACL_DACL,
+ NFS4ACL_SACL,
+};
+
static inline unsigned int
nfsacl_size(struct posix_acl *acl_access, struct posix_acl *acl_default)
{
--
2.44.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [RFC PATCH 04/11] NFSD: prepare to support SETACL nfs4_acl passthru
2026-02-19 22:13 [RFC PATCH 00/11] NFS/NFSD: nfs4_acl passthru for NFSv4 reexport Mike Snitzer
` (2 preceding siblings ...)
2026-02-19 22:13 ` [RFC PATCH 03/11] NFS/NFSD: data structure enablement for nfs4_acl passthru support Mike Snitzer
@ 2026-02-19 22:13 ` Mike Snitzer
2026-02-19 22:13 ` [RFC PATCH 05/11] NFSD: add NFS4 reexport support for " Mike Snitzer
` (8 subsequent siblings)
12 siblings, 0 replies; 20+ messages in thread
From: Mike Snitzer @ 2026-02-19 22:13 UTC (permalink / raw)
To: Chuck Lever, Jeff Layton, Trond Myklebust, Anna Schumaker; +Cc: linux-nfs
From: Mike Snitzer <snitzer@hammerspace.com>
Use a separate xdr_buf and xdr_stream in both nfsd4_decode_acl() and
nfsd4_decode_nfsace4().
This prepares for nfsd4_decode_acl() to save off the xdr_buf
associated with the ACL payload so that deferred decode is possible
when nfs4_acl passthru is needed (in next commit).
Signed-off-by: Mike Snitzer <snitzer@hammerspace.com>
---
fs/nfsd/nfs4xdr.c | 57 ++++++++++++++++++++++++++++++-----------------
1 file changed, 37 insertions(+), 20 deletions(-)
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index f048245b8592..cacdd6285e90 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -288,31 +288,32 @@ nfsd4_decode_bitmap4(struct nfsd4_compoundargs *argp, u32 *bmval, u32 bmlen)
}
static __be32
-nfsd4_decode_nfsace4(struct nfsd4_compoundargs *argp, struct nfs4_ace *ace)
+nfsd4_decode_nfsace4(struct xdr_stream *xdr, struct svc_rqst *rqstp,
+ struct nfs4_ace *ace)
{
__be32 *p, status;
u32 length;
- if (xdr_stream_decode_u32(argp->xdr, &ace->type) < 0)
+ if (xdr_stream_decode_u32(xdr, &ace->type) < 0)
return nfserr_bad_xdr;
- if (xdr_stream_decode_u32(argp->xdr, &ace->flag) < 0)
+ if (xdr_stream_decode_u32(xdr, &ace->flag) < 0)
return nfserr_bad_xdr;
- if (xdr_stream_decode_u32(argp->xdr, &ace->access_mask) < 0)
+ if (xdr_stream_decode_u32(xdr, &ace->access_mask) < 0)
return nfserr_bad_xdr;
- if (xdr_stream_decode_u32(argp->xdr, &length) < 0)
+ if (xdr_stream_decode_u32(xdr, &length) < 0)
return nfserr_bad_xdr;
- p = xdr_inline_decode(argp->xdr, length);
+ p = xdr_inline_decode(xdr, length);
if (!p)
return nfserr_bad_xdr;
ace->whotype = nfs4_acl_get_whotype((char *)p, length);
if (ace->whotype != NFS4_ACL_WHO_NAMED)
status = nfs_ok;
else if (ace->flag & NFS4_ACE_IDENTIFIER_GROUP)
- status = nfsd_map_name_to_gid(argp->rqstp,
+ status = nfsd_map_name_to_gid(rqstp,
(char *)p, length, &ace->who_gid);
else
- status = nfsd_map_name_to_uid(argp->rqstp,
+ status = nfsd_map_name_to_uid(rqstp,
(char *)p, length, &ace->who_uid);
return status;
@@ -320,35 +321,51 @@ nfsd4_decode_nfsace4(struct nfsd4_compoundargs *argp, struct nfs4_ace *ace)
/* A counted array of nfsace4's */
static noinline __be32
-nfsd4_decode_acl(struct nfsd4_compoundargs *argp, struct nfs4_acl **acl)
+nfsd4_decode_acl(struct nfsd4_compoundargs *argp, struct nfs4_acl **acl,
+ u32 acl_len)
{
+
+ struct xdr_buf payload;
+ struct xdr_stream xdr;
struct nfs4_ace *ace;
- __be32 status;
+ __be32 status = nfs_ok;
u32 count;
- if (xdr_stream_decode_u32(argp->xdr, &count) < 0)
+ if (!xdr_stream_subsegment(argp->xdr, &payload, acl_len))
return nfserr_bad_xdr;
- if (count > xdr_stream_remaining(argp->xdr) / 20)
+ xdr_init_decode(&xdr, &payload, payload.head[0].iov_base, NULL);
+
+ if (xdr_stream_decode_u32(&xdr, &count) < 0) {
+ status = nfserr_bad_xdr;
+ goto out;
+ }
+
+ if (count > xdr_stream_remaining(&xdr) / 20) {
/*
* Even with 4-byte names there wouldn't be
* space for that many aces; something fishy is
* going on:
*/
- return nfserr_fbig;
+ status = nfserr_fbig;
+ goto out;
+ }
*acl = svcxdr_tmpalloc(argp, nfs4_acl_bytes(count));
- if (*acl == NULL)
- return nfserr_jukebox;
+ if (*acl == NULL) {
+ status = nfserr_jukebox;
+ goto out;
+ }
(*acl)->naces = count;
for (ace = (*acl)->aces; ace < (*acl)->aces + count; ace++) {
- status = nfsd4_decode_nfsace4(argp, ace);
+ status = nfsd4_decode_nfsace4(&xdr, argp->rqstp, ace);
if (status)
- return status;
+ goto out;
}
-
- return nfs_ok;
+out:
+ xdr_finish_decode(&xdr);
+ return status;
}
static noinline __be32
@@ -514,7 +531,7 @@ nfsd4_decode_fattr4(struct nfsd4_compoundargs *argp, u32 *bmval, u32 bmlen,
iattr->ia_valid |= ATTR_SIZE;
}
if (bmval[0] & FATTR4_WORD0_ACL) {
- status = nfsd4_decode_acl(argp, acl);
+ status = nfsd4_decode_acl(argp, acl, attrlist4_count);
if (status)
return status;
} else
--
2.44.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [RFC PATCH 05/11] NFSD: add NFS4 reexport support for SETACL nfs4_acl passthru
2026-02-19 22:13 [RFC PATCH 00/11] NFS/NFSD: nfs4_acl passthru for NFSv4 reexport Mike Snitzer
` (3 preceding siblings ...)
2026-02-19 22:13 ` [RFC PATCH 04/11] NFSD: prepare to support SETACL nfs4_acl passthru Mike Snitzer
@ 2026-02-19 22:13 ` Mike Snitzer
2026-02-19 22:13 ` [RFC PATCH 06/11] NFSD: add NFS4 reexport support for GETACL " Mike Snitzer
` (7 subsequent siblings)
12 siblings, 0 replies; 20+ messages in thread
From: Mike Snitzer @ 2026-02-19 22:13 UTC (permalink / raw)
To: Chuck Lever, Jeff Layton, Trond Myklebust, Anna Schumaker; +Cc: linux-nfs
From: Mike Snitzer <snitzer@hammerspace.com>
Allow NFSD's 4.1 reexport of a 4.2 mount to perform SETACL by passing
thru nfs4_acl that was decoded from 4.1 client directly to 4.2
client.
Update nfsd4_decode_acl() to save the ACL's payload off to an xdr_buf
in the nfs4_acl. But only do the work to decode that ACL payload into
pages stored in the nfs4_acl, via nfsd4_decode_nfs4_acl_passthru(), if
the exported filesystem supports nfs4_acl passthru (like NFSv4 client
does).
Signed-off-by: Mike Snitzer <snitzer@hammerspace.com>
---
fs/nfsd/nfs4proc.c | 27 +++++++++++++++++++++------
fs/nfsd/nfs4xdr.c | 43 ++++++++++++++++++++++++++++++++++++++++++-
fs/nfsd/xdr4.h | 2 ++
3 files changed, 65 insertions(+), 7 deletions(-)
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 9a21e94a4215..796954a24cde 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -1219,6 +1219,7 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
};
bool save_no_wcc, deleg_attrs;
struct nfs4_stid *st = NULL;
+ struct dentry *dentry;
struct inode *inode;
__be32 status = nfs_ok;
int err;
@@ -1276,12 +1277,14 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
goto out;
}
- inode = cstate->current_fh.fh_dentry->d_inode;
- status = nfsd4_acl_to_attr(S_ISDIR(inode->i_mode) ? NF4DIR : NF4REG,
- setattr->sa_acl, &attrs);
-
- if (status)
- goto out;
+ dentry = cstate->current_fh.fh_dentry;
+ inode = dentry->d_inode;
+ if (IS_POSIXACL(inode)) {
+ status = nfsd4_acl_to_attr(S_ISDIR(inode->i_mode) ? NF4DIR : NF4REG,
+ setattr->sa_acl, &attrs);
+ if (status)
+ goto out;
+ }
save_no_wcc = cstate->current_fh.fh_no_wcc;
cstate->current_fh.fh_no_wcc = true;
status = nfsd_setattr(rqstp, &cstate->current_fh, &attrs, NULL);
@@ -1292,6 +1295,18 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
status = nfserrno(attrs.na_dpaclerr);
if (!status)
status = nfserrno(attrs.na_paclerr);
+ if (!status && !IS_POSIXACL(inode) && setattr->sa_acl &&
+ exportfs_may_passthru_nfs4acl(dentry->d_sb->s_export_op)) {
+ const struct export_operations *ops = dentry->d_sb->s_export_op;
+ if (likely(ops->setacl)) {
+ status = nfsd4_decode_nfs4_acl_passthru(rqstp->rq_argp,
+ setattr->sa_bmval, &setattr->sa_acl);
+ if (status)
+ goto out;
+ status = nfserrno(ops->setacl(inode, setattr->sa_acl));
+ } else
+ status = nfserr_attrnotsupp;
+ }
out:
fh_drop_write(&cstate->current_fh);
out_err:
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index cacdd6285e90..f14c2fb45142 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -287,6 +287,45 @@ nfsd4_decode_bitmap4(struct nfsd4_compoundargs *argp, u32 *bmval, u32 bmlen)
return status == -EBADMSG ? nfserr_bad_xdr : nfs_ok;
}
+__be32 nfsd4_decode_nfs4_acl_passthru(struct nfsd4_compoundargs *argp,
+ u32 *bmval, struct nfs4_acl **acl)
+{
+ u32 acl_len = (*acl)->payload.len;
+ unsigned int pgbase, num_pages;
+ struct xdr_stream xdr;
+ __be32 status = nfs_ok;
+ void *p;
+
+ xdr_init_decode(&xdr, &(*acl)->payload,
+ (*acl)->payload.head[0].iov_base, NULL);
+
+ p = xdr_inline_decode(&xdr, acl_len);
+ if (p == NULL) {
+ status = nfserr_bad_xdr;
+ goto out;
+ }
+
+ pgbase = (unsigned long)p & ~PAGE_MASK;
+ num_pages = DIV_ROUND_UP(pgbase + acl_len, PAGE_SIZE);
+
+ *acl = svcxdr_tmpalloc(argp, (sizeof(struct nfs4_acl) +
+ num_pages * sizeof(struct page *)));
+ if (*acl == NULL) {
+ status = nfserr_jukebox;
+ goto out;
+ }
+
+ (*acl)->type = NFS4ACL_ACL;
+ (*acl)->len = acl_len;
+ (*acl)->pgbase = pgbase;
+
+ for (int i = 0; i < num_pages; i++)
+ (*acl)->pages[i] = virt_to_page(p + (i << PAGE_SHIFT));
+out:
+ xdr_finish_decode(&xdr);
+ return status;
+}
+
static __be32
nfsd4_decode_nfsace4(struct xdr_stream *xdr, struct svc_rqst *rqstp,
struct nfs4_ace *ace)
@@ -325,7 +364,7 @@ nfsd4_decode_acl(struct nfsd4_compoundargs *argp, struct nfs4_acl **acl,
u32 acl_len)
{
- struct xdr_buf payload;
+ struct xdr_buf payload, saved_payload;
struct xdr_stream xdr;
struct nfs4_ace *ace;
__be32 status = nfs_ok;
@@ -333,6 +372,7 @@ nfsd4_decode_acl(struct nfsd4_compoundargs *argp, struct nfs4_acl **acl,
if (!xdr_stream_subsegment(argp->xdr, &payload, acl_len))
return nfserr_bad_xdr;
+ memcpy(&saved_payload, &payload, sizeof(struct xdr_buf));
xdr_init_decode(&xdr, &payload, payload.head[0].iov_base, NULL);
@@ -356,6 +396,7 @@ nfsd4_decode_acl(struct nfsd4_compoundargs *argp, struct nfs4_acl **acl,
status = nfserr_jukebox;
goto out;
}
+ memcpy(&(*acl)->payload, &saved_payload, sizeof(struct xdr_buf));
(*acl)->naces = count;
for (ace = (*acl)->aces; ace < (*acl)->aces + count; ace++) {
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
index 417e9ad9fbb3..d3561ce76a12 100644
--- a/fs/nfsd/xdr4.h
+++ b/fs/nfsd/xdr4.h
@@ -1011,6 +1011,8 @@ extern __be32 nfsd4_test_stateid(struct svc_rqst *rqstp,
extern __be32 nfsd4_free_stateid(struct svc_rqst *rqstp,
struct nfsd4_compound_state *, union nfsd4_op_u *);
extern void nfsd4_bump_seqid(struct nfsd4_compound_state *, __be32 nfserr);
+__be32 nfsd4_decode_nfs4_acl_passthru(struct nfsd4_compoundargs *,
+ u32 *bmval, struct nfs4_acl **acl);
enum nfsd4_op_flags {
ALLOWED_WITHOUT_FH = 1 << 0, /* No current filehandle required */
--
2.44.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [RFC PATCH 06/11] NFSD: add NFS4 reexport support for GETACL nfs4_acl passthru
2026-02-19 22:13 [RFC PATCH 00/11] NFS/NFSD: nfs4_acl passthru for NFSv4 reexport Mike Snitzer
` (4 preceding siblings ...)
2026-02-19 22:13 ` [RFC PATCH 05/11] NFSD: add NFS4 reexport support for " Mike Snitzer
@ 2026-02-19 22:13 ` Mike Snitzer
2026-02-19 22:13 ` [RFC PATCH 07/11] NFSD: add NFS4ACL_DACL and NFS4ACL_SACL passthru support Mike Snitzer
` (6 subsequent siblings)
12 siblings, 0 replies; 20+ messages in thread
From: Mike Snitzer @ 2026-02-19 22:13 UTC (permalink / raw)
To: Chuck Lever, Jeff Layton, Trond Myklebust, Anna Schumaker; +Cc: linux-nfs
From: Mike Snitzer <snitzer@hammerspace.com>
Allow NFSD's 4.1 reexport of a 4.2 mount to perform GETACL by passing
thru nfs4_acl whose pages are allocated in nfsd4_get_nfs4_acl_passthru
and then passed down to exported filesystem's ops->getacl(). Once
nfs4_acl is retrieved nfsd4_encode_fattr4_acl() will send the
ACL payload to the client using nfsd4_encode_nfs4_acl_passthru().
Signed-off-by: Mike Snitzer <snitzer@hammerspace.com>
---
fs/nfsd/acl.h | 3 ++-
fs/nfsd/nfs4acl.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++-
fs/nfsd/nfs4xdr.c | 33 ++++++++++++++++++++++-
3 files changed, 102 insertions(+), 3 deletions(-)
diff --git a/fs/nfsd/acl.h b/fs/nfsd/acl.h
index 699a3b19bdb8..488be04551e4 100644
--- a/fs/nfsd/acl.h
+++ b/fs/nfsd/acl.h
@@ -42,13 +42,14 @@ struct svc_fh;
struct svc_rqst;
struct nfsd_attrs;
enum nfs_ftype4;
+enum nfs4_acl_type;
int nfs4_acl_bytes(int entries);
int nfs4_acl_get_whotype(char *, u32);
__be32 nfs4_acl_write_who(struct xdr_stream *xdr, int who);
int nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry,
- struct nfs4_acl **acl);
+ enum nfs4_acl_type acl_type, struct nfs4_acl **acl);
__be32 nfsd4_acl_to_attr(enum nfs_ftype4 type, struct nfs4_acl *acl,
struct nfsd_attrs *attr);
void sort_pacl_range(struct posix_acl *pacl, int start, int end);
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
index 2c2f2fd89e87..2d494909e63a 100644
--- a/fs/nfsd/nfs4acl.c
+++ b/fs/nfsd/nfs4acl.c
@@ -37,6 +37,7 @@
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/posix_acl.h>
+#include <linux/nfsacl.h>
#include "nfsfh.h"
#include "nfsd.h"
@@ -125,9 +126,62 @@ static short ace2type(struct nfs4_ace *);
static void _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *,
unsigned int);
+static int
+nfsd4_get_nfs4_acl_passthru(struct inode *inode,
+ const struct export_operations *ops,
+ enum nfs4_acl_type acl_type,
+ u32 acl_len, struct nfs4_acl **acl)
+{
+ int error = 0;
+ int i = 0;
+ unsigned int npages;
+
+ npages = DIV_ROUND_UP(acl_len, PAGE_SIZE);
+ *acl = kmalloc(sizeof(struct nfs4_acl) +
+ npages * sizeof(struct page *), GFP_KERNEL);
+ if (*acl == NULL)
+ return -ENOMEM;
+
+ (*acl)->type = acl_type;
+ (*acl)->len = acl_len = npages * PAGE_SIZE;
+ (*acl)->pgbase = 0;
+
+ for (; i < npages; i++) {
+ (*acl)->pages[i] = alloc_page(GFP_KERNEL);
+ if (!(*acl)->pages[i]) {
+ error = -ENOMEM;
+ goto out;
+ }
+ }
+
+ if (unlikely(!ops->getacl)) {
+ error = -EOPNOTSUPP;
+ goto out;
+ }
+
+ error = ops->getacl(inode, *acl);
+ if (likely(error > 0)) {
+ error = 0; /* don't error out below */
+ if ((*acl)->len < acl_len) {
+ /* free any unused pages */
+ npages = DIV_ROUND_UP((*acl)->len, PAGE_SIZE);
+ while (--i >= npages)
+ __free_page((*acl)->pages[i]);
+ }
+ }
+out:
+ if (error) {
+ while (--i >= 0)
+ __free_page((*acl)->pages[i]);
+ kfree(*acl);
+ *acl = NULL;
+ }
+ return error;
+}
+
int
nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry,
- struct nfs4_acl **acl)
+ enum nfs4_acl_type acl_type, struct nfs4_acl **acl)
{
struct inode *inode = d_inode(dentry);
int error = 0;
@@ -157,6 +211,19 @@ nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry,
size += 2 * dpacl->a_count;
}
+ if (!IS_POSIXACL(inode) &&
+ exportfs_may_passthru_nfs4acl(dentry->d_sb->s_export_op)) {
+ /* Ensure NFSv4 ACL has adequate space based on POSIX ACL size */
+ u32 acl_len = min_t(u32, svc_max_payload(rqstp),
+ (2 * nfs4_acl_bytes(size) -
+ 2 * sizeof(struct nfs4_acl)));
+ const struct export_operations *ops = dentry->d_sb->s_export_op;
+
+ error = nfsd4_get_nfs4_acl_passthru(inode, ops, acl_type,
+ acl_len, acl);
+ goto out;
+ }
+
*acl = kmalloc(nfs4_acl_bytes(size), GFP_KERNEL);
if (*acl == NULL) {
error = -ENOMEM;
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index f14c2fb45142..01d362a486f8 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -3391,6 +3391,33 @@ static __be32 nfsd4_encode_fattr4_aclsupport(struct xdr_stream *xdr,
return nfsd4_encode_uint32_t(xdr, mask);
}
+static __be32 nfsd4_encode_nfs4_acl_passthru(struct xdr_stream *xdr,
+ struct nfs4_acl *acl)
+{
+ uint32_t pgbase = acl->pgbase;
+ uint32_t remaining = acl->len;
+ unsigned int npages = DIV_ROUND_UP(remaining, PAGE_SIZE);
+
+ for (int i = 0; i < npages; i++) {
+ void *vaddr = page_address(acl->pages[i]);
+ size_t len = (remaining < PAGE_SIZE) ? remaining : PAGE_SIZE;
+
+ if (pgbase) {
+ vaddr += pgbase;
+ pgbase = 0;
+ }
+ WARN_ON_ONCE(xdr_stream_encode_opaque_fixed(xdr, vaddr, len) < 0);
+ remaining -= len;
+ /*
+ * Free each page that was allocated using alloc_page()
+ * in nfsd4_get_nfs4_acl_passthru().
+ */
+ __free_page(acl->pages[i]);
+ }
+
+ return nfs_ok;
+}
+
static __be32 nfsd4_encode_fattr4_acl(struct xdr_stream *xdr,
const struct nfsd4_fattr_args *args)
{
@@ -3403,6 +3430,10 @@ static __be32 nfsd4_encode_fattr4_acl(struct xdr_stream *xdr,
if (xdr_stream_encode_u32(xdr, 0) != XDR_UNIT)
return nfserr_resource;
} else {
+ if (!IS_POSIXACL(d_inode(args->dentry)) &&
+ exportfs_may_passthru_nfs4acl(args->dentry->d_sb->s_export_op))
+ return nfsd4_encode_nfs4_acl_passthru(xdr, acl);
+
if (xdr_stream_encode_u32(xdr, acl->naces) != XDR_UNIT)
return nfserr_resource;
for (ace = acl->aces; ace < acl->aces + acl->naces; ace++) {
@@ -4029,7 +4060,7 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
args.fhp = fhp;
if (attrmask[0] & FATTR4_WORD0_ACL) {
- err = nfsd4_get_nfs4_acl(rqstp, dentry, &args.acl);
+ err = nfsd4_get_nfs4_acl(rqstp, dentry, NFS4ACL_ACL, &args.acl);
if (err == -EOPNOTSUPP)
attrmask[0] &= ~FATTR4_WORD0_ACL;
else if (err == -EINVAL) {
--
2.44.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [RFC PATCH 07/11] NFSD: add NFS4ACL_DACL and NFS4ACL_SACL passthru support
2026-02-19 22:13 [RFC PATCH 00/11] NFS/NFSD: nfs4_acl passthru for NFSv4 reexport Mike Snitzer
` (5 preceding siblings ...)
2026-02-19 22:13 ` [RFC PATCH 06/11] NFSD: add NFS4 reexport support for GETACL " Mike Snitzer
@ 2026-02-19 22:13 ` Mike Snitzer
2026-02-19 22:13 ` [RFC PATCH 08/11] NFSD: avoid extra nfs4_acl passthru work unless needed Mike Snitzer
` (5 subsequent siblings)
12 siblings, 0 replies; 20+ messages in thread
From: Mike Snitzer @ 2026-02-19 22:13 UTC (permalink / raw)
To: Chuck Lever, Jeff Layton, Trond Myklebust, Anna Schumaker; +Cc: linux-nfs
From: Mike Snitzer <snitzer@hammerspace.com>
This 4.1 DACL and SACL support is confined to NFSD's NFS reexport case
(e.g. when NFSD 4.1 reexports NFS 4.2).
Signed-off-by: Mike Snitzer <snitzer@hammerspace.com>
---
fs/nfsd/nfs4proc.c | 3 +++
fs/nfsd/nfs4xdr.c | 49 ++++++++++++++++++++++++++++++++++++++--------
fs/nfsd/nfsd.h | 5 +++--
3 files changed, 47 insertions(+), 10 deletions(-)
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 796954a24cde..86c792996d85 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -91,6 +91,9 @@ check_attr_support(struct nfsd4_compound_state *cstate, u32 *bmval,
return nfserr_attrnotsupp;
if ((bmval[0] & FATTR4_WORD0_ACL) && !nfsd_supports_nfs4_acl(dentry))
return nfserr_attrnotsupp;
+ if ((bmval[1] & (FATTR4_WORD1_DACL | FATTR4_WORD1_SACL)) &&
+ !nfsd_supports_nfs4_acl(dentry))
+ return nfserr_attrnotsupp;
if ((bmval[2] & (FATTR4_WORD2_POSIX_DEFAULT_ACL |
FATTR4_WORD2_POSIX_ACCESS_ACL)) &&
!IS_POSIXACL(d_inode(dentry)))
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 01d362a486f8..45aecf1c7878 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -315,7 +315,13 @@ __be32 nfsd4_decode_nfs4_acl_passthru(struct nfsd4_compoundargs *argp,
goto out;
}
- (*acl)->type = NFS4ACL_ACL;
+ if (bmval[0] & FATTR4_WORD0_ACL)
+ (*acl)->type = NFS4ACL_ACL;
+ else if (bmval[1] & FATTR4_WORD1_DACL)
+ (*acl)->type = NFS4ACL_DACL;
+ else if (bmval[1] & FATTR4_WORD1_SACL)
+ (*acl)->type = NFS4ACL_SACL;
+
(*acl)->len = acl_len;
(*acl)->pgbase = pgbase;
@@ -571,7 +577,8 @@ nfsd4_decode_fattr4(struct nfsd4_compoundargs *argp, u32 *bmval, u32 bmlen,
iattr->ia_size = size;
iattr->ia_valid |= ATTR_SIZE;
}
- if (bmval[0] & FATTR4_WORD0_ACL) {
+ if (bmval[0] & FATTR4_WORD0_ACL ||
+ (bmval[1] & (FATTR4_WORD1_DACL | FATTR4_WORD1_SACL))) {
status = nfsd4_decode_acl(argp, acl, attrlist4_count);
if (status)
return status;
@@ -3253,8 +3260,12 @@ static __be32 nfsd4_encode_fattr4_supported_attrs(struct xdr_stream *xdr,
u32 supp[3];
memcpy(supp, nfsd_suppattrs[minorversion], sizeof(supp));
- if (!nfsd_supports_nfs4_acl(args->dentry))
- supp[0] &= ~FATTR4_WORD0_ACL;
+ if (!nfsd_supports_nfs4_acl(args->dentry)) {
+ if (supp[0] & FATTR4_WORD0_ACL)
+ supp[0] &= ~FATTR4_WORD0_ACL;
+ else if ((supp[1] & (FATTR4_WORD1_DACL | FATTR4_WORD1_SACL)))
+ supp[1] &= ~(FATTR4_WORD1_DACL | FATTR4_WORD1_SACL);
+ }
if (!args->contextsupport)
supp[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
@@ -3689,8 +3700,12 @@ static __be32 nfsd4_encode_fattr4_suppattr_exclcreat(struct xdr_stream *xdr,
u32 supp[3];
memcpy(supp, nfsd_suppattrs[resp->cstate.minorversion], sizeof(supp));
- if (!nfsd_supports_nfs4_acl(args->dentry))
- supp[0] &= ~FATTR4_WORD0_ACL;
+ if (!nfsd_supports_nfs4_acl(args->dentry)) {
+ if (supp[0] & FATTR4_WORD0_ACL)
+ supp[0] &= ~FATTR4_WORD0_ACL;
+ else if ((supp[1] & (FATTR4_WORD1_DACL | FATTR4_WORD1_SACL)))
+ supp[1] &= ~(FATTR4_WORD1_DACL | FATTR4_WORD1_SACL);
+ }
if (!args->contextsupport)
supp[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
@@ -3880,8 +3895,8 @@ static const nfsd4_enc_attr nfsd4_enc_fattr4_encode_ops[] = {
[FATTR4_MOUNTED_ON_FILEID] = nfsd4_encode_fattr4_mounted_on_fileid,
[FATTR4_DIR_NOTIF_DELAY] = nfsd4_encode_fattr4__noop,
[FATTR4_DIRENT_NOTIF_DELAY] = nfsd4_encode_fattr4__noop,
- [FATTR4_DACL] = nfsd4_encode_fattr4__noop,
- [FATTR4_SACL] = nfsd4_encode_fattr4__noop,
+ [FATTR4_DACL] = nfsd4_encode_fattr4_acl,
+ [FATTR4_SACL] = nfsd4_encode_fattr4_acl,
[FATTR4_CHANGE_POLICY] = nfsd4_encode_fattr4__noop,
[FATTR4_FS_STATUS] = nfsd4_encode_fattr4__noop,
@@ -4068,6 +4083,24 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
goto out;
} else if (err != 0)
goto out_nfserr;
+ } else if (attrmask[1] & FATTR4_WORD1_DACL) {
+ err = nfsd4_get_nfs4_acl(rqstp, dentry, NFS4ACL_DACL, &args.acl);
+ if (err == -EOPNOTSUPP)
+ attrmask[1] &= ~FATTR4_WORD1_DACL;
+ else if (err == -EINVAL) {
+ status = nfserr_attrnotsupp;
+ goto out;
+ } else if (err != 0)
+ goto out_nfserr;
+ } else if (attrmask[1] & FATTR4_WORD1_SACL) {
+ err = nfsd4_get_nfs4_acl(rqstp, dentry, NFS4ACL_SACL, &args.acl);
+ if (err == -EOPNOTSUPP)
+ attrmask[1] &= ~FATTR4_WORD1_SACL;
+ else if (err == -EINVAL) {
+ status = nfserr_attrnotsupp;
+ goto out;
+ } else if (err != 0)
+ goto out_nfserr;
}
args.contextsupport = false;
diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
index a01d70953358..34f3254ba939 100644
--- a/fs/nfsd/nfsd.h
+++ b/fs/nfsd/nfsd.h
@@ -441,7 +441,8 @@ enum {
NFSD4_SUPPORTED_ATTRS_WORD0
#define NFSD4_1_SUPPORTED_ATTRS_WORD1 \
- (NFSD4_SUPPORTED_ATTRS_WORD1 | PNFSD_SUPPORTED_ATTRS_WORD1)
+ (NFSD4_SUPPORTED_ATTRS_WORD1 | PNFSD_SUPPORTED_ATTRS_WORD1 | \
+ FATTR4_WORD1_DACL | FATTR4_WORD1_SACL)
#define NFSD4_1_SUPPORTED_ATTRS_WORD2 \
(NFSD4_SUPPORTED_ATTRS_WORD2 | PNFSD_SUPPORTED_ATTRS_WORD2 | \
@@ -534,7 +535,7 @@ static inline bool nfsd_attrs_supported(u32 minorversion, const u32 *bmval)
#define NFSD_WRITEABLE_ATTRS_WORD1 \
(FATTR4_WORD1_MODE | FATTR4_WORD1_OWNER | FATTR4_WORD1_OWNER_GROUP \
| FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_CREATE \
- | FATTR4_WORD1_TIME_MODIFY_SET)
+ | FATTR4_WORD1_TIME_MODIFY_SET | FATTR4_WORD1_DACL | FATTR4_WORD1_SACL)
#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
#define MAYBE_FATTR4_WORD2_SECURITY_LABEL \
FATTR4_WORD2_SECURITY_LABEL
--
2.44.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [RFC PATCH 08/11] NFSD: avoid extra nfs4_acl passthru work unless needed
2026-02-19 22:13 [RFC PATCH 00/11] NFS/NFSD: nfs4_acl passthru for NFSv4 reexport Mike Snitzer
` (6 preceding siblings ...)
2026-02-19 22:13 ` [RFC PATCH 07/11] NFSD: add NFS4ACL_DACL and NFS4ACL_SACL passthru support Mike Snitzer
@ 2026-02-19 22:13 ` Mike Snitzer
2026-02-19 22:13 ` [RFC PATCH 09/11] NFSv4: add reexport support for SETACL nfs4_acl passthru Mike Snitzer
` (4 subsequent siblings)
12 siblings, 0 replies; 20+ messages in thread
From: Mike Snitzer @ 2026-02-19 22:13 UTC (permalink / raw)
To: Chuck Lever, Jeff Layton, Trond Myklebust, Anna Schumaker; +Cc: linux-nfs
From: Mike Snitzer <snitzer@hammerspace.com>
Avoid the nfsd4_decode_acl()'s memcpy() work, that
nfsd4_decode_nfs4_acl_passthru() requires, unless
nfsd4_encode_nfs4_acl_passthru() has already been called.
Implemented by enabling and checking a static_key.
Mike Snitzer <snitzer@hammerspace.com>
---
fs/nfsd/nfs4xdr.c | 20 +++++++++++++++++---
1 file changed, 17 insertions(+), 3 deletions(-)
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 45aecf1c7878..113e478ebc8d 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -287,6 +287,8 @@ nfsd4_decode_bitmap4(struct nfsd4_compoundargs *argp, u32 *bmval, u32 bmlen)
return status == -EBADMSG ? nfserr_bad_xdr : nfs_ok;
}
+static DEFINE_STATIC_KEY_FALSE(nfs4_acl_passthru);
+
__be32 nfsd4_decode_nfs4_acl_passthru(struct nfsd4_compoundargs *argp,
u32 *bmval, struct nfs4_acl **acl)
{
@@ -296,6 +298,9 @@ __be32 nfsd4_decode_nfs4_acl_passthru(struct nfsd4_compoundargs *argp,
__be32 status = nfs_ok;
void *p;
+ if (WARN_ON_ONCE(!static_key_enabled(&nfs4_acl_passthru.key)))
+ return nfserr_resource;
+
xdr_init_decode(&xdr, &(*acl)->payload,
(*acl)->payload.head[0].iov_base, NULL);
@@ -378,8 +383,8 @@ nfsd4_decode_acl(struct nfsd4_compoundargs *argp, struct nfs4_acl **acl,
if (!xdr_stream_subsegment(argp->xdr, &payload, acl_len))
return nfserr_bad_xdr;
- memcpy(&saved_payload, &payload, sizeof(struct xdr_buf));
-
+ if (static_key_enabled(&nfs4_acl_passthru.key))
+ memcpy(&saved_payload, &payload, sizeof(struct xdr_buf));
xdr_init_decode(&xdr, &payload, payload.head[0].iov_base, NULL);
if (xdr_stream_decode_u32(&xdr, &count) < 0) {
@@ -402,7 +407,9 @@ nfsd4_decode_acl(struct nfsd4_compoundargs *argp, struct nfs4_acl **acl,
status = nfserr_jukebox;
goto out;
}
- memcpy(&(*acl)->payload, &saved_payload, sizeof(struct xdr_buf));
+ if (static_key_enabled(&nfs4_acl_passthru.key))
+ memcpy(&(*acl)->payload, &saved_payload,
+ sizeof(struct xdr_buf));
(*acl)->naces = count;
for (ace = (*acl)->aces; ace < (*acl)->aces + count; ace++) {
@@ -3409,6 +3416,13 @@ static __be32 nfsd4_encode_nfs4_acl_passthru(struct xdr_stream *xdr,
uint32_t remaining = acl->len;
unsigned int npages = DIV_ROUND_UP(remaining, PAGE_SIZE);
+ /*
+ * GETACL will precede SETACL, if passthru is used for
+ * GETACL then enable SETACL's extra work required
+ * to support passthru.
+ */
+ static_key_enable(&nfs4_acl_passthru.key);
+
for (int i = 0; i < npages; i++) {
void *vaddr = page_address(acl->pages[i]);
size_t len = (remaining < PAGE_SIZE) ? remaining : PAGE_SIZE;
--
2.44.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [RFC PATCH 09/11] NFSv4: add reexport support for SETACL nfs4_acl passthru
2026-02-19 22:13 [RFC PATCH 00/11] NFS/NFSD: nfs4_acl passthru for NFSv4 reexport Mike Snitzer
` (7 preceding siblings ...)
2026-02-19 22:13 ` [RFC PATCH 08/11] NFSD: avoid extra nfs4_acl passthru work unless needed Mike Snitzer
@ 2026-02-19 22:13 ` Mike Snitzer
2026-02-19 22:13 ` [RFC PATCH 10/11] NFSv4: add reexport support for GETACL " Mike Snitzer
` (3 subsequent siblings)
12 siblings, 0 replies; 20+ messages in thread
From: Mike Snitzer @ 2026-02-19 22:13 UTC (permalink / raw)
To: Chuck Lever, Jeff Layton, Trond Myklebust, Anna Schumaker; +Cc: linux-nfs
From: Mike Snitzer <snitzer@hammerspace.com>
Wire up the export_operations .setacl hook and use the upper layer
provided nfs4_acl's pages in the call to NFSPROC4_CLNT_SETACL.
Signed-off-by: Mike Snitzer <snitzer@hammerspace.com>
---
fs/nfs/export.c | 10 ++++++++++
fs/nfs/nfs4proc.c | 33 +++++++++++++++++++++++++++------
fs/nfs/nfs4xdr.c | 2 +-
include/linux/nfs_xdr.h | 3 +++
4 files changed, 41 insertions(+), 7 deletions(-)
diff --git a/fs/nfs/export.c b/fs/nfs/export.c
index a10dd5f9d078..9a90eee3e433 100644
--- a/fs/nfs/export.c
+++ b/fs/nfs/export.c
@@ -152,10 +152,20 @@ nfs_get_parent(struct dentry *dentry)
return parent;
}
+static int nfs_set_nfs4_acl(struct inode *inode, struct nfs4_acl *acl)
+{
+ const struct nfs_rpc_ops *rpc_ops = NFS_SERVER(inode)->nfs_client->rpc_ops;
+
+ if (rpc_ops->set_nfs4_acl == NULL)
+ return -EOPNOTSUPP;
+ return rpc_ops->set_nfs4_acl(inode, acl);
+}
+
const struct export_operations nfs_export_ops = {
.encode_fh = nfs_encode_fh,
.fh_to_dentry = nfs_fh_to_dentry,
.get_parent = nfs_get_parent,
+ .setacl = nfs_set_nfs4_acl,
.flags = EXPORT_OP_NOWCC |
EXPORT_OP_NOSUBTREECHK |
EXPORT_OP_CLOSE_BEFORE_UNLINK |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index f3116145b354..f97ef2d41e35 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -6219,7 +6219,8 @@ static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen,
}
static int __nfs4_proc_set_acl(struct inode *inode, const void *buf,
- size_t buflen, enum nfs4_acl_type type)
+ size_t buflen, enum nfs4_acl_type type,
+ struct nfs4_acl *acl)
{
struct nfs_server *server = NFS_SERVER(inode);
struct page *pages[NFS4ACL_MAXPAGES];
@@ -6227,6 +6228,7 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf,
.fh = NFS_FH(inode),
.acl_type = type,
.acl_len = buflen,
+ .acl_pgbase = 0,
.acl_pages = pages,
};
struct nfs_setaclres res;
@@ -6238,6 +6240,15 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf,
unsigned int npages = DIV_ROUND_UP(buflen, PAGE_SIZE);
int ret, i;
+ if (acl != NULL) {
+ arg.acl_len = acl->len;
+ arg.acl_pgbase = acl->pgbase;
+ arg.acl_pages = acl->pages;
+ nfs4_inode_make_writeable(inode);
+ ret = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1);
+ goto out;
+ }
+
/* You can't remove system.nfs4_acl: */
if (buflen == 0)
return -EINVAL;
@@ -6262,6 +6273,7 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf,
* Acl update can result in inode attribute update.
* so mark the attribute cache invalid.
*/
+out:
spin_lock(&inode->i_lock);
nfs_set_cache_invalid(inode, NFS_INO_INVALID_CHANGE |
NFS_INO_INVALID_CTIME |
@@ -6273,7 +6285,8 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf,
}
static int nfs4_proc_set_acl(struct inode *inode, const void *buf,
- size_t buflen, enum nfs4_acl_type type)
+ size_t buflen, enum nfs4_acl_type type,
+ struct nfs4_acl *acl)
{
struct nfs4_exception exception = { };
int err;
@@ -6281,7 +6294,7 @@ static int nfs4_proc_set_acl(struct inode *inode, const void *buf,
if (unlikely(NFS_FH(inode)->size == 0))
return -ENODATA;
do {
- err = __nfs4_proc_set_acl(inode, buf, buflen, type);
+ err = __nfs4_proc_set_acl(inode, buf, buflen, type, acl);
trace_nfs4_set_acl(inode, err);
if (err == -NFS4ERR_BADOWNER || err == -NFS4ERR_BADNAME) {
/*
@@ -6297,6 +6310,13 @@ static int nfs4_proc_set_acl(struct inode *inode, const void *buf,
return err;
}
+static int nfs4_set_nfs4_acl(struct inode *inode, struct nfs4_acl *acl)
+{
+ if (!nfs4_server_supports_acls(NFS_SERVER(inode), acl->type))
+ return -EOPNOTSUPP;
+ return nfs4_proc_set_acl(inode, NULL, 0, acl->type, acl);
+}
+
#ifdef CONFIG_NFS_V4_SECURITY_LABEL
static int _nfs4_get_security_label(struct inode *inode, void *buf,
size_t buflen)
@@ -7950,7 +7970,7 @@ static int nfs4_xattr_set_nfs4_acl(const struct xattr_handler *handler,
const char *key, const void *buf,
size_t buflen, int flags)
{
- return nfs4_proc_set_acl(inode, buf, buflen, NFS4ACL_ACL);
+ return nfs4_proc_set_acl(inode, buf, buflen, NFS4ACL_ACL, NULL);
}
static int nfs4_xattr_get_nfs4_acl(const struct xattr_handler *handler,
@@ -7974,7 +7994,7 @@ static int nfs4_xattr_set_nfs4_dacl(const struct xattr_handler *handler,
const char *key, const void *buf,
size_t buflen, int flags)
{
- return nfs4_proc_set_acl(inode, buf, buflen, NFS4ACL_DACL);
+ return nfs4_proc_set_acl(inode, buf, buflen, NFS4ACL_DACL, NULL);
}
static int nfs4_xattr_get_nfs4_dacl(const struct xattr_handler *handler,
@@ -7997,7 +8017,7 @@ static int nfs4_xattr_set_nfs4_sacl(const struct xattr_handler *handler,
const char *key, const void *buf,
size_t buflen, int flags)
{
- return nfs4_proc_set_acl(inode, buf, buflen, NFS4ACL_SACL);
+ return nfs4_proc_set_acl(inode, buf, buflen, NFS4ACL_SACL, NULL);
}
static int nfs4_xattr_get_nfs4_sacl(const struct xattr_handler *handler,
@@ -11020,6 +11040,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
.discover_trunking = nfs4_discover_trunking,
.enable_swap = nfs4_enable_swap,
.disable_swap = nfs4_disable_swap,
+ .set_nfs4_acl = nfs4_set_nfs4_acl,
};
static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = {
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 1d0e6c10f921..228dbb2a8af5 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -1717,7 +1717,7 @@ static void encode_setacl(struct xdr_stream *xdr,
encode_nfs4_stateid(xdr, &zero_stateid);
xdr_encode_bitmap4(xdr, bitmap, ARRAY_SIZE(bitmap));
encode_uint32(xdr, arg->acl_len);
- xdr_write_pages(xdr, arg->acl_pages, 0, arg->acl_len);
+ xdr_write_pages(xdr, arg->acl_pages, arg->acl_pgbase, arg->acl_len);
}
static void
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 65dbe7c05346..47cb3b140640 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -832,6 +832,7 @@ struct nfs_setaclargs {
struct nfs_fh * fh;
enum nfs4_acl_type acl_type;
size_t acl_len;
+ unsigned int acl_pgbase;
struct page ** acl_pages;
};
@@ -1759,6 +1760,7 @@ struct nfs_mount_info;
struct nfs_client_initdata;
struct nfs_pageio_descriptor;
struct fs_context;
+struct nfs4_acl;
/*
* RPC procedure vector for NFSv2/NFSv3 demuxing
@@ -1845,6 +1847,7 @@ struct nfs_rpc_ops {
int (*discover_trunking)(struct nfs_server *, struct nfs_fh *);
void (*enable_swap)(struct inode *inode);
void (*disable_swap)(struct inode *inode);
+ int (*set_nfs4_acl)(struct inode *, struct nfs4_acl *);
};
/*
--
2.44.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [RFC PATCH 10/11] NFSv4: add reexport support for GETACL nfs4_acl passthru
2026-02-19 22:13 [RFC PATCH 00/11] NFS/NFSD: nfs4_acl passthru for NFSv4 reexport Mike Snitzer
` (8 preceding siblings ...)
2026-02-19 22:13 ` [RFC PATCH 09/11] NFSv4: add reexport support for SETACL nfs4_acl passthru Mike Snitzer
@ 2026-02-19 22:13 ` Mike Snitzer
2026-02-19 22:13 ` [RFC PATCH 11/11] NFSv4: set EXPORT_OP_NFSV4_ACL_PASSTHRU flag Mike Snitzer
` (2 subsequent siblings)
12 siblings, 0 replies; 20+ messages in thread
From: Mike Snitzer @ 2026-02-19 22:13 UTC (permalink / raw)
To: Chuck Lever, Jeff Layton, Trond Myklebust, Anna Schumaker; +Cc: linux-nfs
From: Mike Snitzer <snitzer@hammerspace.com>
Wire up the export_operations .getacl hook and use the upper layer
provided nfs4_acl's pages in the call to NFSPROC4_CLNT_GETACL.
In this reexporting case (e.g. 4.1 reexporting 4.2),
__nfs4_get_acl_uncached() is always used because the NFSv4 client's
cache is designed to reply with the buffer that gets generated from
the ACL's pages. So the frontend client (4.1) will cache the ACL
returned by the backend (4.2) client.
Signed-off-by: Mike Snitzer <snitzer@hammerspace.com>
---
fs/nfs/export.c | 10 ++++++
fs/nfs/nfs4proc.c | 79 ++++++++++++++++++++++++++++-------------
include/linux/nfs_xdr.h | 1 +
3 files changed, 65 insertions(+), 25 deletions(-)
diff --git a/fs/nfs/export.c b/fs/nfs/export.c
index 9a90eee3e433..6623eb13f4e6 100644
--- a/fs/nfs/export.c
+++ b/fs/nfs/export.c
@@ -161,11 +161,21 @@ static int nfs_set_nfs4_acl(struct inode *inode, struct nfs4_acl *acl)
return rpc_ops->set_nfs4_acl(inode, acl);
}
+static int nfs_get_nfs4_acl(struct inode *inode, struct nfs4_acl *acl)
+{
+ const struct nfs_rpc_ops *rpc_ops = NFS_SERVER(inode)->nfs_client->rpc_ops;
+
+ if (rpc_ops->get_nfs4_acl == NULL)
+ return -EOPNOTSUPP;
+ return rpc_ops->get_nfs4_acl(inode, acl);
+}
+
const struct export_operations nfs_export_ops = {
.encode_fh = nfs_encode_fh,
.fh_to_dentry = nfs_fh_to_dentry,
.get_parent = nfs_get_parent,
.setacl = nfs_set_nfs4_acl,
+ .getacl = nfs_get_nfs4_acl,
.flags = EXPORT_OP_NOWCC |
EXPORT_OP_NOSUBTREECHK |
EXPORT_OP_CLOSE_BEFORE_UNLINK |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index f97ef2d41e35..480c06b69296 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -6099,7 +6099,8 @@ static void nfs4_write_cached_acl(struct inode *inode, struct page **pages,
* the server, this time with the input buf of the required size.
*/
static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf,
- size_t buflen, enum nfs4_acl_type type)
+ size_t buflen, enum nfs4_acl_type type,
+ struct nfs4_acl *acl)
{
struct page **pages;
struct nfs_getaclargs args = {
@@ -6123,26 +6124,29 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf,
if (buflen == 0)
buflen = server->rsize;
- npages = DIV_ROUND_UP(buflen, PAGE_SIZE) + 1;
- pages = kmalloc_array(npages, sizeof(struct page *), GFP_KERNEL);
- if (!pages)
- return -ENOMEM;
+ if (!acl) {
+ npages = DIV_ROUND_UP(buflen, PAGE_SIZE) + 1;
+ pages = kmalloc_array(npages, sizeof(struct page *), GFP_KERNEL);
+ if (!pages)
+ return -ENOMEM;
+ for (i = 0; i < npages; i++) {
+ pages[i] = alloc_page(GFP_KERNEL);
+ if (!pages[i])
+ goto out_free;
+ }
+ args.acl_len = npages * PAGE_SIZE;
+ } else {
+ npages = DIV_ROUND_UP(buflen, PAGE_SIZE);
+ pages = acl->pages;
+ }
args.acl_pages = pages;
- for (i = 0; i < npages; i++) {
- pages[i] = alloc_page(GFP_KERNEL);
- if (!pages[i])
- goto out_free;
- }
-
/* for decoding across pages */
res.acl_scratch = folio_alloc(GFP_KERNEL, 0);
if (!res.acl_scratch)
goto out_free;
- args.acl_len = npages * PAGE_SIZE;
-
dprintk("%s buf %p buflen %zu npages %d args.acl_len %zu\n",
__func__, buf, buflen, npages, args.acl_len);
ret = nfs4_call_sync(NFS_SERVER(inode)->client, NFS_SERVER(inode),
@@ -6158,8 +6162,18 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf,
ret = -ERANGE;
goto out_free;
}
- nfs4_write_cached_acl(inode, pages, res.acl_data_offset, res.acl_len,
- type);
+
+ if (!acl) {
+ nfs4_write_cached_acl(inode, pages, res.acl_data_offset,
+ res.acl_len, type);
+ } else {
+ if (res.acl_len > buflen) {
+ ret = -ERANGE;
+ goto out_free;
+ }
+ acl->len = res.acl_len;
+ acl->pgbase = res.acl_data_offset;
+ }
if (buf) {
if (res.acl_len > buflen) {
ret = -ERANGE;
@@ -6170,23 +6184,26 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf,
out_ok:
ret = res.acl_len;
out_free:
- while (--i >= 0)
- __free_page(pages[i]);
+ if (!acl) {
+ while (--i >= 0)
+ __free_page(pages[i]);
+ kfree(pages);
+ }
if (res.acl_scratch)
folio_put(res.acl_scratch);
- kfree(pages);
return ret;
}
static ssize_t nfs4_get_acl_uncached(struct inode *inode, void *buf,
- size_t buflen, enum nfs4_acl_type type)
+ size_t buflen, enum nfs4_acl_type type,
+ struct nfs4_acl *acl)
{
struct nfs4_exception exception = {
.interruptible = true,
};
ssize_t ret;
do {
- ret = __nfs4_get_acl_uncached(inode, buf, buflen, type);
+ ret = __nfs4_get_acl_uncached(inode, buf, buflen, type, acl);
trace_nfs4_get_acl(inode, ret);
if (ret >= 0)
break;
@@ -6196,7 +6213,7 @@ static ssize_t nfs4_get_acl_uncached(struct inode *inode, void *buf,
}
static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen,
- enum nfs4_acl_type type)
+ enum nfs4_acl_type type, struct nfs4_acl *acl)
{
struct nfs_server *server = NFS_SERVER(inode);
int ret;
@@ -6210,12 +6227,23 @@ static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen,
return ret;
if (NFS_I(inode)->cache_validity & NFS_INO_INVALID_ACL)
nfs_zap_acl_cache(inode);
+ /* Must get ACL if @acl != NULL, frontend NFS layer will cache it */
+ if (acl != NULL)
+ goto get_acl_uncached;
ret = nfs4_read_cached_acl(inode, buf, buflen, type);
if (ret != -ENOENT)
/* -ENOENT is returned if there is no ACL or if there is an ACL
* but no cached acl data, just the acl length */
return ret;
- return nfs4_get_acl_uncached(inode, buf, buflen, type);
+get_acl_uncached:
+ return nfs4_get_acl_uncached(inode, buf, buflen, type, acl);
+}
+
+static int nfs4_get_nfs4_acl(struct inode *inode, struct nfs4_acl *acl)
+{
+ if (!nfs4_server_supports_acls(NFS_SERVER(inode), acl->type))
+ return -EOPNOTSUPP;
+ return nfs4_proc_get_acl(inode, NULL, acl->len, acl->type, acl);
}
static int __nfs4_proc_set_acl(struct inode *inode, const void *buf,
@@ -7977,7 +8005,7 @@ static int nfs4_xattr_get_nfs4_acl(const struct xattr_handler *handler,
struct dentry *unused, struct inode *inode,
const char *key, void *buf, size_t buflen)
{
- return nfs4_proc_get_acl(inode, buf, buflen, NFS4ACL_ACL);
+ return nfs4_proc_get_acl(inode, buf, buflen, NFS4ACL_ACL, NULL);
}
static bool nfs4_xattr_list_nfs4_acl(struct dentry *dentry)
@@ -8001,7 +8029,7 @@ static int nfs4_xattr_get_nfs4_dacl(const struct xattr_handler *handler,
struct dentry *unused, struct inode *inode,
const char *key, void *buf, size_t buflen)
{
- return nfs4_proc_get_acl(inode, buf, buflen, NFS4ACL_DACL);
+ return nfs4_proc_get_acl(inode, buf, buflen, NFS4ACL_DACL, NULL);
}
static bool nfs4_xattr_list_nfs4_dacl(struct dentry *dentry)
@@ -8024,7 +8052,7 @@ static int nfs4_xattr_get_nfs4_sacl(const struct xattr_handler *handler,
struct dentry *unused, struct inode *inode,
const char *key, void *buf, size_t buflen)
{
- return nfs4_proc_get_acl(inode, buf, buflen, NFS4ACL_SACL);
+ return nfs4_proc_get_acl(inode, buf, buflen, NFS4ACL_SACL, NULL);
}
static bool nfs4_xattr_list_nfs4_sacl(struct dentry *dentry)
@@ -11041,6 +11069,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
.enable_swap = nfs4_enable_swap,
.disable_swap = nfs4_disable_swap,
.set_nfs4_acl = nfs4_set_nfs4_acl,
+ .get_nfs4_acl = nfs4_get_nfs4_acl,
};
static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = {
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 47cb3b140640..4be2a40c7fc5 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1848,6 +1848,7 @@ struct nfs_rpc_ops {
void (*enable_swap)(struct inode *inode);
void (*disable_swap)(struct inode *inode);
int (*set_nfs4_acl)(struct inode *, struct nfs4_acl *);
+ int (*get_nfs4_acl)(struct inode *, struct nfs4_acl *);
};
/*
--
2.44.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [RFC PATCH 11/11] NFSv4: set EXPORT_OP_NFSV4_ACL_PASSTHRU flag
2026-02-19 22:13 [RFC PATCH 00/11] NFS/NFSD: nfs4_acl passthru for NFSv4 reexport Mike Snitzer
` (9 preceding siblings ...)
2026-02-19 22:13 ` [RFC PATCH 10/11] NFSv4: add reexport support for GETACL " Mike Snitzer
@ 2026-02-19 22:13 ` Mike Snitzer
2026-02-19 22:21 ` [RFC PATCH 00/11] NFS/NFSD: nfs4_acl passthru for NFSv4 reexport Chuck Lever
2026-02-22 17:53 ` Chuck Lever
12 siblings, 0 replies; 20+ messages in thread
From: Mike Snitzer @ 2026-02-19 22:13 UTC (permalink / raw)
To: Chuck Lever, Jeff Layton, Trond Myklebust, Anna Schumaker; +Cc: linux-nfs
From: Mike Snitzer <snitzer@hammerspace.com>
NFSv4 implements both .setacl and .getacl and so it is appropriate to
enable nfs4_acl passthru.
Signed-off-by: Mike Snitzer <snitzer@hammerspace.com>
---
fs/nfs/export.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/fs/nfs/export.c b/fs/nfs/export.c
index 6623eb13f4e6..f59839b48721 100644
--- a/fs/nfs/export.c
+++ b/fs/nfs/export.c
@@ -182,5 +182,6 @@ const struct export_operations nfs_export_ops = {
EXPORT_OP_REMOTE_FS |
EXPORT_OP_NOATOMIC_ATTR |
EXPORT_OP_FLUSH_ON_CLOSE |
- EXPORT_OP_NOLOCKS,
+ EXPORT_OP_NOLOCKS |
+ EXPORT_OP_NFSV4_ACL_PASSTHRU,
};
--
2.44.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [RFC PATCH 00/11] NFS/NFSD: nfs4_acl passthru for NFSv4 reexport
2026-02-19 22:13 [RFC PATCH 00/11] NFS/NFSD: nfs4_acl passthru for NFSv4 reexport Mike Snitzer
` (10 preceding siblings ...)
2026-02-19 22:13 ` [RFC PATCH 11/11] NFSv4: set EXPORT_OP_NFSV4_ACL_PASSTHRU flag Mike Snitzer
@ 2026-02-19 22:21 ` Chuck Lever
2026-02-19 23:07 ` Mike Snitzer
2026-02-19 23:57 ` Trond Myklebust
2026-02-22 17:53 ` Chuck Lever
12 siblings, 2 replies; 20+ messages in thread
From: Chuck Lever @ 2026-02-19 22:21 UTC (permalink / raw)
To: Mike Snitzer, Jeff Layton, Trond Myklebust, Anna Schumaker; +Cc: linux-nfs
On 2/19/26 5:13 PM, Mike Snitzer wrote:
> Hi,
>
> This patchset aims to enable NFS v4.1 ACLs to be fully supported from
> an NFS v4.1 client to an NFSD v4.1 export that reexports NFS v4.2
> filesystem which has full support for NFS v4.1 ACLs (DACL and SACL).
>
> The first 6 patches focus on nfs4_acl passthru enablement (primarily
> for NFSD), patch 7 adds 4.1 nfs4_acl passthru support (DACL and SACL),
> patch 8 optimizes particular nfs4_acl passthru implementation in NFSD
> to skip memcpy if nfs4_acl passthru isn't needed, patches 9-11 offer
> the corresponding required NFSv4 client changes.
>
> This work is based on the NFS and NFSD code that has been merged
> during the 7.0 merge window.
>
> This patchset is marked as RFC because I expect there will be
> suggestions for possible NFSD implementation improvements.
A couple of random observations:
1. I haven't been a fan of these double-subsystem patch sets. Is there
any way we can get this split into one set for NFSD and one for the NFS
client, with as little code sharing between the two as possible? Maybe a
pipe dream, I know.
2. Do you have a plan for similar passthru support for the NFSv4.2 POSIX
draft ACL extension?
> All review appreciated, thanks.
> Mike
>
> Mike Snitzer (11):
> exportfs: add ability to advertise NFSv4 ACL passthru support
> NFSD: factor out nfsd_supports_nfs4_acl() to nfsd/acl.h
> NFS/NFSD: data structure enablement for nfs4_acl passthru support
> NFSD: prepare to support SETACL nfs4_acl passthru
> NFSD: add NFS4 reexport support for SETACL nfs4_acl passthru
> NFSD: add NFS4 reexport support for GETACL nfs4_acl passthru
> NFSD: add NFS4ACL_DACL and NFS4ACL_SACL passthru support
> NFSD: avoid extra nfs4_acl passthru work unless needed
> NFSv4: add reexport support for SETACL nfs4_acl passthru
> NFSv4: add reexport support for GETACL nfs4_acl passthru
> NFSv4: set EXPORT_OP_NFSV4_ACL_PASSTHRU flag
>
> fs/nfs/export.c | 23 ++++-
> fs/nfs/nfs4proc.c | 112 +++++++++++++++-------
> fs/nfs/nfs4xdr.c | 2 +-
> fs/nfsd/acl.h | 11 ++-
> fs/nfsd/nfs4acl.c | 69 +++++++++++++-
> fs/nfsd/nfs4proc.c | 32 +++++--
> fs/nfsd/nfs4xdr.c | 194 +++++++++++++++++++++++++++++++++------
> fs/nfsd/nfsd.h | 5 +-
> fs/nfsd/xdr4.h | 2 +
> include/linux/exportfs.h | 22 +++++
> include/linux/nfs4.h | 23 ++++-
> include/linux/nfs_xdr.h | 11 +--
> include/linux/nfsacl.h | 7 ++
> 13 files changed, 431 insertions(+), 82 deletions(-)
>
--
Chuck Lever
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [RFC PATCH 00/11] NFS/NFSD: nfs4_acl passthru for NFSv4 reexport
2026-02-19 22:21 ` [RFC PATCH 00/11] NFS/NFSD: nfs4_acl passthru for NFSv4 reexport Chuck Lever
@ 2026-02-19 23:07 ` Mike Snitzer
2026-02-20 15:46 ` Chuck Lever
2026-02-19 23:57 ` Trond Myklebust
1 sibling, 1 reply; 20+ messages in thread
From: Mike Snitzer @ 2026-02-19 23:07 UTC (permalink / raw)
To: Chuck Lever; +Cc: Jeff Layton, Trond Myklebust, Anna Schumaker, linux-nfs
On Thu, Feb 19, 2026 at 05:21:06PM -0500, Chuck Lever wrote:
> On 2/19/26 5:13 PM, Mike Snitzer wrote:
> > Hi,
> >
> > This patchset aims to enable NFS v4.1 ACLs to be fully supported from
> > an NFS v4.1 client to an NFSD v4.1 export that reexports NFS v4.2
> > filesystem which has full support for NFS v4.1 ACLs (DACL and SACL).
> >
> > The first 6 patches focus on nfs4_acl passthru enablement (primarily
> > for NFSD), patch 7 adds 4.1 nfs4_acl passthru support (DACL and SACL),
> > patch 8 optimizes particular nfs4_acl passthru implementation in NFSD
> > to skip memcpy if nfs4_acl passthru isn't needed, patches 9-11 offer
> > the corresponding required NFSv4 client changes.
> >
> > This work is based on the NFS and NFSD code that has been merged
> > during the 7.0 merge window.
> >
> > This patchset is marked as RFC because I expect there will be
> > suggestions for possible NFSD implementation improvements.
>
> A couple of random observations:
>
> 1. I haven't been a fan of these double-subsystem patch sets. Is there
> any way we can get this split into one set for NFSD and one for the NFS
> client, with as little code sharing between the two as possible? Maybe a
> pipe dream, I know.
Open to suggestions, but the reexport nature of this patchset makes it
tough for each half to be entirely standalone.
As is, patches 1 - 8 could all land via NFSD. But the code would be
dormant because no filesystems would set EXPORT_OP_NFSV4_ACL_PASSTHRU.
NFS _could_ just apply patch 3 (so it'd duplicate NFSD's commit for
patch 3) and then apply NFS patches 9 - 11.
> 2. Do you have a plan for similar passthru support for the NFSv4.2 POSIX
> draft ACL extension?
Wasn't on my radar, but I know you and Rick have been busy getting
NFSv4 POSIX draft ACL support to land in NFSD. I still have work ahead
to understand all that you guys landed... but being POSIX I just paid
attention to the mutual exclusion of your newer work versus nfs4_acl.
Excuse my naivety but doesn't NFSD now provide support for NFSv4.2
POSIX draft ACL extension? So what's the usecase you're thinking
passthru would be meaningful for?
If you might provide some guidance on expected work items that'd help
plant seeds. I can try to bone up on NFSv4.2 POSIX draft ACL extension
and we could discuss further at Bake-a-thon?
Relative to NFS v4.1 ACL passthru, Hammerspace needing to support 4.1
access for the benefit of kerberos usage made adding 4.1 ACL passthru
to 4.2 a compelling feature/requirement to implement.
Mike
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [RFC PATCH 00/11] NFS/NFSD: nfs4_acl passthru for NFSv4 reexport
2026-02-19 22:21 ` [RFC PATCH 00/11] NFS/NFSD: nfs4_acl passthru for NFSv4 reexport Chuck Lever
2026-02-19 23:07 ` Mike Snitzer
@ 2026-02-19 23:57 ` Trond Myklebust
2026-02-20 15:33 ` Chuck Lever
1 sibling, 1 reply; 20+ messages in thread
From: Trond Myklebust @ 2026-02-19 23:57 UTC (permalink / raw)
To: Chuck Lever, Mike Snitzer, Jeff Layton, Anna Schumaker; +Cc: linux-nfs
On Thu, 2026-02-19 at 17:21 -0500, Chuck Lever wrote:
>
> 2. Do you have a plan for similar passthru support for the NFSv4.2
> POSIX
> draft ACL extension?
>
Why would we need that?
The current need for a passthrough mechanism is being driven by the
fact that knfsd unconditionally imposes it's own lossy mapping onto the
NFSv4 ACLs.
I'm assuming that for POSIX ACLs, knfsd will just pass them through
unmolested to the VFS layer. Subsequently, they will get passed to the
NFS client via the POSIX ACL interface, which pass them on to any
server that does support that kind of ACL, and fail if not.
--
Trond Myklebust
Linux NFS client maintainer, Hammerspace
trondmy@kernel.org, trond.myklebust@hammerspace.com
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [RFC PATCH 00/11] NFS/NFSD: nfs4_acl passthru for NFSv4 reexport
2026-02-19 23:57 ` Trond Myklebust
@ 2026-02-20 15:33 ` Chuck Lever
0 siblings, 0 replies; 20+ messages in thread
From: Chuck Lever @ 2026-02-20 15:33 UTC (permalink / raw)
To: Trond Myklebust, Mike Snitzer, Jeff Layton, Anna Schumaker; +Cc: linux-nfs
On 2/19/26 6:57 PM, Trond Myklebust wrote:
> On Thu, 2026-02-19 at 17:21 -0500, Chuck Lever wrote:
>>
>> 2. Do you have a plan for similar passthru support for the NFSv4.2
>> POSIX
>> draft ACL extension?
>>
>
> Why would we need that?
>
> The current need for a passthrough mechanism is being driven by the
> fact that knfsd unconditionally imposes it's own lossy mapping onto the
> NFSv4 ACLs.
The opening paragraph of the cover letter states:
>> This patchset aims to enable NFS v4.1 ACLs to be fully supported from
>> an NFS v4.1 client to an NFSD v4.1 export that reexports NFS v4.2
>> filesystem which has full support for NFS v4.1 ACLs (DACL and SACL).
It wasn't clear to me on first read that "fully supported" was doing
some heavy lifting. So what you are really looking for is a mechanism
that bypasses NFSD's NFSv4 ACL <-> local POSIX ACL rewriting mechanism
only for NFS re-exports. Fair enough!
--
Chuck Lever
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [RFC PATCH 00/11] NFS/NFSD: nfs4_acl passthru for NFSv4 reexport
2026-02-19 23:07 ` Mike Snitzer
@ 2026-02-20 15:46 ` Chuck Lever
0 siblings, 0 replies; 20+ messages in thread
From: Chuck Lever @ 2026-02-20 15:46 UTC (permalink / raw)
To: Mike Snitzer; +Cc: Jeff Layton, Trond Myklebust, Anna Schumaker, linux-nfs
On 2/19/26 6:07 PM, Mike Snitzer wrote:
> On Thu, Feb 19, 2026 at 05:21:06PM -0500, Chuck Lever wrote:
>> 1. I haven't been a fan of these double-subsystem patch sets. Is there
>> any way we can get this split into one set for NFSD and one for the NFS
>> client, with as little code sharing between the two as possible? Maybe a
>> pipe dream, I know.
>
> Open to suggestions, but the reexport nature of this patchset makes it
> tough for each half to be entirely standalone.
>
> As is, patches 1 - 8 could all land via NFSD. But the code would be
> dormant because no filesystems would set EXPORT_OP_NFSV4_ACL_PASSTHRU.
>
> NFS _could_ just apply patch 3 (so it'd duplicate NFSD's commit for
> patch 3) and then apply NFS patches 9 - 11.
Aside from the added complications and compromises needed to manage a
merge for two independently maintained subsystems, the API boundary
between the two subsystems is already ragged and rather /ad hoc/.
The sharing of XDR definitions is going to get more complex as NFSD
transitions to the use of xdrgen.
As a general mission statement: I'm just hoping for a way to minimize
the effort to merge such cross-system work as well as lower the long-
term maintenance costs. But I guess none of that gives direct actionable
guidance, so I'll try to dig in and get to know the patch set first.
--
Chuck Lever
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [RFC PATCH 00/11] NFS/NFSD: nfs4_acl passthru for NFSv4 reexport
2026-02-19 22:13 [RFC PATCH 00/11] NFS/NFSD: nfs4_acl passthru for NFSv4 reexport Mike Snitzer
` (11 preceding siblings ...)
2026-02-19 22:21 ` [RFC PATCH 00/11] NFS/NFSD: nfs4_acl passthru for NFSv4 reexport Chuck Lever
@ 2026-02-22 17:53 ` Chuck Lever
2026-02-22 19:39 ` Mike Snitzer
12 siblings, 1 reply; 20+ messages in thread
From: Chuck Lever @ 2026-02-22 17:53 UTC (permalink / raw)
To: Mike Snitzer, Chuck Lever, Jeff Layton, Trond Myklebust,
Anna Schumaker
Cc: linux-nfs
On Thu, Feb 19, 2026, at 5:13 PM, Mike Snitzer wrote:
> Hi,
>
> This patchset aims to enable NFS v4.1 ACLs to be fully supported from
> an NFS v4.1 client to an NFSD v4.1 export that reexports NFS v4.2
> filesystem which has full support for NFS v4.1 ACLs (DACL and SACL).
>
> The first 6 patches focus on nfs4_acl passthru enablement (primarily
> for NFSD), patch 7 adds 4.1 nfs4_acl passthru support (DACL and SACL),
> patch 8 optimizes particular nfs4_acl passthru implementation in NFSD
> to skip memcpy if nfs4_acl passthru isn't needed, patches 9-11 offer
> the corresponding required NFSv4 client changes.
>
> This work is based on the NFS and NFSD code that has been merged
> during the 7.0 merge window.
Hey Mike, do you have a particular commit hash on which this series
applies? I've tried Torvalds master and nfsd-testing, and patch 3/11
fails to apply to either of them.
> This patchset is marked as RFC because I expect there will be
> suggestions for possible NFSD implementation improvements.
I think I understand the purpose of the series, and agree there is
an issue here. It doesn't look intractable to resolve.
Wondering, though, if plumbing .setacl and .getacl through the
export ops is the right way to go. These seem like inode ops to
me, not export ops. Shouldn't they work like an inode's existing
POSIX ACL ops?
Second, I see this in one of the patch descriptions: "This 4.1 DACL
and SACL support is confined to NFSD's NFS reexport case (e.g. when
NFSD 4.1 reexports NFS 4.2)." It made me wonder -- is re-exporting
NFSv4.2 on an NFSv4.1 mount the only configuration that we want NFSD
to support? I would think that any combination of NFSv4 minor
versions could be supported. And if only a few combinations can be
supported, the cover letter or Documentation/ should explain why.
But really, I expect any file system type might be able to implement
NFSv4 ACLs (eg, ZFS does, but it's out-of-tree). I would like to
think about this in terms of "native file system NFSv4 ACL support"
rather than "NFSD pass through". So, the NFS client's NFSv4 inodes
have it, and this series doesn't need to add it anywhere else for
now.
--
Chuck Lever
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [RFC PATCH 00/11] NFS/NFSD: nfs4_acl passthru for NFSv4 reexport
2026-02-22 17:53 ` Chuck Lever
@ 2026-02-22 19:39 ` Mike Snitzer
2026-02-22 20:31 ` Chuck Lever
0 siblings, 1 reply; 20+ messages in thread
From: Mike Snitzer @ 2026-02-22 19:39 UTC (permalink / raw)
To: Chuck Lever
Cc: Chuck Lever, Jeff Layton, Trond Myklebust, Anna Schumaker,
linux-nfs
On Sun, Feb 22, 2026 at 12:53:14PM -0500, Chuck Lever wrote:
>
>
> On Thu, Feb 19, 2026, at 5:13 PM, Mike Snitzer wrote:
> > Hi,
> >
> > This patchset aims to enable NFS v4.1 ACLs to be fully supported from
> > an NFS v4.1 client to an NFSD v4.1 export that reexports NFS v4.2
> > filesystem which has full support for NFS v4.1 ACLs (DACL and SACL).
> >
> > The first 6 patches focus on nfs4_acl passthru enablement (primarily
> > for NFSD), patch 7 adds 4.1 nfs4_acl passthru support (DACL and SACL),
> > patch 8 optimizes particular nfs4_acl passthru implementation in NFSD
> > to skip memcpy if nfs4_acl passthru isn't needed, patches 9-11 offer
> > the corresponding required NFSv4 client changes.
> >
> > This work is based on the NFS and NFSD code that has been merged
> > during the 7.0 merge window.
>
> Hey Mike, do you have a particular commit hash on which this series
> applies? I've tried Torvalds master and nfsd-testing, and patch 3/11
> fails to apply to either of them.
Sorry about that.
It's closest baseline is nfsd-7.0 (but my tree is a frankenbeast
starting at 6.12 sync'd all the way through to nfs-for-6.18-3 and
nfsd-7.0), see:
https://git.kernel.org/pub/scm/linux/kernel/git/snitzer/linux.git/log/?h=kernel-6.12.63/nfs4_acl-passthru
Given what you found, I'm missing some of your latest conflicting
changes. So it'll need a rebase.
> > This patchset is marked as RFC because I expect there will be
> > suggestions for possible NFSD implementation improvements.
>
> I think I understand the purpose of the series, and agree there is
> an issue here. It doesn't look intractable to resolve.
>
> Wondering, though, if plumbing .setacl and .getacl through the
> export ops is the right way to go. These seem like inode ops to
> me, not export ops. Shouldn't they work like an inode's existing
> POSIX ACL ops?
I didn't even consider this.
I'll have to take a closer look, but my intent was to convey that
these interfaces are tightly coupled to NFSD for passthru purposes.
Making them inode operations exposes the interface in a more generic
way right? Is it useful to do _now_? If/when there is a need then
they could be exposed as inode operations. How might doing that
expose the interfaces to usage that was never intended or needed?
Getting a bit into the weeds of design philosophy but I prefer to
expose interfaces that cater to their immediate use. Put differently:
I try not to game out hypotheticals too much. But I do welcome
suggestions like this that offer experienced vision for being mindful
of exposing interfaces that lend themselves to standing the test of
time (more so than my scalpel approach anyway).
Below you mention ZFS supports NFSv4 ACLs, how is that used? And does
its usage offer a glimpse of some further hypothetical that is
meaningful for Linux?
> Second, I see this in one of the patch descriptions: "This 4.1 DACL
> and SACL support is confined to NFSD's NFS reexport case (e.g. when
> NFSD 4.1 reexports NFS 4.2)." It made me wonder -- is re-exporting
> NFSv4.2 on an NFSv4.1 mount the only configuration that we want NFSD
> to support? I would think that any combination of NFSv4 minor
> versions could be supported. And if only a few combinations can be
> supported, the cover letter or Documentation/ should explain why.
My "(e.g. when NFSD 4.1 reexports NFS 4.2)" was only an example. The
code should work fine with any NFSv4 combination -- though obviously
4.0 won't understand nfs4 acl utils --dacl and --sacl flags.
> But really, I expect any file system type might be able to implement
> NFSv4 ACLs (eg, ZFS does, but it's out-of-tree). I would like to
> think about this in terms of "native file system NFSv4 ACL support"
> rather than "NFSD pass through". So, the NFS client's NFSv4 inodes
> have it, and this series doesn't need to add it anywhere else for
> now.
Sounds fine to frame it in those terms, but may cause make-work for
some future consumer that'll never actually materialize.
Relative to NFSD, its purely about passing through the nfs4_acl pages
that it got off the wire directly down to FS that has "native file
system NFSv4 ACL support".
Thanks,
Mike
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [RFC PATCH 00/11] NFS/NFSD: nfs4_acl passthru for NFSv4 reexport
2026-02-22 19:39 ` Mike Snitzer
@ 2026-02-22 20:31 ` Chuck Lever
0 siblings, 0 replies; 20+ messages in thread
From: Chuck Lever @ 2026-02-22 20:31 UTC (permalink / raw)
To: Mike Snitzer
Cc: Chuck Lever, Jeff Layton, Trond Myklebust, Anna Schumaker,
linux-nfs
On Sun, Feb 22, 2026, at 2:39 PM, Mike Snitzer wrote:
> On Sun, Feb 22, 2026 at 12:53:14PM -0500, Chuck Lever wrote:
>>
>>
>> On Thu, Feb 19, 2026, at 5:13 PM, Mike Snitzer wrote:
>> > Hi,
>> >
>> > This patchset aims to enable NFS v4.1 ACLs to be fully supported from
>> > an NFS v4.1 client to an NFSD v4.1 export that reexports NFS v4.2
>> > filesystem which has full support for NFS v4.1 ACLs (DACL and SACL).
>> >
>> > The first 6 patches focus on nfs4_acl passthru enablement (primarily
>> > for NFSD), patch 7 adds 4.1 nfs4_acl passthru support (DACL and SACL),
>> > patch 8 optimizes particular nfs4_acl passthru implementation in NFSD
>> > to skip memcpy if nfs4_acl passthru isn't needed, patches 9-11 offer
>> > the corresponding required NFSv4 client changes.
>> >
>> > This work is based on the NFS and NFSD code that has been merged
>> > during the 7.0 merge window.
>>
>> Hey Mike, do you have a particular commit hash on which this series
>> applies? I've tried Torvalds master and nfsd-testing, and patch 3/11
>> fails to apply to either of them.
>
> Sorry about that.
>
> It's closest baseline is nfsd-7.0 (but my tree is a frankenbeast
> starting at 6.12 sync'd all the way through to nfs-for-6.18-3 and
> nfsd-7.0), see:
> https://git.kernel.org/pub/scm/linux/kernel/git/snitzer/linux.git/log/?h=kernel-6.12.63/nfs4_acl-passthru
>
> Given what you found, I'm missing some of your latest conflicting
> changes. So it'll need a rebase.
Anything publicly available will work. Rebase, then just toss the
tag or commit hash in your next cover-letter.
--
Chuck Lever
^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2026-02-22 20:31 UTC | newest]
Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-19 22:13 [RFC PATCH 00/11] NFS/NFSD: nfs4_acl passthru for NFSv4 reexport Mike Snitzer
2026-02-19 22:13 ` [RFC PATCH 01/11] exportfs: add ability to advertise NFSv4 ACL passthru support Mike Snitzer
2026-02-19 22:13 ` [RFC PATCH 02/11] NFSD: factor out nfsd_supports_nfs4_acl() to nfsd/acl.h Mike Snitzer
2026-02-19 22:13 ` [RFC PATCH 03/11] NFS/NFSD: data structure enablement for nfs4_acl passthru support Mike Snitzer
2026-02-19 22:13 ` [RFC PATCH 04/11] NFSD: prepare to support SETACL nfs4_acl passthru Mike Snitzer
2026-02-19 22:13 ` [RFC PATCH 05/11] NFSD: add NFS4 reexport support for " Mike Snitzer
2026-02-19 22:13 ` [RFC PATCH 06/11] NFSD: add NFS4 reexport support for GETACL " Mike Snitzer
2026-02-19 22:13 ` [RFC PATCH 07/11] NFSD: add NFS4ACL_DACL and NFS4ACL_SACL passthru support Mike Snitzer
2026-02-19 22:13 ` [RFC PATCH 08/11] NFSD: avoid extra nfs4_acl passthru work unless needed Mike Snitzer
2026-02-19 22:13 ` [RFC PATCH 09/11] NFSv4: add reexport support for SETACL nfs4_acl passthru Mike Snitzer
2026-02-19 22:13 ` [RFC PATCH 10/11] NFSv4: add reexport support for GETACL " Mike Snitzer
2026-02-19 22:13 ` [RFC PATCH 11/11] NFSv4: set EXPORT_OP_NFSV4_ACL_PASSTHRU flag Mike Snitzer
2026-02-19 22:21 ` [RFC PATCH 00/11] NFS/NFSD: nfs4_acl passthru for NFSv4 reexport Chuck Lever
2026-02-19 23:07 ` Mike Snitzer
2026-02-20 15:46 ` Chuck Lever
2026-02-19 23:57 ` Trond Myklebust
2026-02-20 15:33 ` Chuck Lever
2026-02-22 17:53 ` Chuck Lever
2026-02-22 19:39 ` Mike Snitzer
2026-02-22 20:31 ` Chuck Lever
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox