@@ -18,6 +18,9 @@
#include "xfs_errortag.h"
#include "xfs_trace.h"
#include "xfs_health.h"
+#include "xfs_shared.h"
+#include "xfs_bmap_btree.h"
+#include "xfs_trans_space.h"
const struct xfs_name xfs_name_dotdot = {
.name = (const unsigned char *)"..",
@@ -780,3 +783,45 @@ 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_new_child(
+ struct xfs_trans *tp,
+ uint resblks,
+ struct xfs_inode *dp,
+ struct xfs_name *name,
+ struct xfs_inode *ip)
+{
+ struct xfs_mount *mp = tp->t_mountp;
+ int error;
+
+ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
+ ASSERT(xfs_isilocked(dp, XFS_ILOCK_EXCL));
+ ASSERT(resblks == 0 || resblks > XFS_IALLOC_SPACE_RES(mp));
+
+ error = xfs_dir_createname(tp, dp, name, ip->i_ino,
+ resblks - XFS_IALLOC_SPACE_RES(mp));
+ 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))
+ return 0;
+
+ error = xfs_dir_init(tp, ip, dp);
+ if (error)
+ return error;
+
+ xfs_bumplink(tp, dp);
+ return 0;
+}
@@ -253,4 +253,8 @@ unsigned int xfs_dir3_data_end_offset(struct xfs_da_geometry *geo,
struct xfs_dir2_data_hdr *hdr);
bool xfs_dir2_namecheck(const void *name, size_t length);
+int xfs_dir_create_new_child(struct xfs_trans *tp, uint resblks,
+ struct xfs_inode *dp, struct xfs_name *name,
+ struct xfs_inode *ip);
+
#endif /* __XFS_DIR2_H__ */