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

            Line data    Source code
       1              : #include "clusterautoconfig.h"
       2              : 
       3              : #include <unistd.h>
       4              : #include <inttypes.h>
       5              : #include <stdio.h>
       6              : #include <stdint.h>
       7              : #include <stdlib.h>
       8              : #include <string.h>
       9              : #include <errno.h>
      10              : #include <fcntl.h>
      11              : 
      12              : #include "libgfs2.h"
      13              : #include "osi_list.h"
      14              : 
      15              : /**
      16              :  * lgfs2_check_sb - Check superblock
      17              :  * @sb: The superblock
      18              :  *
      19              :  * Checks the version code of the FS is one that we understand how to
      20              :  * read and that the sizes of the various on-disk structures have not
      21              :  * changed.
      22              :  *
      23              :  * Returns: -1 on failure, 2 if this is gfs2
      24              :  */
      25           84 : int lgfs2_check_sb(void *sbp)
      26              : {
      27           84 :         struct gfs2_sb *sb = sbp;
      28              : 
      29          168 :         if (be32_to_cpu(sb->sb_header.mh_magic) != GFS2_MAGIC ||
      30           84 :             be32_to_cpu(sb->sb_header.mh_type) != GFS2_METATYPE_SB) {
      31            0 :                 errno = EIO;
      32            0 :                 return -1;
      33              :         }
      34              :         /* It's gfs2. Check format number is in a sensible range. */
      35          168 :         if (be32_to_cpu(sb->sb_fs_format) < LGFS2_FS_FORMAT_MIN ||
      36           84 :             be32_to_cpu(sb->sb_fs_format) > 1899) {
      37            1 :                 errno = EINVAL;
      38            1 :                 return -1;
      39              :         }
      40           83 :         return 2;
      41              : }
      42              : 
      43              : 
      44              : /*
      45              :  * lgfs2_read_sb: read the super block from disk
      46              :  * sdp: in-core super block
      47              :  *
      48              :  * This function reads in the super block from disk and
      49              :  * initializes various constants maintained in the super
      50              :  * block
      51              :  *
      52              :  * Returns: 0 on success, -1 on failure
      53              :  */
      54           78 : int lgfs2_read_sb(struct lgfs2_sbd *sdp)
      55              : {
      56              :         struct lgfs2_buffer_head *bh;
      57           78 :         uint64_t space = 0;
      58              :         unsigned int x;
      59              :         int ret;
      60              : 
      61           78 :         bh = lgfs2_bread(sdp, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift);
      62              : 
      63           78 :         ret = lgfs2_check_sb(bh->b_data);
      64           78 :         if (ret < 0) {
      65            1 :                 lgfs2_brelse(bh);
      66            1 :                 return ret;
      67              :         }
      68           77 :         lgfs2_sb_in(sdp, bh->b_data);
      69           77 :         lgfs2_brelse(bh);
      70           77 :         sdp->sd_fsb2bb_shift = sdp->sd_bsize_shift - GFS2_BASIC_BLOCK_SHIFT;
      71           77 :         if (sdp->sd_bsize < 512 || sdp->sd_bsize != (sdp->sd_bsize & -sdp->sd_bsize)) {
      72            5 :                 return -1;
      73              :         }
      74           72 :         sdp->sd_diptrs = (sdp->sd_bsize - sizeof(struct gfs2_dinode)) / sizeof(uint64_t);
      75           72 :         sdp->sd_inptrs = (sdp->sd_bsize - sizeof(struct gfs2_meta_header)) / sizeof(uint64_t);
      76           72 :         sdp->sd_jbsize = sdp->sd_bsize - sizeof(struct gfs2_meta_header);
      77           72 :         sdp->sd_hash_bsize = sdp->sd_bsize / 2;
      78           72 :         sdp->sd_hash_bsize_shift = sdp->sd_bsize_shift - 1;
      79           72 :         sdp->sd_hash_ptrs = sdp->sd_hash_bsize / sizeof(uint64_t);
      80           72 :         sdp->sd_heightsize[0] = sdp->sd_bsize - sizeof(struct gfs2_dinode);
      81           72 :         sdp->sd_heightsize[1] = sdp->sd_bsize * sdp->sd_diptrs;
      82          385 :         for (x = 2; x < GFS2_MAX_META_HEIGHT; x++){
      83          380 :                 space = sdp->sd_heightsize[x - 1] * sdp->sd_inptrs;
      84              :                 /* FIXME: Do we really need this first check?? */
      85          380 :                 if (space / sdp->sd_inptrs != sdp->sd_heightsize[x - 1] ||
      86          313 :                     space % sdp->sd_inptrs != 0)
      87              :                         break;
      88          313 :                 sdp->sd_heightsize[x] = space;
      89              :         }
      90           72 :         if (x > GFS2_MAX_META_HEIGHT){
      91            0 :                 errno = E2BIG;
      92            0 :                 return -1;
      93              :         }
      94              : 
      95           72 :         sdp->sd_jheightsize[0] = sdp->sd_bsize - sizeof(struct gfs2_dinode);
      96           72 :         sdp->sd_jheightsize[1] = sdp->sd_jbsize * sdp->sd_diptrs;
      97           72 :         for (x = 2; ; x++){
      98          385 :                 space = sdp->sd_jheightsize[x - 1] * sdp->sd_inptrs;
      99          385 :                 if (space / sdp->sd_inptrs != sdp->sd_jheightsize[x - 1] ||
     100          313 :                         space % sdp->sd_inptrs != 0)
     101              :                         break;
     102          313 :                 sdp->sd_jheightsize[x] = space;
     103              :         }
     104           72 :         sdp->sd_max_jheight = x;
     105           72 :         if(sdp->sd_max_jheight > GFS2_MAX_META_HEIGHT) {
     106            0 :                 errno = E2BIG;
     107            0 :                 return -1;
     108              :         }
     109           72 :         sdp->fssize = lseek(sdp->device_fd, 0, SEEK_END) / sdp->sd_bsize;
     110           72 :         sdp->sd_blocks_per_bitmap = (sdp->sd_bsize - sizeof(struct gfs2_meta_header))
     111              :                                      * GFS2_NBBY;
     112              : 
     113           72 :         return 0;
     114              : }
     115              : 
     116              : /* rgd_seems_ok - check some general things about the rindex entry
     117              :  *
     118              :  * If rg lengths are not consistent, it's not sane (or it's converted from
     119              :  * gfs1). The first RG will be a different length due to space reserved for
     120              :  * the superblock, so we can't detect this until we check rgrp 3, when we
     121              :  * can compare the distance between rgrp 1 and rgrp 2.
     122              :  *
     123              :  * Returns: 1 if the rgd seems relatively sane
     124              :  */
     125      2123204 : static int rgd_seems_ok(struct lgfs2_sbd *sdp, struct lgfs2_rgrp_tree *rgd)
     126              : {
     127              :         uint32_t most_bitmaps_possible;
     128              : 
     129              :         /* rg length must be at least 1 */
     130      2123204 :         if (rgd->rt_length == 0)
     131            3 :                 return 0;
     132              : 
     133              :         /* A max rgrp, 2GB, divided into blocksize, divided by blocks/byte
     134              :            represented in the bitmap, NBBY. Rough approximation only, due to
     135              :            metadata headers. I'm doing the math this way to avoid overflow. */
     136      2123201 :         most_bitmaps_possible = (LGFS2_MAX_RGSIZE * 1024 * 256) / sdp->sd_bsize;
     137      2123201 :         if (rgd->rt_length > most_bitmaps_possible)
     138            0 :                 return 0;
     139              : 
     140      2123201 :         if (rgd->rt_data0 != rgd->rt_addr + rgd->rt_length)
     141            0 :                 return 0;
     142              : 
     143      2123201 :         if (rgd->rt_bitbytes != rgd->rt_data / GFS2_NBBY)
     144            0 :                 return 0;
     145              : 
     146      2123201 :         return 1;
     147              : }
     148              : 
     149              : /* good_on_disk - check if the rindex points to what looks like an rgrp on disk
     150              :  *
     151              :  * This is only called when the rindex pointers aren't spaced evenly, which
     152              :  * isn't often. The rindex is pointing to an unexpected location, so we
     153              :  * check if the block it is pointing to is really an rgrp. If so, we count the
     154              :  * rindex entry as "sane" (after all, it did pass the previous checks above.)
     155              :  * If not, we count it as not sane, and therefore, the whole rindex is not to
     156              :  * be trusted by fsck.gfs2.
     157              :  */
     158         4535 : static int good_on_disk(struct lgfs2_sbd *sdp, struct lgfs2_rgrp_tree *rgd)
     159              : {
     160              :         struct lgfs2_buffer_head *bh;
     161              :         int is_rgrp;
     162              : 
     163         4535 :         bh = lgfs2_bread(sdp, rgd->rt_addr);
     164         4535 :         is_rgrp = (lgfs2_check_meta(bh->b_data, GFS2_METATYPE_RG) == 0);
     165         4535 :         lgfs2_brelse(bh);
     166         4535 :         return is_rgrp;
     167              : }
     168              : 
     169              : /**
     170              :  * lgfs2_rindex_read - read in the rg index file
     171              :  * @sdp: the incore superblock pointer
     172              :  * @rgcount: return count of the rgs.
     173              :  * @ok: return whether rindex is consistent
     174              :  *
     175              :  * Returns: 0 on success, -1 on failure
     176              :  */
     177         4545 : int lgfs2_rindex_read(struct lgfs2_sbd *sdp, uint64_t *rgcount, int *ok)
     178              : {
     179              :         unsigned int rg;
     180              :         int error;
     181         4545 :         struct lgfs2_rgrp_tree *rgd = NULL, *prev_rgd = NULL;
     182         4545 :         uint64_t prev_length = 0;
     183              : 
     184         4545 :         *ok = 1;
     185         4545 :         *rgcount = 0;
     186         4545 :         if (sdp->md.riinode->i_size % sizeof(struct gfs2_rindex))
     187            0 :                 *ok = 0; /* rindex file size must be a multiple of 96 */
     188      2132297 :         for (rg = 0; ; rg++) {
     189              :                 struct gfs2_rindex ri;
     190              :                 uint64_t addr;
     191              : 
     192      2132297 :                 error = lgfs2_readi(sdp->md.riinode, &ri,
     193              :                                    rg * sizeof(struct gfs2_rindex),
     194              :                                    sizeof(struct gfs2_rindex));
     195      2132297 :                 if (!error)
     196         4545 :                         break;
     197      2127752 :                 if (error != sizeof(struct gfs2_rindex))
     198            0 :                         return -1;
     199              : 
     200      2127752 :                 addr = be64_to_cpu(ri.ri_addr);
     201      2127752 :                 if (lgfs2_check_range(sdp, addr) != 0) {
     202            6 :                         *ok = 0;
     203            6 :                         if (prev_rgd == NULL)
     204            3 :                                 continue;
     205            3 :                         addr = prev_rgd->rt_data0 + prev_rgd->rt_data;
     206              :                 }
     207      2127749 :                 rgd = lgfs2_rgrp_insert(&sdp->rgtree, addr);
     208      2127749 :                 rgd->rt_length = be32_to_cpu(ri.ri_length);
     209      2127749 :                 rgd->rt_data0 = be64_to_cpu(ri.ri_data0);
     210      2127749 :                 rgd->rt_data = be32_to_cpu(ri.ri_data);
     211      2127749 :                 rgd->rt_bitbytes = be32_to_cpu(ri.ri_bitbytes);
     212      2127749 :                 if (prev_rgd) {
     213      2123204 :                         if (prev_rgd->rt_addr >= rgd->rt_addr)
     214            0 :                                 *ok = 0;
     215      2123204 :                         else if (!rgd_seems_ok(sdp, rgd))
     216            3 :                                 *ok = 0;
     217      2123201 :                         else if (*ok && rg > 2 && prev_length &&
     218      2113650 :                             prev_length != rgd->rt_addr - prev_rgd->rt_addr)
     219         4535 :                                 *ok = good_on_disk(sdp, rgd);
     220      2123204 :                         prev_length = rgd->rt_addr - prev_rgd->rt_addr;
     221              :                 }
     222              : 
     223      2127749 :                 if(lgfs2_compute_bitstructs(sdp->sd_bsize, rgd))
     224            3 :                         *ok = 0;
     225              : 
     226      2127749 :                 (*rgcount)++;
     227      2127749 :                 prev_rgd = rgd;
     228              :         }
     229         4545 :         if (*rgcount == 0)
     230            0 :                 return -1;
     231         4545 :         return 0;
     232              : }
        

Generated by: LCOV version 2.0-1