mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 12:11:40 +00:00
xfs: add parent attributes to symlink
This patch modifies xfs_symlink to add a parent pointer to the inode. Signed-off-by: Allison Henderson <allison.henderson@oracle.com> Reviewed-by: Darrick J. Wong <djwong@kernel.org> [djwong: minor rebase fixups] Signed-off-by: Darrick J. Wong <djwong@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
parent
f1097be220
commit
5d31a85dcc
@ -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;
|
||||
}
|
||||
|
@ -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__ */
|
||||
|
@ -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,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 @@ out_release_inode:
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user