diff options
Diffstat (limited to 'fs/xfs/xfs_buf.c')
| -rw-r--r-- | fs/xfs/xfs_buf.c | 20 | 
1 files changed, 20 insertions, 0 deletions
| diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index 56d1614760cf..fbbb9eb92e32 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c @@ -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; |