]> www.infradead.org Git - users/hch/xfsprogs.git/commitdiff
libxfs: backport inode init code from the kernel
authorDarrick J. Wong <djwong@kernel.org>
Tue, 9 Jan 2024 17:39:36 +0000 (09:39 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Wed, 10 Apr 2024 00:21:33 +0000 (17:21 -0700)
Reorganize the userspace inode initialization code to more closely resemble
its kernel counterpart.  This is preparation to hoist the initialization
routines to libxfs.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
include/xfs_inode.h
include/xfs_mount.h
libxfs/inode.c
libxfs/libxfs_priv.h

index 8173f0968fc27c881ed4aa578e938c5dbae4e38f..45df652b088486a2cd1274adf14a007392d83b4f 100644 (file)
@@ -403,4 +403,6 @@ extern void libxfs_irele(struct xfs_inode *ip);
 
 #define XFS_DEFAULT_COWEXTSZ_HINT 32
 
+#define XFS_INHERIT_GID(pip)           (VFS_I(pip)->i_mode & S_ISGID)
+
 #endif /* __XFS_INODE_H__ */
index a9525e4e054601e398f1fbee299bf22bf321981e..6e4b13b79152df2342d70511a766d6530ad81757 100644 (file)
@@ -228,6 +228,7 @@ __XFS_UNSUPP_FEAT(ikeep)
 __XFS_UNSUPP_FEAT(swalloc)
 __XFS_UNSUPP_FEAT(small_inums)
 __XFS_UNSUPP_FEAT(readonly)
+__XFS_UNSUPP_FEAT(grpid)
 
 /* Operational mount state flags */
 #define XFS_OPSTATE_INODE32            0       /* inode32 allocator active */
index 3af859a413154390f4b5fc902fccbe5d1cad8e15..4b5e472237d0578cf755cee81665139d604926a0 100644 (file)
@@ -31,7 +31,7 @@
 
 /* Propagate di_flags from a parent inode to a child inode. */
 static void
-xfs_inode_propagate_flags(
+xfs_inode_inherit_flags(
        struct xfs_inode        *ip,
        const struct xfs_inode  *pip)
 {
@@ -99,31 +99,47 @@ xfs_inode_init(
        struct xfs_inode        *ip)
 {
        struct xfs_inode        *pip = args->pip;
+       struct inode            *dir = pip ? VFS_I(pip) : NULL;
+       struct xfs_mount        *mp = tp->t_mountp;
+       struct inode            *inode = VFS_I(ip);
        unsigned int            flags;
        int                     times = XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG |
                                        XFS_ICHGTIME_ACCESS;
 
-       VFS_I(ip)->i_mode = args->mode;
-       set_nlink(VFS_I(ip), args->nlink);
-       VFS_I(ip)->i_uid = args->uid;
+       set_nlink(inode, args->nlink);
+       inode->i_rdev = args->rdev;
        ip->i_projid = args->prid;
 
-       if (pip && (VFS_I(pip)->i_mode & S_ISGID)) {
-               if (!(args->flags & XFS_ICREATE_ARGS_FORCE_GID))
-                       VFS_I(ip)->i_gid = VFS_I(pip)->i_gid;
-               if ((VFS_I(pip)->i_mode & S_ISGID) && S_ISDIR(args->mode))
-                       VFS_I(ip)->i_mode |= S_ISGID;
-       } else
-               VFS_I(ip)->i_gid = args->gid;
+       if (dir && !(dir->i_mode & S_ISGID) &&
+           xfs_has_grpid(mp)) {
+               inode->i_uid = args->uid;
+               inode->i_gid = dir->i_gid;
+               inode->i_mode = args->mode;
+       } else {
+               inode_init_owner(args->idmap, inode, dir, args->mode);
+       }
+
+       /* struct copies */
+       if (args->flags & XFS_ICREATE_ARGS_FORCE_UID)
+               inode->i_uid = args->uid;
+       else
+               ASSERT(uid_eq(inode->i_uid, args->uid));
+       if (args->flags & XFS_ICREATE_ARGS_FORCE_GID)
+               inode->i_gid = args->gid;
+       else if (!pip || !XFS_INHERIT_GID(pip))
+               ASSERT(gid_eq(inode->i_gid, args->gid));
+       if (args->flags & XFS_ICREATE_ARGS_FORCE_MODE)
+               inode->i_mode = args->mode;
 
        ip->i_disk_size = 0;
        ip->i_df.if_nextents = 0;
        ASSERT(ip->i_nblocks == 0);
+
        ip->i_extsize = 0;
        ip->i_diflags = 0;
+
        if (xfs_has_v3inodes(ip->i_mount)) {
                VFS_I(ip)->i_version = 1;
-               ip->i_diflags2 = ip->i_mount->m_ino_geo.new_diflags2;
                ip->i_cowextsize = 0;
                times |= XFS_ICHGTIME_CREATE;
        }
@@ -138,12 +154,11 @@ xfs_inode_init(
        case S_IFBLK:
                ip->i_df.if_format = XFS_DINODE_FMT_DEV;
                flags |= XFS_ILOG_DEV;
-               VFS_I(ip)->i_rdev = args->rdev;
                break;
        case S_IFREG:
        case S_IFDIR:
                if (pip && (pip->i_diflags & XFS_DIFLAG_ANY))
-                       xfs_inode_propagate_flags(ip, pip);
+                       xfs_inode_inherit_flags(ip, pip);
                if (pip && (pip->i_diflags2 & XFS_DIFLAG2_ANY))
                        xfs_inode_inherit_flags2(ip, pip);
                /* FALLTHROUGH */
@@ -165,7 +180,8 @@ xfs_inode_init(
         * this saves us from needing to run a separate transaction to set the
         * fork offset in the immediate future.
         */
-       if (xfs_has_parent(tp->t_mountp) && xfs_has_attr(tp->t_mountp)) {
+       if ((args->flags & XFS_ICREATE_ARGS_INIT_XATTRS) &&
+           xfs_has_attr(mp)) {
                ip->i_forkoff = xfs_default_attroffset(ip) >> 3;
                xfs_ifork_init_attr(ip, XFS_DINODE_FMT_EXTENTS, 0);
        }
@@ -293,15 +309,15 @@ libxfs_dir_ialloc(
                .nlink          = nlink,
                .rdev           = rdev,
                .mode           = mode,
+               .flags          = XFS_ICREATE_ARGS_FORCE_UID |
+                                 XFS_ICREATE_ARGS_FORCE_GID |
+                                 XFS_ICREATE_ARGS_FORCE_MODE,
        };
        struct xfs_inode        *ip;
        xfs_ino_t               parent_ino = dp ? dp->i_ino : 0;
        xfs_ino_t               ino;
        int                     error;
 
-       if (cr->cr_flags & CRED_FORCE_GID)
-               args.flags |= XFS_ICREATE_ARGS_FORCE_GID;
-
        if (dp && xfs_has_parent(dp->i_mount))
                args.flags |= XFS_ICREATE_ARGS_INIT_XATTRS;
 
@@ -361,6 +377,7 @@ libxfs_iget(
        VFS_I(ip)->i_count = 1;
        ip->i_ino = ino;
        ip->i_mount = mp;
+       ip->i_diflags2 = mp->m_ino_geo.new_diflags2;
        ip->i_af.if_format = XFS_DINODE_FMT_EXTENTS;
        spin_lock_init(&VFS_I(ip)->i_lock);
 
@@ -442,3 +459,30 @@ libxfs_irele(
                kmem_cache_free(xfs_inode_cache, ip);
        }
 }
+
+static inline void inode_fsuid_set(struct inode *inode,
+                                  struct mnt_idmap *idmap)
+{
+       inode->i_uid = make_kuid(0);
+}
+
+static inline void inode_fsgid_set(struct inode *inode,
+                                  struct mnt_idmap *idmap)
+{
+       inode->i_gid = make_kgid(0);
+}
+
+void inode_init_owner(struct mnt_idmap *idmap, struct inode *inode,
+                     const struct inode *dir, umode_t mode)
+{
+       inode_fsuid_set(inode, idmap);
+       if (dir && dir->i_mode & S_ISGID) {
+               inode->i_gid = dir->i_gid;
+
+               /* Directories are special, and always inherit S_ISGID */
+               if (S_ISDIR(mode))
+                       mode |= S_ISGID;
+       } else
+               inode_fsgid_set(inode, idmap);
+       inode->i_mode = mode;
+}
index b2b1c56028b6f915344c336b95e0a6174c8639b8..3094de640757fe81a28f00319ea67b026a462bd1 100644 (file)
@@ -219,6 +219,12 @@ static inline bool WARN_ON(bool expr) {
        (inode)->i_version = (version); \
 } while (0)
 
+struct inode;
+struct mnt_idmap;
+
+void inode_init_owner(struct mnt_idmap *idmap, struct inode *inode,
+                     const struct inode *dir, umode_t mode);
+
 #define __must_check   __attribute__((__warn_unused_result__))
 
 /*