Message ID | 20220414094434.2508781-16-david@fromorbit.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | xfs: LARP - clean up xfs_attr_set_iter state machine | expand |
On Thu, 2022-04-14 at 19:44 +1000, Dave Chinner wrote: > From: Dave Chinner <dchinner@redhat.com> > > In preparation for having a different replace algorithm when LARP > mode is active. > > Signed-off-by: Dave Chinner <dchinner@redhat.com> Looks fine Reviewed-by: Allison Henderson<allison.henderson@oracle.com> > --- > 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;
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;