xfs: uncached buffer reads need to return an error
authorDave Chinner <dchinner@redhat.com>
Mon, 12 Nov 2012 11:54:02 +0000 (22:54 +1100)
committerBen Myers <bpm@sgi.com>
Fri, 16 Nov 2012 03:34:05 +0000 (21:34 -0600)
With verification being done as an IO completion callback, different
errors can be returned from a read. Uncached reads only return a
buffer or NULL on failure, which means the verification error cannot
be returned to the caller.

Split the error handling for these reads into two - a failure to get
a buffer will still return NULL, but a read error will return a
referenced buffer with b_error set rather than NULL. The caller is
responsible for checking the error state of the buffer returned.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Phil White <pwhite@sgi.com>
Signed-off-by: Ben Myers <bpm@sgi.com>
fs/xfs/xfs_buf.c
fs/xfs/xfs_fsops.c
fs/xfs/xfs_mount.c
fs/xfs/xfs_rtalloc.c

index 0298dd6847982ffb8db91c3875274110b651097f..fbc965fc075ab212940994e9a1c875496e108fa4 100644 (file)
@@ -715,8 +715,7 @@ xfs_buf_read_uncached(
        int                     flags,
        xfs_buf_iodone_t        verify)
 {
-       xfs_buf_t               *bp;
-       int                     error;
+       struct xfs_buf          *bp;
 
        bp = xfs_buf_get_uncached(target, numblks, flags);
        if (!bp)
@@ -730,11 +729,7 @@ xfs_buf_read_uncached(
        bp->b_iodone = verify;
 
        xfsbdstrat(target->bt_mount, bp);
-       error = xfs_buf_iowait(bp);
-       if (error) {
-               xfs_buf_relse(bp);
-               return NULL;
-       }
+       xfs_buf_iowait(bp);
        return bp;
 }
 
index 5440768ec41c1e17bad3961de9c935a40ed61a2e..f35f8d7731f0a2fbde84671f1aa27c61130b8253 100644 (file)
@@ -171,6 +171,11 @@ xfs_growfs_data_private(
                                XFS_FSS_TO_BB(mp, 1), 0, NULL);
        if (!bp)
                return EIO;
+       if (bp->b_error) {
+               int     error = bp->b_error;
+               xfs_buf_relse(bp);
+               return error;
+       }
        xfs_buf_relse(bp);
 
        new = nb;       /* use new as a temporary here */
index d5402b0eb6a3619ef2977cbde440ab31fd87eec1..df6d0b2aade107ace47d51fb1f1253881a4344c1 100644 (file)
@@ -658,6 +658,12 @@ reread:
                        xfs_warn(mp, "SB buffer read failed");
                return EIO;
        }
+       if (bp->b_error) {
+               error = bp->b_error;
+               if (loud)
+                       xfs_warn(mp, "SB validate failed");
+               goto release_buf;
+       }
 
        /*
         * Initialize the mount structure from the superblock.
index b271ed939d7bd48107c54a3fcc5eba82e149f8c4..98dc670d3ee04182da47b27e7db1695b71807434 100644 (file)
@@ -1876,6 +1876,11 @@ xfs_growfs_rt(
                                XFS_FSB_TO_BB(mp, 1), 0, NULL);
        if (!bp)
                return EIO;
+       if (bp->b_error) {
+               error = bp->b_error;
+               xfs_buf_relse(bp);
+               return error;
+       }
        xfs_buf_relse(bp);
 
        /*
@@ -2221,8 +2226,10 @@ xfs_rtmount_init(
        bp = xfs_buf_read_uncached(mp->m_rtdev_targp,
                                        d - XFS_FSB_TO_BB(mp, 1),
                                        XFS_FSB_TO_BB(mp, 1), 0, NULL);
-       if (!bp) {
+       if (!bp || bp->b_error) {
                xfs_warn(mp, "realtime device size check failed");
+               if (bp)
+                       xfs_buf_relse(bp);
                return EIO;
        }
        xfs_buf_relse(bp);