|
@@ -749,6 +749,30 @@ _xfs_buf_read(
|
|
|
return xfs_buf_submit(bp);
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * If the caller passed in an ops structure and the buffer doesn't have ops
|
|
|
+ * assigned, set the ops and use them to verify the contents. If the contents
|
|
|
+ * cannot be verified, we'll clear XBF_DONE. We assume the buffer has no
|
|
|
+ * recorded errors and is already in XBF_DONE state.
|
|
|
+ */
|
|
|
+int
|
|
|
+xfs_buf_ensure_ops(
|
|
|
+ struct xfs_buf *bp,
|
|
|
+ const struct xfs_buf_ops *ops)
|
|
|
+{
|
|
|
+ ASSERT(bp->b_flags & XBF_DONE);
|
|
|
+ ASSERT(bp->b_error == 0);
|
|
|
+
|
|
|
+ if (!ops || bp->b_ops)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ bp->b_ops = ops;
|
|
|
+ bp->b_ops->verify_read(bp);
|
|
|
+ if (bp->b_error)
|
|
|
+ bp->b_flags &= ~XBF_DONE;
|
|
|
+ return bp->b_error;
|
|
|
+}
|
|
|
+
|
|
|
xfs_buf_t *
|
|
|
xfs_buf_read_map(
|
|
|
struct xfs_buftarg *target,
|
|
@@ -762,26 +786,32 @@ xfs_buf_read_map(
|
|
|
flags |= XBF_READ;
|
|
|
|
|
|
bp = xfs_buf_get_map(target, map, nmaps, flags);
|
|
|
- if (bp) {
|
|
|
- trace_xfs_buf_read(bp, flags, _RET_IP_);
|
|
|
+ if (!bp)
|
|
|
+ return NULL;
|
|
|
|
|
|
- if (!(bp->b_flags & XBF_DONE)) {
|
|
|
- XFS_STATS_INC(target->bt_mount, xb_get_read);
|
|
|
- bp->b_ops = ops;
|
|
|
- _xfs_buf_read(bp, flags);
|
|
|
- } else if (flags & XBF_ASYNC) {
|
|
|
- /*
|
|
|
- * Read ahead call which is already satisfied,
|
|
|
- * drop the buffer
|
|
|
- */
|
|
|
- xfs_buf_relse(bp);
|
|
|
- return NULL;
|
|
|
- } else {
|
|
|
- /* We do not want read in the flags */
|
|
|
- bp->b_flags &= ~XBF_READ;
|
|
|
- }
|
|
|
+ trace_xfs_buf_read(bp, flags, _RET_IP_);
|
|
|
+
|
|
|
+ if (!(bp->b_flags & XBF_DONE)) {
|
|
|
+ XFS_STATS_INC(target->bt_mount, xb_get_read);
|
|
|
+ bp->b_ops = ops;
|
|
|
+ _xfs_buf_read(bp, flags);
|
|
|
+ return bp;
|
|
|
+ }
|
|
|
+
|
|
|
+ xfs_buf_ensure_ops(bp, ops);
|
|
|
+
|
|
|
+ if (flags & XBF_ASYNC) {
|
|
|
+ /*
|
|
|
+ * Read ahead call which is already satisfied,
|
|
|
+ * drop the buffer
|
|
|
+ */
|
|
|
+ xfs_buf_relse(bp);
|
|
|
+ return NULL;
|
|
|
}
|
|
|
|
|
|
+ /* We do not want read in the flags */
|
|
|
+ bp->b_flags &= ~XBF_READ;
|
|
|
+ ASSERT(bp->b_ops != NULL || ops == NULL);
|
|
|
return bp;
|
|
|
}
|
|
|
|