[PATCH 05/10] libxfs: support in-memory buffer cache targets

Darrick J. Wong
2023-12-31T22:15:51Z

Allow the buffer cache to target in-memory files by connecting it to
xfiles.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
---
libxfs/libxfs_io.h | 3 +++
libxfs/rdwr.c | 40 ++++++++++++++++++++++++++++++++++++++--
2 files changed, 41 insertions(+), 2 deletions(-)

diff --git a/libxfs/libxfs_io.h b/libxfs/libxfs_io.h
index 7877e17685b..a20e78338dd 100644
--- a/libxfs/libxfs_io.h
+++ b/libxfs/libxfs_io.h
@@ -27,6 +27,7 @@ struct xfs_buftarg {
unsigned long writes_left;
dev_t bt_bdev;
int bt_bdev_fd;
+ struct xfile *bt_xfile;
unsigned int flags;
struct cache *bcache; /* buffer cache */
};
@@ -39,6 +40,8 @@ struct xfs_buftarg {
#define XFS_BUFTARG_INJECT_WRITE_FAIL (1 << 2)
/* purge buffers when lookups find a size mismatch */
#define XFS_BUFTARG_MISCOMPARE_PURGE (1 << 3)
+/* use bt_xfile instead of bt_bdev/bt_bdev_fd */
+#define XFS_BUFTARG_XFILE (1 << 4)

/* Simulate the system crashing after a certain number of writes. */
static inline void
diff --git a/libxfs/rdwr.c b/libxfs/rdwr.c
index f791136c982..645c4b7838d 100644
--- a/libxfs/rdwr.c
+++ b/libxfs/rdwr.c
@@ -18,7 +18,7 @@
#include "xfs_inode.h"
#include "xfs_trans.h"
#include "libfrog/platform.h"
-
+#include "libxfs/xfile.h"
#include "libxfs.h"

static void libxfs_brelse(struct cache_node *node);
@@ -69,6 +69,9 @@ libxfs_device_zero(struct xfs_buftarg *btp, xfs_daddr_t start, uint len)
char *z;
int error;

+ if (btp->flags & XFS_BUFTARG_XFILE)
+ return -EOPNOTSUPP;
+
start_offset = LIBXFS_BBTOOFF64(start);

/* try to use special zeroing methods, fall back to writes if needed */
@@ -578,6 +581,31 @@ libxfs_balloc(
return &bp->b_node;
}

+static inline int
+libxfs_buf_ioapply_in_memory(
+ struct xfs_buf *bp,
+ bool is_write)
+{
+ struct xfile *xfile = bp->b_target->bt_xfile;
+ loff_t pos = BBTOB(xfs_buf_daddr(bp));
+ size_t size = BBTOB(bp->b_length);
+ int error;
+
+ if (bp->b_nmaps > 1) {
+ /* We don't need or support multi-map buffers. */
+ ASSERT(0);
+ error = -EIO;
+ } else if (is_write) {
+ error = xfile_obj_store(xfile, bp->b_addr, size, pos);
+ } else {
+ error = xfile_obj_load(xfile, bp->b_addr, size, pos);
+ }
+ if (error)
+ bp->b_error = error;
+ else if (!is_write)
+ bp->b_flags |= LIBXFS_B_UPTODATE;
+ return error;
+}

static int
__read_buf(int fd, void *buf, int len, off64_t offset, int flags)
@@ -608,6 +636,9 @@ libxfs_readbufr(struct xfs_buftarg *btp, xfs_daddr_t blkno, struct xfs_buf *bp,

ASSERT(len <= bp->b_length);

+ if (bp->b_target->flags & XFS_BUFTARG_XFILE)
+ return libxfs_buf_ioapply_in_memory(bp, false);
+
error = __read_buf(fd, bp->b_addr, bytes, LIBXFS_BBTOOFF64(blkno), flags);
if (!error &&
bp->b_target->bt_bdev == btp->bt_bdev &&
@@ -640,6 +671,9 @@ libxfs_readbufr_map(struct xfs_buftarg *btp, struct xfs_buf *bp, int flags)
void *buf;
int i;

+ if (bp->b_target->flags & XFS_BUFTARG_XFILE)
+ return libxfs_buf_ioapply_in_memory(bp, false);
+
buf = bp->b_addr;
for (i = 0; i < bp->b_nmaps; i++) {
off64_t offset = LIBXFS_BBTOOFF64(bp->b_maps[i].bm_bn);
@@ -858,7 +892,9 @@ libxfs_bwrite(
}
}

- if (!(bp->b_flags & LIBXFS_B_DISCONTIG)) {
+ if (bp->b_target->flags & XFS_BUFTARG_XFILE) {
+ libxfs_buf_ioapply_in_memory(bp, true);
+ } else if (!(bp->b_flags & LIBXFS_B_DISCONTIG)) {
bp->b_error = __write_buf(fd, bp->b_addr, BBTOB(bp->b_length),
LIBXFS_BBTOOFF64(xfs_buf_daddr(bp)),
bp->b_flags);