diff options
Diffstat (limited to 'fs/xfs/xfs_alloc.c')
| -rw-r--r-- | fs/xfs/xfs_alloc.c | 39 | 
1 files changed, 38 insertions, 1 deletions
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c index c9eb955a49c..38b4ab8957f 100644 --- a/fs/xfs/xfs_alloc.c +++ b/fs/xfs/xfs_alloc.c @@ -430,6 +430,43 @@ xfs_alloc_fixup_trees(  	return 0;  } +void +xfs_agfl_read_verify( +	struct xfs_buf	*bp) +{ +#ifdef WHEN_CRCS_COME_ALONG +	/* +	 * we cannot actually do any verification of the AGFL because mkfs does +	 * not initialise the AGFL to zero or NULL. Hence the only valid part of +	 * the AGFL is what the AGF says is active. We can't get to the AGF, so +	 * we can't verify just those entries are valid. +	 * +	 * This problem goes away when the CRC format change comes along as that +	 * requires the AGFL to be initialised by mkfs. At that point, we can +	 * verify the blocks in the agfl -active or not- lie within the bounds +	 * of the AG. Until then, just leave this check ifdef'd out. +	 */ +	struct xfs_mount *mp = bp->b_target->bt_mount; +	struct xfs_agfl	*agfl = XFS_BUF_TO_AGFL(bp); +	int		agfl_ok = 1; + +	int		i; + +	for (i = 0; i < XFS_AGFL_SIZE(mp); i++) { +		if (be32_to_cpu(agfl->agfl_bno[i]) == NULLAGBLOCK || +		    be32_to_cpu(agfl->agfl_bno[i]) >= mp->m_sb.sb_agblocks) +			agfl_ok = 0; +	} + +	if (!agfl_ok) { +		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, agfl); +		xfs_buf_ioerror(bp, EFSCORRUPTED); +	} +#endif +	bp->b_iodone = NULL; +	xfs_buf_ioend(bp, 0); +} +  /*   * Read in the allocation group free block array.   */ @@ -447,7 +484,7 @@ xfs_alloc_read_agfl(  	error = xfs_trans_read_buf(  			mp, tp, mp->m_ddev_targp,  			XFS_AG_DADDR(mp, agno, XFS_AGFL_DADDR(mp)), -			XFS_FSS_TO_BB(mp, 1), 0, &bp, NULL); +			XFS_FSS_TO_BB(mp, 1), 0, &bp, xfs_agfl_read_verify);  	if (error)  		return error;  	ASSERT(!xfs_buf_geterror(bp));  |