diff options
Diffstat (limited to 'fs/xfs/xfs_bmap_util.c')
| -rw-r--r-- | fs/xfs/xfs_bmap_util.c | 160 | 
1 files changed, 93 insertions, 67 deletions
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index 9e3cc2146d5b..93e955262d07 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -219,20 +219,24 @@ xfs_bmap_eof(   */  /* - * Count leaf blocks given a range of extent records. + * Count leaf blocks given a range of extent records.  Delayed allocation + * extents are not counted towards the totals.   */  STATIC void  xfs_bmap_count_leaves( -	xfs_ifork_t		*ifp, -	xfs_extnum_t		idx, -	int			numrecs, -	int			*count) +	struct xfs_ifork	*ifp, +	xfs_extnum_t		*numrecs, +	xfs_filblks_t		*count)  { -	int		b; +	xfs_extnum_t		i; +	xfs_extnum_t		nr_exts = xfs_iext_count(ifp); -	for (b = 0; b < numrecs; b++) { -		xfs_bmbt_rec_host_t *frp = xfs_iext_get_ext(ifp, idx + b); -		*count += xfs_bmbt_get_blockcount(frp); +	for (i = 0; i < nr_exts; i++) { +		xfs_bmbt_rec_host_t *frp = xfs_iext_get_ext(ifp, i); +		if (!isnullstartblock(xfs_bmbt_get_startblock(frp))) { +			(*numrecs)++; +			*count += xfs_bmbt_get_blockcount(frp); +		}  	}  } @@ -245,7 +249,7 @@ xfs_bmap_disk_count_leaves(  	struct xfs_mount	*mp,  	struct xfs_btree_block	*block,  	int			numrecs, -	int			*count) +	xfs_filblks_t		*count)  {  	int		b;  	xfs_bmbt_rec_t	*frp; @@ -260,17 +264,18 @@ xfs_bmap_disk_count_leaves(   * Recursively walks each level of a btree   * to count total fsblocks in use.   */ -STATIC int                                     /* error */ +STATIC int  xfs_bmap_count_tree( -	xfs_mount_t     *mp,            /* file system mount point */ -	xfs_trans_t     *tp,            /* transaction pointer */ -	xfs_ifork_t	*ifp,		/* inode fork pointer */ -	xfs_fsblock_t   blockno,	/* file system block number */ -	int             levelin,	/* level in btree */ -	int		*count)		/* Count of blocks */ +	struct xfs_mount	*mp, +	struct xfs_trans	*tp, +	struct xfs_ifork	*ifp, +	xfs_fsblock_t		blockno, +	int			levelin, +	xfs_extnum_t		*nextents, +	xfs_filblks_t		*count)  {  	int			error; -	xfs_buf_t		*bp, *nbp; +	struct xfs_buf		*bp, *nbp;  	int			level = levelin;  	__be64			*pp;  	xfs_fsblock_t           bno = blockno; @@ -303,8 +308,9 @@ xfs_bmap_count_tree(  		/* Dive to the next level */  		pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]);  		bno = be64_to_cpu(*pp); -		if (unlikely((error = -		     xfs_bmap_count_tree(mp, tp, ifp, bno, level, count)) < 0)) { +		error = xfs_bmap_count_tree(mp, tp, ifp, bno, level, nextents, +				count); +		if (error) {  			xfs_trans_brelse(tp, bp);  			XFS_ERROR_REPORT("xfs_bmap_count_tree(1)",  					 XFS_ERRLEVEL_LOW, mp); @@ -316,6 +322,7 @@ xfs_bmap_count_tree(  		for (;;) {  			nextbno = be64_to_cpu(block->bb_u.l.bb_rightsib);  			numrecs = be16_to_cpu(block->bb_numrecs); +			(*nextents) += numrecs;  			xfs_bmap_disk_count_leaves(mp, block, numrecs, count);  			xfs_trans_brelse(tp, bp);  			if (nextbno == NULLFSBLOCK) @@ -334,46 +341,64 @@ xfs_bmap_count_tree(  }  /* - * Count fsblocks of the given fork. + * Count fsblocks of the given fork.  Delayed allocation extents are + * not counted towards the totals.   */ -static int					/* error */ +int  xfs_bmap_count_blocks( -	xfs_trans_t		*tp,		/* transaction pointer */ -	xfs_inode_t		*ip,		/* incore inode */ -	int			whichfork,	/* data or attr fork */ -	int			*count)		/* out: count of blocks */ +	struct xfs_trans	*tp, +	struct xfs_inode	*ip, +	int			whichfork, +	xfs_extnum_t		*nextents, +	xfs_filblks_t		*count)  { +	struct xfs_mount	*mp;	/* file system mount structure */ +	__be64			*pp;	/* pointer to block address */  	struct xfs_btree_block	*block;	/* current btree block */ +	struct xfs_ifork	*ifp;	/* fork structure */  	xfs_fsblock_t		bno;	/* block # of "block" */ -	xfs_ifork_t		*ifp;	/* fork structure */  	int			level;	/* btree level, for checking */ -	xfs_mount_t		*mp;	/* file system mount structure */ -	__be64			*pp;	/* pointer to block address */ +	int			error;  	bno = NULLFSBLOCK;  	mp = ip->i_mount; +	*nextents = 0; +	*count = 0;  	ifp = XFS_IFORK_PTR(ip, whichfork); -	if ( XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS ) { -		xfs_bmap_count_leaves(ifp, 0, xfs_iext_count(ifp), count); +	if (!ifp)  		return 0; -	} -	/* -	 * Root level must use BMAP_BROOT_PTR_ADDR macro to get ptr out. -	 */ -	block = ifp->if_broot; -	level = be16_to_cpu(block->bb_level); -	ASSERT(level > 0); -	pp = XFS_BMAP_BROOT_PTR_ADDR(mp, block, 1, ifp->if_broot_bytes); -	bno = be64_to_cpu(*pp); -	ASSERT(bno != NULLFSBLOCK); -	ASSERT(XFS_FSB_TO_AGNO(mp, bno) < mp->m_sb.sb_agcount); -	ASSERT(XFS_FSB_TO_AGBNO(mp, bno) < mp->m_sb.sb_agblocks); +	switch (XFS_IFORK_FORMAT(ip, whichfork)) { +	case XFS_DINODE_FMT_EXTENTS: +		xfs_bmap_count_leaves(ifp, nextents, count); +		return 0; +	case XFS_DINODE_FMT_BTREE: +		if (!(ifp->if_flags & XFS_IFEXTENTS)) { +			error = xfs_iread_extents(tp, ip, whichfork); +			if (error) +				return error; +		} -	if (unlikely(xfs_bmap_count_tree(mp, tp, ifp, bno, level, count) < 0)) { -		XFS_ERROR_REPORT("xfs_bmap_count_blocks(2)", XFS_ERRLEVEL_LOW, -				 mp); -		return -EFSCORRUPTED; +		/* +		 * Root level must use BMAP_BROOT_PTR_ADDR macro to get ptr out. +		 */ +		block = ifp->if_broot; +		level = be16_to_cpu(block->bb_level); +		ASSERT(level > 0); +		pp = XFS_BMAP_BROOT_PTR_ADDR(mp, block, 1, ifp->if_broot_bytes); +		bno = be64_to_cpu(*pp); +		ASSERT(bno != NULLFSBLOCK); +		ASSERT(XFS_FSB_TO_AGNO(mp, bno) < mp->m_sb.sb_agcount); +		ASSERT(XFS_FSB_TO_AGBNO(mp, bno) < mp->m_sb.sb_agblocks); + +		error = xfs_bmap_count_tree(mp, tp, ifp, bno, level, +				nextents, count); +		if (error) { +			XFS_ERROR_REPORT("xfs_bmap_count_blocks(2)", +					XFS_ERRLEVEL_LOW, mp); +			return -EFSCORRUPTED; +		} +		return 0;  	}  	return 0; @@ -389,11 +414,11 @@ xfs_getbmapx_fix_eof_hole(  	struct getbmapx		*out,		/* output structure */  	int			prealloced,	/* this is a file with  						 * preallocated data space */ -	__int64_t		end,		/* last block requested */ +	int64_t			end,		/* last block requested */  	xfs_fsblock_t		startblock,  	bool			moretocome)  { -	__int64_t		fixlen; +	int64_t			fixlen;  	xfs_mount_t		*mp;		/* file system mount point */  	xfs_ifork_t		*ifp;		/* inode fork pointer */  	xfs_extnum_t		lastx;		/* last extent pointer */ @@ -455,8 +480,8 @@ xfs_getbmap_adjust_shared(  	agno = XFS_FSB_TO_AGNO(mp, map->br_startblock);  	agbno = XFS_FSB_TO_AGBNO(mp, map->br_startblock); -	error = xfs_reflink_find_shared(mp, agno, agbno, map->br_blockcount, -			&ebno, &elen, true); +	error = xfs_reflink_find_shared(mp, NULL, agno, agbno, +			map->br_blockcount, &ebno, &elen, true);  	if (error)  		return error; @@ -514,9 +539,9 @@ xfs_getbmap(  	xfs_bmap_format_t	formatter,	/* format to user */  	void			*arg)		/* formatter arg */  { -	__int64_t		bmvend;		/* last block requested */ +	int64_t			bmvend;		/* last block requested */  	int			error = 0;	/* return value */ -	__int64_t		fixlen;		/* length for -1 case */ +	int64_t			fixlen;		/* length for -1 case */  	int			i;		/* extent number */  	int			lock;		/* lock state */  	xfs_bmbt_irec_t		*map;		/* buffer for user's data */ @@ -605,7 +630,7 @@ xfs_getbmap(  	if (bmv->bmv_length == -1) {  		fixlen = XFS_FSB_TO_BB(mp, XFS_B_TO_FSB(mp, fixlen));  		bmv->bmv_length = -			max_t(__int64_t, fixlen - bmv->bmv_offset, 0); +			max_t(int64_t, fixlen - bmv->bmv_offset, 0);  	} else if (bmv->bmv_length == 0) {  		bmv->bmv_entries = 0;  		return 0; @@ -742,7 +767,7 @@ xfs_getbmap(  				out[cur_ext].bmv_offset +  				out[cur_ext].bmv_length;  			bmv->bmv_length = -				max_t(__int64_t, 0, bmvend - bmv->bmv_offset); +				max_t(int64_t, 0, bmvend - bmv->bmv_offset);  			/*  			 * In case we don't want to return the hole, @@ -1617,7 +1642,7 @@ xfs_swap_extents_check_format(  	 * extent format...  	 */  	if (tip->i_d.di_format == XFS_DINODE_FMT_BTREE) { -		if (XFS_IFORK_BOFF(ip) && +		if (XFS_IFORK_Q(ip) &&  		    XFS_BMAP_BMDR_SPACE(tip->i_df.if_broot) > XFS_IFORK_BOFF(ip))  			return -EINVAL;  		if (XFS_IFORK_NEXTENTS(tip, XFS_DATA_FORK) <= @@ -1627,7 +1652,7 @@ xfs_swap_extents_check_format(  	/* Reciprocal target->temp btree format checks */  	if (ip->i_d.di_format == XFS_DINODE_FMT_BTREE) { -		if (XFS_IFORK_BOFF(tip) && +		if (XFS_IFORK_Q(tip) &&  		    XFS_BMAP_BMDR_SPACE(ip->i_df.if_broot) > XFS_IFORK_BOFF(tip))  			return -EINVAL;  		if (XFS_IFORK_NEXTENTS(ip, XFS_DATA_FORK) <= @@ -1676,7 +1701,7 @@ xfs_swap_extent_rmap(  	xfs_filblks_t			ilen;  	xfs_filblks_t			rlen;  	int				nimaps; -	__uint64_t			tip_flags2; +	uint64_t			tip_flags2;  	/*  	 * If the source file has shared blocks, we must flag the donor @@ -1789,10 +1814,11 @@ xfs_swap_extent_forks(  	int			*target_log_flags)  {  	struct xfs_ifork	tempifp, *ifp, *tifp; -	int			aforkblks = 0; -	int			taforkblks = 0; +	xfs_filblks_t		aforkblks = 0; +	xfs_filblks_t		taforkblks = 0; +	xfs_extnum_t		junk;  	xfs_extnum_t		nextents; -	__uint64_t		tmp; +	uint64_t		tmp;  	int			error;  	/* @@ -1800,14 +1826,14 @@ xfs_swap_extent_forks(  	 */  	if ( ((XFS_IFORK_Q(ip) != 0) && (ip->i_d.di_anextents > 0)) &&  	     (ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)) { -		error = xfs_bmap_count_blocks(tp, ip, XFS_ATTR_FORK, +		error = xfs_bmap_count_blocks(tp, ip, XFS_ATTR_FORK, &junk,  				&aforkblks);  		if (error)  			return error;  	}  	if ( ((XFS_IFORK_Q(tip) != 0) && (tip->i_d.di_anextents > 0)) &&  	     (tip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)) { -		error = xfs_bmap_count_blocks(tp, tip, XFS_ATTR_FORK, +		error = xfs_bmap_count_blocks(tp, tip, XFS_ATTR_FORK, &junk,  				&taforkblks);  		if (error)  			return error; @@ -1850,15 +1876,15 @@ xfs_swap_extent_forks(  	/*  	 * Fix the on-disk inode values  	 */ -	tmp = (__uint64_t)ip->i_d.di_nblocks; +	tmp = (uint64_t)ip->i_d.di_nblocks;  	ip->i_d.di_nblocks = tip->i_d.di_nblocks - taforkblks + aforkblks;  	tip->i_d.di_nblocks = tmp + taforkblks - aforkblks; -	tmp = (__uint64_t) ip->i_d.di_nextents; +	tmp = (uint64_t) ip->i_d.di_nextents;  	ip->i_d.di_nextents = tip->i_d.di_nextents;  	tip->i_d.di_nextents = tmp; -	tmp = (__uint64_t) ip->i_d.di_format; +	tmp = (uint64_t) ip->i_d.di_format;  	ip->i_d.di_format = tip->i_d.di_format;  	tip->i_d.di_format = tmp; @@ -1927,7 +1953,7 @@ xfs_swap_extents(  	int			error = 0;  	int			lock_flags;  	struct xfs_ifork	*cowfp; -	__uint64_t		f; +	uint64_t		f;  	int			resblks;  	/*  | 
