diff --git a/libxfs/xfs_attr.c b/libxfs/xfs_attr.c
index ae8d1d6..d31560d 100644
--- a/libxfs/xfs_attr.c
+++ b/libxfs/xfs_attr.c
@@ -44,15 +44,15 @@ STATIC int xfs_attr_shortform_addname(xfs_da_args_t *args);
  * Internal routines when attribute list is one block.
  */
 STATIC int xfs_attr_leaf_get(xfs_da_args_t *args);
-STATIC int xfs_attr_leaf_addname(xfs_da_args_t *args);
-STATIC int xfs_attr_leaf_removename(xfs_da_args_t *args);
+STATIC int xfs_attr_leaf_addname(xfs_da_args_t *args, bool roll_trans);
+STATIC int xfs_attr_leaf_removename(xfs_da_args_t *args, bool roll_trans);
 
 /*
  * Internal routines when attribute list is more than one block.
  */
 STATIC int xfs_attr_node_get(xfs_da_args_t *args);
-STATIC int xfs_attr_node_addname(xfs_da_args_t *args);
-STATIC int xfs_attr_node_removename(xfs_da_args_t *args);
+STATIC int xfs_attr_node_addname(xfs_da_args_t *args, bool roll_trans);
+STATIC int xfs_attr_node_removename(xfs_da_args_t *args, bool roll_trans);
 STATIC int xfs_attr_fillstate(xfs_da_state_t *state);
 STATIC int xfs_attr_refillstate(xfs_da_state_t *state);
 
@@ -228,10 +228,11 @@ xfs_attr_try_sf_addname(
 int
 xfs_attr_set_args(
 	struct xfs_da_args	*args,
-	struct xfs_buf          **leaf_bp)
+	struct xfs_buf          **leaf_bp,
+	bool			roll_trans)
 {
 	struct xfs_inode	*dp = args->dp;
-	int			error;
+	int			error = 0;
 	int			sf_size;
 
 	/*
@@ -276,33 +277,35 @@ xfs_attr_set_args(
 		if (error)
 			goto out;
 
-		/*
-		 * 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) {
+			/*
+			 * 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);
 
-		error = xfs_defer_finish(&args->trans);
-		if (error)
-			goto out;
+			error = xfs_defer_finish(&args->trans);
+			if (error)
+				goto out;
 
-		/*
-		 * Commit the leaf transformation.  We'll need another
-		 * (linked) transaction to add the new attribute to the
-		 * leaf.
-		 */
-		error = xfs_trans_roll_inode(&args->trans, dp);
-		if (error)
-			goto out;
-		xfs_trans_bjoin(args->trans, *leaf_bp);
-		*leaf_bp = NULL;
+			/*
+			 * Commit the leaf transformation.  We'll need another
+			 * (linked) transaction to add the new attribute to the
+			 * leaf.
+			 */
+			error = xfs_trans_roll_inode(&args->trans, dp);
+			if (error)
+				goto out;
+			xfs_trans_bjoin(args->trans, *leaf_bp);
+			*leaf_bp = NULL;
+		}
 	}
 
 	if (xfs_bmap_one_block(dp, XFS_ATTR_FORK))
-		error = xfs_attr_leaf_addname(args);
+		error = xfs_attr_leaf_addname(args, roll_trans);
 	else
-		error = xfs_attr_node_addname(args);
+		error = xfs_attr_node_addname(args, roll_trans);
 	if (error)
 		goto out;
 
@@ -315,7 +318,8 @@ out:
  */
 int
 xfs_attr_remove_args(
-	struct xfs_da_args      *args)
+	struct xfs_da_args      *args,
+	bool                    roll_trans)
 {
 	struct xfs_inode	*dp = args->dp;
 	int			error;
@@ -326,9 +330,9 @@ xfs_attr_remove_args(
 		ASSERT(dp->i_afp->if_flags & XFS_IFINLINE);
 		error = xfs_attr_shortform_remove(args);
 	} else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
-		error = xfs_attr_leaf_removename(args);
+		error = xfs_attr_leaf_removename(args, roll_trans);
 	} else {
-		error = xfs_attr_node_removename(args);
+		error = xfs_attr_node_removename(args, roll_trans);
 	}
 
 	return error;
