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