diff options
Diffstat (limited to 'fs/xfs/xfs_da_btree.c')
| -rw-r--r-- | fs/xfs/xfs_da_btree.c | 40 | 
1 files changed, 25 insertions, 15 deletions
diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c index 087950fc2eb..4d7696a0241 100644 --- a/fs/xfs/xfs_da_btree.c +++ b/fs/xfs/xfs_da_btree.c @@ -117,6 +117,12 @@ xfs_da_node_write_verify(  	xfs_da_node_verify(bp);  } +/* + * leaf/node format detection on trees is sketchy, so a node read can be done on + * leaf level blocks when detection identifies the tree as a node format tree + * incorrectly. In this case, we need to swap the verifier to match the correct + * format of the block being read. + */  static void  xfs_da_node_read_verify(  	struct xfs_buf		*bp) @@ -129,10 +135,12 @@ xfs_da_node_read_verify(  			xfs_da_node_verify(bp);  			break;  		case XFS_ATTR_LEAF_MAGIC: -			xfs_attr_leaf_read_verify(bp); +			bp->b_ops = &xfs_attr_leaf_buf_ops; +			bp->b_ops->verify_read(bp);  			return;  		case XFS_DIR2_LEAFN_MAGIC: -			xfs_dir2_leafn_read_verify(bp); +			bp->b_ops = &xfs_dir2_leafn_buf_ops; +			bp->b_ops->verify_read(bp);  			return;  		default:  			XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, @@ -140,12 +148,14 @@ xfs_da_node_read_verify(  			xfs_buf_ioerror(bp, EFSCORRUPTED);  			break;  	} - -	bp->b_pre_io = xfs_da_node_write_verify; -	bp->b_iodone = NULL; -	xfs_buf_ioend(bp, 0);  } +const struct xfs_buf_ops xfs_da_node_buf_ops = { +	.verify_read = xfs_da_node_read_verify, +	.verify_write = xfs_da_node_write_verify, +}; + +  int  xfs_da_node_read(  	struct xfs_trans	*tp, @@ -156,7 +166,7 @@ xfs_da_node_read(  	int			which_fork)  {  	return xfs_da_read_buf(tp, dp, bno, mappedbno, bpp, -					which_fork, xfs_da_node_read_verify); +					which_fork, &xfs_da_node_buf_ops);  }  /*======================================================================== @@ -193,7 +203,7 @@ xfs_da_node_create(xfs_da_args_t *args, xfs_dablk_t blkno, int level,  	xfs_trans_log_buf(tp, bp,  		XFS_DA_LOGRANGE(node, &node->hdr, sizeof(node->hdr))); -	bp->b_pre_io = xfs_da_node_write_verify; +	bp->b_ops = &xfs_da_node_buf_ops;  	*bpp = bp;  	return(0);  } @@ -394,7 +404,7 @@ xfs_da_root_split(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,  	memcpy(node, oldroot, size);  	xfs_trans_log_buf(tp, bp, 0, size - 1); -	bp->b_pre_io = blk1->bp->b_pre_io; +	bp->b_ops = blk1->bp->b_ops;  	blk1->bp = bp;  	blk1->blkno = blkno; @@ -828,11 +838,11 @@ xfs_da_root_join(xfs_da_state_t *state, xfs_da_state_blk_t *root_blk)  	/*  	 * This could be copying a leaf back into the root block in the case of  	 * there only being a single leaf block left in the tree. Hence we have -	 * to update the pre_io pointer as well to match the buffer type change +	 * to update the b_ops pointer as well to match the buffer type change  	 * that could occur.  	 */  	memcpy(root_blk->bp->b_addr, bp->b_addr, state->blocksize); -	root_blk->bp->b_pre_io = bp->b_pre_io; +	root_blk->bp->b_ops = bp->b_ops;  	xfs_trans_log_buf(args->trans, root_blk->bp, 0, state->blocksize - 1);  	error = xfs_da_shrink_inode(args, child, bp);  	return(error); @@ -2223,7 +2233,7 @@ xfs_da_read_buf(  	xfs_daddr_t		mappedbno,  	struct xfs_buf		**bpp,  	int			whichfork, -	xfs_buf_iodone_t	verifier) +	const struct xfs_buf_ops *ops)  {  	struct xfs_buf		*bp;  	struct xfs_buf_map	map; @@ -2245,7 +2255,7 @@ xfs_da_read_buf(  	error = xfs_trans_read_buf_map(dp->i_mount, trans,  					dp->i_mount->m_ddev_targp, -					mapp, nmap, 0, &bp, verifier); +					mapp, nmap, 0, &bp, ops);  	if (error)  		goto out_free; @@ -2303,7 +2313,7 @@ xfs_da_reada_buf(  	xfs_dablk_t		bno,  	xfs_daddr_t		mappedbno,  	int			whichfork, -	xfs_buf_iodone_t	verifier) +	const struct xfs_buf_ops *ops)  {  	struct xfs_buf_map	map;  	struct xfs_buf_map	*mapp; @@ -2322,7 +2332,7 @@ xfs_da_reada_buf(  	}  	mappedbno = mapp[0].bm_bn; -	xfs_buf_readahead_map(dp->i_mount->m_ddev_targp, mapp, nmap, NULL); +	xfs_buf_readahead_map(dp->i_mount->m_ddev_targp, mapp, nmap, ops);  out_free:  	if (mapp != &map)  |