|
@@ -487,6 +487,7 @@ _xfs_buf_find(
|
|
|
struct rb_node *parent;
|
|
|
xfs_buf_t *bp;
|
|
|
xfs_daddr_t blkno = map[0].bm_bn;
|
|
|
+ xfs_daddr_t eofs;
|
|
|
int numblks = 0;
|
|
|
int i;
|
|
|
|
|
@@ -498,6 +499,23 @@ _xfs_buf_find(
|
|
|
ASSERT(!(numbytes < (1 << btp->bt_sshift)));
|
|
|
ASSERT(!(BBTOB(blkno) & (xfs_off_t)btp->bt_smask));
|
|
|
|
|
|
+ /*
|
|
|
+ * Corrupted block numbers can get through to here, unfortunately, so we
|
|
|
+ * have to check that the buffer falls within the filesystem bounds.
|
|
|
+ */
|
|
|
+ eofs = XFS_FSB_TO_BB(btp->bt_mount, btp->bt_mount->m_sb.sb_dblocks);
|
|
|
+ if (blkno >= eofs) {
|
|
|
+ /*
|
|
|
+ * XXX (dgc): we should really be returning EFSCORRUPTED here,
|
|
|
+ * but none of the higher level infrastructure supports
|
|
|
+ * returning a specific error on buffer lookup failures.
|
|
|
+ */
|
|
|
+ xfs_alert(btp->bt_mount,
|
|
|
+ "%s: Block out of range: block 0x%llx, EOFS 0x%llx ",
|
|
|
+ __func__, blkno, eofs);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
/* get tree root */
|
|
|
pag = xfs_perag_get(btp->bt_mount,
|
|
|
xfs_daddr_to_agno(btp->bt_mount, blkno));
|
|
@@ -1487,6 +1505,8 @@ restart:
|
|
|
while (!list_empty(&btp->bt_lru)) {
|
|
|
bp = list_first_entry(&btp->bt_lru, struct xfs_buf, b_lru);
|
|
|
if (atomic_read(&bp->b_hold) > 1) {
|
|
|
+ trace_xfs_buf_wait_buftarg(bp, _RET_IP_);
|
|
|
+ list_move_tail(&bp->b_lru, &btp->bt_lru);
|
|
|
spin_unlock(&btp->bt_lru_lock);
|
|
|
delay(100);
|
|
|
goto restart;
|