aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Myers <bpm@sgi.com>2013-12-18 11:36:58 -0500
committerBen Myers <bpm@sgi.com>2013-12-18 11:36:58 -0500
commit324bb26144e9be037227ff75fae1042d048a15b4 (patch)
treec90ce3a7a9712884c5f36fa64b5c113f1e37f906
parent46f23adf78545c49591619a615edeec41ed5a549 (diff)
parentac8809f9ab01a73de1a47b5a37bd8dcca8712fb3 (diff)
Merge branch 'xfs-for-linus-v3.13-rc5' into for-next
-rw-r--r--fs/xfs/xfs_bmap.c23
-rw-r--r--fs/xfs/xfs_bmap_util.c14
-rw-r--r--fs/xfs/xfs_buf.c37
-rw-r--r--fs/xfs/xfs_buf.h11
-rw-r--r--fs/xfs/xfs_buf_item.c21
-rw-r--r--fs/xfs/xfs_log_recover.c13
-rw-r--r--fs/xfs/xfs_trans_buf.c13
7 files changed, 92 insertions, 40 deletions
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index 8401f11f378f..3b2c14b6f0fb 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -3648,10 +3648,19 @@ xfs_bmap_btalloc(
3648 int isaligned; 3648 int isaligned;
3649 int tryagain; 3649 int tryagain;
3650 int error; 3650 int error;
3651 int stripe_align;
3651 3652
3652 ASSERT(ap->length); 3653 ASSERT(ap->length);
3653 3654
3654 mp = ap->ip->i_mount; 3655 mp = ap->ip->i_mount;
3656
3657 /* stripe alignment for allocation is determined by mount parameters */
3658 stripe_align = 0;
3659 if (mp->m_swidth && (mp->m_flags & XFS_MOUNT_SWALLOC))
3660 stripe_align = mp->m_swidth;
3661 else if (mp->m_dalign)
3662 stripe_align = mp->m_dalign;
3663
3655 align = ap->userdata ? xfs_get_extsz_hint(ap->ip) : 0; 3664 align = ap->userdata ? xfs_get_extsz_hint(ap->ip) : 0;
3656 if (unlikely(align)) { 3665 if (unlikely(align)) {
3657 error = xfs_bmap_extsize_align(mp, &ap->got, &ap->prev, 3666 error = xfs_bmap_extsize_align(mp, &ap->got, &ap->prev,
@@ -3660,6 +3669,8 @@ xfs_bmap_btalloc(
3660 ASSERT(!error); 3669 ASSERT(!error);
3661 ASSERT(ap->length); 3670 ASSERT(ap->length);
3662 } 3671 }
3672
3673
3663 nullfb = *ap->firstblock == NULLFSBLOCK; 3674 nullfb = *ap->firstblock == NULLFSBLOCK;
3664 fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, *ap->firstblock); 3675 fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, *ap->firstblock);
3665 if (nullfb) { 3676 if (nullfb) {
@@ -3735,7 +3746,7 @@ xfs_bmap_btalloc(
3735 */ 3746 */
3736 if (!ap->flist->xbf_low && ap->aeof) { 3747 if (!ap->flist->xbf_low && ap->aeof) {
3737 if (!ap->offset) { 3748 if (!ap->offset) {
3738 args.alignment = mp->m_dalign; 3749 args.alignment = stripe_align;
3739 atype = args.type; 3750 atype = args.type;
3740 isaligned = 1; 3751 isaligned = 1;
3741 /* 3752 /*
@@ -3760,13 +3771,13 @@ xfs_bmap_btalloc(
3760 * of minlen+alignment+slop doesn't go up 3771 * of minlen+alignment+slop doesn't go up
3761 * between the calls. 3772 * between the calls.
3762 */ 3773 */
3763 if (blen > mp->m_dalign && blen <= args.maxlen) 3774 if (blen > stripe_align && blen <= args.maxlen)
3764 nextminlen = blen - mp->m_dalign; 3775 nextminlen = blen - stripe_align;
3765 else 3776 else
3766 nextminlen = args.minlen; 3777 nextminlen = args.minlen;
3767 if (nextminlen + mp->m_dalign > args.minlen + 1) 3778 if (nextminlen + stripe_align > args.minlen + 1)
3768 args.minalignslop = 3779 args.minalignslop =
3769 nextminlen + mp->m_dalign - 3780 nextminlen + stripe_align -
3770 args.minlen - 1; 3781 args.minlen - 1;
3771 else 3782 else
3772 args.minalignslop = 0; 3783 args.minalignslop = 0;
@@ -3788,7 +3799,7 @@ xfs_bmap_btalloc(
3788 */ 3799 */
3789 args.type = atype; 3800 args.type = atype;
3790 args.fsbno = ap->blkno; 3801 args.fsbno = ap->blkno;
3791 args.alignment = mp->m_dalign; 3802 args.alignment = stripe_align;
3792 args.minlen = nextminlen; 3803 args.minlen = nextminlen;
3793 args.minalignslop = 0; 3804 args.minalignslop = 0;
3794 isaligned = 1; 3805 isaligned = 1;
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
index 5887e41c0323..1394106ed22d 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -1187,7 +1187,12 @@ xfs_zero_remaining_bytes(
1187 XFS_BUF_UNWRITE(bp); 1187 XFS_BUF_UNWRITE(bp);
1188 XFS_BUF_READ(bp); 1188 XFS_BUF_READ(bp);
1189 XFS_BUF_SET_ADDR(bp, xfs_fsb_to_db(ip, imap.br_startblock)); 1189 XFS_BUF_SET_ADDR(bp, xfs_fsb_to_db(ip, imap.br_startblock));
1190 xfsbdstrat(mp, bp); 1190
1191 if (XFS_FORCED_SHUTDOWN(mp)) {
1192 error = XFS_ERROR(EIO);
1193 break;
1194 }
1195 xfs_buf_iorequest(bp);
1191 error = xfs_buf_iowait(bp); 1196 error = xfs_buf_iowait(bp);
1192 if (error) { 1197 if (error) {
1193 xfs_buf_ioerror_alert(bp, 1198 xfs_buf_ioerror_alert(bp,
@@ -1200,7 +1205,12 @@ xfs_zero_remaining_bytes(
1200 XFS_BUF_UNDONE(bp); 1205 XFS_BUF_UNDONE(bp);
1201 XFS_BUF_UNREAD(bp); 1206 XFS_BUF_UNREAD(bp);
1202 XFS_BUF_WRITE(bp); 1207 XFS_BUF_WRITE(bp);
1203 xfsbdstrat(mp, bp); 1208
1209 if (XFS_FORCED_SHUTDOWN(mp)) {
1210 error = XFS_ERROR(EIO);
1211 break;
1212 }
1213 xfs_buf_iorequest(bp);
1204 error = xfs_buf_iowait(bp); 1214 error = xfs_buf_iowait(bp);
1205 if (error) { 1215 if (error) {
1206 xfs_buf_ioerror_alert(bp, 1216 xfs_buf_ioerror_alert(bp,
diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c
index ce01c1a17cc1..9fccfb594291 100644
--- a/fs/xfs/xfs_buf.c
+++ b/fs/xfs/xfs_buf.c
@@ -698,7 +698,11 @@ xfs_buf_read_uncached(
698 bp->b_flags |= XBF_READ; 698 bp->b_flags |= XBF_READ;
699 bp->b_ops = ops; 699 bp->b_ops = ops;
700 700
701 xfsbdstrat(target->bt_mount, bp); 701 if (XFS_FORCED_SHUTDOWN(target->bt_mount)) {
702 xfs_buf_relse(bp);
703 return NULL;
704 }
705 xfs_buf_iorequest(bp);
702 xfs_buf_iowait(bp); 706 xfs_buf_iowait(bp);
703 return bp; 707 return bp;
704} 708}
@@ -1089,7 +1093,7 @@ xfs_bioerror(
1089 * This is meant for userdata errors; metadata bufs come with 1093 * This is meant for userdata errors; metadata bufs come with
1090 * iodone functions attached, so that we can track down errors. 1094 * iodone functions attached, so that we can track down errors.
1091 */ 1095 */
1092STATIC int 1096int
1093xfs_bioerror_relse( 1097xfs_bioerror_relse(
1094 struct xfs_buf *bp) 1098 struct xfs_buf *bp)
1095{ 1099{
@@ -1152,7 +1156,7 @@ xfs_bwrite(
1152 ASSERT(xfs_buf_islocked(bp)); 1156 ASSERT(xfs_buf_islocked(bp));
1153 1157
1154 bp->b_flags |= XBF_WRITE; 1158 bp->b_flags |= XBF_WRITE;
1155 bp->b_flags &= ~(XBF_ASYNC | XBF_READ | _XBF_DELWRI_Q); 1159 bp->b_flags &= ~(XBF_ASYNC | XBF_READ | _XBF_DELWRI_Q | XBF_WRITE_FAIL);
1156 1160
1157 xfs_bdstrat_cb(bp); 1161 xfs_bdstrat_cb(bp);
1158 1162
@@ -1164,25 +1168,6 @@ xfs_bwrite(
1164 return error; 1168 return error;
1165} 1169}
1166 1170
1167/*
1168 * Wrapper around bdstrat so that we can stop data from going to disk in case
1169 * we are shutting down the filesystem. Typically user data goes thru this
1170 * path; one of the exceptions is the superblock.
1171 */
1172void
1173xfsbdstrat(
1174 struct xfs_mount *mp,
1175 struct xfs_buf *bp)
1176{
1177 if (XFS_FORCED_SHUTDOWN(mp)) {
1178 trace_xfs_bdstrat_shut(bp, _RET_IP_);
1179 xfs_bioerror_relse(bp);
1180 return;
1181 }
1182
1183 xfs_buf_iorequest(bp);
1184}
1185
1186STATIC void 1171STATIC void
1187_xfs_buf_ioend( 1172_xfs_buf_ioend(
1188 xfs_buf_t *bp, 1173 xfs_buf_t *bp,
@@ -1516,6 +1501,12 @@ xfs_wait_buftarg(
1516 struct xfs_buf *bp; 1501 struct xfs_buf *bp;
1517 bp = list_first_entry(&dispose, struct xfs_buf, b_lru); 1502 bp = list_first_entry(&dispose, struct xfs_buf, b_lru);
1518 list_del_init(&bp->b_lru); 1503 list_del_init(&bp->b_lru);
1504 if (bp->b_flags & XBF_WRITE_FAIL) {
1505 xfs_alert(btp->bt_mount,
1506"Corruption Alert: Buffer at block 0x%llx had permanent write failures!\n"
1507"Please run xfs_repair to determine the extent of the problem.",
1508 (long long)bp->b_bn);
1509 }
1519 xfs_buf_rele(bp); 1510 xfs_buf_rele(bp);
1520 } 1511 }
1521 if (loop++ != 0) 1512 if (loop++ != 0)
@@ -1789,7 +1780,7 @@ __xfs_buf_delwri_submit(
1789 1780
1790 blk_start_plug(&plug); 1781 blk_start_plug(&plug);
1791 list_for_each_entry_safe(bp, n, io_list, b_list) { 1782 list_for_each_entry_safe(bp, n, io_list, b_list) {
1792 bp->b_flags &= ~(_XBF_DELWRI_Q | XBF_ASYNC); 1783 bp->b_flags &= ~(_XBF_DELWRI_Q | XBF_ASYNC | XBF_WRITE_FAIL);
1793 bp->b_flags |= XBF_WRITE; 1784 bp->b_flags |= XBF_WRITE;
1794 1785
1795 if (!wait) { 1786 if (!wait) {
diff --git a/fs/xfs/xfs_buf.h b/fs/xfs/xfs_buf.h
index e65683361017..1cf21a4a9f22 100644
--- a/fs/xfs/xfs_buf.h
+++ b/fs/xfs/xfs_buf.h
@@ -45,6 +45,7 @@ typedef enum {
45#define XBF_ASYNC (1 << 4) /* initiator will not wait for completion */ 45#define XBF_ASYNC (1 << 4) /* initiator will not wait for completion */
46#define XBF_DONE (1 << 5) /* all pages in the buffer uptodate */ 46#define XBF_DONE (1 << 5) /* all pages in the buffer uptodate */
47#define XBF_STALE (1 << 6) /* buffer has been staled, do not find it */ 47#define XBF_STALE (1 << 6) /* buffer has been staled, do not find it */
48#define XBF_WRITE_FAIL (1 << 24)/* async writes have failed on this buffer */
48 49
49/* I/O hints for the BIO layer */ 50/* I/O hints for the BIO layer */
50#define XBF_SYNCIO (1 << 10)/* treat this buffer as synchronous I/O */ 51#define XBF_SYNCIO (1 << 10)/* treat this buffer as synchronous I/O */
@@ -70,6 +71,7 @@ typedef unsigned int xfs_buf_flags_t;
70 { XBF_ASYNC, "ASYNC" }, \ 71 { XBF_ASYNC, "ASYNC" }, \
71 { XBF_DONE, "DONE" }, \ 72 { XBF_DONE, "DONE" }, \
72 { XBF_STALE, "STALE" }, \ 73 { XBF_STALE, "STALE" }, \
74 { XBF_WRITE_FAIL, "WRITE_FAIL" }, \
73 { XBF_SYNCIO, "SYNCIO" }, \ 75 { XBF_SYNCIO, "SYNCIO" }, \
74 { XBF_FUA, "FUA" }, \ 76 { XBF_FUA, "FUA" }, \
75 { XBF_FLUSH, "FLUSH" }, \ 77 { XBF_FLUSH, "FLUSH" }, \
@@ -80,6 +82,7 @@ typedef unsigned int xfs_buf_flags_t;
80 { _XBF_DELWRI_Q, "DELWRI_Q" }, \ 82 { _XBF_DELWRI_Q, "DELWRI_Q" }, \
81 { _XBF_COMPOUND, "COMPOUND" } 83 { _XBF_COMPOUND, "COMPOUND" }
82 84
85
83/* 86/*
84 * Internal state flags. 87 * Internal state flags.
85 */ 88 */
@@ -269,9 +272,6 @@ extern void xfs_buf_unlock(xfs_buf_t *);
269 272
270/* Buffer Read and Write Routines */ 273/* Buffer Read and Write Routines */
271extern int xfs_bwrite(struct xfs_buf *bp); 274extern int xfs_bwrite(struct xfs_buf *bp);
272
273extern void xfsbdstrat(struct xfs_mount *, struct xfs_buf *);
274
275extern void xfs_buf_ioend(xfs_buf_t *, int); 275extern void xfs_buf_ioend(xfs_buf_t *, int);
276extern void xfs_buf_ioerror(xfs_buf_t *, int); 276extern void xfs_buf_ioerror(xfs_buf_t *, int);
277extern void xfs_buf_ioerror_alert(struct xfs_buf *, const char *func); 277extern void xfs_buf_ioerror_alert(struct xfs_buf *, const char *func);
@@ -282,6 +282,8 @@ extern void xfs_buf_iomove(xfs_buf_t *, size_t, size_t, void *,
282#define xfs_buf_zero(bp, off, len) \ 282#define xfs_buf_zero(bp, off, len) \
283 xfs_buf_iomove((bp), (off), (len), NULL, XBRW_ZERO) 283 xfs_buf_iomove((bp), (off), (len), NULL, XBRW_ZERO)
284 284
285extern int xfs_bioerror_relse(struct xfs_buf *);
286
285static inline int xfs_buf_geterror(xfs_buf_t *bp) 287static inline int xfs_buf_geterror(xfs_buf_t *bp)
286{ 288{
287 return bp ? bp->b_error : ENOMEM; 289 return bp ? bp->b_error : ENOMEM;
@@ -301,7 +303,8 @@ extern void xfs_buf_terminate(void);
301 303
302#define XFS_BUF_ZEROFLAGS(bp) \ 304#define XFS_BUF_ZEROFLAGS(bp) \
303 ((bp)->b_flags &= ~(XBF_READ|XBF_WRITE|XBF_ASYNC| \ 305 ((bp)->b_flags &= ~(XBF_READ|XBF_WRITE|XBF_ASYNC| \
304 XBF_SYNCIO|XBF_FUA|XBF_FLUSH)) 306 XBF_SYNCIO|XBF_FUA|XBF_FLUSH| \
307 XBF_WRITE_FAIL))
305 308
306void xfs_buf_stale(struct xfs_buf *bp); 309void xfs_buf_stale(struct xfs_buf *bp);
307#define XFS_BUF_UNSTALE(bp) ((bp)->b_flags &= ~XBF_STALE) 310#define XFS_BUF_UNSTALE(bp) ((bp)->b_flags &= ~XBF_STALE)
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index 764117305438..33149113e333 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -495,6 +495,14 @@ xfs_buf_item_unpin(
495 } 495 }
496} 496}
497 497
498/*
499 * Buffer IO error rate limiting. Limit it to no more than 10 messages per 30
500 * seconds so as to not spam logs too much on repeated detection of the same
501 * buffer being bad..
502 */
503
504DEFINE_RATELIMIT_STATE(xfs_buf_write_fail_rl_state, 30 * HZ, 10);
505
498STATIC uint 506STATIC uint
499xfs_buf_item_push( 507xfs_buf_item_push(
500 struct xfs_log_item *lip, 508 struct xfs_log_item *lip,
@@ -523,6 +531,14 @@ xfs_buf_item_push(
523 531
524 trace_xfs_buf_item_push(bip); 532 trace_xfs_buf_item_push(bip);
525 533
534 /* has a previous flush failed due to IO errors? */
535 if ((bp->b_flags & XBF_WRITE_FAIL) &&
536 ___ratelimit(&xfs_buf_write_fail_rl_state, "XFS:")) {
537 xfs_warn(bp->b_target->bt_mount,
538"Detected failing async write on buffer block 0x%llx. Retrying async write.\n",
539 (long long)bp->b_bn);
540 }
541
526 if (!xfs_buf_delwri_queue(bp, buffer_list)) 542 if (!xfs_buf_delwri_queue(bp, buffer_list))
527 rval = XFS_ITEM_FLUSHING; 543 rval = XFS_ITEM_FLUSHING;
528 xfs_buf_unlock(bp); 544 xfs_buf_unlock(bp);
@@ -1095,8 +1111,9 @@ xfs_buf_iodone_callbacks(
1095 1111
1096 xfs_buf_ioerror(bp, 0); /* errno of 0 unsets the flag */ 1112 xfs_buf_ioerror(bp, 0); /* errno of 0 unsets the flag */
1097 1113
1098 if (!XFS_BUF_ISSTALE(bp)) { 1114 if (!(bp->b_flags & (XBF_STALE|XBF_WRITE_FAIL))) {
1099 bp->b_flags |= XBF_WRITE | XBF_ASYNC | XBF_DONE; 1115 bp->b_flags |= XBF_WRITE | XBF_ASYNC |
1116 XBF_DONE | XBF_WRITE_FAIL;
1100 xfs_buf_iorequest(bp); 1117 xfs_buf_iorequest(bp);
1101 } else { 1118 } else {
1102 xfs_buf_relse(bp); 1119 xfs_buf_relse(bp);
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 22b6f35765c1..bce53ac81096 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -193,7 +193,10 @@ xlog_bread_noalign(
193 bp->b_io_length = nbblks; 193 bp->b_io_length = nbblks;
194 bp->b_error = 0; 194 bp->b_error = 0;
195 195
196 xfsbdstrat(log->l_mp, bp); 196 if (XFS_FORCED_SHUTDOWN(log->l_mp))
197 return XFS_ERROR(EIO);
198
199 xfs_buf_iorequest(bp);
197 error = xfs_buf_iowait(bp); 200 error = xfs_buf_iowait(bp);
198 if (error) 201 if (error)
199 xfs_buf_ioerror_alert(bp, __func__); 202 xfs_buf_ioerror_alert(bp, __func__);
@@ -4408,7 +4411,13 @@ xlog_do_recover(
4408 XFS_BUF_READ(bp); 4411 XFS_BUF_READ(bp);
4409 XFS_BUF_UNASYNC(bp); 4412 XFS_BUF_UNASYNC(bp);
4410 bp->b_ops = &xfs_sb_buf_ops; 4413 bp->b_ops = &xfs_sb_buf_ops;
4411 xfsbdstrat(log->l_mp, bp); 4414
4415 if (XFS_FORCED_SHUTDOWN(log->l_mp)) {
4416 xfs_buf_relse(bp);
4417 return XFS_ERROR(EIO);
4418 }
4419
4420 xfs_buf_iorequest(bp);
4412 error = xfs_buf_iowait(bp); 4421 error = xfs_buf_iowait(bp);
4413 if (error) { 4422 if (error) {
4414 xfs_buf_ioerror_alert(bp, __func__); 4423 xfs_buf_ioerror_alert(bp, __func__);
diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c
index c035d11b7734..647b6f1d8923 100644
--- a/fs/xfs/xfs_trans_buf.c
+++ b/fs/xfs/xfs_trans_buf.c
@@ -314,7 +314,18 @@ xfs_trans_read_buf_map(
314 ASSERT(bp->b_iodone == NULL); 314 ASSERT(bp->b_iodone == NULL);
315 XFS_BUF_READ(bp); 315 XFS_BUF_READ(bp);
316 bp->b_ops = ops; 316 bp->b_ops = ops;
317 xfsbdstrat(tp->t_mountp, bp); 317
318 /*
319 * XXX(hch): clean up the error handling here to be less
320 * of a mess..
321 */
322 if (XFS_FORCED_SHUTDOWN(mp)) {
323 trace_xfs_bdstrat_shut(bp, _RET_IP_);
324 xfs_bioerror_relse(bp);
325 } else {
326 xfs_buf_iorequest(bp);
327 }
328
318 error = xfs_buf_iowait(bp); 329 error = xfs_buf_iowait(bp);
319 if (error) { 330 if (error) {
320 xfs_buf_ioerror_alert(bp, __func__); 331 xfs_buf_ioerror_alert(bp, __func__);