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

xfs: add parent attributes to symlink



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

Signed-off-by: default avatarAllison Henderson <allison.henderson@oracle.com>
Reviewed-by: default avatarDarrick J. Wong <djwong@kernel.org>
[djwong: minor rebase fixups]
Signed-off-by: default avatarDarrick J. Wong <djwong@kernel.org>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
parent f1097be2
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -64,3 +64,20 @@ xfs_link_space_res(

	return ret;
}

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

	ret = XFS_IALLOC_SPACE_RES(mp) + XFS_DIRENTER_SPACE_RES(mp, namelen) +
			fsblocks;

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

	return ret;
}
+2 −2
Original line number Diff line number Diff line
@@ -95,8 +95,6 @@
	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_SYMLINK_SPACE_RES(mp,nl,b)	\
	(XFS_IALLOC_SPACE_RES(mp) + XFS_DIRENTER_SPACE_RES(mp,nl) + (b))
#define XFS_IFREE_SPACE_RES(mp)		\
	(xfs_has_finobt(mp) ? M_IGEO(mp)->inobt_maxlevels : 0)

@@ -106,5 +104,7 @@ 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);
unsigned int xfs_symlink_space_res(struct xfs_mount *mp, unsigned int namelen,
		unsigned int fsblocks);

#endif	/* __XFS_TRANS_SPACE_H__ */
+1 −1
Original line number Diff line number Diff line
@@ -421,7 +421,7 @@ xrep_symlink_rebuild(
	 * unlikely.
	 */
	fs_blocks = xfs_symlink_blocks(sc->mp, target_len);
	resblks = XFS_SYMLINK_SPACE_RES(sc->mp, target_len, fs_blocks);
	resblks = xfs_symlink_space_res(sc->mp, target_len, fs_blocks);
	error = xfs_trans_reserve_quota_nblks(sc->tp, sc->tempip, resblks, 0,
			true);
	if (error)
+25 −5
Original line number Diff line number Diff line
@@ -25,6 +25,8 @@
#include "xfs_error.h"
#include "xfs_health.h"
#include "xfs_symlink_remote.h"
#include "xfs_parent.h"
#include "xfs_defer.h"

int
xfs_readlink(
@@ -100,6 +102,7 @@ xfs_symlink(
	struct xfs_dquot	*pdqp = NULL;
	uint			resblks;
	xfs_ino_t		ino;
	struct xfs_parent_args	*ppargs;

	*ipp = NULL;

@@ -130,18 +133,24 @@ xfs_symlink(

	/*
	 * The symlink will fit into the inode data fork?
	 * There can't be any attributes so we get the whole variable part.
	 * If there are no parent pointers, then there wont't be any attributes.
	 * So we get the whole variable part, and do not need to reserve extra
	 * blocks.  Otherwise, we need to reserve the blocks.
	 */
	if (pathlen <= XFS_LITINO(mp))
	if (pathlen <= XFS_LITINO(mp) && !xfs_has_parent(mp))
		fs_blocks = 0;
	else
		fs_blocks = xfs_symlink_blocks(mp, pathlen);
	resblks = XFS_SYMLINK_SPACE_RES(mp, link_name->len, fs_blocks);
	resblks = xfs_symlink_space_res(mp, link_name->len, fs_blocks);

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

	error = xfs_trans_alloc_icreate(mp, &M_RES(mp)->tr_symlink, udqp, gdqp,
			pdqp, resblks, &tp);
	if (error)
		goto out_release_dquots;
		goto out_parent;

	xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT);
	unlock_dp_on_error = true;
@@ -161,7 +170,7 @@ xfs_symlink(
	if (!error)
		error = xfs_init_new_inode(idmap, tp, dp, ino,
				S_IFLNK | (mode & ~S_IFMT), 1, 0, prid,
				false, &ip);
				xfs_has_parent(mp), &ip);
	if (error)
		goto out_trans_cancel;

@@ -195,6 +204,14 @@ xfs_symlink(
		goto out_trans_cancel;
	xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
	xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);

	/* Add parent pointer for the new symlink. */
	if (ppargs) {
		error = xfs_parent_addname(tp, ppargs, dp, link_name, ip);
		if (error)
			goto out_trans_cancel;
	}

	xfs_dir_update_hook(dp, ip, 1, link_name);

	/*
@@ -216,6 +233,7 @@ xfs_symlink(
	*ipp = ip;
	xfs_iunlock(ip, XFS_ILOCK_EXCL);
	xfs_iunlock(dp, XFS_ILOCK_EXCL);
	xfs_parent_finish(mp, ppargs);
	return 0;

out_trans_cancel:
@@ -231,6 +249,8 @@ xfs_symlink(
		xfs_finish_inode_setup(ip);
		xfs_irele(ip);
	}
out_parent:
	xfs_parent_finish(mp, ppargs);
out_release_dquots:
	xfs_qm_dqrele(udqp);
	xfs_qm_dqrele(gdqp);