diff options
Diffstat (limited to 'fs/xfs/libxfs')
-rw-r--r-- | fs/xfs/libxfs/xfs_attr.c | 113 | ||||
-rw-r--r-- | fs/xfs/libxfs/xfs_attr.h | 14 |
2 files changed, 71 insertions, 56 deletions
diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c index d06998d8cbdb..513f0b1a6a4c 100644 --- a/fs/xfs/libxfs/xfs_attr.c +++ b/fs/xfs/libxfs/xfs_attr.c @@ -333,9 +333,11 @@ xfs_attr_leaf_addname( * or perform more xattr manipulations. Otherwise there is nothing more * to do and we can return success. */ - if (args->rmtblkno || - (args->op_flags & XFS_DA_OP_RENAME)) { - attr->xattri_dela_state = XFS_DAS_FOUND_LBLK; + if (args->rmtblkno) { + attr->xattri_dela_state = XFS_DAS_LEAF_SET_RMT; + error = -EAGAIN; + } else if (args->op_flags & XFS_DA_OP_RENAME) { + attr->xattri_dela_state = XFS_DAS_LEAF_REPLACE; error = -EAGAIN; } else { attr->xattri_dela_state = XFS_DAS_DONE; @@ -362,9 +364,11 @@ xfs_attr_node_addname( if (error) return error; - if (args->rmtblkno || - (args->op_flags & XFS_DA_OP_RENAME)) { - attr->xattri_dela_state = XFS_DAS_FOUND_NBLK; + if (args->rmtblkno) { + attr->xattri_dela_state = XFS_DAS_NODE_SET_RMT; + error = -EAGAIN; + } else if (args->op_flags & XFS_DA_OP_RENAME) { + attr->xattri_dela_state = XFS_DAS_NODE_REPLACE; error = -EAGAIN; } else { attr->xattri_dela_state = XFS_DAS_DONE; @@ -374,6 +378,40 @@ xfs_attr_node_addname( return error; } +static int +xfs_attr_rmtval_alloc( + struct xfs_attr_item *attr) +{ + struct xfs_da_args *args = attr->xattri_da_args; + int error = 0; + + /* + * If there was an out-of-line value, allocate the blocks we + * identified for its storage and copy the value. This is done + * after we create the attribute so that we don't overflow the + * maximum size of a transaction and/or hit a deadlock. + */ + if (attr->xattri_blkcnt > 0) { + error = xfs_attr_rmtval_set_blk(attr); + if (error) + return error; + error = -EAGAIN; + goto out; + } + + error = xfs_attr_rmtval_set_value(args); + if (error) + return error; + + /* If this is not a rename, clear the incomplete flag and we're done. */ + if (!(args->op_flags & XFS_DA_OP_RENAME)) { + error = xfs_attr3_leaf_clearflag(args); + attr->xattri_dela_state = XFS_DAS_DONE; + } +out: + trace_xfs_attr_rmtval_alloc(attr->xattri_dela_state, args->dp); + return error; +} /* * Set the attribute specified in @args. @@ -405,54 +443,26 @@ next_state: case XFS_DAS_NODE_ADD: return xfs_attr_node_addname(attr); - case XFS_DAS_FOUND_LBLK: - case XFS_DAS_FOUND_NBLK: - /* - * Find space for remote blocks and fall into the allocation - * state. - */ - if (args->rmtblkno > 0) { - error = xfs_attr_rmtval_find_space(attr); - if (error) - return error; - } + case XFS_DAS_LEAF_SET_RMT: + case XFS_DAS_NODE_SET_RMT: + error = xfs_attr_rmtval_find_space(attr); + if (error) + return error; attr->xattri_dela_state++; fallthrough; + case XFS_DAS_LEAF_ALLOC_RMT: case XFS_DAS_NODE_ALLOC_RMT: - - /* - * If there was an out-of-line value, allocate the blocks we - * identified for its storage and copy the value. This is done - * after we create the attribute so that we don't overflow the - * maximum size of a transaction and/or hit a deadlock. - */ - if (args->rmtblkno > 0) { - if (attr->xattri_blkcnt > 0) { - error = xfs_attr_rmtval_set_blk(attr); - if (error) - return error; - trace_xfs_attr_set_iter_return( - attr->xattri_dela_state, - args->dp); - return -EAGAIN; - } - - error = xfs_attr_rmtval_set_value(args); - if (error) - return error; - } - - /* - * If this is not a rename, clear the incomplete flag and we're - * done. - */ - if (!(args->op_flags & XFS_DA_OP_RENAME)) { - if (args->rmtblkno > 0) - error = xfs_attr3_leaf_clearflag(args); + error = xfs_attr_rmtval_alloc(attr); + if (error) return error; - } + if (attr->xattri_dela_state == XFS_DAS_DONE) + break; + attr->xattri_dela_state++; + fallthrough; + case XFS_DAS_LEAF_REPLACE: + case XFS_DAS_NODE_REPLACE: /* * If this is an atomic rename operation, we must "flip" the * incomplete flags on the "new" and "old" attribute/value pairs @@ -470,10 +480,9 @@ next_state: * Commit the flag value change and start the next trans * in series at FLIP_FLAG. */ + error = -EAGAIN; attr->xattri_dela_state++; - trace_xfs_attr_set_iter_return(attr->xattri_dela_state, - args->dp); - return -EAGAIN; + break; } attr->xattri_dela_state++; @@ -548,6 +557,8 @@ next_state: ASSERT(0); break; } + + trace_xfs_attr_set_iter_return(attr->xattri_dela_state, args->dp); return error; } diff --git a/fs/xfs/libxfs/xfs_attr.h b/fs/xfs/libxfs/xfs_attr.h index 908a13d61716..a0e631df1e24 100644 --- a/fs/xfs/libxfs/xfs_attr.h +++ b/fs/xfs/libxfs/xfs_attr.h @@ -452,15 +452,17 @@ enum xfs_delattr_state { XFS_DAS_RM_SHRINK, /* We are shrinking the tree */ /* Leaf state set sequence */ - XFS_DAS_FOUND_LBLK, /* We found leaf blk for attr */ + XFS_DAS_LEAF_SET_RMT, /* set a remote xattr from a leaf */ XFS_DAS_LEAF_ALLOC_RMT, /* We are allocating remote blocks */ + XFS_DAS_LEAF_REPLACE, /* Perform replace ops on a leaf */ XFS_DAS_FLIP_LFLAG, /* Flipped leaf INCOMPLETE attr flag */ XFS_DAS_RM_LBLK, /* A rename is removing leaf blocks */ XFS_DAS_RD_LEAF, /* Read in the new leaf */ /* Node state set sequence, must match leaf state above */ - XFS_DAS_FOUND_NBLK, /* We found node blk for attr */ + XFS_DAS_NODE_SET_RMT, /* set a remote xattr from a node */ XFS_DAS_NODE_ALLOC_RMT, /* We are allocating remote blocks */ + XFS_DAS_NODE_REPLACE, /* Perform replace ops on a node */ XFS_DAS_FLIP_NFLAG, /* Flipped node INCOMPLETE attr flag */ XFS_DAS_RM_NBLK, /* A rename is removing node blocks */ XFS_DAS_CLR_FLAG, /* Clear incomplete flag */ @@ -476,13 +478,15 @@ enum xfs_delattr_state { { XFS_DAS_RMTBLK, "XFS_DAS_RMTBLK" }, \ { XFS_DAS_RM_NAME, "XFS_DAS_RM_NAME" }, \ { XFS_DAS_RM_SHRINK, "XFS_DAS_RM_SHRINK" }, \ - { XFS_DAS_FOUND_LBLK, "XFS_DAS_FOUND_LBLK" }, \ + { XFS_DAS_LEAF_SET_RMT, "XFS_DAS_LEAF_SET_RMT" }, \ { XFS_DAS_LEAF_ALLOC_RMT, "XFS_DAS_LEAF_ALLOC_RMT" }, \ - { XFS_DAS_FOUND_NBLK, "XFS_DAS_FOUND_NBLK" }, \ - { XFS_DAS_NODE_ALLOC_RMT, "XFS_DAS_NODE_ALLOC_RMT" }, \ + { XFS_DAS_LEAF_REPLACE, "XFS_DAS_LEAF_REPLACE" }, \ { XFS_DAS_FLIP_LFLAG, "XFS_DAS_FLIP_LFLAG" }, \ { XFS_DAS_RM_LBLK, "XFS_DAS_RM_LBLK" }, \ { XFS_DAS_RD_LEAF, "XFS_DAS_RD_LEAF" }, \ + { XFS_DAS_NODE_SET_RMT, "XFS_DAS_NODE_SET_RMT" }, \ + { XFS_DAS_NODE_ALLOC_RMT, "XFS_DAS_NODE_ALLOC_RMT" }, \ + { XFS_DAS_NODE_REPLACE, "XFS_DAS_NODE_REPLACE" }, \ { XFS_DAS_FLIP_NFLAG, "XFS_DAS_FLIP_NFLAG" }, \ { XFS_DAS_RM_NBLK, "XFS_DAS_RM_NBLK" }, \ { XFS_DAS_CLR_FLAG, "XFS_DAS_CLR_FLAG" }, \ |