LCOV - code coverage report
Current view: top level - libgfs2 - fs_bits.c (source / functions) Coverage Total Hit
Test: gfs2-utils.info Lines: 86.7 % 75 65
Test Date: 2024-03-07 16:24:06 Functions: 100.0 % 5 5

            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     39029205 : 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     39029205 :         tmp = le64_to_cpu(*ptr) ^ search[state];
      53     39029205 :         tmp &= (tmp >> 1);
      54     39029205 :         tmp &= mask;
      55     39029205 :         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       321299 : unsigned long lgfs2_bitfit(const unsigned char *buf, const unsigned int len,
      68              :                           unsigned long goal, unsigned char state)
      69              : {
      70       321299 :         uint32_t spoint = (goal << 1) & ((8 * sizeof(uint64_t)) - 1);
      71       321299 :         const __le64 *ptr = ((__le64 *)buf) + (goal >> 5);
      72       321299 :         const __le64 *end = (__le64 *) (buf + ALIGN(len, sizeof(uint64_t)));
      73              :         uint64_t tmp;
      74       321299 :         uint64_t mask = 0x5555555555555555ULL;
      75              :         uint32_t bit;
      76              : 
      77       321299 :         if (state > 3)
      78            0 :                 return 0;
      79              : 
      80              :         /* Mask off bits we don't care about at the start of the search */
      81       321299 :         mask <<= spoint;
      82       321299 :         tmp = bit_search(ptr, mask, state);
      83       321299 :         ptr++;
      84     39029205 :         while(tmp == 0 && ptr < end) {
      85     38707906 :                 tmp = bit_search(ptr, 0x5555555555555555ULL, state);
      86     38707906 :                 ptr++;
      87              :         }
      88              :         /* Mask off any bits which are more than len bytes from the start */
      89       321299 :         if (ptr == end && (len & (sizeof(uint64_t) - 1)))
      90         1800 :                 tmp &= (((uint64_t)~0) >>
      91         1800 :                         (64 - 8 * (len & (sizeof(uint64_t) - 1))));
      92              :         /* Didn't find anything, so return */
      93       321299 :         if (tmp == 0)
      94       223826 :                 return LGFS2_BFITNOENT;
      95        97473 :         ptr--;
      96        97473 :         bit = ffsll(tmp);
      97        97473 :         bit /= 2;       /* two bits per entry in the bitmap */
      98        97473 :         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      2171329 : int lgfs2_check_range(struct lgfs2_sbd *sdp, uint64_t blkno)
     109              : {
     110      2171329 :         if((blkno > sdp->fssize) || (blkno <= LGFS2_SB_ADDR(sdp)))
     111            6 :                 return -1;
     112      2171323 :         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      2528809 : int lgfs2_set_bitmap(lgfs2_rgrp_t rgd, uint64_t blkno, int state)
     127              : {
     128              :         int           buf;
     129              :         uint32_t        rgrp_block;
     130      2528809 :         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      2528809 :         if ((state < GFS2_BLKST_FREE) || (state > GFS2_BLKST_DINODE))
     136            0 :                 return -1;
     137              : 
     138      2528809 :         if(!rgd || blkno < rgd->rt_data0)
     139            0 :                 return -1;
     140              : 
     141      2528809 :         rgrp_block = (uint32_t)(blkno - rgd->rt_data0);
     142      7226861 :         for(buf= 0; buf < rgd->rt_length; buf++){
     143      7226861 :                 bits = &(rgd->rt_bits[buf]);
     144      7226861 :                 if(rgrp_block < ((bits->bi_start + bits->bi_len)*GFS2_NBBY))
     145      2528809 :                         break;
     146              :         }
     147              : 
     148      2528809 :         if (bits == NULL)
     149            0 :                 return -1;
     150      2528809 :         byte = (unsigned char *)(bits->bi_data + bits->bi_offset) +
     151      2528809 :                 (rgrp_block/GFS2_NBBY - bits->bi_start);
     152      2528809 :         bit = (rgrp_block % GFS2_NBBY) * GFS2_BIT_SIZE;
     153              : 
     154      2528809 :         cur_state = (*byte >> bit) & GFS2_BIT_MASK;
     155      2528809 :         *byte ^= cur_state << bit;
     156      2528809 :         *byte |= state << bit;
     157              : 
     158      2528809 :         bits->bi_modified = 1;
     159      2528809 :         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      2001257 : int lgfs2_get_bitmap(struct lgfs2_sbd *sdp, uint64_t blkno, struct lgfs2_rgrp_tree *rgd)
     178              : {
     179              :         uint64_t offset;
     180      2001257 :         uint32_t i = 0;
     181              :         char *byte;
     182              :         unsigned int bit;
     183              :         struct lgfs2_bitmap *bi;
     184              : 
     185      2001257 :         if (rgd == NULL) {
     186            2 :                 rgd = lgfs2_blk2rgrpd(sdp, blkno);
     187            2 :                 if(rgd == NULL)
     188            0 :                         return -1;
     189              :         }
     190              : 
     191      2001257 :         offset = blkno - rgd->rt_data0;
     192      2001257 :         if (offset > UINT_MAX) {
     193            0 :                 errno = EINVAL;
     194            0 :                 return -1;
     195              :         }
     196      2001257 :         if (offset >= rgd->rt_data0 + rgd->rt_data) {
     197            0 :                 errno = E2BIG;
     198            0 :                 return -1;
     199              :         }
     200              : 
     201      2001257 :         if (offset >= ((uint64_t)rgd->rt_bits->bi_start + rgd->rt_bits->bi_len) * GFS2_NBBY) {
     202      1217892 :                 offset += (sizeof(struct gfs2_rgrp) - sizeof(struct gfs2_meta_header))
     203              :                           * GFS2_NBBY;
     204      1217892 :                 i = offset / sdp->sd_blocks_per_bitmap;
     205      1217892 :                 offset -= (uint64_t)i * sdp->sd_blocks_per_bitmap;
     206              :         }
     207              : 
     208      2001257 :         bi = &rgd->rt_bits[i];
     209      2001257 :         if (bi->bi_data == NULL)
     210            0 :                 return GFS2_BLKST_FREE;
     211              : 
     212      2001257 :         byte = (bi->bi_data + bi->bi_offset) + (offset/GFS2_NBBY);
     213      2001257 :         bit = (offset % GFS2_NBBY) * GFS2_BIT_SIZE;
     214              : 
     215      2001257 :         return (*byte >> bit) & GFS2_BIT_MASK;
     216              : }
        

Generated by: LCOV version 2.0-1