]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs: create libxfs helper to link a new inode into a directory
authorDarrick J. Wong <djwong@kernel.org>
Wed, 2 Oct 2024 01:14:20 +0000 (18:14 -0700)
committerAndrey Albershteyn <aalbersh@redhat.com>
Fri, 4 Oct 2024 10:42:07 +0000 (12:42 +0200)
Source kernel commit: 1fa2e81957cf11620867729fb613b121692ee0d3

Create a new libxfs function to link a newly created inode into a
directory.  The upcoming metadata directory feature will need this to
create a metadata directory tree.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
libxfs/xfs_dir2.c
libxfs/xfs_dir2.h

index 9cf05ec51185ee3faf387051e288a635ecbe0558..e98b2802408a98c1cf22f2924634f653547cc217 100644 (file)
@@ -18,6 +18,9 @@
 #include "xfs_errortag.h"
 #include "xfs_trace.h"
 #include "xfs_health.h"
+#include "xfs_bmap_btree.h"
+#include "xfs_trans_space.h"
+#include "xfs_parent.h"
 
 const struct xfs_name xfs_name_dotdot = {
        .name   = (const unsigned char *)"..",
@@ -755,3 +758,53 @@ xfs_dir2_compname(
                return xfs_ascii_ci_compname(args, name, len);
        return xfs_da_compname(args, name, len);
 }
+
+/*
+ * Given a directory @dp, a newly allocated inode @ip, and a @name, link @ip
+ * into @dp under the given @name.  If @ip is a directory, it will be
+ * initialized.  Both inodes must have the ILOCK held and the transaction must
+ * have sufficient blocks reserved.
+ */
+int
+xfs_dir_create_child(
+       struct xfs_trans        *tp,
+       unsigned int            resblks,
+       struct xfs_dir_update   *du)
+{
+       struct xfs_inode        *dp = du->dp;
+       const struct xfs_name   *name = du->name;
+       struct xfs_inode        *ip = du->ip;
+       int                     error;
+
+       xfs_assert_ilocked(ip, XFS_ILOCK_EXCL);
+       xfs_assert_ilocked(dp, XFS_ILOCK_EXCL);
+
+       error = xfs_dir_createname(tp, dp, name, ip->i_ino, resblks);
+       if (error) {
+               ASSERT(error != -ENOSPC);
+               return error;
+       }
+
+       xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+       xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
+
+       if (S_ISDIR(VFS_I(ip)->i_mode)) {
+               error = xfs_dir_init(tp, ip, dp);
+               if (error)
+                       return error;
+
+               xfs_bumplink(tp, dp);
+       }
+
+       /*
+        * If we have parent pointers, we need to add the attribute containing
+        * the parent information now.
+        */
+       if (du->ppargs) {
+               error = xfs_parent_addname(tp, du->ppargs, dp, name, ip);
+               if (error)
+                       return error;
+       }
+
+       return 0;
+}
index 6dbe6e9ecb491f69e87e2b8ba2dc54a73f59355a..a1ba6fd0a725fe20e3169bd60888d3acf12d1e3e 100644 (file)
@@ -309,4 +309,16 @@ static inline unsigned char xfs_ascii_ci_xfrm(unsigned char c)
        return c;
 }
 
+struct xfs_parent_args;
+
+struct xfs_dir_update {
+       struct xfs_inode        *dp;
+       const struct xfs_name   *name;
+       struct xfs_inode        *ip;
+       struct xfs_parent_args  *ppargs;
+};
+
+int xfs_dir_create_child(struct xfs_trans *tp, unsigned int resblks,
+               struct xfs_dir_update *du);
+
 #endif /* __XFS_DIR2_H__ */