diff mbox series

[1/6] xfs: create a blob array data structure

Message ID 170404835229.1753315.13978723246161515244.stgit@frogsfrogsfrogs (mailing list archive)
State Superseded
Headers show
Series [1/6] xfs: create a blob array data structure | expand

Commit Message

Darrick J. Wong Dec. 31, 2023, 8:35 p.m. UTC
From: Darrick J. Wong <djwong@kernel.org>

Create a simple 'blob array' data structure for storage of arbitrarily
sized metadata objects that will be used to reconstruct metadata.  For
the intended usage (temporarily storing extended attribute names and
values) we only have to support storing objects and retrieving them.
Use the xfile abstraction to store the attribute information in memory
that can be swapped out.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
---
 fs/xfs/Makefile       |    1 
 fs/xfs/scrub/xfblob.c |  151 +++++++++++++++++++++++++++++++++++++++++++++++++
 fs/xfs/scrub/xfblob.h |   24 ++++++++
 3 files changed, 176 insertions(+)
 create mode 100644 fs/xfs/scrub/xfblob.c
 create mode 100644 fs/xfs/scrub/xfblob.h

Comments

Christoph Hellwig Jan. 5, 2024, 5:53 a.m. UTC | #1
On Sun, Dec 31, 2023 at 12:35:11PM -0800, Darrick J. Wong wrote:
> From: Darrick J. Wong <djwong@kernel.org>
> 
> Create a simple 'blob array' data structure for storage of arbitrarily
> sized metadata objects that will be used to reconstruct metadata.  For
> the intended usage (temporarily storing extended attribute names and
> values) we only have to support storing objects and retrieving them.
> Use the xfile abstraction to store the attribute information in memory
> that can be swapped out.

Can't this simply be supported by xfiles directly?  Just add a
xfile_append that writes at i_size and retuns the offset and we're done?
Darrick J. Wong Jan. 6, 2024, 1:33 a.m. UTC | #2
On Thu, Jan 04, 2024 at 09:53:33PM -0800, Christoph Hellwig wrote:
> On Sun, Dec 31, 2023 at 12:35:11PM -0800, Darrick J. Wong wrote:
> > From: Darrick J. Wong <djwong@kernel.org>
> > 
> > Create a simple 'blob array' data structure for storage of arbitrarily
> > sized metadata objects that will be used to reconstruct metadata.  For
> > the intended usage (temporarily storing extended attribute names and
> > values) we only have to support storing objects and retrieving them.
> > Use the xfile abstraction to store the attribute information in memory
> > that can be swapped out.
> 
> Can't this simply be supported by xfiles directly?  Just add a
> xfile_append that writes at i_size and retuns the offset and we're done?

Yeah, xfile could just do an "append and tell me where you wrote it".
That said, i_size_read is less direct than reading a u64 out of a
struct.

Another speedbump with doing that is that eventually xfs_repair ports
the xfblob to userspace to support parent pointers.  For that, a statx
call is much more expensive, so I decided that both implementations
should just have their own private u64 write pointer.

