From: Dave Chinner <dchinner@xxxxxxxxxx> In preparation for having a different replace algorithm when LARP mode is active. Signed-off-by: Dave Chinner <dchinner@xxxxxxxxxx> --- fs/xfs/libxfs/xfs_attr.c | 194 ++++++++++++++++++++++----------------- fs/xfs/libxfs/xfs_attr.h | 2 - 2 files changed, 112 insertions(+), 84 deletions(-) diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c index 34c31077b08f..772506d44bfa 100644 --- a/fs/xfs/libxfs/xfs_attr.c +++ b/fs/xfs/libxfs/xfs_attr.c @@ -724,6 +724,96 @@ xfs_attr_lookup( return xfs_attr_node_hasname(args, NULL); } +static int +xfs_attr_item_init( + struct xfs_da_args *args, + unsigned int op_flags, /* op flag (set or remove) */ + struct xfs_attr_item **attr) /* new xfs_attr_item */ +{ + + struct xfs_attr_item *new; + + new = kmem_zalloc(sizeof(struct xfs_attr_item), KM_NOFS); + new->xattri_op_flags = op_flags; + new->xattri_da_args = args; + + *attr = new; + return 0; +} + +/* Sets an attribute for an inode as a deferred operation */ +static int +xfs_attr_defer_add( + struct xfs_da_args *args) +{ + struct xfs_attr_item *new; + int error = 0; + + error = xfs_attr_item_init(args, XFS_ATTR_OP_FLAGS_SET, &new); + if (error) + return error; + + if (xfs_attr_is_shortform(args->dp)) + new->xattri_dela_state = XFS_DAS_SF_ADD; + else if (xfs_attr_is_leaf(args->dp)) + new->xattri_dela_state = XFS_DAS_LEAF_ADD; + else + new->xattri_dela_state = XFS_DAS_NODE_ADD; + + xfs_defer_add(args->trans, XFS_DEFER_OPS_TYPE_ATTR, &new->xattri_list); + + return 0; +} + +/* Sets an attribute for an inode as a deferred operation */ +static int +xfs_attr_defer_replace( + struct xfs_da_args *args) +{ + struct xfs_attr_item *new; + int error = 0; + + error = xfs_attr_item_init(args, XFS_ATTR_OP_FLAGS_SET, &new); + if (error) + return error; + + if (xfs_attr_is_shortform(args->dp)) + new->xattri_dela_state = XFS_DAS_SF_ADD; + else if (xfs_attr_is_leaf(args->dp)) + new->xattri_dela_state = XFS_DAS_LEAF_ADD; + else + new->xattri_dela_state = XFS_DAS_NODE_ADD; + + xfs_defer_add(args->trans, XFS_DEFER_OPS_TYPE_ATTR, &new->xattri_list); + + return 0; +} + +/* Removes an attribute for an inode as a deferred operation */ +static int +xfs_attr_defer_remove( + struct xfs_da_args *args) +{ + + struct xfs_attr_item *new; + int error; + + error = xfs_attr_item_init(args, XFS_ATTR_OP_FLAGS_REMOVE, &new); + if (error) + return error; + + if (xfs_attr_is_shortform(args->dp)) + new->xattri_dela_state = XFS_DAS_SF_REMOVE; + else if (xfs_attr_is_leaf(args->dp)) + new->xattri_dela_state = XFS_DAS_LEAF_REMOVE; + else + new->xattri_dela_state = XFS_DAS_NODE_REMOVE; + + xfs_defer_add(args->trans, XFS_DEFER_OPS_TYPE_ATTR, &new->xattri_list); + + return 0; +} + /* * Note: If args->value is NULL the attribute will be removed, just like the * Linux ->setattr API. @@ -812,29 +902,35 @@ xfs_attr_set( } error = xfs_attr_lookup(args); - if (args->value) { - if (error == -EEXIST && (args->attr_flags & XATTR_CREATE)) - goto out_trans_cancel; - if (error == -ENOATTR && (args->attr_flags & XATTR_REPLACE)) - goto out_trans_cancel; - if (error != -ENOATTR && error != -EEXIST) + switch (error) { + case -EEXIST: + /* if no value, we are performing a remove operation */ + if (!args->value) { + error = xfs_attr_defer_remove(args); + break; + } + /* Pure create fails if the attr already exists */ + if (args->attr_flags & XATTR_CREATE) goto out_trans_cancel; - error = xfs_attr_set_deferred(args); - if (error) + error = xfs_attr_defer_replace(args); + break; + case -ENOATTR: + /* Can't remove what isn't there. */ + if (!args->value) goto out_trans_cancel; - /* shortform attribute has already been committed */ - if (!args->trans) - goto out_unlock; - } else { - if (error != -EEXIST) + /* Pure replace fails if no existing attr to replace. */ + if (args->attr_flags & XATTR_REPLACE) goto out_trans_cancel; - error = xfs_attr_remove_deferred(args); - if (error) - goto out_trans_cancel; + error = xfs_attr_defer_add(args); + break; + default: + goto out_trans_cancel; } + if (error) + goto out_trans_cancel; /* * If this is a synchronous mount, make sure that the @@ -898,72 +994,6 @@ xfs_attrd_destroy_cache(void) xfs_attrd_cache = NULL; } -STATIC int -xfs_attr_item_init( - struct xfs_da_args *args, - unsigned int op_flags, /* op flag (set or remove) */ - struct xfs_attr_item **attr) /* new xfs_attr_item */ -{ - - struct xfs_attr_item *new; - - new = kmem_zalloc(sizeof(struct xfs_attr_item), KM_NOFS); - new->xattri_op_flags = op_flags; - new->xattri_da_args = args; - - *attr = new; - return 0; -} - -/* Sets an attribute for an inode as a deferred operation */ -int -xfs_attr_set_deferred( - struct xfs_da_args *args) -{ - struct xfs_attr_item *new; - int error = 0; - - error = xfs_attr_item_init(args, XFS_ATTR_OP_FLAGS_SET, &new); - if (error) - return error; - - if (xfs_attr_is_shortform(args->dp)) - new->xattri_dela_state = XFS_DAS_SF_ADD; - else if (xfs_attr_is_leaf(args->dp)) - new->xattri_dela_state = XFS_DAS_LEAF_ADD; - else - new->xattri_dela_state = XFS_DAS_NODE_ADD; - - xfs_defer_add(args->trans, XFS_DEFER_OPS_TYPE_ATTR, &new->xattri_list); - - return 0; -} - -/* Removes an attribute for an inode as a deferred operation */ -int -xfs_attr_remove_deferred( - struct xfs_da_args *args) -{ - - struct xfs_attr_item *new; - int error; - - error = xfs_attr_item_init(args, XFS_ATTR_OP_FLAGS_REMOVE, &new); - if (error) - return error; - - if (xfs_attr_is_shortform(args->dp)) - new->xattri_dela_state = XFS_DAS_SF_REMOVE; - else if (xfs_attr_is_leaf(args->dp)) - new->xattri_dela_state = XFS_DAS_LEAF_REMOVE; - else - new->xattri_dela_state = XFS_DAS_NODE_REMOVE; - - xfs_defer_add(args->trans, XFS_DEFER_OPS_TYPE_ATTR, &new->xattri_list); - - return 0; -} - /*======================================================================== * External routines when attribute list is inside the inode *========================================================================*/ diff --git a/fs/xfs/libxfs/xfs_attr.h b/fs/xfs/libxfs/xfs_attr.h index e4b11ac243d7..cac7dfcf2dbe 100644 --- a/fs/xfs/libxfs/xfs_attr.h +++ b/fs/xfs/libxfs/xfs_attr.h @@ -559,8 +559,6 @@ bool xfs_attr_namecheck(const void *name, size_t length); int xfs_attr_calc_size(struct xfs_da_args *args, int *local); void xfs_init_attr_trans(struct xfs_da_args *args, struct xfs_trans_res *tres, unsigned int *total); -int xfs_attr_set_deferred(struct xfs_da_args *args); -int xfs_attr_remove_deferred(struct xfs_da_args *args); extern struct kmem_cache *xfs_attri_cache; extern struct kmem_cache *xfs_attrd_cache; -- 2.35.1