]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
xfs: hoist new inode initialization functions to libxfs
authorDarrick J. Wong <djwong@kernel.org>
Tue, 2 Jul 2024 18:22:37 +0000 (11:22 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 2 Jul 2024 18:36:57 +0000 (11:36 -0700)
Move all the code that initializes a new inode's attributes from the
icreate_args structure and the parent directory into libxfs.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
fs/xfs/libxfs/xfs_inode_util.c
fs/xfs/libxfs/xfs_inode_util.h
fs/xfs/libxfs/xfs_shared.h
fs/xfs/xfs_inode.c
fs/xfs/xfs_trans.h

index 3b5397a3f34f2ac843d30ddbf48845bf70e14ccf..8654cb3d79efb7b3364cf4524900ab39006d756b 100644 (file)
@@ -3,6 +3,7 @@
  * Copyright (c) 2000-2006 Silicon Graphics, Inc.
  * All Rights Reserved.
  */
+#include <linux/iversion.h>
 #include "xfs.h"
 #include "xfs_fs.h"
 #include "xfs_shared.h"
 #include "xfs_mount.h"
 #include "xfs_inode.h"
 #include "xfs_inode_util.h"
+#include "xfs_trans.h"
+#include "xfs_ialloc.h"
+#include "xfs_health.h"
+#include "xfs_bmap.h"
 
 uint16_t
 xfs_flags2diflags(
@@ -132,3 +137,210 @@ xfs_get_initial_prid(struct xfs_inode *dp)
        /* Assign to the root project by default. */
        return 0;
 }
+
+/* Propagate di_flags from a parent inode to a child inode. */
+static inline void
+xfs_inode_inherit_flags(
+       struct xfs_inode        *ip,
+       const struct xfs_inode  *pip)
+{
+       unsigned int            di_flags = 0;
+       xfs_failaddr_t          failaddr;
+       umode_t                 mode = VFS_I(ip)->i_mode;
+
+       if (S_ISDIR(mode)) {
+               if (pip->i_diflags & XFS_DIFLAG_RTINHERIT)
+                       di_flags |= XFS_DIFLAG_RTINHERIT;
+               if (pip->i_diflags & XFS_DIFLAG_EXTSZINHERIT) {
+                       di_flags |= XFS_DIFLAG_EXTSZINHERIT;
+                       ip->i_extsize = pip->i_extsize;
+               }
+               if (pip->i_diflags & XFS_DIFLAG_PROJINHERIT)
+                       di_flags |= XFS_DIFLAG_PROJINHERIT;
+       } else if (S_ISREG(mode)) {
+               if ((pip->i_diflags & XFS_DIFLAG_RTINHERIT) &&
+                   xfs_has_realtime(ip->i_mount))
+                       di_flags |= XFS_DIFLAG_REALTIME;
+               if (pip->i_diflags & XFS_DIFLAG_EXTSZINHERIT) {
+                       di_flags |= XFS_DIFLAG_EXTSIZE;
+                       ip->i_extsize = pip->i_extsize;
+               }
+       }
+       if ((pip->i_diflags & XFS_DIFLAG_NOATIME) &&
+           xfs_inherit_noatime)
+               di_flags |= XFS_DIFLAG_NOATIME;
+       if ((pip->i_diflags & XFS_DIFLAG_NODUMP) &&
+           xfs_inherit_nodump)
+               di_flags |= XFS_DIFLAG_NODUMP;
+       if ((pip->i_diflags & XFS_DIFLAG_SYNC) &&
+           xfs_inherit_sync)
+               di_flags |= XFS_DIFLAG_SYNC;
+       if ((pip->i_diflags & XFS_DIFLAG_NOSYMLINKS) &&
+           xfs_inherit_nosymlinks)
+               di_flags |= XFS_DIFLAG_NOSYMLINKS;
+       if ((pip->i_diflags & XFS_DIFLAG_NODEFRAG) &&
+           xfs_inherit_nodefrag)
+               di_flags |= XFS_DIFLAG_NODEFRAG;
+       if (pip->i_diflags & XFS_DIFLAG_FILESTREAM)
+               di_flags |= XFS_DIFLAG_FILESTREAM;
+
+       ip->i_diflags |= di_flags;
+
+       /*
+        * Inode verifiers on older kernels only check that the extent size
+        * hint is an integer multiple of the rt extent size on realtime files.
+        * They did not check the hint alignment on a directory with both
+        * rtinherit and extszinherit flags set.  If the misaligned hint is
+        * propagated from a directory into a new realtime file, new file
+        * allocations will fail due to math errors in the rt allocator and/or
+        * trip the verifiers.  Validate the hint settings in the new file so
+        * that we don't let broken hints propagate.
+        */
+       failaddr = xfs_inode_validate_extsize(ip->i_mount, ip->i_extsize,
+                       VFS_I(ip)->i_mode, ip->i_diflags);
+       if (failaddr) {
+               ip->i_diflags &= ~(XFS_DIFLAG_EXTSIZE |
+                                  XFS_DIFLAG_EXTSZINHERIT);
+               ip->i_extsize = 0;
+       }
+}
+
+/* Propagate di_flags2 from a parent inode to a child inode. */
+static inline void
+xfs_inode_inherit_flags2(
+       struct xfs_inode        *ip,
+       const struct xfs_inode  *pip)
+{
+       xfs_failaddr_t          failaddr;
+
+       if (pip->i_diflags2 & XFS_DIFLAG2_COWEXTSIZE) {
+               ip->i_diflags2 |= XFS_DIFLAG2_COWEXTSIZE;
+               ip->i_cowextsize = pip->i_cowextsize;
+       }
+       if (pip->i_diflags2 & XFS_DIFLAG2_DAX)
+               ip->i_diflags2 |= XFS_DIFLAG2_DAX;
+
+       /* Don't let invalid cowextsize hints propagate. */
+       failaddr = xfs_inode_validate_cowextsize(ip->i_mount, ip->i_cowextsize,
+                       VFS_I(ip)->i_mode, ip->i_diflags, ip->i_diflags2);
+       if (failaddr) {
+               ip->i_diflags2 &= ~XFS_DIFLAG2_COWEXTSIZE;
+               ip->i_cowextsize = 0;
+       }
+}
+
+/* Initialise an inode's attributes. */
+void
+xfs_inode_init(
+       struct xfs_trans        *tp,
+       const struct xfs_icreate_args *args,
+       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;
+
+       if (args->flags & XFS_ICREATE_TMPFILE)
+               set_nlink(inode, 0);
+       else if (S_ISDIR(args->mode))
+               set_nlink(inode, 2);
+       else
+               set_nlink(inode, 1);
+       inode->i_rdev = args->rdev;
+
+       if (!args->idmap || pip == NULL) {
+               /* creating a tree root, sb rooted, or detached file */
+               inode->i_uid = GLOBAL_ROOT_UID;
+               inode->i_gid = GLOBAL_ROOT_GID;
+               ip->i_projid = 0;
+               inode->i_mode = args->mode;
+       } else {
+               /* creating a child in the directory tree */
+               if (dir && !(dir->i_mode & S_ISGID) && xfs_has_grpid(mp)) {
+                       inode_fsuid_set(inode, args->idmap);
+                       inode->i_gid = dir->i_gid;
+                       inode->i_mode = args->mode;
+               } else {
+                       inode_init_owner(args->idmap, inode, dir, args->mode);
+               }
+
+               /*
+                * If the group ID of the new file does not match the effective
+                * group ID or one of the supplementary group IDs, the S_ISGID
+                * bit is cleared (and only if the irix_sgid_inherit
+                * compatibility variable is set).
+                */
+               if (irix_sgid_inherit && (inode->i_mode & S_ISGID) &&
+                   !vfsgid_in_group_p(i_gid_into_vfsgid(args->idmap, inode)))
+                       inode->i_mode &= ~S_ISGID;
+
+               ip->i_projid = pip ? xfs_get_initial_prid(pip) : 0;
+       }
+
+       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(mp)) {
+               inode_set_iversion(inode, 1);
+               ip->i_cowextsize = 0;
+               times |= XFS_ICHGTIME_CREATE;
+       }
+
+       xfs_trans_ichgtime(tp, ip, times);
+
+       flags = XFS_ILOG_CORE;
+       switch (args->mode & S_IFMT) {
+       case S_IFIFO:
+       case S_IFCHR:
+       case S_IFBLK:
+       case S_IFSOCK:
+               ip->i_df.if_format = XFS_DINODE_FMT_DEV;
+               flags |= XFS_ILOG_DEV;
+               break;
+       case S_IFREG:
+       case S_IFDIR:
+               if (pip && (pip->i_diflags & XFS_DIFLAG_ANY))
+                       xfs_inode_inherit_flags(ip, pip);
+               if (pip && (pip->i_diflags2 & XFS_DIFLAG2_ANY))
+                       xfs_inode_inherit_flags2(ip, pip);
+               fallthrough;
+       case S_IFLNK:
+               ip->i_df.if_format = XFS_DINODE_FMT_EXTENTS;
+               ip->i_df.if_bytes = 0;
+               ip->i_df.if_data = NULL;
+               break;
+       default:
+               ASSERT(0);
+       }
+
+       /*
+        * If we need to create attributes immediately after allocating the
+        * inode, initialise an empty attribute fork right now. We use the
+        * default fork offset for attributes here as we don't know exactly what
+        * size or how many attributes we might be adding. We can do this
+        * safely here because we know the data fork is completely empty and
+        * this saves us from needing to run a separate transaction to set the
+        * fork offset in the immediate future.
+        */
+       if (args->flags & XFS_ICREATE_INIT_XATTRS) {
+               ip->i_forkoff = xfs_default_attroffset(ip) >> 3;
+               xfs_ifork_init_attr(ip, XFS_DINODE_FMT_EXTENTS, 0);
+
+               if (!xfs_has_attr(mp)) {
+                       spin_lock(&mp->m_sb_lock);
+                       xfs_add_attr(mp);
+                       spin_unlock(&mp->m_sb_lock);
+                       xfs_log_sb(tp);
+               }
+       }
+
+       xfs_trans_log_inode(tp, ip, flags);
+}
index 9226482fdee8cea668a2730c89e172256b350ec4..bf5393db4fde61712ab236997a5fddbeebcd99ee 100644 (file)
@@ -35,4 +35,16 @@ struct xfs_icreate_args {
        uint16_t                flags;
 };
 
