summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2012-11-12 22:54:19 +1100
committerBen Myers <bpm@sgi.com>2012-11-15 21:35:00 -0600
commitcfb02852226aa449fe27075caffe88726507668c (patch)
tree796ede500b5fe4d3b0a7e7ec4621f85347741d79
parentda6958c873ecd846d71fafbfe0f6168bb9c2c99e (diff)
downloadlwn-cfb02852226aa449fe27075caffe88726507668c.tar.gz
lwn-cfb02852226aa449fe27075caffe88726507668c.zip
xfs: add buffer pre-write callback
Add a callback to the buffer write path to enable verification of the buffer and CRC calculation prior to issuing the write to the underlying storage. If the callback function detects some kind of failure or error condition, it must mark the buffer with an error so that the caller can take appropriate action. In the case of xfs_buf_ioapply(), a corrupt metadta buffer willt rigger a shutdown of the filesystem, because something is clearly wrong and we can't allow corrupt metadata to be written to disk. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Phil White <pwhite@sgi.com> Signed-off-by: Ben Myers <bpm@sgi.com>
-rw-r--r--fs/xfs/xfs_buf.c16
-rw-r--r--fs/xfs/xfs_buf.h3
2 files changed, 19 insertions, 0 deletions
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_);
@@ -1324,6 +1326,20 @@ _xfs_buf_ioapply(
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 -
* _xfs_buf_ioapply_vec() will modify them appropriately for each
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