]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - fs/xfs/xfs_trans_buf.c
ext4: fix race between writepages and enabling EXT4_EXTENTS_FL
[linux.git] / fs / xfs / xfs_trans_buf.c
index b5b3a78ef31c41e0f057d8f8ab752a21ec8e910e..08174ffa2118935a4c00493c8e8d77aefdd215d9 100644 (file)
@@ -112,19 +112,22 @@ xfs_trans_bjoin(
  * If the transaction pointer is NULL, make this just a normal
  * get_buf() call.
  */
-struct xfs_buf *
+int
 xfs_trans_get_buf_map(
        struct xfs_trans        *tp,
        struct xfs_buftarg      *target,
        struct xfs_buf_map      *map,
        int                     nmaps,
-       xfs_buf_flags_t         flags)
+       xfs_buf_flags_t         flags,
+       struct xfs_buf          **bpp)
 {
        xfs_buf_t               *bp;
        struct xfs_buf_log_item *bip;
+       int                     error;
 
+       *bpp = NULL;
        if (!tp)
-               return xfs_buf_get_map(target, map, nmaps, flags);
+               return xfs_buf_get_map(target, map, nmaps, flags, bpp);
 
        /*
         * If we find the buffer in the cache with this transaction
@@ -146,19 +149,20 @@ xfs_trans_get_buf_map(
                ASSERT(atomic_read(&bip->bli_refcount) > 0);
                bip->bli_recur++;
                trace_xfs_trans_get_buf_recur(bip);
-               return bp;
+               *bpp = bp;
+               return 0;
        }
 
-       bp = xfs_buf_get_map(target, map, nmaps, flags);
-       if (bp == NULL) {
-               return NULL;
-       }
+       error = xfs_buf_get_map(target, map, nmaps, flags, &bp);
+       if (error)
+               return error;
 
        ASSERT(!bp->b_error);
 
        _xfs_trans_bjoin(tp, bp, 1);
        trace_xfs_trans_get_buf(bp->b_log_item);
-       return bp;
+       *bpp = bp;
+       return 0;
 }
 
 /*
@@ -276,7 +280,7 @@ xfs_trans_read_buf_map(
                ASSERT(bp->b_ops != NULL);
                error = xfs_buf_reverify(bp, ops);
                if (error) {
-                       xfs_buf_ioerror_alert(bp, __func__);
+                       xfs_buf_ioerror_alert(bp, __return_address);
 
                        if (tp->t_flags & XFS_TRANS_DIRTY)
                                xfs_force_shutdown(tp->t_mountp,
@@ -298,36 +302,17 @@ xfs_trans_read_buf_map(
                return 0;
        }
 
-       bp = xfs_buf_read_map(target, map, nmaps, flags, ops);
-       if (!bp) {
-               if (!(flags & XBF_TRYLOCK))
-                       return -ENOMEM;
-               return tp ? 0 : -EAGAIN;
-       }
-
-       /*
-        * If we've had a read error, then the contents of the buffer are
-        * invalid and should not be used. To ensure that a followup read tries
-        * to pull the buffer from disk again, we clear the XBF_DONE flag and
-        * mark the buffer stale. This ensures that anyone who has a current
-        * reference to the buffer will interpret it's contents correctly and
-        * future cache lookups will also treat it as an empty, uninitialised
-        * buffer.
-        */
-       if (bp->b_error) {
-               error = bp->b_error;
-               if (!XFS_FORCED_SHUTDOWN(mp))
-                       xfs_buf_ioerror_alert(bp, __func__);
-               bp->b_flags &= ~XBF_DONE;
-               xfs_buf_stale(bp);
-
+       error = xfs_buf_read_map(target, map, nmaps, flags, &bp, ops,
+                       __return_address);
+       switch (error) {
+       case 0:
+               break;
+       default:
                if (tp && (tp->t_flags & XFS_TRANS_DIRTY))
                        xfs_force_shutdown(tp->t_mountp, SHUTDOWN_META_IO_ERROR);
-               xfs_buf_relse(bp);
-
-               /* bad CRC means corrupted metadata */
-               if (error == -EFSBADCRC)
-                       error = -EFSCORRUPTED;
+               /* fall through */
+       case -ENOMEM:
+       case -EAGAIN:
                return error;
        }