diff options
Diffstat (limited to 'fs/xfs/libxfs/xfs_bmap.c')
| -rw-r--r-- | fs/xfs/libxfs/xfs_bmap.c | 145 | 
1 files changed, 63 insertions, 82 deletions
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 74198dd82b03..24462bdfd8e7 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -52,19 +52,17 @@ xfs_bmap_compute_maxlevels(  	xfs_mount_t	*mp,		/* file system mount structure */  	int		whichfork)	/* data or attr fork */  { +	uint64_t	maxblocks;	/* max blocks at this level */ +	xfs_extnum_t	maxleafents;	/* max leaf entries possible */  	int		level;		/* btree level */ -	uint		maxblocks;	/* max blocks at this level */ -	uint		maxleafents;	/* max leaf entries possible */  	int		maxrootrecs;	/* max records in root block */  	int		minleafrecs;	/* min records in leaf block */  	int		minnoderecs;	/* min records in node block */  	int		sz;		/* root block size */  	/* -	 * The maximum number of extents in a file, hence the maximum number of -	 * leaf entries, is controlled by the size of the on-disk extent count, -	 * either a signed 32-bit number for the data fork, or a signed 16-bit -	 * number for the attr fork. +	 * The maximum number of extents in a fork, hence the maximum number of +	 * leaf entries, is controlled by the size of the on-disk extent count.  	 *  	 * Note that we can no longer assume that if we are in ATTR1 that the  	 * fork offset of all the inodes will be @@ -74,22 +72,22 @@ xfs_bmap_compute_maxlevels(  	 * ATTR2 we have to assume the worst case scenario of a minimum size  	 * available.  	 */ -	if (whichfork == XFS_DATA_FORK) { -		maxleafents = MAXEXTNUM; +	maxleafents = xfs_iext_max_nextents(xfs_has_large_extent_counts(mp), +				whichfork); +	if (whichfork == XFS_DATA_FORK)  		sz = XFS_BMDR_SPACE_CALC(MINDBTPTRS); -	} else { -		maxleafents = MAXAEXTNUM; +	else  		sz = XFS_BMDR_SPACE_CALC(MINABTPTRS); -	} +  	maxrootrecs = xfs_bmdr_maxrecs(sz, 0);  	minleafrecs = mp->m_bmap_dmnr[0];  	minnoderecs = mp->m_bmap_dmnr[1]; -	maxblocks = (maxleafents + minleafrecs - 1) / minleafrecs; +	maxblocks = howmany_64(maxleafents, minleafrecs);  	for (level = 1; maxblocks > 1; level++) {  		if (maxblocks <= maxrootrecs)  			maxblocks = 1;  		else -			maxblocks = (maxblocks + minnoderecs - 1) / minnoderecs; +			maxblocks = howmany_64(maxblocks, minnoderecs);  	}  	mp->m_bm_maxlevels[whichfork] = level;  	ASSERT(mp->m_bm_maxlevels[whichfork] <= xfs_bmbt_maxlevels_ondisk()); @@ -468,7 +466,7 @@ error0:  	if (bp_release)  		xfs_trans_brelse(NULL, bp);  error_norelse: -	xfs_warn(mp, "%s: BAD after btree leaves for %d extents", +	xfs_warn(mp, "%s: BAD after btree leaves for %llu extents",  		__func__, i);  	xfs_err(mp, "%s: CORRUPTED BTREE OR SOMETHING", __func__);  	xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); @@ -485,7 +483,7 @@ STATIC void  xfs_bmap_validate_ret(  	xfs_fileoff_t		bno,  	xfs_filblks_t		len, -	int			flags, +	uint32_t		flags,  	xfs_bmbt_irec_t		*mval,  	int			nmap,  	int			ret_nmap) @@ -1399,7 +1397,7 @@ xfs_bmap_add_extent_delay_real(  	xfs_bmbt_irec_t		r[3];	/* neighbor extent entries */  					/* left is 0, right is 1, prev is 2 */  	int			rval=0;	/* return value (logging flags) */ -	int			state = xfs_bmap_fork_to_state(whichfork); +	uint32_t		state = xfs_bmap_fork_to_state(whichfork);  	xfs_filblks_t		da_new; /* new count del alloc blocks used */  	xfs_filblks_t		da_old; /* old count del alloc blocks used */  	xfs_filblks_t		temp=0;	/* value for da_new calculations */ @@ -1452,7 +1450,7 @@ xfs_bmap_add_extent_delay_real(  	    LEFT.br_startoff + LEFT.br_blockcount == new->br_startoff &&  	    LEFT.br_startblock + LEFT.br_blockcount == new->br_startblock &&  	    LEFT.br_state == new->br_state && -	    LEFT.br_blockcount + new->br_blockcount <= MAXEXTLEN) +	    LEFT.br_blockcount + new->br_blockcount <= XFS_MAX_BMBT_EXTLEN)  		state |= BMAP_LEFT_CONTIG;  	/* @@ -1470,13 +1468,13 @@ xfs_bmap_add_extent_delay_real(  	    new_endoff == RIGHT.br_startoff &&  	    new->br_startblock + new->br_blockcount == RIGHT.br_startblock &&  	    new->br_state == RIGHT.br_state && -	    new->br_blockcount + RIGHT.br_blockcount <= MAXEXTLEN && +	    new->br_blockcount + RIGHT.br_blockcount <= XFS_MAX_BMBT_EXTLEN &&  	    ((state & (BMAP_LEFT_CONTIG | BMAP_LEFT_FILLING |  		       BMAP_RIGHT_FILLING)) !=  		      (BMAP_LEFT_CONTIG | BMAP_LEFT_FILLING |  		       BMAP_RIGHT_FILLING) ||  	     LEFT.br_blockcount + new->br_blockcount + RIGHT.br_blockcount -			<= MAXEXTLEN)) +			<= XFS_MAX_BMBT_EXTLEN))  		state |= BMAP_RIGHT_CONTIG;  	error = 0; @@ -1950,7 +1948,7 @@ xfs_bmap_add_extent_unwritten_real(  	xfs_bmbt_irec_t		r[3];	/* neighbor extent entries */  					/* left is 0, right is 1, prev is 2 */  	int			rval=0;	/* return value (logging flags) */ -	int			state = xfs_bmap_fork_to_state(whichfork); +	uint32_t		state = xfs_bmap_fork_to_state(whichfork);  	struct xfs_mount	*mp = ip->i_mount;  	struct xfs_bmbt_irec	old; @@ -2000,7 +1998,7 @@ xfs_bmap_add_extent_unwritten_real(  	    LEFT.br_startoff + LEFT.br_blockcount == new->br_startoff &&  	    LEFT.br_startblock + LEFT.br_blockcount == new->br_startblock &&  	    LEFT.br_state == new->br_state && -	    LEFT.br_blockcount + new->br_blockcount <= MAXEXTLEN) +	    LEFT.br_blockcount + new->br_blockcount <= XFS_MAX_BMBT_EXTLEN)  		state |= BMAP_LEFT_CONTIG;  	/* @@ -2018,13 +2016,13 @@ xfs_bmap_add_extent_unwritten_real(  	    new_endoff == RIGHT.br_startoff &&  	    new->br_startblock + new->br_blockcount == RIGHT.br_startblock &&  	    new->br_state == RIGHT.br_state && -	    new->br_blockcount + RIGHT.br_blockcount <= MAXEXTLEN && +	    new->br_blockcount + RIGHT.br_blockcount <= XFS_MAX_BMBT_EXTLEN &&  	    ((state & (BMAP_LEFT_CONTIG | BMAP_LEFT_FILLING |  		       BMAP_RIGHT_FILLING)) !=  		      (BMAP_LEFT_CONTIG | BMAP_LEFT_FILLING |  		       BMAP_RIGHT_FILLING) ||  	     LEFT.br_blockcount + new->br_blockcount + RIGHT.br_blockcount -			<= MAXEXTLEN)) +			<= XFS_MAX_BMBT_EXTLEN))  		state |= BMAP_RIGHT_CONTIG;  	/* @@ -2479,7 +2477,7 @@ xfs_bmap_add_extent_hole_delay(  	xfs_filblks_t		newlen=0;	/* new indirect size */  	xfs_filblks_t		oldlen=0;	/* old indirect size */  	xfs_bmbt_irec_t		right;	/* right neighbor extent entry */ -	int			state = xfs_bmap_fork_to_state(whichfork); +	uint32_t		state = xfs_bmap_fork_to_state(whichfork);  	xfs_filblks_t		temp;	 /* temp for indirect calculations */  	ifp = XFS_IFORK_PTR(ip, whichfork); @@ -2510,15 +2508,15 @@ xfs_bmap_add_extent_hole_delay(  	 */  	if ((state & BMAP_LEFT_VALID) && (state & BMAP_LEFT_DELAY) &&  	    left.br_startoff + left.br_blockcount == new->br_startoff && -	    left.br_blockcount + new->br_blockcount <= MAXEXTLEN) +	    left.br_blockcount + new->br_blockcount <= XFS_MAX_BMBT_EXTLEN)  		state |= BMAP_LEFT_CONTIG;  	if ((state & BMAP_RIGHT_VALID) && (state & BMAP_RIGHT_DELAY) &&  	    new->br_startoff + new->br_blockcount == right.br_startoff && -	    new->br_blockcount + right.br_blockcount <= MAXEXTLEN && +	    new->br_blockcount + right.br_blockcount <= XFS_MAX_BMBT_EXTLEN &&  	    (!(state & BMAP_LEFT_CONTIG) ||  	     (left.br_blockcount + new->br_blockcount + -	      right.br_blockcount <= MAXEXTLEN))) +	      right.br_blockcount <= XFS_MAX_BMBT_EXTLEN)))  		state |= BMAP_RIGHT_CONTIG;  	/* @@ -2616,7 +2614,7 @@ xfs_bmap_add_extent_hole_real(  	struct xfs_btree_cur	**curp,  	struct xfs_bmbt_irec	*new,  	int			*logflagsp, -	int			flags) +	uint32_t		flags)  {  	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, whichfork);  	struct xfs_mount	*mp = ip->i_mount; @@ -2626,7 +2624,7 @@ xfs_bmap_add_extent_hole_real(  	xfs_bmbt_irec_t		left;	/* left neighbor extent entry */  	xfs_bmbt_irec_t		right;	/* right neighbor extent entry */  	int			rval=0;	/* return value (logging flags) */ -	int			state = xfs_bmap_fork_to_state(whichfork); +	uint32_t		state = xfs_bmap_fork_to_state(whichfork);  	struct xfs_bmbt_irec	old;  	ASSERT(!isnullstartblock(new->br_startblock)); @@ -2661,17 +2659,17 @@ xfs_bmap_add_extent_hole_real(  	    left.br_startoff + left.br_blockcount == new->br_startoff &&  	    left.br_startblock + left.br_blockcount == new->br_startblock &&  	    left.br_state == new->br_state && -	    left.br_blockcount + new->br_blockcount <= MAXEXTLEN) +	    left.br_blockcount + new->br_blockcount <= XFS_MAX_BMBT_EXTLEN)  		state |= BMAP_LEFT_CONTIG;  	if ((state & BMAP_RIGHT_VALID) && !(state & BMAP_RIGHT_DELAY) &&  	    new->br_startoff + new->br_blockcount == right.br_startoff &&  	    new->br_startblock + new->br_blockcount == right.br_startblock &&  	    new->br_state == right.br_state && -	    new->br_blockcount + right.br_blockcount <= MAXEXTLEN && +	    new->br_blockcount + right.br_blockcount <= XFS_MAX_BMBT_EXTLEN &&  	    (!(state & BMAP_LEFT_CONTIG) ||  	     left.br_blockcount + new->br_blockcount + -	     right.br_blockcount <= MAXEXTLEN)) +	     right.br_blockcount <= XFS_MAX_BMBT_EXTLEN))  		state |= BMAP_RIGHT_CONTIG;  	error = 0; @@ -2906,15 +2904,15 @@ xfs_bmap_extsize_align(  	/*  	 * For large extent hint sizes, the aligned extent might be larger than -	 * MAXEXTLEN. In that case, reduce the size by an extsz so that it pulls -	 * the length back under MAXEXTLEN. The outer allocation loops handle -	 * short allocation just fine, so it is safe to do this. We only want to -	 * do it when we are forced to, though, because it means more allocation -	 * operations are required. +	 * XFS_BMBT_MAX_EXTLEN. In that case, reduce the size by an extsz so +	 * that it pulls the length back under XFS_BMBT_MAX_EXTLEN. The outer +	 * allocation loops handle short allocation just fine, so it is safe to +	 * do this. We only want to do it when we are forced to, though, because +	 * it means more allocation operations are required.  	 */ -	while (align_alen > MAXEXTLEN) +	while (align_alen > XFS_MAX_BMBT_EXTLEN)  		align_alen -= extsz; -	ASSERT(align_alen <= MAXEXTLEN); +	ASSERT(align_alen <= XFS_MAX_BMBT_EXTLEN);  	/*  	 * If the previous block overlaps with this proposed allocation @@ -3004,9 +3002,9 @@ xfs_bmap_extsize_align(  			return -EINVAL;  	} else {  		ASSERT(orig_off >= align_off); -		/* see MAXEXTLEN handling above */ +		/* see XFS_BMBT_MAX_EXTLEN handling above */  		ASSERT(orig_end <= align_off + align_alen || -		       align_alen + extsz > MAXEXTLEN); +		       align_alen + extsz > XFS_MAX_BMBT_EXTLEN);  	}  #ifdef DEBUG @@ -3766,7 +3764,7 @@ xfs_bmapi_trim_map(  	xfs_fileoff_t		obno,  	xfs_fileoff_t		end,  	int			n, -	int			flags) +	uint32_t		flags)  {  	if ((flags & XFS_BMAPI_ENTIRE) ||  	    got->br_startoff + got->br_blockcount <= obno) { @@ -3811,7 +3809,7 @@ xfs_bmapi_update_map(  	xfs_fileoff_t		obno,  	xfs_fileoff_t		end,  	int			*n, -	int			flags) +	uint32_t		flags)  {  	xfs_bmbt_irec_t	*mval = *map; @@ -3864,7 +3862,7 @@ xfs_bmapi_read(  	xfs_filblks_t		len,  	struct xfs_bmbt_irec	*mval,  	int			*nmap, -	int			flags) +	uint32_t		flags)  {  	struct xfs_mount	*mp = ip->i_mount;  	int			whichfork = xfs_bmapi_whichfork(flags); @@ -3971,7 +3969,7 @@ xfs_bmapi_reserve_delalloc(  	 * Cap the alloc length. Keep track of prealloc so we know whether to  	 * tag the inode before we return.  	 */ -	alen = XFS_FILBLKS_MIN(len + prealloc, MAXEXTLEN); +	alen = XFS_FILBLKS_MIN(len + prealloc, XFS_MAX_BMBT_EXTLEN);  	if (!eof)  		alen = XFS_FILBLKS_MIN(alen, got->br_startoff - aoff);  	if (prealloc && alen >= len) @@ -4104,7 +4102,7 @@ xfs_bmapi_allocate(  		if (!xfs_iext_peek_prev_extent(ifp, &bma->icur, &bma->prev))  			bma->prev.br_startoff = NULLFILEOFF;  	} else { -		bma->length = XFS_FILBLKS_MIN(bma->length, MAXEXTLEN); +		bma->length = XFS_FILBLKS_MIN(bma->length, XFS_MAX_BMBT_EXTLEN);  		if (!bma->eof)  			bma->length = XFS_FILBLKS_MIN(bma->length,  					bma->got.br_startoff - bma->offset); @@ -4184,7 +4182,7 @@ xfs_bmapi_convert_unwritten(  	struct xfs_bmalloca	*bma,  	struct xfs_bmbt_irec	*mval,  	xfs_filblks_t		len, -	int			flags) +	uint32_t		flags)  {  	int			whichfork = xfs_bmapi_whichfork(flags);  	struct xfs_ifork	*ifp = XFS_IFORK_PTR(bma->ip, whichfork); @@ -4312,7 +4310,7 @@ xfs_bmapi_write(  	struct xfs_inode	*ip,		/* incore inode */  	xfs_fileoff_t		bno,		/* starting file offs. mapped */  	xfs_filblks_t		len,		/* length to map in file */ -	int			flags,		/* XFS_BMAPI_... */ +	uint32_t		flags,		/* XFS_BMAPI_... */  	xfs_extlen_t		total,		/* total blocks needed */  	struct xfs_bmbt_irec	*mval,		/* output: map values */  	int			*nmap)		/* i/o: mval size/count */ @@ -4424,8 +4422,8 @@ xfs_bmapi_write(  			 * xfs_extlen_t and therefore 32 bits. Hence we have to  			 * check for 32-bit overflows and handle them here.  			 */ -			if (len > (xfs_filblks_t)MAXEXTLEN) -				bma.length = MAXEXTLEN; +			if (len > (xfs_filblks_t)XFS_MAX_BMBT_EXTLEN) +				bma.length = XFS_MAX_BMBT_EXTLEN;  			else  				bma.length = len; @@ -4526,14 +4524,16 @@ xfs_bmapi_convert_delalloc(  		return error;  	xfs_ilock(ip, XFS_ILOCK_EXCL); +	xfs_trans_ijoin(tp, ip, 0);  	error = xfs_iext_count_may_overflow(ip, whichfork,  			XFS_IEXT_ADD_NOSPLIT_CNT); +	if (error == -EFBIG) +		error = xfs_iext_count_upgrade(tp, ip, +				XFS_IEXT_ADD_NOSPLIT_CNT);  	if (error)  		goto out_trans_cancel; -	xfs_trans_ijoin(tp, ip, 0); -  	if (!xfs_iext_lookup_extent(ip, ifp, offset_fsb, &bma.icur, &bma.got) ||  	    bma.got.br_startoff > offset_fsb) {  		/* @@ -4560,7 +4560,8 @@ xfs_bmapi_convert_delalloc(  	bma.ip = ip;  	bma.wasdel = true;  	bma.offset = bma.got.br_startoff; -	bma.length = max_t(xfs_filblks_t, bma.got.br_blockcount, MAXEXTLEN); +	bma.length = max_t(xfs_filblks_t, bma.got.br_blockcount, +			XFS_MAX_BMBT_EXTLEN);  	bma.minleft = xfs_bmapi_minleft(tp, ip, whichfork);  	/* @@ -4629,7 +4630,7 @@ xfs_bmapi_remap(  	xfs_fileoff_t		bno,  	xfs_filblks_t		len,  	xfs_fsblock_t		startblock, -	int			flags) +	uint32_t		flags)  {  	struct xfs_mount	*mp = ip->i_mount;  	struct xfs_ifork	*ifp; @@ -4641,7 +4642,7 @@ xfs_bmapi_remap(  	ifp = XFS_IFORK_PTR(ip, whichfork);  	ASSERT(len > 0); -	ASSERT(len <= (xfs_filblks_t)MAXEXTLEN); +	ASSERT(len <= (xfs_filblks_t)XFS_MAX_BMBT_EXTLEN);  	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));  	ASSERT(!(flags & ~(XFS_BMAPI_ATTRFORK | XFS_BMAPI_PREALLOC |  			   XFS_BMAPI_NORMAP))); @@ -4801,7 +4802,7 @@ xfs_bmap_del_extent_delay(  	int64_t			da_old, da_new, da_diff = 0;  	xfs_fileoff_t		del_endoff, got_endoff;  	xfs_filblks_t		got_indlen, new_indlen, stolen; -	int			state = xfs_bmap_fork_to_state(whichfork); +	uint32_t		state = xfs_bmap_fork_to_state(whichfork);  	int			error = 0;  	bool			isrt; @@ -4926,7 +4927,7 @@ xfs_bmap_del_extent_cow(  	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK);  	struct xfs_bmbt_irec	new;  	xfs_fileoff_t		del_endoff, got_endoff; -	int			state = BMAP_COWFORK; +	uint32_t		state = BMAP_COWFORK;  	XFS_STATS_INC(mp, xs_del_exlist); @@ -4999,7 +5000,7 @@ xfs_bmap_del_extent_real(  	xfs_bmbt_irec_t		*del,	/* data to remove from extents */  	int			*logflagsp, /* inode logging flags */  	int			whichfork, /* data or attr fork */ -	int			bflags)	/* bmapi flags */ +	uint32_t		bflags)	/* bmapi flags */  {  	xfs_fsblock_t		del_endblock=0;	/* first block past del */  	xfs_fileoff_t		del_endoff;	/* first offset past del */ @@ -5015,7 +5016,7 @@ xfs_bmap_del_extent_real(  	xfs_bmbt_irec_t		new;	/* new record to be inserted */  	/* REFERENCED */  	uint			qfield;	/* quota field to update */ -	int			state = xfs_bmap_fork_to_state(whichfork); +	uint32_t		state = xfs_bmap_fork_to_state(whichfork);  	struct xfs_bmbt_irec	old;  	mp = ip->i_mount; @@ -5148,26 +5149,6 @@ xfs_bmap_del_extent_real(  		 * Deleting the middle of the extent.  		 */ -		/* -		 * For directories, -ENOSPC is returned since a directory entry -		 * remove operation must not fail due to low extent count -		 * availability. -ENOSPC will be handled by higher layers of XFS -		 * by letting the corresponding empty Data/Free blocks to linger -		 * until a future remove operation. Dabtree blocks would be -		 * swapped with the last block in the leaf space and then the -		 * new last block will be unmapped. -		 * -		 * The above logic also applies to the source directory entry of -		 * a rename operation. -		 */ -		error = xfs_iext_count_may_overflow(ip, whichfork, 1); -		if (error) { -			ASSERT(S_ISDIR(VFS_I(ip)->i_mode) && -				whichfork == XFS_DATA_FORK); -			error = -ENOSPC; -			goto done; -		} -  		old = got;  		got.br_blockcount = del->br_startoff - got.br_startoff; @@ -5281,7 +5262,7 @@ __xfs_bunmapi(  	struct xfs_inode	*ip,		/* incore inode */  	xfs_fileoff_t		start,		/* first file offset deleted */  	xfs_filblks_t		*rlen,		/* i/o: amount remaining */ -	int			flags,		/* misc flags */ +	uint32_t		flags,		/* misc flags */  	xfs_extnum_t		nexts)		/* number of extents max */  {  	struct xfs_btree_cur	*cur;		/* bmap btree cursor */ @@ -5609,7 +5590,7 @@ xfs_bunmapi(  	struct xfs_inode	*ip,  	xfs_fileoff_t		bno,  	xfs_filblks_t		len, -	int			flags, +	uint32_t		flags,  	xfs_extnum_t		nexts,  	int			*done)  { @@ -5641,7 +5622,7 @@ xfs_bmse_can_merge(  	if ((left->br_startoff + left->br_blockcount != startoff) ||  	    (left->br_startblock + left->br_blockcount != got->br_startblock) ||  	    (left->br_state != got->br_state) || -	    (left->br_blockcount + got->br_blockcount > MAXEXTLEN)) +	    (left->br_blockcount + got->br_blockcount > XFS_MAX_BMBT_EXTLEN))  		return false;  	return true;  |