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