Commit f1097be2 authored by Allison Henderson's avatar Allison Henderson Committed by Darrick J. Wong
Browse files

xfs: add parent attributes to link



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

Signed-off-by: default avatarDave Chinner <dchinner@redhat.com>
Signed-off-by: default avatarAllison Henderson <allison.henderson@oracle.com>
Reviewed-by: default avatarDarrick J. Wong <djwong@kernel.org>
[djwong: minor rebase fixes]
Signed-off-by: default avatarDarrick J. Wong <djwong@kernel.org>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
parent b7c62d90
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -50,3 +50,17 @@ xfs_mkdir_space_res(
{
	return xfs_create_space_res(mp, namelen);
}

unsigned int
xfs_link_space_res(
	struct xfs_mount	*mp,
	unsigned int		namelen)
{
	unsigned int		ret;

	ret = XFS_DIRENTER_SPACE_RES(mp, namelen);
	if (xfs_has_parent(mp))
		ret += xfs_parent_calc_space_res(mp, namelen);

	return ret;
}
+1 −2
Original line number Diff line number Diff line
@@ -86,8 +86,6 @@
	(2 * (mp)->m_alloc_maxlevels)
#define	XFS_GROWFSRT_SPACE_RES(mp,b)	\
	((b) + XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK))
#define	XFS_LINK_SPACE_RES(mp,nl)	\
	XFS_DIRENTER_SPACE_RES(mp,nl)
#define	XFS_QM_DQALLOC_SPACE_RES(mp)	\
	(XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK) + \
	 XFS_DQUOT_CLUSTER_SIZE_FSB)
@@ -107,5 +105,6 @@ unsigned int xfs_parent_calc_space_res(struct xfs_mount *mp,

unsigned int xfs_create_space_res(struct xfs_mount *mp, unsigned int namelen);
unsigned int xfs_mkdir_space_res(struct xfs_mount *mp, unsigned int namelen);
unsigned int xfs_link_space_res(struct xfs_mount *mp, unsigned int namelen);

#endif	/* __XFS_TRANS_SPACE_H__ */
+1 −1
Original line number Diff line number Diff line
@@ -704,7 +704,7 @@ xrep_dir_replay_update(
	uint				resblks;
	int				error;

	resblks = XFS_LINK_SPACE_RES(mp, xname->len);
	resblks = xfs_link_space_res(mp, xname->len);
	error = xchk_trans_alloc(rd->sc, resblks);
	if (error)
		return error;
+1 −1
Original line number Diff line number Diff line
@@ -326,7 +326,7 @@ xrep_adoption_trans_alloc(

	/* Compute the worst case space reservation that we need. */
	adopt->sc = sc;
	adopt->orphanage_blkres = XFS_LINK_SPACE_RES(mp, MAXNAMELEN);
	adopt->orphanage_blkres = xfs_link_space_res(mp, MAXNAMELEN);
	if (S_ISDIR(VFS_I(sc->ip)->i_mode))
		child_blkres = XFS_RENAME_SPACE_RES(mp, xfs_name_dotdot.len);
	adopt->child_blkres = child_blkres;
+37 −6
Original line number Diff line number Diff line
@@ -1299,14 +1299,15 @@ 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;
	struct xfs_parent_args	*ppargs;

	trace_xfs_link(tdp, target_name);

@@ -1325,11 +1326,25 @@ xfs_link(
	if (error)
		goto std_return;

	resblks = XFS_LINK_SPACE_RES(mp, target_name->len);
	error = xfs_parent_start(mp, &ppargs);
	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 out_parent;

	/*
	 * We don't allow reservationless or quotaless hardlinking when parent
	 * pointers are enabled because we can't back out if the xattrs must
	 * grow.
	 */
	if (ppargs && nospace_error) {
		error = nospace_error;
		goto error_return;
	}

	/*
	 * If we are using project inheritance, we only allow hard link
@@ -1380,6 +1395,19 @@ xfs_link(
	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 (ppargs) {
		error = xfs_parent_addname(tp, ppargs, tdp, target_name, sip);
		if (error)
			goto error_return;
	}

	xfs_dir_update_hook(tdp, sip, 1, target_name);

	/*
@@ -1393,12 +1421,15 @@ xfs_link(
	error = xfs_trans_commit(tp);
	xfs_iunlock(tdp, XFS_ILOCK_EXCL);
	xfs_iunlock(sip, XFS_ILOCK_EXCL);
	xfs_parent_finish(mp, ppargs);
	return error;

 error_return:
	xfs_trans_cancel(tp);
	xfs_iunlock(tdp, XFS_ILOCK_EXCL);
	xfs_iunlock(sip, XFS_ILOCK_EXCL);
 out_parent:
	xfs_parent_finish(mp, ppargs);
 std_return:
	if (error == -ENOSPC && nospace_error)
		error = nospace_error;