From: Darrick J. Wong <darrick.wong@xxxxxxxxxx> 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@xxxxxxxxxx> Reviewed-by: Christoph Hellwig <hch@xxxxxx> --- 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 2c67edde..3b470266 100644 --- a/libxfs/rdwr.c +++ b/libxfs/rdwr.c @@ -1073,6 +1073,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) {