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

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
...@@ -205,3 +205,25 @@ xfs_parent_addname( ...@@ -205,3 +205,25 @@ xfs_parent_addname(
xfs_attr_defer_add(&ppargs->args, XFS_ATTR_DEFER_SET); xfs_attr_defer_add(&ppargs->args, XFS_ATTR_DEFER_SET);
return 0; 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( ...@@ -81,5 +81,8 @@ xfs_parent_finish(
int xfs_parent_addname(struct xfs_trans *tp, struct xfs_parent_args *ppargs, 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 *dp, const struct xfs_name *parent_name,
struct xfs_inode *child); 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__ */ #endif /* __XFS_PARENT_H__ */
...@@ -81,3 +81,16 @@ xfs_symlink_space_res( ...@@ -81,3 +81,16 @@ xfs_symlink_space_res(
return ret; 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 @@ ...@@ -91,8 +91,6 @@
XFS_DQUOT_CLUSTER_SIZE_FSB) XFS_DQUOT_CLUSTER_SIZE_FSB)
#define XFS_QM_QINOCREATE_SPACE_RES(mp) \ #define XFS_QM_QINOCREATE_SPACE_RES(mp) \
XFS_IALLOC_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) \ #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_IFREE_SPACE_RES(mp) \ #define XFS_IFREE_SPACE_RES(mp) \
...@@ -106,5 +104,6 @@ unsigned int xfs_mkdir_space_res(struct xfs_mount *mp, unsigned int namelen); ...@@ -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_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 xfs_symlink_space_res(struct xfs_mount *mp, unsigned int namelen,
unsigned int fsblocks); unsigned int fsblocks);
unsigned int xfs_remove_space_res(struct xfs_mount *mp, unsigned int namelen);
#endif /* __XFS_TRANS_SPACE_H__ */ #endif /* __XFS_TRANS_SPACE_H__ */
...@@ -2721,16 +2721,17 @@ xfs_iunpin_wait( ...@@ -2721,16 +2721,17 @@ xfs_iunpin_wait(
*/ */
int int
xfs_remove( xfs_remove(
xfs_inode_t *dp, struct xfs_inode *dp,
struct xfs_name *name, struct xfs_name *name,
xfs_inode_t *ip) struct xfs_inode *ip)
{ {
xfs_mount_t *mp = dp->i_mount; struct xfs_mount *mp = dp->i_mount;
xfs_trans_t *tp = NULL; struct xfs_trans *tp = NULL;
int is_dir = S_ISDIR(VFS_I(ip)->i_mode); int is_dir = S_ISDIR(VFS_I(ip)->i_mode);
int dontcare; int dontcare;
int error = 0; int error = 0;
uint resblks; uint resblks;
struct xfs_parent_args *ppargs;
trace_xfs_remove(dp, name); trace_xfs_remove(dp, name);
...@@ -2747,6 +2748,10 @@ xfs_remove( ...@@ -2747,6 +2748,10 @@ xfs_remove(
if (error) if (error)
goto std_return; 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 * We try to get the real space reservation first, allowing for
* directory btree deletion(s) implying possible bmap insert(s). If we * directory btree deletion(s) implying possible bmap insert(s). If we
...@@ -2758,12 +2763,12 @@ xfs_remove( ...@@ -2758,12 +2763,12 @@ xfs_remove(
* the directory code can handle a reservationless update and we don't * 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. * 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, error = xfs_trans_alloc_dir(dp, &M_RES(mp)->tr_remove, ip, &resblks,
&tp, &dontcare); &tp, &dontcare);
if (error) { if (error) {
ASSERT(error != -ENOSPC); ASSERT(error != -ENOSPC);
goto std_return; goto out_parent;
} }
/* /*
...@@ -2823,6 +2828,13 @@ xfs_remove( ...@@ -2823,6 +2828,13 @@ xfs_remove(
goto out_trans_cancel; 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 * Drop the link from dp to ip, and if ip was a directory, remove the
* '.' and '..' references since we freed the directory. * '.' and '..' references since we freed the directory.
...@@ -2846,6 +2858,7 @@ xfs_remove( ...@@ -2846,6 +2858,7 @@ xfs_remove(
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:
...@@ -2853,6 +2866,8 @@ xfs_remove( ...@@ -2853,6 +2866,8 @@ xfs_remove(
out_unlock: out_unlock:
xfs_iunlock(ip, XFS_ILOCK_EXCL); xfs_iunlock(ip, XFS_ILOCK_EXCL);
xfs_iunlock(dp, XFS_ILOCK_EXCL); xfs_iunlock(dp, XFS_ILOCK_EXCL);
out_parent:
xfs_parent_finish(mp, ppargs);
std_return: std_return:
return error; return error;
} }
......
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