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