]> www.infradead.org Git - users/hch/xfsprogs.git/commitdiff
xfs: split new inode creation into two pieces
authorDarrick J. Wong <djwong@kernel.org>
Tue, 9 Jan 2024 17:39:35 +0000 (09:39 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Wed, 10 Apr 2024 00:21:33 +0000 (17:21 -0700)
There are two parts to initializing a newly allocated inode: setting up
the incore structures, and initializing the new inode core based on the
parent inode and the current user's environment.  The initialization
code is not specific to the kernel, so we would like to share that with
userspace by hoisting it to libxfs.  Therefore, split xfs_icreate into
separate functions to prepare for the next few patches.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
libxfs/inode.c
libxfs/xfs_ialloc.c

index 1f240de48deb9aa43b723580c7f6711d1465145c..3af859a413154390f4b5fc902fccbe5d1cad8e15 100644 (file)
@@ -91,28 +91,17 @@ libxfs_bumplink(
        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 }
 
-/*
- * Initialise a newly allocated inode and return the in-core inode to the
- * caller locked exclusively.
- */
-static int
-libxfs_icreate(
+/* Initialise an inode's attributes. */
+static void
+xfs_inode_init(
        struct xfs_trans        *tp,
-       xfs_ino_t               ino,
        const struct xfs_icreate_args *args,
-       struct xfs_inode        **ipp)
+       struct xfs_inode        *ip)
 {
        struct xfs_inode        *pip = args->pip;
-       struct xfs_inode        *ip;
        unsigned int            flags;
        int                     times = XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG |
                                        XFS_ICHGTIME_ACCESS;
-       int                     error;
-
-       error = libxfs_iget(tp->t_mountp, tp, ino, XFS_IGET_CREATE, &ip);
-       if (error != 0)
-               return error;
-       ASSERT(ip != NULL);
 
        VFS_I(ip)->i_mode = args->mode;
        set_nlink(VFS_I(ip), args->nlink);
@@ -181,11 +170,32 @@ libxfs_icreate(
                xfs_ifork_init_attr(ip, XFS_DINODE_FMT_EXTENTS, 0);
        }
 
-       /*
-        * Log the new values stuffed into the inode.
-        */
-       xfs_trans_ijoin(tp, ip, 0);
        xfs_trans_log_inode(tp, ip, flags);
+}
+
+/*
+ * Initialise a newly allocated inode and return the in-core inode to the
+ * caller locked exclusively.
+ */
+static int
+libxfs_icreate(
+       struct xfs_trans        *tp,
+       xfs_ino_t               ino,
+       const struct xfs_icreate_args *args,
+       struct xfs_inode        **ipp)
+{
+       struct xfs_mount        *mp = tp->t_mountp;
+       struct xfs_inode        *ip = NULL;
+       int                     error;
+
+       error = libxfs_iget(mp, tp, ino, XFS_IGET_CREATE, &ip);
+       if (error)
+               return error;
+
+       ASSERT(ip != NULL);
+       xfs_trans_ijoin(tp, ip, 0);
+       xfs_inode_init(tp, args, ip);
+
        *ipp = ip;
        return 0;
 }
index d8697561e7df2f1b106f91f9824d057279cefe90..cef2819aa31677c25c776500143b04d6117eaace 100644 (file)
@@ -1941,6 +1941,21 @@ retry:
                }
                return -ENOSPC;
        }
+
+       /*
+        * Protect against obviously corrupt allocation btree records. Later
+        * xfs_iget checks will catch re-allocation of other active in-memory
+        * and on-disk inodes. If we don't catch reallocating the parent inode
+        * here we will deadlock in xfs_iget() so we have to do these checks
+        * first.
+        */
+       if (ino == parent || !xfs_verify_dir_ino(mp, ino)) {
+               xfs_alert(mp, "Allocated a known in-use inode 0x%llx!", ino);
+               xfs_agno_mark_sick(mp, XFS_INO_TO_AGNO(mp, ino),
+                               XFS_SICK_AG_INOBT);
+               return -EFSCORRUPTED;
+       }
+
        *new_ino = ino;
        return 0;
 }