]> www.infradead.org Git - users/hch/xfsprogs.git/commitdiff
libxfs: make libxfs_buf_read_map return an error code
authorDarrick J. Wong <darrick.wong@oracle.com>
Sat, 14 Mar 2020 03:01:00 +0000 (23:01 -0400)
committerEric Sandeen <sandeen@sandeen.net>
Sat, 14 Mar 2020 03:01:00 +0000 (23:01 -0400)
Make libxfs_buf_read_map() and libxfs_readbuf() return an error code
instead of making callers guess what happened based on whether or not
they got a buffer back.

Add a new SALVAGE flag so that certain utilities (xfs_db and xfs_repair)
can attempt salvage operations even if the verifiers failed, which was
the behavior before this change.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
db/io.c
libxfs/libxfs_io.h
libxfs/rdwr.c
libxfs/trans.c
repair/da_util.c

diff --git a/db/io.c b/db/io.c
index b81e996963d4c10e596fc206cad3ce8167cb4f07..5c9d72bb14e724ad4d6d2fa4522b29a2f99c665d 100644 (file)
--- a/db/io.c
+++ b/db/io.c
@@ -542,8 +542,8 @@ set_cur(
                if (!iocur_top->bbmap)
                        return;
                memcpy(iocur_top->bbmap, bbmap, sizeof(struct bbmap));
-               bp = libxfs_buf_read_map(mp->m_ddev_targp, bbmap->b,
-                                       bbmap->nmaps, 0, ops);
+               libxfs_buf_read_map(mp->m_ddev_targp, bbmap->b, bbmap->nmaps,
+                               LIBXFS_READBUF_SALVAGE, &bp, ops);
        } else {
                bp = libxfs_buf_read(mp->m_ddev_targp, blknum, len, 0, ops);
                iocur_top->bbmap = NULL;
index 98bce31170fc3d3b4c5bf821a47b753b779c95ef..456e41cbcf2ab709582cddc1965ef1b47f8c0132 100644 (file)
@@ -125,14 +125,17 @@ extern struct cache_operations    libxfs_bcache_operations;
 
 #define LIBXFS_GETBUF_TRYLOCK  (1 << 0)
 
+/* Return the buffer even if the verifiers fail. */
+#define LIBXFS_READBUF_SALVAGE         (1 << 1)
+
 #ifdef XFS_BUF_TRACING
 
 #define libxfs_buf_read(dev, daddr, len, flags, ops) \
        libxfs_trace_readbuf(__FUNCTION__, __FILE__, __LINE__, \
                            (dev), (daddr), (len), (flags), (ops))
-#define libxfs_buf_read_map(dev, map, nmaps, flags, ops) \
+#define libxfs_buf_read_map(dev, map, nmaps, flags, bpp, ops) \
        libxfs_trace_readbuf_map(__FUNCTION__, __FILE__, __LINE__, \
-                           (dev), (map), (nmaps), (flags), (ops))
+                           (dev), (map), (nmaps), (flags), (bpp), (ops))
 #define libxfs_buf_mark_dirty(buf) \
        libxfs_trace_dirtybuf(__FUNCTION__, __FILE__, __LINE__, \
                              (buf))
@@ -148,9 +151,10 @@ extern struct cache_operations     libxfs_bcache_operations;
 struct xfs_buf *libxfs_trace_readbuf(const char *func, const char *file,
                        int line, struct xfs_buftarg *btp, xfs_daddr_t daddr,
                        size_t len, int flags, const struct xfs_buf_ops *ops);
