xfs: Add xfs_attr_set_deferred and xfs_attr_remove_deferred
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> Reviewed-by: Chandan Babu R <chandanrlinux@gmail.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
This commit is contained in:
parent
f38dc503d3
commit
f3f36c893f
4 changed files with 111 additions and 3 deletions
|
@ -25,6 +25,7 @@
|
||||||
#include "xfs_trans_space.h"
|
#include "xfs_trans_space.h"
|
||||||
#include "xfs_trace.h"
|
#include "xfs_trace.h"
|
||||||
#include "xfs_attr_item.h"
|
#include "xfs_attr_item.h"
|
||||||
|
#include "xfs_log.h"
|
||||||
|
|
||||||
struct kmem_cache *xfs_attri_cache;
|
struct kmem_cache *xfs_attri_cache;
|
||||||
struct kmem_cache *xfs_attrd_cache;
|
struct kmem_cache *xfs_attrd_cache;
|
||||||
|
@ -729,6 +730,7 @@ xfs_attr_set(
|
||||||
int error, local;
|
int error, local;
|
||||||
int rmt_blks = 0;
|
int rmt_blks = 0;
|
||||||
unsigned int total;
|
unsigned int total;
|
||||||
|
int delayed = xfs_has_larp(mp);
|
||||||
|
|
||||||
if (xfs_is_shutdown(dp->i_mount))
|
if (xfs_is_shutdown(dp->i_mount))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
@ -785,13 +787,19 @@ xfs_attr_set(
|
||||||
rmt_blks = xfs_attr3_rmt_blocks(mp, XFS_XATTR_SIZE_MAX);
|
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
|
* Root fork attributes can use reserved data blocks for this
|
||||||
* operation if necessary
|
* operation if necessary
|
||||||
*/
|
*/
|
||||||
error = xfs_trans_alloc_inode(dp, &tres, total, 0, rsvd, &args->trans);
|
error = xfs_trans_alloc_inode(dp, &tres, total, 0, rsvd, &args->trans);
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
goto drop_incompat;
|
||||||
|
|
||||||
if (args->value || xfs_inode_hasattr(dp)) {
|
if (args->value || xfs_inode_hasattr(dp)) {
|
||||||
error = xfs_iext_count_may_overflow(dp, XFS_ATTR_FORK,
|
error = xfs_iext_count_may_overflow(dp, XFS_ATTR_FORK,
|
||||||
|
@ -812,9 +820,10 @@ xfs_attr_set(
|
||||||
if (error != -ENOATTR && error != -EEXIST)
|
if (error != -ENOATTR && error != -EEXIST)
|
||||||
goto out_trans_cancel;
|
goto out_trans_cancel;
|
||||||
|
|
||||||
error = xfs_attr_set_args(args);
|
error = xfs_attr_set_deferred(args);
|
||||||
if (error)
|
if (error)
|
||||||
goto out_trans_cancel;
|
goto out_trans_cancel;
|
||||||
|
|
||||||
/* shortform attribute has already been committed */
|
/* shortform attribute has already been committed */
|
||||||
if (!args->trans)
|
if (!args->trans)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
@ -822,7 +831,7 @@ xfs_attr_set(
|
||||||
if (error != -EEXIST)
|
if (error != -EEXIST)
|
||||||
goto out_trans_cancel;
|
goto out_trans_cancel;
|
||||||
|
|
||||||
error = xfs_attr_remove_args(args);
|
error = xfs_attr_remove_deferred(args);
|
||||||
if (error)
|
if (error)
|
||||||
goto out_trans_cancel;
|
goto out_trans_cancel;
|
||||||
}
|
}
|
||||||
|
@ -844,6 +853,9 @@ xfs_attr_set(
|
||||||
error = xfs_trans_commit(args->trans);
|
error = xfs_trans_commit(args->trans);
|
||||||
out_unlock:
|
out_unlock:
|
||||||
xfs_iunlock(dp, XFS_ILOCK_EXCL);
|
xfs_iunlock(dp, XFS_ILOCK_EXCL);
|
||||||
|
drop_incompat:
|
||||||
|
if (delayed)
|
||||||
|
xlog_drop_incompat_feat(mp->m_log);
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
out_trans_cancel:
|
out_trans_cancel:
|
||||||
|
@ -886,6 +898,58 @@ xfs_attrd_destroy_cache(void)
|
||||||
xfs_attrd_cache = NULL;
|
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_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
|
* External routines when attribute list is inside the inode
|
||||||
*========================================================================*/
|
*========================================================================*/
|
||||||
|
|
|
@ -525,6 +525,8 @@ bool xfs_attr_namecheck(const void *name, size_t length);
|
||||||
void xfs_delattr_context_init(struct xfs_delattr_context *dac,
|
void xfs_delattr_context_init(struct xfs_delattr_context *dac,
|
||||||
struct xfs_da_args *args);
|
struct xfs_da_args *args);
|
||||||
int xfs_attr_calc_size(struct xfs_da_args *args, int *local);
|
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);
|
||||||
|
|
||||||
extern struct kmem_cache *xfs_attri_cache;
|
extern struct kmem_cache *xfs_attri_cache;
|
||||||
extern struct kmem_cache *xfs_attrd_cache;
|
extern struct kmem_cache *xfs_attrd_cache;
|
||||||
|
|
|
@ -3877,3 +3877,44 @@ xlog_drop_incompat_feat(
|
||||||
{
|
{
|
||||||
up_read(&log->l_incompat_users);
|
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 (xfs_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;
|
||||||
|
}
|
||||||
|
|
|
@ -153,5 +153,6 @@ bool xlog_force_shutdown(struct xlog *log, uint32_t shutdown_flags);
|
||||||
|
|
||||||
void xlog_use_incompat_feat(struct xlog *log);
|
void xlog_use_incompat_feat(struct xlog *log);
|
||||||
void xlog_drop_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__ */
|
#endif /* __XFS_LOG_H__ */
|
||||||
|
|
Loading…
Add table
Reference in a new issue