xref: /OK3568_Linux_fs/kernel/fs/xfs/libxfs/xfs_rtbitmap.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (c) 2000-2005 Silicon Graphics, Inc.
4*4882a593Smuzhiyun  * All Rights Reserved.
5*4882a593Smuzhiyun  */
6*4882a593Smuzhiyun #include "xfs.h"
7*4882a593Smuzhiyun #include "xfs_fs.h"
8*4882a593Smuzhiyun #include "xfs_shared.h"
9*4882a593Smuzhiyun #include "xfs_format.h"
10*4882a593Smuzhiyun #include "xfs_log_format.h"
11*4882a593Smuzhiyun #include "xfs_trans_resv.h"
12*4882a593Smuzhiyun #include "xfs_bit.h"
13*4882a593Smuzhiyun #include "xfs_mount.h"
14*4882a593Smuzhiyun #include "xfs_inode.h"
15*4882a593Smuzhiyun #include "xfs_bmap.h"
16*4882a593Smuzhiyun #include "xfs_trans.h"
17*4882a593Smuzhiyun #include "xfs_rtalloc.h"
18*4882a593Smuzhiyun #include "xfs_error.h"
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun /*
21*4882a593Smuzhiyun  * Realtime allocator bitmap functions shared with userspace.
22*4882a593Smuzhiyun  */
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun /*
25*4882a593Smuzhiyun  * Real time buffers need verifiers to avoid runtime warnings during IO.
26*4882a593Smuzhiyun  * We don't have anything to verify, however, so these are just dummy
27*4882a593Smuzhiyun  * operations.
28*4882a593Smuzhiyun  */
29*4882a593Smuzhiyun static void
xfs_rtbuf_verify_read(struct xfs_buf * bp)30*4882a593Smuzhiyun xfs_rtbuf_verify_read(
31*4882a593Smuzhiyun 	struct xfs_buf	*bp)
32*4882a593Smuzhiyun {
33*4882a593Smuzhiyun 	return;
34*4882a593Smuzhiyun }
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun static void
xfs_rtbuf_verify_write(struct xfs_buf * bp)37*4882a593Smuzhiyun xfs_rtbuf_verify_write(
38*4882a593Smuzhiyun 	struct xfs_buf	*bp)
39*4882a593Smuzhiyun {
40*4882a593Smuzhiyun 	return;
41*4882a593Smuzhiyun }
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun const struct xfs_buf_ops xfs_rtbuf_ops = {
44*4882a593Smuzhiyun 	.name = "rtbuf",
45*4882a593Smuzhiyun 	.verify_read = xfs_rtbuf_verify_read,
46*4882a593Smuzhiyun 	.verify_write = xfs_rtbuf_verify_write,
47*4882a593Smuzhiyun };
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun /*
50*4882a593Smuzhiyun  * Get a buffer for the bitmap or summary file block specified.
51*4882a593Smuzhiyun  * The buffer is returned read and locked.
52*4882a593Smuzhiyun  */
53*4882a593Smuzhiyun int
xfs_rtbuf_get(xfs_mount_t * mp,xfs_trans_t * tp,xfs_rtblock_t block,int issum,xfs_buf_t ** bpp)54*4882a593Smuzhiyun xfs_rtbuf_get(
55*4882a593Smuzhiyun 	xfs_mount_t	*mp,		/* file system mount structure */
56*4882a593Smuzhiyun 	xfs_trans_t	*tp,		/* transaction pointer */
57*4882a593Smuzhiyun 	xfs_rtblock_t	block,		/* block number in bitmap or summary */
58*4882a593Smuzhiyun 	int		issum,		/* is summary not bitmap */
59*4882a593Smuzhiyun 	xfs_buf_t	**bpp)		/* output: buffer for the block */
60*4882a593Smuzhiyun {
61*4882a593Smuzhiyun 	xfs_buf_t	*bp;		/* block buffer, result */
62*4882a593Smuzhiyun 	xfs_inode_t	*ip;		/* bitmap or summary inode */
63*4882a593Smuzhiyun 	xfs_bmbt_irec_t	map;
64*4882a593Smuzhiyun 	int		nmap = 1;
65*4882a593Smuzhiyun 	int		error;		/* error value */
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun 	ip = issum ? mp->m_rsumip : mp->m_rbmip;
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun 	error = xfs_bmapi_read(ip, block, 1, &map, &nmap, 0);
70*4882a593Smuzhiyun 	if (error)
71*4882a593Smuzhiyun 		return error;
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun 	if (XFS_IS_CORRUPT(mp, nmap == 0 || !xfs_bmap_is_written_extent(&map)))
74*4882a593Smuzhiyun 		return -EFSCORRUPTED;
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun 	ASSERT(map.br_startblock != NULLFSBLOCK);
77*4882a593Smuzhiyun 	error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
78*4882a593Smuzhiyun 				   XFS_FSB_TO_DADDR(mp, map.br_startblock),
79*4882a593Smuzhiyun 				   mp->m_bsize, 0, &bp, &xfs_rtbuf_ops);
80*4882a593Smuzhiyun 	if (error)
81*4882a593Smuzhiyun 		return error;
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun 	xfs_trans_buf_set_type(tp, bp, issum ? XFS_BLFT_RTSUMMARY_BUF
84*4882a593Smuzhiyun 					     : XFS_BLFT_RTBITMAP_BUF);
85*4882a593Smuzhiyun 	*bpp = bp;
86*4882a593Smuzhiyun 	return 0;
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun /*
90*4882a593Smuzhiyun  * Searching backward from start to limit, find the first block whose
91*4882a593Smuzhiyun  * allocated/free state is different from start's.
92*4882a593Smuzhiyun  */
93*4882a593Smuzhiyun int
xfs_rtfind_back(xfs_mount_t * mp,xfs_trans_t * tp,xfs_rtblock_t start,xfs_rtblock_t limit,xfs_rtblock_t * rtblock)94*4882a593Smuzhiyun xfs_rtfind_back(
95*4882a593Smuzhiyun 	xfs_mount_t	*mp,		/* file system mount point */
96*4882a593Smuzhiyun 	xfs_trans_t	*tp,		/* transaction pointer */
97*4882a593Smuzhiyun 	xfs_rtblock_t	start,		/* starting block to look at */
98*4882a593Smuzhiyun 	xfs_rtblock_t	limit,		/* last block to look at */
99*4882a593Smuzhiyun 	xfs_rtblock_t	*rtblock)	/* out: start block found */
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun 	xfs_rtword_t	*b;		/* current word in buffer */
102*4882a593Smuzhiyun 	int		bit;		/* bit number in the word */
103*4882a593Smuzhiyun 	xfs_rtblock_t	block;		/* bitmap block number */
104*4882a593Smuzhiyun 	xfs_buf_t	*bp;		/* buf for the block */
105*4882a593Smuzhiyun 	xfs_rtword_t	*bufp;		/* starting word in buffer */
106*4882a593Smuzhiyun 	int		error;		/* error value */
107*4882a593Smuzhiyun 	xfs_rtblock_t	firstbit;	/* first useful bit in the word */
108*4882a593Smuzhiyun 	xfs_rtblock_t	i;		/* current bit number rel. to start */
109*4882a593Smuzhiyun 	xfs_rtblock_t	len;		/* length of inspected area */
110*4882a593Smuzhiyun 	xfs_rtword_t	mask;		/* mask of relevant bits for value */
111*4882a593Smuzhiyun 	xfs_rtword_t	want;		/* mask for "good" values */
112*4882a593Smuzhiyun 	xfs_rtword_t	wdiff;		/* difference from wanted value */
113*4882a593Smuzhiyun 	int		word;		/* word number in the buffer */
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun 	/*
116*4882a593Smuzhiyun 	 * Compute and read in starting bitmap block for starting block.
117*4882a593Smuzhiyun 	 */
118*4882a593Smuzhiyun 	block = XFS_BITTOBLOCK(mp, start);
119*4882a593Smuzhiyun 	error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
120*4882a593Smuzhiyun 	if (error) {
121*4882a593Smuzhiyun 		return error;
122*4882a593Smuzhiyun 	}
123*4882a593Smuzhiyun 	bufp = bp->b_addr;
124*4882a593Smuzhiyun 	/*
125*4882a593Smuzhiyun 	 * Get the first word's index & point to it.
126*4882a593Smuzhiyun 	 */
127*4882a593Smuzhiyun 	word = XFS_BITTOWORD(mp, start);
128*4882a593Smuzhiyun 	b = &bufp[word];
129*4882a593Smuzhiyun 	bit = (int)(start & (XFS_NBWORD - 1));
130*4882a593Smuzhiyun 	len = start - limit + 1;
131*4882a593Smuzhiyun 	/*
132*4882a593Smuzhiyun 	 * Compute match value, based on the bit at start: if 1 (free)
133*4882a593Smuzhiyun 	 * then all-ones, else all-zeroes.
134*4882a593Smuzhiyun 	 */
135*4882a593Smuzhiyun 	want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
136*4882a593Smuzhiyun 	/*
137*4882a593Smuzhiyun 	 * If the starting position is not word-aligned, deal with the
138*4882a593Smuzhiyun 	 * partial word.
139*4882a593Smuzhiyun 	 */
140*4882a593Smuzhiyun 	if (bit < XFS_NBWORD - 1) {
141*4882a593Smuzhiyun 		/*
142*4882a593Smuzhiyun 		 * Calculate first (leftmost) bit number to look at,
143*4882a593Smuzhiyun 		 * and mask for all the relevant bits in this word.
144*4882a593Smuzhiyun 		 */
145*4882a593Smuzhiyun 		firstbit = XFS_RTMAX((xfs_srtblock_t)(bit - len + 1), 0);
146*4882a593Smuzhiyun 		mask = (((xfs_rtword_t)1 << (bit - firstbit + 1)) - 1) <<
147*4882a593Smuzhiyun 			firstbit;
148*4882a593Smuzhiyun 		/*
149*4882a593Smuzhiyun 		 * Calculate the difference between the value there
150*4882a593Smuzhiyun 		 * and what we're looking for.
151*4882a593Smuzhiyun 		 */
152*4882a593Smuzhiyun 		if ((wdiff = (*b ^ want) & mask)) {
153*4882a593Smuzhiyun 			/*
154*4882a593Smuzhiyun 			 * Different.  Mark where we are and return.
155*4882a593Smuzhiyun 			 */
156*4882a593Smuzhiyun 			xfs_trans_brelse(tp, bp);
157*4882a593Smuzhiyun 			i = bit - XFS_RTHIBIT(wdiff);
158*4882a593Smuzhiyun 			*rtblock = start - i + 1;
159*4882a593Smuzhiyun 			return 0;
160*4882a593Smuzhiyun 		}
161*4882a593Smuzhiyun 		i = bit - firstbit + 1;
162*4882a593Smuzhiyun 		/*
163*4882a593Smuzhiyun 		 * Go on to previous block if that's where the previous word is
164*4882a593Smuzhiyun 		 * and we need the previous word.
165*4882a593Smuzhiyun 		 */
166*4882a593Smuzhiyun 		if (--word == -1 && i < len) {
167*4882a593Smuzhiyun 			/*
168*4882a593Smuzhiyun 			 * If done with this block, get the previous one.
169*4882a593Smuzhiyun 			 */
170*4882a593Smuzhiyun 			xfs_trans_brelse(tp, bp);
171*4882a593Smuzhiyun 			error = xfs_rtbuf_get(mp, tp, --block, 0, &bp);
172*4882a593Smuzhiyun 			if (error) {
173*4882a593Smuzhiyun 				return error;
174*4882a593Smuzhiyun 			}
175*4882a593Smuzhiyun 			bufp = bp->b_addr;
176*4882a593Smuzhiyun 			word = XFS_BLOCKWMASK(mp);
177*4882a593Smuzhiyun 			b = &bufp[word];
178*4882a593Smuzhiyun 		} else {
179*4882a593Smuzhiyun 			/*
180*4882a593Smuzhiyun 			 * Go on to the previous word in the buffer.
181*4882a593Smuzhiyun 			 */
182*4882a593Smuzhiyun 			b--;
183*4882a593Smuzhiyun 		}
184*4882a593Smuzhiyun 	} else {
185*4882a593Smuzhiyun 		/*
186*4882a593Smuzhiyun 		 * Starting on a word boundary, no partial word.
187*4882a593Smuzhiyun 		 */
188*4882a593Smuzhiyun 		i = 0;
189*4882a593Smuzhiyun 	}
190*4882a593Smuzhiyun 	/*
191*4882a593Smuzhiyun 	 * Loop over whole words in buffers.  When we use up one buffer
192*4882a593Smuzhiyun 	 * we move on to the previous one.
193*4882a593Smuzhiyun 	 */
194*4882a593Smuzhiyun 	while (len - i >= XFS_NBWORD) {
195*4882a593Smuzhiyun 		/*
196*4882a593Smuzhiyun 		 * Compute difference between actual and desired value.
197*4882a593Smuzhiyun 		 */
198*4882a593Smuzhiyun 		if ((wdiff = *b ^ want)) {
199*4882a593Smuzhiyun 			/*
200*4882a593Smuzhiyun 			 * Different, mark where we are and return.
201*4882a593Smuzhiyun 			 */
202*4882a593Smuzhiyun 			xfs_trans_brelse(tp, bp);
203*4882a593Smuzhiyun 			i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
204*4882a593Smuzhiyun 			*rtblock = start - i + 1;
205*4882a593Smuzhiyun 			return 0;
206*4882a593Smuzhiyun 		}
207*4882a593Smuzhiyun 		i += XFS_NBWORD;
208*4882a593Smuzhiyun 		/*
209*4882a593Smuzhiyun 		 * Go on to previous block if that's where the previous word is
210*4882a593Smuzhiyun 		 * and we need the previous word.
211*4882a593Smuzhiyun 		 */
212*4882a593Smuzhiyun 		if (--word == -1 && i < len) {
213*4882a593Smuzhiyun 			/*
214*4882a593Smuzhiyun 			 * If done with this block, get the previous one.
215*4882a593Smuzhiyun 			 */
216*4882a593Smuzhiyun 			xfs_trans_brelse(tp, bp);
217*4882a593Smuzhiyun 			error = xfs_rtbuf_get(mp, tp, --block, 0, &bp);
218*4882a593Smuzhiyun 			if (error) {
219*4882a593Smuzhiyun 				return error;
220*4882a593Smuzhiyun 			}
221*4882a593Smuzhiyun 			bufp = bp->b_addr;
222*4882a593Smuzhiyun 			word = XFS_BLOCKWMASK(mp);
223*4882a593Smuzhiyun 			b = &bufp[word];
224*4882a593Smuzhiyun 		} else {
225*4882a593Smuzhiyun 			/*
226*4882a593Smuzhiyun 			 * Go on to the previous word in the buffer.
227*4882a593Smuzhiyun 			 */
228*4882a593Smuzhiyun 			b--;
229*4882a593Smuzhiyun 		}
230*4882a593Smuzhiyun 	}
231*4882a593Smuzhiyun 	/*
232*4882a593Smuzhiyun 	 * If not ending on a word boundary, deal with the last
233*4882a593Smuzhiyun 	 * (partial) word.
234*4882a593Smuzhiyun 	 */
235*4882a593Smuzhiyun 	if (len - i) {
236*4882a593Smuzhiyun 		/*
237*4882a593Smuzhiyun 		 * Calculate first (leftmost) bit number to look at,
238*4882a593Smuzhiyun 		 * and mask for all the relevant bits in this word.
239*4882a593Smuzhiyun 		 */
240*4882a593Smuzhiyun 		firstbit = XFS_NBWORD - (len - i);
241*4882a593Smuzhiyun 		mask = (((xfs_rtword_t)1 << (len - i)) - 1) << firstbit;
242*4882a593Smuzhiyun 		/*
243*4882a593Smuzhiyun 		 * Compute difference between actual and desired value.
244*4882a593Smuzhiyun 		 */
245*4882a593Smuzhiyun 		if ((wdiff = (*b ^ want) & mask)) {
246*4882a593Smuzhiyun 			/*
247*4882a593Smuzhiyun 			 * Different, mark where we are and return.
248*4882a593Smuzhiyun 			 */
249*4882a593Smuzhiyun 			xfs_trans_brelse(tp, bp);
250*4882a593Smuzhiyun 			i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
251*4882a593Smuzhiyun 			*rtblock = start - i + 1;
252*4882a593Smuzhiyun 			return 0;
253*4882a593Smuzhiyun 		} else
254*4882a593Smuzhiyun 			i = len;
255*4882a593Smuzhiyun 	}
256*4882a593Smuzhiyun 	/*
257*4882a593Smuzhiyun 	 * No match, return that we scanned the whole area.
258*4882a593Smuzhiyun 	 */
259*4882a593Smuzhiyun 	xfs_trans_brelse(tp, bp);
260*4882a593Smuzhiyun 	*rtblock = start - i + 1;
261*4882a593Smuzhiyun 	return 0;
262*4882a593Smuzhiyun }
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun /*
265*4882a593Smuzhiyun  * Searching forward from start to limit, find the first block whose
266*4882a593Smuzhiyun  * allocated/free state is different from start's.
267*4882a593Smuzhiyun  */
268*4882a593Smuzhiyun int
xfs_rtfind_forw(xfs_mount_t * mp,xfs_trans_t * tp,xfs_rtblock_t start,xfs_rtblock_t limit,xfs_rtblock_t * rtblock)269*4882a593Smuzhiyun xfs_rtfind_forw(
270*4882a593Smuzhiyun 	xfs_mount_t	*mp,		/* file system mount point */
271*4882a593Smuzhiyun 	xfs_trans_t	*tp,		/* transaction pointer */
272*4882a593Smuzhiyun 	xfs_rtblock_t	start,		/* starting block to look at */
273*4882a593Smuzhiyun 	xfs_rtblock_t	limit,		/* last block to look at */
274*4882a593Smuzhiyun 	xfs_rtblock_t	*rtblock)	/* out: start block found */
275*4882a593Smuzhiyun {
276*4882a593Smuzhiyun 	xfs_rtword_t	*b;		/* current word in buffer */
277*4882a593Smuzhiyun 	int		bit;		/* bit number in the word */
278*4882a593Smuzhiyun 	xfs_rtblock_t	block;		/* bitmap block number */
279*4882a593Smuzhiyun 	xfs_buf_t	*bp;		/* buf for the block */
280*4882a593Smuzhiyun 	xfs_rtword_t	*bufp;		/* starting word in buffer */
281*4882a593Smuzhiyun 	int		error;		/* error value */
282*4882a593Smuzhiyun 	xfs_rtblock_t	i;		/* current bit number rel. to start */
283*4882a593Smuzhiyun 	xfs_rtblock_t	lastbit;	/* last useful bit in the word */
284*4882a593Smuzhiyun 	xfs_rtblock_t	len;		/* length of inspected area */
285*4882a593Smuzhiyun 	xfs_rtword_t	mask;		/* mask of relevant bits for value */
286*4882a593Smuzhiyun 	xfs_rtword_t	want;		/* mask for "good" values */
287*4882a593Smuzhiyun 	xfs_rtword_t	wdiff;		/* difference from wanted value */
288*4882a593Smuzhiyun 	int		word;		/* word number in the buffer */
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun 	/*
291*4882a593Smuzhiyun 	 * Compute and read in starting bitmap block for starting block.
292*4882a593Smuzhiyun 	 */
293*4882a593Smuzhiyun 	block = XFS_BITTOBLOCK(mp, start);
294*4882a593Smuzhiyun 	error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
295*4882a593Smuzhiyun 	if (error) {
296*4882a593Smuzhiyun 		return error;
297*4882a593Smuzhiyun 	}
298*4882a593Smuzhiyun 	bufp = bp->b_addr;
299*4882a593Smuzhiyun 	/*
300*4882a593Smuzhiyun 	 * Get the first word's index & point to it.
301*4882a593Smuzhiyun 	 */
302*4882a593Smuzhiyun 	word = XFS_BITTOWORD(mp, start);
303*4882a593Smuzhiyun 	b = &bufp[word];
304*4882a593Smuzhiyun 	bit = (int)(start & (XFS_NBWORD - 1));
305*4882a593Smuzhiyun 	len = limit - start + 1;
306*4882a593Smuzhiyun 	/*
307*4882a593Smuzhiyun 	 * Compute match value, based on the bit at start: if 1 (free)
308*4882a593Smuzhiyun 	 * then all-ones, else all-zeroes.
309*4882a593Smuzhiyun 	 */
310*4882a593Smuzhiyun 	want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
311*4882a593Smuzhiyun 	/*
312*4882a593Smuzhiyun 	 * If the starting position is not word-aligned, deal with the
313*4882a593Smuzhiyun 	 * partial word.
314*4882a593Smuzhiyun 	 */
315*4882a593Smuzhiyun 	if (bit) {
316*4882a593Smuzhiyun 		/*
317*4882a593Smuzhiyun 		 * Calculate last (rightmost) bit number to look at,
318*4882a593Smuzhiyun 		 * and mask for all the relevant bits in this word.
319*4882a593Smuzhiyun 		 */
320*4882a593Smuzhiyun 		lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
321*4882a593Smuzhiyun 		mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
322*4882a593Smuzhiyun 		/*
323*4882a593Smuzhiyun 		 * Calculate the difference between the value there
324*4882a593Smuzhiyun 		 * and what we're looking for.
325*4882a593Smuzhiyun 		 */
326*4882a593Smuzhiyun 		if ((wdiff = (*b ^ want) & mask)) {
327*4882a593Smuzhiyun 			/*
328*4882a593Smuzhiyun 			 * Different.  Mark where we are and return.
329*4882a593Smuzhiyun 			 */
330*4882a593Smuzhiyun 			xfs_trans_brelse(tp, bp);
331*4882a593Smuzhiyun 			i = XFS_RTLOBIT(wdiff) - bit;
332*4882a593Smuzhiyun 			*rtblock = start + i - 1;
333*4882a593Smuzhiyun 			return 0;
334*4882a593Smuzhiyun 		}
335*4882a593Smuzhiyun 		i = lastbit - bit;
336*4882a593Smuzhiyun 		/*
337*4882a593Smuzhiyun 		 * Go on to next block if that's where the next word is
338*4882a593Smuzhiyun 		 * and we need the next word.
339*4882a593Smuzhiyun 		 */
340*4882a593Smuzhiyun 		if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
341*4882a593Smuzhiyun 			/*
342*4882a593Smuzhiyun 			 * If done with this block, get the previous one.
343*4882a593Smuzhiyun 			 */
344*4882a593Smuzhiyun 			xfs_trans_brelse(tp, bp);
345*4882a593Smuzhiyun 			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
346*4882a593Smuzhiyun 			if (error) {
347*4882a593Smuzhiyun 				return error;
348*4882a593Smuzhiyun 			}
349*4882a593Smuzhiyun 			b = bufp = bp->b_addr;
350*4882a593Smuzhiyun 			word = 0;
351*4882a593Smuzhiyun 		} else {
352*4882a593Smuzhiyun 			/*
353*4882a593Smuzhiyun 			 * Go on to the previous word in the buffer.
354*4882a593Smuzhiyun 			 */
355*4882a593Smuzhiyun 			b++;
356*4882a593Smuzhiyun 		}
357*4882a593Smuzhiyun 	} else {
358*4882a593Smuzhiyun 		/*
359*4882a593Smuzhiyun 		 * Starting on a word boundary, no partial word.
360*4882a593Smuzhiyun 		 */
361*4882a593Smuzhiyun 		i = 0;
362*4882a593Smuzhiyun 	}
363*4882a593Smuzhiyun 	/*
364*4882a593Smuzhiyun 	 * Loop over whole words in buffers.  When we use up one buffer
365*4882a593Smuzhiyun 	 * we move on to the next one.
366*4882a593Smuzhiyun 	 */
367*4882a593Smuzhiyun 	while (len - i >= XFS_NBWORD) {
368*4882a593Smuzhiyun 		/*
369*4882a593Smuzhiyun 		 * Compute difference between actual and desired value.
370*4882a593Smuzhiyun 		 */
371*4882a593Smuzhiyun 		if ((wdiff = *b ^ want)) {
372*4882a593Smuzhiyun 			/*
373*4882a593Smuzhiyun 			 * Different, mark where we are and return.
374*4882a593Smuzhiyun 			 */
375*4882a593Smuzhiyun 			xfs_trans_brelse(tp, bp);
376*4882a593Smuzhiyun 			i += XFS_RTLOBIT(wdiff);
377*4882a593Smuzhiyun 			*rtblock = start + i - 1;
378*4882a593Smuzhiyun 			return 0;
379*4882a593Smuzhiyun 		}
380*4882a593Smuzhiyun 		i += XFS_NBWORD;
381*4882a593Smuzhiyun 		/*
382*4882a593Smuzhiyun 		 * Go on to next block if that's where the next word is
383*4882a593Smuzhiyun 		 * and we need the next word.
384*4882a593Smuzhiyun 		 */
385*4882a593Smuzhiyun 		if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
386*4882a593Smuzhiyun 			/*
387*4882a593Smuzhiyun 			 * If done with this block, get the next one.
388*4882a593Smuzhiyun 			 */
389*4882a593Smuzhiyun 			xfs_trans_brelse(tp, bp);
390*4882a593Smuzhiyun 			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
391*4882a593Smuzhiyun 			if (error) {
392*4882a593Smuzhiyun 				return error;
393*4882a593Smuzhiyun 			}
394*4882a593Smuzhiyun 			b = bufp = bp->b_addr;
395*4882a593Smuzhiyun 			word = 0;
396*4882a593Smuzhiyun 		} else {
397*4882a593Smuzhiyun 			/*
398*4882a593Smuzhiyun 			 * Go on to the next word in the buffer.
399*4882a593Smuzhiyun 			 */
400*4882a593Smuzhiyun 			b++;
401*4882a593Smuzhiyun 		}
402*4882a593Smuzhiyun 	}
403*4882a593Smuzhiyun 	/*
404*4882a593Smuzhiyun 	 * If not ending on a word boundary, deal with the last
405*4882a593Smuzhiyun 	 * (partial) word.
406*4882a593Smuzhiyun 	 */
407*4882a593Smuzhiyun 	if ((lastbit = len - i)) {
408*4882a593Smuzhiyun 		/*
409*4882a593Smuzhiyun 		 * Calculate mask for all the relevant bits in this word.
410*4882a593Smuzhiyun 		 */
411*4882a593Smuzhiyun 		mask = ((xfs_rtword_t)1 << lastbit) - 1;
412*4882a593Smuzhiyun 		/*
413*4882a593Smuzhiyun 		 * Compute difference between actual and desired value.
414*4882a593Smuzhiyun 		 */
415*4882a593Smuzhiyun 		if ((wdiff = (*b ^ want) & mask)) {
416*4882a593Smuzhiyun 			/*
417*4882a593Smuzhiyun 			 * Different, mark where we are and return.
418*4882a593Smuzhiyun 			 */
419*4882a593Smuzhiyun 			xfs_trans_brelse(tp, bp);
420*4882a593Smuzhiyun 			i += XFS_RTLOBIT(wdiff);
421*4882a593Smuzhiyun 			*rtblock = start + i - 1;
422*4882a593Smuzhiyun 			return 0;
423*4882a593Smuzhiyun 		} else
424*4882a593Smuzhiyun 			i = len;
425*4882a593Smuzhiyun 	}
426*4882a593Smuzhiyun 	/*
427*4882a593Smuzhiyun 	 * No match, return that we scanned the whole area.
428*4882a593Smuzhiyun 	 */
429*4882a593Smuzhiyun 	xfs_trans_brelse(tp, bp);
430*4882a593Smuzhiyun 	*rtblock = start + i - 1;
431*4882a593Smuzhiyun 	return 0;
432*4882a593Smuzhiyun }
433*4882a593Smuzhiyun 
434*4882a593Smuzhiyun /*
435*4882a593Smuzhiyun  * Read and/or modify the summary information for a given extent size,
436*4882a593Smuzhiyun  * bitmap block combination.
437*4882a593Smuzhiyun  * Keeps track of a current summary block, so we don't keep reading
438*4882a593Smuzhiyun  * it from the buffer cache.
439*4882a593Smuzhiyun  *
440*4882a593Smuzhiyun  * Summary information is returned in *sum if specified.
441*4882a593Smuzhiyun  * If no delta is specified, returns summary only.
442*4882a593Smuzhiyun  */
443*4882a593Smuzhiyun int
xfs_rtmodify_summary_int(xfs_mount_t * mp,xfs_trans_t * tp,int log,xfs_rtblock_t bbno,int delta,xfs_buf_t ** rbpp,xfs_fsblock_t * rsb,xfs_suminfo_t * sum)444*4882a593Smuzhiyun xfs_rtmodify_summary_int(
445*4882a593Smuzhiyun 	xfs_mount_t	*mp,		/* file system mount structure */
446*4882a593Smuzhiyun 	xfs_trans_t	*tp,		/* transaction pointer */
447*4882a593Smuzhiyun 	int		log,		/* log2 of extent size */
448*4882a593Smuzhiyun 	xfs_rtblock_t	bbno,		/* bitmap block number */
449*4882a593Smuzhiyun 	int		delta,		/* change to make to summary info */
450*4882a593Smuzhiyun 	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */
451*4882a593Smuzhiyun 	xfs_fsblock_t	*rsb,		/* in/out: summary block number */
452*4882a593Smuzhiyun 	xfs_suminfo_t	*sum)		/* out: summary info for this block */
453*4882a593Smuzhiyun {
454*4882a593Smuzhiyun 	xfs_buf_t	*bp;		/* buffer for the summary block */
455*4882a593Smuzhiyun 	int		error;		/* error value */
456*4882a593Smuzhiyun 	xfs_fsblock_t	sb;		/* summary fsblock */
457*4882a593Smuzhiyun 	int		so;		/* index into the summary file */
458*4882a593Smuzhiyun 	xfs_suminfo_t	*sp;		/* pointer to returned data */
459*4882a593Smuzhiyun 
460*4882a593Smuzhiyun 	/*
461*4882a593Smuzhiyun 	 * Compute entry number in the summary file.
462*4882a593Smuzhiyun 	 */
463*4882a593Smuzhiyun 	so = XFS_SUMOFFS(mp, log, bbno);
464*4882a593Smuzhiyun 	/*
465*4882a593Smuzhiyun 	 * Compute the block number in the summary file.
466*4882a593Smuzhiyun 	 */
467*4882a593Smuzhiyun 	sb = XFS_SUMOFFSTOBLOCK(mp, so);
468*4882a593Smuzhiyun 	/*
469*4882a593Smuzhiyun 	 * If we have an old buffer, and the block number matches, use that.
470*4882a593Smuzhiyun 	 */
471*4882a593Smuzhiyun 	if (*rbpp && *rsb == sb)
472*4882a593Smuzhiyun 		bp = *rbpp;
473*4882a593Smuzhiyun 	/*
474*4882a593Smuzhiyun 	 * Otherwise we have to get the buffer.
475*4882a593Smuzhiyun 	 */
476*4882a593Smuzhiyun 	else {
477*4882a593Smuzhiyun 		/*
478*4882a593Smuzhiyun 		 * If there was an old one, get rid of it first.
479*4882a593Smuzhiyun 		 */
480*4882a593Smuzhiyun 		if (*rbpp)
481*4882a593Smuzhiyun 			xfs_trans_brelse(tp, *rbpp);
482*4882a593Smuzhiyun 		error = xfs_rtbuf_get(mp, tp, sb, 1, &bp);
483*4882a593Smuzhiyun 		if (error) {
484*4882a593Smuzhiyun 			return error;
485*4882a593Smuzhiyun 		}
486*4882a593Smuzhiyun 		/*
487*4882a593Smuzhiyun 		 * Remember this buffer and block for the next call.
488*4882a593Smuzhiyun 		 */
489*4882a593Smuzhiyun 		*rbpp = bp;
490*4882a593Smuzhiyun 		*rsb = sb;
491*4882a593Smuzhiyun 	}
492*4882a593Smuzhiyun 	/*
493*4882a593Smuzhiyun 	 * Point to the summary information, modify/log it, and/or copy it out.
494*4882a593Smuzhiyun 	 */
495*4882a593Smuzhiyun 	sp = XFS_SUMPTR(mp, bp, so);
496*4882a593Smuzhiyun 	if (delta) {
497*4882a593Smuzhiyun 		uint first = (uint)((char *)sp - (char *)bp->b_addr);
498*4882a593Smuzhiyun 
499*4882a593Smuzhiyun 		*sp += delta;
500*4882a593Smuzhiyun 		if (mp->m_rsum_cache) {
501*4882a593Smuzhiyun 			if (*sp == 0 && log == mp->m_rsum_cache[bbno])
502*4882a593Smuzhiyun 				mp->m_rsum_cache[bbno]++;
503*4882a593Smuzhiyun 			if (*sp != 0 && log < mp->m_rsum_cache[bbno])
504*4882a593Smuzhiyun 				mp->m_rsum_cache[bbno] = log;
505*4882a593Smuzhiyun 		}
506*4882a593Smuzhiyun 		xfs_trans_log_buf(tp, bp, first, first + sizeof(*sp) - 1);
507*4882a593Smuzhiyun 	}
508*4882a593Smuzhiyun 	if (sum)
509*4882a593Smuzhiyun 		*sum = *sp;
510*4882a593Smuzhiyun 	return 0;
511*4882a593Smuzhiyun }
512*4882a593Smuzhiyun 
513*4882a593Smuzhiyun int
xfs_rtmodify_summary(xfs_mount_t * mp,xfs_trans_t * tp,int log,xfs_rtblock_t bbno,int delta,xfs_buf_t ** rbpp,xfs_fsblock_t * rsb)514*4882a593Smuzhiyun xfs_rtmodify_summary(
515*4882a593Smuzhiyun 	xfs_mount_t	*mp,		/* file system mount structure */
516*4882a593Smuzhiyun 	xfs_trans_t	*tp,		/* transaction pointer */
517*4882a593Smuzhiyun 	int		log,		/* log2 of extent size */
518*4882a593Smuzhiyun 	xfs_rtblock_t	bbno,		/* bitmap block number */
519*4882a593Smuzhiyun 	int		delta,		/* change to make to summary info */
520*4882a593Smuzhiyun 	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */
521*4882a593Smuzhiyun 	xfs_fsblock_t	*rsb)		/* in/out: summary block number */
522*4882a593Smuzhiyun {
523*4882a593Smuzhiyun 	return xfs_rtmodify_summary_int(mp, tp, log, bbno,
524*4882a593Smuzhiyun 					delta, rbpp, rsb, NULL);
525*4882a593Smuzhiyun }
526*4882a593Smuzhiyun 
527*4882a593Smuzhiyun /*
528*4882a593Smuzhiyun  * Set the given range of bitmap bits to the given value.
529*4882a593Smuzhiyun  * Do whatever I/O and logging is required.
530*4882a593Smuzhiyun  */
531*4882a593Smuzhiyun int
xfs_rtmodify_range(xfs_mount_t * mp,xfs_trans_t * tp,xfs_rtblock_t start,xfs_extlen_t len,int val)532*4882a593Smuzhiyun xfs_rtmodify_range(
533*4882a593Smuzhiyun 	xfs_mount_t	*mp,		/* file system mount point */
534*4882a593Smuzhiyun 	xfs_trans_t	*tp,		/* transaction pointer */
535*4882a593Smuzhiyun 	xfs_rtblock_t	start,		/* starting block to modify */
536*4882a593Smuzhiyun 	xfs_extlen_t	len,		/* length of extent to modify */
537*4882a593Smuzhiyun 	int		val)		/* 1 for free, 0 for allocated */
538*4882a593Smuzhiyun {
539*4882a593Smuzhiyun 	xfs_rtword_t	*b;		/* current word in buffer */
540*4882a593Smuzhiyun 	int		bit;		/* bit number in the word */
541*4882a593Smuzhiyun 	xfs_rtblock_t	block;		/* bitmap block number */
542*4882a593Smuzhiyun 	xfs_buf_t	*bp;		/* buf for the block */
543*4882a593Smuzhiyun 	xfs_rtword_t	*bufp;		/* starting word in buffer */
544*4882a593Smuzhiyun 	int		error;		/* error value */
545*4882a593Smuzhiyun 	xfs_rtword_t	*first;		/* first used word in the buffer */
546*4882a593Smuzhiyun 	int		i;		/* current bit number rel. to start */
547*4882a593Smuzhiyun 	int		lastbit;	/* last useful bit in word */
548*4882a593Smuzhiyun 	xfs_rtword_t	mask;		/* mask o frelevant bits for value */
549*4882a593Smuzhiyun 	int		word;		/* word number in the buffer */
550*4882a593Smuzhiyun 
551*4882a593Smuzhiyun 	/*
552*4882a593Smuzhiyun 	 * Compute starting bitmap block number.
553*4882a593Smuzhiyun 	 */
554*4882a593Smuzhiyun 	block = XFS_BITTOBLOCK(mp, start);
555*4882a593Smuzhiyun 	/*
556*4882a593Smuzhiyun 	 * Read the bitmap block, and point to its data.
557*4882a593Smuzhiyun 	 */
558*4882a593Smuzhiyun 	error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
559*4882a593Smuzhiyun 	if (error) {
560*4882a593Smuzhiyun 		return error;
561*4882a593Smuzhiyun 	}
562*4882a593Smuzhiyun 	bufp = bp->b_addr;
563*4882a593Smuzhiyun 	/*
564*4882a593Smuzhiyun 	 * Compute the starting word's address, and starting bit.
565*4882a593Smuzhiyun 	 */
566*4882a593Smuzhiyun 	word = XFS_BITTOWORD(mp, start);
567*4882a593Smuzhiyun 	first = b = &bufp[word];
568*4882a593Smuzhiyun 	bit = (int)(start & (XFS_NBWORD - 1));
569*4882a593Smuzhiyun 	/*
570*4882a593Smuzhiyun 	 * 0 (allocated) => all zeroes; 1 (free) => all ones.
571*4882a593Smuzhiyun 	 */
572*4882a593Smuzhiyun 	val = -val;
573*4882a593Smuzhiyun 	/*
574*4882a593Smuzhiyun 	 * If not starting on a word boundary, deal with the first
575*4882a593Smuzhiyun 	 * (partial) word.
576*4882a593Smuzhiyun 	 */
577*4882a593Smuzhiyun 	if (bit) {
578*4882a593Smuzhiyun 		/*
579*4882a593Smuzhiyun 		 * Compute first bit not changed and mask of relevant bits.
580*4882a593Smuzhiyun 		 */
581*4882a593Smuzhiyun 		lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
582*4882a593Smuzhiyun 		mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
583*4882a593Smuzhiyun 		/*
584*4882a593Smuzhiyun 		 * Set/clear the active bits.
585*4882a593Smuzhiyun 		 */
586*4882a593Smuzhiyun 		if (val)
587*4882a593Smuzhiyun 			*b |= mask;
588*4882a593Smuzhiyun 		else
589*4882a593Smuzhiyun 			*b &= ~mask;
590*4882a593Smuzhiyun 		i = lastbit - bit;
591*4882a593Smuzhiyun 		/*
592*4882a593Smuzhiyun 		 * Go on to the next block if that's where the next word is
593*4882a593Smuzhiyun 		 * and we need the next word.
594*4882a593Smuzhiyun 		 */
595*4882a593Smuzhiyun 		if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
596*4882a593Smuzhiyun 			/*
597*4882a593Smuzhiyun 			 * Log the changed part of this block.
598*4882a593Smuzhiyun 			 * Get the next one.
599*4882a593Smuzhiyun 			 */
600*4882a593Smuzhiyun 			xfs_trans_log_buf(tp, bp,
601*4882a593Smuzhiyun 				(uint)((char *)first - (char *)bufp),
602*4882a593Smuzhiyun 				(uint)((char *)b - (char *)bufp));
603*4882a593Smuzhiyun 			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
604*4882a593Smuzhiyun 			if (error) {
605*4882a593Smuzhiyun 				return error;
606*4882a593Smuzhiyun 			}
607*4882a593Smuzhiyun 			first = b = bufp = bp->b_addr;
608*4882a593Smuzhiyun 			word = 0;
609*4882a593Smuzhiyun 		} else {
610*4882a593Smuzhiyun 			/*
611*4882a593Smuzhiyun 			 * Go on to the next word in the buffer
612*4882a593Smuzhiyun 			 */
613*4882a593Smuzhiyun 			b++;
614*4882a593Smuzhiyun 		}
615*4882a593Smuzhiyun 	} else {
616*4882a593Smuzhiyun 		/*
617*4882a593Smuzhiyun 		 * Starting on a word boundary, no partial word.
618*4882a593Smuzhiyun 		 */
619*4882a593Smuzhiyun 		i = 0;
620*4882a593Smuzhiyun 	}
621*4882a593Smuzhiyun 	/*
622*4882a593Smuzhiyun 	 * Loop over whole words in buffers.  When we use up one buffer
623*4882a593Smuzhiyun 	 * we move on to the next one.
624*4882a593Smuzhiyun 	 */
625*4882a593Smuzhiyun 	while (len - i >= XFS_NBWORD) {
626*4882a593Smuzhiyun 		/*
627*4882a593Smuzhiyun 		 * Set the word value correctly.
628*4882a593Smuzhiyun 		 */
629*4882a593Smuzhiyun 		*b = val;
630*4882a593Smuzhiyun 		i += XFS_NBWORD;
631*4882a593Smuzhiyun 		/*
632*4882a593Smuzhiyun 		 * Go on to the next block if that's where the next word is
633*4882a593Smuzhiyun 		 * and we need the next word.
634*4882a593Smuzhiyun 		 */
635*4882a593Smuzhiyun 		if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
636*4882a593Smuzhiyun 			/*
637*4882a593Smuzhiyun 			 * Log the changed part of this block.
638*4882a593Smuzhiyun 			 * Get the next one.
639*4882a593Smuzhiyun 			 */
640*4882a593Smuzhiyun 			xfs_trans_log_buf(tp, bp,
641*4882a593Smuzhiyun 				(uint)((char *)first - (char *)bufp),
642*4882a593Smuzhiyun 				(uint)((char *)b - (char *)bufp));
643*4882a593Smuzhiyun 			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
644*4882a593Smuzhiyun 			if (error) {
645*4882a593Smuzhiyun 				return error;
646*4882a593Smuzhiyun 			}
647*4882a593Smuzhiyun 			first = b = bufp = bp->b_addr;
648*4882a593Smuzhiyun 			word = 0;
649*4882a593Smuzhiyun 		} else {
650*4882a593Smuzhiyun 			/*
651*4882a593Smuzhiyun 			 * Go on to the next word in the buffer
652*4882a593Smuzhiyun 			 */
653*4882a593Smuzhiyun 			b++;
654*4882a593Smuzhiyun 		}
655*4882a593Smuzhiyun 	}
656*4882a593Smuzhiyun 	/*
657*4882a593Smuzhiyun 	 * If not ending on a word boundary, deal with the last
658*4882a593Smuzhiyun 	 * (partial) word.
659*4882a593Smuzhiyun 	 */
660*4882a593Smuzhiyun 	if ((lastbit = len - i)) {
661*4882a593Smuzhiyun 		/*
662*4882a593Smuzhiyun 		 * Compute a mask of relevant bits.
663*4882a593Smuzhiyun 		 */
664*4882a593Smuzhiyun 		mask = ((xfs_rtword_t)1 << lastbit) - 1;
665*4882a593Smuzhiyun 		/*
666*4882a593Smuzhiyun 		 * Set/clear the active bits.
667*4882a593Smuzhiyun 		 */
668*4882a593Smuzhiyun 		if (val)
669*4882a593Smuzhiyun 			*b |= mask;
670*4882a593Smuzhiyun 		else
671*4882a593Smuzhiyun 			*b &= ~mask;
672*4882a593Smuzhiyun 		b++;
673*4882a593Smuzhiyun 	}
674*4882a593Smuzhiyun 	/*
675*4882a593Smuzhiyun 	 * Log any remaining changed bytes.
676*4882a593Smuzhiyun 	 */
677*4882a593Smuzhiyun 	if (b > first)
678*4882a593Smuzhiyun 		xfs_trans_log_buf(tp, bp, (uint)((char *)first - (char *)bufp),
679*4882a593Smuzhiyun 			(uint)((char *)b - (char *)bufp - 1));
680*4882a593Smuzhiyun 	return 0;
681*4882a593Smuzhiyun }
682*4882a593Smuzhiyun 
683*4882a593Smuzhiyun /*
684*4882a593Smuzhiyun  * Mark an extent specified by start and len freed.
685*4882a593Smuzhiyun  * Updates all the summary information as well as the bitmap.
686*4882a593Smuzhiyun  */
687*4882a593Smuzhiyun int
xfs_rtfree_range(xfs_mount_t * mp,xfs_trans_t * tp,xfs_rtblock_t start,xfs_extlen_t len,xfs_buf_t ** rbpp,xfs_fsblock_t * rsb)688*4882a593Smuzhiyun xfs_rtfree_range(
689*4882a593Smuzhiyun 	xfs_mount_t	*mp,		/* file system mount point */
690*4882a593Smuzhiyun 	xfs_trans_t	*tp,		/* transaction pointer */
691*4882a593Smuzhiyun 	xfs_rtblock_t	start,		/* starting block to free */
692*4882a593Smuzhiyun 	xfs_extlen_t	len,		/* length to free */
693*4882a593Smuzhiyun 	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */
694*4882a593Smuzhiyun 	xfs_fsblock_t	*rsb)		/* in/out: summary block number */
695*4882a593Smuzhiyun {
696*4882a593Smuzhiyun 	xfs_rtblock_t	end;		/* end of the freed extent */
697*4882a593Smuzhiyun 	int		error;		/* error value */
698*4882a593Smuzhiyun 	xfs_rtblock_t	postblock;	/* first block freed > end */
699*4882a593Smuzhiyun 	xfs_rtblock_t	preblock;	/* first block freed < start */
700*4882a593Smuzhiyun 
701*4882a593Smuzhiyun 	end = start + len - 1;
702*4882a593Smuzhiyun 	/*
703*4882a593Smuzhiyun 	 * Modify the bitmap to mark this extent freed.
704*4882a593Smuzhiyun 	 */
705*4882a593Smuzhiyun 	error = xfs_rtmodify_range(mp, tp, start, len, 1);
706*4882a593Smuzhiyun 	if (error) {
707*4882a593Smuzhiyun 		return error;
708*4882a593Smuzhiyun 	}
709*4882a593Smuzhiyun 	/*
710*4882a593Smuzhiyun 	 * Assume we're freeing out of the middle of an allocated extent.
711*4882a593Smuzhiyun 	 * We need to find the beginning and end of the extent so we can
712*4882a593Smuzhiyun 	 * properly update the summary.
713*4882a593Smuzhiyun 	 */
714*4882a593Smuzhiyun 	error = xfs_rtfind_back(mp, tp, start, 0, &preblock);
715*4882a593Smuzhiyun 	if (error) {
716*4882a593Smuzhiyun 		return error;
717*4882a593Smuzhiyun 	}
718*4882a593Smuzhiyun 	/*
719*4882a593Smuzhiyun 	 * Find the next allocated block (end of allocated extent).
720*4882a593Smuzhiyun 	 */
721*4882a593Smuzhiyun 	error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1,
722*4882a593Smuzhiyun 		&postblock);
723*4882a593Smuzhiyun 	if (error)
724*4882a593Smuzhiyun 		return error;
725*4882a593Smuzhiyun 	/*
726*4882a593Smuzhiyun 	 * If there are blocks not being freed at the front of the
727*4882a593Smuzhiyun 	 * old extent, add summary data for them to be allocated.
728*4882a593Smuzhiyun 	 */
729*4882a593Smuzhiyun 	if (preblock < start) {
730*4882a593Smuzhiyun 		error = xfs_rtmodify_summary(mp, tp,
731*4882a593Smuzhiyun 			XFS_RTBLOCKLOG(start - preblock),
732*4882a593Smuzhiyun 			XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb);
733*4882a593Smuzhiyun 		if (error) {
734*4882a593Smuzhiyun 			return error;
735*4882a593Smuzhiyun 		}
736*4882a593Smuzhiyun 	}
737*4882a593Smuzhiyun 	/*
738*4882a593Smuzhiyun 	 * If there are blocks not being freed at the end of the
739*4882a593Smuzhiyun 	 * old extent, add summary data for them to be allocated.
740*4882a593Smuzhiyun 	 */
741*4882a593Smuzhiyun 	if (postblock > end) {
742*4882a593Smuzhiyun 		error = xfs_rtmodify_summary(mp, tp,
743*4882a593Smuzhiyun 			XFS_RTBLOCKLOG(postblock - end),
744*4882a593Smuzhiyun 			XFS_BITTOBLOCK(mp, end + 1), -1, rbpp, rsb);
745*4882a593Smuzhiyun 		if (error) {
746*4882a593Smuzhiyun 			return error;
747*4882a593Smuzhiyun 		}
748*4882a593Smuzhiyun 	}
749*4882a593Smuzhiyun 	/*
750*4882a593Smuzhiyun 	 * Increment the summary information corresponding to the entire
751*4882a593Smuzhiyun 	 * (new) free extent.
752*4882a593Smuzhiyun 	 */
753*4882a593Smuzhiyun 	error = xfs_rtmodify_summary(mp, tp,
754*4882a593Smuzhiyun 		XFS_RTBLOCKLOG(postblock + 1 - preblock),
755*4882a593Smuzhiyun 		XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb);
756*4882a593Smuzhiyun 	return error;
757*4882a593Smuzhiyun }
758*4882a593Smuzhiyun 
759*4882a593Smuzhiyun /*
760*4882a593Smuzhiyun  * Check that the given range is either all allocated (val = 0) or
761*4882a593Smuzhiyun  * all free (val = 1).
762*4882a593Smuzhiyun  */
763*4882a593Smuzhiyun int
xfs_rtcheck_range(xfs_mount_t * mp,xfs_trans_t * tp,xfs_rtblock_t start,xfs_extlen_t len,int val,xfs_rtblock_t * new,int * stat)764*4882a593Smuzhiyun xfs_rtcheck_range(
765*4882a593Smuzhiyun 	xfs_mount_t	*mp,		/* file system mount point */
766*4882a593Smuzhiyun 	xfs_trans_t	*tp,		/* transaction pointer */
767*4882a593Smuzhiyun 	xfs_rtblock_t	start,		/* starting block number of extent */
768*4882a593Smuzhiyun 	xfs_extlen_t	len,		/* length of extent */
769*4882a593Smuzhiyun 	int		val,		/* 1 for free, 0 for allocated */
770*4882a593Smuzhiyun 	xfs_rtblock_t	*new,		/* out: first block not matching */
771*4882a593Smuzhiyun 	int		*stat)		/* out: 1 for matches, 0 for not */
772*4882a593Smuzhiyun {
773*4882a593Smuzhiyun 	xfs_rtword_t	*b;		/* current word in buffer */
774*4882a593Smuzhiyun 	int		bit;		/* bit number in the word */
775*4882a593Smuzhiyun 	xfs_rtblock_t	block;		/* bitmap block number */
776*4882a593Smuzhiyun 	xfs_buf_t	*bp;		/* buf for the block */
777*4882a593Smuzhiyun 	xfs_rtword_t	*bufp;		/* starting word in buffer */
778*4882a593Smuzhiyun 	int		error;		/* error value */
779*4882a593Smuzhiyun 	xfs_rtblock_t	i;		/* current bit number rel. to start */
780*4882a593Smuzhiyun 	xfs_rtblock_t	lastbit;	/* last useful bit in word */
781*4882a593Smuzhiyun 	xfs_rtword_t	mask;		/* mask of relevant bits for value */
782*4882a593Smuzhiyun 	xfs_rtword_t	wdiff;		/* difference from wanted value */
783*4882a593Smuzhiyun 	int		word;		/* word number in the buffer */
784*4882a593Smuzhiyun 
785*4882a593Smuzhiyun 	/*
786*4882a593Smuzhiyun 	 * Compute starting bitmap block number
787*4882a593Smuzhiyun 	 */
788*4882a593Smuzhiyun 	block = XFS_BITTOBLOCK(mp, start);
789*4882a593Smuzhiyun 	/*
790*4882a593Smuzhiyun 	 * Read the bitmap block.
791*4882a593Smuzhiyun 	 */
792*4882a593Smuzhiyun 	error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
793*4882a593Smuzhiyun 	if (error) {
794*4882a593Smuzhiyun 		return error;
795*4882a593Smuzhiyun 	}
796*4882a593Smuzhiyun 	bufp = bp->b_addr;
797*4882a593Smuzhiyun 	/*
798*4882a593Smuzhiyun 	 * Compute the starting word's address, and starting bit.
799*4882a593Smuzhiyun 	 */
800*4882a593Smuzhiyun 	word = XFS_BITTOWORD(mp, start);
801*4882a593Smuzhiyun 	b = &bufp[word];
802*4882a593Smuzhiyun 	bit = (int)(start & (XFS_NBWORD - 1));
803*4882a593Smuzhiyun 	/*
804*4882a593Smuzhiyun 	 * 0 (allocated) => all zero's; 1 (free) => all one's.
805*4882a593Smuzhiyun 	 */
806*4882a593Smuzhiyun 	val = -val;
807*4882a593Smuzhiyun 	/*
808*4882a593Smuzhiyun 	 * If not starting on a word boundary, deal with the first
809*4882a593Smuzhiyun 	 * (partial) word.
810*4882a593Smuzhiyun 	 */
811*4882a593Smuzhiyun 	if (bit) {
812*4882a593Smuzhiyun 		/*
813*4882a593Smuzhiyun 		 * Compute first bit not examined.
814*4882a593Smuzhiyun 		 */
815*4882a593Smuzhiyun 		lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
816*4882a593Smuzhiyun 		/*
817*4882a593Smuzhiyun 		 * Mask of relevant bits.
818*4882a593Smuzhiyun 		 */
819*4882a593Smuzhiyun 		mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
820*4882a593Smuzhiyun 		/*
821*4882a593Smuzhiyun 		 * Compute difference between actual and desired value.
822*4882a593Smuzhiyun 		 */
823*4882a593Smuzhiyun 		if ((wdiff = (*b ^ val) & mask)) {
824*4882a593Smuzhiyun 			/*
825*4882a593Smuzhiyun 			 * Different, compute first wrong bit and return.
826*4882a593Smuzhiyun 			 */
827*4882a593Smuzhiyun 			xfs_trans_brelse(tp, bp);
828*4882a593Smuzhiyun 			i = XFS_RTLOBIT(wdiff) - bit;
829*4882a593Smuzhiyun 			*new = start + i;
830*4882a593Smuzhiyun 			*stat = 0;
831*4882a593Smuzhiyun 			return 0;
832*4882a593Smuzhiyun 		}
833*4882a593Smuzhiyun 		i = lastbit - bit;
834*4882a593Smuzhiyun 		/*
835*4882a593Smuzhiyun 		 * Go on to next block if that's where the next word is
836*4882a593Smuzhiyun 		 * and we need the next word.
837*4882a593Smuzhiyun 		 */
838*4882a593Smuzhiyun 		if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
839*4882a593Smuzhiyun 			/*
840*4882a593Smuzhiyun 			 * If done with this block, get the next one.
841*4882a593Smuzhiyun 			 */
842*4882a593Smuzhiyun 			xfs_trans_brelse(tp, bp);
843*4882a593Smuzhiyun 			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
844*4882a593Smuzhiyun 			if (error) {
845*4882a593Smuzhiyun 				return error;
846*4882a593Smuzhiyun 			}
847*4882a593Smuzhiyun 			b = bufp = bp->b_addr;
848*4882a593Smuzhiyun 			word = 0;
849*4882a593Smuzhiyun 		} else {
850*4882a593Smuzhiyun 			/*
851*4882a593Smuzhiyun 			 * Go on to the next word in the buffer.
852*4882a593Smuzhiyun 			 */
853*4882a593Smuzhiyun 			b++;
854*4882a593Smuzhiyun 		}
855*4882a593Smuzhiyun 	} else {
856*4882a593Smuzhiyun 		/*
857*4882a593Smuzhiyun 		 * Starting on a word boundary, no partial word.
858*4882a593Smuzhiyun 		 */
859*4882a593Smuzhiyun 		i = 0;
860*4882a593Smuzhiyun 	}
861*4882a593Smuzhiyun 	/*
862*4882a593Smuzhiyun 	 * Loop over whole words in buffers.  When we use up one buffer
863*4882a593Smuzhiyun 	 * we move on to the next one.
864*4882a593Smuzhiyun 	 */
865*4882a593Smuzhiyun 	while (len - i >= XFS_NBWORD) {
866*4882a593Smuzhiyun 		/*
867*4882a593Smuzhiyun 		 * Compute difference between actual and desired value.
868*4882a593Smuzhiyun 		 */
869*4882a593Smuzhiyun 		if ((wdiff = *b ^ val)) {
870*4882a593Smuzhiyun 			/*
871*4882a593Smuzhiyun 			 * Different, compute first wrong bit and return.
872*4882a593Smuzhiyun 			 */
873*4882a593Smuzhiyun 			xfs_trans_brelse(tp, bp);
874*4882a593Smuzhiyun 			i += XFS_RTLOBIT(wdiff);
875*4882a593Smuzhiyun 			*new = start + i;
876*4882a593Smuzhiyun 			*stat = 0;
877*4882a593Smuzhiyun 			return 0;
878*4882a593Smuzhiyun 		}
879*4882a593Smuzhiyun 		i += XFS_NBWORD;
880*4882a593Smuzhiyun 		/*
881*4882a593Smuzhiyun 		 * Go on to next block if that's where the next word is
882*4882a593Smuzhiyun 		 * and we need the next word.
883*4882a593Smuzhiyun 		 */
884*4882a593Smuzhiyun 		if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
885*4882a593Smuzhiyun 			/*
886*4882a593Smuzhiyun 			 * If done with this block, get the next one.
887*4882a593Smuzhiyun 			 */
888*4882a593Smuzhiyun 			xfs_trans_brelse(tp, bp);
889*4882a593Smuzhiyun 			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
890*4882a593Smuzhiyun 			if (error) {
891*4882a593Smuzhiyun 				return error;
892*4882a593Smuzhiyun 			}
893*4882a593Smuzhiyun 			b = bufp = bp->b_addr;
894*4882a593Smuzhiyun 			word = 0;
895*4882a593Smuzhiyun 		} else {
896*4882a593Smuzhiyun 			/*
897*4882a593Smuzhiyun 			 * Go on to the next word in the buffer.
898*4882a593Smuzhiyun 			 */
899*4882a593Smuzhiyun 			b++;
900*4882a593Smuzhiyun 		}
901*4882a593Smuzhiyun 	}
902*4882a593Smuzhiyun 	/*
903*4882a593Smuzhiyun 	 * If not ending on a word boundary, deal with the last
904*4882a593Smuzhiyun 	 * (partial) word.
905*4882a593Smuzhiyun 	 */
906*4882a593Smuzhiyun 	if ((lastbit = len - i)) {
907*4882a593Smuzhiyun 		/*
908*4882a593Smuzhiyun 		 * Mask of relevant bits.
909*4882a593Smuzhiyun 		 */
910*4882a593Smuzhiyun 		mask = ((xfs_rtword_t)1 << lastbit) - 1;
911*4882a593Smuzhiyun 		/*
912*4882a593Smuzhiyun 		 * Compute difference between actual and desired value.
913*4882a593Smuzhiyun 		 */
914*4882a593Smuzhiyun 		if ((wdiff = (*b ^ val) & mask)) {
915*4882a593Smuzhiyun 			/*
916*4882a593Smuzhiyun 			 * Different, compute first wrong bit and return.
917*4882a593Smuzhiyun 			 */
918*4882a593Smuzhiyun 			xfs_trans_brelse(tp, bp);
919*4882a593Smuzhiyun 			i += XFS_RTLOBIT(wdiff);
920*4882a593Smuzhiyun 			*new = start + i;
921*4882a593Smuzhiyun 			*stat = 0;
922*4882a593Smuzhiyun 			return 0;
923*4882a593Smuzhiyun 		} else
924*4882a593Smuzhiyun 			i = len;
925*4882a593Smuzhiyun 	}
926*4882a593Smuzhiyun 	/*
927*4882a593Smuzhiyun 	 * Successful, return.
928*4882a593Smuzhiyun 	 */
929*4882a593Smuzhiyun 	xfs_trans_brelse(tp, bp);
930*4882a593Smuzhiyun 	*new = start + i;
931*4882a593Smuzhiyun 	*stat = 1;
932*4882a593Smuzhiyun 	return 0;
933*4882a593Smuzhiyun }
934*4882a593Smuzhiyun 
935*4882a593Smuzhiyun #ifdef DEBUG
936*4882a593Smuzhiyun /*
937*4882a593Smuzhiyun  * Check that the given extent (block range) is allocated already.
938*4882a593Smuzhiyun  */
939*4882a593Smuzhiyun STATIC int				/* error */
xfs_rtcheck_alloc_range(xfs_mount_t * mp,xfs_trans_t * tp,xfs_rtblock_t bno,xfs_extlen_t len)940*4882a593Smuzhiyun xfs_rtcheck_alloc_range(
941*4882a593Smuzhiyun 	xfs_mount_t	*mp,		/* file system mount point */
942*4882a593Smuzhiyun 	xfs_trans_t	*tp,		/* transaction pointer */
943*4882a593Smuzhiyun 	xfs_rtblock_t	bno,		/* starting block number of extent */
944*4882a593Smuzhiyun 	xfs_extlen_t	len)		/* length of extent */
945*4882a593Smuzhiyun {
946*4882a593Smuzhiyun 	xfs_rtblock_t	new;		/* dummy for xfs_rtcheck_range */
947*4882a593Smuzhiyun 	int		stat;
948*4882a593Smuzhiyun 	int		error;
949*4882a593Smuzhiyun 
950*4882a593Smuzhiyun 	error = xfs_rtcheck_range(mp, tp, bno, len, 0, &new, &stat);
951*4882a593Smuzhiyun 	if (error)
952*4882a593Smuzhiyun 		return error;
953*4882a593Smuzhiyun 	ASSERT(stat);
954*4882a593Smuzhiyun 	return 0;
955*4882a593Smuzhiyun }
956*4882a593Smuzhiyun #else
957*4882a593Smuzhiyun #define xfs_rtcheck_alloc_range(m,t,b,l)	(0)
958*4882a593Smuzhiyun #endif
959*4882a593Smuzhiyun /*
960*4882a593Smuzhiyun  * Free an extent in the realtime subvolume.  Length is expressed in
961*4882a593Smuzhiyun  * realtime extents, as is the block number.
962*4882a593Smuzhiyun  */
963*4882a593Smuzhiyun int					/* error */
xfs_rtfree_extent(xfs_trans_t * tp,xfs_rtblock_t bno,xfs_extlen_t len)964*4882a593Smuzhiyun xfs_rtfree_extent(
965*4882a593Smuzhiyun 	xfs_trans_t	*tp,		/* transaction pointer */
966*4882a593Smuzhiyun 	xfs_rtblock_t	bno,		/* starting block number to free */
967*4882a593Smuzhiyun 	xfs_extlen_t	len)		/* length of extent freed */
968*4882a593Smuzhiyun {
969*4882a593Smuzhiyun 	int		error;		/* error value */
970*4882a593Smuzhiyun 	xfs_mount_t	*mp;		/* file system mount structure */
971*4882a593Smuzhiyun 	xfs_fsblock_t	sb;		/* summary file block number */
972*4882a593Smuzhiyun 	xfs_buf_t	*sumbp = NULL;	/* summary file block buffer */
973*4882a593Smuzhiyun 
974*4882a593Smuzhiyun 	mp = tp->t_mountp;
975*4882a593Smuzhiyun 
976*4882a593Smuzhiyun 	ASSERT(mp->m_rbmip->i_itemp != NULL);
977*4882a593Smuzhiyun 	ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
978*4882a593Smuzhiyun 
979*4882a593Smuzhiyun 	error = xfs_rtcheck_alloc_range(mp, tp, bno, len);
980*4882a593Smuzhiyun 	if (error)
981*4882a593Smuzhiyun 		return error;
982*4882a593Smuzhiyun 
983*4882a593Smuzhiyun 	/*
984*4882a593Smuzhiyun 	 * Free the range of realtime blocks.
985*4882a593Smuzhiyun 	 */
986*4882a593Smuzhiyun 	error = xfs_rtfree_range(mp, tp, bno, len, &sumbp, &sb);
987*4882a593Smuzhiyun 	if (error) {
988*4882a593Smuzhiyun 		return error;
989*4882a593Smuzhiyun 	}
990*4882a593Smuzhiyun 	/*
991*4882a593Smuzhiyun 	 * Mark more blocks free in the superblock.
992*4882a593Smuzhiyun 	 */
993*4882a593Smuzhiyun 	xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS, (long)len);
994*4882a593Smuzhiyun 	/*
995*4882a593Smuzhiyun 	 * If we've now freed all the blocks, reset the file sequence
996*4882a593Smuzhiyun 	 * number to 0.
997*4882a593Smuzhiyun 	 */
998*4882a593Smuzhiyun 	if (tp->t_frextents_delta + mp->m_sb.sb_frextents ==
999*4882a593Smuzhiyun 	    mp->m_sb.sb_rextents) {
1000*4882a593Smuzhiyun 		if (!(mp->m_rbmip->i_d.di_flags & XFS_DIFLAG_NEWRTBM))
1001*4882a593Smuzhiyun 			mp->m_rbmip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM;
1002*4882a593Smuzhiyun 		*(uint64_t *)&VFS_I(mp->m_rbmip)->i_atime = 0;
1003*4882a593Smuzhiyun 		xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);
1004*4882a593Smuzhiyun 	}
1005*4882a593Smuzhiyun 	return 0;
1006*4882a593Smuzhiyun }
1007*4882a593Smuzhiyun 
1008*4882a593Smuzhiyun /* Find all the free records within a given range. */
1009*4882a593Smuzhiyun int
xfs_rtalloc_query_range(struct xfs_trans * tp,struct xfs_rtalloc_rec * low_rec,struct xfs_rtalloc_rec * high_rec,xfs_rtalloc_query_range_fn fn,void * priv)1010*4882a593Smuzhiyun xfs_rtalloc_query_range(
1011*4882a593Smuzhiyun 	struct xfs_trans		*tp,
1012*4882a593Smuzhiyun 	struct xfs_rtalloc_rec		*low_rec,
1013*4882a593Smuzhiyun 	struct xfs_rtalloc_rec		*high_rec,
1014*4882a593Smuzhiyun 	xfs_rtalloc_query_range_fn	fn,
1015*4882a593Smuzhiyun 	void				*priv)
1016*4882a593Smuzhiyun {
1017*4882a593Smuzhiyun 	struct xfs_rtalloc_rec		rec;
1018*4882a593Smuzhiyun 	struct xfs_mount		*mp = tp->t_mountp;
1019*4882a593Smuzhiyun 	xfs_rtblock_t			rtstart;
1020*4882a593Smuzhiyun 	xfs_rtblock_t			rtend;
1021*4882a593Smuzhiyun 	int				is_free;
1022*4882a593Smuzhiyun 	int				error = 0;
1023*4882a593Smuzhiyun 
1024*4882a593Smuzhiyun 	if (low_rec->ar_startext > high_rec->ar_startext)
1025*4882a593Smuzhiyun 		return -EINVAL;
1026*4882a593Smuzhiyun 	if (low_rec->ar_startext >= mp->m_sb.sb_rextents ||
1027*4882a593Smuzhiyun 	    low_rec->ar_startext == high_rec->ar_startext)
1028*4882a593Smuzhiyun 		return 0;
1029*4882a593Smuzhiyun 	high_rec->ar_startext = min(high_rec->ar_startext,
1030*4882a593Smuzhiyun 			mp->m_sb.sb_rextents - 1);
1031*4882a593Smuzhiyun 
1032*4882a593Smuzhiyun 	/* Iterate the bitmap, looking for discrepancies. */
1033*4882a593Smuzhiyun 	rtstart = low_rec->ar_startext;
1034*4882a593Smuzhiyun 	while (rtstart <= high_rec->ar_startext) {
1035*4882a593Smuzhiyun 		/* Is the first block free? */
1036*4882a593Smuzhiyun 		error = xfs_rtcheck_range(mp, tp, rtstart, 1, 1, &rtend,
1037*4882a593Smuzhiyun 				&is_free);
1038*4882a593Smuzhiyun 		if (error)
1039*4882a593Smuzhiyun 			break;
1040*4882a593Smuzhiyun 
1041*4882a593Smuzhiyun 		/* How long does the extent go for? */
1042*4882a593Smuzhiyun 		error = xfs_rtfind_forw(mp, tp, rtstart,
1043*4882a593Smuzhiyun 				high_rec->ar_startext, &rtend);
1044*4882a593Smuzhiyun 		if (error)
1045*4882a593Smuzhiyun 			break;
1046*4882a593Smuzhiyun 
1047*4882a593Smuzhiyun 		if (is_free) {
1048*4882a593Smuzhiyun 			rec.ar_startext = rtstart;
1049*4882a593Smuzhiyun 			rec.ar_extcount = rtend - rtstart + 1;
1050*4882a593Smuzhiyun 
1051*4882a593Smuzhiyun 			error = fn(tp, &rec, priv);
1052*4882a593Smuzhiyun 			if (error)
1053*4882a593Smuzhiyun 				break;
1054*4882a593Smuzhiyun 		}
1055*4882a593Smuzhiyun 
1056*4882a593Smuzhiyun 		rtstart = rtend + 1;
1057*4882a593Smuzhiyun 	}
1058*4882a593Smuzhiyun 
1059*4882a593Smuzhiyun 	return error;
1060*4882a593Smuzhiyun }
1061*4882a593Smuzhiyun 
1062*4882a593Smuzhiyun /* Find all the free records. */
1063*4882a593Smuzhiyun int
xfs_rtalloc_query_all(struct xfs_trans * tp,xfs_rtalloc_query_range_fn fn,void * priv)1064*4882a593Smuzhiyun xfs_rtalloc_query_all(
1065*4882a593Smuzhiyun 	struct xfs_trans		*tp,
1066*4882a593Smuzhiyun 	xfs_rtalloc_query_range_fn	fn,
1067*4882a593Smuzhiyun 	void				*priv)
1068*4882a593Smuzhiyun {
1069*4882a593Smuzhiyun 	struct xfs_rtalloc_rec		keys[2];
1070*4882a593Smuzhiyun 
1071*4882a593Smuzhiyun 	keys[0].ar_startext = 0;
1072*4882a593Smuzhiyun 	keys[1].ar_startext = tp->t_mountp->m_sb.sb_rextents - 1;
1073*4882a593Smuzhiyun 	keys[0].ar_extcount = keys[1].ar_extcount = 0;
1074*4882a593Smuzhiyun 
1075*4882a593Smuzhiyun 	return xfs_rtalloc_query_range(tp, &keys[0], &keys[1], fn, priv);
1076*4882a593Smuzhiyun }
1077*4882a593Smuzhiyun 
1078*4882a593Smuzhiyun /* Is the given extent all free? */
1079*4882a593Smuzhiyun int
xfs_rtalloc_extent_is_free(struct xfs_mount * mp,struct xfs_trans * tp,xfs_rtblock_t start,xfs_extlen_t len,bool * is_free)1080*4882a593Smuzhiyun xfs_rtalloc_extent_is_free(
1081*4882a593Smuzhiyun 	struct xfs_mount		*mp,
1082*4882a593Smuzhiyun 	struct xfs_trans		*tp,
1083*4882a593Smuzhiyun 	xfs_rtblock_t			start,
1084*4882a593Smuzhiyun 	xfs_extlen_t			len,
1085*4882a593Smuzhiyun 	bool				*is_free)
1086*4882a593Smuzhiyun {
1087*4882a593Smuzhiyun 	xfs_rtblock_t			end;
1088*4882a593Smuzhiyun 	int				matches;
1089*4882a593Smuzhiyun 	int				error;
1090*4882a593Smuzhiyun 
1091*4882a593Smuzhiyun 	error = xfs_rtcheck_range(mp, tp, start, len, 1, &end, &matches);
1092*4882a593Smuzhiyun 	if (error)
1093*4882a593Smuzhiyun 		return error;
1094*4882a593Smuzhiyun 
1095*4882a593Smuzhiyun 	*is_free = matches;
1096*4882a593Smuzhiyun 	return 0;
1097*4882a593Smuzhiyun }
1098