2023-02-01 13:15:42

by Christian Brauner

[permalink] [raw]
Subject: [PATCH v3 00/10] acl: drop posix acl handlers from xattr handlers

Hey everyone,

After we finished the introduction of the new posix acl api last cycle
we still left the generic POSIX ACL xattr handlers around in the
filesystems xattr handlers for two reasons:

(1) Because a few filesystems rely on the ->list() method of the generic
POSIX ACL xattr handlers in their ->listxattr() inode operation.
(2) POSIX ACLs are only available if IOP_XATTR is raised. The IOP_XATTR
flag is raised in inode_init_always() based on whether the
sb->s_xattr pointer is non-NULL. IOW, the registered xattr handlers
of the filesystem are used to raise IOP_XATTR.
If we were to remove the generic POSIX ACL xattr handlers from all
filesystems we would risk regressing filesystems that only implement
POSIX ACL support and no other xattrs (nfs3 comes to mind).

This series makes it possible to remove the generic POSIX ACL xattr
handlers from the sb->s_xattr list of all filesystems. This is a crucial
step as the generic POSIX ACL xattr handlers aren't used for POSIX ACLs
anymore and POSIX ACLs don't depend on the xattr infrastructure in a
meaningful way anymore.

Adressing problem (1) will require more work long-term. It would be best
to get rid of the ->list() method of xattr handlers completely if we
can.

For erofs, ext{2,4}, f2fs, jffs2, ocfs2, and reiserfs we keep the dummy
handler around so they can continue to use array-based xattr handler
indexing. The series does simplify the ->listxattr() implementation of
all these filesystems.

This series decouples POSIX ACLs from IOP_XATTR as they don't depend on
xattr handlers anymore. With this we can finally remove the dummy xattr
handlers from all filesystems xattr handlers.

All filesystems with reasonable integration into xfstests have been
tested with:

./check -g acl,attr,cap,idmapped,io_uring,perms,unlink

All tests pass without regression on xfstests for-next branch.

Since erofs doesn't have integration into xfstests yet afaict I have
tested it with the testuite available in erofs-utils. They also all pass
without any regressions.

Thanks!
Christian

Signed-off-by: Christian Brauner (Microsoft) <[email protected]>
---
Changes in v3:
- Decouple POSIX ACLs from IOP_XATTR.
- Allow vfs_listxattr() to function without checking for IOP_XATTR
making it possible to list POSIX ACLs for filesystems that only
implement POSIX ACLs and no other xattrs.
- Give reiserfs a set of dedicated inode operation for private inodes
that have turned of xattrs completely.
- Link to v2: https://lore.kernel.org/r/20230125-fs-acl-remove-generic-xattr-handlers-v2-0-214cfb88bb56@kernel.org

Changes in v2:
- Please see changelogs of the individual patches.
- Christoph & Christian:
Remove SB_I_XATTR and instead introduce IOP_NOACL so filesystems can
opt out of POSIX ACLs for specific inodes. Decouple POSIX ACLs from
IOP_XATTR.
- Keep generic posix acl xattr handlers so filesystems that use array
based indexing on xattr handlers can continue to do so.
- Minor fixes.
- Link to v1: https://lore.kernel.org/r/20230125-fs-acl-remove-generic-xattr-handlers-v1-0-6cf155b492b6@kernel.org

---
Christian Brauner (10):
xattr: simplify listxattr helpers
xattr: add listxattr helper
xattr: remove unused argument
fs: drop unused posix acl handlers
fs: simplify ->listxattr() implementation
reiserfs: rework ->listxattr() implementation
fs: rename generic posix acl handlers
reiserfs: rework priv inode handling
ovl: check for ->listxattr() support
acl: don't depend on IOP_XATTR