@@ -405,7 +409,7 @@ xfs_attr_set(
 	}
 
 	xfs_trans_ijoin(args.trans, dp, 0);
-	error = xfs_attr_set_args(&args, &leaf_bp);
+	error = xfs_attr_set_args(&args, &leaf_bp, true);
 	if (error)
 		goto out;
 
@@ -489,7 +493,8 @@ xfs_attr_remove(
 	 */
 	xfs_trans_ijoin(args.trans, dp, 0);
 
-	error = xfs_attr_remove_args(&args);
+	error = xfs_attr_remove_args(&args, true);
+
 	if (error)
 		goto out;
 
@@ -579,7 +584,8 @@ xfs_attr_shortform_addname(xfs_da_args_t *args)
  */
 STATIC int
 xfs_attr_leaf_addname(
-	struct xfs_da_args	*args)
+	struct xfs_da_args	*args,
+	bool			roll_trans)
 {
 	struct xfs_inode	*dp;
 	struct xfs_buf		*bp;
@@ -644,32 +650,39 @@ xfs_attr_leaf_addname(
 		error = xfs_attr3_leaf_to_node(args);
 		if (error)
 			goto out_defer_cancel;
-		error = xfs_defer_finish(&args->trans);
-		if (error)
-			return error;
 
-		/*
-		 * Commit the current trans (including the inode) and start
-		 * a new one.
-		 */
-		error = xfs_trans_roll_inode(&args->trans, dp);
-		if (error)
-			return error;
+		if (roll_trans) {
+			error = xfs_defer_finish(&args->trans);
+			if (error)
+				return error;
+
+			/*
+			 * Commit the current trans (including the inode) and
+			 * start a new one.
+			 */
+			error = xfs_trans_roll_inode(&args->trans, dp);
+			if (error)
+				return error;
+		}
 
 		/*
 		 * Fob the whole rest of the problem off on the Btree code.
 		 */
-		error = xfs_attr_node_addname(args);
+		error = xfs_attr_node_addname(args, roll_trans);
+
 		return error;
 	}
 
-	/*
-	 * Commit the transaction that added the attr name so that
-	 * later routines can manage their own transactions.
-	 */
-	error = xfs_trans_roll_inode(&args->trans, dp);
-	if (error)
-		return error;
+
+	if (roll_trans) {
+		/*
+		 * Commit the transaction that added the attr name so that
+		 * later routines can manage their own transactions.
+		 */
+		error = xfs_trans_roll_inode(&args->trans, dp);
+		if (error)
+			return error;
+	}
 
 	/*
 	 * If there was an out-of-line value, allocate the blocks we
@@ -678,7 +691,7 @@ xfs_attr_leaf_addname(
 	 * maximum size of a transaction and/or hit a deadlock.
 	 */
 	if (args->rmtblkno > 0) {
-		error = xfs_attr_rmtval_set(args);
+		error = xfs_attr_rmtval_set(args, roll_trans);
 		if (error)
 			return error;
 	}
@@ -694,7 +707,7 @@ xfs_attr_leaf_addname(
 		 * In a separate transaction, set the incomplete flag on the
 		 * "old" attr and clear the incomplete flag on the "new" attr.
 		 */
-		error = xfs_attr3_leaf_flipflags(args);
+		error = xfs_attr3_leaf_flipflags(args, roll_trans);
 		if (error)
 			return error;
 
@@ -708,7 +721,7 @@ xfs_attr_leaf_addname(
 		args->rmtblkcnt = args->rmtblkcnt2;
 		args->rmtvaluelen = args->rmtvaluelen2;
 		if (args->rmtblkno) {
-			error = xfs_attr_rmtval_remove(args);
+			error = xfs_attr_rmtval_remove(args, roll_trans);
 			if (error)
 				return error;
 		}
@@ -732,21 +745,25 @@ xfs_attr_leaf_addname(
 			/* bp is gone due to xfs_da_shrink_inode */
 			if (error)
 				goto out_defer_cancel;
-			error = xfs_defer_finish(&args->trans);
-			if (error)
-				return error;
+
+			if (roll_trans) {
+				error = xfs_defer_finish(&args->trans);
+				if (error)
+					return error;
+			}
 		}
 
 		/*
 		 * Commit the remove and start the next trans in series.
 		 */
-		error = xfs_trans_roll_inode(&args->trans, dp);
+		if (roll_trans)
+			error = xfs_trans_roll_inode(&args->trans, dp);
 
 	} else if (args->rmtblkno > 0) {
 		/*
 		 * Added a "remote" value, just clear the incomplete flag.
 		 */
-		error = xfs_attr3_leaf_clearflag(args);
+		error = xfs_attr3_leaf_clearflag(args, roll_trans);
 	}
 	return error;
 out_defer_cancel:
@@ -762,7 +779,8 @@ out_defer_cancel:
  */
 STATIC int
 xfs_attr_leaf_removename(
-	struct xfs_da_args	*args)
+	struct xfs_da_args	*args,
+	bool roll_trans)
 {
 	struct xfs_inode	*dp;
 	struct xfs_buf		*bp;
@@ -795,9 +813,11 @@ xfs_attr_leaf_removename(
 		/* bp is gone due to xfs_da_shrink_inode */
 		if (error)
 			goto out_defer_cancel;
-		error = xfs_defer_finish(&args->trans);
-		if (error)
-			return error;
+		if (roll_trans) {
+			error = xfs_defer_finish(&args->trans);
+			if (error)
+				return error;
+		}
 	}
 	return 0;
 out_defer_cancel:
@@ -853,7 +873,8 @@ xfs_attr_leaf_get(xfs_da_args_t *args)
  */
 STATIC int
 xfs_attr_node_addname(
-	struct xfs_da_args	*args)
+	struct xfs_da_args	*args,
+	bool			roll_trans)
 {
 	struct xfs_da_state	*state;
 	struct xfs_da_state_blk	*blk;
@@ -918,20 +939,24 @@ restart:
 			 */
 			xfs_da_state_free(state);
 			state = NULL;
+
 			error = xfs_attr3_leaf_to_node(args);
 			if (error)
 				goto out_defer_cancel;
-			error = xfs_defer_finish(&args->trans);
-			if (error)
-				goto out;
 
-			/*
-			 * Commit the node conversion and start the next
-			 * trans in the chain.
-			 */
-			error = xfs_trans_roll_inode(&args->trans, dp);
-			if (error)
-				goto out;
+			if (roll_trans) {
+				error = xfs_defer_finish(&args->trans);
+				if (error)
+					goto out;
+
+				/*
+				 * Commit the node conversion and start the next
+				 * trans in the chain.
+				 */
+				error = xfs_trans_roll_inode(&args->trans, dp);
+				if (error)
+					goto out;
+			}
 
 			goto restart;
 		}
@@ -945,9 +970,12 @@ restart:
 		error = xfs_da3_split(state);
 		if (error)
 			goto out_defer_cancel;
-		error = xfs_defer_finish(&args->trans);
-		if (error)
-			goto out;
+
+		if (roll_trans) {
+			error = xfs_defer_finish(&args->trans);
+			if (error)
+				goto out;
+		}
 	} else {
 		/*
 		 * Addition succeeded, update Btree hashvals.
@@ -966,9 +994,11 @@ restart:
 	 * Commit the leaf addition or btree split and start the next
 	 * trans in the chain.
 	 */
-	error = xfs_trans_roll_inode(&args->trans, dp);
-	if (error)
-		goto out;
+	if (roll_trans) {
+		error = xfs_trans_roll_inode(&args->trans, dp);
+		if (error)
+			goto out;
+	}
 
 	/*
 	 * If there was an out-of-line value, allocate the blocks we
@@ -977,7 +1007,7 @@ restart:
 	 * maximum size of a transaction and/or hit a deadlock.
 	 */
 	if (args->rmtblkno > 0) {
-		error = xfs_attr_rmtval_set(args);
+		error = xfs_attr_rmtval_set(args, roll_trans);
 		if (error)
 			return error;
 	}
@@ -993,7 +1023,7 @@ restart:
 		 * In a separate transaction, set the incomplete flag on the
 		 * "old" attr and clear the incomplete flag on the "new" attr.
 		 */
-		error = xfs_attr3_leaf_flipflags(args);
+		error = xfs_attr3_leaf_flipflags(args, roll_trans);
 		if (error)
 			goto out;
 
@@ -1007,7 +1037,7 @@ restart:
 		args->rmtblkcnt = args->rmtblkcnt2;
 		args->rmtvaluelen = args->rmtvaluelen2;
 		if (args->rmtblkno) {
-			error = xfs_attr_rmtval_remove(args);
+			error = xfs_attr_rmtval_remove(args, roll_trans);
 			if (error)
 				return error;
 		}
@@ -1041,9 +1071,11 @@ restart:
 			error = xfs_da3_join(state);
 			if (error)
 				goto out_defer_cancel;
-			error = xfs_defer_finish(&args->trans);
-			if (error)
-				goto out;
+			if (roll_trans) {
+				error = xfs_defer_finish(&args->trans);
+				if (error)
+					goto out;
+			}
 		}
 
 		/*
@@ -1057,7 +1089,7 @@ restart:
 		/*
 		 * Added a "remote" value, just clear the incomplete flag.
 		 */
