Commit d7d02f75 authored by Chandan Babu R's avatar Chandan Babu R

Merge tag 'improve-attr-validation-6.10_2024-04-23' of...

Merge tag 'improve-attr-validation-6.10_2024-04-23' of https://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux into xfs-6.10-mergeC

xfs: improve extended attribute validation

Prior to introducing parent pointer extended attributes, let's spend
some time cleaning up the attr code and strengthening the validation
that it performs on attrs coming in from the disk.
Signed-off-by: default avatarDarrick J. Wong <djwong@kernel.org>
Signed-off-by: default avatarChandan Babu R <chandanbabu@kernel.org>

* tag 'improve-attr-validation-6.10_2024-04-23' of https://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux:
  xfs: enforce one namespace per attribute
  xfs: refactor name/value iovec validation in xlog_recover_attri_commit_pass2
  xfs: refactor name/length checks in xfs_attri_validate
  xfs: use local variables for name and value length in _attri_commit_pass2
  xfs: always set args->value in xfs_attri_item_recover
  xfs: validate recovered name buffers when recovering xattr items
  xfs: use helpers to extract xattr op from opflags
  xfs: restructure xfs_attr_complete_op a bit
  xfs: check shortform attr entry flags specifically
  xfs: fix missing check for invalid attr flags
  xfs: check opcode and iovec count match in xlog_recover_attri_commit_pass2
  xfs: use an XFS_OPSTATE_ flag for detecting if logged xattrs are available
  xfs: require XFS_SB_FEAT_INCOMPAT_LOG_XATTRS for attr log intent item recovery
  xfs: attr fork iext must be loaded before calling xfs_attr_is_leaf
