From: Darrick J. Wong <djwong@xxxxxxxxxx> Allow the buffer cache to target in-memory files by connecting it to xfiles. Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx> --- 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);