From: Dave Chinner <dchinner@xxxxxxxxxx> Buffers can now be written by the buftarg IO engine, so redirect the API to the new implementation and ensure it twiddles flag state correctly. Signed-off-by: Dave Chinner <dchinner@xxxxxxxxxx> --- libxfs/buftarg.c | 30 +++++++++++++++- libxfs/libxfs_io.h | 1 - libxfs/libxfs_priv.h | 2 +- libxfs/rdwr.c | 85 -------------------------------------------- libxfs/xfs_buftarg.h | 5 ++- 5 files changed, 34 insertions(+), 89 deletions(-) diff --git a/libxfs/buftarg.c b/libxfs/buftarg.c index 62c2bea87b5c..1f6a89d14ec6 100644 --- a/libxfs/buftarg.c +++ b/libxfs/buftarg.c @@ -126,8 +126,16 @@ xfs_buf_ioend( bp->b_ops->verify_read(bp); } - if (!bp->b_error) + if (!bp->b_error) { bp->b_flags |= XBF_DONE; + bp->b_flags &= ~(LIBXFS_B_DIRTY | LIBXFS_B_UNCHECKED); + } else { + fprintf(stderr, + _("%s: IO failed on %s bno 0x%llx/0x%x, err=%d\n"), + __func__, bp->b_ops ? bp->b_ops->name : "(unknown)", + (long long)bp->b_maps[0].bm_bn, bp->b_length, + -bp->b_error); + } } static void @@ -227,6 +235,19 @@ xfs_buftarg_submit_io( bp->b_error = 0; if (bp->b_flags & XBF_WRITE) { + + /* + * we never write buffers that are marked stale. This indicates + * they contain data that has been invalidated, and even if the + * buffer is dirty it must *never* be written. Verifiers are + * wonderful for finding bugs like this. Make sure the error is + * obvious as to the cause. + */ + if (bp->b_flags & XBF_STALE) { + bp->b_error = -ESTALE; + return; + } + /* * Run the write verifier callback function if it exists. If * this function fails it will mark the buffer with an error and @@ -366,6 +387,13 @@ xfs_buf_read_uncached( return 0; } +int +xfs_bwrite(struct xfs_buf *bp) +{ + return xfs_buf_uncached_submit(bp->b_target, bp, bp->b_length, + XBF_WRITE); +} + /* * Return a buffer associated to external memory via xfs_buf_associate_memory() * back to it's empty state. diff --git a/libxfs/libxfs_io.h b/libxfs/libxfs_io.h index c59d42e02040..c17cdc33bf2a 100644 --- a/libxfs/libxfs_io.h +++ b/libxfs/libxfs_io.h @@ -145,7 +145,6 @@ extern void libxfs_bcache_flush(void); extern int libxfs_bcache_overflowed(void); /* Buffer (Raw) Interfaces */ -int libxfs_bwrite(struct xfs_buf *bp); extern int libxfs_device_zero(struct xfs_buftarg *, xfs_daddr_t, uint); extern int libxfs_bhash_size; diff --git a/libxfs/libxfs_priv.h b/libxfs/libxfs_priv.h index dce77024b5de..151c030b5876 100644 --- a/libxfs/libxfs_priv.h +++ b/libxfs/libxfs_priv.h @@ -408,7 +408,7 @@ howmany_64(uint64_t x, uint32_t y) /* buffer management */ #define XBF_TRYLOCK 0 #define XBF_UNMAPPED 0 -#define xfs_buf_stale(bp) ((bp)->b_flags |= LIBXFS_B_STALE) +#define xfs_buf_stale(bp) ((bp)->b_flags |= XBF_STALE) #define XFS_BUF_UNDELAYWRITE(bp) ((bp)->b_flags &= ~LIBXFS_B_DIRTY) /* buffer type flags for write callbacks */ diff --git a/libxfs/rdwr.c b/libxfs/rdwr.c index af70dbe339e4..371a6d221bb2 100644 --- a/libxfs/rdwr.c +++ b/libxfs/rdwr.c @@ -710,91 +710,6 @@ err: return error; } -static int -__write_buf(int fd, void *buf, int len, off64_t offset, int flags) -{ - int sts; - - sts = pwrite(fd, buf, len, offset); - if (sts < 0) { - int error = errno; - fprintf(stderr, _("%s: pwrite failed: %s\n"), - progname, strerror(error)); - return -error; - } else if (sts != len) { - fprintf(stderr, _("%s: error - pwrite only %d of %d bytes\n"), - progname, sts, len); - return -EIO; - } - return 0; -} - -int -libxfs_bwrite( - struct xfs_buf *bp) -{ - int fd = libxfs_device_to_fd(bp->b_target->bt_bdev); - - /* - * we never write buffers that are marked stale. This indicates they - * contain data that has been invalidated, and even if the buffer is - * dirty it must *never* be written. Verifiers are wonderful for finding - * bugs like this. Make sure the error is obvious as to the cause. - */ - if (bp->b_flags & LIBXFS_B_STALE) { - bp->b_error = -ESTALE; - return bp->b_error; - } - - /* - * clear any pre-existing error status on the buffer. This can occur if - * the buffer is corrupt on disk and the repair process doesn't clear - * the error before fixing and writing it back. - */ - bp->b_error = 0; - if (bp->b_ops) { - bp->b_ops->verify_write(bp); - if (bp->b_error) { - fprintf(stderr, - _("%s: write verifier failed on %s bno 0x%llx/0x%x\n"), - __func__, bp->b_ops->name, - (long long)bp->b_bn, bp->b_length); - return bp->b_error; - } - } - - if (!(bp->b_flags & LIBXFS_B_DISCONTIG)) { - bp->b_error = __write_buf(fd, bp->b_addr, BBTOB(bp->b_length), - LIBXFS_BBTOOFF64(bp->b_maps[0].bm_bn), - bp->b_flags); - } else { - int i; - void *buf = bp->b_addr; - - for (i = 0; i < bp->b_map_count; i++) { - off64_t offset = LIBXFS_BBTOOFF64(bp->b_maps[i].bm_bn); - int len = BBTOB(bp->b_maps[i].bm_len); - - bp->b_error = __write_buf(fd, buf, len, offset, - bp->b_flags); - if (bp->b_error) - break; - buf += len; - } - } - - if (bp->b_error) { - fprintf(stderr, - _("%s: write failed on %s bno 0x%llx/0x%x, err=%d\n"), - __func__, bp->b_ops ? bp->b_ops->name : "(unknown)", - (long long)bp->b_bn, bp->b_length, -bp->b_error); - } else { - bp->b_flags |= LIBXFS_B_UPTODATE; - bp->b_flags &= ~(LIBXFS_B_DIRTY | LIBXFS_B_UNCHECKED); - } - return bp->b_error; -} - /* * Mark a buffer dirty. The dirty data will be written out when the cache * is flushed (or at release time if the buffer is uncached). diff --git a/libxfs/xfs_buftarg.h b/libxfs/xfs_buftarg.h index 71054317ee9d..7d2a7ab29c0f 100644 --- a/libxfs/xfs_buftarg.h +++ b/libxfs/xfs_buftarg.h @@ -81,6 +81,8 @@ int xfs_buf_read_uncached(struct xfs_buftarg *target, xfs_daddr_t daddr, int xfs_bread(struct xfs_buf *bp, size_t bblen); +int xfs_bwrite(struct xfs_buf *bp); + /* * Temporary: these need to be the same as the LIBXFS_B_* flags until we change * over to the kernel structures. For those that aren't the same or don't yet @@ -88,7 +90,8 @@ int xfs_bread(struct xfs_buf *bp, size_t bblen); */ #define XBF_READ (1 << 31) #define XBF_WRITE (1 << 30) -#define XBF_DONE (1 << 3) // LIBXFS_B_UPTODATE 0x0008 +#define XBF_DONE (1 << 3) // LIBXFS_B_UPTODATE 0x0008 +#define XBF_STALE (1 << 2) // LIBXFS_B_STALE 0x0004 /* * Raw buffer access functions. These exist as temporary bridges for uncached IO -- 2.28.0