|
@@ -1112,6 +1112,126 @@ xfs_bdwrite(
|
|
|
xfs_buf_delwri_queue(bp, 1);
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * Called when we want to stop a buffer from getting written or read.
|
|
|
+ * We attach the EIO error, muck with its flags, and call biodone
|
|
|
+ * so that the proper iodone callbacks get called.
|
|
|
+ */
|
|
|
+STATIC int
|
|
|
+xfs_bioerror(
|
|
|
+ xfs_buf_t *bp)
|
|
|
+{
|
|
|
+#ifdef XFSERRORDEBUG
|
|
|
+ ASSERT(XFS_BUF_ISREAD(bp) || bp->b_iodone);
|
|
|
+#endif
|
|
|
+
|
|
|
+ /*
|
|
|
+ * No need to wait until the buffer is unpinned, we aren't flushing it.
|
|
|
+ */
|
|
|
+ XFS_BUF_ERROR(bp, EIO);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * We're calling biodone, so delete XBF_DONE flag.
|
|
|
+ */
|
|
|
+ XFS_BUF_UNREAD(bp);
|
|
|
+ XFS_BUF_UNDELAYWRITE(bp);
|
|
|
+ XFS_BUF_UNDONE(bp);
|
|
|
+ XFS_BUF_STALE(bp);
|
|
|
+
|
|
|
+ XFS_BUF_CLR_BDSTRAT_FUNC(bp);
|
|
|
+ xfs_biodone(bp);
|
|
|
+
|
|
|
+ return EIO;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Same as xfs_bioerror, except that we are releasing the buffer
|
|
|
+ * here ourselves, and avoiding the biodone call.
|
|
|
+ * This is meant for userdata errors; metadata bufs come with
|
|
|
+ * iodone functions attached, so that we can track down errors.
|
|
|
+ */
|
|
|
+STATIC int
|
|
|
+xfs_bioerror_relse(
|
|
|
+ struct xfs_buf *bp)
|
|
|
+{
|
|
|
+ int64_t fl = XFS_BUF_BFLAGS(bp);
|
|
|
+ /*
|
|
|
+ * No need to wait until the buffer is unpinned.
|
|
|
+ * We aren't flushing it.
|
|
|
+ *
|
|
|
+ * chunkhold expects B_DONE to be set, whether
|
|
|
+ * we actually finish the I/O or not. We don't want to
|
|
|
+ * change that interface.
|
|
|
+ */
|
|
|
+ XFS_BUF_UNREAD(bp);
|
|
|
+ XFS_BUF_UNDELAYWRITE(bp);
|
|
|
+ XFS_BUF_DONE(bp);
|
|
|
+ XFS_BUF_STALE(bp);
|
|
|
+ XFS_BUF_CLR_IODONE_FUNC(bp);
|
|
|
+ XFS_BUF_CLR_BDSTRAT_FUNC(bp);
|
|
|
+ if (!(fl & XFS_B_ASYNC)) {
|
|
|
+ /*
|
|
|
+ * Mark b_error and B_ERROR _both_.
|
|
|
+ * Lot's of chunkcache code assumes that.
|
|
|
+ * There's no reason to mark error for
|
|
|
+ * ASYNC buffers.
|
|
|
+ */
|
|
|
+ XFS_BUF_ERROR(bp, EIO);
|
|
|
+ XFS_BUF_FINISH_IOWAIT(bp);
|
|
|
+ } else {
|
|
|
+ xfs_buf_relse(bp);
|
|
|
+ }
|
|
|
+
|
|
|
+ return EIO;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+ * All xfs metadata buffers except log state machine buffers
|
|
|
+ * get this attached as their b_bdstrat callback function.
|
|
|
+ * This is so that we can catch a buffer
|
|
|
+ * after prematurely unpinning it to forcibly shutdown the filesystem.
|
|
|
+ */
|
|
|
+int
|
|
|
+xfs_bdstrat_cb(
|
|
|
+ struct xfs_buf *bp)
|
|
|
+{
|
|
|
+ if (XFS_FORCED_SHUTDOWN(bp->b_mount)) {
|
|
|
+ trace_xfs_bdstrat_shut(bp, _RET_IP_);
|
|
|
+ /*
|
|
|
+ * Metadata write that didn't get logged but
|
|
|
+ * written delayed anyway. These aren't associated
|
|
|
+ * with a transaction, and can be ignored.
|
|
|
+ */
|
|
|
+ if (!bp->b_iodone && !XFS_BUF_ISREAD(bp))
|
|
|
+ return xfs_bioerror_relse(bp);
|
|
|
+ else
|
|
|
+ return xfs_bioerror(bp);
|
|
|
+ }
|
|
|
+
|
|
|
+ xfs_buf_iorequest(bp);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * 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,
|