From: Darrick J. Wong <djwong@xxxxxxxxxx> Move the xattr value buffer from somewhere in xchk_xattr_buf.buf[] to an explicit pointer. Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx> --- 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__ */