fs/9p/xattr.c | 4 --
fs/btrfs/xattr.c | 4 --
fs/ceph/xattr.c | 4 --
fs/cifs/xattr.c | 4 --
fs/ecryptfs/inode.c | 4 --
fs/erofs/xattr.c | 12 +---
fs/erofs/xattr.h | 20 ++++---
fs/ext2/xattr.c | 25 ++++----
fs/ext4/xattr.c | 25 ++++----
fs/f2fs/xattr.c | 24 ++++----
fs/gfs2/xattr.c | 2 -
fs/jffs2/xattr.c | 29 +++++-----
fs/jfs/xattr.c | 4 --
fs/nfs/nfs3_fs.h | 1 -
fs/nfs/nfs3acl.c | 6 --
fs/nfs/nfs3super.c | 3 -
fs/nfsd/nfs4xdr.c | 3 +-
fs/ntfs3/xattr.c | 4 --
fs/ocfs2/xattr.c | 14 ++---
fs/orangefs/xattr.c | 2 -
fs/overlayfs/copy_up.c | 3 +-
fs/overlayfs/super.c | 8 ---
fs/posix_acl.c | 61 +++++++++++++++-----
fs/reiserfs/file.c | 7 +++
fs/reiserfs/inode.c | 6 +-
fs/reiserfs/namei.c | 50 ++++++++++++++--
fs/reiserfs/reiserfs.h | 2 +
fs/reiserfs/xattr.c | 55 +++++++++---------
fs/xattr.c | 124 ++++++++++++++++++++--------------------
fs/xfs/xfs_xattr.c | 4 --
include/linux/posix_acl.h | 7 +++
include/linux/posix_acl_xattr.h | 5 +-
include/linux/xattr.h | 19 +++++-
mm/shmem.c | 4 --
34 files changed, 292 insertions(+), 257 deletions(-)
---
base-commit: ab072681eabe1ce0a9a32d4baa1a27a2d046bc4a
change-id: 20230125-fs-acl-remove-generic-xattr-handlers-4cfed8558d88



2023-02-01 13:16:14

by Christian Brauner

[permalink] [raw]
Subject: [PATCH v3 05/10] fs: simplify ->listxattr() implementation

The ext{2,4}, erofs, f2fs, and jffs2 filesystems use the same logic to
check whether a given xattr can be listed. Simplify them and avoid
open-coding the same check by calling the helper we introduced earlier.

Reviewed-by: Christoph Hellwig <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Signed-off-by: Christian Brauner (Microsoft) <[email protected]>
---
Changes in v3:
- Patch unchanged.

Changes in v2:
- Christoph Hellwig <[email protected]>:
- Rework this patch completey by keeping the legacy generic POSIX ACL
handlers around so that array-based handler indexing still works.
This means way less churn for filesystems.
---
fs/erofs/xattr.c | 8 ++------
fs/erofs/xattr.h | 14 +++++++++++---
fs/ext2/xattr.c | 17 ++++++++++-------
fs/ext4/xattr.c | 17 ++++++++++-------
fs/f2fs/xattr.c | 16 ++++++++++------
fs/jffs2/xattr.c | 21 ++++++++++++---------
6 files changed, 55 insertions(+), 38 deletions(-)

