[PATCH 06/11] xfs: split valuebuf from xchk_xattr_buf.buf

Darrick J. Wong
2022-12-30T22:49:50Z

Move the xattr value buffer from somewhere in xchk_xattr_buf.buf[] to an
explicit pointer.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
---
fs/xfs/scrub/attr.c | 89 +++++++++++++++++++++++++--------------------------
fs/xfs/scrub/attr.h | 21 ++----------
2 files changed, 46 insertions(+), 64 deletions(-)

diff --git a/fs/xfs/scrub/attr.c b/fs/xfs/scrub/attr.c
index c343ae932ae3..98371daa1397 100644
--- a/fs/xfs/scrub/attr.c
+++ b/fs/xfs/scrub/attr.c
@@ -31,6 +31,9 @@ xchk_xattr_buf_cleanup(
ab->freemap = NULL;
kvfree(ab->usedmap);
ab->usedmap = NULL;
+ kvfree(ab->value);
+ ab->value = NULL;
+ ab->value_sz = 0;
}

/*
@@ -44,54 +47,45 @@ xchk_setup_xattr_buf(
size_t value_size,
gfp_t flags)
{
- size_t sz = value_size;
size_t bmp_sz;
struct xchk_xattr_buf *ab = sc->buf;
- unsigned long *old_usedmap = NULL;
- unsigned long *old_freemap = NULL;
+ void *new_val;

bmp_sz = sizeof(long) * BITS_TO_LONGS(sc->mp->m_attr_geo->blksize);

- /*
- * If there's already a buffer, figure out if we need to reallocate it
- * to accommodate a larger size.
- */
- if (ab) {
- if (sz <= ab->sz)
- return 0;
- old_freemap = ab->freemap;
- old_usedmap = ab->usedmap;
- kvfree(ab);
- sc->buf = NULL;
- }
+ if (ab)
+ goto resize_value;

- /*
- * Don't zero the buffer upon allocation to avoid runtime overhead.
- * All users must be careful never to read uninitialized contents.
- */
- ab = kvmalloc(sizeof(*ab) + sz, flags);
+ ab = kvzalloc(sizeof(struct xchk_xattr_buf), flags);
if (!ab)
return -ENOMEM;
- ab->sz = sz;
sc->buf = ab;
sc->buf_cleanup = xchk_xattr_buf_cleanup;

- if (old_usedmap) {
- ab->usedmap = old_usedmap;
- } else {
- ab->usedmap = kvmalloc(bmp_sz, flags);
- if (!ab->usedmap)
- return -ENOMEM;
- }
+ ab->usedmap = kvmalloc(bmp_sz, flags);
+ if (!ab->usedmap)
+ return -ENOMEM;
+
+ ab->freemap = kvmalloc(bmp_sz, flags);
+ if (!ab->freemap)
+ return -ENOMEM;

- if (old_freemap) {
- ab->freemap = old_freemap;
- } else {
- ab->freemap = kvmalloc(bmp_sz, flags);
- if (!ab->freemap)
- return -ENOMEM;
+resize_value:
+ if (ab->value_sz >= value_size)
+ return 0;
+
+ if (ab->value) {
+ kvfree(ab->value);
+ ab->value = NULL;
+ ab->value_sz = 0;
}

+ new_val = kvmalloc(value_size, flags);
+ if (!new_val)
+ return -ENOMEM;
+
+ ab->value = new_val;
+ ab->value_sz = value_size;
return 0;
}

@@ -140,11 +134,24 @@ xchk_xattr_listent(
int namelen,
int valuelen)
{
+ struct xfs_da_args args = {
+ .op_flags = XFS_DA_OP_NOTIME,
+ .attr_filter = flags & XFS_ATTR_NSP_ONDISK_MASK,
+ .geo = context->dp->i_mount->m_attr_geo,
+ .whichfork = XFS_ATTR_FORK,
+ .dp = context->dp,
+ .name = name,
+ .namelen = namelen,
+ .hashval = xfs_da_hashname(name, namelen),
+ .trans = context->tp,
+ .valuelen = valuelen,
+ };
+ struct xchk_xattr_buf *ab;
struct xchk_xattr *sx;
- struct xfs_da_args args = { NULL };
int error = 0;

sx = container_of(context, struct xchk_xattr, context);
+ ab = sx->sc->buf;

if (xchk_should_terminate(sx->sc, &error)) {
context->seen_enough = error;
@@ -182,17 +189,7 @@ xchk_xattr_listent(
return;
}

- args.op_flags = XFS_DA_OP_NOTIME;
- args.attr_filter = flags & XFS_ATTR_NSP_ONDISK_MASK;
- args.geo = context->dp->i_mount->m_attr_geo;
- args.whichfork = XFS_ATTR_FORK;
- args.dp = context->dp;
- args.name = name;
- args.namelen = namelen;
- args.hashval = xfs_da_hashname(args.name, args.namelen);
- args.trans = context->tp;
- args.value = xchk_xattr_valuebuf(sx->sc);
- args.valuelen = valuelen;
+ args.value = ab->value;

error = xfs_attr_get_ilocked(&args);
/* ENODATA means the hash lookup failed and the attr is bad */
diff --git a/fs/xfs/scrub/attr.h b/fs/xfs/scrub/attr.h
index f6f033c19118..18445cc3d33b 100644
--- a/fs/xfs/scrub/attr.h
+++ b/fs/xfs/scrub/attr.h
@@ -16,24 +16,9 @@ struct xchk_xattr_buf {
/* Bitmap of free space in xattr leaf blocks. */
unsigned long *freemap;

- /* Size of @buf, in bytes. */
- size_t sz;
-
- /*
- * Memory buffer -- used for extracting attr values while walking the
- * attributes.
- */
- uint8_t buf[];
+ /* Memory buffer used to extract xattr values. */
+ void *value;
+ size_t value_sz;
};

-/* A place to store attribute values. */
-static inline uint8_t *
-xchk_xattr_valuebuf(
- struct xfs_scrub *sc)
-{
- struct xchk_xattr_buf *ab = sc->buf;
-
- return ab->buf;
-}
-
#endif /* __XFS_SCRUB_ATTR_H__ */