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