LCOV - code coverage report
Current view: top level - libgfs2 - fs_bits.c (source / functions) Hit Total Coverage
Test: gfs2-utils.info Lines: 65 75 86.7 %
Date: 2023-10-25 12:04:14 Functions: 5 5 100.0 %

          Line data    Source code
       1             : #include "clusterautoconfig.h"
       2             : 
       3             : #include <inttypes.h>
       4             : #include <stdlib.h>
       5             : #include <string.h>
       6             : #include <unistd.h>
       7             : #include <limits.h>
       8             : 
       9             : #include "libgfs2.h"
      10             : 
      11             : #if BITS_PER_LONG == 32
      12             : #define LBITMASK   (0x55555555UL)
      13             : #define LBITSKIP55 (0x55555555UL)
      14             : #define LBITSKIP00 (0x00000000UL)
      15             : #else
      16             : #define LBITMASK   (0x5555555555555555UL)
      17             : #define LBITSKIP55 (0x5555555555555555UL)
      18             : #define LBITSKIP00 (0x0000000000000000UL)
      19             : #endif
      20             : 
      21             : #define ALIGN(x,a) (((x)+(a)-1)&~((a)-1))
      22             : 
      23             : /**
      24             :  * bit_search
      25             :  * @ptr: Pointer to bitmap data
      26             :  * @mask: Mask to use (normally 0x55555.... but adjusted for search start)
      27             :  * @state: The state we are searching for
      28             :  *
      29             :  * We xor the bitmap data with a patter which is the bitwise opposite
      30             :  * of what we are looking for, this gives rise to a pattern of ones
      31             :  * wherever there is a match. Since we have two bits per entry, we
      32             :  * take this pattern, shift it down by one place and then and it with
      33             :  * the original. All the even bit positions (0,2,4, etc) then represent
      34             :  * successful matches, so we mask with 0x55555..... to remove the unwanted
      35             :  * odd bit positions.
      36             :  *
      37             :  * This allows searching of a whole u64 at once (32 blocks) with a
      38             :  * single test (on 64 bit arches).
      39             :  */
      40             : 
      41    38698224 : static inline uint64_t bit_search(const __le64 *ptr,
      42             :                                        unsigned long long mask,
      43             :                                        uint8_t state)
      44             : {
      45             :         unsigned long long tmp;
      46             :         static const unsigned long long search[] = {
      47             :                 [0] = 0xffffffffffffffffULL,
      48             :                 [1] = 0xaaaaaaaaaaaaaaaaULL,
      49             :                 [2] = 0x5555555555555555ULL,
      50             :                 [3] = 0x0000000000000000ULL,
      51             :         };
      52    38698224 :         tmp = le64_to_cpu(*ptr) ^ search[state];
      53    38698224 :         tmp &= (tmp >> 1);
      54    38698224 :         tmp &= mask;
      55    38698224 :         return tmp;
      56             : }
      57             : 
      58             : /**
      59             :  * lgfs2_bitfit - Find a free block in the bitmaps
      60             :  * @buffer: the buffer that holds the bitmaps
      61             :  * @buflen: the length (in bytes) of the buffer
      62             :  * @goal: the block to try to allocate
      63             :  * @old_state: the state of the block we're looking for
      64             :  *
      65             :  * Return: the block number that was allocated
      66             :  */
      67      320198 : unsigned long lgfs2_bitfit(const unsigned char *buf, const unsigned int len,
      68             :                           unsigned long goal, unsigned char state)
      69             : {
      70      320198 :         uint32_t spoint = (goal << 1) & ((8 * sizeof(uint64_t)) - 1);
      71      320198 :         const __le64 *ptr = ((__le64 *)buf) + (goal >> 5);
      72      320198 :         const __le64 *end = (__le64 *) (buf + ALIGN(len, sizeof(uint64_t)));
      73             :         uint64_t tmp;
      74      320198 :         uint64_t mask = 0x5555555555555555ULL;
      75             :         uint32_t bit;
      76             : 
      77      320198 :         if (state > 3)
      78           0 :                 return 0;
      79             : 
      80             :         /* Mask off bits we don't care about at the start of the search */
      81      320198 :         mask <<= spoint;
      82      320198 :         tmp = bit_search(ptr, mask, state);
      83      320198 :         ptr++;
      84    38698224 :         while(tmp == 0 && ptr < end) {
      85    38378026 :                 tmp = bit_search(ptr, 0x5555555555555555ULL, state);
      86    38378026 :                 ptr++;
      87             :         }
      88             :         /* Mask off any bits which are more than len bytes from the start */
      89      320198 :         if (ptr == end && (len & (sizeof(uint64_t) - 1)))
      90        1794 :                 tmp &= (((uint64_t)~0) >>
      91        1794 :                         (64 - 8 * (len & (sizeof(uint64_t) - 1))));
      92             :         /* Didn't find anything, so return */
      93      320198 :         if (tmp == 0)
      94      223018 :                 return LGFS2_BFITNOENT;
      95       97180 :         ptr--;
      96       97180 :         bit = ffsll(tmp);
      97       97180 :         bit /= 2;       /* two bits per entry in the bitmap */
      98       97180 :         return (((const unsigned char *)ptr - buf) * GFS2_NBBY) + bit;
      99             : }
     100             : 
     101             : /*
     102             :  * lgfs2_check_range - check if blkno is within FS limits
     103             :  * @sdp: super block
     104             :  * @blkno: block number
     105             :  *
     106             :  * Returns: 0 if ok, -1 if out of bounds
     107             :  */
     108     2170736 : int lgfs2_check_range(struct lgfs2_sbd *sdp, uint64_t blkno)
     109             : {
     110     2170736 :         if((blkno > sdp->fssize) || (blkno <= LGFS2_SB_ADDR(sdp)))
     111           6 :                 return -1;
     112     2170730 :         return 0;
     113             : }
     114             : 
     115             : /*
     116             :  * lgfs2_set_bitmap
     117             :  * @sdp: super block
     118             :  * @blkno: block number relative to file system
     119             :  * @state: one of three possible states
     120             :  *
     121             :  * This function sets the value of a bit of the
     122             :  * file system bitmap.
     123             :  *
     124             :  * Returns: 0 on success, -1 on error
     125             :  */
     126     2495706 : int lgfs2_set_bitmap(lgfs2_rgrp_t rgd, uint64_t blkno, int state)
     127             : {
     128             :         int           buf;
     129             :         uint32_t        rgrp_block;
     130     2495706 :         struct lgfs2_bitmap *bits = NULL;
     131             :         unsigned char *byte, cur_state;
     132             :         unsigned int bit;
     133             : 
     134             :         /* FIXME: should GFS2_BLKST_INVALID be allowed */
     135     2495706 :         if ((state < GFS2_BLKST_FREE) || (state > GFS2_BLKST_DINODE))
     136           0 :                 return -1;
     137             : 
     138     2495706 :         if(!rgd || blkno < rgd->rt_data0)
     139           0 :                 return -1;
     140             : 
     141     2495706 :         rgrp_block = (uint32_t)(blkno - rgd->rt_data0);
     142     7176118 :         for(buf= 0; buf < rgd->rt_length; buf++){
     143     7176118 :                 bits = &(rgd->rt_bits[buf]);
     144     7176118 :                 if(rgrp_block < ((bits->bi_start + bits->bi_len)*GFS2_NBBY))
     145     2495706 :                         break;
     146             :         }
     147             : 
     148     2495706 :         if (bits == NULL)
     149           0 :                 return -1;
     150     2495706 :         byte = (unsigned char *)(bits->bi_data + bits->bi_offset) +
     151     2495706 :                 (rgrp_block/GFS2_NBBY - bits->bi_start);
     152     2495706 :         bit = (rgrp_block % GFS2_NBBY) * GFS2_BIT_SIZE;
     153             : 
     154     2495706 :         cur_state = (*byte >> bit) & GFS2_BIT_MASK;
     155     2495706 :         *byte ^= cur_state << bit;
     156     2495706 :         *byte |= state << bit;
     157             : 
     158     2495706 :         bits->bi_modified = 1;
     159     2495706 :         return 0;
     160             : }
     161             : 
     162             : /*
     163             :  * lgfs2_get_bitmap - get value of FS bitmap
     164             :  * @sdp: super block
     165             :  * @blkno: block number relative to file system
     166             :  *
     167             :  * This function gets the value of a bit of the
     168             :  * file system bitmap.
     169             :  * Possible state values for a block in the bitmap are:
     170             :  *  GFS_BLKST_FREE     (0)
     171             :  *  GFS_BLKST_USED     (1)
     172             :  *  GFS_BLKST_INVALID  (2)
     173             :  *  GFS_BLKST_DINODE   (3)
     174             :  *
     175             :  * Returns: state on success, -1 on error
     176             :  */
     177     1968110 : int lgfs2_get_bitmap(struct lgfs2_sbd *sdp, uint64_t blkno, struct lgfs2_rgrp_tree *rgd)
     178             : {
     179             :         uint64_t offset;
     180     1968110 :         uint32_t i = 0;
     181             :         char *byte;
     182             :         unsigned int bit;
     183             :         struct lgfs2_bitmap *bi;
     184             : 
     185     1968110 :         if (rgd == NULL) {
     186           2 :                 rgd = lgfs2_blk2rgrpd(sdp, blkno);
     187           2 :                 if(rgd == NULL)
     188           0 :                         return -1;
     189             :         }
     190             : 
     191     1968110 :         offset = blkno - rgd->rt_data0;
     192     1968110 :         if (offset > UINT_MAX) {
     193           0 :                 errno = EINVAL;
     194           0 :                 return -1;
     195             :         }
     196     1968110 :         if (offset >= rgd->rt_data0 + rgd->rt_data) {
     197           0 :                 errno = E2BIG;
     198           0 :                 return -1;
     199             :         }
     200             : 
     201     1968110 :         if (offset >= ((uint64_t)rgd->rt_bits->bi_start + rgd->rt_bits->bi_len) * GFS2_NBBY) {
     202     1200911 :                 offset += (sizeof(struct gfs2_rgrp) - sizeof(struct gfs2_meta_header))
     203             :                           * GFS2_NBBY;
     204     1200911 :                 i = offset / sdp->sd_blocks_per_bitmap;
     205     1200911 :                 offset -= (uint64_t)i * sdp->sd_blocks_per_bitmap;
     206             :         }
     207             : 
     208     1968110 :         bi = &rgd->rt_bits[i];
     209     1968110 :         if (bi->bi_data == NULL)
     210           0 :                 return GFS2_BLKST_FREE;
     211             : 
     212     1968110 :         byte = (bi->bi_data + bi->bi_offset) + (offset/GFS2_NBBY);
     213     1968110 :         bit = (offset % GFS2_NBBY) * GFS2_BIT_SIZE;
     214             : 
     215     1968110 :         return (*byte >> bit) & GFS2_BIT_MASK;
     216             : }

Generated by: LCOV version 1.14