aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2012-04-23 01:58:46 -0400
committerBen Myers <bpm@sgi.com>2012-05-14 17:20:42 -0400
commit0e95f19ad983e72a9cb93a67b3290b58f0467b36 (patch)
tree2b3117e20f1e739d5cb560b1b1b32f3fdc8e3ee5 /fs/xfs
parentfe2429b0966a7ec42b5fe3bf96f0f10de0a3b536 (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.c22
-rw-r--r--fs/xfs/xfs_buf.h2
-rw-r--r--fs/xfs/xfs_log_recover.c2
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
1255int 1253void
1256xfs_buf_iorequest( 1254xfs_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 */
1284int 1281int
1285xfs_buf_iowait( 1282xfs_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 *);
191extern void xfs_buf_ioend(xfs_buf_t *, int); 191extern void xfs_buf_ioend(xfs_buf_t *, int);
192extern void xfs_buf_ioerror(xfs_buf_t *, int); 192extern void xfs_buf_ioerror(xfs_buf_t *, int);
193extern void xfs_buf_ioerror_alert(struct xfs_buf *, const char *func); 193extern void xfs_buf_ioerror_alert(struct xfs_buf *, const char *func);
194extern int xfs_buf_iorequest(xfs_buf_t *); 194extern void xfs_buf_iorequest(xfs_buf_t *);
195extern int xfs_buf_iowait(xfs_buf_t *); 195extern int xfs_buf_iowait(xfs_buf_t *);
196extern void xfs_buf_iomove(xfs_buf_t *, size_t, size_t, void *, 196extern 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)