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