-extern xfs_buf_t *libxfs_trace_readbuf_map(const char *, const char *, int,
-                       struct xfs_buftarg *, struct xfs_buf_map *, int, int,
-                       const struct xfs_buf_ops *);
+int libxfs_trace_readbuf_map(const char *func, const char *file, int line,
+                       struct xfs_buftarg *btp, struct xfs_buf_map *maps,
+                       int nmaps, int flags, struct xfs_buf **bpp,
+                       const struct xfs_buf_ops *ops);
 void libxfs_trace_dirtybuf(const char *func, const char *file, int line,
                        struct xfs_buf *bp);
 struct xfs_buf *libxfs_trace_getbuf(const char *func, const char *file,
@@ -164,8 +168,8 @@ extern void libxfs_trace_putbuf (const char *, const char *, int,
 
 #else
 
-struct xfs_buf *libxfs_buf_read_map(struct xfs_buftarg *btp,
-                       struct xfs_buf_map *map, int nmaps, int flags,
+int libxfs_buf_read_map(struct xfs_buftarg *btp, struct xfs_buf_map *maps,
+                       int nmaps, int flags, struct xfs_buf **bpp,
                        const struct xfs_buf_ops *ops);
 void libxfs_buf_mark_dirty(struct xfs_buf *bp);
 int libxfs_buf_get_map(struct xfs_buftarg *btp, struct xfs_buf_map *maps,
@@ -196,9 +200,14 @@ libxfs_buf_read(
        xfs_buf_flags_t         flags,
        const struct xfs_buf_ops *ops)
 {
+       struct xfs_buf          *bp;
+       int                     error;
        DEFINE_SINGLE_BUF_MAP(map, blkno, numblks);
 
-       return libxfs_buf_read_map(target, &map, 1, flags, ops);
+       error = libxfs_buf_read_map(target, &map, 1, flags, &bp, ops);
+       if (error)
+               return NULL;
+       return bp;
 }
 
 #endif /* XFS_BUF_TRACING */
index 9429d86ba4a89705e5fbacf97d217eccf26da5ee..4316007cf30c8aa2cbc2fafca6fd63ac7851e3b0 100644 (file)
@@ -158,9 +158,10 @@ static char *next(
 #undef libxfs_writebuf
 #undef libxfs_buf_get_map
 
-struct xfs_buf *libxfs_buf_read_map(struct xfs_buftarg *btp,
-                       struct xfs_buf_map *map, int nmaps, int flags,
-                       const struct xfs_buf_ops *ops);
+int            libxfs_buf_read_map(struct xfs_buftarg *btp,
+                               struct xfs_buf_map *maps, int nmaps, int flags,
+                               struct xfs_buf **bpp,
+                               const struct xfs_buf_ops *ops);
 int            libxfs_writebuf(xfs_buf_t *, int);
 int            libxfs_buf_get_map(struct xfs_buftarg *btp,
                                struct xfs_buf_map *maps, int nmaps, int flags,
@@ -190,11 +191,30 @@ libxfs_trace_readbuf(
        struct xfs_buf          *bp;
        DEFINE_SINGLE_BUF_MAP(map, blkno, numblks);
 
-       bp = libxfs_buf_read_map(btp, &map, 1, flags, ops);
+       libxfs_buf_read_map(btp, &map, 1, flags, &bp, ops);
        __add_trace(bp, func, file, line);
        return bp;
 }
 
+int
+libxfs_trace_readbuf_map(
+       const char              *func,
+       const char              *file,
+       int                     line,
+       struct xfs_buftarg      *btp,
+       struct xfs_buf_map      *map,
+       int                     nmaps,
+       int                     flags,
+       struct xfs_buf          **bpp,
+       const struct xfs_buf_ops *ops)
+{
+       int                     error;
+
+       error = libxfs_buf_read_map(btp, map, nmaps, flags, bpp, ops);
+       __add_trace(*bpp, func, file, line);
+       return error;
+}
+
 void
 libxfs_trace_dirtybuf(
        const char              *func,
@@ -775,20 +795,27 @@ libxfs_readbufr_map(struct xfs_buftarg *btp, struct xfs_buf *bp, int flags)
        return error;
 }
 
-struct xfs_buf *
-libxfs_buf_read_map(struct xfs_buftarg *btp, struct xfs_buf_map *map, int nmaps,
-               int flags, const struct xfs_buf_ops *ops)
+int
+libxfs_buf_read_map(
+       struct xfs_buftarg      *btp,
+       struct xfs_buf_map      *map,
+       int                     nmaps,
+       int                     flags,
+       struct xfs_buf          **bpp,
+       const struct xfs_buf_ops *ops)
 {
-       struct xfs_buf  *bp;
-       int             error = 0;
+       struct xfs_buf          *bp;
+       bool                    salvage = flags & LIBXFS_READBUF_SALVAGE;
+       int                     error = 0;
 
+       *bpp = NULL;
        if (nmaps == 1)
                error = libxfs_getbuf_flags(btp, map[0].bm_bn, map[0].bm_len,
                                0, &bp);
        else
                error = __libxfs_buf_get_map(btp, map, nmaps, 0, &bp);
        if (error)
-               return NULL;
+               return error;
 
        /*
         * If the buffer was prefetched, it is likely that it was not validated.
@@ -801,12 +828,17 @@ libxfs_buf_read_map(struct xfs_buftarg *btp, struct xfs_buf_map *map, int nmaps,
         * should not be dirtying unchecked buffers and therefore failing it
         * here because it's dirty and unchecked indicates we've screwed up
         * somewhere else.
+        *
+        * Note that if the caller passes in LIBXFS_READBUF_SALVAGE, that means
+        * they want the buffer even if it fails verification.
         */
        bp->b_error = 0;
        if (bp->b_flags & (LIBXFS_B_UPTODATE | LIBXFS_B_DIRTY)) {
                if (bp->b_flags & LIBXFS_B_UNCHECKED)
-                       libxfs_readbuf_verify(bp, ops);
-               return bp;
+                       error = libxfs_readbuf_verify(bp, ops);
+               if (error && !salvage)
+                       goto err;
+               goto ok;
        }
 
        /*
@@ -821,15 +853,24 @@ libxfs_buf_read_map(struct xfs_buftarg *btp, struct xfs_buf_map *map, int nmaps,
                                flags);
        else
                error = libxfs_readbufr_map(btp, bp, flags);
-       if (!error)
-               libxfs_readbuf_verify(bp, ops);
+       if (error)
+               goto err;
+
+       error = libxfs_readbuf_verify(bp, ops);
+       if (error && !salvage)
+               goto err;
 
+ok:
 #ifdef IO_DEBUGX
        printf("%lx: %s: read %lu bytes, error %d, blkno=%llu(%llu), %p\n",
                pthread_self(), __FUNCTION__, buf - (char *)bp->b_addr, error,
                (long long)LIBXFS_BBTOOFF64(bp->b_bn), (long long)bp->b_bn, bp);
 #endif
-       return bp;
+       *bpp = bp;
+       return 0;
+err:
+       libxfs_buf_relse(bp);
+       return error;
 }
 
 /* Allocate a raw uncached buffer. */
index 21dd66cbf7d2f5544eb3415662d4176b20854ea7..73f69bcea3c32faf88efc1faa8443bfcea548eb0 100644 (file)
@@ -510,15 +510,8 @@ libxfs_trans_read_buf_map(
 
        *bpp = NULL;
 
-       if (tp == NULL) {
-               bp = libxfs_buf_read_map(target, map, nmaps, flags, ops);
-               if (!bp) {
-                       return (flags & XBF_TRYLOCK) ?  -EAGAIN : -ENOMEM;
-               }
-               if (bp->b_error)
-                       goto out_relse;
-               goto done;
-       }
+       if (tp == NULL)
+               return libxfs_buf_read_map(target, map, nmaps, flags, bpp, ops);
 
        bp = xfs_trans_buf_item_match(tp, target, map, nmaps);
        if (bp) {
@@ -530,22 +523,15 @@ libxfs_trans_read_buf_map(
                goto done;
        }
 
-       bp = libxfs_buf_read_map(target, map, nmaps, flags, ops);
-       if (!bp) {
-               return (flags & XBF_TRYLOCK) ?  -EAGAIN : -ENOMEM;
-       }
-       if (bp->b_error)
-               goto out_relse;
+       error = libxfs_buf_read_map(target, map, nmaps, flags, &bp, ops);
+       if (error)
+               return error;
 
        _libxfs_trans_bjoin(tp, bp, 1);
 done:
        trace_xfs_trans_read_buf(bp->b_log_item);
        *bpp = bp;
        return 0;
-out_relse:
-       error = bp->b_error;
-       xfs_buf_relse(bp);
-       return error;
 }
 
 /*
index e639ecdad71c1fdcc0f24590ab85b8f85a2bab14..5061880fbab2cd3057440882babc0b8c7fc48121 100644 (file)
@@ -64,7 +64,8 @@ da_read_buf(
                map[i].bm_bn = XFS_FSB_TO_DADDR(mp, bmp[i].startblock);
                map[i].bm_len = XFS_FSB_TO_BB(mp, bmp[i].blockcount);
        }
-       bp = libxfs_buf_read_map(mp->m_dev, map, nex, 0, ops);
+       libxfs_buf_read_map(mp->m_dev, map, nex, LIBXFS_READBUF_SALVAGE,
+                       &bp, ops);
        if (map != map_array)
                free(map);
        return bp;