-		error = xfs_attr3_leaf_clearflag(args);
+		error = xfs_attr3_leaf_clearflag(args, roll_trans);
 		if (error)
 			goto out;
 	}
@@ -1083,7 +1115,8 @@ out_defer_cancel:
  */
 STATIC int
 xfs_attr_node_removename(
-	struct xfs_da_args	*args)
+	struct xfs_da_args	*args,
+	bool			roll_trans)
 {
 	struct xfs_da_state	*state;
 	struct xfs_da_state_blk	*blk;
@@ -1133,10 +1166,10 @@ xfs_attr_node_removename(
 		 * Mark the attribute as INCOMPLETE, then bunmapi() the
 		 * remote value.
 		 */
-		error = xfs_attr3_leaf_setflag(args);
+		error = xfs_attr3_leaf_setflag(args, roll_trans);
 		if (error)
 			goto out;
-		error = xfs_attr_rmtval_remove(args);
+		error = xfs_attr_rmtval_remove(args, roll_trans);
 		if (error)
 			goto out;
 
@@ -1164,15 +1197,19 @@ xfs_attr_node_removename(
 		error = xfs_da3_join(state);
 		if (error)
 			goto out_defer_cancel;
-		error = xfs_defer_finish(&args->trans);
-		if (error)
-			goto out;
-		/*
-		 * Commit the Btree join operation and start a new trans.
-		 */
-		error = xfs_trans_roll_inode(&args->trans, dp);
-		if (error)
-			goto out;
+
+		if (roll_trans) {
+			error = xfs_defer_finish(&args->trans);
+			if (error)
+				goto out;
+			/*
+			 * Commit the Btree join operation and
+			 * start a new trans.
+			 */
+			error = xfs_trans_roll_inode(&args->trans, dp);
+			if (error)
+				goto out;
+		}
 	}
 
 	/*
@@ -1195,9 +1232,12 @@ xfs_attr_node_removename(
 			/* bp is gone due to xfs_da_shrink_inode */
 			if (error)
 				goto out_defer_cancel;
-			error = xfs_defer_finish(&args->trans);
-			if (error)
-				goto out;
+
+			if (roll_trans) {
+				error = xfs_defer_finish(&args->trans);
+				if (error)
+					goto out;
+			}
 		} else
 			xfs_trans_brelse(args->trans, bp);
 	}
