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

xfs: remove parent pointers in unlink



This patch removes the parent pointer attribute during unlink

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: adjust to new ondisk format, minor rebase fixes]
Signed-off-by: default avatarDarrick J. Wong <djwong@kernel.org>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
parent 5d31a85d
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -205,3 +205,25 @@ xfs_parent_addname(
	xfs_attr_defer_add(&ppargs->args, XFS_ATTR_DEFER_SET);
	return 0;
}

/* Remove a parent pointer to reflect a dirent removal. */
int
xfs_parent_removename(
	struct xfs_trans	*tp,
	struct xfs_parent_args	*ppargs,
	struct xfs_inode	*dp,
	const struct xfs_name	*parent_name,
	struct xfs_inode	*child)
{
	int			error;

	error = xfs_parent_iread_extents(tp, child);
	if (error)
		return error;

	xfs_inode_to_parent_rec(&ppargs->rec, dp);
	xfs_parent_da_args_init(&ppargs->args, tp, &ppargs->rec, child,
			child->i_ino, parent_name);
	xfs_attr_defer_add(&ppargs->args, XFS_ATTR_DEFER_REMOVE);
	return 0;
}
+3 −0
Original line number Diff line number Diff line
@@ -81,5 +81,8 @@ xfs_parent_finish(
int xfs_parent_addname(struct xfs_trans *tp, struct xfs_parent_args *ppargs,
		struct xfs_inode *dp, const struct xfs_name *parent_name,
		struct xfs_inode *child);
int xfs_parent_removename(struct xfs_trans *tp, struct xfs_parent_args *ppargs,
		struct xfs_inode *dp, const struct xfs_name *parent_name,
		struct xfs_inode *child);

#endif /* __XFS_PARENT_H__ */
+13 −0
Original line number Diff line number Diff line
@@ -81,3 +81,16 @@ xfs_symlink_space_res(

	return ret;
}

unsigned int
xfs_remove_space_res(
	struct xfs_mount	*mp,
	unsigned int		namelen)
{
	unsigned int		ret = XFS_DIRREMOVE_SPACE_RES(mp);

	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
@@ -91,8 +91,6 @@
	 XFS_DQUOT_CLUSTER_SIZE_FSB)
#define	XFS_QM_QINOCREATE_SPACE_RES(mp)	\
	XFS_IALLOC_SPACE_RES(mp)
#define	XFS_REMOVE_SPACE_RES(mp)	\
	XFS_DIRREMOVE_SPACE_RES(mp)
#define	XFS_RENAME_SPACE_RES(mp,nl)	\
	(XFS_DIRREMOVE_SPACE_RES(mp) + XFS_DIRENTER_SPACE_RES(mp,nl))
#define XFS_IFREE_SPACE_RES(mp)		\
@@ -106,5 +104,6 @@ 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);
unsigned int xfs_symlink_space_res(struct xfs_mount *mp, unsigned int namelen,
		unsigned int fsblocks);
unsigned int xfs_remove_space_res(struct xfs_mount *mp, unsigned int namelen);

#endif	/* __XFS_TRANS_SPACE_H__ */
+21 −6
Original line number Diff line number Diff line
@@ -2721,16 +2721,17 @@ xfs_iunpin_wait(
 */
int
xfs_remove(
	xfs_inode_t             *dp,
	struct xfs_inode	*dp,
	struct xfs_name		*name,
	xfs_inode_t		*ip)
	struct xfs_inode	*ip)
{
	xfs_mount_t		*mp = dp->i_mount;
	xfs_trans_t             *tp = NULL;
	struct xfs_mount	*mp = dp->i_mount;
	struct xfs_trans	*tp = NULL;
	int			is_dir = S_ISDIR(VFS_I(ip)->i_mode);
	int			dontcare;
	int                     error = 0;
	uint			resblks;
	struct xfs_parent_args	*ppargs;

	trace_xfs_remove(dp, name);

@@ -2747,6 +2748,10 @@ xfs_remove(
	if (error)
		goto std_return;

	error = xfs_parent_start(mp, &ppargs);
	if (error)
		goto std_return;

	/*
	 * We try to get the real space reservation first, allowing for
	 * directory btree deletion(s) implying possible bmap insert(s).  If we
@@ -2758,12 +2763,12 @@ xfs_remove(
	 * the directory code can handle a reservationless update and we don't
	 * want to prevent a user from trying to free space by deleting things.
	 */
	resblks = XFS_REMOVE_SPACE_RES(mp);
	resblks = xfs_remove_space_res(mp, name->len);
	error = xfs_trans_alloc_dir(dp, &M_RES(mp)->tr_remove, ip, &resblks,
			&tp, &dontcare);
	if (error) {
		ASSERT(error != -ENOSPC);
		goto std_return;
		goto out_parent;
	}

	/*
@@ -2823,6 +2828,13 @@ xfs_remove(
		goto out_trans_cancel;
	}

	/* Remove parent pointer. */
	if (ppargs) {
		error = xfs_parent_removename(tp, ppargs, dp, name, ip);
		if (error)
			goto out_trans_cancel;
	}

	/*
	 * Drop the link from dp to ip, and if ip was a directory, remove the
	 * '.' and '..' references since we freed the directory.
@@ -2846,6 +2858,7 @@ xfs_remove(

	xfs_iunlock(ip, XFS_ILOCK_EXCL);
	xfs_iunlock(dp, XFS_ILOCK_EXCL);
	xfs_parent_finish(mp, ppargs);
	return 0;

 out_trans_cancel:
@@ -2853,6 +2866,8 @@ xfs_remove(
 out_unlock:
	xfs_iunlock(ip, XFS_ILOCK_EXCL);
	xfs_iunlock(dp, XFS_ILOCK_EXCL);
 out_parent:
	xfs_parent_finish(mp, ppargs);
 std_return:
	return error;
}