quota: port quota helpers mount ids
authorChristian Brauner <brauner@kernel.org>
Tue, 21 Jun 2022 14:14:52 +0000 (16:14 +0200)
committerChristian Brauner (Microsoft) <brauner@kernel.org>
Sun, 26 Jun 2022 16:18:55 +0000 (18:18 +0200)
Port the is_quota_modification() and dqout_transfer() helper to type
safe vfs{g,u}id_t. Since these helpers are only called by a few
filesystems don't introduce a new helper but simply extend the existing
helpers to pass down the mount's idmapping.

Note, that this is a non-functional change, i.e. nothing will have
happened here or at the end of this series to how quota are done! This
a change necessary because we will at the end of this series make
ownership changes easier to reason about by keeping the original value
in struct iattr for both non-idmapped and idmapped mounts.

For now we always pass the initial idmapping which makes the idmapping
functions these helpers call nops.

This is done because we currently always pass the actual value to be
written to i_{g,u}id via struct iattr. While this allowed us to treat
the {g,u}id values in struct iattr as values that can be directly
written to inode->i_{g,u}id it also increases the potential for
confusion for filesystems.

Now that we are have dedicated types to prevent this confusion we will
ultimately only map the value from the idmapped mount into a filesystem
value that can be written to inode->i_{g,u}id when the filesystem
actually updates the inode. So pass down the initial idmapping until we
finished that conversion at which point we pass down the mount's
idmapping.

Since struct iattr uses an anonymous union with overlapping types as
supported by the C standard, filesystems that haven't converted to
ia_vfs{g,u}id won't see any difference and things will continue to work
as before. In other words, no functional changes intended with this
change.

Link: https://lore.kernel.org/r/20220621141454.2914719-7-brauner@kernel.org
Cc: Seth Forshee <sforshee@digitalocean.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Jan Kara <jack@suse.cz>
Cc: Aleksa Sarai <cyphar@cyphar.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Al Viro <viro@zeniv.linux.org.uk>
CC: linux-fsdevel@vger.kernel.org
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Seth Forshee <sforshee@digitalocean.com>
Signed-off-by: Christian Brauner (Microsoft) <brauner@kernel.org>
fs/ext2/inode.c
fs/ext4/inode.c
fs/f2fs/file.c
fs/f2fs/recovery.c
fs/jfs/file.c
fs/ocfs2/file.c
fs/quota/dquot.c
fs/reiserfs/inode.c
fs/zonefs/super.c
include/linux/quotaops.h

index 6dc66ab97d20042a395acfb71d51a651a9ca0873..593b79416e0eefa66e9c2f2d85d07680aa45e59a 100644 (file)
@@ -1679,14 +1679,14 @@ int ext2_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
        if (error)
                return error;
 
