diff options
author | Dave Chinner <dchinner@redhat.com> | 2010-07-20 03:52:59 -0400 |
---|---|---|
committer | Alex Elder <aelder@sgi.com> | 2010-07-26 14:16:48 -0400 |
commit | ec53d1dbb3ca960e7b552397613358ba1dbd12bd (patch) | |
tree | 9b04fd4e4f1149ce0b5927c9f9a89d26fa6a3d4a | |
parent | a4190f90b4e22bde8b01b0086e00dd95439e2edd (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.c | 19 |
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 | ||
586 | xfs_buf_t * | 586 | xfs_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 | ||