xfs: remove parent pointers in unlink
This patch removes the parent pointer attribute during unlink Signed-off-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Allison Henderson <allison.henderson@oracle.com> Reviewed-by: Darrick J. Wong <djwong@kernel.org> [djwong: adjust to new ondisk format, minor rebase fixes] Signed-off-by: Darrick J. Wong <djwong@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
parent
5d31a85dcc
commit
d2d18330f6
@ -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;
|
||||
}
|
||||
|
@ -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__ */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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__ */
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user