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