diff options
| author | Christoph Hellwig <hch@lst.de> | 2013-04-21 14:53:46 -0500 | 
|---|---|---|
| committer | Ben Myers <bpm@sgi.com> | 2013-04-21 14:53:46 -0500 | 
| commit | ee1a47ab0e77600fcbdf1c87d461bd8f3f63150d (patch) | |
| tree | 6340d9f4b8b53c0d18045da1372599645375efce /fs/xfs/xfs_bmap.c | |
| parent | a2050646f655a90400cbb66c3866d2e0137eee0c (diff) | |
| download | olio-linux-3.10-ee1a47ab0e77600fcbdf1c87d461bd8f3f63150d.tar.xz olio-linux-3.10-ee1a47ab0e77600fcbdf1c87d461bd8f3f63150d.zip  | |
xfs: add support for large btree blocks
Add support for larger btree blocks that contains a CRC32C checksum,
a filesystem uuid and block number for detecting filesystem
consistency and out of place writes.
[dchinner@redhat.com] Also include an owner field to allow reverse
mappings to be implemented for improved repairability and a LSN
field to so that log recovery can easily determine the last
modification that made it to disk for each buffer.
[dchinner@redhat.com] Add buffer log format flags to indicate the
type of buffer to recovery so that we don't have to do blind magic
number tests to determine what the buffer is.
[dchinner@redhat.com] Modified to fit into the verifier structure.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Ben Myers <bpm@sgi.com>
Signed-off-by: Ben Myers <bpm@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_bmap.c')
| -rw-r--r-- | fs/xfs/xfs_bmap.c | 47 | 
1 files changed, 31 insertions, 16 deletions
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 20efb397a7f..0531cd3927a 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -439,11 +439,15 @@ xfs_bmap_sanity_check(  {  	struct xfs_btree_block  *block = XFS_BUF_TO_BLOCK(bp); -	if (block->bb_magic != cpu_to_be32(XFS_BMAP_MAGIC) || -	    be16_to_cpu(block->bb_level) != level || +	if (block->bb_magic != cpu_to_be32(XFS_BMAP_CRC_MAGIC) && +	    block->bb_magic != cpu_to_be32(XFS_BMAP_MAGIC)) +		return 0; + +	if (be16_to_cpu(block->bb_level) != level ||  	    be16_to_cpu(block->bb_numrecs) == 0 ||  	    be16_to_cpu(block->bb_numrecs) > mp->m_bmap_dmxr[level != 0])  		return 0; +  	return 1;  } @@ -1031,6 +1035,7 @@ xfs_bmap_extents_to_btree(  	xfs_extnum_t		nextents;	/* number of file extents */  	xfs_bmbt_ptr_t		*pp;		/* root block address pointer */ +	mp = ip->i_mount;  	ifp = XFS_IFORK_PTR(ip, whichfork);  	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS); @@ -1044,16 +1049,18 @@ xfs_bmap_extents_to_btree(  	 * Fill in the root.  	 */  	block = ifp->if_broot; -	block->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC); -	block->bb_level = cpu_to_be16(1); -	block->bb_numrecs = cpu_to_be16(1); -	block->bb_u.l.bb_leftsib = cpu_to_be64(NULLDFSBNO); -	block->bb_u.l.bb_rightsib = cpu_to_be64(NULLDFSBNO); +	if (xfs_sb_version_hascrc(&mp->m_sb)) +		xfs_btree_init_block_int(mp, block, XFS_BUF_DADDR_NULL, +				 XFS_BMAP_CRC_MAGIC, 1, 1, ip->i_ino, +				 XFS_BTREE_LONG_PTRS | XFS_BTREE_CRC_BLOCKS); +	else +		xfs_btree_init_block_int(mp, block, XFS_BUF_DADDR_NULL, +				 XFS_BMAP_MAGIC, 1, 1, ip->i_ino, +				 XFS_BTREE_LONG_PTRS);  	/*  	 * Need a cursor.  Can't allocate until bb_level is filled in.  	 */ -	mp = ip->i_mount;  	cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);  	cur->bc_private.b.firstblock = *firstblock;  	cur->bc_private.b.flist = flist; @@ -1102,10 +1109,15 @@ xfs_bmap_extents_to_btree(  	 */  	abp->b_ops = &xfs_bmbt_buf_ops;  	ablock = XFS_BUF_TO_BLOCK(abp); -	ablock->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC); -	ablock->bb_level = 0; -	ablock->bb_u.l.bb_leftsib = cpu_to_be64(NULLDFSBNO); -	ablock->bb_u.l.bb_rightsib = cpu_to_be64(NULLDFSBNO); +	if (xfs_sb_version_hascrc(&mp->m_sb)) +		xfs_btree_init_block_int(mp, ablock, abp->b_bn, +				XFS_BMAP_CRC_MAGIC, 0, 0, ip->i_ino, +				XFS_BTREE_LONG_PTRS | XFS_BTREE_CRC_BLOCKS); +	else +		xfs_btree_init_block_int(mp, ablock, abp->b_bn, +				XFS_BMAP_MAGIC, 0, 0, ip->i_ino, +				XFS_BTREE_LONG_PTRS); +  	arp = XFS_BMBT_REC_ADDR(mp, ablock, 1);  	nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);  	for (cnt = i = 0; i < nextents; i++) { @@ -1155,7 +1167,8 @@ xfs_bmap_local_to_extents(  	xfs_extlen_t	total,		/* total blocks needed by transaction */  	int		*logflagsp,	/* inode logging flags */  	int		whichfork, -	void		(*init_fn)(struct xfs_buf *bp, +	void		(*init_fn)(struct xfs_trans *tp, +				   struct xfs_buf *bp,  				   struct xfs_inode *ip,  				   struct xfs_ifork *ifp))  { @@ -1207,7 +1220,7 @@ xfs_bmap_local_to_extents(  		bp = xfs_btree_get_bufl(args.mp, tp, args.fsbno, 0);  		/* initialise the block and copy the data */ -		init_fn(bp, ip, ifp); +		init_fn(tp, bp, ip, ifp);  		/* account for the change in fork size and log everything */  		xfs_trans_log_buf(tp, bp, 0, ifp->if_bytes - 1); @@ -1314,16 +1327,19 @@ xfs_bmap_add_attrfork_extents(   */  STATIC void  xfs_bmap_local_to_extents_init_fn( +	struct xfs_trans	*tp,  	struct xfs_buf		*bp,  	struct xfs_inode	*ip,  	struct xfs_ifork	*ifp)  {  	bp->b_ops = &xfs_bmbt_buf_ops;  	memcpy(bp->b_addr, ifp->if_u1.if_data, ifp->if_bytes); +	xfs_trans_buf_set_type(tp, bp, XFS_BLF_BTREE_BUF);  }  STATIC void  xfs_symlink_local_to_remote( +	struct xfs_trans	*tp,  	struct xfs_buf		*bp,  	struct xfs_inode	*ip,  	struct xfs_ifork	*ifp) @@ -1342,8 +1358,7 @@ xfs_symlink_local_to_remote(   *   * XXX (dgc): investigate whether directory conversion can use the generic   * formatting callout. It should be possible - it's just a very complex - * formatter. it would also require passing the transaction through to the init - * function. + * formatter.   */  STATIC int					/* error */  xfs_bmap_add_attrfork_local(  |