parents 1321890a ea0b3e81
...@@ -87,6 +87,8 @@ xfs_attr_is_leaf( ...@@ -87,6 +87,8 @@ xfs_attr_is_leaf(
struct xfs_iext_cursor icur; struct xfs_iext_cursor icur;
struct xfs_bmbt_irec imap; struct xfs_bmbt_irec imap;
ASSERT(!xfs_need_iread_extents(ifp));
if (ifp->if_nextents != 1 || ifp->if_format != XFS_DINODE_FMT_EXTENTS) if (ifp->if_nextents != 1 || ifp->if_format != XFS_DINODE_FMT_EXTENTS)
return false; return false;
...@@ -224,11 +226,21 @@ int ...@@ -224,11 +226,21 @@ int
xfs_attr_get_ilocked( xfs_attr_get_ilocked(
struct xfs_da_args *args) struct xfs_da_args *args)
{ {
int error;
xfs_assert_ilocked(args->dp, XFS_ILOCK_SHARED | XFS_ILOCK_EXCL); xfs_assert_ilocked(args->dp, XFS_ILOCK_SHARED | XFS_ILOCK_EXCL);
if (!xfs_inode_hasattr(args->dp)) if (!xfs_inode_hasattr(args->dp))
return -ENOATTR; return -ENOATTR;
/*
* The incore attr fork iext tree must be loaded for xfs_attr_is_leaf
* to work correctly.
*/
error = xfs_iread_extents(args->trans, args->dp, XFS_ATTR_FORK);
if (error)
return error;
if (args->dp->i_af.if_format == XFS_DINODE_FMT_LOCAL) if (args->dp->i_af.if_format == XFS_DINODE_FMT_LOCAL)
return xfs_attr_shortform_getvalue(args); return xfs_attr_shortform_getvalue(args);
if (xfs_attr_is_leaf(args->dp)) if (xfs_attr_is_leaf(args->dp))
...@@ -420,14 +432,13 @@ xfs_attr_complete_op( ...@@ -420,14 +432,13 @@ xfs_attr_complete_op(
enum xfs_delattr_state replace_state) enum xfs_delattr_state replace_state)
{ {
struct xfs_da_args *args = attr->xattri_da_args; struct xfs_da_args *args = attr->xattri_da_args;
bool do_replace = args->op_flags & XFS_DA_OP_REPLACE;
if (!(args->op_flags & XFS_DA_OP_REPLACE))
replace_state = XFS_DAS_DONE;
args->op_flags &= ~XFS_DA_OP_REPLACE; args->op_flags &= ~XFS_DA_OP_REPLACE;
args->attr_filter &= ~XFS_ATTR_INCOMPLETE; args->attr_filter &= ~XFS_ATTR_INCOMPLETE;
if (do_replace) return replace_state;
return replace_state;
return XFS_DAS_DONE;
} }
static int static int
...@@ -870,6 +881,11 @@ xfs_attr_lookup( ...@@ -870,6 +881,11 @@ xfs_attr_lookup(
return -ENOATTR; return -ENOATTR;
} }
/* Prerequisite for xfs_attr_is_leaf */
error = xfs_iread_extents(args->trans, args->dp, XFS_ATTR_FORK);
if (error)
return error;
if (xfs_attr_is_leaf(dp)) { if (xfs_attr_is_leaf(dp)) {
error = xfs_attr_leaf_hasname(args, &bp); error = xfs_attr_leaf_hasname(args, &bp);
...@@ -1516,12 +1532,23 @@ xfs_attr_node_get( ...@@ -1516,12 +1532,23 @@ xfs_attr_node_get(
return error; return error;
} }
/* Enforce that there is at most one namespace bit per attr. */
inline bool xfs_attr_check_namespace(unsigned int attr_flags)
{
return hweight32(attr_flags & XFS_ATTR_NSP_ONDISK_MASK) < 2;
}
/* Returns true if the attribute entry name is valid. */ /* Returns true if the attribute entry name is valid. */
bool bool
xfs_attr_namecheck( xfs_attr_namecheck(
unsigned int attr_flags,
const void *name, const void *name,
size_t length) size_t length)
{ {
/* Only one namespace bit allowed. */
if (!xfs_attr_check_namespace(attr_flags))
return false;
/* /*
* MAXNAMELEN includes the trailing null, but (name/length) leave it * MAXNAMELEN includes the trailing null, but (name/length) leave it
* out, so use >= for the length check. * out, so use >= for the length check.
......
...@@ -529,6 +529,11 @@ struct xfs_attr_intent { ...@@ -529,6 +529,11 @@ struct xfs_attr_intent {
struct xfs_bmbt_irec xattri_map; struct xfs_bmbt_irec xattri_map;
}; };
static inline unsigned int
xfs_attr_intent_op(const struct xfs_attr_intent *attr)
{
return attr->xattri_op_flags & XFS_ATTRI_OP_FLAGS_TYPE_MASK;
}
/*======================================================================== /*========================================================================
* Function prototypes for the kernel. * Function prototypes for the kernel.
...@@ -555,7 +560,9 @@ enum xfs_attr_update { ...@@ -555,7 +560,9 @@ enum xfs_attr_update {
int xfs_attr_set(struct xfs_da_args *args, enum xfs_attr_update op); int xfs_attr_set(struct xfs_da_args *args, enum xfs_attr_update op);
int xfs_attr_set_iter(struct xfs_attr_intent *attr); int xfs_attr_set_iter(struct xfs_attr_intent *attr);
int xfs_attr_remove_iter(struct xfs_attr_intent *attr); int xfs_attr_remove_iter(struct xfs_attr_intent *attr);
bool xfs_attr_namecheck(const void *name, size_t length); bool xfs_attr_check_namespace(unsigned int attr_flags);
bool xfs_attr_namecheck(unsigned int attr_flags, const void *name,
size_t length);
int xfs_attr_calc_size(struct xfs_da_args *args, int *local); 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, void xfs_init_attr_trans(struct xfs_da_args *args, struct xfs_trans_res *tres,
unsigned int *total); unsigned int *total);
......
...@@ -950,6 +950,11 @@ xfs_attr_shortform_to_leaf( ...@@ -950,6 +950,11 @@ xfs_attr_shortform_to_leaf(
nargs.hashval = xfs_da_hashname(sfe->nameval, nargs.hashval = xfs_da_hashname(sfe->nameval,
sfe->namelen); sfe->namelen);
nargs.attr_filter = sfe->flags & XFS_ATTR_NSP_ONDISK_MASK; nargs.attr_filter = sfe->flags & XFS_ATTR_NSP_ONDISK_MASK;
if (!xfs_attr_check_namespace(sfe->flags)) {
xfs_da_mark_sick(args);
error = -EFSCORRUPTED;
goto out;
}
error = xfs_attr3_leaf_lookup_int(bp, &nargs); /* set a->index */ error = xfs_attr3_leaf_lookup_int(bp, &nargs); /* set a->index */
ASSERT(error == -ENOATTR); ASSERT(error == -ENOATTR);
error = xfs_attr3_leaf_add(bp, &nargs); error = xfs_attr3_leaf_add(bp, &nargs);
...@@ -1063,7 +1068,7 @@ xfs_attr_shortform_verify( ...@@ -1063,7 +1068,7 @@ xfs_attr_shortform_verify(
* one namespace flag per xattr, so we can just count the * one namespace flag per xattr, so we can just count the
* bits (i.e. hweight) here. * bits (i.e. hweight) here.
*/ */
if (hweight8(sfep->flags & XFS_ATTR_NSP_ONDISK_MASK) > 1) if (!xfs_attr_check_namespace(sfep->flags))
return __this_address; return __this_address;
sfep = next_sfep; sfep = next_sfep;
......
...@@ -719,8 +719,13 @@ struct xfs_attr3_leafblock { ...@@ -719,8 +719,13 @@ struct xfs_attr3_leafblock {
#define XFS_ATTR_ROOT (1u << XFS_ATTR_ROOT_BIT) #define XFS_ATTR_ROOT (1u << XFS_ATTR_ROOT_BIT)
#define XFS_ATTR_SECURE (1u << XFS_ATTR_SECURE_BIT) #define XFS_ATTR_SECURE (1u << XFS_ATTR_SECURE_BIT)
#define XFS_ATTR_INCOMPLETE (1u << XFS_ATTR_INCOMPLETE_BIT) #define XFS_ATTR_INCOMPLETE (1u << XFS_ATTR_INCOMPLETE_BIT)
#define XFS_ATTR_NSP_ONDISK_MASK (XFS_ATTR_ROOT | XFS_ATTR_SECURE) #define XFS_ATTR_NSP_ONDISK_MASK (XFS_ATTR_ROOT | XFS_ATTR_SECURE)
#define XFS_ATTR_ONDISK_MASK (XFS_ATTR_NSP_ONDISK_MASK | \
XFS_ATTR_LOCAL | \
XFS_ATTR_INCOMPLETE)
#define XFS_ATTR_NAMESPACE_STR \ #define XFS_ATTR_NAMESPACE_STR \
{ XFS_ATTR_LOCAL, "local" }, \ { XFS_ATTR_LOCAL, "local" }, \
{ XFS_ATTR_ROOT, "root" }, \ { XFS_ATTR_ROOT, "root" }, \
......
...@@ -192,20 +192,19 @@ xchk_xattr_actor( ...@@ -192,20 +192,19 @@ xchk_xattr_actor(
if (xchk_should_terminate(sc, &error)) if (xchk_should_terminate(sc, &error))
return error; return error;
if (attr_flags & ~XFS_ATTR_ONDISK_MASK) {
xchk_fblock_set_corrupt(sc, XFS_ATTR_FORK, args.blkno);
return -ECANCELED;
}
if (attr_flags & XFS_ATTR_INCOMPLETE) { if (attr_flags & XFS_ATTR_INCOMPLETE) {
/* Incomplete attr key, just mark the inode for preening. */ /* Incomplete attr key, just mark the inode for preening. */
xchk_ino_set_preen(sc, ip->i_ino); xchk_ino_set_preen(sc, ip->i_ino);
return 0; return 0;
} }
/* Only one namespace bit allowed. */
if (hweight32(attr_flags & XFS_ATTR_NSP_ONDISK_MASK) > 1) {
xchk_fblock_set_corrupt(sc, XFS_ATTR_FORK, args.blkno);
return -ECANCELED;
}
/* Does this name make sense? */ /* Does this name make sense? */
if (!xfs_attr_namecheck(name, namelen)) { if (!xfs_attr_namecheck(attr_flags, name, namelen)) {
xchk_fblock_set_corrupt(sc, XFS_ATTR_FORK, args.blkno); xchk_fblock_set_corrupt(sc, XFS_ATTR_FORK, args.blkno);
return -ECANCELED; return -ECANCELED;
} }
...@@ -481,7 +480,6 @@ xchk_xattr_rec( ...@@ -481,7 +480,6 @@ xchk_xattr_rec(
xfs_dahash_t hash; xfs_dahash_t hash;
int nameidx; int nameidx;
int hdrsize; int hdrsize;
unsigned int badflags;
int error; int error;
ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC); ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
...@@ -511,10 +509,15 @@ xchk_xattr_rec( ...@@ -511,10 +509,15 @@ xchk_xattr_rec(
/* Retrieve the entry and check it. */ /* Retrieve the entry and check it. */
hash = be32_to_cpu(ent->hashval); hash = be32_to_cpu(ent->hashval);
badflags = ~(XFS_ATTR_LOCAL | XFS_ATTR_ROOT | XFS_ATTR_SECURE | if (ent->flags & ~XFS_ATTR_ONDISK_MASK) {
XFS_ATTR_INCOMPLETE); xchk_da_set_corrupt(ds, level);
if ((ent->flags & badflags) != 0) return 0;
}
if (!xfs_attr_check_namespace(ent->flags)) {
xchk_da_set_corrupt(ds, level); xchk_da_set_corrupt(ds, level);
return 0;
}
if (ent->flags & XFS_ATTR_LOCAL) { if (ent->flags & XFS_ATTR_LOCAL) {
lentry = (struct xfs_attr_leaf_name_local *) lentry = (struct xfs_attr_leaf_name_local *)
(((char *)bp->b_addr) + nameidx); (((char *)bp->b_addr) + nameidx);
...@@ -574,6 +577,15 @@ xchk_xattr_check_sf( ...@@ -574,6 +577,15 @@ xchk_xattr_check_sf(
break; break;
} }
/*
* Shortform entries do not set LOCAL or INCOMPLETE, so the
* only valid flag bits here are for namespaces.
*/
if (sfe->flags & ~XFS_ATTR_NSP_ONDISK_MASK) {
xchk_fblock_set_corrupt(sc, XFS_ATTR_FORK, 0);
break;
}
if (!xchk_xattr_set_map(sc, ab->usedmap, if (!xchk_xattr_set_map(sc, ab->usedmap,
(char *)sfe - (char *)sf, (char *)sfe - (char *)sf,
sizeof(struct xfs_attr_sf_entry))) { sizeof(struct xfs_attr_sf_entry))) {
......
...@@ -123,12 +123,10 @@ xrep_xattr_want_salvage( ...@@ -123,12 +123,10 @@ xrep_xattr_want_salvage(
return false; return false;
if (namelen > XATTR_NAME_MAX || namelen <= 0) if (namelen > XATTR_NAME_MAX || namelen <= 0)
return false; return false;
if (!xfs_attr_namecheck(name, namelen)) if (!xfs_attr_namecheck(attr_flags, name, namelen))
return false; return false;
if (valuelen > XATTR_SIZE_MAX || valuelen < 0) if (valuelen > XATTR_SIZE_MAX || valuelen < 0)
return false; return false;
if (hweight32(attr_flags & XFS_ATTR_NSP_ONDISK_MASK) > 1)
return false;
return true; return true;
} }
......
This diff is collapsed.
...@@ -82,7 +82,8 @@ xfs_attr_shortform_list( ...@@ -82,7 +82,8 @@ xfs_attr_shortform_list(
(dp->i_af.if_bytes + sf->count * 16) < context->bufsize)) { (dp->i_af.if_bytes + sf->count * 16) < context->bufsize)) {
for (i = 0, sfe = xfs_attr_sf_firstentry(sf); i < sf->count; i++) { for (i = 0, sfe = xfs_attr_sf_firstentry(sf); i < sf->count; i++) {
if (XFS_IS_CORRUPT(context->dp->i_mount, if (XFS_IS_CORRUPT(context->dp->i_mount,
!xfs_attr_namecheck(sfe->nameval, !xfs_attr_namecheck(sfe->flags,
sfe->nameval,
sfe->namelen))) { sfe->namelen))) {
xfs_dirattr_mark_sick(context->dp, XFS_ATTR_FORK); xfs_dirattr_mark_sick(context->dp, XFS_ATTR_FORK);
return -EFSCORRUPTED; return -EFSCORRUPTED;
...@@ -122,7 +123,8 @@ xfs_attr_shortform_list( ...@@ -122,7 +123,8 @@ xfs_attr_shortform_list(
for (i = 0, sfe = xfs_attr_sf_firstentry(sf); i < sf->count; i++) { for (i = 0, sfe = xfs_attr_sf_firstentry(sf); i < sf->count; i++) {
if (unlikely( if (unlikely(
((char *)sfe < (char *)sf) || ((char *)sfe < (char *)sf) ||
((char *)sfe >= ((char *)sf + dp->i_af.if_bytes)))) { ((char *)sfe >= ((char *)sf + dp->i_af.if_bytes)) ||
!xfs_attr_check_namespace(sfe->flags))) {
XFS_CORRUPTION_ERROR("xfs_attr_shortform_list", XFS_CORRUPTION_ERROR("xfs_attr_shortform_list",
XFS_ERRLEVEL_LOW, XFS_ERRLEVEL_LOW,
context->dp->i_mount, sfe, context->dp->i_mount, sfe,
...@@ -177,7 +179,7 @@ xfs_attr_shortform_list( ...@@ -177,7 +179,7 @@ xfs_attr_shortform_list(
cursor->offset = 0; cursor->offset = 0;
} }
if (XFS_IS_CORRUPT(context->dp->i_mount, if (XFS_IS_CORRUPT(context->dp->i_mount,
!xfs_attr_namecheck(sbp->name, !xfs_attr_namecheck(sbp->flags, sbp->name,
sbp->namelen))) { sbp->namelen))) {
xfs_dirattr_mark_sick(context->dp, XFS_ATTR_FORK); xfs_dirattr_mark_sick(context->dp, XFS_ATTR_FORK);
error = -EFSCORRUPTED; error = -EFSCORRUPTED;
...@@ -502,7 +504,8 @@ xfs_attr3_leaf_list_int( ...@@ -502,7 +504,8 @@ xfs_attr3_leaf_list_int(
} }
if (XFS_IS_CORRUPT(context->dp->i_mount, if (XFS_IS_CORRUPT(context->dp->i_mount,
!xfs_attr_namecheck(name, namelen))) { !xfs_attr_namecheck(entry->flags, name,
namelen))) {
xfs_dirattr_mark_sick(context->dp, XFS_ATTR_FORK); xfs_dirattr_mark_sick(context->dp, XFS_ATTR_FORK);
return -EFSCORRUPTED; return -EFSCORRUPTED;
} }
...@@ -544,6 +547,7 @@ xfs_attr_list_ilocked( ...@@ -544,6 +547,7 @@ xfs_attr_list_ilocked(
struct xfs_attr_list_context *context) struct xfs_attr_list_context *context)
{ {
struct xfs_inode *dp = context->dp; struct xfs_inode *dp = context->dp;
int error;
xfs_assert_ilocked(dp, XFS_ILOCK_SHARED | XFS_ILOCK_EXCL); xfs_assert_ilocked(dp, XFS_ILOCK_SHARED | XFS_ILOCK_EXCL);
...@@ -554,6 +558,12 @@ xfs_attr_list_ilocked( ...@@ -554,6 +558,12 @@ xfs_attr_list_ilocked(
return 0; return 0;
if (dp->i_af.if_format == XFS_DINODE_FMT_LOCAL) if (dp->i_af.if_format == XFS_DINODE_FMT_LOCAL)
return xfs_attr_shortform_list(context); return xfs_attr_shortform_list(context);
/* Prerequisite for xfs_attr_is_leaf */
error = xfs_iread_extents(NULL, dp, XFS_ATTR_FORK);
if (error)
return error;
if (xfs_attr_is_leaf(dp)) if (xfs_attr_is_leaf(dp))
return xfs_attr_leaf_list(context); return xfs_attr_leaf_list(context);
return xfs_attr_node_list(context); return xfs_attr_node_list(context);
......
...@@ -231,6 +231,13 @@ xfs_readsb( ...@@ -231,6 +231,13 @@ xfs_readsb(
mp->m_features |= xfs_sb_version_to_features(sbp); mp->m_features |= xfs_sb_version_to_features(sbp);
xfs_reinit_percpu_counters(mp); xfs_reinit_percpu_counters(mp);
/*
* If logged xattrs are enabled after log recovery finishes, then set
* the opstate so that log recovery will work properly.
*/
if (xfs_sb_version_haslogxattrs(&mp->m_sb))
xfs_set_using_logged_xattrs(mp);
/* no need to be quiet anymore, so reset the buf ops */ /* no need to be quiet anymore, so reset the buf ops */
bp->b_ops = &xfs_sb_buf_ops; bp->b_ops = &xfs_sb_buf_ops;
...@@ -829,6 +836,15 @@ xfs_mountfs( ...@@ -829,6 +836,15 @@ xfs_mountfs(
goto out_inodegc_shrinker; goto out_inodegc_shrinker;
} }
/*
* If logged xattrs are still enabled after log recovery finishes, then
* they'll be available until unmount. Otherwise, turn them off.
*/
if (xfs_sb_version_haslogxattrs(&mp->m_sb))
xfs_set_using_logged_xattrs(mp);
else
xfs_clear_using_logged_xattrs(mp);
/* Enable background inode inactivation workers. */ /* Enable background inode inactivation workers. */
xfs_inodegc_start(mp); xfs_inodegc_start(mp);
xfs_blockgc_start(mp); xfs_blockgc_start(mp);
......
...@@ -444,6 +444,8 @@ __XFS_HAS_FEAT(nouuid, NOUUID) ...@@ -444,6 +444,8 @@ __XFS_HAS_FEAT(nouuid, NOUUID)
#define XFS_OPSTATE_QUOTACHECK_RUNNING 10 #define XFS_OPSTATE_QUOTACHECK_RUNNING 10
/* Do we want to clear log incompat flags? */ /* Do we want to clear log incompat flags? */
#define XFS_OPSTATE_UNSET_LOG_INCOMPAT 11 #define XFS_OPSTATE_UNSET_LOG_INCOMPAT 11
/* Filesystem can use logged extended attributes */
#define XFS_OPSTATE_USE_LARP 12
#define __XFS_IS_OPSTATE(name, NAME) \ #define __XFS_IS_OPSTATE(name, NAME) \
static inline bool xfs_is_ ## name (struct xfs_mount *mp) \ static inline bool xfs_is_ ## name (struct xfs_mount *mp) \
...@@ -472,6 +474,7 @@ __XFS_IS_OPSTATE(quotacheck_running, QUOTACHECK_RUNNING) ...@@ -472,6 +474,7 @@ __XFS_IS_OPSTATE(quotacheck_running, QUOTACHECK_RUNNING)
# define xfs_is_quotacheck_running(mp) (false) # define xfs_is_quotacheck_running(mp) (false)
#endif #endif
__XFS_IS_OPSTATE(done_with_log_incompat, UNSET_LOG_INCOMPAT) __XFS_IS_OPSTATE(done_with_log_incompat, UNSET_LOG_INCOMPAT)
__XFS_IS_OPSTATE(using_logged_xattrs, USE_LARP)
static inline bool static inline bool
xfs_should_warn(struct xfs_mount *mp, long nr) xfs_should_warn(struct xfs_mount *mp, long nr)
...@@ -491,7 +494,8 @@ xfs_should_warn(struct xfs_mount *mp, long nr) ...@@ -491,7 +494,8 @@ xfs_should_warn(struct xfs_mount *mp, long nr)
{ (1UL << XFS_OPSTATE_WARNED_SHRINK), "wshrink" }, \ { (1UL << XFS_OPSTATE_WARNED_SHRINK), "wshrink" }, \
{ (1UL << XFS_OPSTATE_WARNED_LARP), "wlarp" }, \ { (1UL << XFS_OPSTATE_WARNED_LARP), "wlarp" }, \
{ (1UL << XFS_OPSTATE_QUOTACHECK_RUNNING), "quotacheck" }, \ { (1UL << XFS_OPSTATE_QUOTACHECK_RUNNING), "quotacheck" }, \
{ (1UL << XFS_OPSTATE_UNSET_LOG_INCOMPAT), "unset_log_incompat" } { (1UL << XFS_OPSTATE_UNSET_LOG_INCOMPAT), "unset_log_incompat" }, \
{ (1UL << XFS_OPSTATE_USE_LARP), "logged_xattrs" }
/* /*
* Max and min values for mount-option defined I/O * Max and min values for mount-option defined I/O
......
...@@ -31,7 +31,7 @@ xfs_attr_grab_log_assist( ...@@ -31,7 +31,7 @@ xfs_attr_grab_log_assist(
int error = 0; int error = 0;
/* xattr update log intent items are already enabled */ /* xattr update log intent items are already enabled */
if (xfs_sb_version_haslogxattrs(&mp->m_sb)) if (xfs_is_using_logged_xattrs(mp))
return 0; return 0;
/* /*
...@@ -48,6 +48,7 @@ xfs_attr_grab_log_assist( ...@@ -48,6 +48,7 @@ xfs_attr_grab_log_assist(
XFS_SB_FEAT_INCOMPAT_LOG_XATTRS); XFS_SB_FEAT_INCOMPAT_LOG_XATTRS);
if (error) if (error)
return error; return error;
xfs_set_using_logged_xattrs(mp);
xfs_warn_mount(mp, XFS_OPSTATE_WARNED_LARP, xfs_warn_mount(mp, XFS_OPSTATE_WARNED_LARP,
"EXPERIMENTAL logged extended attributes feature in use. Use at your own risk!"); "EXPERIMENTAL logged extended attributes feature in use. Use at your own risk!");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment