aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2010-07-20 03:52:59 -0400
committerAlex Elder <aelder@sgi.com>2010-07-26 14:16:48 -0400
commitec53d1dbb3ca960e7b552397613358ba1dbd12bd (patch)
tree9b04fd4e4f1149ce0b5927c9f9a89d26fa6a3d4a
parenta4190f90b4e22bde8b01b0086e00dd95439e2edd (diff)
xfs: don't block on buffer read errors
xfs_buf_read() fails to detect dispatch errors before attempting to wait on sychronous IO. If there was an error, it will get stuck forever, waiting for an I/O that was never started. Make sure the error is detected correctly. Further, such a failure can leave locked pages in the page cache which will cause a later operation to hang on the page. Ensure that we correctly process pages in the buffers when we get a dispatch error. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Dave Chinner <david@fromorbit.com>
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.c19
1 files changed, 15 insertions, 4 deletions
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index efce8abb375c..f4d4e708a8d6 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -578,9 +578,9 @@ _xfs_buf_read(
578 XBF_READ_AHEAD | _XBF_RUN_QUEUES); 578 XBF_READ_AHEAD | _XBF_RUN_QUEUES);
579 579
580 status = xfs_buf_iorequest(bp); 580 status = xfs_buf_iorequest(bp);
581 if (!status && !(flags & XBF_ASYNC)) 581 if (status || XFS_BUF_ISERROR(bp) || (flags & XBF_ASYNC))
582 status = xfs_buf_iowait(bp); 582 return status;
583 return status; 583 return xfs_buf_iowait(bp);
584} 584}
585 585
586xfs_buf_t * 586xfs_buf_t *
@@ -1280,8 +1280,19 @@ submit_io:
1280 if (size) 1280 if (size)
1281 goto next_chunk; 1281 goto next_chunk;
1282 } else { 1282 } else {
1283 bio_put(bio); 1283 /*
1284 * if we get here, no pages were added to the bio. However,
1285 * we can't just error out here - if the pages are locked then
1286 * we have to unlock them otherwise we can hang on a later
1287 * access to the page.
1288 */
1284 xfs_buf_ioerror(bp, EIO); 1289 xfs_buf_ioerror(bp, EIO);
1290 if (bp->b_flags & _XBF_PAGE_LOCKED) {
1291 int i;
1292 for (i = 0; i < bp->b_page_count; i++)
1293 unlock_page(bp->b_pages[i]);
1294 }
1295 bio_put(bio);
1285 } 1296 }
1286} 1297}
1287 1298