Message ID | 20210824224434.968720-7-allison.henderson@oracle.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | Log Attribute Replay | expand |
On 25 Aug 2021 at 04:14, Allison Henderson wrote: > From: Allison Collins <allison.henderson@oracle.com> > > These routines set up and queue a new deferred attribute operations. > These functions are meant to be called by any routine needing to > initiate a deferred attribute operation as opposed to the existing > inline operations. New helper function xfs_attr_item_init also added. > > Finally enable delayed attributes in xfs_attr_set and xfs_attr_remove. > Looks good to me. Reviewed-by: Chandan Babu R <chandanrlinux@gmail.com> > Signed-off-by: Allison Henderson <allison.henderson@oracle.com> > Reviewed-by: Darrick J. Wong <djwong@kernel.org> > --- > fs/xfs/libxfs/xfs_attr.c | 71 ++++++++++++++++++++++++++++++++++++++-- > fs/xfs/libxfs/xfs_attr.h | 2 ++ > fs/xfs/xfs_log.c | 41 +++++++++++++++++++++++ > fs/xfs/xfs_log.h | 1 + > 4 files changed, 112 insertions(+), 3 deletions(-) > > diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c > index fce67c717be2..6877683e2e35 100644 > --- a/fs/xfs/libxfs/xfs_attr.c > +++ b/fs/xfs/libxfs/xfs_attr.c > @@ -25,6 +25,8 @@ > #include "xfs_trans_space.h" > #include "xfs_trace.h" > #include "xfs_attr_item.h" > +#include "xfs_attr.h" > +#include "xfs_log.h" > > /* > * xfs_attr.c > @@ -726,6 +728,7 @@ xfs_attr_set( > int error, local; > int rmt_blks = 0; > unsigned int total; > + int delayed = xfs_has_larp(mp); > > if (xfs_is_shutdown(dp->i_mount)) > return -EIO; > @@ -782,13 +785,19 @@ xfs_attr_set( > rmt_blks = xfs_attr3_rmt_blocks(mp, XFS_XATTR_SIZE_MAX); > } > > + if (delayed) { > + error = xfs_attr_use_log_assist(mp); > + if (error) > + return error; > + } > + > /* > * Root fork attributes can use reserved data blocks for this > * operation if necessary > */ > error = xfs_trans_alloc_inode(dp, &tres, total, 0, rsvd, &args->trans); > if (error) > - return error; > + goto drop_incompat; > > if (args->value || xfs_inode_hasattr(dp)) { > error = xfs_iext_count_may_overflow(dp, XFS_ATTR_FORK, > @@ -806,9 +815,10 @@ xfs_attr_set( > if (error != -ENOATTR && error != -EEXIST) > goto out_trans_cancel; > > - error = xfs_attr_set_args(args); > + error = xfs_attr_set_deferred(args); > if (error) > goto out_trans_cancel; > + > /* shortform attribute has already been committed */ > if (!args->trans) > goto out_unlock; > @@ -816,7 +826,7 @@ xfs_attr_set( > if (error != -EEXIST) > goto out_trans_cancel; > > - error = xfs_attr_remove_args(args); > + error = xfs_attr_remove_deferred(args); > if (error) > goto out_trans_cancel; > } > @@ -838,6 +848,9 @@ xfs_attr_set( > error = xfs_trans_commit(args->trans); > out_unlock: > xfs_iunlock(dp, XFS_ILOCK_EXCL); > +drop_incompat: > + if (delayed) > + xlog_drop_incompat_feat(mp->m_log); > return error; > > out_trans_cancel: > @@ -846,6 +859,58 @@ xfs_attr_set( > goto out_unlock; > } > > +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_dac.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; > + > + 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; > + > + 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 aa33cdcf26b8..0f326c28ab7c 100644 > --- a/fs/xfs/libxfs/xfs_attr.h > +++ b/fs/xfs/libxfs/xfs_attr.h > @@ -526,5 +526,7 @@ bool xfs_attr_namecheck(const void *name, size_t length); > void xfs_delattr_context_init(struct xfs_delattr_context *dac, > struct xfs_da_args *args); > int xfs_attr_calc_size(struct xfs_da_args *args, int *local); > +int xfs_attr_set_deferred(struct xfs_da_args *args); > +int xfs_attr_remove_deferred(struct xfs_da_args *args); > > #endif /* __XFS_ATTR_H__ */ > diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c > index 4402c5d09269..0d0afa1aae59 100644 > --- a/fs/xfs/xfs_log.c > +++ b/fs/xfs/xfs_log.c > @@ -3993,3 +3993,44 @@ xlog_drop_incompat_feat( > { > up_read(&log->l_incompat_users); > } > + > +/* > + * Get permission to use log-assisted atomic exchange of file extents. > + * > + * Callers must not be running any transactions or hold any inode locks, and > + * they must release the permission by calling xlog_drop_incompat_feat > + * when they're done. > + */ > +int > +xfs_attr_use_log_assist( > + struct xfs_mount *mp) > +{ > + int error = 0; > + > + /* > + * Protect ourselves from an idle log clearing the logged xattrs log > + * incompat feature bit. > + */ > + xlog_use_incompat_feat(mp->m_log); > + > + /* > + * If log-assisted xattrs are already enabled, the caller can use the > + * log assisted swap functions with the log-incompat reference we got. > + */ > + if (sb_version_haslogxattrs(&mp->m_sb)) > + return 0; > + > + /* Enable log-assisted xattrs. */ > + error = xfs_add_incompat_log_feature(mp, > + XFS_SB_FEAT_INCOMPAT_LOG_XATTRS); > + if (error) > + goto drop_incompat; > + > + xfs_warn_once(mp, > +"EXPERIMENTAL logged extended attributes feature added. Use at your own risk!"); > + > + return 0; > +drop_incompat: > + xlog_drop_incompat_feat(mp->m_log); > + return error; > +} > diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h > index dc1b77b92fc1..4504ab60ac85 100644 > --- a/fs/xfs/xfs_log.h > +++ b/fs/xfs/xfs_log.h > @@ -144,5 +144,6 @@ bool xlog_force_shutdown(struct xlog *log, int shutdown_flags); > > void xlog_use_incompat_feat(struct xlog *log); > void xlog_drop_incompat_feat(struct xlog *log); > +int xfs_attr_use_log_assist(struct xfs_mount *mp); > > #endif /* __XFS_LOG_H__ */
On 8/30/21 3:27 AM, Chandan Babu R wrote: > On 25 Aug 2021 at 04:14, Allison Henderson wrote: >> From: Allison Collins <allison.henderson@oracle.com> >> >> These routines set up and queue a new deferred attribute operations. >> These functions are meant to be called by any routine needing to >> initiate a deferred attribute operation as opposed to the existing >> inline operations. New helper function xfs_attr_item_init also added. >> >> Finally enable delayed attributes in xfs_attr_set and xfs_attr_remove. >> > > Looks good to me. > > Reviewed-by: Chandan Babu R <chandanrlinux@gmail.com> Thank you! Allison > >> Signed-off-by: Allison Henderson <allison.henderson@oracle.com> >> Reviewed-by: Darrick J. Wong <djwong@kernel.org> >> --- >> fs/xfs/libxfs/xfs_attr.c | 71 ++++++++++++++++++++++++++++++++++++++-- >> fs/xfs/libxfs/xfs_attr.h | 2 ++ >> fs/xfs/xfs_log.c | 41 +++++++++++++++++++++++ >> fs/xfs/xfs_log.h | 1 + >> 4 files changed, 112 insertions(+), 3 deletions(-) >> >> diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c >> index fce67c717be2..6877683e2e35 100644 >> --- a/fs/xfs/libxfs/xfs_attr.c >> +++ b/fs/xfs/libxfs/xfs_attr.c >> @@ -25,6 +25,8 @@ >> #include "xfs_trans_space.h" >> #include "xfs_trace.h" >> #include "xfs_attr_item.h" >> +#include "xfs_attr.h" >> +#include "xfs_log.h" >> >> /* >> * xfs_attr.c >> @@ -726,6 +728,7 @@ xfs_attr_set( >> int error, local; >> int rmt_blks = 0; >> unsigned int total; >> + int delayed = xfs_has_larp(mp); >> >> if (xfs_is_shutdown(dp->i_mount)) >> return -EIO; >> @@ -782,13 +785,19 @@ xfs_attr_set( >> rmt_blks = xfs_attr3_rmt_blocks(mp, XFS_XATTR_SIZE_MAX); >> } >> >> + if (delayed) { >> + error = xfs_attr_use_log_assist(mp); >> + if (error) >> + return error; >> + } >> + >> /* >> * Root fork attributes can use reserved data blocks for this >> * operation if necessary >> */ >> error = xfs_trans_alloc_inode(dp, &tres, total, 0, rsvd, &args->trans); >> if (error) >> - return error; >> + goto drop_incompat; >> >> if (args->value || xfs_inode_hasattr(dp)) { >> error = xfs_iext_count_may_overflow(dp, XFS_ATTR_FORK, >> @@ -806,9 +815,10 @@ xfs_attr_set( >> if (error != -ENOATTR && error != -EEXIST) >> goto out_trans_cancel; >> >> - error = xfs_attr_set_args(args); >> + error = xfs_attr_set_deferred(args); >> if (error) >> goto out_trans_cancel; >> + >> /* shortform attribute has already been committed */ >> if (!args->trans) >> goto out_unlock; >> @@ -816,7 +826,7 @@ xfs_attr_set( >> if (error != -EEXIST) >> goto out_trans_cancel; >> >> - error = xfs_attr_remove_args(args); >> + error = xfs_attr_remove_deferred(args); >> if (error) >> goto out_trans_cancel; >> } >> @@ -838,6 +848,9 @@ xfs_attr_set( >> error = xfs_trans_commit(args->trans); >> out_unlock: >> xfs_iunlock(dp, XFS_ILOCK_EXCL); >> +drop_incompat: >> + if (delayed) >> + xlog_drop_incompat_feat(mp->m_log); >> return error; >> >> out_trans_cancel: >> @@ -846,6 +859,58 @@ xfs_attr_set( >> goto out_unlock; >> } >> >> +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_dac.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; >> + >> + 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; >> + >> + 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 aa33cdcf26b8..0f326c28ab7c 100644 >> --- a/fs/xfs/libxfs/xfs_attr.h >> +++ b/fs/xfs/libxfs/xfs_attr.h >> @@ -526,5 +526,7 @@ bool xfs_attr_namecheck(const void *name, size_t length); >> void xfs_delattr_context_init(struct xfs_delattr_context *dac, >> struct xfs_da_args *args); >> int xfs_attr_calc_size(struct xfs_da_args *args, int *local); >> +int xfs_attr_set_deferred(struct xfs_da_args *args); >> +int xfs_attr_remove_deferred(struct xfs_da_args *args); >> >> #endif /* __XFS_ATTR_H__ */ >> diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c >> index 4402c5d09269..0d0afa1aae59 100644 >> --- a/fs/xfs/xfs_log.c >> +++ b/fs/xfs/xfs_log.c >> @@ -3993,3 +3993,44 @@ xlog_drop_incompat_feat( >> { >> up_read(&log->l_incompat_users); >> } >> + >> +/* >> + * Get permission to use log-assisted atomic exchange of file extents. >> + * >> + * Callers must not be running any transactions or hold any inode locks, and >> + * they must release the permission by calling xlog_drop_incompat_feat >> + * when they're done. >> + */ >> +int >> +xfs_attr_use_log_assist( >> + struct xfs_mount *mp) >> +{ >> + int error = 0; >> + >> + /* >> + * Protect ourselves from an idle log clearing the logged xattrs log >> + * incompat feature bit. >> + */ >> + xlog_use_incompat_feat(mp->m_log); >> + >> + /* >> + * If log-assisted xattrs are already enabled, the caller can use the >> + * log assisted swap functions with the log-incompat reference we got. >> + */ >> + if (sb_version_haslogxattrs(&mp->m_sb)) >> + return 0; >> + >> + /* Enable log-assisted xattrs. */ >> + error = xfs_add_incompat_log_feature(mp, >> + XFS_SB_FEAT_INCOMPAT_LOG_XATTRS); >> + if (error) >> + goto drop_incompat; >> + >> + xfs_warn_once(mp, >> +"EXPERIMENTAL logged extended attributes feature added. Use at your own risk!"); >> + >> + return 0; >> +drop_incompat: >> + xlog_drop_incompat_feat(mp->m_log); >> + return error; >> +} >> diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h >> index dc1b77b92fc1..4504ab60ac85 100644 >> --- a/fs/xfs/xfs_log.h >> +++ b/fs/xfs/xfs_log.h >> @@ -144,5 +144,6 @@ bool xlog_force_shutdown(struct xlog *log, int shutdown_flags); >> >> void xlog_use_incompat_feat(struct xlog *log); >> void xlog_drop_incompat_feat(struct xlog *log); >> +int xfs_attr_use_log_assist(struct xfs_mount *mp); >> >> #endif /* __XFS_LOG_H__ */ > >
On Tue, Aug 24, 2021 at 03:44:29PM -0700, Allison Henderson wrote: > From: Allison Collins <allison.henderson@oracle.com> > > These routines set up and queue a new deferred attribute operations. > These functions are meant to be called by any routine needing to > initiate a deferred attribute operation as opposed to the existing > inline operations. New helper function xfs_attr_item_init also added. > > Finally enable delayed attributes in xfs_attr_set and xfs_attr_remove. > > Signed-off-by: Allison Henderson <allison.henderson@oracle.com> > Reviewed-by: Darrick J. Wong <djwong@kernel.org> ..... > > +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); In transaction context here so we don't need KM_NOFS. > + new->xattri_op_flags = op_flags; > + new->xattri_dac.da_args = args; > + > + *attr = new; > + return 0; > +} Why doesn't this just return the object or NULL on allocation failure? What other error could it ever return? > + > +/* 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; i.e. attri = xfs_attr_item_init(args, XFS_ATTR_OP_FLAGS_SET); if (!attri) return -ENOMEM; > + > + 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; > + > + xfs_defer_add(args->trans, XFS_DEFER_OPS_TYPE_ATTR, &new->xattri_list); > + > + return 0; > +} We really should not use "new" as a variable name. As a general rule, the common pattern set by this file is that xfs_attri_item objects in a function are named "attri". Just because it's newly allocated doesn't mean we should use a different convention for naming xfs_attri_item objects... Cheers, Dave.
On 8/31/21 8:47 PM, Dave Chinner wrote: > On Tue, Aug 24, 2021 at 03:44:29PM -0700, Allison Henderson wrote: >> From: Allison Collins <allison.henderson@oracle.com> >> >> These routines set up and queue a new deferred attribute operations. >> These functions are meant to be called by any routine needing to >> initiate a deferred attribute operation as opposed to the existing >> inline operations. New helper function xfs_attr_item_init also added. >> >> Finally enable delayed attributes in xfs_attr_set and xfs_attr_remove. >> >> Signed-off-by: Allison Henderson <allison.henderson@oracle.com> >> Reviewed-by: Darrick J. Wong <djwong@kernel.org> > ..... >> >> +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); > > In transaction context here so we don't need KM_NOFS. ok, will remove > >> + new->xattri_op_flags = op_flags; >> + new->xattri_dac.da_args = args; >> + >> + *attr = new; >> + return 0; >> +} > > Why doesn't this just return the object or NULL on allocation > failure? What other error could it ever return? I had adopted this function signature just to be consistent with other *_item_init routines at the time. Mostly just trying to be uniform, though they may have changed since. This patch spent some time on the back burner while we were more focused on the state machine refactoring. > >> + >> +/* 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; > > i.e. > attri = xfs_attr_item_init(args, XFS_ATTR_OP_FLAGS_SET); > if (!attri) > return -ENOMEM; > >> + >> + 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; >> + >> + xfs_defer_add(args->trans, XFS_DEFER_OPS_TYPE_ATTR, &new->xattri_list); >> + >> + return 0; >> +} > > We really should not use "new" as a variable name. As a general > rule, the common pattern set by this file is that xfs_attri_item > objects in a function are named "attri". Just because it's newly > allocated doesn't mean we should use a different convention for > naming xfs_attri_item objects... > Ok, I had seen the pattern around and reused it. Will change to attri Allison > Cheers, > > Dave. >
diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c index fce67c717be2..6877683e2e35 100644 --- a/fs/xfs/libxfs/xfs_attr.c +++ b/fs/xfs/libxfs/xfs_attr.c @@ -25,6 +25,8 @@ #include "xfs_trans_space.h" #include "xfs_trace.h" #include "xfs_attr_item.h" +#include "xfs_attr.h" +#include "xfs_log.h" /* * xfs_attr.c @@ -726,6 +728,7 @@ xfs_attr_set( int error, local; int rmt_blks = 0; unsigned int total; + int delayed = xfs_has_larp(mp); if (xfs_is_shutdown(dp->i_mount)) return -EIO; @@ -782,13 +785,19 @@ xfs_attr_set( rmt_blks = xfs_attr3_rmt_blocks(mp, XFS_XATTR_SIZE_MAX); } + if (delayed) { + error = xfs_attr_use_log_assist(mp); + if (error) + return error; + } + /* * Root fork attributes can use reserved data blocks for this * operation if necessary */ error = xfs_trans_alloc_inode(dp, &tres, total, 0, rsvd, &args->trans); if (error) - return error; + goto drop_incompat; if (args->value || xfs_inode_hasattr(dp)) { error = xfs_iext_count_may_overflow(dp, XFS_ATTR_FORK, @@ -806,9 +815,10 @@ xfs_attr_set( if (error != -ENOATTR && error != -EEXIST) goto out_trans_cancel; - error = xfs_attr_set_args(args); + error = xfs_attr_set_deferred(args); if (error) goto out_trans_cancel; + /* shortform attribute has already been committed */ if (!args->trans) goto out_unlock; @@ -816,7 +826,7 @@ xfs_attr_set( if (error != -EEXIST) goto out_trans_cancel; - error = xfs_attr_remove_args(args); + error = xfs_attr_remove_deferred(args); if (error) goto out_trans_cancel; } @@ -838,6 +848,9 @@ xfs_attr_set( error = xfs_trans_commit(args->trans); out_unlock: xfs_iunlock(dp, XFS_ILOCK_EXCL); +drop_incompat: + if (delayed) + xlog_drop_incompat_feat(mp->m_log); return error; out_trans_cancel: @@ -846,6 +859,58 @@ xfs_attr_set( goto out_unlock; } +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_dac.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; + + 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; + + 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 aa33cdcf26b8..0f326c28ab7c 100644 --- a/fs/xfs/libxfs/xfs_attr.h +++ b/fs/xfs/libxfs/xfs_attr.h @@ -526,5 +526,7 @@ bool xfs_attr_namecheck(const void *name, size_t length); void xfs_delattr_context_init(struct xfs_delattr_context *dac, struct xfs_da_args *args); int xfs_attr_calc_size(struct xfs_da_args *args, int *local); +int xfs_attr_set_deferred(struct xfs_da_args *args); +int xfs_attr_remove_deferred(struct xfs_da_args *args); #endif /* __XFS_ATTR_H__ */ diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 4402c5d09269..0d0afa1aae59 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -3993,3 +3993,44 @@ xlog_drop_incompat_feat( { up_read(&log->l_incompat_users); } + +/* + * Get permission to use log-assisted atomic exchange of file extents. + * + * Callers must not be running any transactions or hold any inode locks, and + * they must release the permission by calling xlog_drop_incompat_feat + * when they're done. + */ +int +xfs_attr_use_log_assist( + struct xfs_mount *mp) +{ + int error = 0; + + /* + * Protect ourselves from an idle log clearing the logged xattrs log + * incompat feature bit. + */ + xlog_use_incompat_feat(mp->m_log); + + /* + * If log-assisted xattrs are already enabled, the caller can use the + * log assisted swap functions with the log-incompat reference we got. + */ + if (sb_version_haslogxattrs(&mp->m_sb)) + return 0; + + /* Enable log-assisted xattrs. */ + error = xfs_add_incompat_log_feature(mp, + XFS_SB_FEAT_INCOMPAT_LOG_XATTRS); + if (error) + goto drop_incompat; + + xfs_warn_once(mp, +"EXPERIMENTAL logged extended attributes feature added. Use at your own risk!"); + + return 0; +drop_incompat: + xlog_drop_incompat_feat(mp->m_log); + return error; +} diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h index dc1b77b92fc1..4504ab60ac85 100644 --- a/fs/xfs/xfs_log.h +++ b/fs/xfs/xfs_log.h @@ -144,5 +144,6 @@ bool xlog_force_shutdown(struct xlog *log, int shutdown_flags); void xlog_use_incompat_feat(struct xlog *log); void xlog_drop_incompat_feat(struct xlog *log); +int xfs_attr_use_log_assist(struct xfs_mount *mp); #endif /* __XFS_LOG_H__ */