Loading fs/xfs/xfs_bmap.c +17 −6 Original line number Diff line number Diff line Loading @@ -3648,10 +3648,19 @@ xfs_bmap_btalloc( int isaligned; int tryagain; int error; int stripe_align; ASSERT(ap->length); mp = ap->ip->i_mount; /* stripe alignment for allocation is determined by mount parameters */ stripe_align = 0; if (mp->m_swidth && (mp->m_flags & XFS_MOUNT_SWALLOC)) stripe_align = mp->m_swidth; else if (mp->m_dalign) stripe_align = mp->m_dalign; align = ap->userdata ? xfs_get_extsz_hint(ap->ip) : 0; if (unlikely(align)) { error = xfs_bmap_extsize_align(mp, &ap->got, &ap->prev, Loading @@ -3660,6 +3669,8 @@ xfs_bmap_btalloc( ASSERT(!error); ASSERT(ap->length); } nullfb = *ap->firstblock == NULLFSBLOCK; fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, *ap->firstblock); if (nullfb) { Loading Loading @@ -3735,7 +3746,7 @@ xfs_bmap_btalloc( */ if (!ap->flist->xbf_low && ap->aeof) { if (!ap->offset) { args.alignment = mp->m_dalign; args.alignment = stripe_align; atype = args.type; isaligned = 1; /* Loading @@ -3760,13 +3771,13 @@ xfs_bmap_btalloc( * of minlen+alignment+slop doesn't go up * between the calls. */ if (blen > mp->m_dalign && blen <= args.maxlen) nextminlen = blen - mp->m_dalign; if (blen > stripe_align && blen <= args.maxlen) nextminlen = blen - stripe_align; else nextminlen = args.minlen; if (nextminlen + mp->m_dalign > args.minlen + 1) if (nextminlen + stripe_align > args.minlen + 1) args.minalignslop = nextminlen + mp->m_dalign - nextminlen + stripe_align - args.minlen - 1; else args.minalignslop = 0; Loading @@ -3788,7 +3799,7 @@ xfs_bmap_btalloc( */ args.type = atype; args.fsbno = ap->blkno; args.alignment = mp->m_dalign; args.alignment = stripe_align; args.minlen = nextminlen; args.minalignslop = 0; isaligned = 1; Loading fs/xfs/xfs_bmap_util.c +12 −2 Original line number Diff line number Diff line Loading @@ -1187,7 +1187,12 @@ xfs_zero_remaining_bytes( XFS_BUF_UNWRITE(bp); XFS_BUF_READ(bp); XFS_BUF_SET_ADDR(bp, xfs_fsb_to_db(ip, imap.br_startblock)); xfsbdstrat(mp, bp); if (XFS_FORCED_SHUTDOWN(mp)) { error = XFS_ERROR(EIO); break; } xfs_buf_iorequest(bp); error = xfs_buf_iowait(bp); if (error) { xfs_buf_ioerror_alert(bp, Loading @@ -1200,7 +1205,12 @@ xfs_zero_remaining_bytes( XFS_BUF_UNDONE(bp); XFS_BUF_UNREAD(bp); XFS_BUF_WRITE(bp); xfsbdstrat(mp, bp); if (XFS_FORCED_SHUTDOWN(mp)) { error = XFS_ERROR(EIO); break; } xfs_buf_iorequest(bp); error = xfs_buf_iowait(bp); if (error) { xfs_buf_ioerror_alert(bp, Loading fs/xfs/xfs_buf.c +14 −23 Original line number Diff line number Diff line Loading @@ -698,7 +698,11 @@ xfs_buf_read_uncached( bp->b_flags |= XBF_READ; bp->b_ops = ops; xfsbdstrat(target->bt_mount, bp); if (XFS_FORCED_SHUTDOWN(target->bt_mount)) { xfs_buf_relse(bp); return NULL; } xfs_buf_iorequest(bp); xfs_buf_iowait(bp); return bp; } Loading Loading @@ -1089,7 +1093,7 @@ xfs_bioerror( * This is meant for userdata errors; metadata bufs come with * iodone functions attached, so that we can track down errors. */ STATIC int int xfs_bioerror_relse( struct xfs_buf *bp) { Loading Loading @@ -1152,7 +1156,7 @@ xfs_bwrite( ASSERT(xfs_buf_islocked(bp)); bp->b_flags |= XBF_WRITE; bp->b_flags &= ~(XBF_ASYNC | XBF_READ | _XBF_DELWRI_Q); bp->b_flags &= ~(XBF_ASYNC | XBF_READ | _XBF_DELWRI_Q | XBF_WRITE_FAIL); xfs_bdstrat_cb(bp); Loading @@ -1164,25 +1168,6 @@ xfs_bwrite( return error; } /* * Wrapper around bdstrat so that we can stop data from going to disk in case * we are shutting down the filesystem. Typically user data goes thru this * path; one of the exceptions is the superblock. */ void xfsbdstrat( struct xfs_mount *mp, struct xfs_buf *bp) { if (XFS_FORCED_SHUTDOWN(mp)) { trace_xfs_bdstrat_shut(bp, _RET_IP_); xfs_bioerror_relse(bp); return; } xfs_buf_iorequest(bp); } STATIC void _xfs_buf_ioend( xfs_buf_t *bp, Loading Loading @@ -1516,6 +1501,12 @@ xfs_wait_buftarg( struct xfs_buf *bp; bp = list_first_entry(&dispose, struct xfs_buf, b_lru); list_del_init(&bp->b_lru); if (bp->b_flags & XBF_WRITE_FAIL) { xfs_alert(btp->bt_mount, "Corruption Alert: Buffer at block 0x%llx had permanent write failures!\n" "Please run xfs_repair to determine the extent of the problem.", (long long)bp->b_bn); } xfs_buf_rele(bp); } if (loop++ != 0) Loading Loading @@ -1789,7 +1780,7 @@ __xfs_buf_delwri_submit( blk_start_plug(&plug); list_for_each_entry_safe(bp, n, io_list, b_list) { bp->b_flags &= ~(_XBF_DELWRI_Q | XBF_ASYNC); bp->b_flags &= ~(_XBF_DELWRI_Q | XBF_ASYNC | XBF_WRITE_FAIL); bp->b_flags |= XBF_WRITE; if (!wait) { Loading fs/xfs/xfs_buf.h +7 −4 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ typedef enum { #define XBF_ASYNC (1 << 4) /* initiator will not wait for completion */ #define XBF_DONE (1 << 5) /* all pages in the buffer uptodate */ #define XBF_STALE (1 << 6) /* buffer has been staled, do not find it */ #define XBF_WRITE_FAIL (1 << 24)/* async writes have failed on this buffer */ /* I/O hints for the BIO layer */ #define XBF_SYNCIO (1 << 10)/* treat this buffer as synchronous I/O */ Loading @@ -70,6 +71,7 @@ typedef unsigned int xfs_buf_flags_t; { XBF_ASYNC, "ASYNC" }, \ { XBF_DONE, "DONE" }, \ { XBF_STALE, "STALE" }, \ { XBF_WRITE_FAIL, "WRITE_FAIL" }, \ { XBF_SYNCIO, "SYNCIO" }, \ { XBF_FUA, "FUA" }, \ { XBF_FLUSH, "FLUSH" }, \ Loading @@ -80,6 +82,7 @@ typedef unsigned int xfs_buf_flags_t; { _XBF_DELWRI_Q, "DELWRI_Q" }, \ { _XBF_COMPOUND, "COMPOUND" } /* * Internal state flags. */ Loading Loading @@ -269,9 +272,6 @@ extern void xfs_buf_unlock(xfs_buf_t *); /* Buffer Read and Write Routines */ extern int xfs_bwrite(struct xfs_buf *bp); extern void xfsbdstrat(struct xfs_mount *, struct xfs_buf *); extern void xfs_buf_ioend(xfs_buf_t *, int); extern void xfs_buf_ioerror(xfs_buf_t *, int); extern void xfs_buf_ioerror_alert(struct xfs_buf *, const char *func); Loading @@ -282,6 +282,8 @@ extern void xfs_buf_iomove(xfs_buf_t *, size_t, size_t, void *, #define xfs_buf_zero(bp, off, len) \ xfs_buf_iomove((bp), (off), (len), NULL, XBRW_ZERO) extern int xfs_bioerror_relse(struct xfs_buf *); static inline int xfs_buf_geterror(xfs_buf_t *bp) { return bp ? bp->b_error : ENOMEM; Loading @@ -301,7 +303,8 @@ extern void xfs_buf_terminate(void); #define XFS_BUF_ZEROFLAGS(bp) \ ((bp)->b_flags &= ~(XBF_READ|XBF_WRITE|XBF_ASYNC| \ XBF_SYNCIO|XBF_FUA|XBF_FLUSH)) XBF_SYNCIO|XBF_FUA|XBF_FLUSH| \ XBF_WRITE_FAIL)) void xfs_buf_stale(struct xfs_buf *bp); #define XFS_BUF_UNSTALE(bp) ((bp)->b_flags &= ~XBF_STALE) Loading fs/xfs/xfs_buf_item.c +19 −2 Original line number Diff line number Diff line Loading @@ -495,6 +495,14 @@ xfs_buf_item_unpin( } } /* * Buffer IO error rate limiting. Limit it to no more than 10 messages per 30 * seconds so as to not spam logs too much on repeated detection of the same * buffer being bad.. */ DEFINE_RATELIMIT_STATE(xfs_buf_write_fail_rl_state, 30 * HZ, 10); STATIC uint xfs_buf_item_push( struct xfs_log_item *lip, Loading Loading @@ -523,6 +531,14 @@ xfs_buf_item_push( trace_xfs_buf_item_push(bip); /* has a previous flush failed due to IO errors? */ if ((bp->b_flags & XBF_WRITE_FAIL) && ___ratelimit(&xfs_buf_write_fail_rl_state, "XFS:")) { xfs_warn(bp->b_target->bt_mount, "Detected failing async write on buffer block 0x%llx. Retrying async write.\n", (long long)bp->b_bn); } if (!xfs_buf_delwri_queue(bp, buffer_list)) rval = XFS_ITEM_FLUSHING; xfs_buf_unlock(bp); Loading Loading @@ -1095,8 +1111,9 @@ xfs_buf_iodone_callbacks( xfs_buf_ioerror(bp, 0); /* errno of 0 unsets the flag */ if (!XFS_BUF_ISSTALE(bp)) { bp->b_flags |= XBF_WRITE | XBF_ASYNC | XBF_DONE; if (!(bp->b_flags & (XBF_STALE|XBF_WRITE_FAIL))) { bp->b_flags |= XBF_WRITE | XBF_ASYNC | XBF_DONE | XBF_WRITE_FAIL; xfs_buf_iorequest(bp); } else { xfs_buf_relse(bp); Loading Loading
fs/xfs/xfs_bmap.c +17 −6 Original line number Diff line number Diff line Loading @@ -3648,10 +3648,19 @@ xfs_bmap_btalloc( int isaligned; int tryagain; int error; int stripe_align; ASSERT(ap->length); mp = ap->ip->i_mount; /* stripe alignment for allocation is determined by mount parameters */ stripe_align = 0; if (mp->m_swidth && (mp->m_flags & XFS_MOUNT_SWALLOC)) stripe_align = mp->m_swidth; else if (mp->m_dalign) stripe_align = mp->m_dalign; align = ap->userdata ? xfs_get_extsz_hint(ap->ip) : 0; if (unlikely(align)) { error = xfs_bmap_extsize_align(mp, &ap->got, &ap->prev, Loading @@ -3660,6 +3669,8 @@ xfs_bmap_btalloc( ASSERT(!error); ASSERT(ap->length); } nullfb = *ap->firstblock == NULLFSBLOCK; fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, *ap->firstblock); if (nullfb) { Loading Loading @@ -3735,7 +3746,7 @@ xfs_bmap_btalloc( */ if (!ap->flist->xbf_low && ap->aeof) { if (!ap->offset) { args.alignment = mp->m_dalign; args.alignment = stripe_align; atype = args.type; isaligned = 1; /* Loading @@ -3760,13 +3771,13 @@ xfs_bmap_btalloc( * of minlen+alignment+slop doesn't go up * between the calls. */ if (blen > mp->m_dalign && blen <= args.maxlen) nextminlen = blen - mp->m_dalign; if (blen > stripe_align && blen <= args.maxlen) nextminlen = blen - stripe_align; else nextminlen = args.minlen; if (nextminlen + mp->m_dalign > args.minlen + 1) if (nextminlen + stripe_align > args.minlen + 1) args.minalignslop = nextminlen + mp->m_dalign - nextminlen + stripe_align - args.minlen - 1; else args.minalignslop = 0; Loading @@ -3788,7 +3799,7 @@ xfs_bmap_btalloc( */ args.type = atype; args.fsbno = ap->blkno; args.alignment = mp->m_dalign; args.alignment = stripe_align; args.minlen = nextminlen; args.minalignslop = 0; isaligned = 1; Loading
fs/xfs/xfs_bmap_util.c +12 −2 Original line number Diff line number Diff line Loading @@ -1187,7 +1187,12 @@ xfs_zero_remaining_bytes( XFS_BUF_UNWRITE(bp); XFS_BUF_READ(bp); XFS_BUF_SET_ADDR(bp, xfs_fsb_to_db(ip, imap.br_startblock)); xfsbdstrat(mp, bp); if (XFS_FORCED_SHUTDOWN(mp)) { error = XFS_ERROR(EIO); break; } xfs_buf_iorequest(bp); error = xfs_buf_iowait(bp); if (error) { xfs_buf_ioerror_alert(bp, Loading @@ -1200,7 +1205,12 @@ xfs_zero_remaining_bytes( XFS_BUF_UNDONE(bp); XFS_BUF_UNREAD(bp); XFS_BUF_WRITE(bp); xfsbdstrat(mp, bp); if (XFS_FORCED_SHUTDOWN(mp)) { error = XFS_ERROR(EIO); break; } xfs_buf_iorequest(bp); error = xfs_buf_iowait(bp); if (error) { xfs_buf_ioerror_alert(bp, Loading
fs/xfs/xfs_buf.c +14 −23 Original line number Diff line number Diff line Loading @@ -698,7 +698,11 @@ xfs_buf_read_uncached( bp->b_flags |= XBF_READ; bp->b_ops = ops; xfsbdstrat(target->bt_mount, bp); if (XFS_FORCED_SHUTDOWN(target->bt_mount)) { xfs_buf_relse(bp); return NULL; } xfs_buf_iorequest(bp); xfs_buf_iowait(bp); return bp; } Loading Loading @@ -1089,7 +1093,7 @@ xfs_bioerror( * This is meant for userdata errors; metadata bufs come with * iodone functions attached, so that we can track down errors. */ STATIC int int xfs_bioerror_relse( struct xfs_buf *bp) { Loading Loading @@ -1152,7 +1156,7 @@ xfs_bwrite( ASSERT(xfs_buf_islocked(bp)); bp->b_flags |= XBF_WRITE; bp->b_flags &= ~(XBF_ASYNC | XBF_READ | _XBF_DELWRI_Q); bp->b_flags &= ~(XBF_ASYNC | XBF_READ | _XBF_DELWRI_Q | XBF_WRITE_FAIL); xfs_bdstrat_cb(bp); Loading @@ -1164,25 +1168,6 @@ xfs_bwrite( return error; } /* * Wrapper around bdstrat so that we can stop data from going to disk in case * we are shutting down the filesystem. Typically user data goes thru this * path; one of the exceptions is the superblock. */ void xfsbdstrat( struct xfs_mount *mp, struct xfs_buf *bp) { if (XFS_FORCED_SHUTDOWN(mp)) { trace_xfs_bdstrat_shut(bp, _RET_IP_); xfs_bioerror_relse(bp); return; } xfs_buf_iorequest(bp); } STATIC void _xfs_buf_ioend( xfs_buf_t *bp, Loading Loading @@ -1516,6 +1501,12 @@ xfs_wait_buftarg( struct xfs_buf *bp; bp = list_first_entry(&dispose, struct xfs_buf, b_lru); list_del_init(&bp->b_lru); if (bp->b_flags & XBF_WRITE_FAIL) { xfs_alert(btp->bt_mount, "Corruption Alert: Buffer at block 0x%llx had permanent write failures!\n" "Please run xfs_repair to determine the extent of the problem.", (long long)bp->b_bn); } xfs_buf_rele(bp); } if (loop++ != 0) Loading Loading @@ -1789,7 +1780,7 @@ __xfs_buf_delwri_submit( blk_start_plug(&plug); list_for_each_entry_safe(bp, n, io_list, b_list) { bp->b_flags &= ~(_XBF_DELWRI_Q | XBF_ASYNC); bp->b_flags &= ~(_XBF_DELWRI_Q | XBF_ASYNC | XBF_WRITE_FAIL); bp->b_flags |= XBF_WRITE; if (!wait) { Loading
fs/xfs/xfs_buf.h +7 −4 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ typedef enum { #define XBF_ASYNC (1 << 4) /* initiator will not wait for completion */ #define XBF_DONE (1 << 5) /* all pages in the buffer uptodate */ #define XBF_STALE (1 << 6) /* buffer has been staled, do not find it */ #define XBF_WRITE_FAIL (1 << 24)/* async writes have failed on this buffer */ /* I/O hints for the BIO layer */ #define XBF_SYNCIO (1 << 10)/* treat this buffer as synchronous I/O */ Loading @@ -70,6 +71,7 @@ typedef unsigned int xfs_buf_flags_t; { XBF_ASYNC, "ASYNC" }, \ { XBF_DONE, "DONE" }, \ { XBF_STALE, "STALE" }, \ { XBF_WRITE_FAIL, "WRITE_FAIL" }, \ { XBF_SYNCIO, "SYNCIO" }, \ { XBF_FUA, "FUA" }, \ { XBF_FLUSH, "FLUSH" }, \ Loading @@ -80,6 +82,7 @@ typedef unsigned int xfs_buf_flags_t; { _XBF_DELWRI_Q, "DELWRI_Q" }, \ { _XBF_COMPOUND, "COMPOUND" } /* * Internal state flags. */ Loading Loading @@ -269,9 +272,6 @@ extern void xfs_buf_unlock(xfs_buf_t *); /* Buffer Read and Write Routines */ extern int xfs_bwrite(struct xfs_buf *bp); extern void xfsbdstrat(struct xfs_mount *, struct xfs_buf *); extern void xfs_buf_ioend(xfs_buf_t *, int); extern void xfs_buf_ioerror(xfs_buf_t *, int); extern void xfs_buf_ioerror_alert(struct xfs_buf *, const char *func); Loading @@ -282,6 +282,8 @@ extern void xfs_buf_iomove(xfs_buf_t *, size_t, size_t, void *, #define xfs_buf_zero(bp, off, len) \ xfs_buf_iomove((bp), (off), (len), NULL, XBRW_ZERO) extern int xfs_bioerror_relse(struct xfs_buf *); static inline int xfs_buf_geterror(xfs_buf_t *bp) { return bp ? bp->b_error : ENOMEM; Loading @@ -301,7 +303,8 @@ extern void xfs_buf_terminate(void); #define XFS_BUF_ZEROFLAGS(bp) \ ((bp)->b_flags &= ~(XBF_READ|XBF_WRITE|XBF_ASYNC| \ XBF_SYNCIO|XBF_FUA|XBF_FLUSH)) XBF_SYNCIO|XBF_FUA|XBF_FLUSH| \ XBF_WRITE_FAIL)) void xfs_buf_stale(struct xfs_buf *bp); #define XFS_BUF_UNSTALE(bp) ((bp)->b_flags &= ~XBF_STALE) Loading
fs/xfs/xfs_buf_item.c +19 −2 Original line number Diff line number Diff line Loading @@ -495,6 +495,14 @@ xfs_buf_item_unpin( } } /* * Buffer IO error rate limiting. Limit it to no more than 10 messages per 30 * seconds so as to not spam logs too much on repeated detection of the same * buffer being bad.. */ DEFINE_RATELIMIT_STATE(xfs_buf_write_fail_rl_state, 30 * HZ, 10); STATIC uint xfs_buf_item_push( struct xfs_log_item *lip, Loading Loading @@ -523,6 +531,14 @@ xfs_buf_item_push( trace_xfs_buf_item_push(bip); /* has a previous flush failed due to IO errors? */ if ((bp->b_flags & XBF_WRITE_FAIL) && ___ratelimit(&xfs_buf_write_fail_rl_state, "XFS:")) { xfs_warn(bp->b_target->bt_mount, "Detected failing async write on buffer block 0x%llx. Retrying async write.\n", (long long)bp->b_bn); } if (!xfs_buf_delwri_queue(bp, buffer_list)) rval = XFS_ITEM_FLUSHING; xfs_buf_unlock(bp); Loading Loading @@ -1095,8 +1111,9 @@ xfs_buf_iodone_callbacks( xfs_buf_ioerror(bp, 0); /* errno of 0 unsets the flag */ if (!XFS_BUF_ISSTALE(bp)) { bp->b_flags |= XBF_WRITE | XBF_ASYNC | XBF_DONE; if (!(bp->b_flags & (XBF_STALE|XBF_WRITE_FAIL))) { bp->b_flags |= XBF_WRITE | XBF_ASYNC | XBF_DONE | XBF_WRITE_FAIL; xfs_buf_iorequest(bp); } else { xfs_buf_relse(bp); Loading