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

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
...@@ -64,3 +64,20 @@ xfs_link_space_res( ...@@ -64,3 +64,20 @@ xfs_link_space_res(
return ret; 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 @@ ...@@ -95,8 +95,6 @@
XFS_DIRREMOVE_SPACE_RES(mp) XFS_DIRREMOVE_SPACE_RES(mp)
#define XFS_RENAME_SPACE_RES(mp,nl) \ #define XFS_RENAME_SPACE_RES(mp,nl) \
(XFS_DIRREMOVE_SPACE_RES(mp) + XFS_DIRENTER_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) \ #define XFS_IFREE_SPACE_RES(mp) \
(xfs_has_finobt(mp) ? M_IGEO(mp)->inobt_maxlevels : 0) (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, ...@@ -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_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_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_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__ */ #endif /* __XFS_TRANS_SPACE_H__ */
...@@ -421,7 +421,7 @@ xrep_symlink_rebuild( ...@@ -421,7 +421,7 @@ xrep_symlink_rebuild(
* unlikely. * unlikely.
*/ */
fs_blocks = xfs_symlink_blocks(sc->mp, target_len); 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, error = xfs_trans_reserve_quota_nblks(sc->tp, sc->tempip, resblks, 0,
true); true);
if (error) if (error)
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
#include "xfs_error.h" #include "xfs_error.h"
#include "xfs_health.h" #include "xfs_health.h"
#include "xfs_symlink_remote.h" #include "xfs_symlink_remote.h"
#include "xfs_parent.h"
#include "xfs_defer.h"
int int
xfs_readlink( xfs_readlink(
...@@ -100,6 +102,7 @@ xfs_symlink( ...@@ -100,6 +102,7 @@ xfs_symlink(
struct xfs_dquot *pdqp = NULL; struct xfs_dquot *pdqp = NULL;
uint resblks; uint resblks;
xfs_ino_t ino; xfs_ino_t ino;
struct xfs_parent_args *ppargs;
*ipp = NULL; *ipp = NULL;
...@@ -130,18 +133,24 @@ xfs_symlink( ...@@ -130,18 +133,24 @@ xfs_symlink(
/* /*
* The symlink will fit into the inode data fork? * 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; fs_blocks = 0;
else else
fs_blocks = xfs_symlink_blocks(mp, pathlen); 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, error = xfs_trans_alloc_icreate(mp, &M_RES(mp)->tr_symlink, udqp, gdqp,
pdqp, resblks, &tp); pdqp, resblks, &tp);
if (error) if (error)
goto out_release_dquots; goto out_parent;
xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT); xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT);
unlock_dp_on_error = true; unlock_dp_on_error = true;
...@@ -161,7 +170,7 @@ xfs_symlink( ...@@ -161,7 +170,7 @@ xfs_symlink(
if (!error) if (!error)
error = xfs_init_new_inode(idmap, tp, dp, ino, error = xfs_init_new_inode(idmap, tp, dp, ino,
S_IFLNK | (mode & ~S_IFMT), 1, 0, prid, S_IFLNK | (mode & ~S_IFMT), 1, 0, prid,
false, &ip); xfs_has_parent(mp), &ip);
if (error) if (error)
goto out_trans_cancel; goto out_trans_cancel;
...@@ -195,6 +204,14 @@ xfs_symlink( ...@@ -195,6 +204,14 @@ xfs_symlink(
goto out_trans_cancel; goto out_trans_cancel;
xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); 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); xfs_dir_update_hook(dp, ip, 1, link_name);
/* /*
...@@ -216,6 +233,7 @@ xfs_symlink( ...@@ -216,6 +233,7 @@ xfs_symlink(
*ipp = ip; *ipp = ip;
xfs_iunlock(ip, XFS_ILOCK_EXCL); xfs_iunlock(ip, XFS_ILOCK_EXCL);
xfs_iunlock(dp, XFS_ILOCK_EXCL); xfs_iunlock(dp, XFS_ILOCK_EXCL);
xfs_parent_finish(mp, ppargs);
return 0; return 0;
out_trans_cancel: out_trans_cancel:
...@@ -231,6 +249,8 @@ xfs_symlink( ...@@ -231,6 +249,8 @@ xfs_symlink(
xfs_finish_inode_setup(ip); xfs_finish_inode_setup(ip);
xfs_irele(ip); xfs_irele(ip);
} }
out_parent:
xfs_parent_finish(mp, ppargs);
out_release_dquots: out_release_dquots:
xfs_qm_dqrele(udqp); xfs_qm_dqrele(udqp);
xfs_qm_dqrele(gdqp); xfs_qm_dqrele(gdqp);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment