diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index fbc965fc075a..bd1a948ee39c 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c @@ -569,7 +569,9 @@ found: */ if (bp->b_flags & XBF_STALE) { ASSERT((bp->b_flags & _XBF_DELWRI_Q) == 0); + ASSERT(bp->b_iodone == NULL); bp->b_flags &= _XBF_KMEM | _XBF_PAGES; + bp->b_pre_io = NULL; } trace_xfs_buf_find(bp, flags, _RET_IP_); @@ -1323,6 +1325,20 @@ _xfs_buf_ioapply( /* we only use the buffer cache for meta-data */ rw |= REQ_META; + /* + * run the pre-io callback function if it exists. If this function + * fails it will mark the buffer with an error and the IO should + * not be dispatched. + */ + if (bp->b_pre_io) { + bp->b_pre_io(bp); + if (bp->b_error) { + xfs_force_shutdown(bp->b_target->bt_mount, + SHUTDOWN_CORRUPT_INCORE); + return; + } + } + /* * Walk all the vectors issuing IO on them. Set up the initial offset * into the buffer and the desired IO size before we start - diff --git a/fs/xfs/xfs_buf.h b/fs/xfs/xfs_buf.h index 677b1dc822f4..51bc16a1cd9c 100644 --- a/fs/xfs/xfs_buf.h +++ b/fs/xfs/xfs_buf.h @@ -155,6 +155,9 @@ typedef struct xfs_buf { unsigned int b_offset; /* page offset in first page */ unsigned short b_error; /* error code on I/O */ + void (*b_pre_io)(struct xfs_buf *); + /* pre-io callback function */ + #ifdef XFS_BUF_LOCK_TRACKING int b_last_holder; #endif