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> --- copy/xfs_copy.c | 13 +++++++-- db/init.c | 9 +++--- libxfs/libxfs_api_defs.h | 2 + libxfs/libxfs_io.h | 22 +++------------ libxfs/rdwr.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 88 insertions(+), 25 deletions(-) diff --git a/copy/xfs_copy.c b/copy/xfs_copy.c index bb3ecd43..75c39407 100644 --- a/copy/xfs_copy.c +++ b/copy/xfs_copy.c @@ -562,6 +562,7 @@ main(int argc, char **argv) libxfs_init_t xargs; thread_args *tcarg; struct stat statbuf; + int error; progname = basename(argv[0]); @@ -710,14 +711,20 @@ main(int argc, char **argv) /* We don't yet know the sector size, so read maximal size */ libxfs_buftarg_init(&mbuf, xargs.ddev, xargs.logdev, xargs.rtdev); - sbp = libxfs_buf_read(mbuf.m_ddev_targp, XFS_SB_DADDR, - 1 << (XFS_MAX_SECTORSIZE_LOG - BBSHIFT), 0, NULL); + error = -libxfs_buf_read_uncached(mbuf.m_ddev_targp, XFS_SB_DADDR, + 1 << (XFS_MAX_SECTORSIZE_LOG - BBSHIFT), 0, &sbp, NULL); + if (error) { + do_log(_("%s: couldn't read superblock, error=%d\n"), + progname, error); + exit(1); + } + sb = &mbuf.m_sb; libxfs_sb_from_disk(sb, XFS_BUF_TO_SBP(sbp)); /* Do it again, now with proper length and verifier */ libxfs_buf_relse(sbp); - libxfs_purgebuf(sbp); + sbp = libxfs_buf_read(mbuf.m_ddev_targp, XFS_SB_DADDR, 1 << (sb->sb_sectlog - BBSHIFT), 0, &xfs_sb_buf_ops); diff --git a/db/init.c b/db/init.c index acab349c..eb53d672 100644 --- a/db/init.c +++ b/db/init.c @@ -47,6 +47,7 @@ init( struct xfs_buf *bp; unsigned int agcount; int c; + int error; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); @@ -112,10 +113,9 @@ init( */ memset(&xmount, 0, sizeof(struct xfs_mount)); libxfs_buftarg_init(&xmount, x.ddev, x.logdev, x.rtdev); - bp = libxfs_buf_read(xmount.m_ddev_targp, XFS_SB_DADDR, - 1 << (XFS_MAX_SECTORSIZE_LOG - BBSHIFT), 0, NULL); - - if (!bp || bp->b_error) { + error = -libxfs_buf_read_uncached(xmount.m_ddev_targp, XFS_SB_DADDR, + 1 << (XFS_MAX_SECTORSIZE_LOG - BBSHIFT), 0, &bp, NULL); + if (error) { fprintf(stderr, _("%s: %s is invalid (cannot read first 512 " "bytes)\n"), progname, fsdevice); exit(1); @@ -124,7 +124,6 @@ init( /* copy SB from buffer to in-core, converting architecture as we go */ libxfs_sb_from_disk(&xmount.m_sb, XFS_BUF_TO_SBP(bp)); libxfs_buf_relse(bp); - libxfs_purgebuf(bp); sbp = &xmount.m_sb; if (sbp->sb_magicnum != XFS_SB_MAGIC) { 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 b01f2896..546b7710 100644 --- a/libxfs/libxfs_io.h +++ b/libxfs/libxfs_io.h @@ -257,23 +257,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 51f93c3e..ada20dd9 100644 --- a/libxfs/rdwr.c +++ b/libxfs/rdwr.c @@ -1070,6 +1070,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) {