LCOV - code coverage report
Current view: top level - libgfs2 - rgrp.c (source / functions) Hit Total Coverage
Test: gfs2-utils.info Lines: 410 486 84.4 %
Date: 2023-10-25 12:04:14 Functions: 37 38 97.4 %

          Line data    Source code
       1             : #include "clusterautoconfig.h"
       2             : 
       3             : #include <inttypes.h>
       4             : #include <limits.h>
       5             : #include <stdio.h>
       6             : #include <stdlib.h>
       7             : #include <string.h>
       8             : #include <unistd.h>
       9             : 
      10             : #include "libgfs2.h"
      11             : #include "rgrp.h"
      12             : 
      13             : #define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
      14             : 
      15     2137351 : static void compute_bitmaps(lgfs2_rgrp_t rg, const unsigned bsize)
      16             : {
      17             :         int x;
      18             : 
      19     2137351 :         rg->rt_bits[0].bi_offset = sizeof(struct gfs2_rgrp);
      20     2137351 :         rg->rt_bits[0].bi_start = 0;
      21     2137351 :         rg->rt_bits[0].bi_len = bsize - sizeof(struct gfs2_rgrp);
      22             : 
      23     2860557 :         for (x = 1; x < rg->rt_length; x++) {
      24      723206 :                 rg->rt_bits[x].bi_offset = sizeof(struct gfs2_meta_header);
      25      723206 :                 rg->rt_bits[x].bi_start = rg->rt_bits[x - 1].bi_start + rg->rt_bits[x - 1].bi_len;
      26      723206 :                 rg->rt_bits[x].bi_len = bsize - sizeof(struct gfs2_meta_header);
      27             :         }
      28     2137351 :         x--;
      29     2137351 :         rg->rt_bits[x].bi_len = rg->rt_bitbytes - rg->rt_bits[x].bi_start;
      30     2137351 : }
      31             : 
      32             : /**
      33             :  * lgfs2_compute_bitstructs - Compute the bitmap sizes
      34             :  * bsize: Block size
      35             :  * rgd: The resource group descriptor
      36             :  * Returns: 0 on success, -1 on error
      37             :  */
      38     2130333 : int lgfs2_compute_bitstructs(const uint32_t bsize, struct lgfs2_rgrp_tree *rgd)
      39             : {
      40     2130333 :         uint32_t length = rgd->rt_length;
      41             :         uint32_t bytes_left;
      42     2130333 :         int ownbits = 0;
      43             : 
      44             :         /* Max size of an rg is 2GB.  A 2GB RG with (minimum) 512-byte blocks
      45             :            has 4194304 blocks.  We can represent 4 blocks in one bitmap byte.
      46             :            Therefore, all 4194304 blocks can be represented in 1048576 bytes.
      47             :            Subtract a metadata header for each 512-byte block and we get
      48             :            488 bytes of bitmap per block.  Divide 1048576 by 488 and we can
      49             :            be assured we should never have more than 2149 of them. */
      50     2130333 :         errno = EINVAL;
      51     2130333 :         if (length > 2149 || length == 0)
      52           3 :                 return -1;
      53             : 
      54     2130330 :         if(rgd->rt_bits == NULL) {
      55     2130330 :                 rgd->rt_bits = calloc(length, sizeof(struct lgfs2_bitmap));
      56     2130330 :                 if(rgd->rt_bits == NULL)
      57           0 :                         return -1;
      58     2130330 :                 ownbits = 1;
      59             :         }
      60             : 
      61     2130330 :         compute_bitmaps(rgd, bsize);
      62     2130330 :         bytes_left = rgd->rt_bitbytes - (rgd->rt_bits[rgd->rt_length - 1].bi_start +
      63     2130330 :                                             rgd->rt_bits[rgd->rt_length - 1].bi_len);
      64     2130330 :         errno = EINVAL;
      65     2130330 :         if(bytes_left)
      66           0 :                 goto errbits;
      67             : 
      68     2130330 :         if((rgd->rt_bits[length - 1].bi_start +
      69     2130330 :             rgd->rt_bits[length - 1].bi_len) * GFS2_NBBY != rgd->rt_data)
      70           0 :                 goto errbits;
      71             : 
      72     2130330 :         return 0;
      73           0 : errbits:
      74           0 :         if (ownbits) {
      75           0 :                 free(rgd->rt_bits);
      76           0 :                 rgd->rt_bits = NULL;
      77             :         }
      78           0 :         return -1;
      79             : }
      80             : 
      81             : 
      82             : /**
      83             :  * blk2rgrpd - Find resource group for a given data block number
      84             :  * @sdp: The GFS superblock
      85             :  * @n: The data block number
      86             :  *
      87             :  * Returns: Ths resource group, or NULL if not found
      88             :  */
      89     3956565 : struct lgfs2_rgrp_tree *lgfs2_blk2rgrpd(struct lgfs2_sbd *sdp, uint64_t blk)
      90             : {
      91     3956565 :         struct lgfs2_rgrp_tree *rgd = (struct lgfs2_rgrp_tree *)sdp->rgtree.osi_node;
      92    21668964 :         while (rgd) {
      93    21668964 :                 if (blk < rgd->rt_addr)
      94    17662811 :                         rgd = (struct lgfs2_rgrp_tree *) rgd->rt_node.osi_left;
      95     4006153 :                 else if (blk >= rgd->rt_data0 + rgd->rt_data)
      96       49588 :                         rgd = (struct lgfs2_rgrp_tree *) rgd->rt_node.osi_right;
      97             :                 else
      98     3956565 :                         return rgd;
      99             :         }
     100           0 :         return NULL;
     101             : }
     102             : 
     103             : /**
     104             :  * Allocate a multi-block buffer for a resource group's bitmaps. This is done
     105             :  * as one chunk and should be freed using lgfs2_rgrp_bitbuf_free().
     106             :  * Returns 0 on success with the bitmap buffer allocated in the resource group,
     107             :  * or non-zero on failure with errno set.
     108             :  */
     109        6745 : int lgfs2_rgrp_bitbuf_alloc(lgfs2_rgrp_t rg)
     110             : {
     111        6745 :         struct lgfs2_sbd *sdp = rg->rt_rgrps->rgs_sdp;
     112        6745 :         size_t len = rg->rt_length * sdp->sd_bsize;
     113        6745 :         unsigned long io_align = sdp->sd_bsize;
     114             :         unsigned i;
     115             :         void *bufs;
     116             : 
     117        6745 :         if (rg->rt_rgrps->rgs_align > 0) {
     118         408 :                 len = ROUND_UP(len, rg->rt_rgrps->rgs_align * sdp->sd_bsize);
     119         408 :                 io_align = rg->rt_rgrps->rgs_align_off * sdp->sd_bsize;
     120             :         }
     121        6745 :         if (posix_memalign(&bufs, io_align, len) != 0) {
     122           0 :                 errno = ENOMEM;
     123           0 :                 return 1;
     124             :         }
     125        6745 :         memset(bufs, 0, len);
     126             : 
     127      162536 :         for (i = 0; i < rg->rt_length; i++) {
     128      155791 :                 rg->rt_bits[i].bi_data = (char *)bufs + (i * sdp->sd_bsize);
     129      155791 :                 rg->rt_bits[i].bi_modified = 0;
     130             :         }
     131             :         /* coverity[leaked_storage:SUPPRESS] */
     132        6745 :         return 0;
     133             : }
     134             : 
     135             : /**
     136             :  * Free the multi-block bitmap buffer from a resource group. The buffer should
     137             :  * have been allocated as a single chunk as in lgfs2_rgrp_bitbuf_alloc().
     138             :  * This does not implicitly write the bitmaps to disk. Use lgfs2_rgrp_write()
     139             :  * for that.
     140             :  * rg: The resource groups whose bitmap buffer should be freed.
     141             :  */
     142        6503 : void lgfs2_rgrp_bitbuf_free(lgfs2_rgrp_t rg)
     143             : {
     144             :         unsigned i;
     145             : 
     146        6503 :         free(rg->rt_bits[0].bi_data);
     147      153582 :         for (i = 0; i < rg->rt_length; i++) {
     148      147079 :                 rg->rt_bits[i].bi_data = NULL;
     149      147079 :                 rg->rt_bits[i].bi_modified = 0;
     150             :         }
     151        6503 : }
     152             : 
     153             : /**
     154             :  * Check a resource group's crc
     155             :  * Returns 0 on success, non-zero if crc is bad
     156             :  */
     157       42645 : int lgfs2_rgrp_crc_check(char *buf)
     158             : {
     159       42645 :         int ret = 0;
     160       42645 :         struct gfs2_rgrp *rg = (struct gfs2_rgrp *)buf;
     161       42645 :         __be32 crc = rg->rg_crc;
     162             : 
     163       42645 :         if (crc == 0)
     164           0 :                 return 0;
     165             : 
     166       42645 :         rg->rg_crc = 0;
     167       42645 :         if (be32_to_cpu(crc) != lgfs2_disk_hash(buf, sizeof(struct gfs2_rgrp)))
     168           0 :                 ret = 1;
     169       42645 :         rg->rg_crc = crc;
     170       42645 :         return ret;
     171             : }
     172             : 
     173             : /**
     174             :  * Set the crc of an on-disk resource group
     175             :  */
     176       77291 : void lgfs2_rgrp_crc_set(char *buf)
     177             : {
     178       77291 :         struct gfs2_rgrp *rg = (struct gfs2_rgrp *)buf;
     179             :         uint32_t crc;
     180             : 
     181       77291 :         rg->rg_crc = 0;
     182       77291 :         crc = lgfs2_disk_hash(buf, sizeof(struct gfs2_rgrp));
     183       77291 :         rg->rg_crc = cpu_to_be32(crc);
     184       77291 : }
     185             : 
     186             : /**
     187             :  * lgfs2_rgrp_read - read in the resource group information from disk.
     188             :  * @rgd - resource group structure
     189             :  * returns: 0 if no error, otherwise the block number that failed
     190             :  */
     191       42653 : uint64_t lgfs2_rgrp_read(struct lgfs2_sbd *sdp, struct lgfs2_rgrp_tree *rgd)
     192             : {
     193       42653 :         unsigned length = rgd->rt_length * sdp->sd_bsize;
     194       42653 :         off_t offset = rgd->rt_addr * sdp->sd_bsize;
     195             :         char *buf;
     196             : 
     197       42653 :         if (length == 0 || lgfs2_check_range(sdp, rgd->rt_addr))
     198           0 :                 return -1;
     199             : 
     200       42653 :         buf = calloc(1, length);
     201       42653 :         if (buf == NULL)
     202           0 :                 return -1;
     203             : 
     204       42653 :         if (pread(sdp->device_fd, buf, length, offset) != length) {
     205           0 :                 free(buf);
     206           0 :                 return -1;
     207             :         }
     208             : 
     209     8914828 :         for (unsigned i = 0; i < rgd->rt_length; i++) {
     210     8872183 :                 int mtype = (i ? GFS2_METATYPE_RB : GFS2_METATYPE_RG);
     211             : 
     212     8872183 :                 rgd->rt_bits[i].bi_data = buf + (i * sdp->sd_bsize);
     213     8872183 :                 if (lgfs2_check_meta(rgd->rt_bits[i].bi_data, mtype)) {
     214           8 :                         free(buf);
     215           8 :                         rgd->rt_bits[0].bi_data = NULL;
     216           8 :                         return rgd->rt_addr + i;
     217             :                 }
     218             :         }
     219       42645 :         if (lgfs2_rgrp_crc_check(buf)) {
     220           0 :                 free(buf);
     221           0 :                 return rgd->rt_addr;
     222             :         }
     223       42645 :         lgfs2_rgrp_in(rgd, buf);
     224             :         /* coverity[leaked_storage:SUPPRESS] */
     225       42645 :         return 0;
     226             : }
     227             : 
     228     2168038 : void lgfs2_rgrp_relse(struct lgfs2_sbd *sdp, struct lgfs2_rgrp_tree *rgd)
     229             : {
     230     2168038 :         if (rgd->rt_bits == NULL)
     231         178 :                 return;
     232    13609519 :         for (unsigned i = 0; i < rgd->rt_length; i++) {
     233    11441659 :                 off_t offset = sdp->sd_bsize * (rgd->rt_addr + i);
     234             :                 ssize_t ret;
     235             : 
     236    11441659 :                 if (rgd->rt_bits[i].bi_data == NULL || !rgd->rt_bits[i].bi_modified)
     237    11392848 :                         continue;
     238             : 
     239       48811 :                 ret = pwrite(sdp->device_fd, rgd->rt_bits[i].bi_data,
     240       48811 :                              sdp->sd_bsize, offset);
     241       48811 :                 if (ret != sdp->sd_bsize) {
     242           0 :                         fprintf(stderr, "Failed to write modified resource group at block %"PRIu64": %s\n",
     243           0 :                                 rgd->rt_addr, strerror(errno));
     244             :                 }
     245       48811 :                 rgd->rt_bits[i].bi_modified = 0;
     246             :         }
     247     2167860 :         free(rgd->rt_bits[0].bi_data);
     248    13609519 :         for (unsigned i = 0; i < rgd->rt_length; i++)
     249    11441659 :                 rgd->rt_bits[i].bi_data = NULL;
     250             : }
     251             : 
     252     2130508 : struct lgfs2_rgrp_tree *lgfs2_rgrp_insert(struct osi_root *rgtree, uint64_t rgblock)
     253             : {
     254     2130508 :         struct osi_node **newn = &rgtree->osi_node, *parent = NULL;
     255             :         struct lgfs2_rgrp_tree *data;
     256             : 
     257             :         /* Figure out where to put new node */
     258    29804218 :         while (*newn) {
     259    27673710 :                 struct lgfs2_rgrp_tree *cur = (struct lgfs2_rgrp_tree *)*newn;
     260             : 
     261    27673710 :                 parent = *newn;
     262    27673710 :                 if (rgblock < cur->rt_addr)
     263           6 :                         newn = &((*newn)->osi_left);
     264    27673704 :                 else if (rgblock > cur->rt_addr)
     265    27673704 :                         newn = &((*newn)->osi_right);
     266             :                 else
     267           0 :                         return cur;
     268             :         }
     269             : 
     270     2130508 :         data = calloc(1, sizeof(struct lgfs2_rgrp_tree));
     271     2130508 :         if (!data)
     272           0 :                 return NULL;
     273             :         /* Add new node and rebalance tree. */
     274     2130508 :         data->rt_addr = rgblock;
     275     2130508 :         osi_link_node(&data->rt_node, parent, newn);
     276     2130508 :         osi_insert_color(&data->rt_node, rgtree);
     277             : 
     278     2130508 :         return data;
     279             : }
     280             : 
     281        4545 : void lgfs2_rgrp_free(struct lgfs2_sbd *sdp, struct osi_root *rgrp_tree)
     282             : {
     283             :         struct lgfs2_rgrp_tree *rgd;
     284             :         struct osi_node *n;
     285             : 
     286        4545 :         if (OSI_EMPTY_ROOT(rgrp_tree))
     287           4 :                 return;
     288     2134295 :         while ((n = osi_first(rgrp_tree))) {
     289     2129754 :                 rgd = (struct lgfs2_rgrp_tree *)n;
     290             : 
     291     2129754 :                 lgfs2_rgrp_relse(sdp, rgd);
     292     2129754 :                 free(rgd->rt_bits);
     293     2129754 :                 rgd->rt_bits = NULL;
     294     2129754 :                 osi_erase(&rgd->rt_node, rgrp_tree);
     295     2129754 :                 free(rgd);
     296             :         }
     297             : }
     298             : 
     299         286 : static uint64_t align_block(const uint64_t base, const uint64_t align)
     300             : {
     301         286 :         if ((align > 0) && ((base % align) > 0))
     302          19 :                 return (base - (base % align)) + align;
     303         267 :         return base;
     304             : }
     305             : 
     306             : /**
     307             :  * Calculate the aligned block address of a resource group.
     308             :  * rgs: The resource groups handle
     309             :  * base: The base address of the first resource group address, in blocks
     310             :  * Returns the aligned address of the first resource group.
     311             :  */
     312         140 : uint64_t lgfs2_rgrp_align_addr(const lgfs2_rgrps_t rgs, uint64_t addr)
     313             : {
     314         140 :         return align_block(addr, rgs->rgs_align_off);
     315             : }
     316             : 
     317             : /**
     318             :  * Calculate the aligned relative address of the next resource group (and thus
     319             :  * the aligned length of this one).
     320             :  * rgs: The resource groups handle
     321             :  * base: The base length of the current resource group, in blocks
     322             :  * Returns the length of the resource group (the aligned relative address of
     323             :  * the next one)
     324             :  */
     325         146 : uint32_t lgfs2_rgrp_align_len(const lgfs2_rgrps_t rgs, uint32_t len)
     326             : {
     327         146 :         return align_block(len, rgs->rgs_align) + rgs->rgs_align_off;
     328             : }
     329             : 
     330             : /**
     331             :  * Plan the sizes of resource groups for remaining free space, based on a
     332             :  * target maximum size. In order to make best use of the space while keeping
     333             :  * the resource groups aligned appropriately we need to either reduce the
     334             :  * length of every resource group or of a subset of the resource groups, so
     335             :  * we're left with either one or two resource group sizes. We keep track of
     336             :  * both of these and the numbers of each size of resource group inside the
     337             :  * resource groups descriptor.
     338             :  * rgs: The resource groups descriptor
     339             :  * space: The number of remaining blocks to be allocated
     340             :  * tgtsize: The target resource group size in blocks
     341             :  * Returns the number of resource groups planned to fit in the given space, or
     342             :  * 0 if the smallest resource group would be smaller than GFS2_MIN_RGSIZE.
     343             :  */
     344          76 : uint32_t lgfs2_rgrps_plan(const lgfs2_rgrps_t rgs, uint64_t space, uint32_t tgtsize)
     345             : {
     346          76 :         uint32_t maxlen = (LGFS2_MAX_RGSIZE << 20) / rgs->rgs_sdp->sd_bsize;
     347          76 :         uint32_t minlen = (LGFS2_MIN_RGSIZE << 20) / rgs->rgs_sdp->sd_bsize;
     348          76 :         struct rg_spec *spec = rgs->rgs_plan->rg_specs;
     349             : 
     350             :         /* Apps should already have checked that the rg size is <=
     351             :            GFS2_MAX_RGSIZE but just in case alignment pushes it over we clamp
     352             :            it back down while calculating the initial rgrp length.  */
     353             :         do {
     354          76 :                 spec[0].len = lgfs2_rgrp_align_len(rgs, tgtsize);
     355          76 :                 tgtsize -= (rgs->rgs_align + 1);
     356          76 :         } while (spec[0].len > maxlen);
     357             : 
     358          76 :         spec[0].num = space / spec[0].len;
     359             : 
     360          76 :         if ((space - (spec[0].num * spec[0].len)) > rgs->rgs_align) {
     361          76 :                 unsigned adj = (rgs->rgs_align > 0) ? rgs->rgs_align : 1;
     362             : 
     363             :                 /* Spread the adjustment required to fit a new rgrp at the end
     364             :                    over all of the rgrps so that we don't end with a single
     365             :                    tiny one.  */
     366          76 :                 spec[0].num++;
     367      174198 :                 while (((spec[0].len - adj) * (uint64_t)spec[0].num) >= space)
     368      174122 :                         spec[0].len -= adj;
     369             : 
     370             :                 /* We've adjusted the size of the rgrps down as far as we can
     371             :                    without leaving a large gap at the end of the device now,
     372             :                    but we still need to reduce the size of some rgrps in order
     373             :                    to make everything fit, so we use the second rgplan to
     374             :                    specify a second length for a subset of the resource groups.
     375             :                    If plan[0].len already divides the space with no remainder,
     376             :                    plan[1].num will stay 0 and it won't be used.  */
     377          76 :                 spec[1].len = spec[0].len - adj;
     378          76 :                 spec[1].num = 0;
     379             : 
     380          76 :                 while ((((uint64_t)spec[0].len * spec[0].num) +
     381        3345 :                         ((uint64_t)spec[1].len * spec[1].num)) >= space) {
     382             :                         /* Total number of rgrps stays constant now. We just
     383             :                            need to shift some weight around */
     384        3269 :                         spec[0].num--;
     385        3269 :                         spec[1].num++;
     386             :                 }
     387             :         }
     388             : 
     389             :         /* Once we've reached this point,
     390             :            (spec[0].num * spec[0].len) + (spec[1].num * spec[1].len)
     391             :            will be less than one adjustment smaller than 'space'.  */
     392          76 :         if (spec[0].len < minlen)
     393           1 :                 return 0;
     394             : 
     395          75 :         return spec[0].num + spec[1].num;
     396             : }
     397             : 
     398             : /**
     399             :  * Create and initialise an empty set of resource groups
     400             :  * bsize: The block size of the fs
     401             :  * devlen: The length of the device, in fs blocks
     402             :  * align: The required stripe alignment of the resource groups. Must be a multiple of 'offset'.
     403             :  * offset: The required stripe offset of the resource groups
     404             :  * Returns an initialised lgfs2_rgrps_t or NULL if unsuccessful with errno set
     405             :  */
     406          82 : lgfs2_rgrps_t lgfs2_rgrps_init(struct lgfs2_sbd *sdp, uint64_t align, uint64_t offset)
     407             : {
     408             :         lgfs2_rgrps_t rgs;
     409             : 
     410          82 :         errno = EINVAL;
     411          82 :         if (offset != 0 && (align % offset) != 0)
     412           0 :                 return NULL;
     413             : 
     414          82 :         rgs = calloc(1, sizeof(*rgs));
     415          82 :         if (rgs == NULL)
     416           0 :                 return NULL;
     417             : 
     418          82 :         rgs->rgs_plan = calloc(1, sizeof(struct rgs_plan) + (5 * sizeof(struct rg_spec)));
     419          82 :         if (rgs->rgs_plan == NULL) {
     420           0 :                 free(rgs);
     421           0 :                 return NULL;
     422             :         }
     423          82 :         rgs->rgs_plan->length = 0;
     424          82 :         rgs->rgs_plan->capacity = 5;
     425          82 :         rgs->rgs_sdp = sdp;
     426          82 :         rgs->rgs_align = align;
     427          82 :         rgs->rgs_align_off = offset;
     428          82 :         memset(&rgs->rgs_root, 0, sizeof(rgs->rgs_root));
     429             : 
     430          82 :         return rgs;
     431             : }
     432             : 
     433             : /**
     434             :  * Populate a set of resource groups from a gfs2 rindex file.
     435             :  * fd: An open file descriptor for the rindex file.
     436             :  * rgs: The set of resource groups.
     437             :  * Returns the number of resource groups added to the set or 0 on error with
     438             :  * errno set.
     439             :  */
     440           0 : unsigned lgfs2_rindex_read_fd(int fd, lgfs2_rgrps_t rgs)
     441             : {
     442           0 :         unsigned count = 0;
     443             : 
     444           0 :         errno = EINVAL;
     445           0 :         if (fd < 0 || rgs == NULL)
     446           0 :                 return 0;
     447             : 
     448           0 :         while (1) {
     449             :                 lgfs2_rgrp_t rg;
     450             :                 struct gfs2_rindex ri;
     451           0 :                 ssize_t ret = read(fd, &ri, sizeof(ri));
     452           0 :                 if (ret == 0)
     453           0 :                         break;
     454             : 
     455           0 :                 if (ret != sizeof(ri))
     456           0 :                         return 0;
     457             : 
     458           0 :                 rg = lgfs2_rgrps_append(rgs, &ri, 0);
     459           0 :                 if (rg == NULL)
     460           0 :                         return 0;
     461           0 :                 count++;
     462             :         }
     463           0 :         return count;
     464             : }
     465             : 
     466             : /**
     467             :  * Read a rindex entry into a set of resource groups
     468             :  * rip: The inode of the rindex file
     469             :  * rgs: The set of resource groups.
     470             :  * i: The index of the entry to read from the rindex file
     471             :  * Returns the new rindex entry added to the set or NULL on error with errno
     472             :  * set.
     473             :  */
     474         346 : lgfs2_rgrp_t lgfs2_rindex_read_one(struct lgfs2_inode *rip, lgfs2_rgrps_t rgs, unsigned i)
     475             : {
     476         346 :         uint64_t off = i * sizeof(struct gfs2_rindex);
     477             :         struct gfs2_rindex ri;
     478             :         lgfs2_rgrp_t rg;
     479             :         int ret;
     480             : 
     481         346 :         errno = EINVAL;
     482         346 :         if (rip == NULL || rgs == NULL)
     483           0 :                 return NULL;
     484             : 
     485         346 :         ret = lgfs2_readi(rip, &ri, off, sizeof(struct gfs2_rindex));
     486         346 :         if (ret != sizeof(struct gfs2_rindex))
     487           0 :                 return NULL;
     488             : 
     489         346 :         rg = lgfs2_rgrps_append(rgs, &ri, 0);
     490         346 :         if (rg == NULL)
     491           0 :                 return NULL;
     492             : 
     493         346 :         return rg;
     494             : }
     495             : 
     496             : /**
     497             :  * Free a set of resource groups created with lgfs2_rgrps_append() etc. This
     498             :  * does not write any dirty buffers to disk. See lgfs2_rgrp_write().
     499             :  * rgs: A pointer to the set of resource groups to be freed.
     500             :  */
     501          82 : void lgfs2_rgrps_free(lgfs2_rgrps_t *rgs)
     502             : {
     503             :         lgfs2_rgrp_t rg;
     504          82 :         struct osi_root *tree = &(*rgs)->rgs_root;
     505             : 
     506        7103 :         while ((rg = (struct lgfs2_rgrp_tree *)osi_first(tree))) {
     507             :                 int i;
     508        7021 :                 free(rg->rt_bits[0].bi_data);
     509      161201 :                 for (i = 0; i < rg->rt_length; i++) {
     510      154180 :                         rg->rt_bits[i].bi_data = NULL;
     511             :                 }
     512        7021 :                 osi_erase(&rg->rt_node, tree);
     513        7021 :                 free(rg);
     514             :         }
     515          82 :         free((*rgs)->rgs_plan);
     516          82 :         free(*rgs);
     517          82 :         *rgs = NULL;
     518          82 : }
     519             : 
     520             : /**
     521             :  * Given a number of blocks in a resource group, return the number of blocks
     522             :  * needed for bitmaps. Also calculate the adjusted number of free data blocks
     523             :  * in the resource group and store it in *ri_data.
     524             :  */
     525        9427 : uint32_t lgfs2_rgblocks2bitblocks(const unsigned int bsize, const uint32_t rgblocks, uint32_t *ri_data)
     526             : {
     527        9427 :         uint32_t mappable = 0;
     528        9427 :         uint32_t bitblocks = 0;
     529             :         /* Number of blocks mappable by bitmap blocks with these header types */
     530        9427 :         const uint32_t blks_rgrp = GFS2_NBBY * (bsize - sizeof(struct gfs2_rgrp));
     531        9427 :         const uint32_t blks_meta = GFS2_NBBY * (bsize - sizeof(struct gfs2_meta_header));
     532             : 
     533      155346 :         while (blks_rgrp + (blks_meta * bitblocks) < ((rgblocks - bitblocks) & ~(uint32_t)3))
     534      145919 :                 bitblocks++;
     535             : 
     536        9427 :         if (bitblocks > 0)
     537        4941 :                 mappable = blks_rgrp + (blks_meta * (bitblocks - 1));
     538             : 
     539        9427 :         *ri_data = (rgblocks - (bitblocks + 1)) & ~(uint32_t)3;
     540        9427 :         if (mappable < *ri_data)
     541        9427 :                 bitblocks++;
     542             : 
     543        9427 :         return bitblocks;
     544             : }
     545             : 
     546             : /**
     547             :  * Calculate the fields for a new entry in the resource group index.
     548             :  * ri: A pointer to the resource group index entry to be calculated.
     549             :  * addr: The address at which to place this resource group
     550             :  * len: The required length of the resource group, in fs blocks.
     551             :  *        If rglen is 0, geometry previously calculated by lgfs2_rgrps_plan() will be used.
     552             :  * Returns the calculated address of the next resource group or 0 with errno set:
     553             :  *   EINVAL - The entry pointer is NULL
     554             :  *   ENOSPC - This rgrp would extend past the end of the device
     555             :  */
     556        6747 : uint64_t lgfs2_rindex_entry_new(lgfs2_rgrps_t rgs, struct gfs2_rindex *ri, uint64_t addr, uint32_t len)
     557             : {
     558        6747 :         struct rg_spec *spec = rgs->rgs_plan->rg_specs;
     559             :         uint32_t ri_length, ri_data;
     560        6747 :         int plan = -1;
     561        6747 :         errno = EINVAL;
     562        6747 :         if (!ri)
     563           0 :                 return 0;
     564             : 
     565        6747 :         errno = ENOSPC;
     566        6747 :         if (spec[0].num > 0)
     567        3341 :                 plan = 0;
     568        3406 :         else if (spec[1].num > 0)
     569        3257 :                 plan = 1;
     570         149 :         else if (len == 0)
     571          72 :                 return 0;
     572             : 
     573        6675 :         if (plan >= 0 && (len == 0 || len == spec[plan].len)) {
     574        6594 :                 len = spec[plan].len;
     575        6594 :                 spec[plan].num--;
     576             :         }
     577             : 
     578        6675 :         if (addr + len > rgs->rgs_sdp->device.length)
     579           0 :                 return 0;
     580             : 
     581        6675 :         ri_length = lgfs2_rgblocks2bitblocks(rgs->rgs_sdp->sd_bsize, len, &ri_data);
     582        6675 :         ri->ri_addr = cpu_to_be64(addr);
     583        6675 :         ri->ri_length = cpu_to_be32(ri_length);
     584        6675 :         ri->ri_data = cpu_to_be32(ri_data);
     585        6675 :         ri->__pad = 0;
     586        6675 :         ri->ri_data0 = cpu_to_be64(addr + ri_length);
     587        6675 :         ri->ri_bitbytes = cpu_to_be32(ri_data / GFS2_NBBY);
     588        6675 :         memset(&ri->ri_reserved, 0, sizeof(ri->ri_reserved));
     589             : 
     590        6675 :         return addr + len;
     591             : }
     592             : 
     593             : /**
     594             :  * Returns the total resource group size, in blocks, required to give blksreq data blocks
     595             :  */
     596          70 : unsigned lgfs2_rgsize_for_data(uint64_t blksreq, unsigned bsize)
     597             : {
     598          70 :         const uint32_t blks_rgrp = GFS2_NBBY * (bsize - sizeof(struct gfs2_rgrp));
     599          70 :         const uint32_t blks_meta = GFS2_NBBY * (bsize - sizeof(struct gfs2_meta_header));
     600          70 :         unsigned bitblocks = 1;
     601          70 :         blksreq = (blksreq + 3) & ~3;
     602          70 :         if (blksreq > blks_rgrp)
     603          66 :                 bitblocks += ((blksreq - blks_rgrp) + blks_meta - 1) / blks_meta;
     604          70 :         return bitblocks + blksreq;
     605             : }
     606             : 
     607             : // Temporary function to aid in API migration
     608          72 : void lgfs2_attach_rgrps(struct lgfs2_sbd *sdp, lgfs2_rgrps_t rgs)
     609             : {
     610          72 :         sdp->rgtree.osi_node = rgs->rgs_root.osi_node;
     611          72 : }
     612             : 
     613             : /**
     614             :  * Insert a new resource group after the last resource group in a set.
     615             :  * rgs: The set of resource groups
     616             :  * entry: The entry to be added
     617             :  * rg_skip: The value to be used for this resource group's rg_skip field
     618             :  * Returns the new resource group on success or NULL on failure with errno set.
     619             :  */
     620        7021 : lgfs2_rgrp_t lgfs2_rgrps_append(lgfs2_rgrps_t rgs, struct gfs2_rindex *entry, uint32_t rg_skip)
     621             : {
     622             :         lgfs2_rgrp_t rg;
     623        7021 :         struct osi_node **link = &rgs->rgs_root.osi_node;
     624        7021 :         struct osi_node *parent = osi_last(&rgs->rgs_root);
     625        7021 :         lgfs2_rgrp_t lastrg = (lgfs2_rgrp_t)parent;
     626             : 
     627        7021 :         errno = EINVAL;
     628        7021 :         if (entry == NULL)
     629           0 :                 return NULL;
     630             : 
     631        7021 :         if (lastrg != NULL) { /* Tree is not empty */
     632        6939 :                 if (be64_to_cpu(entry->ri_addr) <= lastrg->rt_addr)
     633           0 :                         return NULL; /* Appending with a lower address doesn't make sense */
     634        6939 :                 link = &lastrg->rt_node.osi_right;
     635             :         }
     636             : 
     637        7021 :         rg = calloc(1, sizeof(*rg) + (be32_to_cpu(entry->ri_length) * sizeof(struct lgfs2_bitmap)));
     638        7021 :         if (rg == NULL)
     639           0 :                 return NULL;
     640             : 
     641        7021 :         rg->rt_bits = (struct lgfs2_bitmap *)(rg + 1);
     642             : 
     643        7021 :         osi_link_node(&rg->rt_node, parent, link);
     644        7021 :         osi_insert_color(&rg->rt_node, &rgs->rgs_root);
     645             : 
     646        7021 :         rg->rt_addr = be64_to_cpu(entry->ri_addr);
     647        7021 :         rg->rt_length = be32_to_cpu(entry->ri_length);
     648        7021 :         rg->rt_data0 = rg->rt_rg_data0 = be64_to_cpu(entry->ri_data0);
     649        7021 :         rg->rt_data = rg->rt_rg_data = be32_to_cpu(entry->ri_data);
     650        7021 :         rg->rt_bitbytes = rg->rt_rg_bitbytes = be32_to_cpu(entry->ri_bitbytes);
     651        7021 :         rg->rt_flags = 0;
     652        7021 :         rg->rt_free = be32_to_cpu(entry->ri_data);
     653        7021 :         rg->rt_dinodes = 0;
     654        7021 :         rg->rt_skip = rg_skip;
     655        7021 :         rg->rt_igeneration = 0;
     656        7021 :         compute_bitmaps(rg, rgs->rgs_sdp->sd_bsize);
     657        7021 :         rg->rt_rgrps = rgs;
     658        7021 :         return rg;
     659             : }
     660             : 
     661             : /**
     662             :  * Write a resource group to a file descriptor.
     663             :  * Returns 0 on success or non-zero on failure with errno set
     664             :  */
     665        6501 : int lgfs2_rgrp_write(int fd, const lgfs2_rgrp_t rg)
     666             : {
     667        6501 :         struct lgfs2_sbd *sdp = rg->rt_rgrps->rgs_sdp;
     668             :         unsigned int i;
     669        6501 :         int freebufs = 0;
     670             :         ssize_t ret;
     671             :         size_t len;
     672             : 
     673        6501 :         if (rg->rt_bits[0].bi_data == NULL) {
     674        6422 :                 freebufs = 1;
     675        6422 :                 if (lgfs2_rgrp_bitbuf_alloc(rg) != 0)
     676           0 :                         return -1;
     677             :         }
     678        6501 :         lgfs2_rgrp_out(rg, rg->rt_bits[0].bi_data);
     679      147075 :         for (i = 1; i < rg->rt_length; i++) {
     680      140574 :                 struct gfs2_meta_header *mh = (void *) rg->rt_bits[i].bi_data;
     681             : 
     682      140574 :                 mh->mh_magic = cpu_to_be32(GFS2_MAGIC);
     683      140574 :                 mh->mh_type = cpu_to_be32(GFS2_METATYPE_RB);
     684      140574 :                 mh->mh_format = cpu_to_be32(GFS2_FORMAT_RB);
     685             :         }
     686             : 
     687        6501 :         len = sdp->sd_bsize * rg->rt_length;
     688        6501 :         if (rg->rt_rgrps->rgs_align > 0)
     689         408 :                 len = ROUND_UP(len, rg->rt_rgrps->rgs_align * sdp->sd_bsize);
     690             : 
     691        6501 :         ret = pwrite(fd, rg->rt_bits[0].bi_data, len,
     692        6501 :                      rg->rt_addr * sdp->sd_bsize);
     693             : 
     694        6501 :         if (freebufs)
     695        6422 :                 lgfs2_rgrp_bitbuf_free(rg);
     696             : 
     697        6501 :         return ret == len ? 0 : -1;
     698             : }
     699             : 
     700             : /**
     701             :  * Write the final resource group with rg_skip == 0.
     702             :  * If there is no bitmap data attached to the rg then the block after the
     703             :  * header will be zeroed.
     704             :  * fd: The file descriptor to write to
     705             :  * rgs: The set of resource groups
     706             :  */
     707          72 : int lgfs2_rgrps_write_final(int fd, lgfs2_rgrps_t rgs)
     708             : {
     709          72 :         lgfs2_rgrp_t rg = lgfs2_rgrp_last(rgs);
     710             : 
     711          72 :         rg->rt_skip = 0;
     712          72 :         if (lgfs2_rgrp_write(fd, rg) != 0)
     713           1 :                 return -1;
     714          71 :         return 0;
     715             : }
     716             : 
     717          13 : lgfs2_rgrp_t lgfs2_rgrp_first(lgfs2_rgrps_t rgs)
     718             : {
     719          13 :         return (lgfs2_rgrp_t)osi_first(&rgs->rgs_root);
     720             : }
     721             : 
     722         346 : lgfs2_rgrp_t lgfs2_rgrp_next(lgfs2_rgrp_t rg)
     723             : {
     724         346 :         return (lgfs2_rgrp_t)osi_next(&rg->rt_node);
     725             : }
     726             : 
     727        6429 : lgfs2_rgrp_t lgfs2_rgrp_prev(lgfs2_rgrp_t rg)
     728             : {
     729        6429 :         return (lgfs2_rgrp_t)osi_prev(&rg->rt_node);
     730             : }
     731             : 
     732          73 : lgfs2_rgrp_t lgfs2_rgrp_last(lgfs2_rgrps_t rgs)
     733             : {
     734          73 :         return (lgfs2_rgrp_t)osi_last(&rgs->rgs_root);
     735             : }
     736             : 
     737             : /**
     738             :  * gfs2_rbm_from_block - Set the rbm based upon rgd and block number
     739             :  * @rbm: The rbm with rgd already set correctly
     740             :  * @block: The block number (filesystem relative)
     741             :  *
     742             :  * This sets the bi and offset members of an rbm based on a
     743             :  * resource group and a filesystem relative block number. The
     744             :  * resource group must be set in the rbm on entry, the bi and
     745             :  * offset members will be set by this function.
     746             :  *
     747             :  * Returns: 0 on success, or non-zero with errno set
     748             :  */
     749     2427409 : int lgfs2_rbm_from_block(struct lgfs2_rbm *rbm, uint64_t block)
     750             : {
     751     2427409 :         uint64_t rblock = block - rbm->rgd->rt_data0;
     752     2427409 :         struct lgfs2_sbd *sdp = rbm->rgd->rt_rgrps->rgs_sdp;
     753             : 
     754     2427409 :         if (rblock > UINT_MAX) {
     755           0 :                 errno = EINVAL;
     756           0 :                 return 1;
     757             :         }
     758     2427409 :         if (block >= rbm->rgd->rt_data0 + rbm->rgd->rt_data) {
     759           1 :                 errno = E2BIG;
     760           1 :                 return 1;
     761             :         }
     762             : 
     763     2427408 :         rbm->bii = 0;
     764     2427408 :         rbm->offset = (uint32_t)(rblock);
     765             :         /* Check if the block is within the first block */
     766     2427408 :         if (rbm->offset < (rbm_bi(rbm)->bi_len * GFS2_NBBY))
     767      967724 :                 return 0;
     768             : 
     769             :         /* Adjust for the size diff between gfs2_meta_header and gfs2_rgrp */
     770     1459684 :         rbm->offset += (sizeof(struct gfs2_rgrp) -
     771             :                         sizeof(struct gfs2_meta_header)) * GFS2_NBBY;
     772     1459684 :         rbm->bii = rbm->offset / sdp->sd_blocks_per_bitmap;
     773     1459684 :         rbm->offset -= rbm->bii * sdp->sd_blocks_per_bitmap;
     774     1459684 :         return 0;
     775             : }
     776             : 
     777             : /**
     778             :  * lgfs2_rbm_incr - increment an rbm structure
     779             :  * @rbm: The rbm with rgd already set correctly
     780             :  *
     781             :  * This function takes an existing rbm structure and increments it to the next
     782             :  * viable block offset.
     783             :  *
     784             :  * Returns: If incrementing the offset would cause the rbm to go past the
     785             :  *          end of the rgrp, true is returned, otherwise false.
     786             :  *
     787             :  */
     788       19197 : static int lgfs2_rbm_incr(struct lgfs2_rbm *rbm)
     789             : {
     790       19197 :         if (rbm->offset + 1 < (rbm_bi(rbm)->bi_len * GFS2_NBBY)) { /* in the same bitmap */
     791       19197 :                 rbm->offset++;
     792       19197 :                 return 0;
     793             :         }
     794           0 :         if (rbm->bii == rbm->rgd->rt_length - 1) /* at the last bitmap */
     795           0 :                 return 1;
     796             : 
     797           0 :         rbm->offset = 0;
     798           0 :         rbm->bii++;
     799           0 :         return 0;
     800             : }
     801             : 
     802             : /**
     803             :  * lgfs2_testbit - test a bit in the bitmaps
     804             :  * @rbm: The bit to test
     805             :  *
     806             :  * Returns: The two bit block state of the requested bit
     807             :  */
     808     2430413 : static inline uint8_t lgfs2_testbit(const struct lgfs2_rbm *rbm)
     809             : {
     810     2430413 :         struct lgfs2_bitmap *bi = rbm_bi(rbm);
     811     2430413 :         const uint8_t *buffer = (uint8_t *)bi->bi_data + bi->bi_offset;
     812             :         const uint8_t *byte;
     813             :         unsigned int bit;
     814             : 
     815     2430413 :         byte = buffer + (rbm->offset / GFS2_NBBY);
     816     2430413 :         bit = (rbm->offset % GFS2_NBBY) * GFS2_BIT_SIZE;
     817             : 
     818     2430413 :         return (*byte >> bit) & GFS2_BIT_MASK;
     819             : }
     820             : 
     821             : /**
     822             :  * lgfs2_unaligned_extlen - Look for free blocks which are not byte aligned
     823             :  * @rbm: Position to search (value/result)
     824             :  * @n_unaligned: Number of unaligned blocks to check
     825             :  * @len: Decremented for each block found (terminate on zero)
     826             :  *
     827             :  * Returns: true if a non-free block is encountered
     828             :  */
     829       19198 : static int lgfs2_unaligned_extlen(struct lgfs2_rbm *rbm, uint32_t n_unaligned, uint32_t *len)
     830             : {
     831             :         uint32_t n;
     832             :         uint8_t res;
     833             : 
     834       38395 :         for (n = 0; n < n_unaligned; n++) {
     835       38395 :                 res = lgfs2_testbit(rbm);
     836       38395 :                 if (res != GFS2_BLKST_FREE)
     837           0 :                         return 1;
     838       38395 :                 (*len)--;
     839       38395 :                 if (*len == 0)
     840       19198 :                         return 1;
     841       19197 :                 if (lgfs2_rbm_incr(rbm))
     842           0 :                         return 1;
     843             :         }
     844             : 
     845           0 :         return 0;
     846             : }
     847             : 
     848       35314 : static uint8_t *check_bytes8(const uint8_t *start, uint8_t value, unsigned bytes)
     849             : {
     850    81923317 :         while (bytes) {
     851    81888003 :                 if (*start != value)
     852           0 :                         return (void *)start;
     853    81888003 :                 start++;
     854    81888003 :                 bytes--;
     855             :         }
     856       35314 :         return NULL;
     857             : }
     858             : 
     859             : /**
     860             :  * lgfs2_free_extlen - Return extent length of free blocks
     861             :  * @rbm: Starting position
     862             :  * @len: Max length to check
     863             :  *
     864             :  * Starting at the block specified by the rbm, see how many free blocks
     865             :  * there are, not reading more than len blocks ahead. This can be done
     866             :  * using check_bytes8 when the blocks are byte aligned, but has to be done
     867             :  * on a block by block basis in case of unaligned blocks. Also this
     868             :  * function can cope with bitmap boundaries (although it must stop on
     869             :  * a resource group boundary)
     870             :  *
     871             :  * Returns: Number of free blocks in the extent
     872             :  */
     873       25597 : static uint32_t lgfs2_free_extlen(const struct lgfs2_rbm *rrbm, uint32_t len)
     874             : {
     875       25597 :         struct lgfs2_rbm rbm = *rrbm;
     876       25597 :         uint32_t n_unaligned = rbm.offset & 3;
     877       25597 :         uint32_t size = len;
     878             :         uint32_t bytes;
     879             :         uint32_t chunk_size;
     880             :         uint8_t *ptr, *start, *end;
     881             :         uint64_t block;
     882             :         struct lgfs2_bitmap *bi;
     883       25597 :         struct lgfs2_sbd *sdp = rbm.rgd->rt_rgrps->rgs_sdp;
     884             : 
     885       25598 :         if (n_unaligned &&
     886           1 :             lgfs2_unaligned_extlen(&rbm, 4 - n_unaligned, &len))
     887           1 :                 goto out;
     888             : 
     889       25596 :         n_unaligned = len & 3;
     890             :         /* Start is now byte aligned */
     891       60909 :         while (len > 3) {
     892       35314 :                 bi = rbm_bi(&rbm);
     893       35314 :                 start = (uint8_t *)bi->bi_data;
     894       35314 :                 end = start + sdp->sd_bsize;
     895       35314 :                 start += bi->bi_offset;
     896       35314 :                 start += (rbm.offset / GFS2_NBBY);
     897       35314 :                 bytes = (len / GFS2_NBBY) < (end - start) ? (len / GFS2_NBBY):(end - start);
     898       35314 :                 ptr = check_bytes8(start, 0, bytes);
     899       35314 :                 chunk_size = ((ptr == NULL) ? bytes : (ptr - start));
     900       35314 :                 chunk_size *= GFS2_NBBY;
     901       35314 :                 len -= chunk_size;
     902       35314 :                 block = lgfs2_rbm_to_block(&rbm);
     903       35314 :                 if (lgfs2_rbm_from_block(&rbm, block + chunk_size)) {
     904           1 :                         n_unaligned = 0;
     905           1 :                         break;
     906             :                 }
     907       35313 :                 if (ptr) {
     908           0 :                         n_unaligned = 3;
     909           0 :                         break;
     910             :                 }
     911       35313 :                 n_unaligned = len & 3;
     912             :         }
     913             : 
     914             :         /* Deal with any bits left over at the end */
     915       25596 :         if (n_unaligned)
     916       19197 :                 lgfs2_unaligned_extlen(&rbm, n_unaligned, &len);
     917        6399 : out:
     918       25597 :         return size - len;
     919             : }
     920             : 
     921             : /**
     922             :  * gfs2_rbm_find - Look for blocks of a particular state
     923             :  * @rbm: Value/result starting position and final position
     924             :  * @state: The state which we want to find
     925             :  * @minext: Pointer to the requested extent length (NULL for a single block)
     926             :  *          This is updated to be the actual reservation size.
     927             :  *
     928             :  * Returns: 0 on success, non-zero with errno == ENOSPC if there is no block of the requested state
     929             :  */
     930       25598 : int lgfs2_rbm_find(struct lgfs2_rbm *rbm, uint8_t state, uint32_t *minext)
     931             : {
     932             :         int initial_bii;
     933             :         uint32_t offset;
     934       25598 :         int n = 0;
     935       25598 :         int iters = rbm->rgd->rt_length;
     936             :         uint32_t extlen;
     937             : 
     938             :         /* If we are not starting at the beginning of a bitmap, then we
     939             :          * need to add one to the bitmap count to ensure that we search
     940             :          * the starting bitmap twice.
     941             :          */
     942       25598 :         if (rbm->offset != 0)
     943           0 :                 iters++;
     944             : 
     945       25600 :         for (n = 0; n < iters; n++) {
     946       25600 :                 struct lgfs2_bitmap *bi = rbm_bi(rbm);
     947       25600 :                 uint8_t *buf = (uint8_t *)bi->bi_data + bi->bi_offset;
     948             :                 uint64_t block;
     949             :                 int ret;
     950             : 
     951       25600 :                 if ((rbm->rgd->rt_free < *minext) && (state == GFS2_BLKST_FREE))
     952           2 :                         goto next_bitmap;
     953             : 
     954       25598 :                 offset = lgfs2_bitfit(buf, bi->bi_len, rbm->offset, state);
     955       25598 :                 if (offset == LGFS2_BFITNOENT)
     956           1 :                         goto next_bitmap;
     957             : 
     958       25597 :                 rbm->offset = offset;
     959       25597 :                 initial_bii = rbm->bii;
     960       25597 :                 block = lgfs2_rbm_to_block(rbm);
     961       25597 :                 extlen = 1;
     962             : 
     963       25597 :                 if (*minext != 0)
     964       25597 :                         extlen = lgfs2_free_extlen(rbm, *minext);
     965             : 
     966       25597 :                 if (extlen >= *minext)
     967       25597 :                         return 0;
     968             : 
     969           0 :                 ret = lgfs2_rbm_from_block(rbm, block + extlen);
     970           0 :                 if (ret == 0) {
     971           0 :                         n += (rbm->bii - initial_bii);
     972           0 :                         continue;
     973             :                 }
     974             : 
     975           0 :                 if (errno == E2BIG) {
     976           0 :                         rbm->bii = 0;
     977           0 :                         rbm->offset = 0;
     978           0 :                         n += (rbm->bii - initial_bii);
     979           0 :                         goto res_covered_end_of_rgrp;
     980             :                 }
     981             : 
     982           0 :                 return ret;
     983             : 
     984           3 : next_bitmap:    /* Find next bitmap in the rgrp */
     985           3 :                 rbm->offset = 0;
     986           3 :                 rbm->bii++;
     987           3 :                 if (rbm->bii == rbm->rgd->rt_length)
     988           1 :                         rbm->bii = 0;
     989             : 
     990           2 : res_covered_end_of_rgrp:
     991           3 :                 if (rbm->bii == 0)
     992           1 :                         break;
     993             :         }
     994             : 
     995           1 :         errno = ENOSPC;
     996           1 :         return 1;
     997             : }
     998             : 
     999             : /**
    1000             :  * lgfs2_alloc_extent - allocate an extent from a given bitmap
    1001             :  * @rbm: the resource group information
    1002             :  * @state: The state of the first block, GFS2_BLKST_DINODE or GFS2_BLKST_USED
    1003             :  * @elen: The requested extent length
    1004             :  * Returns the length of the extent allocated.
    1005             :  */
    1006          77 : unsigned lgfs2_alloc_extent(const struct lgfs2_rbm *rbm, int state, const unsigned elen)
    1007             : {
    1008          77 :         struct lgfs2_rbm pos = { .rgd = rbm->rgd, };
    1009          77 :         const uint64_t block = lgfs2_rbm_to_block(rbm);
    1010             :         unsigned len;
    1011             : 
    1012          77 :         lgfs2_set_bitmap(rbm->rgd, block, state);
    1013             : 
    1014     2392095 :         for (len = 1; len < elen; len++) {
    1015     2392018 :                 int ret = lgfs2_rbm_from_block(&pos, block + len);
    1016     2392018 :                 if (ret || lgfs2_testbit(&pos) != GFS2_BLKST_FREE)
    1017             :                         break;
    1018     2392018 :                 lgfs2_set_bitmap(pos.rgd, block + len, GFS2_BLKST_USED);
    1019             :         }
    1020          77 :         return len;
    1021             : }

Generated by: LCOV version 1.14