-       if (is_quota_modification(inode, iattr)) {
+       if (is_quota_modification(&init_user_ns, inode, iattr)) {
                error = dquot_initialize(inode);
                if (error)
                        return error;
        }
        if (i_uid_needs_update(&init_user_ns, iattr, inode) ||
            i_gid_needs_update(&init_user_ns, iattr, inode)) {
-               error = dquot_transfer(inode, iattr);
+               error = dquot_transfer(&init_user_ns, inode, iattr);
                if (error)
                        return error;
        }
index 05d932f81c5365ba92870a9a9faba7a6e4a5ab86..72f08c184768c38808ce54844a75848271314fb8 100644 (file)
@@ -5350,7 +5350,7 @@ int ext4_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
        if (error)
                return error;
 
-       if (is_quota_modification(inode, attr)) {
+       if (is_quota_modification(&init_user_ns, inode, attr)) {
                error = dquot_initialize(inode);
                if (error)
                        return error;
@@ -5374,7 +5374,7 @@ int ext4_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
                 * counts xattr inode references.
                 */
                down_read(&EXT4_I(inode)->xattr_sem);
-               error = dquot_transfer(inode, attr);
+               error = dquot_transfer(&init_user_ns, inode, attr);
                up_read(&EXT4_I(inode)->xattr_sem);
 
                if (error) {
index a35d6b12bd636c1cf38f6466acaa898d4550ed3b..02b2d56d4edc7b4fb6ec188491766fe1b499c791 100644 (file)
@@ -915,7 +915,7 @@ int f2fs_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
        if (err)
                return err;
 
-       if (is_quota_modification(inode, attr)) {
+       if (is_quota_modification(&init_user_ns, inode, attr)) {
                err = f2fs_dquot_initialize(inode);
                if (err)
                        return err;
@@ -923,7 +923,7 @@ int f2fs_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
        if (i_uid_needs_update(&init_user_ns, attr, inode) ||
            i_gid_needs_update(&init_user_ns, attr, inode)) {
                f2fs_lock_op(F2FS_I_SB(inode));
-               err = dquot_transfer(inode, attr);
+               err = dquot_transfer(&init_user_ns, inode, attr);
                if (err) {
                        set_sbi_flag(F2FS_I_SB(inode),
                                        SBI_QUOTA_NEED_REPAIR);
index 3cb7f8a43b4d7e11c1248e39728a359c54e3f2d6..8e5a089f1ac88c855447320572d89ab8634a6dfa 100644 (file)
@@ -266,7 +266,7 @@ static int recover_quota_data(struct inode *inode, struct page *page)
        if (!attr.ia_valid)
                return 0;
 
-       err = dquot_transfer(inode, &attr);
+       err = dquot_transfer(&init_user_ns, inode, &attr);
        if (err)
                set_sbi_flag(F2FS_I_SB(inode), SBI_QUOTA_NEED_REPAIR);
        return err;
index 1d732fd223d4a900a280f3615a5f6e600bf5b8f0..c18569b9895d33179595d533d1e0005ff7d9c9c4 100644 (file)
@@ -95,14 +95,14 @@ int jfs_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
        if (rc)
                return rc;
 
-       if (is_quota_modification(inode, iattr)) {
+       if (is_quota_modification(&init_user_ns, inode, iattr)) {
                rc = dquot_initialize(inode);
                if (rc)
                        return rc;
        }
        if ((iattr->ia_valid & ATTR_UID && !uid_eq(iattr->ia_uid, inode->i_uid)) ||
            (iattr->ia_valid & ATTR_GID && !gid_eq(iattr->ia_gid, inode->i_gid))) {
-               rc = dquot_transfer(inode, iattr);
+               rc = dquot_transfer(&init_user_ns, inode, iattr);
                if (rc)
                        return rc;
        }
index 7497cd59225861d4521df92e83b25277e02b09e3..0e09cd8911da409ca330a85d6b9781f05d6fa81e 100644 (file)
@@ -1146,7 +1146,7 @@ int ocfs2_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
        if (status)
                return status;
 
-       if (is_quota_modification(inode, attr)) {
+       if (is_quota_modification(&init_user_ns, inode, attr)) {
                status = dquot_initialize(inode);
                if (status)
                        return status;
index 6cec2bfbf51b2d2e78034a1ff478c07a6f81b6d8..df9af1ce2851d051f50e59a0aa74302f6e07d659 100644 (file)
@@ -2085,7 +2085,8 @@ EXPORT_SYMBOL(__dquot_transfer);
 /* Wrapper for transferring ownership of an inode for uid/gid only
  * Called from FSXXX_setattr()
  */
-int dquot_transfer(struct inode *inode, struct iattr *iattr)
+int dquot_transfer(struct user_namespace *mnt_userns, struct inode *inode,
+                  struct iattr *iattr)
 {
        struct dquot *transfer_to[MAXQUOTAS] = {};
        struct dquot *dquot;
index 0cffe054b78e16f5a23bb7ada98eb73c518874cb..1e89e76972a042b138524900675e34ff36124b60 100644 (file)
@@ -3284,7 +3284,7 @@ int reiserfs_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
        /* must be turned off for recursive notify_change calls */
        ia_valid = attr->ia_valid &= ~(ATTR_KILL_SUID|ATTR_KILL_SGID);
 
-       if (is_quota_modification(inode, attr)) {
+       if (is_quota_modification(&init_user_ns, inode, attr)) {
                error = dquot_initialize(inode);
                if (error)
                        return error;
@@ -3367,7 +3367,7 @@ int reiserfs_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
                reiserfs_write_unlock(inode->i_sb);
                if (error)
                        goto out;
-               error = dquot_transfer(inode, attr);
+               error = dquot_transfer(&init_user_ns, inode, attr);
                reiserfs_write_lock(inode->i_sb);
                if (error) {
                        journal_end(&th);
index 053299758deb98abfe8a2154dd14fb6e32646a07..dd422b1d73201144c7764fef0dc7c7ed184f8646 100644 (file)
@@ -616,7 +616,7 @@ static int zonefs_inode_setattr(struct user_namespace *mnt_userns,
             !uid_eq(iattr->ia_uid, inode->i_uid)) ||
            ((iattr->ia_valid & ATTR_GID) &&
             !gid_eq(iattr->ia_gid, inode->i_gid))) {
-               ret = dquot_transfer(inode, iattr);
+               ret = dquot_transfer(&init_user_ns, inode, iattr);
                if (ret)
                        return ret;
        }
index 61ee34861ca2a4c97d5f67e0ba74a80bd3cd477a..0342ff6584fddfbc234df3f5cef6b8b50b9e4ab7 100644 (file)
@@ -20,7 +20,8 @@ static inline struct quota_info *sb_dqopt(struct super_block *sb)
 }
 
 /* i_mutex must being held */
-static inline bool is_quota_modification(struct inode *inode, struct iattr *ia)
+static inline bool is_quota_modification(struct user_namespace *mnt_userns,
+                                        struct inode *inode, struct iattr *ia)
 {
        return ((ia->ia_valid & ATTR_SIZE) ||
                i_uid_needs_update(&init_user_ns, ia, inode) ||
@@ -115,7 +116,8 @@ int dquot_set_dqblk(struct super_block *sb, struct kqid id,
                struct qc_dqblk *di);
 
 int __dquot_transfer(struct inode *inode, struct dquot **transfer_to);
-int dquot_transfer(struct inode *inode, struct iattr *iattr);
+int dquot_transfer(struct user_namespace *mnt_userns, struct inode *inode,
+                  struct iattr *iattr);
 
 static inline struct mem_dqinfo *sb_dqinfo(struct super_block *sb, int type)
 {
@@ -234,7 +236,8 @@ static inline void dquot_free_inode(struct inode *inode)
 {
 }
 
-static inline int dquot_transfer(struct inode *inode, struct iattr *iattr)
+static inline int dquot_transfer(struct user_namespace *mnt_userns,
+                                struct inode *inode, struct iattr *iattr)
 {
        return 0;
 }