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