@@ -1422,6 +1422,7 @@ xfs_link(
struct xfs_defer_ops dfops;
xfs_fsblock_t first_block;
int resblks;
+ xfs_dir2_dataptr_t diroffset;
trace_xfs_link(tdp, target_name);
@@ -1449,8 +1450,8 @@ xfs_link(
xfs_lock_two_inodes(sip, XFS_ILOCK_EXCL, tdp, XFS_ILOCK_EXCL);
- xfs_trans_ijoin(tp, sip, XFS_ILOCK_EXCL);
- xfs_trans_ijoin(tp, tdp, XFS_ILOCK_EXCL);
+ xfs_trans_ijoin(tp, sip, 0);
+ xfs_trans_ijoin(tp, tdp, 0);
/*
* If we are using project inheritance, we only allow hard link
@@ -1469,8 +1470,6 @@ xfs_link(
goto error_return;
}
- xfs_defer_init(&dfops, &first_block);
-
/*
* Handle initial link state of O_TMPFILE inode
*/
@@ -1480,16 +1479,30 @@ xfs_link(
goto error_return;
}
+ xfs_defer_init(&dfops, &first_block);
error = xfs_dir_createname(tp, tdp, target_name, sip->i_ino,
- &first_block, &dfops, resblks, NULL);
+ &first_block, &dfops, 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);
error = xfs_bumplink(tp, sip);
if (error)
- goto error_return;
+ goto out_defer_cancel;
+
+ /*
+ * 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 (xfs_sb_version_hasparent(&mp->m_sb)) {
+ error = xfs_parent_add_deferred(tdp, sip, target_name,
+ diroffset, &dfops);
+ if (error)
+ goto out_defer_cancel;
+ }
/*
* If this is a synchronous mount, make sure that the
@@ -1500,16 +1513,21 @@ xfs_link(
xfs_trans_set_sync(tp);
error = xfs_defer_finish(&tp, &dfops);
- if (error) {
- xfs_defer_cancel(&dfops);
- goto error_return;
- }
+ if (error)
+ goto out_defer_cancel;
- return xfs_trans_commit(tp);
+ error = xfs_trans_commit(tp);
+ xfs_iunlock(tdp, XFS_ILOCK_EXCL);
+ xfs_iunlock(sip, XFS_ILOCK_EXCL);
+ return error;
- error_return:
+out_defer_cancel:
+ xfs_defer_cancel(&dfops);
+error_return:
xfs_trans_cancel(tp);
- std_return:
+ xfs_iunlock(tdp, XFS_ILOCK_EXCL);
+ xfs_iunlock(sip, XFS_ILOCK_EXCL);
+std_return:
return error;
}