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_sb.h" 26 #include "xfs_ag.h" 27 #include "xfs_mount.h" 28 #include "xfs_inode.h" 29 #include "xfs_bmap.h" 30 #include "xfs_bmap_util.h" 31 #include "xfs_bmap_btree.h" 32 #include "xfs_alloc.h" 33 #include "xfs_error.h" 34 #include "xfs_trans.h" 35 #include "xfs_trans_space.h" 36 #include "xfs_trace.h" 37 #include "xfs_buf.h" 38 #include "xfs_icache.h" 39 #include "xfs_dinode.h" 40 #include "xfs_rtalloc.h" 41 42 43 /* 44 * Realtime allocator bitmap functions shared with userspace. 45 */ 46 47 /* 48 * Get a buffer for the bitmap or summary file block specified. 49 * The buffer is returned read and locked. 50 */ 51 int 52 xfs_rtbuf_get( 53 xfs_mount_t *mp, /* file system mount structure */ 54 xfs_trans_t *tp, /* transaction pointer */ 55 xfs_rtblock_t block, /* block number in bitmap or summary */ 56 int issum, /* is summary not bitmap */ 57 xfs_buf_t **bpp) /* output: buffer for the block */ 58 { 59 xfs_buf_t *bp; /* block buffer, result */ 60 xfs_inode_t *ip; /* bitmap or summary inode */ 61 xfs_bmbt_irec_t map; 62 int nmap = 1; 63 int error; /* error value */ 64 65 ip = issum ? mp->m_rsumip : mp->m_rbmip; 66 67 error = xfs_bmapi_read(ip, block, 1, &map, &nmap, XFS_DATA_FORK); 68 if (error) 69 return error; 70 71 ASSERT(map.br_startblock != NULLFSBLOCK); 72 error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, 73 XFS_FSB_TO_DADDR(mp, map.br_startblock), 74 mp->m_bsize, 0, &bp, NULL); 75 if (error) 76 return error; 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 */ 85 int 86 xfs_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 */ 260 int 261 xfs_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 /* 427 * Read and modify the summary information for a given extent size, 428 * bitmap block combination. 429 * Keeps track of a current summary block, so we don't keep reading 430 * it from the buffer cache. 431 */ 432 int 433 xfs_rtmodify_summary( 434 xfs_mount_t *mp, /* file system mount point */ 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 { 442 xfs_buf_t *bp; /* buffer for the summary block */ 443 int error; /* error value */ 444 xfs_fsblock_t sb; /* summary fsblock */ 445 int so; /* index into the summary file */ 446 xfs_suminfo_t *sp; /* pointer to returned data */ 447 448 /* 449 * Compute entry number in the summary file. 450 */ 451 so = XFS_SUMOFFS(mp, log, bbno); 452 /* 453 * Compute the block number in the summary file. 454 */ 455 sb = XFS_SUMOFFSTOBLOCK(mp, so); 456 /* 457 * If we have an old buffer, and the block number matches, use that. 458 */ 459 if (rbpp && *rbpp && *rsb == sb) 460 bp = *rbpp; 461 /* 462 * Otherwise we have to get the buffer. 463 */ 464 else { 465 /* 466 * If there was an old one, get rid of it first. 467 */ 468 if (rbpp && *rbpp) 469 xfs_trans_brelse(tp, *rbpp); 470 error = xfs_rtbuf_get(mp, tp, sb, 1, &bp); 471 if (error) { 472 return error; 473 } 474 /* 475 * Remember this buffer and block for the next call. 476 */ 477 if (rbpp) { 478 *rbpp = bp; 479 *rsb = sb; 480 } 481 } 482 /* 483 * Point to the summary information, modify and log it. 484 */ 485 sp = XFS_SUMPTR(mp, bp, so); 486 *sp += delta; 487 xfs_trans_log_buf(tp, bp, (uint)((char *)sp - (char *)bp->b_addr), 488 (uint)((char *)sp - (char *)bp->b_addr + sizeof(*sp) - 1)); 489 return 0; 490 } 491 492 /* 493 * Set the given range of bitmap bits to the given value. 494 * Do whatever I/O and logging is required. 495 */ 496 int 497 xfs_rtmodify_range( 498 xfs_mount_t *mp, /* file system mount point */ 499 xfs_trans_t *tp, /* transaction pointer */ 500 xfs_rtblock_t start, /* starting block to modify */ 501 xfs_extlen_t len, /* length of extent to modify */ 502 int val) /* 1 for free, 0 for allocated */ 503 { 504 xfs_rtword_t *b; /* current word in buffer */ 505 int bit; /* bit number in the word */ 506 xfs_rtblock_t block; /* bitmap block number */ 507 xfs_buf_t *bp; /* buf for the block */ 508 xfs_rtword_t *bufp; /* starting word in buffer */ 509 int error; /* error value */ 510 xfs_rtword_t *first; /* first used word in the buffer */ 511 int i; /* current bit number rel. to start */ 512 int lastbit; /* last useful bit in word */ 513 xfs_rtword_t mask; /* mask o frelevant bits for value */ 514 int word; /* word number in the buffer */ 515 516 /* 517 * Compute starting bitmap block number. 518 */ 519 block = XFS_BITTOBLOCK(mp, start); 520 /* 521 * Read the bitmap block, and point to its data. 522 */ 523 error = xfs_rtbuf_get(mp, tp, block, 0, &bp); 524 if (error) { 525 return error; 526 } 527 bufp = bp->b_addr; 528 /* 529 * Compute the starting word's address, and starting bit. 530 */ 531 word = XFS_BITTOWORD(mp, start); 532 first = b = &bufp[word]; 533 bit = (int)(start & (XFS_NBWORD - 1)); 534 /* 535 * 0 (allocated) => all zeroes; 1 (free) => all ones. 536 */ 537 val = -val; 538 /* 539 * If not starting on a word boundary, deal with the first 540 * (partial) word. 541 */ 542 if (bit) { 543 /* 544 * Compute first bit not changed and mask of relevant bits. 545 */ 546 lastbit = XFS_RTMIN(bit + len, XFS_NBWORD); 547 mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit; 548 /* 549 * Set/clear the active bits. 550 */ 551 if (val) 552 *b |= mask; 553 else 554 *b &= ~mask; 555 i = lastbit - bit; 556 /* 557 * Go on to the next block if that's where the next word is 558 * and we need the next word. 559 */ 560 if (++word == XFS_BLOCKWSIZE(mp) && i < len) { 561 /* 562 * Log the changed part of this block. 563 * Get the next one. 564 */ 565 xfs_trans_log_buf(tp, bp, 566 (uint)((char *)first - (char *)bufp), 567 (uint)((char *)b - (char *)bufp)); 568 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); 569 if (error) { 570 return error; 571 } 572 first = b = bufp = bp->b_addr; 573 word = 0; 574 } else { 575 /* 576 * Go on to the next word in the buffer 577 */ 578 b++; 579 } 580 } else { 581 /* 582 * Starting on a word boundary, no partial word. 583 */ 584 i = 0; 585 } 586 /* 587 * Loop over whole words in buffers. When we use up one buffer 588 * we move on to the next one. 589 */ 590 while (len - i >= XFS_NBWORD) { 591 /* 592 * Set the word value correctly. 593 */ 594 *b = val; 595 i += XFS_NBWORD; 596 /* 597 * Go on to the next block if that's where the next word is 598 * and we need the next word. 599 */ 600 if (++word == XFS_BLOCKWSIZE(mp) && i < len) { 601 /* 602 * Log the changed part of this block. 603 * Get the next one. 604 */ 605 xfs_trans_log_buf(tp, bp, 606 (uint)((char *)first - (char *)bufp), 607 (uint)((char *)b - (char *)bufp)); 608 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); 609 if (error) { 610 return error; 611 } 612 first = b = bufp = bp->b_addr; 613 word = 0; 614 } else { 615 /* 616 * Go on to the next word in the buffer 617 */ 618 b++; 619 } 620 } 621 /* 622 * If not ending on a word boundary, deal with the last 623 * (partial) word. 624 */ 625 if ((lastbit = len - i)) { 626 /* 627 * Compute a mask of relevant bits. 628 */ 629 bit = 0; 630 mask = ((xfs_rtword_t)1 << lastbit) - 1; 631 /* 632 * Set/clear the active bits. 633 */ 634 if (val) 635 *b |= mask; 636 else 637 *b &= ~mask; 638 b++; 639 } 640 /* 641 * Log any remaining changed bytes. 642 */ 643 if (b > first) 644 xfs_trans_log_buf(tp, bp, (uint)((char *)first - (char *)bufp), 645 (uint)((char *)b - (char *)bufp - 1)); 646 return 0; 647 } 648 649 /* 650 * Mark an extent specified by start and len freed. 651 * Updates all the summary information as well as the bitmap. 652 */ 653 int 654 xfs_rtfree_range( 655 xfs_mount_t *mp, /* file system mount point */ 656 xfs_trans_t *tp, /* transaction pointer */ 657 xfs_rtblock_t start, /* starting block to free */ 658 xfs_extlen_t len, /* length to free */ 659 xfs_buf_t **rbpp, /* in/out: summary block buffer */ 660 xfs_fsblock_t *rsb) /* in/out: summary block number */ 661 { 662 xfs_rtblock_t end; /* end of the freed extent */ 663 int error; /* error value */ 664 xfs_rtblock_t postblock; /* first block freed > end */ 665 xfs_rtblock_t preblock; /* first block freed < start */ 666 667 end = start + len - 1; 668 /* 669 * Modify the bitmap to mark this extent freed. 670 */ 671 error = xfs_rtmodify_range(mp, tp, start, len, 1); 672 if (error) { 673 return error; 674 } 675 /* 676 * Assume we're freeing out of the middle of an allocated extent. 677 * We need to find the beginning and end of the extent so we can 678 * properly update the summary. 679 */ 680 error = xfs_rtfind_back(mp, tp, start, 0, &preblock); 681 if (error) { 682 return error; 683 } 684 /* 685 * Find the next allocated block (end of allocated extent). 686 */ 687 error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1, 688 &postblock); 689 if (error) 690 return error; 691 /* 692 * If there are blocks not being freed at the front of the 693 * old extent, add summary data for them to be allocated. 694 */ 695 if (preblock < start) { 696 error = xfs_rtmodify_summary(mp, tp, 697 XFS_RTBLOCKLOG(start - preblock), 698 XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb); 699 if (error) { 700 return error; 701 } 702 } 703 /* 704 * If there are blocks not being freed at the end of the 705 * old extent, add summary data for them to be allocated. 706 */ 707 if (postblock > end) { 708 error = xfs_rtmodify_summary(mp, tp, 709 XFS_RTBLOCKLOG(postblock - end), 710 XFS_BITTOBLOCK(mp, end + 1), -1, rbpp, rsb); 711 if (error) { 712 return error; 713 } 714 } 715 /* 716 * Increment the summary information corresponding to the entire 717 * (new) free extent. 718 */ 719 error = xfs_rtmodify_summary(mp, tp, 720 XFS_RTBLOCKLOG(postblock + 1 - preblock), 721 XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb); 722 return error; 723 } 724 725 /* 726 * Check that the given range is either all allocated (val = 0) or 727 * all free (val = 1). 728 */ 729 int 730 xfs_rtcheck_range( 731 xfs_mount_t *mp, /* file system mount point */ 732 xfs_trans_t *tp, /* transaction pointer */ 733 xfs_rtblock_t start, /* starting block number of extent */ 734 xfs_extlen_t len, /* length of extent */ 735 int val, /* 1 for free, 0 for allocated */ 736 xfs_rtblock_t *new, /* out: first block not matching */ 737 int *stat) /* out: 1 for matches, 0 for not */ 738 { 739 xfs_rtword_t *b; /* current word in buffer */ 740 int bit; /* bit number in the word */ 741 xfs_rtblock_t block; /* bitmap block number */ 742 xfs_buf_t *bp; /* buf for the block */ 743 xfs_rtword_t *bufp; /* starting word in buffer */ 744 int error; /* error value */ 745 xfs_rtblock_t i; /* current bit number rel. to start */ 746 xfs_rtblock_t lastbit; /* last useful bit in word */ 747 xfs_rtword_t mask; /* mask of relevant bits for value */ 748 xfs_rtword_t wdiff; /* difference from wanted value */ 749 int word; /* word number in the buffer */ 750 751 /* 752 * Compute starting bitmap block number 753 */ 754 block = XFS_BITTOBLOCK(mp, start); 755 /* 756 * Read the bitmap block. 757 */ 758 error = xfs_rtbuf_get(mp, tp, block, 0, &bp); 759 if (error) { 760 return error; 761 } 762 bufp = bp->b_addr; 763 /* 764 * Compute the starting word's address, and starting bit. 765 */ 766 word = XFS_BITTOWORD(mp, start); 767 b = &bufp[word]; 768 bit = (int)(start & (XFS_NBWORD - 1)); 769 /* 770 * 0 (allocated) => all zero's; 1 (free) => all one's. 771 */ 772 val = -val; 773 /* 774 * If not starting on a word boundary, deal with the first 775 * (partial) word. 776 */ 777 if (bit) { 778 /* 779 * Compute first bit not examined. 780 */ 781 lastbit = XFS_RTMIN(bit + len, XFS_NBWORD); 782 /* 783 * Mask of relevant bits. 784 */ 785 mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit; 786 /* 787 * Compute difference between actual and desired value. 788 */ 789 if ((wdiff = (*b ^ val) & mask)) { 790 /* 791 * Different, compute first wrong bit and return. 792 */ 793 xfs_trans_brelse(tp, bp); 794 i = XFS_RTLOBIT(wdiff) - bit; 795 *new = start + i; 796 *stat = 0; 797 return 0; 798 } 799 i = lastbit - bit; 800 /* 801 * Go on to next block if that's where the next word is 802 * and we need the next word. 803 */ 804 if (++word == XFS_BLOCKWSIZE(mp) && i < len) { 805 /* 806 * If done with this block, get the next one. 807 */ 808 xfs_trans_brelse(tp, bp); 809 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); 810 if (error) { 811 return error; 812 } 813 b = bufp = bp->b_addr; 814 word = 0; 815 } else { 816 /* 817 * Go on to the next word in the buffer. 818 */ 819 b++; 820 } 821 } else { 822 /* 823 * Starting on a word boundary, no partial word. 824 */ 825 i = 0; 826 } 827 /* 828 * Loop over whole words in buffers. When we use up one buffer 829 * we move on to the next one. 830 */ 831 while (len - i >= XFS_NBWORD) { 832 /* 833 * Compute difference between actual and desired value. 834 */ 835 if ((wdiff = *b ^ val)) { 836 /* 837 * Different, compute first wrong bit and return. 838 */ 839 xfs_trans_brelse(tp, bp); 840 i += XFS_RTLOBIT(wdiff); 841 *new = start + i; 842 *stat = 0; 843 return 0; 844 } 845 i += XFS_NBWORD; 846 /* 847 * Go on to next block if that's where the next word is 848 * and we need the next word. 849 */ 850 if (++word == XFS_BLOCKWSIZE(mp) && i < len) { 851 /* 852 * If done with this block, get the next one. 853 */ 854 xfs_trans_brelse(tp, bp); 855 error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); 856 if (error) { 857 return error; 858 } 859 b = bufp = bp->b_addr; 860 word = 0; 861 } else { 862 /* 863 * Go on to the next word in the buffer. 864 */ 865 b++; 866 } 867 } 868 /* 869 * If not ending on a word boundary, deal with the last 870 * (partial) word. 871 */ 872 if ((lastbit = len - i)) { 873 /* 874 * Mask of relevant bits. 875 */ 876 mask = ((xfs_rtword_t)1 << lastbit) - 1; 877 /* 878 * Compute difference between actual and desired value. 879 */ 880 if ((wdiff = (*b ^ val) & mask)) { 881 /* 882 * Different, compute first wrong bit and return. 883 */ 884 xfs_trans_brelse(tp, bp); 885 i += XFS_RTLOBIT(wdiff); 886 *new = start + i; 887 *stat = 0; 888 return 0; 889 } else 890 i = len; 891 } 892 /* 893 * Successful, return. 894 */ 895 xfs_trans_brelse(tp, bp); 896 *new = start + i; 897 *stat = 1; 898 return 0; 899 } 900 901 #ifdef DEBUG 902 /* 903 * Check that the given extent (block range) is allocated already. 904 */ 905 STATIC int /* error */ 906 xfs_rtcheck_alloc_range( 907 xfs_mount_t *mp, /* file system mount point */ 908 xfs_trans_t *tp, /* transaction pointer */ 909 xfs_rtblock_t bno, /* starting block number of extent */ 910 xfs_extlen_t len) /* length of extent */ 911 { 912 xfs_rtblock_t new; /* dummy for xfs_rtcheck_range */ 913 int stat; 914 int error; 915 916 error = xfs_rtcheck_range(mp, tp, bno, len, 0, &new, &stat); 917 if (error) 918 return error; 919 ASSERT(stat); 920 return 0; 921 } 922 #else 923 #define xfs_rtcheck_alloc_range(m,t,b,l) (0) 924 #endif 925 /* 926 * Free an extent in the realtime subvolume. Length is expressed in 927 * realtime extents, as is the block number. 928 */ 929 int /* error */ 930 xfs_rtfree_extent( 931 xfs_trans_t *tp, /* transaction pointer */ 932 xfs_rtblock_t bno, /* starting block number to free */ 933 xfs_extlen_t len) /* length of extent freed */ 934 { 935 int error; /* error value */ 936 xfs_mount_t *mp; /* file system mount structure */ 937 xfs_fsblock_t sb; /* summary file block number */ 938 xfs_buf_t *sumbp = NULL; /* summary file block buffer */ 939 940 mp = tp->t_mountp; 941 942 ASSERT(mp->m_rbmip->i_itemp != NULL); 943 ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL)); 944 945 error = xfs_rtcheck_alloc_range(mp, tp, bno, len); 946 if (error) 947 return error; 948 949 /* 950 * Free the range of realtime blocks. 951 */ 952 error = xfs_rtfree_range(mp, tp, bno, len, &sumbp, &sb); 953 if (error) { 954 return error; 955 } 956 /* 957 * Mark more blocks free in the superblock. 958 */ 959 xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS, (long)len); 960 /* 961 * If we've now freed all the blocks, reset the file sequence 962 * number to 0. 963 */ 964 if (tp->t_frextents_delta + mp->m_sb.sb_frextents == 965 mp->m_sb.sb_rextents) { 966 if (!(mp->m_rbmip->i_d.di_flags & XFS_DIFLAG_NEWRTBM)) 967 mp->m_rbmip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM; 968 *(__uint64_t *)&mp->m_rbmip->i_d.di_atime = 0; 969 xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE); 970 } 971 return 0; 972 } 973 974