diff --git a/libxfs/xfs_attr.h b/libxfs/xfs_attr.h
index a6911b8..c7a194c 100644
--- a/libxfs/xfs_attr.h
+++ b/libxfs/xfs_attr.h
@@ -137,9 +137,10 @@ int xfs_attr_get(struct xfs_inode *ip, const unsigned char *name,
 		 unsigned char *value, int *valuelenp, int flags);
 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);
+int xfs_attr_set_args(struct xfs_da_args *args, struct xfs_buf **leaf_bp,
+		 bool roll_trans);
 int xfs_attr_remove(struct xfs_inode *dp, const unsigned char *name, int flags);
-int xfs_attr_remove_args(struct xfs_da_args *args);
+int xfs_attr_remove_args(struct xfs_da_args *args, bool roll_trans);
 int xfs_attr_list(struct xfs_inode *dp, char *buffer, int bufsize,
 		  int flags, struct attrlist_cursor_kern *cursor);
 
diff --git a/libxfs/xfs_attr_leaf.c b/libxfs/xfs_attr_leaf.c
index 3ecd524..60444d0 100644
--- a/libxfs/xfs_attr_leaf.c
+++ b/libxfs/xfs_attr_leaf.c
@@ -2634,7 +2634,8 @@ xfs_attr_leaf_newentsize(
  */
 int
 xfs_attr3_leaf_clearflag(
-	struct xfs_da_args	*args)
+	struct xfs_da_args	*args,
+	bool			roll_trans)
 {
 	struct xfs_attr_leafblock *leaf;
 	struct xfs_attr_leaf_entry *entry;
@@ -2695,7 +2696,9 @@ xfs_attr3_leaf_clearflag(
 	/*
 	 * Commit the flag value change and start the next trans in series.
 	 */
-	return xfs_trans_roll_inode(&args->trans, args->dp);
+	if (roll_trans)
+		error = xfs_trans_roll_inode(&args->trans, args->dp);
+	return error;
 }
 
 /*
@@ -2703,7 +2706,8 @@ xfs_attr3_leaf_clearflag(
  */
 int
 xfs_attr3_leaf_setflag(
-	struct xfs_da_args	*args)
+	struct xfs_da_args	*args,
+	bool			roll_trans)
 {
 	struct xfs_attr_leafblock *leaf;
 	struct xfs_attr_leaf_entry *entry;
@@ -2746,7 +2750,9 @@ xfs_attr3_leaf_setflag(
 	/*
 	 * Commit the flag value change and start the next trans in series.
 	 */
-	return xfs_trans_roll_inode(&args->trans, args->dp);
+	if (roll_trans)
+		error = xfs_trans_roll_inode(&args->trans, args->dp);
+	return error;
 }
 
 /*
@@ -2758,7 +2764,8 @@ xfs_attr3_leaf_setflag(
  */
 int
 xfs_attr3_leaf_flipflags(
-	struct xfs_da_args	*args)
+	struct xfs_da_args	*args,
+	bool			roll_trans)
 {
 	struct xfs_attr_leafblock *leaf1;
 	struct xfs_attr_leafblock *leaf2;
@@ -2864,7 +2871,8 @@ xfs_attr3_leaf_flipflags(
 	/*
 	 * Commit the flag value change and start the next trans in series.
 	 */
-	error = xfs_trans_roll_inode(&args->trans, args->dp);
+	if (roll_trans)
+		error = xfs_trans_roll_inode(&args->trans, args->dp);
 
 	return error;
 }
diff --git a/libxfs/xfs_attr_leaf.h b/libxfs/xfs_attr_leaf.h
index 7b74e18..9d830ec 100644
--- a/libxfs/xfs_attr_leaf.h
+++ b/libxfs/xfs_attr_leaf.h
@@ -49,10 +49,10 @@ void	xfs_attr_fork_remove(struct xfs_inode *ip, struct xfs_trans *tp);
  */
 int	xfs_attr3_leaf_to_node(struct xfs_da_args *args);
 int	xfs_attr3_leaf_to_shortform(struct xfs_buf *bp,
-				   struct xfs_da_args *args, int forkoff);
-int	xfs_attr3_leaf_clearflag(struct xfs_da_args *args);
-int	xfs_attr3_leaf_setflag(struct xfs_da_args *args);
-int	xfs_attr3_leaf_flipflags(struct xfs_da_args *args);
+			struct xfs_da_args *args, int forkoff);
+int	xfs_attr3_leaf_clearflag(struct xfs_da_args *args, bool roll_trans);
+int	xfs_attr3_leaf_setflag(struct xfs_da_args *args, bool roll_trans);
+int	xfs_attr3_leaf_flipflags(struct xfs_da_args *args, bool roll_trans);
 
 /*
  * Routines used for growing the Btree.
diff --git a/libxfs/xfs_attr_remote.c b/libxfs/xfs_attr_remote.c
index 1d078ef..6446607 100644
--- a/libxfs/xfs_attr_remote.c
+++ b/libxfs/xfs_attr_remote.c
@@ -428,7 +428,8 @@ xfs_attr_rmtval_get(
  */
 int
 xfs_attr_rmtval_set(
-	struct xfs_da_args	*args)
+	struct xfs_da_args	*args,
+	bool			roll_trans)
 {
 	struct xfs_inode	*dp = args->dp;
 	struct xfs_mount	*mp = dp->i_mount;
@@ -481,9 +482,12 @@ xfs_attr_rmtval_set(
 				  &nmap);
 		if (error)
 			goto out_defer_cancel;
-		error = xfs_defer_finish(&args->trans);
-		if (error)
-			return error;
+
+		if (roll_trans) {
+			error = xfs_defer_finish(&args->trans);
+			if (error)
+				return error;
+		}
 
 		ASSERT(nmap == 1);
 		ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
@@ -491,12 +495,14 @@ xfs_attr_rmtval_set(
 		lblkno += map.br_blockcount;
 		blkcnt -= map.br_blockcount;
 
-		/*
-		 * Start the next trans in the chain.
-		 */
-		error = xfs_trans_roll_inode(&args->trans, dp);
-		if (error)
-			return error;
+		if (roll_trans) {
+			/*
+			 * Start the next trans in the chain.
+			 */
+			error = xfs_trans_roll_inode(&args->trans, dp);
+			if (error)
+				return error;
+		}
 	}
 
 	/*
@@ -559,7 +565,8 @@ out_defer_cancel:
  */
 int
 xfs_attr_rmtval_remove(
-	struct xfs_da_args	*args)
+	struct xfs_da_args	*args,
+	bool			roll_trans)
 {
 	struct xfs_mount	*mp = args->dp->i_mount;
 	xfs_dablk_t		lblkno;
@@ -621,16 +628,19 @@ xfs_attr_rmtval_remove(
 				    XFS_BMAPI_ATTRFORK, 1, &done);
 		if (error)
 			goto out_defer_cancel;
-		error = xfs_defer_finish(&args->trans);
-		if (error)
-			return error;
 
-		/*
-		 * Close out trans and start the next one in the chain.
-		 */
-		error = xfs_trans_roll_inode(&args->trans, args->dp);
-		if (error)
-			return error;
+		if (roll_trans) {
+			error = xfs_defer_finish(&args->trans);
+			if (error)
+				return error;
+
+			/*
+			 * Close out trans and start the next one in the chain.
+			 */
+			error = xfs_trans_roll_inode(&args->trans, args->dp);
+			if (error)
+				return error;
+		}
 	}
 	return 0;
 out_defer_cancel:
diff --git a/libxfs/xfs_attr_remote.h b/libxfs/xfs_attr_remote.h
index 9d20b66..c7c073d 100644
--- a/libxfs/xfs_attr_remote.h
+++ b/libxfs/xfs_attr_remote.h
@@ -9,7 +9,7 @@
 int xfs_attr3_rmt_blocks(struct xfs_mount *mp, int attrlen);
 
 int xfs_attr_rmtval_get(struct xfs_da_args *args);
-int xfs_attr_rmtval_set(struct xfs_da_args *args);
-int xfs_attr_rmtval_remove(struct xfs_da_args *args);
+int xfs_attr_rmtval_set(struct xfs_da_args *args, bool roll_trans);
+int xfs_attr_rmtval_remove(struct xfs_da_args *args, bool roll_trans);
 
 #endif /* __XFS_ATTR_REMOTE_H__ */
