diff options
Diffstat (limited to 'fs/xfs/xfs_rtalloc.c')
| -rw-r--r-- | fs/xfs/xfs_rtalloc.c | 1552 | 
1 files changed, 297 insertions, 1255 deletions
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index 6f9e63c9fc2..ec5ca65c621 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -17,172 +17,260 @@   */  #include "xfs.h"  #include "xfs_fs.h" +#include "xfs_shared.h"  #include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h"  #include "xfs_bit.h" -#include "xfs_log.h" -#include "xfs_trans.h"  #include "xfs_sb.h"  #include "xfs_ag.h"  #include "xfs_mount.h" -#include "xfs_bmap_btree.h" -#include "xfs_dinode.h"  #include "xfs_inode.h" -#include "xfs_alloc.h"  #include "xfs_bmap.h"  #include "xfs_bmap_util.h" -#include "xfs_rtalloc.h" -#include "xfs_fsops.h" +#include "xfs_bmap_btree.h" +#include "xfs_alloc.h"  #include "xfs_error.h" -#include "xfs_inode_item.h" +#include "xfs_trans.h"  #include "xfs_trans_space.h"  #include "xfs_trace.h"  #include "xfs_buf.h"  #include "xfs_icache.h" +#include "xfs_dinode.h" +#include "xfs_rtalloc.h"  /* - * Prototypes for internal functions. + * Read and return the summary information for a given extent size, + * bitmap block combination. + * Keeps track of a current summary block, so we don't keep reading + * it from the buffer cache.   */ +STATIC int				/* error */ +xfs_rtget_summary( +	xfs_mount_t	*mp,		/* file system mount structure */ +	xfs_trans_t	*tp,		/* transaction pointer */ +	int		log,		/* log2 of extent size */ +	xfs_rtblock_t	bbno,		/* bitmap block number */ +	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */ +	xfs_fsblock_t	*rsb,		/* in/out: summary block number */ +	xfs_suminfo_t	*sum)		/* out: summary info for this block */ +{ +	xfs_buf_t	*bp;		/* buffer for summary block */ +	int		error;		/* error value */ +	xfs_fsblock_t	sb;		/* summary fsblock */ +	int		so;		/* index into the summary file */ +	xfs_suminfo_t	*sp;		/* pointer to returned data */ +	/* +	 * Compute entry number in the summary file. +	 */ +	so = XFS_SUMOFFS(mp, log, bbno); +	/* +	 * Compute the block number in the summary file. +	 */ +	sb = XFS_SUMOFFSTOBLOCK(mp, so); +	/* +	 * If we have an old buffer, and the block number matches, use that. +	 */ +	if (rbpp && *rbpp && *rsb == sb) +		bp = *rbpp; +	/* +	 * Otherwise we have to get the buffer. +	 */ +	else { +		/* +		 * If there was an old one, get rid of it first. +		 */ +		if (rbpp && *rbpp) +			xfs_trans_brelse(tp, *rbpp); +		error = xfs_rtbuf_get(mp, tp, sb, 1, &bp); +		if (error) { +			return error; +		} +		/* +		 * Remember this buffer and block for the next call. +		 */ +		if (rbpp) { +			*rbpp = bp; +			*rsb = sb; +		} +	} +	/* +	 * Point to the summary information & copy it out. +	 */ +	sp = XFS_SUMPTR(mp, bp, so); +	*sum = *sp; +	/* +	 * Drop the buffer if we're not asked to remember it. +	 */ +	if (!rbpp) +		xfs_trans_brelse(tp, bp); +	return 0; +} -STATIC int xfs_rtallocate_range(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t, -		xfs_extlen_t, xfs_buf_t **, xfs_fsblock_t *); -STATIC int xfs_rtany_summary(xfs_mount_t *, xfs_trans_t *, int, int, -		xfs_rtblock_t, xfs_buf_t **, xfs_fsblock_t *, int *); -STATIC int xfs_rtcheck_range(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t, -		xfs_extlen_t, int, xfs_rtblock_t *, int *); -STATIC int xfs_rtfind_back(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t, -		xfs_rtblock_t, xfs_rtblock_t *); -STATIC int xfs_rtfind_forw(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t, -		xfs_rtblock_t, xfs_rtblock_t *); -STATIC int xfs_rtget_summary( xfs_mount_t *, xfs_trans_t *, int, -		xfs_rtblock_t, xfs_buf_t **, xfs_fsblock_t *, xfs_suminfo_t *); -STATIC int xfs_rtmodify_range(xfs_mount_t *, xfs_trans_t *, xfs_rtblock_t, -		xfs_extlen_t, int); -STATIC int xfs_rtmodify_summary(xfs_mount_t *, xfs_trans_t *, int, -		xfs_rtblock_t, int, xfs_buf_t **, xfs_fsblock_t *); - -/* - * Internal functions. - */  /* - * Allocate space to the bitmap or summary file, and zero it, for growfs. + * Return whether there are any free extents in the size range given + * by low and high, for the bitmap block bbno.   */  STATIC int				/* error */ -xfs_growfs_rt_alloc( -	xfs_mount_t	*mp,		/* file system mount point */ -	xfs_extlen_t	oblocks,	/* old count of blocks */ -	xfs_extlen_t	nblocks,	/* new count of blocks */ -	xfs_inode_t	*ip)		/* inode (bitmap/summary) */ +xfs_rtany_summary( +	xfs_mount_t	*mp,		/* file system mount structure */ +	xfs_trans_t	*tp,		/* transaction pointer */ +	int		low,		/* low log2 extent size */ +	int		high,		/* high log2 extent size */ +	xfs_rtblock_t	bbno,		/* bitmap block number */ +	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */ +	xfs_fsblock_t	*rsb,		/* in/out: summary block number */ +	int		*stat)		/* out: any good extents here? */  { -	xfs_fileoff_t	bno;		/* block number in file */ -	xfs_buf_t	*bp;		/* temporary buffer for zeroing */ -	int		committed;	/* transaction committed flag */ -	xfs_daddr_t	d;		/* disk block address */ -	int		error;		/* error return value */ -	xfs_fsblock_t	firstblock;	/* first block allocated in xaction */ -	xfs_bmap_free_t	flist;		/* list of freed blocks */ -	xfs_fsblock_t	fsbno;		/* filesystem block for bno */ -	xfs_bmbt_irec_t	map;		/* block map output */ -	int		nmap;		/* number of block maps */ -	int		resblks;	/* space reservation */ +	int		error;		/* error value */ +	int		log;		/* loop counter, log2 of ext. size */ +	xfs_suminfo_t	sum;		/* summary data */  	/* -	 * Allocate space to the file, as necessary. +	 * Loop over logs of extent sizes.  Order is irrelevant.  	 */ -	while (oblocks < nblocks) { -		int		cancelflags = 0; -		xfs_trans_t	*tp; - -		tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFSRT_ALLOC); -		resblks = XFS_GROWFSRT_SPACE_RES(mp, nblocks - oblocks); +	for (log = low; log <= high; log++) {  		/* -		 * Reserve space & log for one extent added to the file. +		 * Get one summary datum.  		 */ -		error = xfs_trans_reserve(tp, &M_RES(mp)->tr_growdata, -					  resblks, 0); -		if (error) -			goto error_cancel; -		cancelflags = XFS_TRANS_RELEASE_LOG_RES; +		error = xfs_rtget_summary(mp, tp, log, bbno, rbpp, rsb, &sum); +		if (error) { +			return error; +		}  		/* -		 * Lock the inode. +		 * If there are any, return success.  		 */ -		xfs_ilock(ip, XFS_ILOCK_EXCL); -		xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); +		if (sum) { +			*stat = 1; +			return 0; +		} +	} +	/* +	 * Found nothing, return failure. +	 */ +	*stat = 0; +	return 0; +} -		xfs_bmap_init(&flist, &firstblock); -		/* -		 * Allocate blocks to the bitmap file. -		 */ -		nmap = 1; -		cancelflags |= XFS_TRANS_ABORT; -		error = xfs_bmapi_write(tp, ip, oblocks, nblocks - oblocks, -					XFS_BMAPI_METADATA, &firstblock, -					resblks, &map, &nmap, &flist); -		if (!error && nmap < 1) -			error = XFS_ERROR(ENOSPC); -		if (error) -			goto error_cancel; -		/* -		 * Free any blocks freed up in the transaction, then commit. -		 */ -		error = xfs_bmap_finish(&tp, &flist, &committed); -		if (error) -			goto error_cancel; -		error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); -		if (error) -			goto error; -		/* -		 * Now we need to clear the allocated blocks. -		 * Do this one block per transaction, to keep it simple. -		 */ -		cancelflags = 0; -		for (bno = map.br_startoff, fsbno = map.br_startblock; -		     bno < map.br_startoff + map.br_blockcount; -		     bno++, fsbno++) { -			tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFSRT_ZERO); -			/* -			 * Reserve log for one block zeroing. -			 */ -			error = xfs_trans_reserve(tp, &M_RES(mp)->tr_growrtzero, -						  0, 0); + +/* + * Copy and transform the summary file, given the old and new + * parameters in the mount structures. + */ +STATIC int				/* error */ +xfs_rtcopy_summary( +	xfs_mount_t	*omp,		/* old file system mount point */ +	xfs_mount_t	*nmp,		/* new file system mount point */ +	xfs_trans_t	*tp)		/* transaction pointer */ +{ +	xfs_rtblock_t	bbno;		/* bitmap block number */ +	xfs_buf_t	*bp;		/* summary buffer */ +	int		error;		/* error return value */ +	int		log;		/* summary level number (log length) */ +	xfs_suminfo_t	sum;		/* summary data */ +	xfs_fsblock_t	sumbno;		/* summary block number */ + +	bp = NULL; +	for (log = omp->m_rsumlevels - 1; log >= 0; log--) { +		for (bbno = omp->m_sb.sb_rbmblocks - 1; +		     (xfs_srtblock_t)bbno >= 0; +		     bbno--) { +			error = xfs_rtget_summary(omp, tp, log, bbno, &bp, +				&sumbno, &sum);  			if (error) -				goto error_cancel; -			/* -			 * Lock the bitmap inode. -			 */ -			xfs_ilock(ip, XFS_ILOCK_EXCL); -			xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); -			/* -			 * Get a buffer for the block. -			 */ -			d = XFS_FSB_TO_DADDR(mp, fsbno); -			bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, -				mp->m_bsize, 0); -			if (bp == NULL) { -				error = XFS_ERROR(EIO); -error_cancel: -				xfs_trans_cancel(tp, cancelflags); -				goto error; -			} -			memset(bp->b_addr, 0, mp->m_sb.sb_blocksize); -			xfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1); -			/* -			 * Commit the transaction. -			 */ -			error = xfs_trans_commit(tp, 0); +				return error; +			if (sum == 0) +				continue; +			error = xfs_rtmodify_summary(omp, tp, log, bbno, -sum, +				&bp, &sumbno);  			if (error) -				goto error; +				return error; +			error = xfs_rtmodify_summary(nmp, tp, log, bbno, sum, +				&bp, &sumbno); +			if (error) +				return error; +			ASSERT(sum > 0);  		} -		/* -		 * Go on to the next extent, if any. -		 */ -		oblocks = map.br_startoff + map.br_blockcount;  	}  	return 0; +} +/* + * Mark an extent specified by start and len allocated. + * Updates all the summary information as well as the bitmap. + */ +STATIC int				/* error */ +xfs_rtallocate_range( +	xfs_mount_t	*mp,		/* file system mount point */ +	xfs_trans_t	*tp,		/* transaction pointer */ +	xfs_rtblock_t	start,		/* start block to allocate */ +	xfs_extlen_t	len,		/* length to allocate */ +	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */ +	xfs_fsblock_t	*rsb)		/* in/out: summary block number */ +{ +	xfs_rtblock_t	end;		/* end of the allocated extent */ +	int		error;		/* error value */ +	xfs_rtblock_t	postblock = 0;	/* first block allocated > end */ +	xfs_rtblock_t	preblock = 0;	/* first block allocated < start */ -error: +	end = start + len - 1; +	/* +	 * Assume we're allocating out of the middle of a free extent. +	 * We need to find the beginning and end of the extent so we can +	 * properly update the summary. +	 */ +	error = xfs_rtfind_back(mp, tp, start, 0, &preblock); +	if (error) { +		return error; +	} +	/* +	 * Find the next allocated block (end of free extent). +	 */ +	error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1, +		&postblock); +	if (error) { +		return error; +	} +	/* +	 * Decrement the summary information corresponding to the entire +	 * (old) free extent. +	 */ +	error = xfs_rtmodify_summary(mp, tp, +		XFS_RTBLOCKLOG(postblock + 1 - preblock), +		XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb); +	if (error) { +		return error; +	} +	/* +	 * If there are blocks not being allocated at the front of the +	 * old extent, add summary data for them to be free. +	 */ +	if (preblock < start) { +		error = xfs_rtmodify_summary(mp, tp, +			XFS_RTBLOCKLOG(start - preblock), +			XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb); +		if (error) { +			return error; +		} +	} +	/* +	 * If there are blocks not being allocated at the end of the +	 * old extent, add summary data for them to be free. +	 */ +	if (postblock > end) { +		error = xfs_rtmodify_summary(mp, tp, +			XFS_RTBLOCKLOG(postblock - end), +			XFS_BITTOBLOCK(mp, end + 1), 1, rbpp, rsb); +		if (error) { +			return error; +		} +	} +	/* +	 * Modify the bitmap to mark this extent allocated. +	 */ +	error = xfs_rtmodify_range(mp, tp, start, len, 0);  	return error;  } @@ -721,1112 +809,126 @@ xfs_rtallocate_extent_size(  }  /* - * Mark an extent specified by start and len allocated. - * Updates all the summary information as well as the bitmap. + * Allocate space to the bitmap or summary file, and zero it, for growfs.   */  STATIC int				/* error */ -xfs_rtallocate_range( +xfs_growfs_rt_alloc(  	xfs_mount_t	*mp,		/* file system mount point */ -	xfs_trans_t	*tp,		/* transaction pointer */ -	xfs_rtblock_t	start,		/* start block to allocate */ -	xfs_extlen_t	len,		/* length to allocate */ -	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */ -	xfs_fsblock_t	*rsb)		/* in/out: summary block number */ +	xfs_extlen_t	oblocks,	/* old count of blocks */ +	xfs_extlen_t	nblocks,	/* new count of blocks */ +	xfs_inode_t	*ip)		/* inode (bitmap/summary) */  { -	xfs_rtblock_t	end;		/* end of the allocated extent */ -	int		error;		/* error value */ -	xfs_rtblock_t	postblock = 0;	/* first block allocated > end */ -	xfs_rtblock_t	preblock = 0;	/* first block allocated < start */ +	xfs_fileoff_t	bno;		/* block number in file */ +	xfs_buf_t	*bp;		/* temporary buffer for zeroing */ +	int		committed;	/* transaction committed flag */ +	xfs_daddr_t	d;		/* disk block address */ +	int		error;		/* error return value */ +	xfs_fsblock_t	firstblock;	/* first block allocated in xaction */ +	xfs_bmap_free_t	flist;		/* list of freed blocks */ +	xfs_fsblock_t	fsbno;		/* filesystem block for bno */ +	xfs_bmbt_irec_t	map;		/* block map output */ +	int		nmap;		/* number of block maps */ +	int		resblks;	/* space reservation */ -	end = start + len - 1; -	/* -	 * Assume we're allocating out of the middle of a free extent. -	 * We need to find the beginning and end of the extent so we can -	 * properly update the summary. -	 */ -	error = xfs_rtfind_back(mp, tp, start, 0, &preblock); -	if (error) { -		return error; -	} -	/* -	 * Find the next allocated block (end of free extent). -	 */ -	error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1, -		&postblock); -	if (error) { -		return error; -	} -	/* -	 * Decrement the summary information corresponding to the entire -	 * (old) free extent. -	 */ -	error = xfs_rtmodify_summary(mp, tp, -		XFS_RTBLOCKLOG(postblock + 1 - preblock), -		XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb); -	if (error) { -		return error; -	} -	/* -	 * If there are blocks not being allocated at the front of the -	 * old extent, add summary data for them to be free. -	 */ -	if (preblock < start) { -		error = xfs_rtmodify_summary(mp, tp, -			XFS_RTBLOCKLOG(start - preblock), -			XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb); -		if (error) { -			return error; -		} -	} -	/* -	 * If there are blocks not being allocated at the end of the -	 * old extent, add summary data for them to be free. -	 */ -	if (postblock > end) { -		error = xfs_rtmodify_summary(mp, tp, -			XFS_RTBLOCKLOG(postblock - end), -			XFS_BITTOBLOCK(mp, end + 1), 1, rbpp, rsb); -		if (error) { -			return error; -		} -	}  	/* -	 * Modify the bitmap to mark this extent allocated. +	 * Allocate space to the file, as necessary.  	 */ -	error = xfs_rtmodify_range(mp, tp, start, len, 0); -	return error; -} - -/* - * Return whether there are any free extents in the size range given - * by low and high, for the bitmap block bbno. - */ -STATIC int				/* error */ -xfs_rtany_summary( -	xfs_mount_t	*mp,		/* file system mount structure */ -	xfs_trans_t	*tp,		/* transaction pointer */ -	int		low,		/* low log2 extent size */ -	int		high,		/* high log2 extent size */ -	xfs_rtblock_t	bbno,		/* bitmap block number */ -	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */ -	xfs_fsblock_t	*rsb,		/* in/out: summary block number */ -	int		*stat)		/* out: any good extents here? */ -{ -	int		error;		/* error value */ -	int		log;		/* loop counter, log2 of ext. size */ -	xfs_suminfo_t	sum;		/* summary data */ +	while (oblocks < nblocks) { +		int		cancelflags = 0; +		xfs_trans_t	*tp; -	/* -	 * Loop over logs of extent sizes.  Order is irrelevant. -	 */ -	for (log = low; log <= high; log++) { +		tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFSRT_ALLOC); +		resblks = XFS_GROWFSRT_SPACE_RES(mp, nblocks - oblocks);  		/* -		 * Get one summary datum. +		 * Reserve space & log for one extent added to the file.  		 */ -		error = xfs_rtget_summary(mp, tp, log, bbno, rbpp, rsb, &sum); -		if (error) { -			return error; -		} +		error = xfs_trans_reserve(tp, &M_RES(mp)->tr_growrtalloc, +					  resblks, 0); +		if (error) +			goto error_cancel; +		cancelflags = XFS_TRANS_RELEASE_LOG_RES;  		/* -		 * If there are any, return success. +		 * Lock the inode.  		 */ -		if (sum) { -			*stat = 1; -			return 0; -		} -	} -	/* -	 * Found nothing, return failure. -	 */ -	*stat = 0; -	return 0; -} - -/* - * Get a buffer for the bitmap or summary file block specified. - * The buffer is returned read and locked. - */ -STATIC int				/* error */ -xfs_rtbuf_get( -	xfs_mount_t	*mp,		/* file system mount structure */ -	xfs_trans_t	*tp,		/* transaction pointer */ -	xfs_rtblock_t	block,		/* block number in bitmap or summary */ -	int		issum,		/* is summary not bitmap */ -	xfs_buf_t	**bpp)		/* output: buffer for the block */ -{ -	xfs_buf_t	*bp;		/* block buffer, result */ -	xfs_inode_t	*ip;		/* bitmap or summary inode */ -	xfs_bmbt_irec_t	map; -	int		nmap = 1; -	int		error;		/* error value */ - -	ip = issum ? mp->m_rsumip : mp->m_rbmip; - -	error = xfs_bmapi_read(ip, block, 1, &map, &nmap, XFS_DATA_FORK); -	if (error) -		return error; - -	ASSERT(map.br_startblock != NULLFSBLOCK); -	error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, -				   XFS_FSB_TO_DADDR(mp, map.br_startblock), -				   mp->m_bsize, 0, &bp, NULL); -	if (error) -		return error; -	ASSERT(!xfs_buf_geterror(bp)); -	*bpp = bp; -	return 0; -} - -#ifdef DEBUG -/* - * Check that the given extent (block range) is allocated already. - */ -STATIC int				/* error */ -xfs_rtcheck_alloc_range( -	xfs_mount_t	*mp,		/* file system mount point */ -	xfs_trans_t	*tp,		/* transaction pointer */ -	xfs_rtblock_t	bno,		/* starting block number of extent */ -	xfs_extlen_t	len,		/* length of extent */ -	int		*stat)		/* out: 1 for allocated, 0 for not */ -{ -	xfs_rtblock_t	new;		/* dummy for xfs_rtcheck_range */ - -	return xfs_rtcheck_range(mp, tp, bno, len, 0, &new, stat); -} -#endif - -/* - * Check that the given range is either all allocated (val = 0) or - * all free (val = 1). - */ -STATIC int				/* error */ -xfs_rtcheck_range( -	xfs_mount_t	*mp,		/* file system mount point */ -	xfs_trans_t	*tp,		/* transaction pointer */ -	xfs_rtblock_t	start,		/* starting block number of extent */ -	xfs_extlen_t	len,		/* length of extent */ -	int		val,		/* 1 for free, 0 for allocated */ -	xfs_rtblock_t	*new,		/* out: first block not matching */ -	int		*stat)		/* out: 1 for matches, 0 for not */ -{ -	xfs_rtword_t	*b;		/* current word in buffer */ -	int		bit;		/* bit number in the word */ -	xfs_rtblock_t	block;		/* bitmap block number */ -	xfs_buf_t	*bp;		/* buf for the block */ -	xfs_rtword_t	*bufp;		/* starting word in buffer */ -	int		error;		/* error value */ -	xfs_rtblock_t	i;		/* current bit number rel. to start */ -	xfs_rtblock_t	lastbit;	/* last useful bit in word */ -	xfs_rtword_t	mask;		/* mask of relevant bits for value */ -	xfs_rtword_t	wdiff;		/* difference from wanted value */ -	int		word;		/* word number in the buffer */ +		xfs_ilock(ip, XFS_ILOCK_EXCL); +		xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); -	/* -	 * Compute starting bitmap block number -	 */ -	block = XFS_BITTOBLOCK(mp, start); -	/* -	 * Read the bitmap block. -	 */ -	error = xfs_rtbuf_get(mp, tp, block, 0, &bp); -	if (error) { -		return error; -	} -	bufp = bp->b_addr; -	/* -	 * Compute the starting word's address, and starting bit. -	 */ -	word = XFS_BITTOWORD(mp, start); -	b = &bufp[word]; -	bit = (int)(start & (XFS_NBWORD - 1)); -	/* -	 * 0 (allocated) => all zero's; 1 (free) => all one's. -	 */ -	val = -val; -	/* -	 * If not starting on a word boundary, deal with the first -	 * (partial) word. -	 */ -	if (bit) { -		/* -		 * Compute first bit not examined. -		 */ -		lastbit = XFS_RTMIN(bit + len, XFS_NBWORD); -		/* -		 * Mask of relevant bits. -		 */ -		mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit; -		/* -		 * Compute difference between actual and desired value. -		 */ -		if ((wdiff = (*b ^ val) & mask)) { -			/* -			 * Different, compute first wrong bit and return. -			 */ -			xfs_trans_brelse(tp, bp); -			i = XFS_RTLOBIT(wdiff) - bit; -			*new = start + i; -			*stat = 0; -			return 0; -		} -		i = lastbit - bit; -		/* -		 * Go on to next block if that's where the next word is -		 * and we need the next word. -		 */ -		if (++word == XFS_BLOCKWSIZE(mp) && i < len) { -			/* -			 * If done with this block, get the next one. -			 */ -			xfs_trans_brelse(tp, bp); -			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); -			if (error) { -				return error; -			} -			b = bufp = bp->b_addr; -			word = 0; -		} else { -			/* -			 * Go on to the next word in the buffer. -			 */ -			b++; -		} -	} else { -		/* -		 * Starting on a word boundary, no partial word. -		 */ -		i = 0; -	} -	/* -	 * Loop over whole words in buffers.  When we use up one buffer -	 * we move on to the next one. -	 */ -	while (len - i >= XFS_NBWORD) { -		/* -		 * Compute difference between actual and desired value. -		 */ -		if ((wdiff = *b ^ val)) { -			/* -			 * Different, compute first wrong bit and return. -			 */ -			xfs_trans_brelse(tp, bp); -			i += XFS_RTLOBIT(wdiff); -			*new = start + i; -			*stat = 0; -			return 0; -		} -		i += XFS_NBWORD; +		xfs_bmap_init(&flist, &firstblock);  		/* -		 * Go on to next block if that's where the next word is -		 * and we need the next word. +		 * Allocate blocks to the bitmap file.  		 */ -		if (++word == XFS_BLOCKWSIZE(mp) && i < len) { -			/* -			 * If done with this block, get the next one. -			 */ -			xfs_trans_brelse(tp, bp); -			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); -			if (error) { -				return error; -			} -			b = bufp = bp->b_addr; -			word = 0; -		} else { -			/* -			 * Go on to the next word in the buffer. -			 */ -			b++; -		} -	} -	/* -	 * If not ending on a word boundary, deal with the last -	 * (partial) word. -	 */ -	if ((lastbit = len - i)) { +		nmap = 1; +		cancelflags |= XFS_TRANS_ABORT; +		error = xfs_bmapi_write(tp, ip, oblocks, nblocks - oblocks, +					XFS_BMAPI_METADATA, &firstblock, +					resblks, &map, &nmap, &flist); +		if (!error && nmap < 1) +			error = XFS_ERROR(ENOSPC); +		if (error) +			goto error_cancel;  		/* -		 * Mask of relevant bits. +		 * Free any blocks freed up in the transaction, then commit.  		 */ -		mask = ((xfs_rtword_t)1 << lastbit) - 1; +		error = xfs_bmap_finish(&tp, &flist, &committed); +		if (error) +			goto error_cancel; +		error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); +		if (error) +			goto error;  		/* -		 * Compute difference between actual and desired value. +		 * Now we need to clear the allocated blocks. +		 * Do this one block per transaction, to keep it simple.  		 */ -		if ((wdiff = (*b ^ val) & mask)) { +		cancelflags = 0; +		for (bno = map.br_startoff, fsbno = map.br_startblock; +		     bno < map.br_startoff + map.br_blockcount; +		     bno++, fsbno++) { +			tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFSRT_ZERO);  			/* -			 * Different, compute first wrong bit and return. +			 * Reserve log for one block zeroing.  			 */ -			xfs_trans_brelse(tp, bp); -			i += XFS_RTLOBIT(wdiff); -			*new = start + i; -			*stat = 0; -			return 0; -		} else -			i = len; -	} -	/* -	 * Successful, return. -	 */ -	xfs_trans_brelse(tp, bp); -	*new = start + i; -	*stat = 1; -	return 0; -} - -/* - * Copy and transform the summary file, given the old and new - * parameters in the mount structures. - */ -STATIC int				/* error */ -xfs_rtcopy_summary( -	xfs_mount_t	*omp,		/* old file system mount point */ -	xfs_mount_t	*nmp,		/* new file system mount point */ -	xfs_trans_t	*tp)		/* transaction pointer */ -{ -	xfs_rtblock_t	bbno;		/* bitmap block number */ -	xfs_buf_t	*bp;		/* summary buffer */ -	int		error;		/* error return value */ -	int		log;		/* summary level number (log length) */ -	xfs_suminfo_t	sum;		/* summary data */ -	xfs_fsblock_t	sumbno;		/* summary block number */ - -	bp = NULL; -	for (log = omp->m_rsumlevels - 1; log >= 0; log--) { -		for (bbno = omp->m_sb.sb_rbmblocks - 1; -		     (xfs_srtblock_t)bbno >= 0; -		     bbno--) { -			error = xfs_rtget_summary(omp, tp, log, bbno, &bp, -				&sumbno, &sum); -			if (error) -				return error; -			if (sum == 0) -				continue; -			error = xfs_rtmodify_summary(omp, tp, log, bbno, -sum, -				&bp, &sumbno); -			if (error) -				return error; -			error = xfs_rtmodify_summary(nmp, tp, log, bbno, sum, -				&bp, &sumbno); +			error = xfs_trans_reserve(tp, &M_RES(mp)->tr_growrtzero, +						  0, 0);  			if (error) -				return error; -			ASSERT(sum > 0); -		} -	} -	return 0; -} - -/* - * Searching backward from start to limit, find the first block whose - * allocated/free state is different from start's. - */ -STATIC int				/* error */ -xfs_rtfind_back( -	xfs_mount_t	*mp,		/* file system mount point */ -	xfs_trans_t	*tp,		/* transaction pointer */ -	xfs_rtblock_t	start,		/* starting block to look at */ -	xfs_rtblock_t	limit,		/* last block to look at */ -	xfs_rtblock_t	*rtblock)	/* out: start block found */ -{ -	xfs_rtword_t	*b;		/* current word in buffer */ -	int		bit;		/* bit number in the word */ -	xfs_rtblock_t	block;		/* bitmap block number */ -	xfs_buf_t	*bp;		/* buf for the block */ -	xfs_rtword_t	*bufp;		/* starting word in buffer */ -	int		error;		/* error value */ -	xfs_rtblock_t	firstbit;	/* first useful bit in the word */ -	xfs_rtblock_t	i;		/* current bit number rel. to start */ -	xfs_rtblock_t	len;		/* length of inspected area */ -	xfs_rtword_t	mask;		/* mask of relevant bits for value */ -	xfs_rtword_t	want;		/* mask for "good" values */ -	xfs_rtword_t	wdiff;		/* difference from wanted value */ -	int		word;		/* word number in the buffer */ - -	/* -	 * Compute and read in starting bitmap block for starting block. -	 */ -	block = XFS_BITTOBLOCK(mp, start); -	error = xfs_rtbuf_get(mp, tp, block, 0, &bp); -	if (error) { -		return error; -	} -	bufp = bp->b_addr; -	/* -	 * Get the first word's index & point to it. -	 */ -	word = XFS_BITTOWORD(mp, start); -	b = &bufp[word]; -	bit = (int)(start & (XFS_NBWORD - 1)); -	len = start - limit + 1; -	/* -	 * Compute match value, based on the bit at start: if 1 (free) -	 * then all-ones, else all-zeroes. -	 */ -	want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0; -	/* -	 * If the starting position is not word-aligned, deal with the -	 * partial word. -	 */ -	if (bit < XFS_NBWORD - 1) { -		/* -		 * Calculate first (leftmost) bit number to look at, -		 * and mask for all the relevant bits in this word. -		 */ -		firstbit = XFS_RTMAX((xfs_srtblock_t)(bit - len + 1), 0); -		mask = (((xfs_rtword_t)1 << (bit - firstbit + 1)) - 1) << -			firstbit; -		/* -		 * Calculate the difference between the value there -		 * and what we're looking for. -		 */ -		if ((wdiff = (*b ^ want) & mask)) { -			/* -			 * Different.  Mark where we are and return. -			 */ -			xfs_trans_brelse(tp, bp); -			i = bit - XFS_RTHIBIT(wdiff); -			*rtblock = start - i + 1; -			return 0; -		} -		i = bit - firstbit + 1; -		/* -		 * Go on to previous block if that's where the previous word is -		 * and we need the previous word. -		 */ -		if (--word == -1 && i < len) { -			/* -			 * If done with this block, get the previous one. -			 */ -			xfs_trans_brelse(tp, bp); -			error = xfs_rtbuf_get(mp, tp, --block, 0, &bp); -			if (error) { -				return error; -			} -			bufp = bp->b_addr; -			word = XFS_BLOCKWMASK(mp); -			b = &bufp[word]; -		} else { -			/* -			 * Go on to the previous word in the buffer. -			 */ -			b--; -		} -	} else { -		/* -		 * Starting on a word boundary, no partial word. -		 */ -		i = 0; -	} -	/* -	 * Loop over whole words in buffers.  When we use up one buffer -	 * we move on to the previous one. -	 */ -	while (len - i >= XFS_NBWORD) { -		/* -		 * Compute difference between actual and desired value. -		 */ -		if ((wdiff = *b ^ want)) { -			/* -			 * Different, mark where we are and return. -			 */ -			xfs_trans_brelse(tp, bp); -			i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff); -			*rtblock = start - i + 1; -			return 0; -		} -		i += XFS_NBWORD; -		/* -		 * Go on to previous block if that's where the previous word is -		 * and we need the previous word. -		 */ -		if (--word == -1 && i < len) { -			/* -			 * If done with this block, get the previous one. -			 */ -			xfs_trans_brelse(tp, bp); -			error = xfs_rtbuf_get(mp, tp, --block, 0, &bp); -			if (error) { -				return error; -			} -			bufp = bp->b_addr; -			word = XFS_BLOCKWMASK(mp); -			b = &bufp[word]; -		} else { -			/* -			 * Go on to the previous word in the buffer. -			 */ -			b--; -		} -	} -	/* -	 * If not ending on a word boundary, deal with the last -	 * (partial) word. -	 */ -	if (len - i) { -		/* -		 * Calculate first (leftmost) bit number to look at, -		 * and mask for all the relevant bits in this word. -		 */ -		firstbit = XFS_NBWORD - (len - i); -		mask = (((xfs_rtword_t)1 << (len - i)) - 1) << firstbit; -		/* -		 * Compute difference between actual and desired value. -		 */ -		if ((wdiff = (*b ^ want) & mask)) { -			/* -			 * Different, mark where we are and return. -			 */ -			xfs_trans_brelse(tp, bp); -			i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff); -			*rtblock = start - i + 1; -			return 0; -		} else -			i = len; -	} -	/* -	 * No match, return that we scanned the whole area. -	 */ -	xfs_trans_brelse(tp, bp); -	*rtblock = start - i + 1; -	return 0; -} - -/* - * Searching forward from start to limit, find the first block whose - * allocated/free state is different from start's. - */ -STATIC int				/* error */ -xfs_rtfind_forw( -	xfs_mount_t	*mp,		/* file system mount point */ -	xfs_trans_t	*tp,		/* transaction pointer */ -	xfs_rtblock_t	start,		/* starting block to look at */ -	xfs_rtblock_t	limit,		/* last block to look at */ -	xfs_rtblock_t	*rtblock)	/* out: start block found */ -{ -	xfs_rtword_t	*b;		/* current word in buffer */ -	int		bit;		/* bit number in the word */ -	xfs_rtblock_t	block;		/* bitmap block number */ -	xfs_buf_t	*bp;		/* buf for the block */ -	xfs_rtword_t	*bufp;		/* starting word in buffer */ -	int		error;		/* error value */ -	xfs_rtblock_t	i;		/* current bit number rel. to start */ -	xfs_rtblock_t	lastbit;	/* last useful bit in the word */ -	xfs_rtblock_t	len;		/* length of inspected area */ -	xfs_rtword_t	mask;		/* mask of relevant bits for value */ -	xfs_rtword_t	want;		/* mask for "good" values */ -	xfs_rtword_t	wdiff;		/* difference from wanted value */ -	int		word;		/* word number in the buffer */ - -	/* -	 * Compute and read in starting bitmap block for starting block. -	 */ -	block = XFS_BITTOBLOCK(mp, start); -	error = xfs_rtbuf_get(mp, tp, block, 0, &bp); -	if (error) { -		return error; -	} -	bufp = bp->b_addr; -	/* -	 * Get the first word's index & point to it. -	 */ -	word = XFS_BITTOWORD(mp, start); -	b = &bufp[word]; -	bit = (int)(start & (XFS_NBWORD - 1)); -	len = limit - start + 1; -	/* -	 * Compute match value, based on the bit at start: if 1 (free) -	 * then all-ones, else all-zeroes. -	 */ -	want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0; -	/* -	 * If the starting position is not word-aligned, deal with the -	 * partial word. -	 */ -	if (bit) { -		/* -		 * Calculate last (rightmost) bit number to look at, -		 * and mask for all the relevant bits in this word. -		 */ -		lastbit = XFS_RTMIN(bit + len, XFS_NBWORD); -		mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit; -		/* -		 * Calculate the difference between the value there -		 * and what we're looking for. -		 */ -		if ((wdiff = (*b ^ want) & mask)) { -			/* -			 * Different.  Mark where we are and return. -			 */ -			xfs_trans_brelse(tp, bp); -			i = XFS_RTLOBIT(wdiff) - bit; -			*rtblock = start + i - 1; -			return 0; -		} -		i = lastbit - bit; -		/* -		 * Go on to next block if that's where the next word is -		 * and we need the next word. -		 */ -		if (++word == XFS_BLOCKWSIZE(mp) && i < len) { -			/* -			 * If done with this block, get the previous one. -			 */ -			xfs_trans_brelse(tp, bp); -			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); -			if (error) { -				return error; -			} -			b = bufp = bp->b_addr; -			word = 0; -		} else { -			/* -			 * Go on to the previous word in the buffer. -			 */ -			b++; -		} -	} else { -		/* -		 * Starting on a word boundary, no partial word. -		 */ -		i = 0; -	} -	/* -	 * Loop over whole words in buffers.  When we use up one buffer -	 * we move on to the next one. -	 */ -	while (len - i >= XFS_NBWORD) { -		/* -		 * Compute difference between actual and desired value. -		 */ -		if ((wdiff = *b ^ want)) { +				goto error_cancel;  			/* -			 * Different, mark where we are and return. +			 * Lock the bitmap inode.  			 */ -			xfs_trans_brelse(tp, bp); -			i += XFS_RTLOBIT(wdiff); -			*rtblock = start + i - 1; -			return 0; -		} -		i += XFS_NBWORD; -		/* -		 * Go on to next block if that's where the next word is -		 * and we need the next word. -		 */ -		if (++word == XFS_BLOCKWSIZE(mp) && i < len) { +			xfs_ilock(ip, XFS_ILOCK_EXCL); +			xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);  			/* -			 * If done with this block, get the next one. +			 * Get a buffer for the block.  			 */ -			xfs_trans_brelse(tp, bp); -			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); -			if (error) { -				return error; +			d = XFS_FSB_TO_DADDR(mp, fsbno); +			bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, +				mp->m_bsize, 0); +			if (bp == NULL) { +				error = XFS_ERROR(EIO); +error_cancel: +				xfs_trans_cancel(tp, cancelflags); +				goto error;  			} -			b = bufp = bp->b_addr; -			word = 0; -		} else { +			memset(bp->b_addr, 0, mp->m_sb.sb_blocksize); +			xfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1);  			/* -			 * Go on to the next word in the buffer. +			 * Commit the transaction.  			 */ -			b++; +			error = xfs_trans_commit(tp, 0); +			if (error) +				goto error;  		} -	} -	/* -	 * If not ending on a word boundary, deal with the last -	 * (partial) word. -	 */ -	if ((lastbit = len - i)) {  		/* -		 * Calculate mask for all the relevant bits in this word. -		 */ -		mask = ((xfs_rtword_t)1 << lastbit) - 1; -		/* -		 * Compute difference between actual and desired value. +		 * Go on to the next extent, if any.  		 */ -		if ((wdiff = (*b ^ want) & mask)) { -			/* -			 * Different, mark where we are and return. -			 */ -			xfs_trans_brelse(tp, bp); -			i += XFS_RTLOBIT(wdiff); -			*rtblock = start + i - 1; -			return 0; -		} else -			i = len; +		oblocks = map.br_startoff + map.br_blockcount;  	} -	/* -	 * No match, return that we scanned the whole area. -	 */ -	xfs_trans_brelse(tp, bp); -	*rtblock = start + i - 1;  	return 0; -} -/* - * Mark an extent specified by start and len freed. - * Updates all the summary information as well as the bitmap. - */ -STATIC int				/* error */ -xfs_rtfree_range( -	xfs_mount_t	*mp,		/* file system mount point */ -	xfs_trans_t	*tp,		/* transaction pointer */ -	xfs_rtblock_t	start,		/* starting block to free */ -	xfs_extlen_t	len,		/* length to free */ -	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */ -	xfs_fsblock_t	*rsb)		/* in/out: summary block number */ -{ -	xfs_rtblock_t	end;		/* end of the freed extent */ -	int		error;		/* error value */ -	xfs_rtblock_t	postblock;	/* first block freed > end */ -	xfs_rtblock_t	preblock;	/* first block freed < start */ - -	end = start + len - 1; -	/* -	 * Modify the bitmap to mark this extent freed. -	 */ -	error = xfs_rtmodify_range(mp, tp, start, len, 1); -	if (error) { -		return error; -	} -	/* -	 * Assume we're freeing out of the middle of an allocated extent. -	 * We need to find the beginning and end of the extent so we can -	 * properly update the summary. -	 */ -	error = xfs_rtfind_back(mp, tp, start, 0, &preblock); -	if (error) { -		return error; -	} -	/* -	 * Find the next allocated block (end of allocated extent). -	 */ -	error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1, -		&postblock); -	if (error) -		return error; -	/* -	 * If there are blocks not being freed at the front of the -	 * old extent, add summary data for them to be allocated. -	 */ -	if (preblock < start) { -		error = xfs_rtmodify_summary(mp, tp, -			XFS_RTBLOCKLOG(start - preblock), -			XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb); -		if (error) { -			return error; -		} -	} -	/* -	 * If there are blocks not being freed at the end of the -	 * old extent, add summary data for them to be allocated. -	 */ -	if (postblock > end) { -		error = xfs_rtmodify_summary(mp, tp, -			XFS_RTBLOCKLOG(postblock - end), -			XFS_BITTOBLOCK(mp, end + 1), -1, rbpp, rsb); -		if (error) { -			return error; -		} -	} -	/* -	 * Increment the summary information corresponding to the entire -	 * (new) free extent. -	 */ -	error = xfs_rtmodify_summary(mp, tp, -		XFS_RTBLOCKLOG(postblock + 1 - preblock), -		XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb); +error:  	return error;  }  /* - * Read and return the summary information for a given extent size, - * bitmap block combination. - * Keeps track of a current summary block, so we don't keep reading - * it from the buffer cache. - */ -STATIC int				/* error */ -xfs_rtget_summary( -	xfs_mount_t	*mp,		/* file system mount structure */ -	xfs_trans_t	*tp,		/* transaction pointer */ -	int		log,		/* log2 of extent size */ -	xfs_rtblock_t	bbno,		/* bitmap block number */ -	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */ -	xfs_fsblock_t	*rsb,		/* in/out: summary block number */ -	xfs_suminfo_t	*sum)		/* out: summary info for this block */ -{ -	xfs_buf_t	*bp;		/* buffer for summary block */ -	int		error;		/* error value */ -	xfs_fsblock_t	sb;		/* summary fsblock */ -	int		so;		/* index into the summary file */ -	xfs_suminfo_t	*sp;		/* pointer to returned data */ - -	/* -	 * Compute entry number in the summary file. -	 */ -	so = XFS_SUMOFFS(mp, log, bbno); -	/* -	 * Compute the block number in the summary file. -	 */ -	sb = XFS_SUMOFFSTOBLOCK(mp, so); -	/* -	 * If we have an old buffer, and the block number matches, use that. -	 */ -	if (rbpp && *rbpp && *rsb == sb) -		bp = *rbpp; -	/* -	 * Otherwise we have to get the buffer. -	 */ -	else { -		/* -		 * If there was an old one, get rid of it first. -		 */ -		if (rbpp && *rbpp) -			xfs_trans_brelse(tp, *rbpp); -		error = xfs_rtbuf_get(mp, tp, sb, 1, &bp); -		if (error) { -			return error; -		} -		/* -		 * Remember this buffer and block for the next call. -		 */ -		if (rbpp) { -			*rbpp = bp; -			*rsb = sb; -		} -	} -	/* -	 * Point to the summary information & copy it out. -	 */ -	sp = XFS_SUMPTR(mp, bp, so); -	*sum = *sp; -	/* -	 * Drop the buffer if we're not asked to remember it. -	 */ -	if (!rbpp) -		xfs_trans_brelse(tp, bp); -	return 0; -} - -/* - * Set the given range of bitmap bits to the given value. - * Do whatever I/O and logging is required. - */ -STATIC int				/* error */ -xfs_rtmodify_range( -	xfs_mount_t	*mp,		/* file system mount point */ -	xfs_trans_t	*tp,		/* transaction pointer */ -	xfs_rtblock_t	start,		/* starting block to modify */ -	xfs_extlen_t	len,		/* length of extent to modify */ -	int		val)		/* 1 for free, 0 for allocated */ -{ -	xfs_rtword_t	*b;		/* current word in buffer */ -	int		bit;		/* bit number in the word */ -	xfs_rtblock_t	block;		/* bitmap block number */ -	xfs_buf_t	*bp;		/* buf for the block */ -	xfs_rtword_t	*bufp;		/* starting word in buffer */ -	int		error;		/* error value */ -	xfs_rtword_t	*first;		/* first used word in the buffer */ -	int		i;		/* current bit number rel. to start */ -	int		lastbit;	/* last useful bit in word */ -	xfs_rtword_t	mask;		/* mask o frelevant bits for value */ -	int		word;		/* word number in the buffer */ - -	/* -	 * Compute starting bitmap block number. -	 */ -	block = XFS_BITTOBLOCK(mp, start); -	/* -	 * Read the bitmap block, and point to its data. -	 */ -	error = xfs_rtbuf_get(mp, tp, block, 0, &bp); -	if (error) { -		return error; -	} -	bufp = bp->b_addr; -	/* -	 * Compute the starting word's address, and starting bit. -	 */ -	word = XFS_BITTOWORD(mp, start); -	first = b = &bufp[word]; -	bit = (int)(start & (XFS_NBWORD - 1)); -	/* -	 * 0 (allocated) => all zeroes; 1 (free) => all ones. -	 */ -	val = -val; -	/* -	 * If not starting on a word boundary, deal with the first -	 * (partial) word. -	 */ -	if (bit) { -		/* -		 * Compute first bit not changed and mask of relevant bits. -		 */ -		lastbit = XFS_RTMIN(bit + len, XFS_NBWORD); -		mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit; -		/* -		 * Set/clear the active bits. -		 */ -		if (val) -			*b |= mask; -		else -			*b &= ~mask; -		i = lastbit - bit; -		/* -		 * Go on to the next block if that's where the next word is -		 * and we need the next word. -		 */ -		if (++word == XFS_BLOCKWSIZE(mp) && i < len) { -			/* -			 * Log the changed part of this block. -			 * Get the next one. -			 */ -			xfs_trans_log_buf(tp, bp, -				(uint)((char *)first - (char *)bufp), -				(uint)((char *)b - (char *)bufp)); -			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); -			if (error) { -				return error; -			} -			first = b = bufp = bp->b_addr; -			word = 0; -		} else { -			/* -			 * Go on to the next word in the buffer -			 */ -			b++; -		} -	} else { -		/* -		 * Starting on a word boundary, no partial word. -		 */ -		i = 0; -	} -	/* -	 * Loop over whole words in buffers.  When we use up one buffer -	 * we move on to the next one. -	 */ -	while (len - i >= XFS_NBWORD) { -		/* -		 * Set the word value correctly. -		 */ -		*b = val; -		i += XFS_NBWORD; -		/* -		 * Go on to the next block if that's where the next word is -		 * and we need the next word. -		 */ -		if (++word == XFS_BLOCKWSIZE(mp) && i < len) { -			/* -			 * Log the changed part of this block. -			 * Get the next one. -			 */ -			xfs_trans_log_buf(tp, bp, -				(uint)((char *)first - (char *)bufp), -				(uint)((char *)b - (char *)bufp)); -			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); -			if (error) { -				return error; -			} -			first = b = bufp = bp->b_addr; -			word = 0; -		} else { -			/* -			 * Go on to the next word in the buffer -			 */ -			b++; -		} -	} -	/* -	 * If not ending on a word boundary, deal with the last -	 * (partial) word. -	 */ -	if ((lastbit = len - i)) { -		/* -		 * Compute a mask of relevant bits. -		 */ -		bit = 0; -		mask = ((xfs_rtword_t)1 << lastbit) - 1; -		/* -		 * Set/clear the active bits. -		 */ -		if (val) -			*b |= mask; -		else -			*b &= ~mask; -		b++; -	} -	/* -	 * Log any remaining changed bytes. -	 */ -	if (b > first) -		xfs_trans_log_buf(tp, bp, (uint)((char *)first - (char *)bufp), -			(uint)((char *)b - (char *)bufp - 1)); -	return 0; -} - -/* - * Read and modify the summary information for a given extent size, - * bitmap block combination. - * Keeps track of a current summary block, so we don't keep reading - * it from the buffer cache. - */ -STATIC int				/* error */ -xfs_rtmodify_summary( -	xfs_mount_t	*mp,		/* file system mount point */ -	xfs_trans_t	*tp,		/* transaction pointer */ -	int		log,		/* log2 of extent size */ -	xfs_rtblock_t	bbno,		/* bitmap block number */ -	int		delta,		/* change to make to summary info */ -	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */ -	xfs_fsblock_t	*rsb)		/* in/out: summary block number */ -{ -	xfs_buf_t	*bp;		/* buffer for the summary block */ -	int		error;		/* error value */ -	xfs_fsblock_t	sb;		/* summary fsblock */ -	int		so;		/* index into the summary file */ -	xfs_suminfo_t	*sp;		/* pointer to returned data */ - -	/* -	 * Compute entry number in the summary file. -	 */ -	so = XFS_SUMOFFS(mp, log, bbno); -	/* -	 * Compute the block number in the summary file. -	 */ -	sb = XFS_SUMOFFSTOBLOCK(mp, so); -	/* -	 * If we have an old buffer, and the block number matches, use that. -	 */ -	if (rbpp && *rbpp && *rsb == sb) -		bp = *rbpp; -	/* -	 * Otherwise we have to get the buffer. -	 */ -	else { -		/* -		 * If there was an old one, get rid of it first. -		 */ -		if (rbpp && *rbpp) -			xfs_trans_brelse(tp, *rbpp); -		error = xfs_rtbuf_get(mp, tp, sb, 1, &bp); -		if (error) { -			return error; -		} -		/* -		 * Remember this buffer and block for the next call. -		 */ -		if (rbpp) { -			*rbpp = bp; -			*rsb = sb; -		} -	} -	/* -	 * Point to the summary information, modify and log it. -	 */ -	sp = XFS_SUMPTR(mp, bp, so); -	*sp += delta; -	xfs_trans_log_buf(tp, bp, (uint)((char *)sp - (char *)bp->b_addr), -		(uint)((char *)sp - (char *)bp->b_addr + sizeof(*sp) - 1)); -	return 0; -} - -/*   * Visible (exported) functions.   */ @@ -2129,66 +1231,6 @@ xfs_rtallocate_extent(  }  /* - * Free an extent in the realtime subvolume.  Length is expressed in - * realtime extents, as is the block number. - */ -int					/* error */ -xfs_rtfree_extent( -	xfs_trans_t	*tp,		/* transaction pointer */ -	xfs_rtblock_t	bno,		/* starting block number to free */ -	xfs_extlen_t	len)		/* length of extent freed */ -{ -	int		error;		/* error value */ -	xfs_mount_t	*mp;		/* file system mount structure */ -	xfs_fsblock_t	sb;		/* summary file block number */ -	xfs_buf_t	*sumbp;		/* summary file block buffer */ - -	mp = tp->t_mountp; - -	ASSERT(mp->m_rbmip->i_itemp != NULL); -	ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL)); - -#ifdef DEBUG -	/* -	 * Check to see that this whole range is currently allocated. -	 */ -	{ -		int	stat;		/* result from checking range */ - -		error = xfs_rtcheck_alloc_range(mp, tp, bno, len, &stat); -		if (error) { -			return error; -		} -		ASSERT(stat); -	} -#endif -	sumbp = NULL; -	/* -	 * Free the range of realtime blocks. -	 */ -	error = xfs_rtfree_range(mp, tp, bno, len, &sumbp, &sb); -	if (error) { -		return error; -	} -	/* -	 * Mark more blocks free in the superblock. -	 */ -	xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS, (long)len); -	/* -	 * If we've now freed all the blocks, reset the file sequence -	 * number to 0. -	 */ -	if (tp->t_frextents_delta + mp->m_sb.sb_frextents == -	    mp->m_sb.sb_rextents) { -		if (!(mp->m_rbmip->i_d.di_flags & XFS_DIFLAG_NEWRTBM)) -			mp->m_rbmip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM; -		*(__uint64_t *)&mp->m_rbmip->i_d.di_atime = 0; -		xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE); -	} -	return 0; -} - -/*   * Initialize realtime fields in the mount structure.   */  int				/* error */  | 