+/*
+ * Flags for xfs_trans_ichgtime().
+ */
+#define        XFS_ICHGTIME_MOD        0x1     /* data fork modification timestamp */
+#define        XFS_ICHGTIME_CHG        0x2     /* inode field change timestamp */
+#define        XFS_ICHGTIME_CREATE     0x4     /* inode create timestamp */
+#define        XFS_ICHGTIME_ACCESS     0x8     /* last access timestamp */
+void xfs_trans_ichgtime(struct xfs_trans *tp, struct xfs_inode *ip, int flags);
+
+void xfs_inode_init(struct xfs_trans *tp, const struct xfs_icreate_args *args,
+               struct xfs_inode *ip);
+
 #endif /* __XFS_INODE_UTIL_H__ */
index 9a705381f9e4ac9d4ffd1f17d13358c4cd74e5d8..2f7413afbf46cdfafb93ea15daa7d3b9013a5275 100644 (file)
@@ -177,14 +177,6 @@ void       xfs_log_get_max_trans_res(struct xfs_mount *mp,
 #define        XFS_REFC_BTREE_REF      1
 #define        XFS_SSB_REF             0
 
-/*
- * Flags for xfs_trans_ichgtime().
- */
-#define        XFS_ICHGTIME_MOD        0x1     /* data fork modification timestamp */
-#define        XFS_ICHGTIME_CHG        0x2     /* inode field change timestamp */
-#define        XFS_ICHGTIME_CREATE     0x4     /* inode create timestamp */
-#define        XFS_ICHGTIME_ACCESS     0x8     /* last access timestamp */
-
 /* Computed inode geometry for the filesystem. */
 struct xfs_ino_geometry {
        /* Maximum inode count in this filesystem. */
index 88c641400f51e15f3f7a3d9ad2ec0d7f4136a584..152def4ca5db407aae3a38b3427daf935109780a 100644 (file)
@@ -42,7 +42,7 @@
 #include "xfs_pnfs.h"
 #include "xfs_parent.h"
 #include "xfs_xattr.h"
-#include "xfs_sb.h"
+#include "xfs_inode_util.h"
 
 struct kmem_cache *xfs_inode_cache;
 
@@ -564,213 +564,6 @@ out_unlock:
        return error;
 }
 
-/* Propagate di_flags from a parent inode to a child inode. */
-static void
-xfs_inode_inherit_flags(
-       struct xfs_inode        *ip,
-       const struct xfs_inode  *pip)
-{
-       unsigned int            di_flags = 0;
-       xfs_failaddr_t          failaddr;
-       umode_t                 mode = VFS_I(ip)->i_mode;
-
-       if (S_ISDIR(mode)) {
-               if (pip->i_diflags & XFS_DIFLAG_RTINHERIT)
-                       di_flags |= XFS_DIFLAG_RTINHERIT;
-               if (pip->i_diflags & XFS_DIFLAG_EXTSZINHERIT) {
-                       di_flags |= XFS_DIFLAG_EXTSZINHERIT;
-                       ip->i_extsize = pip->i_extsize;
-               }
-               if (pip->i_diflags & XFS_DIFLAG_PROJINHERIT)
-                       di_flags |= XFS_DIFLAG_PROJINHERIT;
-       } else if (S_ISREG(mode)) {
-               if ((pip->i_diflags & XFS_DIFLAG_RTINHERIT) &&
-                   xfs_has_realtime(ip->i_mount))
-                       di_flags |= XFS_DIFLAG_REALTIME;
-               if (pip->i_diflags & XFS_DIFLAG_EXTSZINHERIT) {
-                       di_flags |= XFS_DIFLAG_EXTSIZE;
-                       ip->i_extsize = pip->i_extsize;
-               }
-       }
-       if ((pip->i_diflags & XFS_DIFLAG_NOATIME) &&
-           xfs_inherit_noatime)
-               di_flags |= XFS_DIFLAG_NOATIME;
-       if ((pip->i_diflags & XFS_DIFLAG_NODUMP) &&
-           xfs_inherit_nodump)
-               di_flags |= XFS_DIFLAG_NODUMP;
-       if ((pip->i_diflags & XFS_DIFLAG_SYNC) &&
-           xfs_inherit_sync)
-               di_flags |= XFS_DIFLAG_SYNC;
-       if ((pip->i_diflags & XFS_DIFLAG_NOSYMLINKS) &&
-           xfs_inherit_nosymlinks)
-               di_flags |= XFS_DIFLAG_NOSYMLINKS;
-       if ((pip->i_diflags & XFS_DIFLAG_NODEFRAG) &&
-           xfs_inherit_nodefrag)
-               di_flags |= XFS_DIFLAG_NODEFRAG;
-       if (pip->i_diflags & XFS_DIFLAG_FILESTREAM)
-               di_flags |= XFS_DIFLAG_FILESTREAM;
-
-       ip->i_diflags |= di_flags;
-
-       /*
-        * Inode verifiers on older kernels only check that the extent size
-        * hint is an integer multiple of the rt extent size on realtime files.
-        * They did not check the hint alignment on a directory with both
-        * rtinherit and extszinherit flags set.  If the misaligned hint is
-        * propagated from a directory into a new realtime file, new file
-        * allocations will fail due to math errors in the rt allocator and/or
-        * trip the verifiers.  Validate the hint settings in the new file so
-        * that we don't let broken hints propagate.
-        */
-       failaddr = xfs_inode_validate_extsize(ip->i_mount, ip->i_extsize,
-                       VFS_I(ip)->i_mode, ip->i_diflags);
-       if (failaddr) {
-               ip->i_diflags &= ~(XFS_DIFLAG_EXTSIZE |
-                                  XFS_DIFLAG_EXTSZINHERIT);
-               ip->i_extsize = 0;
-       }
-}
-
-/* Propagate di_flags2 from a parent inode to a child inode. */
-static void
-xfs_inode_inherit_flags2(
-       struct xfs_inode        *ip,
-       const struct xfs_inode  *pip)
-{
-       xfs_failaddr_t          failaddr;
-
-       if (pip->i_diflags2 & XFS_DIFLAG2_COWEXTSIZE) {
-               ip->i_diflags2 |= XFS_DIFLAG2_COWEXTSIZE;
-               ip->i_cowextsize = pip->i_cowextsize;
-       }
-       if (pip->i_diflags2 & XFS_DIFLAG2_DAX)
-               ip->i_diflags2 |= XFS_DIFLAG2_DAX;
-
-       /* Don't let invalid cowextsize hints propagate. */
-       failaddr = xfs_inode_validate_cowextsize(ip->i_mount, ip->i_cowextsize,
-                       VFS_I(ip)->i_mode, ip->i_diflags, ip->i_diflags2);
-       if (failaddr) {
-               ip->i_diflags2 &= ~XFS_DIFLAG2_COWEXTSIZE;
-               ip->i_cowextsize = 0;
-       }
-}
-
-/* Initialise an inode's attributes. */
-static void
-xfs_inode_init(
-       struct xfs_trans        *tp,
-       const struct xfs_icreate_args *args,
-       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;
-
-       if (args->flags & XFS_ICREATE_TMPFILE)
-               set_nlink(inode, 0);
-       else if (S_ISDIR(args->mode))
-               set_nlink(inode, 2);
-       else
-               set_nlink(inode, 1);
-       inode->i_rdev = args->rdev;
-
-       if (!args->idmap || pip == NULL) {
-               /* creating a tree root, sb rooted, or detached file */
-               inode->i_uid = GLOBAL_ROOT_UID;
-               inode->i_gid = GLOBAL_ROOT_GID;
-               ip->i_projid = 0;
-               inode->i_mode = args->mode;
-       } else {
-               /* creating a child in the directory tree */
-               if (dir && !(dir->i_mode & S_ISGID) && xfs_has_grpid(mp)) {
-                       inode_fsuid_set(inode, args->idmap);
-                       inode->i_gid = dir->i_gid;
-                       inode->i_mode = args->mode;
-               } else {
-                       inode_init_owner(args->idmap, inode, dir, args->mode);
-               }
-
-               /*
-                * If the group ID of the new file does not match the effective
-                * group ID or one of the supplementary group IDs, the S_ISGID
-                * bit is cleared (and only if the irix_sgid_inherit
-                * compatibility variable is set).
-                */
-               if (irix_sgid_inherit && (inode->i_mode & S_ISGID) &&
-                   !vfsgid_in_group_p(i_gid_into_vfsgid(args->idmap, inode)))
-                       inode->i_mode &= ~S_ISGID;
-
-               ip->i_projid = pip ? xfs_get_initial_prid(pip) : 0;
-       }
-
-       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(mp)) {
-               inode_set_iversion(inode, 1);
-               ip->i_cowextsize = 0;
-               times |= XFS_ICHGTIME_CREATE;
-       }
-
-       xfs_trans_ichgtime(tp, ip, times);
-
-       flags = XFS_ILOG_CORE;
-       switch (args->mode & S_IFMT) {
-       case S_IFIFO:
-       case S_IFCHR:
-       case S_IFBLK:
-       case S_IFSOCK:
-               ip->i_df.if_format = XFS_DINODE_FMT_DEV;
-               flags |= XFS_ILOG_DEV;
-               break;
-       case S_IFREG:
-       case S_IFDIR:
-               if (pip && (pip->i_diflags & XFS_DIFLAG_ANY))
-                       xfs_inode_inherit_flags(ip, pip);
-               if (pip && (pip->i_diflags2 & XFS_DIFLAG2_ANY))
-                       xfs_inode_inherit_flags2(ip, pip);
-               fallthrough;
-       case S_IFLNK:
-               ip->i_df.if_format = XFS_DINODE_FMT_EXTENTS;
-               ip->i_df.if_bytes = 0;
-               ip->i_df.if_data = NULL;
-               break;
-       default:
-               ASSERT(0);
-       }
-
-       /*
-        * If we need to create attributes immediately after allocating the
-        * inode, initialise an empty attribute fork right now. We use the
-        * default fork offset for attributes here as we don't know exactly what
-        * size or how many attributes we might be adding. We can do this
-        * safely here because we know the data fork is completely empty and
-        * this saves us from needing to run a separate transaction to set the
-        * fork offset in the immediate future.
-        */
-       if (args->flags & XFS_ICREATE_INIT_XATTRS) {
-               ip->i_forkoff = xfs_default_attroffset(ip) >> 3;
-               xfs_ifork_init_attr(ip, XFS_DINODE_FMT_EXTENTS, 0);
-
-               if (!xfs_has_attr(mp)) {
-                       spin_lock(&mp->m_sb_lock);
-                       xfs_add_attr(mp);
-                       spin_unlock(&mp->m_sb_lock);
-                       xfs_log_sb(tp);
-               }
-       }
-
-       xfs_trans_log_inode(tp, ip, flags);
-}
-
 /*
  * Initialise a newly allocated inode and return the in-core inode to the
  * caller locked exclusively.
index 1636663707dc04dd1eb9ab4f5dc3ce37ddfba974..f97e8c68641f0c9c5132978b4359135ef2260599 100644 (file)
@@ -224,7 +224,6 @@ void                xfs_trans_stale_inode_buf(xfs_trans_t *, struct xfs_buf *);
 bool           xfs_trans_ordered_buf(xfs_trans_t *, struct xfs_buf *);
 void           xfs_trans_dquot_buf(xfs_trans_t *, struct xfs_buf *, uint);
 void           xfs_trans_inode_alloc_buf(xfs_trans_t *, struct xfs_buf *);
-void           xfs_trans_ichgtime(struct xfs_trans *, struct xfs_inode *, int);
 void           xfs_trans_ijoin(struct xfs_trans *, struct xfs_inode *, uint);
 void           xfs_trans_log_buf(struct xfs_trans *, struct xfs_buf *, uint,
                                  uint);