diff options
Diffstat (limited to 'fs/xfs/xfs_dir2_leaf.c')
| -rw-r--r-- | fs/xfs/xfs_dir2_leaf.c | 172 | 
1 files changed, 121 insertions, 51 deletions
| diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c index 0b296253bd01..60cd2fa4e047 100644 --- a/fs/xfs/xfs_dir2_leaf.c +++ b/fs/xfs/xfs_dir2_leaf.c @@ -48,6 +48,83 @@ static void xfs_dir2_leaf_log_bests(struct xfs_trans *tp, struct xfs_buf *bp,  				    int first, int last);  static void xfs_dir2_leaf_log_tail(struct xfs_trans *tp, struct xfs_buf *bp); +static void +xfs_dir2_leaf_verify( +	struct xfs_buf		*bp, +	__be16			magic) +{ +	struct xfs_mount	*mp = bp->b_target->bt_mount; +	struct xfs_dir2_leaf_hdr *hdr = bp->b_addr; +	int			block_ok = 0; + +	block_ok = hdr->info.magic == magic; +	if (!block_ok) { +		XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, hdr); +		xfs_buf_ioerror(bp, EFSCORRUPTED); +	} +} + +static void +xfs_dir2_leaf1_read_verify( +	struct xfs_buf	*bp) +{ +	xfs_dir2_leaf_verify(bp, cpu_to_be16(XFS_DIR2_LEAF1_MAGIC)); +} + +static void +xfs_dir2_leaf1_write_verify( +	struct xfs_buf	*bp) +{ +	xfs_dir2_leaf_verify(bp, cpu_to_be16(XFS_DIR2_LEAF1_MAGIC)); +} + +void +xfs_dir2_leafn_read_verify( +	struct xfs_buf	*bp) +{ +	xfs_dir2_leaf_verify(bp, cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); +} + +void +xfs_dir2_leafn_write_verify( +	struct xfs_buf	*bp) +{ +	xfs_dir2_leaf_verify(bp, cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); +} + +static const struct xfs_buf_ops xfs_dir2_leaf1_buf_ops = { +	.verify_read = xfs_dir2_leaf1_read_verify, +	.verify_write = xfs_dir2_leaf1_write_verify, +}; + +const struct xfs_buf_ops xfs_dir2_leafn_buf_ops = { +	.verify_read = xfs_dir2_leafn_read_verify, +	.verify_write = xfs_dir2_leafn_write_verify, +}; + +static int +xfs_dir2_leaf_read( +	struct xfs_trans	*tp, +	struct xfs_inode	*dp, +	xfs_dablk_t		fbno, +	xfs_daddr_t		mappedbno, +	struct xfs_buf		**bpp) +{ +	return xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp, +				XFS_DATA_FORK, &xfs_dir2_leaf1_buf_ops); +} + +int +xfs_dir2_leafn_read( +	struct xfs_trans	*tp, +	struct xfs_inode	*dp, +	xfs_dablk_t		fbno, +	xfs_daddr_t		mappedbno, +	struct xfs_buf		**bpp) +{ +	return xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp, +				XFS_DATA_FORK, &xfs_dir2_leafn_buf_ops); +}  /*   * Convert a block form directory to a leaf form directory. @@ -125,6 +202,7 @@ xfs_dir2_block_to_leaf(  	/*  	 * Fix up the block header, make it a data block.  	 */ +	dbp->b_ops = &xfs_dir2_data_buf_ops;  	hdr->magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC);  	if (needscan)  		xfs_dir2_data_freescan(mp, hdr, &needlog); @@ -311,15 +389,11 @@ xfs_dir2_leaf_addname(  	dp = args->dp;  	tp = args->trans;  	mp = dp->i_mount; -	/* -	 * Read the leaf block. -	 */ -	error = xfs_da_read_buf(tp, dp, mp->m_dirleafblk, -1, &lbp, -		XFS_DATA_FORK); -	if (error) { + +	error = xfs_dir2_leaf_read(tp, dp, mp->m_dirleafblk, -1, &lbp); +	if (error)  		return error; -	} -	ASSERT(lbp != NULL); +  	/*  	 * Look up the entry by hash value and name.  	 * We know it's not there, our caller has already done a lookup. @@ -494,22 +568,21 @@ xfs_dir2_leaf_addname(  		hdr = dbp->b_addr;  		bestsp[use_block] = hdr->bestfree[0].length;  		grown = 1; -	} -	/* -	 * Already had space in some data block. -	 * Just read that one in. -	 */ -	else { -		if ((error = -		    xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, use_block), -			    -1, &dbp, XFS_DATA_FORK))) { +	} else { +		/* +		 * Already had space in some data block. +		 * Just read that one in. +		 */ +		error = xfs_dir2_data_read(tp, dp, +					   xfs_dir2_db_to_da(mp, use_block), +					   -1, &dbp); +		if (error) {  			xfs_trans_brelse(tp, lbp);  			return error;  		}  		hdr = dbp->b_addr;  		grown = 0;  	} -	xfs_dir2_data_check(dp, dbp);  	/*  	 * Point to the biggest freespace in our data block.  	 */ @@ -892,10 +965,9 @@ xfs_dir2_leaf_readbuf(  	 * Read the directory block starting at the first mapping.  	 */  	mip->curdb = xfs_dir2_da_to_db(mp, map->br_startoff); -	error = xfs_da_read_buf(NULL, dp, map->br_startoff, +	error = xfs_dir2_data_read(NULL, dp, map->br_startoff,  			map->br_blockcount >= mp->m_dirblkfsbs ? -			    XFS_FSB_TO_DADDR(mp, map->br_startblock) : -1, -			&bp, XFS_DATA_FORK); +			    XFS_FSB_TO_DADDR(mp, map->br_startblock) : -1, &bp);  	/*  	 * Should just skip over the data block instead of giving up. @@ -922,11 +994,11 @@ xfs_dir2_leaf_readbuf(  		 */  		if (i > mip->ra_current &&  		    map[mip->ra_index].br_blockcount >= mp->m_dirblkfsbs) { -			xfs_buf_readahead(mp->m_ddev_targp, +			xfs_dir2_data_readahead(NULL, dp, +				map[mip->ra_index].br_startoff + mip->ra_offset,  				XFS_FSB_TO_DADDR(mp,  					map[mip->ra_index].br_startblock + -							mip->ra_offset), -				(int)BTOBB(mp->m_dirblksize)); +							mip->ra_offset));  			mip->ra_current = i;  		} @@ -935,10 +1007,9 @@ xfs_dir2_leaf_readbuf(  		 * use our mapping, but this is a very rare case.  		 */  		else if (i > mip->ra_current) { -			xfs_da_reada_buf(NULL, dp, +			xfs_dir2_data_readahead(NULL, dp,  					map[mip->ra_index].br_startoff + -							mip->ra_offset, -					XFS_DATA_FORK); +							mip->ra_offset, -1);  			mip->ra_current = i;  		} @@ -1177,15 +1248,14 @@ xfs_dir2_leaf_init(  	 * Get the buffer for the block.  	 */  	error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(mp, bno), -1, &bp, -		XFS_DATA_FORK); -	if (error) { +			       XFS_DATA_FORK); +	if (error)  		return error; -	} -	ASSERT(bp != NULL); -	leaf = bp->b_addr; +  	/*  	 * Initialize the header.  	 */ +	leaf = bp->b_addr;  	leaf->hdr.info.magic = cpu_to_be16(magic);  	leaf->hdr.info.forw = 0;  	leaf->hdr.info.back = 0; @@ -1198,10 +1268,12 @@ xfs_dir2_leaf_init(  	 * the block.  	 */  	if (magic == XFS_DIR2_LEAF1_MAGIC) { +		bp->b_ops = &xfs_dir2_leaf1_buf_ops;  		ltp = xfs_dir2_leaf_tail_p(mp, leaf);  		ltp->bestcount = 0;  		xfs_dir2_leaf_log_tail(tp, bp); -	} +	} else +		bp->b_ops = &xfs_dir2_leafn_buf_ops;  	*bpp = bp;  	return 0;  } @@ -1372,13 +1444,11 @@ xfs_dir2_leaf_lookup_int(  	dp = args->dp;  	tp = args->trans;  	mp = dp->i_mount; -	/* -	 * Read the leaf block into the buffer. -	 */ -	error = xfs_da_read_buf(tp, dp, mp->m_dirleafblk, -1, &lbp, -							XFS_DATA_FORK); + +	error = xfs_dir2_leaf_read(tp, dp, mp->m_dirleafblk, -1, &lbp);  	if (error)  		return error; +  	*lbpp = lbp;  	leaf = lbp->b_addr;  	xfs_dir2_leaf_check(dp, lbp); @@ -1409,14 +1479,13 @@ xfs_dir2_leaf_lookup_int(  		if (newdb != curdb) {  			if (dbp)  				xfs_trans_brelse(tp, dbp); -			error = xfs_da_read_buf(tp, dp, -						xfs_dir2_db_to_da(mp, newdb), -						-1, &dbp, XFS_DATA_FORK); +			error = xfs_dir2_data_read(tp, dp, +						   xfs_dir2_db_to_da(mp, newdb), +						   -1, &dbp);  			if (error) {  				xfs_trans_brelse(tp, lbp);  				return error;  			} -			xfs_dir2_data_check(dp, dbp);  			curdb = newdb;  		}  		/* @@ -1451,9 +1520,9 @@ xfs_dir2_leaf_lookup_int(  		ASSERT(cidb != -1);  		if (cidb != curdb) {  			xfs_trans_brelse(tp, dbp); -			error = xfs_da_read_buf(tp, dp, -						xfs_dir2_db_to_da(mp, cidb), -						-1, &dbp, XFS_DATA_FORK); +			error = xfs_dir2_data_read(tp, dp, +						   xfs_dir2_db_to_da(mp, cidb), +						   -1, &dbp);  			if (error) {  				xfs_trans_brelse(tp, lbp);  				return error; @@ -1738,10 +1807,9 @@ xfs_dir2_leaf_trim_data(  	/*  	 * Read the offending data block.  We need its buffer.  	 */ -	if ((error = xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, db), -1, &dbp, -			XFS_DATA_FORK))) { +	error = xfs_dir2_data_read(tp, dp, xfs_dir2_db_to_da(mp, db), -1, &dbp); +	if (error)  		return error; -	}  	leaf = lbp->b_addr;  	ltp = xfs_dir2_leaf_tail_p(mp, leaf); @@ -1864,10 +1932,9 @@ xfs_dir2_node_to_leaf(  	/*  	 * Read the freespace block.  	 */ -	if ((error = xfs_da_read_buf(tp, dp, mp->m_dirfreeblk, -1, &fbp, -			XFS_DATA_FORK))) { +	error = xfs_dir2_free_read(tp, dp,  mp->m_dirfreeblk, &fbp); +	if (error)  		return error; -	}  	free = fbp->b_addr;  	ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC));  	ASSERT(!free->hdr.firstdb); @@ -1890,7 +1957,10 @@ xfs_dir2_node_to_leaf(  		xfs_dir2_leaf_compact(args, lbp);  	else  		xfs_dir2_leaf_log_header(tp, lbp); + +	lbp->b_ops = &xfs_dir2_leaf1_buf_ops;  	leaf->hdr.info.magic = cpu_to_be16(XFS_DIR2_LEAF1_MAGIC); +  	/*  	 * Set up the leaf tail from the freespace block.  	 */ |