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