(Unless you want to sponsor a pwrite variant that actually does "append
and tell me where"? ;))

--D
Christoph Hellwig Jan. 6, 2024, 6:42 a.m. UTC | #3
On Fri, Jan 05, 2024 at 05:33:16PM -0800, Darrick J. Wong wrote:
> (Unless you want to sponsor a pwrite variant that actually does "append
> and tell me where"? ;))

Damien and I have adding that on our TODO list (through io_uring) to
better support zonefs and programming models like this one on regular
files.

But I somehow doubt you'd want xfs_repair to depend on it..
Darrick J. Wong Jan. 6, 2024, 6:55 p.m. UTC | #4
On Fri, Jan 05, 2024 at 10:42:01PM -0800, Christoph Hellwig wrote:
> On Fri, Jan 05, 2024 at 05:33:16PM -0800, Darrick J. Wong wrote:
> > (Unless you want to sponsor a pwrite variant that actually does "append
> > and tell me where"? ;))
> 
> Damien and I have adding that on our TODO list (through io_uring) to
> better support zonefs and programming models like this one on regular
> files.
> 
> But I somehow doubt you'd want xfs_repair to depend on it..

Well in theory some day Dave might come back with his libaio patches for
xfsprogs.  After this much time it's a fair question if we'd be better
off aiming for io_uring. <shrug>

https://lore.kernel.org/linux-xfs/20201015072155.1631135-1-david@fromorbit.com/

--D
Darrick J. Wong Jan. 8, 2024, 5:12 p.m. UTC | #5
On Fri, Jan 05, 2024 at 10:42:01PM -0800, Christoph Hellwig wrote:
> On Fri, Jan 05, 2024 at 05:33:16PM -0800, Darrick J. Wong wrote:
> > (Unless you want to sponsor a pwrite variant that actually does "append
> > and tell me where"? ;))
> 
> Damien and I have adding that on our TODO list (through io_uring) to
> better support zonefs and programming models like this one on regular
> files.
> 
> But I somehow doubt you'd want xfs_repair to depend on it..

Nope, not for a few years anyway. :)

--D
diff mbox series

Patch

diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile
index 62e38f70c304b..72df9890edcf6 100644
--- a/fs/xfs/Makefile
+++ b/fs/xfs/Makefile
@@ -208,6 +208,7 @@  xfs-y				+= $(addprefix scrub/, \
 				   repair.o \
 				   rmap_repair.o \
 				   tempfile.o \
+				   xfblob.o \
 				   xfbtree.o \
 				   )
 
diff --git a/fs/xfs/scrub/xfblob.c b/fs/xfs/scrub/xfblob.c
new file mode 100644
index 0000000000000..216f9cb2965a7
--- /dev/null
+++ b/fs/xfs/scrub/xfblob.c
@@ -0,0 +1,151 @@ 
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2021-2024 Oracle.  All Rights Reserved.
+ * Author: Darrick J. Wong <djwong@kernel.org>
+ */
+#include "xfs.h"
+#include "xfs_fs.h"
+#include "xfs_shared.h"
+#include "xfs_format.h"
+#include "scrub/scrub.h"
+#include "scrub/xfile.h"
+#include "scrub/xfarray.h"
+#include "scrub/xfblob.h"
+
+/*
+ * XFS Blob Storage
+ * ================
+ * Stores and retrieves blobs using an xfile.  Objects are appended to the file
+ * and the offset is returned as a magic cookie for retrieval.
+ */
+
+#define XB_KEY_MAGIC	0xABAADDAD
+struct xb_key {
+	uint32_t		xb_magic;  /* XB_KEY_MAGIC */
+	uint32_t		xb_size;   /* size of the blob, in bytes */
+	loff_t			xb_offset; /* byte offset of this key */
+	/* blob comes after here */
+} __packed;
+
+/* Initialize a blob storage object. */
+int
+xfblob_create(
+	const char		*description,
+	struct xfblob		**blobp)
+{
+	struct xfblob		*blob;
+	struct xfile		*xfile;
+	int			error;
+
+	error = xfile_create(description, 0, &xfile);
+	if (error)
+		return error;
+
+	blob = kmalloc(sizeof(struct xfblob), XCHK_GFP_FLAGS);
+	if (!blob) {
+		error = -ENOMEM;
+		goto out_xfile;
+	}
+
+	blob->xfile = xfile;
+	blob->last_offset = PAGE_SIZE;
+
+	*blobp = blob;
+	return 0;
+
+out_xfile:
+	xfile_destroy(xfile);
+	return error;
+}
+
+/* Destroy a blob storage object. */
+void
+xfblob_destroy(
+	struct xfblob	*blob)
+{
+	xfile_destroy(blob->xfile);
+	kfree(blob);
+}
+
+/* Retrieve a blob. */
+int
+xfblob_load(
+	struct xfblob	*blob,
+	xfblob_cookie	cookie,
+	void		*ptr,
+	uint32_t	size)
+{
+	struct xb_key	key;
+	int		error;
+
+	error = xfile_obj_load(blob->xfile, &key, sizeof(key), cookie);
+	if (error)
+		return error;
+
+	if (key.xb_magic != XB_KEY_MAGIC || key.xb_offset != cookie) {
+		ASSERT(0);
+		return -ENODATA;
+	}
+	if (size < key.xb_size) {
+		ASSERT(0);
+		return -EFBIG;
+	}
+
+	return xfile_obj_load(blob->xfile, ptr, key.xb_size,
+			cookie + sizeof(key));
+}
+
+/* Store a blob. */
+int
+xfblob_store(
+	struct xfblob	*blob,
+	xfblob_cookie	*cookie,
+	const void	*ptr,
+	uint32_t	size)
+{
+	struct xb_key	key = {
+		.xb_offset = blob->last_offset,
+		.xb_magic = XB_KEY_MAGIC,
+		.xb_size = size,
+	};
+	loff_t		pos = blob->last_offset;
+	int		error;
+
+	error = xfile_obj_store(blob->xfile, &key, sizeof(key), pos);
+	if (error)
+		return error;
+
+	pos += sizeof(key);
+	error = xfile_obj_store(blob->xfile, ptr, size, pos);
+	if (error)
+		goto out_err;
+
+	*cookie = blob->last_offset;
+	blob->last_offset += sizeof(key) + size;
+	return 0;
+out_err:
+	xfile_discard(blob->xfile, blob->last_offset, sizeof(key));
+	return error;
+}
+
+/* Free a blob. */
+int
+xfblob_free(
+	struct xfblob	*blob,
+	xfblob_cookie	cookie)
+{
+	struct xb_key	key;
+	int		error;
+
+	error = xfile_obj_load(blob->xfile, &key, sizeof(key), cookie);
+	if (error)
+		return error;
+
+	if (key.xb_magic != XB_KEY_MAGIC || key.xb_offset != cookie) {
+		ASSERT(0);
+		return -ENODATA;
+	}
+
+	xfile_discard(blob->xfile, cookie, sizeof(key) + key.xb_size);
+	return 0;
+}
diff --git a/fs/xfs/scrub/xfblob.h b/fs/xfs/scrub/xfblob.h
new file mode 100644
index 0000000000000..bd98647407f1d
--- /dev/null
+++ b/fs/xfs/scrub/xfblob.h
@@ -0,0 +1,24 @@ 
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021-2024 Oracle.  All Rights Reserved.
+ * Author: Darrick J. Wong <djwong@kernel.org>
+ */
+#ifndef __XFS_SCRUB_XFBLOB_H__
+#define __XFS_SCRUB_XFBLOB_H__
+
+struct xfblob {
+	struct xfile	*xfile;
+	loff_t		last_offset;
+};
+
+typedef loff_t		xfblob_cookie;
+
+int xfblob_create(const char *descr, struct xfblob **blobp);
+void xfblob_destroy(struct xfblob *blob);
+int xfblob_load(struct xfblob *blob, xfblob_cookie cookie, void *ptr,
+		uint32_t size);
+int xfblob_store(struct xfblob *blob, xfblob_cookie *cookie, const void *ptr,
+		uint32_t size);
+int xfblob_free(struct xfblob *blob, xfblob_cookie cookie);
+
+#endif /* __XFS_SCRUB_XFBLOB_H__ */