Commit b996c9a8 authored by Darrick J. Wong's avatar Darrick J. Wong
Browse files

xfs: split valuebuf from xchk_xattr_buf.buf



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

Signed-off-by: default avatarDarrick J. Wong <djwong@kernel.org>
Reviewed-by: default avatarDave Chinner <dchinner@redhat.com>
parent 80069284
Loading
Loading
Loading
Loading
+43 −46
Original line number Diff line number Diff line
@@ -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;
	}

	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 */
+3 −18
Original line number Diff line number Diff line
@@ -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__ */