diff --git a/fs/erofs/xattr.c b/fs/erofs/xattr.c
index 2c98a15a92ed..4b73be57c9f4 100644
--- a/fs/erofs/xattr.c
+++ b/fs/erofs/xattr.c
@@ -492,13 +492,9 @@ static int xattr_entrylist(struct xattr_iter *_it,
unsigned int prefix_len;
const char *prefix;

- const struct xattr_handler *h =
- erofs_xattr_handler(entry->e_name_index);
-
- if (!h || (h->list && !h->list(it->dentry)))
+ prefix = erofs_xattr_prefix(entry->e_name_index, it->dentry);
+ if (!prefix)
return 1;
-
- prefix = xattr_prefix(h);
prefix_len = strlen(prefix);

if (!it->buffer) {
diff --git a/fs/erofs/xattr.h b/fs/erofs/xattr.h
index 0a43c9ee9f8f..08658e414c33 100644
--- a/fs/erofs/xattr.h
+++ b/fs/erofs/xattr.h
@@ -41,8 +41,11 @@ extern const struct xattr_handler erofs_xattr_user_handler;
extern const struct xattr_handler erofs_xattr_trusted_handler;
extern const struct xattr_handler erofs_xattr_security_handler;

-static inline const struct xattr_handler *erofs_xattr_handler(unsigned int idx)
+static inline const char *erofs_xattr_prefix(unsigned int idx,
+ struct dentry *dentry)
{
+ const struct xattr_handler *handler = NULL;
+
static const struct xattr_handler *xattr_handler_map[] = {
[EROFS_XATTR_INDEX_USER] = &erofs_xattr_user_handler,
#ifdef CONFIG_EROFS_FS_POSIX_ACL
@@ -57,8 +60,13 @@ static inline const struct xattr_handler *erofs_xattr_handler(unsigned int idx)
#endif
};

- return idx && idx < ARRAY_SIZE(xattr_handler_map) ?
- xattr_handler_map[idx] : NULL;
+ if (idx && idx < ARRAY_SIZE(xattr_handler_map))
+ handler = xattr_handler_map[idx];
+
+ if (!xattr_handler_can_list(handler, dentry))
+ return NULL;
+
+ return xattr_prefix(handler);
}

extern const struct xattr_handler *erofs_xattr_handlers[];
diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c
index 262951ffe8d0..958976f809f5 100644
--- a/fs/ext2/xattr.c
+++ b/fs/ext2/xattr.c
@@ -121,14 +121,18 @@ const struct xattr_handler *ext2_xattr_handlers[] = {

#define EA_BLOCK_CACHE(inode) (EXT2_SB(inode->i_sb)->s_ea_block_cache)

-static inline const struct xattr_handler *
-ext2_xattr_handler(int name_index)
+static inline const char *ext2_xattr_prefix(int name_index,
+ struct dentry *dentry)
{
const struct xattr_handler *handler = NULL;

if (name_index > 0 && name_index < ARRAY_SIZE(ext2_xattr_handler_map))
handler = ext2_xattr_handler_map[name_index];
- return handler;
+
+ if (!xattr_handler_can_list(handler, dentry))
+ return NULL;
+
+ return xattr_prefix(handler);
}

static bool
@@ -329,11 +333,10 @@ ext2_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
/* list the attribute names */
for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
entry = EXT2_XATTR_NEXT(entry)) {
- const struct xattr_handler *handler =
- ext2_xattr_handler(entry->e_name_index);
+ const char *prefix;

- if (handler && (!handler->list || handler->list(dentry))) {
- const char *prefix = handler->prefix ?: handler->name;
+ prefix = ext2_xattr_prefix(entry->e_name_index, dentry);
+ if (prefix) {
size_t prefix_len = strlen(prefix);
size_t size = prefix_len + entry->e_name_len + 1;

diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index ba7f2557adb8..3fbeeb00fd78 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -169,14 +169,18 @@ static void ext4_xattr_block_csum_set(struct inode *inode,
bh->b_blocknr, BHDR(bh));
}

-static inline const struct xattr_handler *
-ext4_xattr_handler(int name_index)
+static inline const char *ext4_xattr_prefix(int name_index,
+ struct dentry *dentry)
{
const struct xattr_handler *handler = NULL;

if (name_index > 0 && name_index < ARRAY_SIZE(ext4_xattr_handler_map))
handler = ext4_xattr_handler_map[name_index];
- return handler;
+
+ if (!xattr_handler_can_list(handler, dentry))
+ return NULL;
+
+ return xattr_prefix(handler);
}

static int
@@ -691,11 +695,10 @@ ext4_xattr_list_entries(struct dentry *dentry, struct ext4_xattr_entry *entry,
size_t rest = buffer_size;

for (; !IS_LAST_ENTRY(entry); entry = EXT4_XATTR_NEXT(entry)) {
- const struct xattr_handler *handler =
- ext4_xattr_handler(entry->e_name_index);
+ const char *prefix;

- if (handler && (!handler->list || handler->list(dentry))) {
- const char *prefix = handler->prefix ?: handler->name;
+ prefix = ext4_xattr_prefix(entry->e_name_index, dentry);
+ if (prefix) {
size_t prefix_len = strlen(prefix);
size_t size = prefix_len + entry->e_name_len + 1;

diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c
index ccb564e328af..9de984645253 100644
--- a/fs/f2fs/xattr.c
+++ b/fs/f2fs/xattr.c
@@ -212,13 +212,18 @@ const struct xattr_handler *f2fs_xattr_handlers[] = {
NULL,
};

-static inline const struct xattr_handler *f2fs_xattr_handler(int index)
+static inline const char *f2fs_xattr_prefix(int index,
+ struct dentry *dentry)
{
const struct xattr_handler *handler = NULL;

if (index > 0 && index < ARRAY_SIZE(f2fs_xattr_handler_map))
handler = f2fs_xattr_handler_map[index];
- return handler;
+
+ if (!xattr_handler_can_list(handler, dentry))
+ return NULL;
+
+ return xattr_prefix(handler);
}

static struct f2fs_xattr_entry *__find_xattr(void *base_addr,
@@ -569,12 +574,12 @@ ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
last_base_addr = (void *)base_addr + XATTR_SIZE(inode);

list_for_each_xattr(entry, base_addr) {
- const struct xattr_handler *handler =
- f2fs_xattr_handler(entry->e_name_index);
const char *prefix;
size_t prefix_len;
size_t size;

+ prefix = f2fs_xattr_prefix(entry->e_name_index, dentry);
+
if ((void *)(entry) + sizeof(__u32) > last_base_addr ||
(void *)XATTR_NEXT_ENTRY(entry) > last_base_addr) {
f2fs_err(F2FS_I_SB(inode), "inode (%lu) has corrupted xattr",
@@ -586,10 +591,9 @@ ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
goto cleanup;
}

- if (!handler || (handler->list && !handler->list(dentry)))
+ if (!prefix)
continue;

- prefix = xattr_prefix(handler);
prefix_len = strlen(prefix);
size = prefix_len + entry->e_name_len + 1;
if (buffer) {
diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c
index 0eaec4a0f3b1..1189a70d2007 100644
--- a/fs/jffs2/xattr.c
+++ b/fs/jffs2/xattr.c
@@ -924,8 +924,9 @@ const struct xattr_handler *jffs2_xattr_handlers[] = {
NULL
};

-static const struct xattr_handler *xprefix_to_handler(int xprefix) {
- const struct xattr_handler *ret;
+static const char *jffs2_xattr_prefix(int xprefix, struct dentry *dentry)
+{
+ const struct xattr_handler *ret = NULL;

switch (xprefix) {
case JFFS2_XPREFIX_USER:
@@ -948,10 +949,13 @@ static const struct xattr_handler *xprefix_to_handler(int xprefix) {
ret = &jffs2_trusted_xattr_handler;
break;
default:
- ret = NULL;
- break;
+ return NULL;
}
- return ret;
+
+ if (!xattr_handler_can_list(ret, dentry))
+ return NULL;
+
+ return xattr_prefix(ret);
}

ssize_t jffs2_listxattr(struct dentry *dentry, char *buffer, size_t size)
@@ -962,7 +966,6 @@ ssize_t jffs2_listxattr(struct dentry *dentry, char *buffer, size_t size)
struct jffs2_inode_cache *ic = f->inocache;
struct jffs2_xattr_ref *ref, **pref;
struct jffs2_xattr_datum *xd;
- const struct xattr_handler *xhandle;
const char *prefix;
ssize_t prefix_len, len, rc;
int retry = 0;
@@ -994,10 +997,10 @@ ssize_t jffs2_listxattr(struct dentry *dentry, char *buffer, size_t size)
goto out;
}
}
- xhandle = xprefix_to_handler(xd->xprefix);
- if (!xhandle || (xhandle->list && !xhandle->list(dentry)))
+
+ prefix = jffs2_xattr_prefix(xd->xprefix, dentry);
+ if (!prefix)
continue;
- prefix = xhandle->prefix ?: xhandle->name;
prefix_len = strlen(prefix);
rc = prefix_len + xd->name_len + 1;


--
2.34.1


2023-02-01 13:31:37

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH v3 00/10] acl: drop posix acl handlers from xattr handlers

This version looks good to me, but I'd really prefer if a reiserfs
insider could look over the reiserfs patches.

2023-02-01 13:43:06

by Christian Brauner

[permalink] [raw]
Subject: Re: [PATCH v3 00/10] acl: drop posix acl handlers from xattr handlers

On Wed, Feb 01, 2023 at 02:30:20PM +0100, Christoph Hellwig wrote:
> This version looks good to me, but I'd really prefer if a reiserfs
> insider could look over the reiserfs patches.

I consider this material for v6.4 even with an -rc8 for v6.3. So there's
time but we shouldn't block it on reiserfs. Especially, since it's
marked deprecated.

Fwiw, I've tested reiserfs with xfstests on a kernel with and without
this series applied and there's no regressions. But it's overall pretty
buggy at least according to xfstests. Which is expected, I guess.

2023-03-06 09:23:56

by Christian Brauner

[permalink] [raw]
Subject: Re: [PATCH v3 00/10] acl: drop posix acl handlers from xattr handlers

From: Christian Brauner (Microsoft) <[email protected]>


On Wed, 01 Feb 2023 14:14:51 +0100, Christian Brauner wrote:
> Hey everyone,
>
> After we finished the introduction of the new posix acl api last cycle
> we still left the generic POSIX ACL xattr handlers around in the
> filesystems xattr handlers for two reasons:
>
> (1) Because a few filesystems rely on the ->list() method of the generic
> POSIX ACL xattr handlers in their ->listxattr() inode operation.
> (2) POSIX ACLs are only available if IOP_XATTR is raised. The IOP_XATTR
> flag is raised in inode_init_always() based on whether the
> sb->s_xattr pointer is non-NULL. IOW, the registered xattr handlers
> of the filesystem are used to raise IOP_XATTR.
> If we were to remove the generic POSIX ACL xattr handlers from all
> filesystems we would risk regressing filesystems that only implement
> POSIX ACL support and no other xattrs (nfs3 comes to mind).
>
> [...]

With v6.3-rc1 out, I've applied this now. Please keep an eye out for any
regressions as this has been a delicate undertaking:

[01/10] xattr: simplify listxattr helpers
commit: f2620f166e2a4db08f016b7b30b904ab28c265e4
[02/10] xattr: add listxattr helper
commit: 2db8a948046cab3a2f707561592906a3d096972f
[03/10] xattr: remove unused argument
commit: 831be973aa21d1cf8948bf4b1d4e73e6d5d028c0
[04/10] fs: drop unused posix acl handlers
commit: 0c95c025a02e477b2d112350e1c78bb0cc994c51
[05/10] fs: simplify ->listxattr() implementation
commit: a5488f29835c0eb5561b46e71c23f6c39aab6c83
[06/10] reiserfs: rework ->listxattr() implementation
commit: 387b96a5891c075986afbf13e84cba357710068e
[07/10] fs: rename generic posix acl handlers
commit: d549b741740e63e87e661754e2d1b336fdc51d50
[08/10] reiserfs: rework priv inode handling
commit: d9f892b9bdc22b12bc960837a09f014d5a324975
[09/10] ovl: check for ->listxattr() support
commit: a1fbb607340d49f208e90cc0d7bdfff2141cce8d
[10/10] acl: don't depend on IOP_XATTR
commit: e499214ce3ef50c50522719e753a1ffc928c2ec1

Christian

2023-03-06 09:26:46

by Christian Brauner

[permalink] [raw]
Subject: Re: [PATCH v3 00/10] acl: drop posix acl handlers from xattr handlers

On Wed, Feb 01, 2023 at 02:42:54PM +0100, Christian Brauner wrote:
> On Wed, Feb 01, 2023 at 02:30:20PM +0100, Christoph Hellwig wrote:
> > This version looks good to me, but I'd really prefer if a reiserfs
> > insider could look over the reiserfs patches.
>
> I consider this material for v6.4 even with an -rc8 for v6.3. So there's
> time but we shouldn't block it on reiserfs. Especially, since it's
> marked deprecated.

So I've applied this now. If there's still someone interested in
checking the reiserfs bits more than what we did with xfstests they
should please do so. But I don't want to hold up this series waiting for
that to happen.

>
> Fwiw, I've tested reiserfs with xfstests on a kernel with and without
> this series applied and there's no regressions. But it's overall pretty
> buggy at least according to xfstests. Which is expected, I guess.

2023-04-26 23:08:59

by patchwork-bot+f2fs

[permalink] [raw]
Subject: Re: [f2fs-dev] [PATCH v3 00/10] acl: drop posix acl handlers from xattr handlers

Hello:

This patch was applied to jaegeuk/f2fs.git (dev)
by Christian Brauner (Microsoft) <[email protected]>:

On Wed, 01 Feb 2023 14:14:51 +0100 you wrote:
> Hey everyone,
>
> After we finished the introduction of the new posix acl api last cycle
> we still left the generic POSIX ACL xattr handlers around in the
> filesystems xattr handlers for two reasons:
>
> (1) Because a few filesystems rely on the ->list() method of the generic
> POSIX ACL xattr handlers in their ->listxattr() inode operation.
> (2) POSIX ACLs are only available if IOP_XATTR is raised. The IOP_XATTR
> flag is raised in inode_init_always() based on whether the
> sb->s_xattr pointer is non-NULL. IOW, the registered xattr handlers
> of the filesystem are used to raise IOP_XATTR.
> If we were to remove the generic POSIX ACL xattr handlers from all
> filesystems we would risk regressing filesystems that only implement
> POSIX ACL support and no other xattrs (nfs3 comes to mind).
>
> [...]

Here is the summary with links:
- [f2fs-dev,v3,05/10] fs: simplify ->listxattr() implementation
https://git.kernel.org/jaegeuk/f2fs/c/a5488f29835c

You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html