]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - libxfs/xfs_rtalloc.c
Merge whitespace changes over
[thirdparty/xfsprogs-dev.git] / libxfs / xfs_rtalloc.c
CommitLineData
2bd0ea18 1/*
0d3e0b37 2 * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
5000d01d 3 *
2bd0ea18
NS
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
5000d01d 7 *
2bd0ea18
NS
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5000d01d 11 *
2bd0ea18
NS
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
dfc130f3 14 * or the like. Any license provided herein, whether implied or
2bd0ea18
NS
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
5000d01d 18 *
2bd0ea18
NS
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
5000d01d 22 *
2bd0ea18
NS
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
5000d01d
SL
25 *
26 * http://www.sgi.com
27 *
28 * For further information regarding this notice, see:
29 *
2bd0ea18
NS
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
31 */
32
33/*
34 * Free realtime space allocation for XFS.
35 */
dfc130f3 36
2bd0ea18
NS
37#include <xfs.h>
38
e49e365f 39extern int xfs_lowbit32(__uint32_t);
2bd0ea18
NS
40
41/*
42 * Get a buffer for the bitmap or summary file block specified.
43 * The buffer is returned read and locked.
44 */
45STATIC int /* error */
46xfs_rtbuf_get(
47 xfs_mount_t *mp, /* file system mount structure */
48 xfs_trans_t *tp, /* transaction pointer */
49 xfs_rtblock_t block, /* block number in bitmap or summary */
50 int issum, /* is summary not bitmap */
e49e365f 51 xfs_buf_t **bpp) /* output: buffer for the block */
2bd0ea18 52{
e49e365f
NS
53 xfs_buf_t *bp; /* block buffer, result */
54 xfs_daddr_t d; /* disk addr of block */
2bd0ea18
NS
55 int error; /* error value */
56 xfs_fsblock_t fsb; /* fs block number for block */
57 xfs_inode_t *ip; /* bitmap or summary inode */
58
59 ip = issum ? mp->m_rsumip : mp->m_rbmip;
60 /*
61 * Map from the file offset (block) and inode number to the
62 * file system block.
63 */
64 error = xfs_bmapi_single(tp, ip, XFS_DATA_FORK, &fsb, block);
65 if (error) {
66 return error;
67 }
68 ASSERT(fsb != NULLFSBLOCK);
69 /*
70 * Convert to disk address for buffer cache.
71 */
72 d = XFS_FSB_TO_DADDR(mp, fsb);
73 /*
74 * Read the buffer.
75 */
76 error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, d,
77 mp->m_bsize, 0, &bp);
78 if (error) {
79 return error;
80 }
81 ASSERT(bp && !XFS_BUF_GETERROR(bp));
82 *bpp = bp;
83 return 0;
84}
85
86/*
87 * Searching backward from start to limit, find the first block whose
88 * allocated/free state is different from start's.
89 */
90STATIC int /* error */
91xfs_rtfind_back(
92 xfs_mount_t *mp, /* file system mount point */
93 xfs_trans_t *tp, /* transaction pointer */
94 xfs_rtblock_t start, /* starting block to look at */
95 xfs_rtblock_t limit, /* last block to look at */
96 xfs_rtblock_t *rtblock) /* out: start block found */
97{
98 xfs_rtword_t *b; /* current word in buffer */
99 int bit; /* bit number in the word */
100 xfs_rtblock_t block; /* bitmap block number */
e49e365f 101 xfs_buf_t *bp; /* buf for the block */
2bd0ea18
NS
102 xfs_rtword_t *bufp; /* starting word in buffer */
103 int error; /* error value */
104 xfs_rtblock_t firstbit; /* first useful bit in the word */
105 xfs_rtblock_t i; /* current bit number rel. to start */
106 xfs_rtblock_t len; /* length of inspected area */
107 xfs_rtword_t mask; /* mask of relevant bits for value */
108 xfs_rtword_t want; /* mask for "good" values */
109 xfs_rtword_t wdiff; /* difference from wanted value */
110 int word; /* word number in the buffer */
111
112 /*
113 * Compute and read in starting bitmap block for starting block.
114 */
115 block = XFS_BITTOBLOCK(mp, start);
116 error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
117 if (error) {
118 return error;
119 }
120 bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
121 /*
122 * Get the first word's index & point to it.
123 */
124 word = XFS_BITTOWORD(mp, start);
125 b = &bufp[word];
126 bit = (int)(start & (XFS_NBWORD - 1));
127 len = start - limit + 1;
128 /*
129 * Compute match value, based on the bit at start: if 1 (free)
130 * then all-ones, else all-zeroes.
131 */
132 want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
133 /*
134 * If the starting position is not word-aligned, deal with the
135 * partial word.
136 */
137 if (bit < XFS_NBWORD - 1) {
138 /*
139 * Calculate first (leftmost) bit number to look at,
140 * and mask for all the relevant bits in this word.
141 */
142 firstbit = XFS_RTMAX((xfs_srtblock_t)(bit - len + 1), 0);
143 mask = (((xfs_rtword_t)1 << (bit - firstbit + 1)) - 1) <<
144 firstbit;
145 /*
146 * Calculate the difference between the value there
147 * and what we're looking for.
148 */
0e266570 149 if ((wdiff = (*b ^ want) & mask)) {
2bd0ea18
NS
150 /*
151 * Different. Mark where we are and return.
152 */
153 xfs_trans_brelse(tp, bp);
154 i = bit - XFS_RTHIBIT(wdiff);
155 *rtblock = start - i + 1;
156 return 0;
157 }
158 i = bit - firstbit + 1;
159 /*
160 * Go on to previous block if that's where the previous word is
161 * and we need the previous word.
162 */
163 if (--word == -1 && i < len) {
164 /*
165 * If done with this block, get the previous one.
166 */
167 xfs_trans_brelse(tp, bp);
168 error = xfs_rtbuf_get(mp, tp, --block, 0, &bp);
169 if (error) {
170 return error;
171 }
172 bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
173 word = XFS_BLOCKWMASK(mp);
174 b = &bufp[word];
175 } else {
176 /*
177 * Go on to the previous word in the buffer.
178 */
179 b--;
180 }
181 } else {
182 /*
183 * Starting on a word boundary, no partial word.
184 */
185 i = 0;
186 }
187 /*
188 * Loop over whole words in buffers. When we use up one buffer
189 * we move on to the previous one.
190 */
191 while (len - i >= XFS_NBWORD) {
192 /*
193 * Compute difference between actual and desired value.
194 */
0e266570 195 if ((wdiff = *b ^ want)) {
2bd0ea18
NS
196 /*
197 * Different, mark where we are and return.
198 */
199 xfs_trans_brelse(tp, bp);
200 i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
201 *rtblock = start - i + 1;
202 return 0;
203 }
204 i += XFS_NBWORD;
205 /*
206 * Go on to previous block if that's where the previous word is
207 * and we need the previous word.
208 */
209 if (--word == -1 && i < len) {
210 /*
211 * If done with this block, get the previous one.
212 */
213 xfs_trans_brelse(tp, bp);
214 error = xfs_rtbuf_get(mp, tp, --block, 0, &bp);
215 if (error) {
216 return error;
217 }
218 bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
219 word = XFS_BLOCKWMASK(mp);
220 b = &bufp[word];
221 } else {
222 /*
223 * Go on to the previous word in the buffer.
224 */
225 b--;
226 }
227 }
228 /*
229 * If not ending on a word boundary, deal with the last
230 * (partial) word.
231 */
232 if (len - i) {
233 /*
234 * Calculate first (leftmost) bit number to look at,
235 * and mask for all the relevant bits in this word.
236 */
237 firstbit = XFS_NBWORD - (len - i);
238 mask = (((xfs_rtword_t)1 << (len - i)) - 1) << firstbit;
239 /*
240 * Compute difference between actual and desired value.
241 */
0e266570 242 if ((wdiff = (*b ^ want) & mask)) {
2bd0ea18
NS
243 /*
244 * Different, mark where we are and return.
245 */
246 xfs_trans_brelse(tp, bp);
247 i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
248 *rtblock = start - i + 1;
249 return 0;
250 } else
251 i = len;
252 }
253 /*
254 * No match, return that we scanned the whole area.
255 */
256 xfs_trans_brelse(tp, bp);
257 *rtblock = start - i + 1;
258 return 0;
259}
260
261/*
262 * Searching forward from start to limit, find the first block whose
263 * allocated/free state is different from start's.
264 */
265STATIC int /* error */
266xfs_rtfind_forw(
267 xfs_mount_t *mp, /* file system mount point */
268 xfs_trans_t *tp, /* transaction pointer */
269 xfs_rtblock_t start, /* starting block to look at */
270 xfs_rtblock_t limit, /* last block to look at */
271 xfs_rtblock_t *rtblock) /* out: start block found */
272{
273 xfs_rtword_t *b; /* current word in buffer */
274 int bit; /* bit number in the word */
275 xfs_rtblock_t block; /* bitmap block number */
e49e365f 276 xfs_buf_t *bp; /* buf for the block */
2bd0ea18
NS
277 xfs_rtword_t *bufp; /* starting word in buffer */
278 int error; /* error value */
279 xfs_rtblock_t i; /* current bit number rel. to start */
280 xfs_rtblock_t lastbit; /* last useful bit in the word */
281 xfs_rtblock_t len; /* length of inspected area */
282 xfs_rtword_t mask; /* mask of relevant bits for value */
283 xfs_rtword_t want; /* mask for "good" values */
284 xfs_rtword_t wdiff; /* difference from wanted value */
285 int word; /* word number in the buffer */
286
287 /*
288 * Compute and read in starting bitmap block for starting block.
289 */
290 block = XFS_BITTOBLOCK(mp, start);
291 error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
292 if (error) {
293 return error;
294 }
295 bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
296 /*
297 * Get the first word's index & point to it.
298 */
299 word = XFS_BITTOWORD(mp, start);
300 b = &bufp[word];
301 bit = (int)(start & (XFS_NBWORD - 1));
302 len = limit - start + 1;
303 /*
304 * Compute match value, based on the bit at start: if 1 (free)
305 * then all-ones, else all-zeroes.
306 */
307 want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
308 /*
309 * If the starting position is not word-aligned, deal with the
310 * partial word.
311 */
312 if (bit) {
313 /*
314 * Calculate last (rightmost) bit number to look at,
315 * and mask for all the relevant bits in this word.
316 */
317 lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
318 mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
319 /*
320 * Calculate the difference between the value there
321 * and what we're looking for.
322 */
0e266570 323 if ((wdiff = (*b ^ want) & mask)) {
2bd0ea18
NS
324 /*
325 * Different. Mark where we are and return.
326 */
327 xfs_trans_brelse(tp, bp);
328 i = XFS_RTLOBIT(wdiff) - bit;
329 *rtblock = start + i - 1;
330 return 0;
331 }
332 i = lastbit - bit;
333 /*
334 * Go on to next block if that's where the next word is
335 * and we need the next word.
336 */
337 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
338 /*
339 * If done with this block, get the previous one.
340 */
341 xfs_trans_brelse(tp, bp);
342 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
343 if (error) {
344 return error;
345 }
346 b = bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
347 word = 0;
348 } else {
349 /*
350 * Go on to the previous word in the buffer.
351 */
352 b++;
353 }
354 } else {
355 /*
356 * Starting on a word boundary, no partial word.
357 */
358 i = 0;
359 }
360 /*
361 * Loop over whole words in buffers. When we use up one buffer
362 * we move on to the next one.
363 */
364 while (len - i >= XFS_NBWORD) {
365 /*
366 * Compute difference between actual and desired value.
367 */
0e266570 368 if ((wdiff = *b ^ want)) {
2bd0ea18
NS
369 /*
370 * Different, mark where we are and return.
371 */
372 xfs_trans_brelse(tp, bp);
373 i += XFS_RTLOBIT(wdiff);
374 *rtblock = start + i - 1;
375 return 0;
376 }
377 i += XFS_NBWORD;
378 /*
379 * Go on to next block if that's where the next word is
380 * and we need the next word.
381 */
382 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
383 /*
384 * If done with this block, get the next one.
385 */
386 xfs_trans_brelse(tp, bp);
387 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
388 if (error) {
389 return error;
390 }
391 b = bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
392 word = 0;
393 } else {
394 /*
395 * Go on to the next word in the buffer.
396 */
397 b++;
398 }
399 }
400 /*
401 * If not ending on a word boundary, deal with the last
402 * (partial) word.
403 */
0e266570 404 if ((lastbit = len - i)) {
2bd0ea18
NS
405 /*
406 * Calculate mask for all the relevant bits in this word.
407 */
408 mask = ((xfs_rtword_t)1 << lastbit) - 1;
409 /*
410 * Compute difference between actual and desired value.
411 */
0e266570 412 if ((wdiff = (*b ^ want) & mask)) {
2bd0ea18
NS
413 /*
414 * Different, mark where we are and return.
415 */
416 xfs_trans_brelse(tp, bp);
417 i += XFS_RTLOBIT(wdiff);
418 *rtblock = start + i - 1;
419 return 0;
420 } else
421 i = len;
422 }
423 /*
424 * No match, return that we scanned the whole area.
425 */
426 xfs_trans_brelse(tp, bp);
427 *rtblock = start + i - 1;
428 return 0;
429}
430
431/*
432 * Mark an extent specified by start and len freed.
433 * Updates all the summary information as well as the bitmap.
434 */
435STATIC int /* error */
436xfs_rtfree_range(
437 xfs_mount_t *mp, /* file system mount point */
438 xfs_trans_t *tp, /* transaction pointer */
439 xfs_rtblock_t start, /* starting block to free */
440 xfs_extlen_t len, /* length to free */
e49e365f 441 xfs_buf_t **rbpp, /* in/out: summary block buffer */
2bd0ea18
NS
442 xfs_fsblock_t *rsb) /* in/out: summary block number */
443{
444 xfs_rtblock_t end; /* end of the freed extent */
445 int error; /* error value */
446 xfs_rtblock_t postblock; /* first block freed > end */
447 xfs_rtblock_t preblock; /* first block freed < start */
448
449 end = start + len - 1;
450 /*
451 * Modify the bitmap to mark this extent freed.
452 */
453 error = xfs_rtmodify_range(mp, tp, start, len, 1);
454 if (error) {
455 return error;
456 }
457 /*
458 * Assume we're freeing out of the middle of an allocated extent.
459 * We need to find the beginning and end of the extent so we can
460 * properly update the summary.
461 */
462 error = xfs_rtfind_back(mp, tp, start, 0, &preblock);
463 if (error) {
464 return error;
465 }
466 /*
467 * Find the next allocated block (end of allocated extent).
468 */
469 error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1,
470 &postblock);
471 /*
472 * If there are blocks not being freed at the front of the
473 * old extent, add summary data for them to be allocated.
474 */
475 if (preblock < start) {
476 error = xfs_rtmodify_summary(mp, tp,
477 XFS_RTBLOCKLOG(start - preblock),
478 XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb);
479 if (error) {
480 return error;
481 }
482 }
483 /*
484 * If there are blocks not being freed at the end of the
485 * old extent, add summary data for them to be allocated.
486 */
487 if (postblock > end) {
488 error = xfs_rtmodify_summary(mp, tp,
489 XFS_RTBLOCKLOG(postblock - end),
490 XFS_BITTOBLOCK(mp, end + 1), -1, rbpp, rsb);
491 if (error) {
492 return error;
493 }
494 }
495 /*
496 * Increment the summary information corresponding to the entire
497 * (new) free extent.
498 */
499 error = xfs_rtmodify_summary(mp, tp,
500 XFS_RTBLOCKLOG(postblock + 1 - preblock),
501 XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb);
502 return error;
503}
504
505/*
506 * Set the given range of bitmap bits to the given value.
507 * Do whatever I/O and logging is required.
508 */
509STATIC int /* error */
510xfs_rtmodify_range(
511 xfs_mount_t *mp, /* file system mount point */
512 xfs_trans_t *tp, /* transaction pointer */
513 xfs_rtblock_t start, /* starting block to modify */
514 xfs_extlen_t len, /* length of extent to modify */
515 int val) /* 1 for free, 0 for allocated */
516{
517 xfs_rtword_t *b; /* current word in buffer */
518 int bit; /* bit number in the word */
519 xfs_rtblock_t block; /* bitmap block number */
006d8e9a 520 xfs_buf_t *bp; /* buf for the block */
2bd0ea18
NS
521 xfs_rtword_t *bufp; /* starting word in buffer */
522 int error; /* error value */
523 xfs_rtword_t *first; /* first used word in the buffer */
524 int i; /* current bit number rel. to start */
525 int lastbit; /* last useful bit in word */
526 xfs_rtword_t mask; /* mask o frelevant bits for value */
527 int word; /* word number in the buffer */
528
529 /*
530 * Compute starting bitmap block number.
531 */
532 block = XFS_BITTOBLOCK(mp, start);
533 /*
534 * Read the bitmap block, and point to its data.
535 */
536 error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
537 if (error) {
538 return error;
539 }
540 bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
541 /*
542 * Compute the starting word's address, and starting bit.
543 */
544 word = XFS_BITTOWORD(mp, start);
545 first = b = &bufp[word];
546 bit = (int)(start & (XFS_NBWORD - 1));
547 /*
548 * 0 (allocated) => all zeroes; 1 (free) => all ones.
549 */
550 val = -val;
551 /*
552 * If not starting on a word boundary, deal with the first
553 * (partial) word.
554 */
555 if (bit) {
556 /*
557 * Compute first bit not changed and mask of relevant bits.
558 */
559 lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
560 mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
561 /*
562 * Set/clear the active bits.
563 */
564 if (val)
565 *b |= mask;
566 else
567 *b &= ~mask;
568 i = lastbit - bit;
569 /*
570 * Go on to the next block if that's where the next word is
571 * and we need the next word.
572 */
573 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
574 /*
575 * Log the changed part of this block.
576 * Get the next one.
577 */
578 xfs_trans_log_buf(tp, bp,
579 (uint)((char *)first - (char *)bufp),
580 (uint)((char *)b - (char *)bufp));
581 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
582 if (error) {
583 return error;
584 }
585 first = b = bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
586 word = 0;
587 } else {
588 /*
589 * Go on to the next word in the buffer
590 */
591 b++;
592 }
593 } else {
594 /*
595 * Starting on a word boundary, no partial word.
596 */
597 i = 0;
598 }
599 /*
600 * Loop over whole words in buffers. When we use up one buffer
601 * we move on to the next one.
602 */
603 while (len - i >= XFS_NBWORD) {
604 /*
605 * Set the word value correctly.
606 */
607 *b = val;
608 i += XFS_NBWORD;
609 /*
610 * Go on to the next block if that's where the next word is
611 * and we need the next word.
612 */
613 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
614 /*
615 * Log the changed part of this block.
616 * Get the next one.
617 */
618 xfs_trans_log_buf(tp, bp,
619 (uint)((char *)first - (char *)bufp),
620 (uint)((char *)b - (char *)bufp));
621 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
622 if (error) {
623 return error;
624 }
625 first = b = bufp = (xfs_rtword_t *)XFS_BUF_PTR(bp);
626 word = 0;
627 } else {
628 /*
629 * Go on to the next word in the buffer
630 */
631 b++;
632 }
633 }
634 /*
635 * If not ending on a word boundary, deal with the last
636 * (partial) word.
637 */
0e266570 638 if ((lastbit = len - i)) {
2bd0ea18
NS
639 /*
640 * Compute a mask of relevant bits.
641 */
642 bit = 0;
643 mask = ((xfs_rtword_t)1 << lastbit) - 1;
644 /*
645 * Set/clear the active bits.
646 */
647 if (val)
648 *b |= mask;
649 else
650 *b &= ~mask;
651 b++;
652 }
653 /*
654 * Log any remaining changed bytes.
655 */
656 if (b > first)
657 xfs_trans_log_buf(tp, bp, (uint)((char *)first - (char *)bufp),
658 (uint)((char *)b - (char *)bufp - 1));
659 return 0;
660}
661
662/*
663 * Read and modify the summary information for a given extent size,
664 * bitmap block combination.
665 * Keeps track of a current summary block, so we don't keep reading
666 * it from the buffer cache.
667 */
668STATIC int /* error */
669xfs_rtmodify_summary(
670 xfs_mount_t *mp, /* file system mount point */
671 xfs_trans_t *tp, /* transaction pointer */
672 int log, /* log2 of extent size */
673 xfs_rtblock_t bbno, /* bitmap block number */
674 int delta, /* change to make to summary info */
e49e365f 675 xfs_buf_t **rbpp, /* in/out: summary block buffer */
2bd0ea18
NS
676 xfs_fsblock_t *rsb) /* in/out: summary block number */
677{
e49e365f 678 xfs_buf_t *bp; /* buffer for the summary block */
2bd0ea18
NS
679 int error; /* error value */
680 xfs_fsblock_t sb; /* summary fsblock */
681 int so; /* index into the summary file */
682 xfs_suminfo_t *sp; /* pointer to returned data */
683
684 /*
685 * Compute entry number in the summary file.
686 */
687 so = XFS_SUMOFFS(mp, log, bbno);
688 /*
689 * Compute the block number in the summary file.
690 */
691 sb = XFS_SUMOFFSTOBLOCK(mp, so);
692 /*
693 * If we have an old buffer, and the block number matches, use that.
694 */
695 if (rbpp && *rbpp && *rsb == sb)
696 bp = *rbpp;
697 /*
698 * Otherwise we have to get the buffer.
699 */
700 else {
701 /*
702 * If there was an old one, get rid of it first.
703 */
704 if (rbpp && *rbpp)
705 xfs_trans_brelse(tp, *rbpp);
706 error = xfs_rtbuf_get(mp, tp, sb, 1, &bp);
707 if (error) {
708 return error;
709 }
710 /*
711 * Remember this buffer and block for the next call.
712 */
713 if (rbpp) {
714 *rbpp = bp;
715 *rsb = sb;
716 }
717 }
718 /*
719 * Point to the summary information, modify and log it.
720 */
721 sp = XFS_SUMPTR(mp, bp, so);
722 *sp += delta;
723 xfs_trans_log_buf(tp, bp, (uint)((char *)sp - (char *)XFS_BUF_PTR(bp)),
724 (uint)((char *)sp - (char *)XFS_BUF_PTR(bp) + sizeof(*sp) - 1));
725 return 0;
726}
727
728/*
5000d01d 729 * Free an extent in the realtime subvolume. Length is expressed in
2bd0ea18
NS
730 * realtime extents, as is the block number.
731 */
732int /* error */
733xfs_rtfree_extent(
734 xfs_trans_t *tp, /* transaction pointer */
735 xfs_rtblock_t bno, /* starting block number to free */
736 xfs_extlen_t len) /* length of extent freed */
737{
738 int error; /* error value */
739 xfs_inode_t *ip; /* bitmap file inode */
740 xfs_mount_t *mp; /* file system mount structure */
741 xfs_fsblock_t sb; /* summary file block number */
e49e365f 742 xfs_buf_t *sumbp; /* summary file block buffer */
2bd0ea18
NS
743
744 mp = tp->t_mountp;
745 /*
746 * Synchronize by locking the bitmap inode.
747 */
748 error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, XFS_ILOCK_EXCL, &ip);
749 if (error) {
750 return error;
751 }
752#if defined(__KERNEL__) && defined(DEBUG)
753 /*
754 * Check to see that this whole range is currently allocated.
755 */
756 {
757 int stat; /* result from checking range */
758
759 error = xfs_rtcheck_alloc_range(mp, tp, bno, len, &stat);
760 if (error) {
761 return error;
762 }
763 ASSERT(stat);
764 }
765#endif
766 sumbp = NULL;
767 /*
768 * Free the range of realtime blocks.
769 */
770 error = xfs_rtfree_range(mp, tp, bno, len, &sumbp, &sb);
771 if (error) {
772 return error;
773 }
774 /*
775 * Mark more blocks free in the superblock.
776 */
777 xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS, (long)len);
778 /*
779 * If we've now freed all the blocks, reset the file sequence
780 * number to 0.
781 */
782 if (tp->t_frextents_delta + mp->m_sb.sb_frextents ==
783 mp->m_sb.sb_rextents) {
784 if (!(ip->i_d.di_flags & XFS_DIFLAG_NEWRTBM))
785 ip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM;
786 *(__uint64_t *)&ip->i_d.di_atime = 0;
787 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
788 }
789 return 0;
790}