@@ -233,12 +233,20 @@ int
xfs_attr_set_args(
struct xfs_da_args *args,
struct xfs_buf **leaf_bp,
+ xfs_attr_state_t *state,
bool roll_trans)
{
struct xfs_inode *dp = args->dp;
int error = 0;
int sf_size;
+ switch (*state) {
+ case (XFS_ATTR_STATE1):
+ goto state1;
+ case (XFS_ATTR_STATE2):
+ goto state2;
+ }
+
/*
* New inodes setting the parent pointer attr will
* not have an attribute fork yet. So set the attribute
@@ -259,7 +267,6 @@ xfs_attr_set_args(
if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL ||
(dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
dp->i_d.di_anextents == 0)) {
-
/*
* Build initial attribute list (if required).
*/
@@ -273,6 +280,9 @@ xfs_attr_set_args(
if (error != -ENOSPC)
goto out;
+ *state = XFS_ATTR_STATE1;
+ return -EAGAIN;
+state1:
/*
* It won't fit in the shortform, transform to a leaf block.
* GROT: another possible req'mt for a double-split btree op.
@@ -281,14 +291,14 @@ xfs_attr_set_args(
if (error)
goto out;
- if (roll_trans) {
- /*
- * Prevent the leaf buffer from being unlocked so that a
- * concurrent AIL push cannot grab the half-baked leaf
- * buffer and run into problems with the write verifier.
- */
- xfs_trans_bhold(args->trans, *leaf_bp);
+ /*
+ * Prevent the leaf buffer from being unlocked so that a
+ * concurrent AIL push cannot grab the half-baked leaf
+ * buffer and run into problems with the write verifier.
+ */
+ xfs_trans_bhold(args->trans, *leaf_bp);
+ if (roll_trans) {
error = xfs_defer_finish(&args->trans);
if (error)
goto out;
@@ -304,6 +314,12 @@ xfs_attr_set_args(
xfs_trans_bjoin(args->trans, *leaf_bp);
*leaf_bp = NULL;
}
+
+ *state = XFS_ATTR_STATE2;
+ return -EAGAIN;
+state2:
+ if (*leaf_bp != NULL)
+ xfs_trans_brelse(args->trans, *leaf_bp);
}
if (xfs_bmap_one_block(dp, XFS_ATTR_FORK))
@@ -436,7 +452,9 @@ xfs_attr_set(
}
xfs_trans_ijoin(args.trans, dp, 0);
- error = xfs_attr_set_args(&args, &leaf_bp, true);
+
+ error = xfs_attr_set_deferred(dp, args.trans, name, strlen(name),
+ value, valuelen, flags);
if (error)
goto out;
@@ -566,8 +584,13 @@ xfs_attr_remove(
*/
xfs_trans_ijoin(args.trans, dp, 0);
- error = xfs_attr_remove_args(&args, true);
+ error = xfs_has_attr(&args);
+ if (error)
+ goto out;
+
+ error = xfs_attr_remove_deferred(dp, args.trans,
+ name, strlen(name), flags);
if (error)
goto out;
@@ -175,7 +175,7 @@ int xfs_attr_get(struct xfs_inode *ip, const unsigned char *name,
int xfs_attr_set(struct xfs_inode *dp, const unsigned char *name,
unsigned char *value, int valuelen, int flags);
int xfs_attr_set_args(struct xfs_da_args *args, struct xfs_buf **leaf_bp,
- bool roll_trans);
+ xfs_attr_state_t *state, bool roll_trans);
int xfs_attr_remove(struct xfs_inode *dp, const unsigned char *name, int flags);
int xfs_has_attr(struct xfs_da_args *args);
int xfs_attr_remove_args(struct xfs_da_args *args, bool roll_trans);
This patch modifies xfs_attr_set_args to return -EAGAIN when a transaction needs to be rolled. All functions currently calling xfs_attr_set_args are modified to use the deferred attr operation, or handle the -EAGAIN return code Signed-off-by: Allison Henderson <allison.henderson@oracle.com> --- libxfs/xfs_attr.c | 43 +++++++++++++++++++++++++++++++++---------- libxfs/xfs_attr.h | 2 +- 2 files changed, 34 insertions(+), 11 deletions(-)