diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c index e53d726480fb..af578ce7b8bb 100644 --- a/fs/xfs/libxfs/xfs_attr.c +++ b/fs/xfs/libxfs/xfs_attr.c @@ -286,6 +286,65 @@ xfs_attr_sf_addname( return -EAGAIN; } +STATIC int +xfs_attr_leaf_addname( + struct xfs_attr_item *attr) +{ + struct xfs_da_args *args = attr->xattri_da_args; + struct xfs_inode *dp = args->dp; + int error; + + if (xfs_attr_is_leaf(dp)) { + error = xfs_attr_leaf_try_add(args, attr->xattri_leaf_bp); + if (error == -ENOSPC) { + error = xfs_attr3_leaf_to_node(args); + if (error) + return error; + + /* + * Finish any deferred work items and roll the + * transaction once more. The goal here is to call + * node_addname with the inode and transaction in the + * same state (inode locked and joined, transaction + * clean) no matter how we got to this step. + * + * At this point, we are still in XFS_DAS_UNINIT, but + * when we come back, we'll be a node, so we'll fall + * down into the node handling code below + */ + trace_xfs_attr_set_iter_return( + attr->xattri_dela_state, args->dp); + return -EAGAIN; + } + + if (error) + return error; + + attr->xattri_dela_state = XFS_DAS_FOUND_LBLK; + } else { + error = xfs_attr_node_addname_find_attr(attr); + if (error) + return error; + + error = xfs_attr_node_addname(attr); + if (error) + return error; + + /* + * If addname was successful, and we dont need to alloc or + * remove anymore blks, we're done. + */ + if (!args->rmtblkno && + !(args->op_flags & XFS_DA_OP_RENAME)) + return 0; + + attr->xattri_dela_state = XFS_DAS_FOUND_NBLK; + } + + trace_xfs_attr_leaf_addname_return(attr->xattri_dela_state, args->dp); + return -EAGAIN; +} + /* * Set the attribute specified in @args. * This routine is meant to function as a delayed operation, and may return @@ -321,57 +380,8 @@ xfs_attr_set_iter( attr->xattri_leaf_bp = NULL; } - if (xfs_attr_is_leaf(dp)) { - error = xfs_attr_leaf_try_add(args, - attr->xattri_leaf_bp); - if (error == -ENOSPC) { - error = xfs_attr3_leaf_to_node(args); - if (error) - return error; + return xfs_attr_leaf_addname(attr); - /* - * Finish any deferred work items and roll the - * transaction once more. The goal here is to - * call node_addname with the inode and - * transaction in the same state (inode locked - * and joined, transaction clean) no matter how - * we got to this step. - * - * At this point, we are still in - * XFS_DAS_UNINIT, but when we come back, we'll - * be a node, so we'll fall down into the node - * handling code below - */ - trace_xfs_attr_set_iter_return( - attr->xattri_dela_state, args->dp); - return -EAGAIN; - } else if (error) { - return error; - } - - attr->xattri_dela_state = XFS_DAS_FOUND_LBLK; - } else { - error = xfs_attr_node_addname_find_attr(attr); - if (error) - return error; - - error = xfs_attr_node_addname(attr); - if (error) - return error; - - /* - * If addname was successful, and we dont need to alloc - * or remove anymore blks, we're done. - */ - if (!args->rmtblkno && - !(args->op_flags & XFS_DA_OP_RENAME)) - return 0; - - attr->xattri_dela_state = XFS_DAS_FOUND_NBLK; - } - trace_xfs_attr_set_iter_return(attr->xattri_dela_state, - args->dp); - return -EAGAIN; case XFS_DAS_FOUND_LBLK: /* * If there was an out-of-line value, allocate the blocks we diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index e19a3f7351be..fec4198b738b 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -4150,6 +4150,7 @@ DEFINE_EVENT(xfs_das_state_class, name, \ TP_ARGS(das, ip)) DEFINE_DAS_STATE_EVENT(xfs_attr_sf_addname_return); DEFINE_DAS_STATE_EVENT(xfs_attr_set_iter_return); +DEFINE_DAS_STATE_EVENT(xfs_attr_leaf_addname_return); DEFINE_DAS_STATE_EVENT(xfs_attr_node_addname_return); DEFINE_DAS_STATE_EVENT(xfs_attr_remove_iter_return); DEFINE_DAS_STATE_EVENT(xfs_attr_rmtval_remove_return);