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