]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
xfs: separate the icreate logic around INIT_XATTRS
authorDarrick J. Wong <djwong@kernel.org>
Tue, 2 Jul 2024 18:22:41 +0000 (11:22 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 2 Jul 2024 18:36:58 +0000 (11:36 -0700)
INIT_XATTRS is overloaded here -- it's set during the creat process when
we think that we're immediately going to set some ACL xattrs to save
time.  However, it's also used by the parent pointers code to enable the
attr fork in preparation to receive ppptr xattrs.  This results in
xfs_has_parent() branches scattered around the codebase to turn on
INIT_XATTRS.

Linkable files are created far more commonly than unlinkable temporary
files or directory tree roots, so we should centralize this logic in
xfs_inode_init.  For the three callers that don't want parent pointers
(online repiar tempfiles, unlinkable tempfiles, rootdir creation) we
provide an UNLINKABLE flag to skip attr fork initialization.

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/scrub/tempfile.c
fs/xfs/xfs_inode.c
fs/xfs/xfs_iops.c
fs/xfs/xfs_qm.c
fs/xfs/xfs_symlink.c

index 214976ecefd7783b0860774c6a65df2806d10c3c..5795445ef4bd21e4e2141e87e4359fa3695315fb 100644 (file)
@@ -233,6 +233,31 @@ xfs_inode_inherit_flags2(
        }
 }
 
+/*
+ * 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 we have parent pointers and the caller hasn't told us that the file will
+ * never be linked into a directory tree, we /must/ create the attr fork.
+ */
+static inline bool
+xfs_icreate_want_attrfork(
+       struct xfs_mount                *mp,
+       const struct xfs_icreate_args   *args)
+{
+       if (args->flags & XFS_ICREATE_INIT_XATTRS)
+               return true;
+
+       if (!(args->flags & XFS_ICREATE_UNLINKABLE) && xfs_has_parent(mp))
+               return true;
+
+       return false;
+}
+
 /* Initialise an inode's attributes. */
 void
 xfs_inode_init(
@@ -325,16 +350,7 @@ xfs_inode_init(
                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) {
+       if (xfs_icreate_want_attrfork(mp, args)) {
                ip->i_forkoff = xfs_default_attroffset(ip) >> 3;
                xfs_ifork_init_attr(ip, XFS_DINODE_FMT_EXTENTS, 0);
 
index 50c14ba6ca5a2c7b7988a4ea00726f208f9f87df..1c54c3b0cf2626ed74884a8569eb5d9caa9bd500 100644 (file)
@@ -32,6 +32,7 @@ struct xfs_icreate_args {
 
 #define XFS_ICREATE_TMPFILE    (1U << 0)  /* create an unlinked file */
 #define XFS_ICREATE_INIT_XATTRS        (1U << 1)  /* will set xattrs immediately */
+#define XFS_ICREATE_UNLINKABLE (1U << 2)  /* cannot link into dir tree */
        uint16_t                flags;
 };
 
index 523971a15a72ac1a15cded5e062552ec158a7cb6..d390d56cd8751e8f433d77782cbda173ab6aac81 100644 (file)
@@ -43,7 +43,7 @@ xrep_tempfile_create(
        struct xfs_icreate_args args = {
                .pip            = sc->mp->m_rootip,
                .mode           = mode,
-               .flags          = XFS_ICREATE_TMPFILE,
+               .flags          = XFS_ICREATE_TMPFILE | XFS_ICREATE_UNLINKABLE,
        };
        struct xfs_mount        *mp = sc->mp;
        struct xfs_trans        *tp = NULL;
index 004f277e589155e2a99b681e09390d9c08dd8920..0062ba92bcc8878017cff7abe4adff56231cd1ac 100644 (file)
@@ -2527,9 +2527,6 @@ xfs_rename_alloc_whiteout(
        struct qstr             name;
        int                     error;
 
-       if (xfs_has_parent(dp->i_mount))
-               args.flags |= XFS_ICREATE_INIT_XATTRS;
-
        error = xfs_create_tmpfile(&args, &tmpfile);
        if (error)
                return error;
index 4563ba440570ba1ab46eede3abd8c81fb6eefade..07f736c42460b1674b471d8d4f6d8a1c7c959b38 100644 (file)
@@ -158,8 +158,6 @@ xfs_create_need_xattr(
        if (dir->i_sb->s_security)
                return true;
 #endif
-       if (xfs_has_parent(XFS_I(dir)->i_mount))
-               return true;
        return false;
 }
 
@@ -215,12 +213,11 @@ xfs_generic_create(
                args.flags |= XFS_ICREATE_TMPFILE;
 
                /*
-                * If this temporary file will be linkable, set up the file
-                * with an attr fork to receive a parent pointer.
+                * If this temporary file will not be linkable, don't bother
+                * creating an attr fork to receive a parent pointer.
                 */
-               if (!(tmpfile->f_flags & O_EXCL) &&
-                   xfs_has_parent(XFS_I(dir)->i_mount))
-                       args.flags |= XFS_ICREATE_INIT_XATTRS;
+               if (tmpfile->f_flags & O_EXCL)
+                       args.flags |= XFS_ICREATE_UNLINKABLE;
 
                error = xfs_create_tmpfile(&args, &ip);
        }
index 78f839630c624b85aac4ca9b7dd50291ad0d5c1f..9490b913a4ab4f39ca046a2f4432fcf909a69aa0 100644 (file)
@@ -795,6 +795,7 @@ xfs_qm_qino_alloc(
        if (need_alloc) {
                struct xfs_icreate_args args = {
                        .mode           = S_IFREG,
+                       .flags          = XFS_ICREATE_UNLINKABLE,
                };
                xfs_ino_t       ino;
 
index 6ff736e5c4e7f545eb8430a3afdb328942a384b4..e471369f6b634eaa253cb5f82588c8cdf09d8554 100644 (file)
@@ -115,9 +115,6 @@ xfs_symlink(
        if (xfs_is_shutdown(mp))
                return -EIO;
 
-       if (xfs_has_parent(mp))
-               args.flags |= XFS_ICREATE_INIT_XATTRS;
-
        /*
         * Check component lengths of the target path name.
         */