[PATCH 10/25] libxfs: introduce libxfs_buf_read_uncached

Darrick J. Wong
2020-02-25T00:12:36Z

Introduce an uncached read function so that userspace can handle them in
the same way as the kernel. This also eliminates the need for some of
the libxfs_purgebuf calls (and two trips into the cache code).

Refactor the get/read uncached buffer functions to hide the details of
uncached buffer-ism in rdwr.c.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
libxfs/libxfs_api_defs.h | 2 +
libxfs/libxfs_io.h | 22 +++------------
libxfs/rdwr.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 74 insertions(+), 17 deletions(-)

diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h
index df267c98..1149e301 100644
--- a/libxfs/libxfs_api_defs.h
+++ b/libxfs/libxfs_api_defs.h
@@ -45,7 +45,9 @@
#define xfs_btree_init_block libxfs_btree_init_block
#define xfs_buf_delwri_submit libxfs_buf_delwri_submit
#define xfs_buf_get libxfs_buf_get
+#define xfs_buf_get_uncached libxfs_buf_get_uncached
#define xfs_buf_read libxfs_buf_read
+#define xfs_buf_read_uncached libxfs_buf_read_uncached
#define xfs_buf_relse libxfs_buf_relse
#define xfs_bunmapi libxfs_bunmapi
#define xfs_bwrite libxfs_bwrite
diff --git a/libxfs/libxfs_io.h b/libxfs/libxfs_io.h
index d96b5318..21afc99c 100644
--- a/libxfs/libxfs_io.h
+++ b/libxfs/libxfs_io.h
@@ -255,23 +255,11 @@ xfs_buf_associate_memory(struct xfs_buf *bp, void *mem, size_t len)
return 0;
}

-/*
- * Allocate an uncached buffer that points nowhere. The refcount will be 1,
- * and the cache node hash list will be empty to indicate that it's uncached.
- */
-static inline struct xfs_buf *
-xfs_buf_get_uncached(struct xfs_buftarg *targ, size_t bblen, int flags)
-{
- struct xfs_buf *bp;
-
- bp = libxfs_getbufr(targ, XFS_BUF_DADDR_NULL, bblen);
- if (!bp)
- return NULL;
-
- INIT_LIST_HEAD(&bp->b_node.cn_hash);
- bp->b_node.cn_count = 1;
- return bp;
-}
+struct xfs_buf *libxfs_buf_get_uncached(struct xfs_buftarg *targ, size_t bblen,
+ int flags);
+int libxfs_buf_read_uncached(struct xfs_buftarg *targ, xfs_daddr_t daddr,
+ size_t bblen, int flags, struct xfs_buf **bpp,
+ const struct xfs_buf_ops *ops);

/* Push a single buffer on a delwri queue. */
static inline void
diff --git a/libxfs/rdwr.c b/libxfs/rdwr.c
index 9ee9d557..9324ee1c 100644
--- a/libxfs/rdwr.c
+++ b/libxfs/rdwr.c
@@ -1066,6 +1066,73 @@ libxfs_readbuf_map(struct xfs_buftarg *btp, struct xfs_buf_map *map, int nmaps,
return bp;
}

+/* Allocate a raw uncached buffer. */
+static inline struct xfs_buf *
+libxfs_getbufr_uncached(
+ struct xfs_buftarg *targ,
+ xfs_daddr_t daddr,
+ size_t bblen)
+{
+ struct xfs_buf *bp;
+
+ bp = libxfs_getbufr(targ, daddr, bblen);
+ if (!bp)
+ return NULL;
+
+ INIT_LIST_HEAD(&bp->b_node.cn_hash);
+ bp->b_node.cn_count = 1;
+ return bp;
+}
+
+/*
+ * Allocate an uncached buffer that points nowhere. The refcount will be 1,
+ * and the cache node hash list will be empty to indicate that it's uncached.
+ */
+struct xfs_buf *
+libxfs_buf_get_uncached(
+ struct xfs_buftarg *targ,
+ size_t bblen,
+ int flags)
+{
+ return libxfs_getbufr_uncached(targ, XFS_BUF_DADDR_NULL, bblen);
+}
+
+/*
+ * Allocate and read an uncached buffer. The refcount will be 1, and the cache
+ * node hash list will be empty to indicate that it's uncached.
+ */
+int
+libxfs_buf_read_uncached(
+ struct xfs_buftarg *targ,
+ xfs_daddr_t daddr,
+ size_t bblen,
+ int flags,
+ struct xfs_buf **bpp,
+ const struct xfs_buf_ops *ops)
+{
+ struct xfs_buf *bp;
+ int error;
+
+ *bpp = NULL;
+ bp = libxfs_getbufr_uncached(targ, daddr, bblen);
+ if (!bp)
+ return -ENOMEM;
+
+ error = libxfs_readbufr(targ, daddr, bp, bblen, flags);
+ if (error)
+ goto err;
+
+ error = libxfs_readbuf_verify(bp, ops);
+ if (error)
+ goto err;
+
+ *bpp = bp;
+ return 0;
+err:
+ libxfs_buf_relse(bp);
+ return error;
+}
+
static int
__write_buf(int fd, void *buf, int len, off64_t offset, int flags)
{