diff options
author | Dave Chinner <dchinner@redhat.com> | 2012-04-23 01:58:46 -0400 |
---|---|---|
committer | Ben Myers <bpm@sgi.com> | 2012-05-14 17:20:42 -0400 |
commit | 0e95f19ad983e72a9cb93a67b3290b58f0467b36 (patch) | |
tree | 2b3117e20f1e739d5cb560b1b1b32f3fdc8e3ee5 /fs/xfs | |
parent | fe2429b0966a7ec42b5fe3bf96f0f10de0a3b536 (diff) |
xfs: check for buffer errors before waiting
If we call xfs_buf_iowait() on a buffer that failed dispatch due to
an IO error, it will wait forever for an Io that does not exist.
This is hndled in xfs_buf_read, but there is other code that calls
xfs_buf_iowait directly that doesn't.
Rather than make the call sites have to handle checking for dispatch
errors and then checking for completion errors, make
xfs_buf_iowait() check for dispatch errors on the buffer before
waiting. This means we handle both dispatch and completion errors
with one set of error handling at the caller sites.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Mark Tinguely <tinguely@sgi.com>
Signed-off-by: Ben Myers <bpm@sgi.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/xfs_buf.c | 22 | ||||
-rw-r--r-- | fs/xfs/xfs_buf.h | 2 | ||||
-rw-r--r-- | fs/xfs/xfs_log_recover.c | 2 |
3 files changed, 13 insertions, 13 deletions
diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index da2541e5ff81..86d9af70ab3b 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c | |||
@@ -600,17 +600,15 @@ _xfs_buf_read( | |||
600 | xfs_buf_t *bp, | 600 | xfs_buf_t *bp, |
601 | xfs_buf_flags_t flags) | 601 | xfs_buf_flags_t flags) |
602 | { | 602 | { |
603 | int status; | ||
604 | |||
605 | ASSERT(!(flags & XBF_WRITE)); | 603 | ASSERT(!(flags & XBF_WRITE)); |
606 | ASSERT(bp->b_bn != XFS_BUF_DADDR_NULL); | 604 | ASSERT(bp->b_bn != XFS_BUF_DADDR_NULL); |
607 | 605 | ||
608 | bp->b_flags &= ~(XBF_WRITE | XBF_ASYNC | XBF_READ_AHEAD); | 606 | bp->b_flags &= ~(XBF_WRITE | XBF_ASYNC | XBF_READ_AHEAD); |
609 | bp->b_flags |= flags & (XBF_READ | XBF_ASYNC | XBF_READ_AHEAD); | 607 | bp->b_flags |= flags & (XBF_READ | XBF_ASYNC | XBF_READ_AHEAD); |
610 | 608 | ||
611 | status = xfs_buf_iorequest(bp); | 609 | xfs_buf_iorequest(bp); |
612 | if (status || bp->b_error || (flags & XBF_ASYNC)) | 610 | if (flags & XBF_ASYNC) |
613 | return status; | 611 | return 0; |
614 | return xfs_buf_iowait(bp); | 612 | return xfs_buf_iowait(bp); |
615 | } | 613 | } |
616 | 614 | ||
@@ -695,7 +693,7 @@ xfs_buf_read_uncached( | |||
695 | 693 | ||
696 | xfsbdstrat(mp, bp); | 694 | xfsbdstrat(mp, bp); |
697 | error = xfs_buf_iowait(bp); | 695 | error = xfs_buf_iowait(bp); |
698 | if (error || bp->b_error) { | 696 | if (error) { |
699 | xfs_buf_relse(bp); | 697 | xfs_buf_relse(bp); |
700 | return NULL; | 698 | return NULL; |
701 | } | 699 | } |
@@ -1252,7 +1250,7 @@ next_chunk: | |||
1252 | } | 1250 | } |
1253 | } | 1251 | } |
1254 | 1252 | ||
1255 | int | 1253 | void |
1256 | xfs_buf_iorequest( | 1254 | xfs_buf_iorequest( |
1257 | xfs_buf_t *bp) | 1255 | xfs_buf_t *bp) |
1258 | { | 1256 | { |
@@ -1273,13 +1271,12 @@ xfs_buf_iorequest( | |||
1273 | _xfs_buf_ioend(bp, 0); | 1271 | _xfs_buf_ioend(bp, 0); |
1274 | 1272 | ||
1275 | xfs_buf_rele(bp); | 1273 | xfs_buf_rele(bp); |
1276 | return 0; | ||
1277 | } | 1274 | } |
1278 | 1275 | ||
1279 | /* | 1276 | /* |
1280 | * Waits for I/O to complete on the buffer supplied. | 1277 | * Waits for I/O to complete on the buffer supplied. It returns immediately if |
1281 | * It returns immediately if no I/O is pending. | 1278 | * no I/O is pending or there is already a pending error on the buffer. It |
1282 | * It returns the I/O error code, if any, or 0 if there was no error. | 1279 | * returns the I/O error code, if any, or 0 if there was no error. |
1283 | */ | 1280 | */ |
1284 | int | 1281 | int |
1285 | xfs_buf_iowait( | 1282 | xfs_buf_iowait( |
@@ -1287,7 +1284,8 @@ xfs_buf_iowait( | |||
1287 | { | 1284 | { |
1288 | trace_xfs_buf_iowait(bp, _RET_IP_); | 1285 | trace_xfs_buf_iowait(bp, _RET_IP_); |
1289 | 1286 | ||
1290 | wait_for_completion(&bp->b_iowait); | 1287 | if (!bp->b_error) |
1288 | wait_for_completion(&bp->b_iowait); | ||
1291 | 1289 | ||
1292 | trace_xfs_buf_iowait_done(bp, _RET_IP_); | 1290 | trace_xfs_buf_iowait_done(bp, _RET_IP_); |
1293 | return bp->b_error; | 1291 | return bp->b_error; |
diff --git a/fs/xfs/xfs_buf.h b/fs/xfs/xfs_buf.h index 7083cf44d95f..87a474853f8a 100644 --- a/fs/xfs/xfs_buf.h +++ b/fs/xfs/xfs_buf.h | |||
@@ -191,7 +191,7 @@ extern int xfs_bdstrat_cb(struct xfs_buf *); | |||
191 | extern void xfs_buf_ioend(xfs_buf_t *, int); | 191 | extern void xfs_buf_ioend(xfs_buf_t *, int); |
192 | extern void xfs_buf_ioerror(xfs_buf_t *, int); | 192 | extern void xfs_buf_ioerror(xfs_buf_t *, int); |
193 | extern void xfs_buf_ioerror_alert(struct xfs_buf *, const char *func); | 193 | extern void xfs_buf_ioerror_alert(struct xfs_buf *, const char *func); |
194 | extern int xfs_buf_iorequest(xfs_buf_t *); | 194 | extern void xfs_buf_iorequest(xfs_buf_t *); |
195 | extern int xfs_buf_iowait(xfs_buf_t *); | 195 | extern int xfs_buf_iowait(xfs_buf_t *); |
196 | extern void xfs_buf_iomove(xfs_buf_t *, size_t, size_t, void *, | 196 | extern void xfs_buf_iomove(xfs_buf_t *, size_t, size_t, void *, |
197 | xfs_buf_rw_t); | 197 | xfs_buf_rw_t); |
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 5540e79da6f5..e1577e763fdf 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c | |||
@@ -179,6 +179,7 @@ xlog_bread_noalign( | |||
179 | XFS_BUF_SET_ADDR(bp, log->l_logBBstart + blk_no); | 179 | XFS_BUF_SET_ADDR(bp, log->l_logBBstart + blk_no); |
180 | XFS_BUF_READ(bp); | 180 | XFS_BUF_READ(bp); |
181 | XFS_BUF_SET_COUNT(bp, BBTOB(nbblks)); | 181 | XFS_BUF_SET_COUNT(bp, BBTOB(nbblks)); |
182 | bp->b_error = 0; | ||
182 | 183 | ||
183 | xfsbdstrat(log->l_mp, bp); | 184 | xfsbdstrat(log->l_mp, bp); |
184 | error = xfs_buf_iowait(bp); | 185 | error = xfs_buf_iowait(bp); |
@@ -266,6 +267,7 @@ xlog_bwrite( | |||
266 | xfs_buf_hold(bp); | 267 | xfs_buf_hold(bp); |
267 | xfs_buf_lock(bp); | 268 | xfs_buf_lock(bp); |
268 | XFS_BUF_SET_COUNT(bp, BBTOB(nbblks)); | 269 | XFS_BUF_SET_COUNT(bp, BBTOB(nbblks)); |
270 | bp->b_error = 0; | ||
269 | 271 | ||
270 | error = xfs_bwrite(bp); | 272 | error = xfs_bwrite(bp); |
271 | if (error) | 273 | if (error) |