[PATCH RESEND v2 13/18] xfs: add parent attributes to link

Allison Henderson
2022-08-04T19:40:45Z

This patch modifies xfs_link to add a parent pointer to the inode.

[bfoster: rebase, use VFS inode fields, fix xfs_bmap_finish() usage]
[achender: rebased, changed __unint32_t to xfs_dir2_dataptr_t,
fixed null pointer bugs]

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
---
fs/xfs/xfs_inode.c | 43 ++++++++++++++++++++++++++++++++++---------
1 file changed, 34 insertions(+), 9 deletions(-)

diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index ef993c3a8963..6e5deb0d42c4 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -1228,14 +1228,16 @@ xfs_create_tmpfile(

int
xfs_link(
- xfs_inode_t *tdp,
- xfs_inode_t *sip,
+ struct xfs_inode *tdp,
+ struct xfs_inode *sip,
struct xfs_name *target_name)
{
- xfs_mount_t *mp = tdp->i_mount;
- xfs_trans_t *tp;
+ struct xfs_mount *mp = tdp->i_mount;
+ struct xfs_trans *tp;
int error, nospace_error = 0;
int resblks;
+ xfs_dir2_dataptr_t diroffset;
+ struct xfs_parent_defer *parent = NULL;

trace_xfs_link(tdp, target_name);

@@ -1252,11 +1254,17 @@ xfs_link(
if (error)
goto std_return;

+ if (xfs_has_parent(mp)) {
+ error = xfs_parent_init(mp, sip, target_name, &parent);
+ if (error)
+ goto std_return;
+ }
+
resblks = XFS_LINK_SPACE_RES(mp, target_name->len);
error = xfs_trans_alloc_dir(tdp, &M_RES(mp)->tr_link, sip, &resblks,
&tp, &nospace_error);
if (error)
- goto std_return;
+ goto drop_incompat;

/*
* If we are using project inheritance, we only allow hard link
@@ -1289,14 +1297,26 @@ xfs_link(
}

error = xfs_dir_createname(tp, tdp, target_name, sip->i_ino,
- resblks, NULL);
+ resblks, &diroffset);
if (error)
- goto error_return;
+ goto out_defer_cancel;
xfs_trans_ichgtime(tp, tdp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
xfs_trans_log_inode(tp, tdp, XFS_ILOG_CORE);

xfs_bumplink(tp, sip);

+ /*
+ * If we have parent pointers, we now need to add the parent record to
+ * the attribute fork of the inode. If this is the initial parent
+ * attribute, we need to create it correctly, otherwise we can just add
+ * the parent to the inode.
+ */
+ if (parent) {
+ error = xfs_parent_defer_add(tp, tdp, parent, diroffset);
+ if (error)
+ goto out_defer_cancel;
+ }
+
/*
* If this is a synchronous mount, make sure that the
* link transaction goes to disk before returning to
@@ -1310,11 +1330,16 @@ xfs_link(
xfs_iunlock(sip, XFS_ILOCK_EXCL);
return error;

- error_return:
+out_defer_cancel:
+ xfs_defer_cancel(tp);
+error_return:
xfs_trans_cancel(tp);
xfs_iunlock(tdp, XFS_ILOCK_EXCL);
xfs_iunlock(sip, XFS_ILOCK_EXCL);
- std_return:
+drop_incompat:
+ if (parent)
+ xfs_parent_cancel(mp, parent);
+std_return:
if (error == -ENOSPC && nospace_error)
error = nospace_error;
return error;
--
2.25.1