xref: /openbmc/linux/fs/xfs/libxfs/xfs_rtbitmap.c (revision 3932b9ca)
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 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 int
433 xfs_rtmodify_summary(
434 	xfs_mount_t	*mp,		/* file system mount point */
435 	xfs_trans_t	*tp,		/* transaction pointer */
436 	int		log,		/* log2 of extent size */
437 	xfs_rtblock_t	bbno,		/* bitmap block number */
438 	int		delta,		/* change to make to summary info */
439 	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */
440 	xfs_fsblock_t	*rsb)		/* in/out: summary block number */
441 {
442 	xfs_buf_t	*bp;		/* buffer for the summary block */
443 	int		error;		/* error value */
444 	xfs_fsblock_t	sb;		/* summary fsblock */
445 	int		so;		/* index into the summary file */
446 	xfs_suminfo_t	*sp;		/* pointer to returned data */
447 
448 	/*
449 	 * Compute entry number in the summary file.
450 	 */
451 	so = XFS_SUMOFFS(mp, log, bbno);
452 	/*
453 	 * Compute the block number in the summary file.
454 	 */
455 	sb = XFS_SUMOFFSTOBLOCK(mp, so);
456 	/*
457 	 * If we have an old buffer, and the block number matches, use that.
458 	 */
459 	if (rbpp && *rbpp && *rsb == sb)
460 		bp = *rbpp;
461 	/*
462 	 * Otherwise we have to get the buffer.
463 	 */
464 	else {
465 		/*
466 		 * If there was an old one, get rid of it first.
467 		 */
468 		if (rbpp && *rbpp)
469 			xfs_trans_brelse(tp, *rbpp);
470 		error = xfs_rtbuf_get(mp, tp, sb, 1, &bp);
471 		if (error) {
472 			return error;
473 		}
474 		/*
475 		 * Remember this buffer and block for the next call.
476 		 */
477 		if (rbpp) {
478 			*rbpp = bp;
479 			*rsb = sb;
480 		}
481 	}
482 	/*
483 	 * Point to the summary information, modify and log it.
484 	 */
485 	sp = XFS_SUMPTR(mp, bp, so);
486 	*sp += delta;
487 	xfs_trans_log_buf(tp, bp, (uint)((char *)sp - (char *)bp->b_addr),
488 		(uint)((char *)sp - (char *)bp->b_addr + sizeof(*sp) - 1));
489 	return 0;
490 }
491 
492 /*
493  * Set the given range of bitmap bits to the given value.
494  * Do whatever I/O and logging is required.
495  */
496 int
497 xfs_rtmodify_range(
498 	xfs_mount_t	*mp,		/* file system mount point */
499 	xfs_trans_t	*tp,		/* transaction pointer */
500 	xfs_rtblock_t	start,		/* starting block to modify */
501 	xfs_extlen_t	len,		/* length of extent to modify */
502 	int		val)		/* 1 for free, 0 for allocated */
503 {
504 	xfs_rtword_t	*b;		/* current word in buffer */
505 	int		bit;		/* bit number in the word */
506 	xfs_rtblock_t	block;		/* bitmap block number */
507 	xfs_buf_t	*bp;		/* buf for the block */
508 	xfs_rtword_t	*bufp;		/* starting word in buffer */
509 	int		error;		/* error value */
510 	xfs_rtword_t	*first;		/* first used word in the buffer */
511 	int		i;		/* current bit number rel. to start */
512 	int		lastbit;	/* last useful bit in word */
513 	xfs_rtword_t	mask;		/* mask o frelevant bits for value */
514 	int		word;		/* word number in the buffer */
515 
516 	/*
517 	 * Compute starting bitmap block number.
518 	 */
519 	block = XFS_BITTOBLOCK(mp, start);
520 	/*
521 	 * Read the bitmap block, and point to its data.
522 	 */
523 	error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
524 	if (error) {
525 		return error;
526 	}
527 	bufp = bp->b_addr;
528 	/*
529 	 * Compute the starting word's address, and starting bit.
530 	 */
531 	word = XFS_BITTOWORD(mp, start);
532 	first = b = &bufp[word];
533 	bit = (int)(start & (XFS_NBWORD - 1));
534 	/*
535 	 * 0 (allocated) => all zeroes; 1 (free) => all ones.
536 	 */
537 	val = -val;
538 	/*
539 	 * If not starting on a word boundary, deal with the first
540 	 * (partial) word.
541 	 */
542 	if (bit) {
543 		/*
544 		 * Compute first bit not changed and mask of relevant bits.
545 		 */
546 		lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
547 		mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
548 		/*
549 		 * Set/clear the active bits.
550 		 */
551 		if (val)
552 			*b |= mask;
553 		else
554 			*b &= ~mask;
555 		i = lastbit - bit;
556 		/*
557 		 * Go on to the next block if that's where the next word is
558 		 * and we need the next word.
559 		 */
560 		if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
561 			/*
562 			 * Log the changed part of this block.
563 			 * Get the next one.
564 			 */
565 			xfs_trans_log_buf(tp, bp,
566 				(uint)((char *)first - (char *)bufp),
567 				(uint)((char *)b - (char *)bufp));
568 			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
569 			if (error) {
570 				return error;
571 			}
572 			first = b = bufp = bp->b_addr;
573 			word = 0;
574 		} else {
575 			/*
576 			 * Go on to the next word in the buffer
577 			 */
578 			b++;
579 		}
580 	} else {
581 		/*
582 		 * Starting on a word boundary, no partial word.
583 		 */
584 		i = 0;
585 	}
586 	/*
587 	 * Loop over whole words in buffers.  When we use up one buffer
588 	 * we move on to the next one.
589 	 */
590 	while (len - i >= XFS_NBWORD) {
591 		/*
592 		 * Set the word value correctly.
593 		 */
594 		*b = val;
595 		i += XFS_NBWORD;
596 		/*
597 		 * Go on to the next block if that's where the next word is
598 		 * and we need the next word.
599 		 */
600 		if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
601 			/*
602 			 * Log the changed part of this block.
603 			 * Get the next one.
604 			 */
605 			xfs_trans_log_buf(tp, bp,
606 				(uint)((char *)first - (char *)bufp),
607 				(uint)((char *)b - (char *)bufp));
608 			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
609 			if (error) {
610 				return error;
611 			}
612 			first = b = bufp = bp->b_addr;
613 			word = 0;
614 		} else {
615 			/*
616 			 * Go on to the next word in the buffer
617 			 */
618 			b++;
619 		}
620 	}
621 	/*
622 	 * If not ending on a word boundary, deal with the last
623 	 * (partial) word.
624 	 */
625 	if ((lastbit = len - i)) {
626 		/*
627 		 * Compute a mask of relevant bits.
628 		 */
629 		bit = 0;
630 		mask = ((xfs_rtword_t)1 << lastbit) - 1;
631 		/*
632 		 * Set/clear the active bits.
633 		 */
634 		if (val)
635 			*b |= mask;
636 		else
637 			*b &= ~mask;
638 		b++;
639 	}
640 	/*
641 	 * Log any remaining changed bytes.
642 	 */
643 	if (b > first)
644 		xfs_trans_log_buf(tp, bp, (uint)((char *)first - (char *)bufp),
645 			(uint)((char *)b - (char *)bufp - 1));
646 	return 0;
647 }
648 
649 /*
650  * Mark an extent specified by start and len freed.
651  * Updates all the summary information as well as the bitmap.
652  */
653 int
654 xfs_rtfree_range(
655 	xfs_mount_t	*mp,		/* file system mount point */
656 	xfs_trans_t	*tp,		/* transaction pointer */
657 	xfs_rtblock_t	start,		/* starting block to free */
658 	xfs_extlen_t	len,		/* length to free */
659 	xfs_buf_t	**rbpp,		/* in/out: summary block buffer */
660 	xfs_fsblock_t	*rsb)		/* in/out: summary block number */
661 {
662 	xfs_rtblock_t	end;		/* end of the freed extent */
663 	int		error;		/* error value */
664 	xfs_rtblock_t	postblock;	/* first block freed > end */
665 	xfs_rtblock_t	preblock;	/* first block freed < start */
666 
667 	end = start + len - 1;
668 	/*
669 	 * Modify the bitmap to mark this extent freed.
670 	 */
671 	error = xfs_rtmodify_range(mp, tp, start, len, 1);
672 	if (error) {
673 		return error;
674 	}
675 	/*
676 	 * Assume we're freeing out of the middle of an allocated extent.
677 	 * We need to find the beginning and end of the extent so we can
678 	 * properly update the summary.
679 	 */
680 	error = xfs_rtfind_back(mp, tp, start, 0, &preblock);
681 	if (error) {
682 		return error;
683 	}
684 	/*
685 	 * Find the next allocated block (end of allocated extent).
686 	 */
687 	error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1,
688 		&postblock);
689 	if (error)
690 		return error;
691 	/*
692 	 * If there are blocks not being freed at the front of the
693 	 * old extent, add summary data for them to be allocated.
694 	 */
695 	if (preblock < start) {
696 		error = xfs_rtmodify_summary(mp, tp,
697 			XFS_RTBLOCKLOG(start - preblock),
698 			XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb);
699 		if (error) {
700 			return error;
701 		}
702 	}
703 	/*
704 	 * If there are blocks not being freed at the end of the
705 	 * old extent, add summary data for them to be allocated.
706 	 */
707 	if (postblock > end) {
708 		error = xfs_rtmodify_summary(mp, tp,
709 			XFS_RTBLOCKLOG(postblock - end),
710 			XFS_BITTOBLOCK(mp, end + 1), -1, rbpp, rsb);
711 		if (error) {
712 			return error;
713 		}
714 	}
715 	/*
716 	 * Increment the summary information corresponding to the entire
717 	 * (new) free extent.
718 	 */
719 	error = xfs_rtmodify_summary(mp, tp,
720 		XFS_RTBLOCKLOG(postblock + 1 - preblock),
721 		XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb);
722 	return error;
723 }
724 
725 /*
726  * Check that the given range is either all allocated (val = 0) or
727  * all free (val = 1).
728  */
729 int
730 xfs_rtcheck_range(
731 	xfs_mount_t	*mp,		/* file system mount point */
732 	xfs_trans_t	*tp,		/* transaction pointer */
733 	xfs_rtblock_t	start,		/* starting block number of extent */
734 	xfs_extlen_t	len,		/* length of extent */
735 	int		val,		/* 1 for free, 0 for allocated */
736 	xfs_rtblock_t	*new,		/* out: first block not matching */
737 	int		*stat)		/* out: 1 for matches, 0 for not */
738 {
739 	xfs_rtword_t	*b;		/* current word in buffer */
740 	int		bit;		/* bit number in the word */
741 	xfs_rtblock_t	block;		/* bitmap block number */
742 	xfs_buf_t	*bp;		/* buf for the block */
743 	xfs_rtword_t	*bufp;		/* starting word in buffer */
744 	int		error;		/* error value */
745 	xfs_rtblock_t	i;		/* current bit number rel. to start */
746 	xfs_rtblock_t	lastbit;	/* last useful bit in word */
747 	xfs_rtword_t	mask;		/* mask of relevant bits for value */
748 	xfs_rtword_t	wdiff;		/* difference from wanted value */
749 	int		word;		/* word number in the buffer */
750 
751 	/*
752 	 * Compute starting bitmap block number
753 	 */
754 	block = XFS_BITTOBLOCK(mp, start);
755 	/*
756 	 * Read the bitmap block.
757 	 */
758 	error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
759 	if (error) {
760 		return error;
761 	}
762 	bufp = bp->b_addr;
763 	/*
764 	 * Compute the starting word's address, and starting bit.
765 	 */
766 	word = XFS_BITTOWORD(mp, start);
767 	b = &bufp[word];
768 	bit = (int)(start & (XFS_NBWORD - 1));
769 	/*
770 	 * 0 (allocated) => all zero's; 1 (free) => all one's.
771 	 */
772 	val = -val;
773 	/*
774 	 * If not starting on a word boundary, deal with the first
775 	 * (partial) word.
776 	 */
777 	if (bit) {
778 		/*
779 		 * Compute first bit not examined.
780 		 */
781 		lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
782 		/*
783 		 * Mask of relevant bits.
784 		 */
785 		mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
786 		/*
787 		 * Compute difference between actual and desired value.
788 		 */
789 		if ((wdiff = (*b ^ val) & mask)) {
790 			/*
791 			 * Different, compute first wrong bit and return.
792 			 */
793 			xfs_trans_brelse(tp, bp);
794 			i = XFS_RTLOBIT(wdiff) - bit;
795 			*new = start + i;
796 			*stat = 0;
797 			return 0;
798 		}
799 		i = lastbit - bit;
800 		/*
801 		 * Go on to next block if that's where the next word is
802 		 * and we need the next word.
803 		 */
804 		if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
805 			/*
806 			 * If done with this block, get the next one.
807 			 */
808 			xfs_trans_brelse(tp, bp);
809 			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
810 			if (error) {
811 				return error;
812 			}
813 			b = bufp = bp->b_addr;
814 			word = 0;
815 		} else {
816 			/*
817 			 * Go on to the next word in the buffer.
818 			 */
819 			b++;
820 		}
821 	} else {
822 		/*
823 		 * Starting on a word boundary, no partial word.
824 		 */
825 		i = 0;
826 	}
827 	/*
828 	 * Loop over whole words in buffers.  When we use up one buffer
829 	 * we move on to the next one.
830 	 */
831 	while (len - i >= XFS_NBWORD) {
832 		/*
833 		 * Compute difference between actual and desired value.
834 		 */
835 		if ((wdiff = *b ^ val)) {
836 			/*
837 			 * Different, compute first wrong bit and return.
838 			 */
839 			xfs_trans_brelse(tp, bp);
840 			i += XFS_RTLOBIT(wdiff);
841 			*new = start + i;
842 			*stat = 0;
843 			return 0;
844 		}
845 		i += XFS_NBWORD;
846 		/*
847 		 * Go on to next block if that's where the next word is
848 		 * and we need the next word.
849 		 */
850 		if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
851 			/*
852 			 * If done with this block, get the next one.
853 			 */
854 			xfs_trans_brelse(tp, bp);
855 			error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
856 			if (error) {
857 				return error;
858 			}
859 			b = bufp = bp->b_addr;
860 			word = 0;
861 		} else {
862 			/*
863 			 * Go on to the next word in the buffer.
864 			 */
865 			b++;
866 		}
867 	}
868 	/*
869 	 * If not ending on a word boundary, deal with the last
870 	 * (partial) word.
871 	 */
872 	if ((lastbit = len - i)) {
873 		/*
874 		 * Mask of relevant bits.
875 		 */
876 		mask = ((xfs_rtword_t)1 << lastbit) - 1;
877 		/*
878 		 * Compute difference between actual and desired value.
879 		 */
880 		if ((wdiff = (*b ^ val) & mask)) {
881 			/*
882 			 * Different, compute first wrong bit and return.
883 			 */
884 			xfs_trans_brelse(tp, bp);
885 			i += XFS_RTLOBIT(wdiff);
886 			*new = start + i;
887 			*stat = 0;
888 			return 0;
889 		} else
890 			i = len;
891 	}
892 	/*
893 	 * Successful, return.
894 	 */
895 	xfs_trans_brelse(tp, bp);
896 	*new = start + i;
897 	*stat = 1;
898 	return 0;
899 }
900 
901 #ifdef DEBUG
902 /*
903  * Check that the given extent (block range) is allocated already.
904  */
905 STATIC int				/* error */
906 xfs_rtcheck_alloc_range(
907 	xfs_mount_t	*mp,		/* file system mount point */
908 	xfs_trans_t	*tp,		/* transaction pointer */
909 	xfs_rtblock_t	bno,		/* starting block number of extent */
910 	xfs_extlen_t	len)		/* length of extent */
911 {
912 	xfs_rtblock_t	new;		/* dummy for xfs_rtcheck_range */
913 	int		stat;
914 	int		error;
915 
916 	error = xfs_rtcheck_range(mp, tp, bno, len, 0, &new, &stat);
917 	if (error)
918 		return error;
919 	ASSERT(stat);
920 	return 0;
921 }
922 #else
923 #define xfs_rtcheck_alloc_range(m,t,b,l)	(0)
924 #endif
925 /*
926  * Free an extent in the realtime subvolume.  Length is expressed in
927  * realtime extents, as is the block number.
928  */
929 int					/* error */
930 xfs_rtfree_extent(
931 	xfs_trans_t	*tp,		/* transaction pointer */
932 	xfs_rtblock_t	bno,		/* starting block number to free */
933 	xfs_extlen_t	len)		/* length of extent freed */
934 {
935 	int		error;		/* error value */
936 	xfs_mount_t	*mp;		/* file system mount structure */
937 	xfs_fsblock_t	sb;		/* summary file block number */
938 	xfs_buf_t	*sumbp = NULL;	/* summary file block buffer */
939 
940 	mp = tp->t_mountp;
941 
942 	ASSERT(mp->m_rbmip->i_itemp != NULL);
943 	ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
944 
945 	error = xfs_rtcheck_alloc_range(mp, tp, bno, len);
946 	if (error)
947 		return error;
948 
949 	/*
950 	 * Free the range of realtime blocks.
951 	 */
952 	error = xfs_rtfree_range(mp, tp, bno, len, &sumbp, &sb);
953 	if (error) {
954 		return error;
955 	}
956 	/*
957 	 * Mark more blocks free in the superblock.
958 	 */
959 	xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS, (long)len);
960 	/*
961 	 * If we've now freed all the blocks, reset the file sequence
962 	 * number to 0.
963 	 */
964 	if (tp->t_frextents_delta + mp->m_sb.sb_frextents ==
965 	    mp->m_sb.sb_rextents) {
966 		if (!(mp->m_rbmip->i_d.di_flags & XFS_DIFLAG_NEWRTBM))
967 			mp->m_rbmip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM;
968 		*(__uint64_t *)&mp->m_rbmip->i_d.di_atime = 0;
969 		xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);
970 	}
971 	return 0;
972 }
973 
974