reiserfs: rework priv inode handling
authorChristian Brauner <brauner@kernel.org>
Wed, 1 Feb 2023 13:14:59 +0000 (14:14 +0100)
committerChristian Brauner (Microsoft) <brauner@kernel.org>
Mon, 6 Mar 2023 08:57:13 +0000 (09:57 +0100)
Reiserfs is the only filesystem that removes IOP_XATTR without also
using a set of dedicated inode operations at the same time that nop all
xattr related inode operations. This means we need to have a IOP_XATTR
check in vfs_listxattr() instead of just being able to check for
->listxatt() being implemented.

Introduce a dedicated set of nop inode operations that are used when
IOP_XATTR is removed, allowing us to remove that check from
vfs_listxattr(). This in turn allows us to completely decouple POSIX ACLs from
IOP_XATTR.

Cc: reiserfs-devel@vger.kernel.org
Signed-off-by: Christian Brauner (Microsoft) <brauner@kernel.org>
fs/reiserfs/file.c
fs/reiserfs/inode.c
fs/reiserfs/namei.c
fs/reiserfs/reiserfs.h
fs/reiserfs/xattr.c

index 467d13d..b54cc70 100644 (file)
@@ -261,3 +261,10 @@ const struct inode_operations reiserfs_file_inode_operations = {
        .fileattr_get = reiserfs_fileattr_get,
        .fileattr_set = reiserfs_fileattr_set,
 };
+
+const struct inode_operations reiserfs_priv_file_inode_operations = {
+       .setattr = reiserfs_setattr,
+       .permission = reiserfs_permission,
+       .fileattr_get = reiserfs_fileattr_get,
+       .fileattr_set = reiserfs_fileattr_set,
+};
index d54cab8..d8debbb 100644 (file)
@@ -2087,10 +2087,8 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
         * Mark it private if we're creating the privroot
         * or something under it.
         */
-       if (IS_PRIVATE(dir) || dentry == REISERFS_SB(sb)->priv_root) {
-               inode->i_flags |= S_PRIVATE;
-               inode->i_opflags &= ~IOP_XATTR;
-       }
+       if (IS_PRIVATE(dir) || dentry == REISERFS_SB(sb)->priv_root)
+               reiserfs_init_priv_inode(inode);
 
        if (reiserfs_posixacl(inode->i_sb)) {
                reiserfs_write_unlock(inode->i_sb);
index 42d2c20..52240cc 100644 (file)
@@ -378,13 +378,11 @@ static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry,
 
                /*
                 * Propagate the private flag so we know we're
-                * in the priv tree.  Also clear IOP_XATTR
+                * in the priv tree.  Also clear xattr support
                 * since we don't have xattrs on xattr files.
                 */
-               if (IS_PRIVATE(dir)) {
-                       inode->i_flags |= S_PRIVATE;
-                       inode->i_opflags &= ~IOP_XATTR;
-               }
+               if (IS_PRIVATE(dir))
+                       reiserfs_init_priv_inode(inode);
        }
        reiserfs_write_unlock(dir->i_sb);
        if (retval == IO_ERROR) {
@@ -1649,6 +1647,48 @@ static int reiserfs_rename(struct mnt_idmap *idmap,
        return retval;
 }
 
+static const struct inode_operations reiserfs_priv_dir_inode_operations = {
+       .create = reiserfs_create,
+       .lookup = reiserfs_lookup,
+       .link = reiserfs_link,
+       .unlink = reiserfs_unlink,
+       .symlink = reiserfs_symlink,
+       .mkdir = reiserfs_mkdir,
+       .rmdir = reiserfs_rmdir,
+       .mknod = reiserfs_mknod,
+       .rename = reiserfs_rename,
+       .setattr = reiserfs_setattr,
+       .permission = reiserfs_permission,
+       .fileattr_get = reiserfs_fileattr_get,
+       .fileattr_set = reiserfs_fileattr_set,
+};
+
+static const struct inode_operations reiserfs_priv_symlink_inode_operations = {
+       .get_link       = page_get_link,
+       .setattr = reiserfs_setattr,
+       .permission = reiserfs_permission,
+};
+
+static const struct inode_operations reiserfs_priv_special_inode_operations = {
+       .setattr = reiserfs_setattr,
+       .permission = reiserfs_permission,
+};
+
+void reiserfs_init_priv_inode(struct inode *inode)
+{
+       inode->i_flags |= S_PRIVATE;
+       inode->i_opflags &= ~IOP_XATTR;
+
+       if (S_ISREG(inode->i_mode))
+               inode->i_op = &reiserfs_priv_file_inode_operations;
+       else if (S_ISDIR(inode->i_mode))
+               inode->i_op = &reiserfs_priv_dir_inode_operations;
+       else if (S_ISLNK(inode->i_mode))
+               inode->i_op = &reiserfs_priv_symlink_inode_operations;
+       else
+               inode->i_op = &reiserfs_priv_special_inode_operations;
+}
+
 /* directories can handle most operations...  */
 const struct inode_operations reiserfs_dir_inode_operations = {
        .create = reiserfs_create,
index 98e6f53..1bccf6a 100644 (file)
@@ -3106,6 +3106,7 @@ int reiserfs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
 int __reiserfs_write_begin(struct page *page, unsigned from, unsigned len);
 
 /* namei.c */
+void reiserfs_init_priv_inode(struct inode *inode);
 void set_de_name_and_namelen(struct reiserfs_dir_entry *de);
 int search_by_entry_key(struct super_block *sb, const struct cpu_key *key,
                        struct treepath *path, struct reiserfs_dir_entry *de);
@@ -3175,6 +3176,7 @@ void reiserfs_unmap_buffer(struct buffer_head *);
 
 /* file.c */
 extern const struct inode_operations reiserfs_file_inode_operations;
+extern const struct inode_operations reiserfs_priv_file_inode_operations;
 extern const struct file_operations reiserfs_file_operations;
 extern const struct address_space_operations reiserfs_address_space_operations;
 
index 354b74b..6510279 100644 (file)
@@ -896,8 +896,7 @@ static int create_privroot(struct dentry *dentry)
                return -EOPNOTSUPP;
        }
 
-       d_inode(dentry)->i_flags |= S_PRIVATE;
-       d_inode(dentry)->i_opflags &= ~IOP_XATTR;
+       reiserfs_init_priv_inode(d_inode(dentry));
        reiserfs_info(dentry->d_sb, "Created %s - reserved for xattr "
                      "storage.\n", PRIVROOT_NAME);
 
@@ -979,10 +978,8 @@ int reiserfs_lookup_privroot(struct super_block *s)
        if (!IS_ERR(dentry)) {
                REISERFS_SB(s)->priv_root = dentry;
                d_set_d_op(dentry, &xattr_lookup_poison_ops);
-               if (d_really_is_positive(dentry)) {
-                       d_inode(dentry)->i_flags |= S_PRIVATE;
-                       d_inode(dentry)->i_opflags &= ~IOP_XATTR;
-               }
+               if (d_really_is_positive(dentry))
+                       reiserfs_init_priv_inode(d_inode(dentry));
        } else
                err = PTR_ERR(dentry);
        inode_unlock(d_inode(s->s_root));