Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (c) 2000-2005 Silicon Graphics, Inc.
0004  * All Rights Reserved.
0005  */
0006 #include "xfs.h"
0007 #include "xfs_fs.h"
0008 #include "xfs_shared.h"
0009 #include "xfs_format.h"
0010 #include "xfs_log_format.h"
0011 #include "xfs_trans_resv.h"
0012 #include "xfs_bit.h"
0013 #include "xfs_mount.h"
0014 #include "xfs_inode.h"
0015 #include "xfs_bmap.h"
0016 #include "xfs_trans.h"
0017 #include "xfs_rtalloc.h"
0018 #include "xfs_error.h"
0019 
0020 /*
0021  * Realtime allocator bitmap functions shared with userspace.
0022  */
0023 
0024 /*
0025  * Real time buffers need verifiers to avoid runtime warnings during IO.
0026  * We don't have anything to verify, however, so these are just dummy
0027  * operations.
0028  */
0029 static void
0030 xfs_rtbuf_verify_read(
0031     struct xfs_buf  *bp)
0032 {
0033     return;
0034 }
0035 
0036 static void
0037 xfs_rtbuf_verify_write(
0038     struct xfs_buf  *bp)
0039 {
0040     return;
0041 }
0042 
0043 const struct xfs_buf_ops xfs_rtbuf_ops = {
0044     .name = "rtbuf",
0045     .verify_read = xfs_rtbuf_verify_read,
0046     .verify_write = xfs_rtbuf_verify_write,
0047 };
0048 
0049 /*
0050  * Get a buffer for the bitmap or summary file block specified.
0051  * The buffer is returned read and locked.
0052  */
0053 int
0054 xfs_rtbuf_get(
0055     xfs_mount_t *mp,        /* file system mount structure */
0056     xfs_trans_t *tp,        /* transaction pointer */
0057     xfs_rtblock_t   block,      /* block number in bitmap or summary */
0058     int     issum,      /* is summary not bitmap */
0059     struct xfs_buf  **bpp)      /* output: buffer for the block */
0060 {
0061     struct xfs_buf  *bp;        /* block buffer, result */
0062     xfs_inode_t *ip;        /* bitmap or summary inode */
0063     xfs_bmbt_irec_t map;
0064     int     nmap = 1;
0065     int     error;      /* error value */
0066 
0067     ip = issum ? mp->m_rsumip : mp->m_rbmip;
0068 
0069     error = xfs_bmapi_read(ip, block, 1, &map, &nmap, 0);
0070     if (error)
0071         return error;
0072 
0073     if (XFS_IS_CORRUPT(mp, nmap == 0 || !xfs_bmap_is_written_extent(&map)))
0074         return -EFSCORRUPTED;
0075 
0076     ASSERT(map.br_startblock != NULLFSBLOCK);
0077     error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
0078                    XFS_FSB_TO_DADDR(mp, map.br_startblock),
0079                    mp->m_bsize, 0, &bp, &xfs_rtbuf_ops);
0080     if (error)
0081         return error;
0082 
0083     xfs_trans_buf_set_type(tp, bp, issum ? XFS_BLFT_RTSUMMARY_BUF
0084                          : XFS_BLFT_RTBITMAP_BUF);
0085     *bpp = bp;
0086     return 0;
0087 }
0088 
0089 /*
0090  * Searching backward from start to limit, find the first block whose
0091  * allocated/free state is different from start's.
0092  */
0093 int
0094 xfs_rtfind_back(
0095     xfs_mount_t *mp,        /* file system mount point */
0096     xfs_trans_t *tp,        /* transaction pointer */
0097     xfs_rtblock_t   start,      /* starting block to look at */
0098     xfs_rtblock_t   limit,      /* last block to look at */
0099     xfs_rtblock_t   *rtblock)   /* out: start block found */
0100 {
0101     xfs_rtword_t    *b;     /* current word in buffer */
0102     int     bit;        /* bit number in the word */
0103     xfs_rtblock_t   block;      /* bitmap block number */
0104     struct xfs_buf  *bp;        /* buf for the block */
0105     xfs_rtword_t    *bufp;      /* starting word in buffer */
0106     int     error;      /* error value */
0107     xfs_rtblock_t   firstbit;   /* first useful bit in the word */
0108     xfs_rtblock_t   i;      /* current bit number rel. to start */
0109     xfs_rtblock_t   len;        /* length of inspected area */
0110     xfs_rtword_t    mask;       /* mask of relevant bits for value */
0111     xfs_rtword_t    want;       /* mask for "good" values */
0112     xfs_rtword_t    wdiff;      /* difference from wanted value */
0113     int     word;       /* word number in the buffer */
0114 
0115     /*
0116      * Compute and read in starting bitmap block for starting block.
0117      */
0118     block = XFS_BITTOBLOCK(mp, start);
0119     error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
0120     if (error) {
0121         return error;
0122     }
0123     bufp = bp->b_addr;
0124     /*
0125      * Get the first word's index & point to it.
0126      */
0127     word = XFS_BITTOWORD(mp, start);
0128     b = &bufp[word];
0129     bit = (int)(start & (XFS_NBWORD - 1));
0130     len = start - limit + 1;
0131     /*
0132      * Compute match value, based on the bit at start: if 1 (free)
0133      * then all-ones, else all-zeroes.
0134      */
0135     want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
0136     /*
0137      * If the starting position is not word-aligned, deal with the
0138      * partial word.
0139      */
0140     if (bit < XFS_NBWORD - 1) {
0141         /*
0142          * Calculate first (leftmost) bit number to look at,
0143          * and mask for all the relevant bits in this word.
0144          */
0145         firstbit = XFS_RTMAX((xfs_srtblock_t)(bit - len + 1), 0);
0146         mask = (((xfs_rtword_t)1 << (bit - firstbit + 1)) - 1) <<
0147             firstbit;
0148         /*
0149          * Calculate the difference between the value there
0150          * and what we're looking for.
0151          */
0152         if ((wdiff = (*b ^ want) & mask)) {
0153             /*
0154              * Different.  Mark where we are and return.
0155              */
0156             xfs_trans_brelse(tp, bp);
0157             i = bit - XFS_RTHIBIT(wdiff);
0158             *rtblock = start - i + 1;
0159             return 0;
0160         }
0161         i = bit - firstbit + 1;
0162         /*
0163          * Go on to previous block if that's where the previous word is
0164          * and we need the previous word.
0165          */
0166         if (--word == -1 && i < len) {
0167             /*
0168              * If done with this block, get the previous one.
0169              */
0170             xfs_trans_brelse(tp, bp);
0171             error = xfs_rtbuf_get(mp, tp, --block, 0, &bp);
0172             if (error) {
0173                 return error;
0174             }
0175             bufp = bp->b_addr;
0176             word = XFS_BLOCKWMASK(mp);
0177             b = &bufp[word];
0178         } else {
0179             /*
0180              * Go on to the previous word in the buffer.
0181              */
0182             b--;
0183         }
0184     } else {
0185         /*
0186          * Starting on a word boundary, no partial word.
0187          */
0188         i = 0;
0189     }
0190     /*
0191      * Loop over whole words in buffers.  When we use up one buffer
0192      * we move on to the previous one.
0193      */
0194     while (len - i >= XFS_NBWORD) {
0195         /*
0196          * Compute difference between actual and desired value.
0197          */
0198         if ((wdiff = *b ^ want)) {
0199             /*
0200              * Different, mark where we are and return.
0201              */
0202             xfs_trans_brelse(tp, bp);
0203             i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
0204             *rtblock = start - i + 1;
0205             return 0;
0206         }
0207         i += XFS_NBWORD;
0208         /*
0209          * Go on to previous block if that's where the previous word is
0210          * and we need the previous word.
0211          */
0212         if (--word == -1 && i < len) {
0213             /*
0214              * If done with this block, get the previous one.
0215              */
0216             xfs_trans_brelse(tp, bp);
0217             error = xfs_rtbuf_get(mp, tp, --block, 0, &bp);
0218             if (error) {
0219                 return error;
0220             }
0221             bufp = bp->b_addr;
0222             word = XFS_BLOCKWMASK(mp);
0223             b = &bufp[word];
0224         } else {
0225             /*
0226              * Go on to the previous word in the buffer.
0227              */
0228             b--;
0229         }
0230     }
0231     /*
0232      * If not ending on a word boundary, deal with the last
0233      * (partial) word.
0234      */
0235     if (len - i) {
0236         /*
0237          * Calculate first (leftmost) bit number to look at,
0238          * and mask for all the relevant bits in this word.
0239          */
0240         firstbit = XFS_NBWORD - (len - i);
0241         mask = (((xfs_rtword_t)1 << (len - i)) - 1) << firstbit;
0242         /*
0243          * Compute difference between actual and desired value.
0244          */
0245         if ((wdiff = (*b ^ want) & mask)) {
0246             /*
0247              * Different, mark where we are and return.
0248              */
0249             xfs_trans_brelse(tp, bp);
0250             i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
0251             *rtblock = start - i + 1;
0252             return 0;
0253         } else
0254             i = len;
0255     }
0256     /*
0257      * No match, return that we scanned the whole area.
0258      */
0259     xfs_trans_brelse(tp, bp);
0260     *rtblock = start - i + 1;
0261     return 0;
0262 }
0263 
0264 /*
0265  * Searching forward from start to limit, find the first block whose
0266  * allocated/free state is different from start's.
0267  */
0268 int
0269 xfs_rtfind_forw(
0270     xfs_mount_t *mp,        /* file system mount point */
0271     xfs_trans_t *tp,        /* transaction pointer */
0272     xfs_rtblock_t   start,      /* starting block to look at */
0273     xfs_rtblock_t   limit,      /* last block to look at */
0274     xfs_rtblock_t   *rtblock)   /* out: start block found */
0275 {
0276     xfs_rtword_t    *b;     /* current word in buffer */
0277     int     bit;        /* bit number in the word */
0278     xfs_rtblock_t   block;      /* bitmap block number */
0279     struct xfs_buf  *bp;        /* buf for the block */
0280     xfs_rtword_t    *bufp;      /* starting word in buffer */
0281     int     error;      /* error value */
0282     xfs_rtblock_t   i;      /* current bit number rel. to start */
0283     xfs_rtblock_t   lastbit;    /* last useful bit in the word */
0284     xfs_rtblock_t   len;        /* length of inspected area */
0285     xfs_rtword_t    mask;       /* mask of relevant bits for value */
0286     xfs_rtword_t    want;       /* mask for "good" values */
0287     xfs_rtword_t    wdiff;      /* difference from wanted value */
0288     int     word;       /* word number in the buffer */
0289 
0290     /*
0291      * Compute and read in starting bitmap block for starting block.
0292      */
0293     block = XFS_BITTOBLOCK(mp, start);
0294     error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
0295     if (error) {
0296         return error;
0297     }
0298     bufp = bp->b_addr;
0299     /*
0300      * Get the first word's index & point to it.
0301      */
0302     word = XFS_BITTOWORD(mp, start);
0303     b = &bufp[word];
0304     bit = (int)(start & (XFS_NBWORD - 1));
0305     len = limit - start + 1;
0306     /*
0307      * Compute match value, based on the bit at start: if 1 (free)
0308      * then all-ones, else all-zeroes.
0309      */
0310     want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
0311     /*
0312      * If the starting position is not word-aligned, deal with the
0313      * partial word.
0314      */
0315     if (bit) {
0316         /*
0317          * Calculate last (rightmost) bit number to look at,
0318          * and mask for all the relevant bits in this word.
0319          */
0320         lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
0321         mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
0322         /*
0323          * Calculate the difference between the value there
0324          * and what we're looking for.
0325          */
0326         if ((wdiff = (*b ^ want) & mask)) {
0327             /*
0328              * Different.  Mark where we are and return.
0329              */
0330             xfs_trans_brelse(tp, bp);
0331             i = XFS_RTLOBIT(wdiff) - bit;
0332             *rtblock = start + i - 1;
0333             return 0;
0334         }
0335         i = lastbit - bit;
0336         /*
0337          * Go on to next block if that's where the next word is
0338          * and we need the next word.
0339          */
0340         if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
0341             /*
0342              * If done with this block, get the previous one.
0343              */
0344             xfs_trans_brelse(tp, bp);
0345             error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
0346             if (error) {
0347                 return error;
0348             }
0349             b = bufp = bp->b_addr;
0350             word = 0;
0351         } else {
0352             /*
0353              * Go on to the previous word in the buffer.
0354              */
0355             b++;
0356         }
0357     } else {
0358         /*
0359          * Starting on a word boundary, no partial word.
0360          */
0361         i = 0;
0362     }
0363     /*
0364      * Loop over whole words in buffers.  When we use up one buffer
0365      * we move on to the next one.
0366      */
0367     while (len - i >= XFS_NBWORD) {
0368         /*
0369          * Compute difference between actual and desired value.
0370          */
0371         if ((wdiff = *b ^ want)) {
0372             /*
0373              * Different, mark where we are and return.
0374              */
0375             xfs_trans_brelse(tp, bp);
0376             i += XFS_RTLOBIT(wdiff);
0377             *rtblock = start + i - 1;
0378             return 0;
0379         }
0380         i += XFS_NBWORD;
0381         /*
0382          * Go on to next block if that's where the next word is
0383          * and we need the next word.
0384          */
0385         if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
0386             /*
0387              * If done with this block, get the next one.
0388              */
0389             xfs_trans_brelse(tp, bp);
0390             error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
0391             if (error) {
0392                 return error;
0393             }
0394             b = bufp = bp->b_addr;
0395             word = 0;
0396         } else {
0397             /*
0398              * Go on to the next word in the buffer.
0399              */
0400             b++;
0401         }
0402     }
0403     /*
0404      * If not ending on a word boundary, deal with the last
0405      * (partial) word.
0406      */
0407     if ((lastbit = len - i)) {
0408         /*
0409          * Calculate mask for all the relevant bits in this word.
0410          */
0411         mask = ((xfs_rtword_t)1 << lastbit) - 1;
0412         /*
0413          * Compute difference between actual and desired value.
0414          */
0415         if ((wdiff = (*b ^ want) & mask)) {
0416             /*
0417              * Different, mark where we are and return.
0418              */
0419             xfs_trans_brelse(tp, bp);
0420             i += XFS_RTLOBIT(wdiff);
0421             *rtblock = start + i - 1;
0422             return 0;
0423         } else
0424             i = len;
0425     }
0426     /*
0427      * No match, return that we scanned the whole area.
0428      */
0429     xfs_trans_brelse(tp, bp);
0430     *rtblock = start + i - 1;
0431     return 0;
0432 }
0433 
0434 /*
0435  * Read and/or modify the summary information for a given extent size,
0436  * bitmap block combination.
0437  * Keeps track of a current summary block, so we don't keep reading
0438  * it from the buffer cache.
0439  *
0440  * Summary information is returned in *sum if specified.
0441  * If no delta is specified, returns summary only.
0442  */
0443 int
0444 xfs_rtmodify_summary_int(
0445     xfs_mount_t *mp,        /* file system mount structure */
0446     xfs_trans_t *tp,        /* transaction pointer */
0447     int     log,        /* log2 of extent size */
0448     xfs_rtblock_t   bbno,       /* bitmap block number */
0449     int     delta,      /* change to make to summary info */
0450     struct xfs_buf  **rbpp,     /* in/out: summary block buffer */
0451     xfs_fsblock_t   *rsb,       /* in/out: summary block number */
0452     xfs_suminfo_t   *sum)       /* out: summary info for this block */
0453 {
0454     struct xfs_buf  *bp;        /* buffer for the summary block */
0455     int     error;      /* error value */
0456     xfs_fsblock_t   sb;     /* summary fsblock */
0457     int     so;     /* index into the summary file */
0458     xfs_suminfo_t   *sp;        /* pointer to returned data */
0459 
0460     /*
0461      * Compute entry number in the summary file.
0462      */
0463     so = XFS_SUMOFFS(mp, log, bbno);
0464     /*
0465      * Compute the block number in the summary file.
0466      */
0467     sb = XFS_SUMOFFSTOBLOCK(mp, so);
0468     /*
0469      * If we have an old buffer, and the block number matches, use that.
0470      */
0471     if (*rbpp && *rsb == sb)
0472         bp = *rbpp;
0473     /*
0474      * Otherwise we have to get the buffer.
0475      */
0476     else {
0477         /*
0478          * If there was an old one, get rid of it first.
0479          */
0480         if (*rbpp)
0481             xfs_trans_brelse(tp, *rbpp);
0482         error = xfs_rtbuf_get(mp, tp, sb, 1, &bp);
0483         if (error) {
0484             return error;
0485         }
0486         /*
0487          * Remember this buffer and block for the next call.
0488          */
0489         *rbpp = bp;
0490         *rsb = sb;
0491     }
0492     /*
0493      * Point to the summary information, modify/log it, and/or copy it out.
0494      */
0495     sp = XFS_SUMPTR(mp, bp, so);
0496     if (delta) {
0497         uint first = (uint)((char *)sp - (char *)bp->b_addr);
0498 
0499         *sp += delta;
0500         if (mp->m_rsum_cache) {
0501             if (*sp == 0 && log == mp->m_rsum_cache[bbno])
0502                 mp->m_rsum_cache[bbno]++;
0503             if (*sp != 0 && log < mp->m_rsum_cache[bbno])
0504                 mp->m_rsum_cache[bbno] = log;
0505         }
0506         xfs_trans_log_buf(tp, bp, first, first + sizeof(*sp) - 1);
0507     }
0508     if (sum)
0509         *sum = *sp;
0510     return 0;
0511 }
0512 
0513 int
0514 xfs_rtmodify_summary(
0515     xfs_mount_t *mp,        /* file system mount structure */
0516     xfs_trans_t *tp,        /* transaction pointer */
0517     int     log,        /* log2 of extent size */
0518     xfs_rtblock_t   bbno,       /* bitmap block number */
0519     int     delta,      /* change to make to summary info */
0520     struct xfs_buf  **rbpp,     /* in/out: summary block buffer */
0521     xfs_fsblock_t   *rsb)       /* in/out: summary block number */
0522 {
0523     return xfs_rtmodify_summary_int(mp, tp, log, bbno,
0524                     delta, rbpp, rsb, NULL);
0525 }
0526 
0527 /*
0528  * Set the given range of bitmap bits to the given value.
0529  * Do whatever I/O and logging is required.
0530  */
0531 int
0532 xfs_rtmodify_range(
0533     xfs_mount_t *mp,        /* file system mount point */
0534     xfs_trans_t *tp,        /* transaction pointer */
0535     xfs_rtblock_t   start,      /* starting block to modify */
0536     xfs_extlen_t    len,        /* length of extent to modify */
0537     int     val)        /* 1 for free, 0 for allocated */
0538 {
0539     xfs_rtword_t    *b;     /* current word in buffer */
0540     int     bit;        /* bit number in the word */
0541     xfs_rtblock_t   block;      /* bitmap block number */
0542     struct xfs_buf  *bp;        /* buf for the block */
0543     xfs_rtword_t    *bufp;      /* starting word in buffer */
0544     int     error;      /* error value */
0545     xfs_rtword_t    *first;     /* first used word in the buffer */
0546     int     i;      /* current bit number rel. to start */
0547     int     lastbit;    /* last useful bit in word */
0548     xfs_rtword_t    mask;       /* mask o frelevant bits for value */
0549     int     word;       /* word number in the buffer */
0550 
0551     /*
0552      * Compute starting bitmap block number.
0553      */
0554     block = XFS_BITTOBLOCK(mp, start);
0555     /*
0556      * Read the bitmap block, and point to its data.
0557      */
0558     error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
0559     if (error) {
0560         return error;
0561     }
0562     bufp = bp->b_addr;
0563     /*
0564      * Compute the starting word's address, and starting bit.
0565      */
0566     word = XFS_BITTOWORD(mp, start);
0567     first = b = &bufp[word];
0568     bit = (int)(start & (XFS_NBWORD - 1));
0569     /*
0570      * 0 (allocated) => all zeroes; 1 (free) => all ones.
0571      */
0572     val = -val;
0573     /*
0574      * If not starting on a word boundary, deal with the first
0575      * (partial) word.
0576      */
0577     if (bit) {
0578         /*
0579          * Compute first bit not changed and mask of relevant bits.
0580          */
0581         lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
0582         mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
0583         /*
0584          * Set/clear the active bits.
0585          */
0586         if (val)
0587             *b |= mask;
0588         else
0589             *b &= ~mask;
0590         i = lastbit - bit;
0591         /*
0592          * Go on to the next block if that's where the next word is
0593          * and we need the next word.
0594          */
0595         if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
0596             /*
0597              * Log the changed part of this block.
0598              * Get the next one.
0599              */
0600             xfs_trans_log_buf(tp, bp,
0601                 (uint)((char *)first - (char *)bufp),
0602                 (uint)((char *)b - (char *)bufp));
0603             error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
0604             if (error) {
0605                 return error;
0606             }
0607             first = b = bufp = bp->b_addr;
0608             word = 0;
0609         } else {
0610             /*
0611              * Go on to the next word in the buffer
0612              */
0613             b++;
0614         }
0615     } else {
0616         /*
0617          * Starting on a word boundary, no partial word.
0618          */
0619         i = 0;
0620     }
0621     /*
0622      * Loop over whole words in buffers.  When we use up one buffer
0623      * we move on to the next one.
0624      */
0625     while (len - i >= XFS_NBWORD) {
0626         /*
0627          * Set the word value correctly.
0628          */
0629         *b = val;
0630         i += XFS_NBWORD;
0631         /*
0632          * Go on to the next block if that's where the next word is
0633          * and we need the next word.
0634          */
0635         if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
0636             /*
0637              * Log the changed part of this block.
0638              * Get the next one.
0639              */
0640             xfs_trans_log_buf(tp, bp,
0641                 (uint)((char *)first - (char *)bufp),
0642                 (uint)((char *)b - (char *)bufp));
0643             error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
0644             if (error) {
0645                 return error;
0646             }
0647             first = b = bufp = bp->b_addr;
0648             word = 0;
0649         } else {
0650             /*
0651              * Go on to the next word in the buffer
0652              */
0653             b++;
0654         }
0655     }
0656     /*
0657      * If not ending on a word boundary, deal with the last
0658      * (partial) word.
0659      */
0660     if ((lastbit = len - i)) {
0661         /*
0662          * Compute a mask of relevant bits.
0663          */
0664         mask = ((xfs_rtword_t)1 << lastbit) - 1;
0665         /*
0666          * Set/clear the active bits.
0667          */
0668         if (val)
0669             *b |= mask;
0670         else
0671             *b &= ~mask;
0672         b++;
0673     }
0674     /*
0675      * Log any remaining changed bytes.
0676      */
0677     if (b > first)
0678         xfs_trans_log_buf(tp, bp, (uint)((char *)first - (char *)bufp),
0679             (uint)((char *)b - (char *)bufp - 1));
0680     return 0;
0681 }
0682 
0683 /*
0684  * Mark an extent specified by start and len freed.
0685  * Updates all the summary information as well as the bitmap.
0686  */
0687 int
0688 xfs_rtfree_range(
0689     xfs_mount_t *mp,        /* file system mount point */
0690     xfs_trans_t *tp,        /* transaction pointer */
0691     xfs_rtblock_t   start,      /* starting block to free */
0692     xfs_extlen_t    len,        /* length to free */
0693     struct xfs_buf  **rbpp,     /* in/out: summary block buffer */
0694     xfs_fsblock_t   *rsb)       /* in/out: summary block number */
0695 {
0696     xfs_rtblock_t   end;        /* end of the freed extent */
0697     int     error;      /* error value */
0698     xfs_rtblock_t   postblock;  /* first block freed > end */
0699     xfs_rtblock_t   preblock;   /* first block freed < start */
0700 
0701     end = start + len - 1;
0702     /*
0703      * Modify the bitmap to mark this extent freed.
0704      */
0705     error = xfs_rtmodify_range(mp, tp, start, len, 1);
0706     if (error) {
0707         return error;
0708     }
0709     /*
0710      * Assume we're freeing out of the middle of an allocated extent.
0711      * We need to find the beginning and end of the extent so we can
0712      * properly update the summary.
0713      */
0714     error = xfs_rtfind_back(mp, tp, start, 0, &preblock);
0715     if (error) {
0716         return error;
0717     }
0718     /*
0719      * Find the next allocated block (end of allocated extent).
0720      */
0721     error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1,
0722         &postblock);
0723     if (error)
0724         return error;
0725     /*
0726      * If there are blocks not being freed at the front of the
0727      * old extent, add summary data for them to be allocated.
0728      */
0729     if (preblock < start) {
0730         error = xfs_rtmodify_summary(mp, tp,
0731             XFS_RTBLOCKLOG(start - preblock),
0732             XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb);
0733         if (error) {
0734             return error;
0735         }
0736     }
0737     /*
0738      * If there are blocks not being freed at the end of the
0739      * old extent, add summary data for them to be allocated.
0740      */
0741     if (postblock > end) {
0742         error = xfs_rtmodify_summary(mp, tp,
0743             XFS_RTBLOCKLOG(postblock - end),
0744             XFS_BITTOBLOCK(mp, end + 1), -1, rbpp, rsb);
0745         if (error) {
0746             return error;
0747         }
0748     }
0749     /*
0750      * Increment the summary information corresponding to the entire
0751      * (new) free extent.
0752      */
0753     error = xfs_rtmodify_summary(mp, tp,
0754         XFS_RTBLOCKLOG(postblock + 1 - preblock),
0755         XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb);
0756     return error;
0757 }
0758 
0759 /*
0760  * Check that the given range is either all allocated (val = 0) or
0761  * all free (val = 1).
0762  */
0763 int
0764 xfs_rtcheck_range(
0765     xfs_mount_t *mp,        /* file system mount point */
0766     xfs_trans_t *tp,        /* transaction pointer */
0767     xfs_rtblock_t   start,      /* starting block number of extent */
0768     xfs_extlen_t    len,        /* length of extent */
0769     int     val,        /* 1 for free, 0 for allocated */
0770     xfs_rtblock_t   *new,       /* out: first block not matching */
0771     int     *stat)      /* out: 1 for matches, 0 for not */
0772 {
0773     xfs_rtword_t    *b;     /* current word in buffer */
0774     int     bit;        /* bit number in the word */
0775     xfs_rtblock_t   block;      /* bitmap block number */
0776     struct xfs_buf  *bp;        /* buf for the block */
0777     xfs_rtword_t    *bufp;      /* starting word in buffer */
0778     int     error;      /* error value */
0779     xfs_rtblock_t   i;      /* current bit number rel. to start */
0780     xfs_rtblock_t   lastbit;    /* last useful bit in word */
0781     xfs_rtword_t    mask;       /* mask of relevant bits for value */
0782     xfs_rtword_t    wdiff;      /* difference from wanted value */
0783     int     word;       /* word number in the buffer */
0784 
0785     /*
0786      * Compute starting bitmap block number
0787      */
0788     block = XFS_BITTOBLOCK(mp, start);
0789     /*
0790      * Read the bitmap block.
0791      */
0792     error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
0793     if (error) {
0794         return error;
0795     }
0796     bufp = bp->b_addr;
0797     /*
0798      * Compute the starting word's address, and starting bit.
0799      */
0800     word = XFS_BITTOWORD(mp, start);
0801     b = &bufp[word];
0802     bit = (int)(start & (XFS_NBWORD - 1));
0803     /*
0804      * 0 (allocated) => all zero's; 1 (free) => all one's.
0805      */
0806     val = -val;
0807     /*
0808      * If not starting on a word boundary, deal with the first
0809      * (partial) word.
0810      */
0811     if (bit) {
0812         /*
0813          * Compute first bit not examined.
0814          */
0815         lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
0816         /*
0817          * Mask of relevant bits.
0818          */
0819         mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
0820         /*
0821          * Compute difference between actual and desired value.
0822          */
0823         if ((wdiff = (*b ^ val) & mask)) {
0824             /*
0825              * Different, compute first wrong bit and return.
0826              */
0827             xfs_trans_brelse(tp, bp);
0828             i = XFS_RTLOBIT(wdiff) - bit;
0829             *new = start + i;
0830             *stat = 0;
0831             return 0;
0832         }
0833         i = lastbit - bit;
0834         /*
0835          * Go on to next block if that's where the next word is
0836          * and we need the next word.
0837          */
0838         if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
0839             /*
0840              * If done with this block, get the next one.
0841              */
0842             xfs_trans_brelse(tp, bp);
0843             error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
0844             if (error) {
0845                 return error;
0846             }
0847             b = bufp = bp->b_addr;
0848             word = 0;
0849         } else {
0850             /*
0851              * Go on to the next word in the buffer.
0852              */
0853             b++;
0854         }
0855     } else {
0856         /*
0857          * Starting on a word boundary, no partial word.
0858          */
0859         i = 0;
0860     }
0861     /*
0862      * Loop over whole words in buffers.  When we use up one buffer
0863      * we move on to the next one.
0864      */
0865     while (len - i >= XFS_NBWORD) {
0866         /*
0867          * Compute difference between actual and desired value.
0868          */
0869         if ((wdiff = *b ^ val)) {
0870             /*
0871              * Different, compute first wrong bit and return.
0872              */
0873             xfs_trans_brelse(tp, bp);
0874             i += XFS_RTLOBIT(wdiff);
0875             *new = start + i;
0876             *stat = 0;
0877             return 0;
0878         }
0879         i += XFS_NBWORD;
0880         /*
0881          * Go on to next block if that's where the next word is
0882          * and we need the next word.
0883          */
0884         if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
0885             /*
0886              * If done with this block, get the next one.
0887              */
0888             xfs_trans_brelse(tp, bp);
0889             error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
0890             if (error) {
0891                 return error;
0892             }
0893             b = bufp = bp->b_addr;
0894             word = 0;
0895         } else {
0896             /*
0897              * Go on to the next word in the buffer.
0898              */
0899             b++;
0900         }
0901     }
0902     /*
0903      * If not ending on a word boundary, deal with the last
0904      * (partial) word.
0905      */
0906     if ((lastbit = len - i)) {
0907         /*
0908          * Mask of relevant bits.
0909          */
0910         mask = ((xfs_rtword_t)1 << lastbit) - 1;
0911         /*
0912          * Compute difference between actual and desired value.
0913          */
0914         if ((wdiff = (*b ^ val) & mask)) {
0915             /*
0916              * Different, compute first wrong bit and return.
0917              */
0918             xfs_trans_brelse(tp, bp);
0919             i += XFS_RTLOBIT(wdiff);
0920             *new = start + i;
0921             *stat = 0;
0922             return 0;
0923         } else
0924             i = len;
0925     }
0926     /*
0927      * Successful, return.
0928      */
0929     xfs_trans_brelse(tp, bp);
0930     *new = start + i;
0931     *stat = 1;
0932     return 0;
0933 }
0934 
0935 #ifdef DEBUG
0936 /*
0937  * Check that the given extent (block range) is allocated already.
0938  */
0939 STATIC int              /* error */
0940 xfs_rtcheck_alloc_range(
0941     xfs_mount_t *mp,        /* file system mount point */
0942     xfs_trans_t *tp,        /* transaction pointer */
0943     xfs_rtblock_t   bno,        /* starting block number of extent */
0944     xfs_extlen_t    len)        /* length of extent */
0945 {
0946     xfs_rtblock_t   new;        /* dummy for xfs_rtcheck_range */
0947     int     stat;
0948     int     error;
0949 
0950     error = xfs_rtcheck_range(mp, tp, bno, len, 0, &new, &stat);
0951     if (error)
0952         return error;
0953     ASSERT(stat);
0954     return 0;
0955 }
0956 #else
0957 #define xfs_rtcheck_alloc_range(m,t,b,l)    (0)
0958 #endif
0959 /*
0960  * Free an extent in the realtime subvolume.  Length is expressed in
0961  * realtime extents, as is the block number.
0962  */
0963 int                 /* error */
0964 xfs_rtfree_extent(
0965     xfs_trans_t *tp,        /* transaction pointer */
0966     xfs_rtblock_t   bno,        /* starting block number to free */
0967     xfs_extlen_t    len)        /* length of extent freed */
0968 {
0969     int     error;      /* error value */
0970     xfs_mount_t *mp;        /* file system mount structure */
0971     xfs_fsblock_t   sb;     /* summary file block number */
0972     struct xfs_buf  *sumbp = NULL;  /* summary file block buffer */
0973 
0974     mp = tp->t_mountp;
0975 
0976     ASSERT(mp->m_rbmip->i_itemp != NULL);
0977     ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
0978 
0979     error = xfs_rtcheck_alloc_range(mp, tp, bno, len);
0980     if (error)
0981         return error;
0982 
0983     /*
0984      * Free the range of realtime blocks.
0985      */
0986     error = xfs_rtfree_range(mp, tp, bno, len, &sumbp, &sb);
0987     if (error) {
0988         return error;
0989     }
0990     /*
0991      * Mark more blocks free in the superblock.
0992      */
0993     xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS, (long)len);
0994     /*
0995      * If we've now freed all the blocks, reset the file sequence
0996      * number to 0.
0997      */
0998     if (tp->t_frextents_delta + mp->m_sb.sb_frextents ==
0999         mp->m_sb.sb_rextents) {
1000         if (!(mp->m_rbmip->i_diflags & XFS_DIFLAG_NEWRTBM))
1001             mp->m_rbmip->i_diflags |= XFS_DIFLAG_NEWRTBM;
1002         *(uint64_t *)&VFS_I(mp->m_rbmip)->i_atime = 0;
1003         xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);
1004     }
1005     return 0;
1006 }
1007 
1008 /* Find all the free records within a given range. */
1009 int
1010 xfs_rtalloc_query_range(
1011     struct xfs_mount        *mp,
1012     struct xfs_trans        *tp,
1013     const struct xfs_rtalloc_rec    *low_rec,
1014     const struct xfs_rtalloc_rec    *high_rec,
1015     xfs_rtalloc_query_range_fn  fn,
1016     void                *priv)
1017 {
1018     struct xfs_rtalloc_rec      rec;
1019     xfs_rtblock_t           rtstart;
1020     xfs_rtblock_t           rtend;
1021     xfs_rtblock_t           high_key;
1022     int             is_free;
1023     int             error = 0;
1024 
1025     if (low_rec->ar_startext > high_rec->ar_startext)
1026         return -EINVAL;
1027     if (low_rec->ar_startext >= mp->m_sb.sb_rextents ||
1028         low_rec->ar_startext == high_rec->ar_startext)
1029         return 0;
1030 
1031     high_key = min(high_rec->ar_startext, mp->m_sb.sb_rextents - 1);
1032 
1033     /* Iterate the bitmap, looking for discrepancies. */
1034     rtstart = low_rec->ar_startext;
1035     while (rtstart <= high_key) {
1036         /* Is the first block free? */
1037         error = xfs_rtcheck_range(mp, tp, rtstart, 1, 1, &rtend,
1038                 &is_free);
1039         if (error)
1040             break;
1041 
1042         /* How long does the extent go for? */
1043         error = xfs_rtfind_forw(mp, tp, rtstart, high_key, &rtend);
1044         if (error)
1045             break;
1046 
1047         if (is_free) {
1048             rec.ar_startext = rtstart;
1049             rec.ar_extcount = rtend - rtstart + 1;
1050 
1051             error = fn(mp, tp, &rec, priv);
1052             if (error)
1053                 break;
1054         }
1055 
1056         rtstart = rtend + 1;
1057     }
1058 
1059     return error;
1060 }
1061 
1062 /* Find all the free records. */
1063 int
1064 xfs_rtalloc_query_all(
1065     struct xfs_mount        *mp,
1066     struct xfs_trans        *tp,
1067     xfs_rtalloc_query_range_fn  fn,
1068     void                *priv)
1069 {
1070     struct xfs_rtalloc_rec      keys[2];
1071 
1072     keys[0].ar_startext = 0;
1073     keys[1].ar_startext = mp->m_sb.sb_rextents - 1;
1074     keys[0].ar_extcount = keys[1].ar_extcount = 0;
1075 
1076     return xfs_rtalloc_query_range(mp, tp, &keys[0], &keys[1], fn, priv);
1077 }
1078 
1079 /* Is the given extent all free? */
1080 int
1081 xfs_rtalloc_extent_is_free(
1082     struct xfs_mount        *mp,
1083     struct xfs_trans        *tp,
1084     xfs_rtblock_t           start,
1085     xfs_extlen_t            len,
1086     bool                *is_free)
1087 {
1088     xfs_rtblock_t           end;
1089     int             matches;
1090     int             error;
1091 
1092     error = xfs_rtcheck_range(mp, tp, start, len, 1, &end, &matches);
1093     if (error)
1094         return error;
1095 
1096     *is_free = matches;
1097     return 0;
1098 }