LCOV - code coverage report
Current view: top level - fsck - initialize.c (source / functions) Hit Total Coverage
Test: gfs2-utils.info Lines: 424 778 54.5 %
Date: 2023-10-25 12:04:14 Functions: 24 25 96.0 %

          Line data    Source code
       1             : #include "clusterautoconfig.h"
       2             : 
       3             : #include <stdio.h>
       4             : #include <stdint.h>
       5             : #include <inttypes.h>
       6             : #include <stdlib.h>
       7             : #include <sys/types.h>
       8             : #include <sys/stat.h>
       9             : #include <fcntl.h>
      10             : #include <string.h>
      11             : #include <unistd.h>
      12             : #include <libintl.h>
      13             : #include <errno.h>
      14             : 
      15             : #define _(String) gettext(String)
      16             : 
      17             : #include <logging.h>
      18             : #include "libgfs2.h"
      19             : #include "fsck.h"
      20             : #include "util.h"
      21             : #include "fs_recovery.h"
      22             : #include "metawalk.h"
      23             : #include "inode_hash.h"
      24             : 
      25             : #define CLEAR_POINTER(x) \
      26             :         if (x) { \
      27             :                 free(x); \
      28             :                 x = NULL; \
      29             :         }
      30             : #define HIGHEST_BLOCK 0xffffffffffffffff
      31             : 
      32             : static int was_mounted_ro = 0;
      33             : static uint64_t possible_root = HIGHEST_BLOCK;
      34             : static struct lgfs2_meta_dir fix_md;
      35             : static uint64_t blks_2free = 0;
      36             : 
      37             : /**
      38             :  * block_mounters
      39             :  *
      40             :  * Change the lock protocol so nobody can mount the fs
      41             :  *
      42             :  */
      43          28 : static int block_mounters(struct lgfs2_sbd *sdp, int block_em)
      44             : {
      45          28 :         if (block_em) {
      46             :                 /* verify it starts with lock_ */
      47          14 :                 if (!strncmp(sdp->sd_lockproto, "lock_", 5)) {
      48             :                         /* Change lock_ to fsck_ */
      49          13 :                         memcpy(sdp->sd_lockproto, "fsck_", 5);
      50             :                 }
      51             :                 /* FIXME: Need to do other verification in the else
      52             :                  * case */
      53             :         } else {
      54             :                 /* verify it starts with fsck_ */
      55             :                 /* verify it starts with lock_ */
      56          14 :                 if (!strncmp(sdp->sd_lockproto, "fsck_", 5)) {
      57             :                         /* Change fsck_ to lock_ */
      58          13 :                         memcpy(sdp->sd_lockproto, "lock_", 5);
      59             :                 }
      60             :         }
      61             : 
      62          28 :         if (lgfs2_sb_write(sdp, sdp->device_fd)) {
      63           0 :                 stack;
      64           0 :                 return -1;
      65             :         }
      66          28 :         return 0;
      67             : }
      68             : 
      69          56 : static void dup_free(struct fsck_cx *cx)
      70             : {
      71             :         struct osi_node *n;
      72             :         struct duptree *dt;
      73             : 
      74          56 :         while ((n = osi_first(&cx->dup_blocks))) {
      75           0 :                 dt = (struct duptree *)n;
      76           0 :                 dup_delete(cx, dt);
      77             :         }
      78          56 : }
      79             : 
      80          56 : static void dirtree_free(struct fsck_cx *cx)
      81             : {
      82             :         struct osi_node *n;
      83             :         struct dir_info *dt;
      84             : 
      85         280 :         while ((n = osi_first(&cx->dirtree))) {
      86         224 :                 dt = (struct dir_info *)n;
      87         224 :                 dirtree_delete(cx, dt);
      88             :         }
      89          56 : }
      90             : 
      91          56 : static void inodetree_free(struct fsck_cx *cx)
      92             : {
      93             :         struct osi_node *n;
      94             :         struct inode_info *dt;
      95             : 
      96          56 :         while ((n = osi_first(&cx->inodetree))) {
      97           0 :                 dt = (struct inode_info *)n;
      98           0 :                 inodetree_delete(cx, dt);
      99             :         }
     100          56 : }
     101             : 
     102             : /*
     103             :  * empty_super_block - free all structures in the super block
     104             :  * sdp: the in-core super block
     105             :  *
     106             :  * This function frees all allocated structures within the
     107             :  * super block.  It does not free the super block itself.
     108             :  *
     109             :  * Returns: Nothing
     110             :  */
     111          56 : static void empty_super_block(struct fsck_cx *cx)
     112             : {
     113          56 :         log_info( _("Freeing buffers.\n"));
     114          56 :         lgfs2_rgrp_free(cx->sdp, &cx->sdp->rgtree);
     115             : 
     116          56 :         inodetree_free(cx);
     117          56 :         dirtree_free(cx);
     118          56 :         dup_free(cx);
     119          56 : }
     120             : 
     121             : 
     122             : /**
     123             :  * set_block_ranges
     124             :  * @sdp: superblock
     125             :  *
     126             :  * Uses info in rgrps and jindex to determine boundaries of the
     127             :  * file system.
     128             :  *
     129             :  * Returns: 0 on success, -1 on failure
     130             :  */
     131          56 : static int set_block_ranges(struct lgfs2_sbd *sdp)
     132             : {
     133          56 :         struct osi_node *n, *next = NULL;
     134             :         struct lgfs2_rgrp_tree *rgd;
     135          56 :         uint64_t rmax = 0;
     136          56 :         uint64_t rmin = 0;
     137             :         ssize_t count;
     138             :         char *buf;
     139             : 
     140          56 :         log_info( _("Setting block ranges..."));
     141             : 
     142        4415 :         for (n = osi_first(&sdp->rgtree); n; n = next) {
     143        4359 :                 next = osi_next(n);
     144        4359 :                 rgd = (struct lgfs2_rgrp_tree *)n;
     145        4359 :                 if (rgd->rt_data0 + rgd->rt_data &&
     146        4359 :                     rgd->rt_data0 + rgd->rt_data - 1 > rmax)
     147        4359 :                         rmax = rgd->rt_data0 + rgd->rt_data - 1;
     148        4359 :                 if (!rmin || rgd->rt_data0 < rmin)
     149          56 :                         rmin = rgd->rt_data0;
     150             :         }
     151             : 
     152          56 :         last_fs_block = rmax;
     153             :         if (last_fs_block > 0xffffffff && sizeof(unsigned long) <= 4) {
     154             :                 log_crit(_("This file system is too big for this computer to handle.\n"));
     155             :                 log_crit(_("Last fs block = 0x%"PRIx64", but sizeof(unsigned long) is %zu bytes.\n"),
     156             :                          last_fs_block, sizeof(unsigned long));
     157             :                 goto fail;
     158             :         }
     159             : 
     160          56 :         last_data_block = rmax;
     161          56 :         first_data_block = rmin;
     162             : 
     163          56 :         buf = calloc(1, sdp->sd_bsize);
     164          56 :         if (buf == NULL) {
     165           0 :                 log_crit(_("Failed to determine file system boundaries: %s\n"), strerror(errno));
     166           0 :                 return -1;
     167             :         }
     168          56 :         count = pread(sdp->device_fd, buf, sdp->sd_bsize, (last_fs_block * sdp->sd_bsize));
     169          56 :         free(buf);
     170          56 :         if (count != sdp->sd_bsize) {
     171           0 :                 log_crit(_("Failed to read highest block number (%"PRIx64"): %s\n"),
     172             :                          last_fs_block, strerror(errno));
     173           0 :                 goto fail;
     174             :         }
     175             : 
     176          56 :         log_info(_("0x%"PRIx64" to 0x%"PRIx64"\n"), first_data_block, last_data_block);
     177          56 :         return 0;
     178             : 
     179           0 :  fail:
     180           0 :         log_info( _("Error\n"));
     181           0 :         return -1;
     182             : }
     183             : 
     184             : /**
     185             :  * check_rgrp_integrity - verify a rgrp free block count against the bitmap
     186             :  */
     187        4359 : static void check_rgrp_integrity(struct fsck_cx *cx, struct lgfs2_rgrp_tree *rgd,
     188             :                                  int *fixit, int *this_rg_fixed,
     189             :                                  int *this_rg_bad, int *this_rg_cleaned)
     190             : {
     191             :         uint32_t rg_free, rg_reclaimed, rg_unlinked, rg_usedmeta, rg_useddi;
     192        4359 :         int rgb, x, y, off, bytes_to_check, total_bytes_to_check, asked = 0;
     193        4359 :         struct lgfs2_sbd *sdp = cx->sdp;
     194             :         unsigned int state;
     195             :         uint64_t diblock;
     196             :         struct lgfs2_buffer_head *bh;
     197             : 
     198        4359 :         rg_free = rg_reclaimed = rg_unlinked = rg_usedmeta = rg_useddi = 0;
     199        4359 :         total_bytes_to_check = rgd->rt_bitbytes;
     200             : 
     201        4359 :         *this_rg_fixed = *this_rg_bad = *this_rg_cleaned = 0;
     202             : 
     203        4359 :         diblock = rgd->rt_data0;
     204      136822 :         for (rgb = 0; rgb < rgd->rt_length; rgb++){
     205             :                 /* Count up the free blocks in the bitmap */
     206      132463 :                 off = (rgb) ? sizeof(struct gfs2_meta_header) :
     207             :                         sizeof(struct gfs2_rgrp);
     208      132463 :                 if (total_bytes_to_check <= sdp->sd_bsize - off)
     209        4359 :                         bytes_to_check = total_bytes_to_check;
     210             :                 else
     211      128104 :                         bytes_to_check = sdp->sd_bsize - off;
     212      132463 :                 total_bytes_to_check -= bytes_to_check;
     213   119507774 :                 for (x = 0; x < bytes_to_check; x++) {
     214             :                         unsigned char *byte;
     215             : 
     216   119375311 :                         byte = (unsigned char *)&rgd->rt_bits[rgb].bi_data[off + x];
     217   119375311 :                         if (*byte == 0x55) {
     218      491106 :                                 diblock += GFS2_NBBY;
     219      491106 :                                 continue;
     220             :                         }
     221   118884205 :                         if (*byte == 0x00) {
     222   118883894 :                                 diblock += GFS2_NBBY;
     223   118883894 :                                 rg_free += GFS2_NBBY;
     224   118883894 :                                 continue;
     225             :                         }
     226        1555 :                         for (y = 0; y < GFS2_NBBY; y++) {
     227        1244 :                                 state = (*byte >>
     228        1244 :                                          (GFS2_BIT_SIZE * y)) & GFS2_BIT_MASK;
     229        1244 :                                 if (state == GFS2_BLKST_USED) {
     230         461 :                                         diblock++;
     231         461 :                                         continue;
     232             :                                 }
     233         783 :                                 if (state == GFS2_BLKST_DINODE) {
     234         700 :                                         diblock++;
     235         700 :                                         continue;
     236             :                                 }
     237          83 :                                 if (state == GFS2_BLKST_FREE) {
     238          83 :                                         diblock++;
     239          83 :                                         rg_free++;
     240          83 :                                         continue;
     241             :                                 }
     242             :                                 /* GFS2_BLKST_UNLINKED */
     243           0 :                                 log_info(_("Unlinked dinode 0x%"PRIx64" found.\n"), diblock);
     244           0 :                                 if (!asked) {
     245             :                                         char msg[256];
     246             : 
     247           0 :                                         asked = 1;
     248           0 :                                         sprintf(msg,
     249           0 :                                                 _("Okay to reclaim free "
     250             :                                                   "metadata in resource group "
     251             :                                                   "%"PRIu64" (0x%"PRIx64")? (y/n)"),
     252             :                                                 rgd->rt_addr, rgd->rt_addr);
     253           0 :                                         if (query(cx, "%s", msg))
     254           0 :                                                 *fixit = 1;
     255             :                                 }
     256           0 :                                 if (!(*fixit)) {
     257           0 :                                         rg_unlinked++;
     258           0 :                                         diblock++;
     259           0 :                                         continue;
     260             :                                 }
     261           0 :                                 *byte &= ~(GFS2_BIT_MASK <<
     262           0 :                                            (GFS2_BIT_SIZE * y));
     263           0 :                                 rgd->rt_bits[rgb].bi_modified = 1;
     264           0 :                                 rg_reclaimed++;
     265           0 :                                 rg_free++;
     266           0 :                                 rgd->rt_free++;
     267           0 :                                 log_info(_("Free metadata block %"PRIu64" (0x%"PRIx64") reclaimed.\n"),
     268             :                                          diblock, diblock);
     269           0 :                                 bh = lgfs2_bread(sdp, diblock);
     270           0 :                                 if (!lgfs2_check_meta(bh->b_data, GFS2_METATYPE_DI)) {
     271           0 :                                         struct lgfs2_inode *ip =
     272           0 :                                                 fsck_inode_get(sdp, rgd, bh);
     273           0 :                                         if (ip->i_blocks > 1) {
     274           0 :                                                 blks_2free += ip->i_blocks - 1;
     275           0 :                                                 log_info(_("%"PRIu64" blocks "
     276             :                                                            "(total) may need "
     277             :                                                            "to be freed in "
     278             :                                                            "pass 5.\n"),
     279             :                                                          blks_2free);
     280             :                                         }
     281           0 :                                         fsck_inode_put(&ip);
     282             :                                 }
     283           0 :                                 lgfs2_brelse(bh);
     284           0 :                                 diblock++;
     285             :                         }
     286             :                 }
     287             :         }
     288             :         /* The unlinked blocks we reclaim shouldn't be considered errors,
     289             :            since we're just reclaiming them as a courtesy. If we already
     290             :            got permission to reclaim them, we adjust the rgrp counts
     291             :            accordingly. That way, only "real" rgrp count inconsistencies
     292             :            will be reported. */
     293        4359 :         if (rg_reclaimed && *fixit) {
     294           0 :                 lgfs2_rgrp_out(rgd, rgd->rt_bits[0].bi_data);
     295           0 :                 rgd->rt_bits[0].bi_modified = 1;
     296           0 :                 *this_rg_cleaned = 1;
     297           0 :                 log_info(_("The rgrp at %"PRIu64" (0x%"PRIx64") was cleaned of %d "
     298             :                             "free metadata blocks.\n"),
     299             :                          rgd->rt_addr, rgd->rt_addr, rg_reclaimed);
     300             :         }
     301        4359 :         if (rgd->rt_free != rg_free) {
     302           4 :                 *this_rg_bad = 1;
     303           4 :                 *this_rg_cleaned = 0;
     304           4 :                 log_err( _("Error: resource group %"PRIu64" (0x%"PRIx64"): "
     305             :                            "free space (%d) does not match bitmap (%d)\n"),
     306             :                         rgd->rt_addr, rgd->rt_addr, rgd->rt_free, rg_free);
     307           4 :                 if (query(cx, _("Fix the rgrp free blocks count? (y/n)"))) {
     308           4 :                         rgd->rt_free = rg_free;
     309           4 :                         lgfs2_rgrp_out(rgd, rgd->rt_bits[0].bi_data);
     310           4 :                         rgd->rt_bits[0].bi_modified = 1;
     311           4 :                         *this_rg_fixed = 1;
     312           4 :                         log_err( _("The rgrp was fixed.\n"));
     313             :                 } else
     314           0 :                         log_err( _("The rgrp was not fixed.\n"));
     315             :         }
     316        4359 : }
     317             : 
     318             : /**
     319             :  * check_rgrps_integrity - verify rgrp consistency
     320             :  * Note: We consider an rgrp "cleaned" if the unlinked meta blocks are
     321             :  *       cleaned, so not quite "bad" and not quite "good" but rewritten anyway.
     322             :  *
     323             :  * Returns: 0 on success, 1 if errors were detected
     324             :  */
     325          56 : static void check_rgrps_integrity(struct fsck_cx *cx)
     326             : {
     327          56 :         struct osi_node *n, *next = NULL;
     328          56 :         int rgs_good = 0, rgs_bad = 0, rgs_fixed = 0, rgs_cleaned = 0;
     329          56 :         int was_bad = 0, was_fixed = 0, was_cleaned = 0;
     330             :         struct lgfs2_rgrp_tree *rgd;
     331          56 :         int reclaim_unlinked = 0;
     332             : 
     333          56 :         log_info( _("Checking the integrity of all resource groups.\n"));
     334        4415 :         for (n = osi_first(&cx->sdp->rgtree); n; n = next) {
     335        4359 :                 next = osi_next(n);
     336        4359 :                 rgd = (struct lgfs2_rgrp_tree *)n;
     337        4359 :                 if (fsck_abort)
     338           0 :                         return;
     339        4359 :                 check_rgrp_integrity(cx, rgd, &reclaim_unlinked,
     340             :                                      &was_fixed, &was_bad, &was_cleaned);
     341        4359 :                 if (was_fixed)
     342           4 :                         rgs_fixed++;
     343        4359 :                 if (was_cleaned)
     344           0 :                         rgs_cleaned++;
     345        4359 :                 else if (was_bad)
     346           4 :                         rgs_bad++;
     347             :                 else
     348        4355 :                         rgs_good++;
     349             :         }
     350          56 :         if (rgs_bad || rgs_cleaned) {
     351           4 :                 log_err( _("RGs: Consistent: %d   Cleaned: %d   Inconsistent: "
     352             :                            "%d   Fixed: %d   Total: %d\n"),
     353             :                          rgs_good, rgs_cleaned, rgs_bad, rgs_fixed,
     354             :                          rgs_good + rgs_bad + rgs_cleaned);
     355           4 :                 if (rgs_cleaned && blks_2free)
     356           0 :                         log_err(_("%"PRIu64" blocks may need to be freed in pass 5 "
     357             :                                   "due to the cleaned resource groups.\n"),
     358             :                                 blks_2free);
     359             :         }
     360             : }
     361             : 
     362           0 : static int rebuild_sysdir(struct fsck_cx *cx)
     363             : {
     364           0 :         struct lgfs2_sbd *sdp = cx->sdp;
     365             :         struct lgfs2_inum inum;
     366           0 :         struct lgfs2_buffer_head *bh = NULL;
     367           0 :         int err = 0;
     368             : 
     369           0 :         log_err(_("The system directory seems to be destroyed.\n"));
     370           0 :         if (!query(cx, _("Okay to rebuild it? (y/n)"))) {
     371           0 :                 log_err(_("System directory not rebuilt; aborting.\n"));
     372           0 :                 return -1;
     373             :         }
     374           0 :         log_err(_("Trying to rebuild the master directory.\n"));
     375           0 :         inum.in_formal_ino = sdp->md.next_inum++;
     376           0 :         inum.in_addr = sdp->sd_meta_dir.in_addr;
     377           0 :         err = lgfs2_init_dinode(sdp, &bh, &inum, S_IFDIR | 0755, GFS2_DIF_SYSTEM, &inum);
     378           0 :         if (err != 0)
     379           0 :                 return -1;
     380           0 :         sdp->master_dir = lgfs2_inode_get(sdp, bh);
     381           0 :         if (sdp->master_dir == NULL) {
     382           0 :                 log_crit(_("Error reading master: %s\n"), strerror(errno));
     383           0 :                 return -1;
     384             :         }
     385           0 :         sdp->master_dir->bh_owned = 1;
     386             : 
     387           0 :         if (fix_md.jiinode) {
     388           0 :                 inum.in_formal_ino = sdp->md.next_inum++;
     389           0 :                 inum.in_addr = fix_md.jiinode->i_num.in_addr;
     390           0 :                 err = lgfs2_dir_add(sdp->master_dir, "jindex", 6, &inum,
     391             :                               IF2DT(S_IFDIR | 0700));
     392           0 :                 if (err) {
     393           0 :                         log_crit(_("Error %d adding jindex directory\n"), errno);
     394           0 :                         exit(FSCK_ERROR);
     395             :                 }
     396           0 :                 sdp->master_dir->i_nlink++;
     397             :         } else {
     398           0 :                 err = build_jindex(cx);
     399           0 :                 if (err) {
     400           0 :                         log_crit(_("Error %d building jindex\n"), err);
     401           0 :                         exit(FSCK_ERROR);
     402             :                 }
     403             :         }
     404             : 
     405           0 :         if (fix_md.pinode) {
     406           0 :                 inum.in_formal_ino = sdp->md.next_inum++;
     407           0 :                 inum.in_addr = fix_md.pinode->i_num.in_addr;
     408             :                 /* coverity[deref_arg:SUPPRESS] */
     409           0 :                 err = lgfs2_dir_add(sdp->master_dir, "per_node", 8, &inum,
     410             :                         IF2DT(S_IFDIR | 0700));
     411           0 :                 if (err) {
     412           0 :                         log_crit(_("Error %d adding per_node directory\n"),
     413             :                                  errno);
     414           0 :                         exit(FSCK_ERROR);
     415             :                 }
     416           0 :                 sdp->master_dir->i_nlink++;
     417             :         } else {
     418             :                 /* coverity[double_free:SUPPRESS] */
     419           0 :                 err = build_per_node(cx);
     420           0 :                 if (err) {
     421           0 :                         log_crit(_("Error %d building per_node directory\n"),
     422             :                                  err);
     423           0 :                         exit(FSCK_ERROR);
     424             :                 }
     425             :         }
     426             : 
     427           0 :         if (fix_md.inum) {
     428           0 :                 inum.in_formal_ino = sdp->md.next_inum++;
     429           0 :                 inum.in_addr = fix_md.inum->i_num.in_addr;
     430             :                 /* coverity[deref_arg:SUPPRESS] */
     431           0 :                 err = lgfs2_dir_add(sdp->master_dir, "inum", 4, &inum,
     432             :                         IF2DT(S_IFREG | 0600));
     433           0 :                 if (err) {
     434           0 :                         log_crit(_("Error %d adding inum inode\n"), errno);
     435           0 :                         exit(FSCK_ERROR);
     436             :                 }
     437             :         } else {
     438           0 :                 sdp->md.inum = lgfs2_build_inum(sdp);
     439           0 :                 if (sdp->md.inum == NULL) {
     440           0 :                         log_crit(_("Error building inum inode: %s\n"), strerror(errno));
     441           0 :                         exit(FSCK_ERROR);
     442             :                 }
     443             :                 /* Write the inode but don't free it, to avoid doing an extra lookup */
     444             :                 /* coverity[deref_after_free:SUPPRESS] */
     445           0 :                 lgfs2_dinode_out(sdp->md.inum, sdp->md.inum->i_bh->b_data);
     446           0 :                 lgfs2_bwrite(sdp->md.inum->i_bh);
     447             :         }
     448             : 
     449           0 :         if (fix_md.statfs) {
     450           0 :                 inum.in_formal_ino = sdp->md.next_inum++;
     451           0 :                 inum.in_addr = fix_md.statfs->i_num.in_addr;
     452             :                 /* coverity[deref_arg:SUPPRESS] */
     453           0 :                 err = lgfs2_dir_add(sdp->master_dir, "statfs", 6, &inum,
     454             :                               IF2DT(S_IFREG | 0600));
     455           0 :                 if (err) {
     456           0 :                         log_crit(_("Error %d adding statfs inode\n"), errno);
     457           0 :                         exit(FSCK_ERROR);
     458             :                 }
     459             :         } else {
     460           0 :                 sdp->md.statfs = lgfs2_build_statfs(sdp);
     461           0 :                 if (sdp->md.statfs == NULL) {
     462           0 :                         log_crit(_("Error %d building statfs inode\n"), err);
     463           0 :                         exit(FSCK_ERROR);
     464             :                 }
     465             :                 /* Write the inode but don't free it, to avoid doing an extra lookup */
     466             :                 /* coverity[deref_after_free:SUPPRESS] */
     467           0 :                 lgfs2_dinode_out(sdp->md.statfs, sdp->md.statfs->i_bh->b_data);
     468           0 :                 lgfs2_bwrite(sdp->md.statfs->i_bh);
     469             :         }
     470             : 
     471           0 :         if (fix_md.riinode) {
     472           0 :                 inum.in_formal_ino = sdp->md.next_inum++;
     473           0 :                 inum.in_addr = fix_md.riinode->i_num.in_addr;
     474             :                 /* coverity[deref_arg:SUPPRESS] */
     475           0 :                 err = lgfs2_dir_add(sdp->master_dir, "rindex", 6, &inum,
     476             :                         IF2DT(S_IFREG | 0600));
     477           0 :                 if (err) {
     478           0 :                         log_crit(_("Error %d adding rindex inode\n"), errno);
     479           0 :                         exit(FSCK_ERROR);
     480             :                 }
     481             :         } else {
     482             :                 /* coverity[double_free:SUPPRESS] */
     483           0 :                 struct lgfs2_inode *rip = lgfs2_build_rindex(sdp);
     484           0 :                 if (rip == NULL) {
     485           0 :                         log_crit(_("Error building rindex inode: %s\n"), strerror(errno));
     486           0 :                         exit(FSCK_ERROR);
     487             :                 }
     488           0 :                 lgfs2_inode_put(&rip);
     489             :         }
     490             : 
     491           0 :         if (fix_md.qinode) {
     492           0 :                 inum.in_formal_ino = sdp->md.next_inum++;
     493           0 :                 inum.in_addr = fix_md.qinode->i_num.in_addr;
     494           0 :                 err = lgfs2_dir_add(sdp->master_dir, "quota", 5, &inum,
     495             :                         IF2DT(S_IFREG | 0600));
     496           0 :                 if (err) {
     497           0 :                         log_crit(_("Error %d adding quota inode\n"), errno);
     498           0 :                         exit(FSCK_ERROR);
     499             :                 }
     500             :         } else {
     501           0 :                 struct lgfs2_inode *qip = lgfs2_build_quota(sdp);
     502           0 :                 if (qip == NULL) {
     503           0 :                         log_crit(_("Error building quota inode: %s\n"), strerror(errno));
     504           0 :                         exit(FSCK_ERROR);
     505             :                 }
     506           0 :                 lgfs2_inode_put(&qip);
     507             :         }
     508             : 
     509           0 :         log_err(_("Master directory rebuilt.\n"));
     510           0 :         lgfs2_inode_put(&sdp->md.inum);
     511           0 :         lgfs2_inode_put(&sdp->md.statfs);
     512           0 :         lgfs2_inode_put(&sdp->master_dir);
     513           0 :         return 0;
     514             : }
     515             : 
     516             : /**
     517             :  * lookup_per_node - Make sure the per_node directory is read in
     518             :  *
     519             :  * This function is used to read in the per_node directory.  It is called
     520             :  * twice.  The first call tries to read in the dinode early on.  That ensures
     521             :  * that if any journals are missing, we can figure out the number of journals
     522             :  * from per_node.  However, we unfortunately can't rebuild per_node at that
     523             :  * point in time because our resource groups aren't read in yet.
     524             :  * The second time it's called is much later when we can rebuild it.
     525             :  *
     526             :  * allow_rebuild: 0 if rebuilds are not allowed
     527             :  *                1 if rebuilds are allowed
     528             :  */
     529         112 : static void lookup_per_node(struct fsck_cx *cx, int allow_rebuild)
     530             : {
     531         112 :         struct lgfs2_sbd *sdp = cx->sdp;
     532             : 
     533         112 :         if (sdp->md.pinode)
     534          56 :                 return;
     535             : 
     536          56 :         sdp->md.pinode = lgfs2_lookupi(sdp->master_dir, "per_node", 8);
     537          56 :         if (sdp->md.pinode)
     538          56 :                 return;
     539           0 :         if (!allow_rebuild) {
     540           0 :                 log_err( _("The gfs2 system per_node directory "
     541             :                            "inode is missing, so we might not be \nable to "
     542             :                            "rebuild missing journals this run.\n"));
     543           0 :                 return;
     544             :         }
     545             : 
     546           0 :         if (query(cx, _("The gfs2 system per_node directory "
     547             :                      "inode is missing. Okay to rebuild it? (y/n) "))) {
     548             :                 int err;
     549             : 
     550             :                 /* coverity[freed_arg:SUPPRESS] False positive */
     551           0 :                 err = build_per_node(cx);
     552           0 :                 if (err) {
     553           0 :                         log_crit(_("Error %d rebuilding per_node directory\n"),
     554             :                                  err);
     555           0 :                         exit(FSCK_ERROR);
     556             :                 }
     557             :         }
     558             :         /* coverity[identity_transfer:SUPPRESS] False positive */
     559           0 :         sdp->md.pinode = lgfs2_lookupi(sdp->master_dir, "per_node", 8);
     560           0 :         if (!sdp->md.pinode) {
     561           0 :                 log_err( _("Unable to rebuild per_node; aborting.\n"));
     562           0 :                 exit(FSCK_ERROR);
     563             :         }
     564             : }
     565             : 
     566             : #define RA_WINDOW 32
     567             : 
     568        1003 : static unsigned rgrp_reada(struct lgfs2_sbd *sdp, unsigned cur_window,
     569             :                                 struct osi_node *n)
     570             : {
     571             :         struct lgfs2_rgrp_tree *rgd;
     572             :         unsigned i;
     573             :         off_t start, len;
     574             : 
     575       14015 :         for (i = 0; i < RA_WINDOW; i++, n = osi_next(n)) {
     576       13841 :                 if (n == NULL)
     577         829 :                         return i;
     578       13012 :                 if (i < cur_window)
     579        8567 :                         continue;
     580        4445 :                 rgd = (struct lgfs2_rgrp_tree *)n;
     581        4445 :                 start = rgd->rt_addr * sdp->sd_bsize;
     582        4445 :                 len = rgd->rt_length * sdp->sd_bsize;
     583        4445 :                 (void)posix_fadvise(sdp->device_fd, start, len, POSIX_FADV_WILLNEED);
     584             :         }
     585             : 
     586         174 :         return i;
     587             : }
     588             : 
     589             : /**
     590             :  * read_rgrps - attach rgrps to the super block
     591             :  * @sdp: incore superblock data
     592             :  * @expected: number of resource groups expected (rindex entries)
     593             :  *
     594             :  * Given the rgrp index inode, link in all rgrps into the super block
     595             :  * and be sure that they can be read.
     596             :  *
     597             :  * Returns: 0 on success, -1 on failure.
     598             :  */
     599          60 : static int read_rgrps(struct lgfs2_sbd *sdp, uint64_t expected)
     600             : {
     601             :         struct lgfs2_rgrp_tree *rgd;
     602          60 :         uint64_t count = 0;
     603          60 :         uint64_t errblock = 0;
     604          60 :         uint64_t rmax = 0;
     605          60 :         struct osi_node *n, *next = NULL;
     606          60 :         unsigned ra_window = 0;
     607             : 
     608             :         /* Turn off generic readhead */
     609          60 :         (void)posix_fadvise(sdp->device_fd, 0, 0, POSIX_FADV_RANDOM);
     610             : 
     611        4421 :         for (n = osi_first(&sdp->rgtree); n; n = next) {
     612        4365 :                 next = osi_next(n);
     613        4365 :                 rgd = (struct lgfs2_rgrp_tree *)n;
     614             :                 /* Readahead resource group headers */
     615        4365 :                 if (ra_window < RA_WINDOW/2)
     616        1003 :                         ra_window = rgrp_reada(sdp, ra_window, n);
     617             :                 /* Read resource group header */
     618        4365 :                 errblock = lgfs2_rgrp_read(sdp, rgd);
     619        4365 :                 if (errblock)
     620           4 :                         return errblock;
     621        4361 :                 ra_window--;
     622        4361 :                 count++;
     623        4361 :                 if (rgd->rt_data0 + rgd->rt_data - 1 > rmax)
     624        4361 :                         rmax = rgd->rt_data0 + rgd->rt_data - 1;
     625             :         }
     626             : 
     627          56 :         sdp->fssize = rmax;
     628          56 :         if (count != expected)
     629           0 :                 goto fail;
     630             : 
     631          56 :         (void)posix_fadvise(sdp->device_fd, 0, 0, POSIX_FADV_NORMAL);
     632          56 :         return 0;
     633             : 
     634           0 :  fail:
     635           0 :         (void)posix_fadvise(sdp->device_fd, 0, 0, POSIX_FADV_NORMAL);
     636           0 :         lgfs2_rgrp_free(sdp, &sdp->rgtree);
     637           0 :         return -1;
     638             : }
     639             : 
     640          68 : static int fetch_rgrps_level(struct fsck_cx *cx, enum rgindex_trust_level lvl, uint64_t *count, int *ok)
     641             : {
     642          68 :         int ret = 1;
     643             : 
     644          68 :         const char *level_desc[] = {
     645          68 :                 _("Checking if all rgrp and rindex values are good"),
     646          68 :                 _("Checking if rindex values may be easily repaired"),
     647          68 :                 _("Calculating where the rgrps should be if evenly spaced"),
     648          68 :                 _("Trying to rebuild rindex assuming evenly spaced rgrps"),
     649          68 :                 _("Trying to rebuild rindex assuming unevenly spaced rgrps"),
     650             :         };
     651          68 :         const char *fail_desc[] = {
     652          68 :                 _("Some damage was found; we need to take remedial measures"),
     653          68 :                 _("rindex is unevenly spaced: either gfs1-style or corrupt"),
     654          68 :                 _("rindex calculations don't match: uneven rgrp boundaries"),
     655          68 :                 _("Too many rgrp misses: rgrps must be unevenly spaced"),
     656          68 :                 _("Too much damage found: we cannot rebuild this rindex"),
     657             :         };
     658             : 
     659          68 :         log_notice(_("Level %d resource group check: %s.\n"), lvl + 1, level_desc[lvl]);
     660             : 
     661          68 :         if (rindex_repair(cx, lvl, ok) != 0)
     662           6 :                 goto fail;
     663             : 
     664          62 :         if (lgfs2_rindex_read(cx->sdp, count, ok) != 0 || !*ok)
     665           2 :                 goto fail;
     666             : 
     667          60 :         ret = read_rgrps(cx->sdp, *count);
     668          60 :         if (ret != 0)
     669           4 :                 goto fail;
     670             : 
     671          56 :         log_notice(_("(level %d passed)\n"), lvl + 1);
     672          56 :         return 0;
     673          12 : fail:
     674          12 :         if (ret == -1)
     675           0 :                 log_err(_("(level %d failed: %s)\n"), lvl + 1, fail_desc[lvl]);
     676             :         else
     677          12 :                 log_err(_("(level %d failed at block %d (0x%x): %s)\n"), lvl + 1,
     678             :                         ret, ret, fail_desc[lvl]);
     679          12 :         return ret;
     680             : }
     681             : 
     682             : /**
     683             :  * fetch_rgrps - fetch the resource groups from disk, and check their integrity
     684             :  */
     685          56 : static int fetch_rgrps(struct fsck_cx *cx)
     686             : {
     687             :         enum rgindex_trust_level trust_lvl;
     688             :         uint64_t rgcount;
     689          56 :         int ok = 1;
     690             : 
     691          56 :         log_notice(_("Validating resource group index.\n"));
     692          68 :         for (trust_lvl = BLIND_FAITH; trust_lvl <= INDIGNATION; trust_lvl++) {
     693          68 :                 int ret = 0;
     694             : 
     695          68 :                 ret = fetch_rgrps_level(cx, trust_lvl, &rgcount, &ok);
     696          68 :                 if (ret == 0)
     697          56 :                         break;
     698          12 :                 if (fsck_abort)
     699           0 :                         break;
     700             :         }
     701          56 :         if (trust_lvl > INDIGNATION) {
     702           0 :                 log_err( _("Resource group recovery impossible; I can't fix "
     703             :                            "this file system.\n"));
     704           0 :                 return -1;
     705             :         }
     706          56 :         log_info( _("%"PRIu64" resource groups found.\n"), rgcount);
     707             : 
     708          56 :         check_rgrps_integrity(cx);
     709          56 :         return 0;
     710             : }
     711             : 
     712             : /**
     713             :  * init_system_inodes
     714             :  *
     715             :  * Returns: 0 on success, -1 on failure
     716             :  */
     717          56 : static int init_system_inodes(struct fsck_cx *cx)
     718             : {
     719          56 :         struct lgfs2_sbd *sdp = cx->sdp;
     720          56 :         __be64 inumbuf = 0;
     721             :         char *buf;
     722             :         int err;
     723             : 
     724          56 :         log_info( _("Initializing special inodes...\n"));
     725             : 
     726             :         /* Get root dinode */
     727          56 :         sdp->md.rooti = lgfs2_inode_read(sdp, sdp->sd_root_dir.in_addr);
     728          56 :         if (sdp->md.rooti == NULL)
     729           0 :                 return -1;
     730             : 
     731             :         /* Look for "inum" entry in master dinode */
     732          56 :         sdp->md.inum = lgfs2_lookupi(sdp->master_dir, "inum", 4);
     733          56 :         if (!sdp->md.inum) {
     734           0 :                 if (!query(cx, _("The gfs2 system inum inode is missing. "
     735             :                               "Okay to rebuild it? (y/n) "))) {
     736           0 :                         log_err( _("fsck.gfs2 cannot continue without "
     737             :                                    "a valid inum file; aborting.\n"));
     738           0 :                         goto fail;
     739             :                 }
     740           0 :                 sdp->md.inum = lgfs2_build_inum(sdp);
     741           0 :                 if (sdp->md.inum == NULL) {
     742           0 :                         log_crit(_("Error rebuilding inum inode: %s\n"), strerror(errno));
     743           0 :                         exit(FSCK_ERROR);
     744             :                 }
     745           0 :                 lgfs2_dinode_out(sdp->md.inum, sdp->md.inum->i_bh->b_data);
     746           0 :                 if (lgfs2_bwrite(sdp->md.inum->i_bh) != 0) {
     747           0 :                         log_crit(_("System inum inode was not rebuilt. Aborting.\n"));
     748           0 :                         goto fail;
     749             :                 }
     750             :         }
     751             :         /* Read inum entry into buffer */
     752          56 :         err = lgfs2_readi(sdp->md.inum, &inumbuf, 0,
     753          56 :                          sdp->md.inum->i_size);
     754          56 :         if (err != sdp->md.inum->i_size) {
     755           0 :                 log_crit(_("Error %d reading system inum inode. "
     756             :                            "Aborting.\n"), err);
     757           0 :                 goto fail;
     758             :         }
     759             :         /* call gfs2_inum_range_in() to retrieve range */
     760          56 :         sdp->md.next_inum = be64_to_cpu(inumbuf);
     761             : 
     762          56 :         sdp->md.statfs = lgfs2_lookupi(sdp->master_dir, "statfs", 6);
     763          56 :         if (!sdp->md.statfs) {
     764           0 :                 if (!query(cx, _("The gfs2 system statfs inode is missing. "
     765             :                               "Okay to rebuild it? (y/n) "))) {
     766           0 :                         log_err( _("fsck.gfs2 cannot continue without a valid "
     767             :                                    "statfs file; aborting.\n"));
     768           0 :                         goto fail;
     769             :                 }
     770           0 :                 sdp->md.statfs = lgfs2_build_statfs(sdp);
     771           0 :                 if (sdp->md.statfs == NULL) {
     772           0 :                         log_crit(_("Error %d rebuilding statfs inode\n"), err);
     773           0 :                         exit(FSCK_ERROR);
     774             :                 }
     775           0 :                 lgfs2_dinode_out(sdp->md.statfs, sdp->md.statfs->i_bh->b_data);
     776           0 :                 if (lgfs2_bwrite(sdp->md.statfs->i_bh) != 0) {
     777           0 :                         log_err( _("Rebuild of statfs system file failed."));
     778           0 :                         log_err( _("fsck.gfs2 cannot continue without "
     779             :                                    "a valid statfs file; aborting.\n"));
     780           0 :                         goto fail;
     781             :                 }
     782           0 :                 lgfs2_init_statfs(sdp, NULL);
     783             :         }
     784          56 :         if (sdp->md.statfs->i_size) {
     785          56 :                 buf = malloc(sdp->md.statfs->i_size);
     786          56 :                 if (buf) {
     787          56 :                         err = lgfs2_readi(sdp->md.statfs, buf, 0,
     788          56 :                                          sdp->md.statfs->i_size);
     789          56 :                         if (err != sdp->md.statfs->i_size) {
     790           0 :                                 log_crit(_("Error %d reading statfs file. "
     791             :                                            "Aborting.\n"), err);
     792           0 :                                 free(buf);
     793           0 :                                 goto fail;
     794             :                         }
     795          56 :                         free(buf);
     796             :                 }
     797             :         }
     798             : 
     799          56 :         sdp->md.qinode = lgfs2_lookupi(sdp->master_dir, "quota", 5);
     800          56 :         if (!sdp->md.qinode) {
     801           0 :                 if (!query(cx, _("The gfs2 system quota inode is missing. "
     802             :                               "Okay to rebuild it? (y/n) "))) {
     803           0 :                         log_crit(_("System quota inode was not "
     804             :                                    "rebuilt.  Aborting.\n"));
     805           0 :                         goto fail;
     806             :                 }
     807           0 :                 sdp->md.qinode = lgfs2_build_quota(sdp);
     808           0 :                 if (sdp->md.qinode == NULL) {
     809           0 :                         log_crit(_("Error rebuilding quota inode: %s\n"), strerror(errno));
     810           0 :                         exit(FSCK_ERROR);
     811             :                 }
     812           0 :                 lgfs2_dinode_out(sdp->md.qinode, sdp->md.qinode->i_bh->b_data);
     813           0 :                 if (lgfs2_bwrite(sdp->md.qinode->i_bh) != 0) {
     814           0 :                         log_crit(_("Unable to rebuild system quota file "
     815             :                                    "inode.  Aborting.\n"));
     816           0 :                         goto fail;
     817             :                 }
     818             :         }
     819             : 
     820             :         /* Try to lookup the per_node inode.  If it was missing, it is now
     821             :            safe to rebuild it. */
     822          56 :         lookup_per_node(cx, 1);
     823             : 
     824             :         /*******************************************************************
     825             :          *******  Now, set boundary fields in the super block  *************
     826             :          *******************************************************************/
     827          56 :         if (set_block_ranges(sdp)){
     828           0 :                 log_err( _("Unable to determine the boundaries of the"
     829             :                         " file system.\n"));
     830           0 :                 goto fail;
     831             :         }
     832             : 
     833          56 :         return 0;
     834           0 :  fail:
     835           0 :         empty_super_block(cx);
     836             : 
     837           0 :         return -1;
     838             : }
     839             : 
     840             : /**
     841             :  * is_journal_copy - Is this a "real" dinode or a copy inside a journal?
     842             :  * A real dinode will be located at the block number in its no_addr.
     843             :  * A journal-copy will be at a different block (inside the journal).
     844             :  */
     845          30 : static int is_journal_copy(struct lgfs2_inode *ip)
     846             : {
     847          30 :         if (ip->i_num.in_addr == ip->i_bh->b_blocknr)
     848          30 :                 return 0;
     849           0 :         return 1; /* journal copy */
     850             : }
     851             : 
     852             : /**
     853             :  * peruse_system_dinode - process a system dinode
     854             :  *
     855             :  * This function looks at a system dinode and tries to figure out which
     856             :  * dinode it is: statfs, inum, per_node, master, etc.  Some of them we
     857             :  * can deduce from the contents.  For example, di_size will be a multiple
     858             :  * of 96 for the rindex.  di_size will be 8 for inum, 24 for statfs, etc.
     859             :  * the per_node directory will have a ".." entry that will lead us to
     860             :  * the master dinode if it's been destroyed.
     861             :  */
     862          66 : static void peruse_system_dinode(struct fsck_cx *cx, struct lgfs2_inode *ip)
     863             : {
     864          66 :         struct lgfs2_sbd *sdp = cx->sdp;
     865             :         struct lgfs2_inode *child_ip;
     866             :         struct lgfs2_inum inum;
     867             :         int error;
     868             : 
     869          66 :         if (ip->i_num.in_formal_ino == 2) {
     870           6 :                 if (sdp->sd_meta_dir.in_addr)
     871          12 :                         return;
     872           1 :                 log_warn(_("Found system master directory at: 0x%"PRIx64".\n"),
     873             :                          ip->i_num.in_addr);
     874           1 :                 sdp->sd_meta_dir.in_addr = ip->i_num.in_addr;
     875           1 :                 return;
     876             :         }
     877          60 :         if (ip->i_num.in_formal_ino == 3) {
     878           6 :                 if (fix_md.jiinode || is_journal_copy(ip))
     879           0 :                         goto out_discard_ip;
     880           6 :                 log_warn(_("Found system jindex file at: 0x%"PRIx64"\n"), ip->i_num.in_addr);
     881           6 :                 fix_md.jiinode = ip;
     882          54 :         } else if (is_dir(ip)) {
     883             :                 /* Check for a jindex dir entry. Only one system dir has a
     884             :                    jindex: master */
     885             :                 /* coverity[identity_transfer:SUPPRESS] */
     886           6 :                 child_ip = lgfs2_lookupi(ip, "jindex", 6);
     887           6 :                 if (child_ip) {
     888           0 :                         if (fix_md.jiinode || is_journal_copy(ip)) {
     889           0 :                                 lgfs2_inode_put(&child_ip);
     890           0 :                                 goto out_discard_ip;
     891             :                         }
     892           0 :                         fix_md.jiinode = child_ip;
     893           0 :                         sdp->sd_meta_dir.in_addr = ip->i_num.in_addr;
     894           0 :                         log_warn(_("Found system master directory at: 0x%"PRIx64"\n"),
     895             :                                  ip->i_num.in_addr);
     896           0 :                         return;
     897             :                 }
     898             : 
     899             :                 /* Check for a statfs_change0 dir entry. Only one system dir
     900             :                    has a statfs_change: per_node, and its .. will be master. */
     901             :                 /* coverity[identity_transfer:SUPPRESS] */
     902           6 :                 child_ip = lgfs2_lookupi(ip, "statfs_change0", 14);
     903           6 :                 if (child_ip) {
     904           6 :                         lgfs2_inode_put(&child_ip);
     905           6 :                         if (fix_md.pinode || is_journal_copy(ip))
     906           0 :                                 goto out_discard_ip;
     907           6 :                         log_warn(_("Found system per_node directory at: 0x%"PRIx64"\n"),
     908             :                                  ip->i_num.in_addr);
     909           6 :                         fix_md.pinode = ip;
     910           6 :                         error = lgfs2_dir_search(ip, "..", 2, NULL, &inum);
     911           6 :                         if (!error && inum.in_addr) {
     912           6 :                                 sdp->sd_meta_dir.in_addr = inum.in_addr;
     913           6 :                                 log_warn(_("From per_node's '..' master directory backtracked to: "
     914             :                                            "0x%"PRIx64"\n"), inum.in_addr);
     915             :                         }
     916           6 :                         return;
     917             :                 }
     918           0 :                 log_debug(_("Unknown system directory at block 0x%"PRIx64"\n"), ip->i_num.in_addr);
     919           0 :                 goto out_discard_ip;
     920          48 :         } else if (ip->i_size == 8) {
     921           6 :                 if (fix_md.inum || is_journal_copy(ip))
     922           0 :                         goto out_discard_ip;
     923           6 :                 fix_md.inum = ip;
     924           6 :                 log_warn(_("Found system inum file at: 0x%"PRIx64"\n"), ip->i_num.in_addr);
     925          42 :         } else if (ip->i_size == 24) {
     926          12 :                 if (fix_md.statfs || is_journal_copy(ip))
     927           6 :                         goto out_discard_ip;
     928           6 :                 fix_md.statfs = ip;
     929           6 :                 log_warn(_("Found system statfs file at: 0x%"PRIx64"\n"), ip->i_num.in_addr);
     930          30 :         } else if ((ip->i_size % 96) == 0) {
     931           6 :                 if (fix_md.riinode || is_journal_copy(ip))
     932           0 :                         goto out_discard_ip;
     933           6 :                 fix_md.riinode = ip;
     934           6 :                 log_warn(_("Found system rindex file at: 0x%"PRIx64"\n"), ip->i_num.in_addr);
     935          24 :         } else if (!fix_md.qinode && ip->i_size >= 176 &&
     936          18 :                    ip->i_num.in_formal_ino >= 12 &&
     937           0 :                    ip->i_num.in_formal_ino <= 100) {
     938           0 :                 if (is_journal_copy(ip))
     939           0 :                         goto out_discard_ip;
     940           0 :                 fix_md.qinode = ip;
     941           0 :                 log_warn(_("Found system quota file at: 0x%"PRIx64"\n"), ip->i_num.in_addr);
     942             :         } else {
     943          24 : out_discard_ip:
     944          30 :                 lgfs2_inode_put(&ip);
     945             :         }
     946             : }
     947             : 
     948             : /**
     949             :  * peruse_user_dinode - process a user dinode trying to find the root directory
     950             :  *
     951             :  */
     952           6 : static void peruse_user_dinode(struct fsck_cx *cx, struct lgfs2_inode *ip)
     953             : {
     954           6 :         struct lgfs2_sbd *sdp = cx->sdp;
     955             :         struct lgfs2_inode *parent_ip;
     956             :         struct lgfs2_inum inum;
     957             :         int error;
     958             : 
     959           6 :         if (sdp->sd_root_dir.in_addr) /* if we know the root dinode */
     960           6 :                 return;             /* we don't need to find the root */
     961           1 :         if (!is_dir(ip))  /* if this isn't a directory */
     962           0 :                 return;             /* it can't lead us to the root anyway */
     963             : 
     964           1 :         if (ip->i_num.in_formal_ino == 1) {
     965             :                 struct lgfs2_buffer_head *root_bh;
     966             : 
     967           0 :                 if (ip->i_num.in_addr == ip->i_bh->b_blocknr) {
     968           0 :                         log_warn(_("Found the root directory at: 0x%"PRIx64".\n"),
     969             :                                  ip->i_num.in_addr);
     970           0 :                         sdp->sd_root_dir.in_addr = ip->i_num.in_addr;
     971           0 :                         return;
     972             :                 }
     973           0 :                 log_warn(_("The root dinode should be at block 0x%"PRIx64" but it "
     974             :                            "seems to be destroyed.\n"),
     975             :                          ip->i_num.in_addr);
     976           0 :                 log_warn(_("Found a copy of the root directory in a journal "
     977             :                            "at block: 0x%"PRIx64".\n"),
     978             :                          ip->i_bh->b_blocknr);
     979           0 :                 if (!query(cx, _("Do you want to replace the root dinode from the copy? (y/n)"))) {
     980           0 :                         log_err(_("Damaged root dinode not fixed.\n"));
     981           0 :                         return;
     982             :                 }
     983           0 :                 root_bh = lgfs2_bread(sdp, ip->i_num.in_addr);
     984           0 :                 memcpy(root_bh->b_data, ip->i_bh->b_data, sdp->sd_bsize);
     985           0 :                 lgfs2_bmodified(root_bh);
     986           0 :                 lgfs2_brelse(root_bh);
     987           0 :                 log_warn(_("Root directory copied from the journal.\n"));
     988           0 :                 return;
     989             :         }
     990             :         /* coverity[check_after_deref:SUPPRESS] */
     991           1 :         while (ip) {
     992             :                 /* coverity[identity_transfer:SUPPRESS] */
     993           1 :                 parent_ip = lgfs2_lookupi(ip, "..", 2);
     994           1 :                 if (parent_ip && parent_ip->i_num.in_addr == ip->i_num.in_addr) {
     995           1 :                         log_warn(_("Found the root directory at: 0x%"PRIx64"\n"),
     996             :                                  ip->i_num.in_addr);
     997           1 :                         sdp->sd_root_dir.in_addr = ip->i_num.in_addr;
     998           1 :                         lgfs2_inode_put(&parent_ip);
     999           1 :                         lgfs2_inode_put(&ip);
    1000           1 :                         return;
    1001             :                 }
    1002           0 :                 if (!parent_ip)
    1003           0 :                         break;
    1004           0 :                 lgfs2_inode_put(&ip);
    1005           0 :                 ip = parent_ip;
    1006             :         }
    1007           0 :         error = lgfs2_dir_search(ip, "..", 2, NULL, &inum);
    1008           0 :         if (!error && inum.in_addr && inum.in_addr < possible_root) {
    1009           0 :                         possible_root = inum.in_addr;
    1010           0 :                         log_debug(_("Found a possible root at: 0x%"PRIx64"\n"),
    1011             :                                   possible_root);
    1012             :         }
    1013           0 :         lgfs2_inode_put(&ip);
    1014             : }
    1015             : 
    1016             : /**
    1017             :  * find_rgs_for_bsize - check a range of blocks for rgrps to determine bsize.
    1018             :  * Assumes: device is open.
    1019             :  */
    1020           6 : static int find_rgs_for_bsize(struct lgfs2_sbd *sdp, uint64_t startblock,
    1021             :                               uint32_t *known_bsize)
    1022             : {
    1023             :         uint64_t blk, max_rg_size, rb_addr;
    1024             :         uint32_t bsize, bsize2;
    1025             :         int found_rg;
    1026             : 
    1027           6 :         sdp->sd_bsize = LGFS2_DEFAULT_BSIZE;
    1028           6 :         max_rg_size = 524288;
    1029             :         /* Max RG size is 2GB. Max block size is 4K. 2G / 4K blks = 524288,
    1030             :            So this is traversing 2GB in 4K block increments. */
    1031          12 :         for (blk = startblock; blk < startblock + max_rg_size; blk++) {
    1032          12 :                 struct lgfs2_buffer_head *bh = lgfs2_bread(sdp, blk);
    1033             : 
    1034          12 :                 found_rg = 0;
    1035          60 :                 for (bsize = 0; bsize < LGFS2_DEFAULT_BSIZE; bsize += GFS2_BASIC_BLOCK) {
    1036             :                         struct gfs2_meta_header mhp;
    1037             : 
    1038          54 :                         memcpy(&mhp, bh->b_data + bsize, sizeof(mhp));
    1039          54 :                         if (be32_to_cpu(mhp.mh_magic) != GFS2_MAGIC)
    1040          42 :                                 continue;
    1041          12 :                         if (be32_to_cpu(mhp.mh_type) == GFS2_METATYPE_RG) {
    1042           6 :                                 found_rg = 1;
    1043           6 :                                 break;
    1044             :                         }
    1045             :                 }
    1046          12 :                 lgfs2_bfree(&bh);
    1047          12 :                 if (!found_rg)
    1048           6 :                         continue;
    1049             :                 /* Try all the block sizes in 512 byte multiples */
    1050          48 :                 for (bsize2 = GFS2_BASIC_BLOCK; bsize2 <= LGFS2_DEFAULT_BSIZE;
    1051          42 :                      bsize2 += GFS2_BASIC_BLOCK) {
    1052             :                         struct lgfs2_buffer_head *rb_bh;
    1053             :                         struct gfs2_meta_header *mh;
    1054             :                         int is_rb;
    1055             : 
    1056          48 :                         rb_addr = (blk * (LGFS2_DEFAULT_BSIZE / bsize2)) +
    1057          48 :                                 (bsize / bsize2) + 1;
    1058          48 :                         sdp->sd_bsize = bsize2; /* temporarily */
    1059          48 :                         rb_bh = lgfs2_bread(sdp, rb_addr);
    1060          48 :                         mh = (struct gfs2_meta_header *)rb_bh->b_data;
    1061          54 :                         is_rb = (be32_to_cpu(mh->mh_magic) == GFS2_MAGIC &&
    1062           6 :                                  be32_to_cpu(mh->mh_type) == GFS2_METATYPE_RB);
    1063          48 :                         lgfs2_brelse(rb_bh);
    1064          48 :                         if (is_rb) {
    1065           6 :                                 log_debug(_("boff:%d bsize2:%d rg:0x%"PRIx64", "
    1066             :                                             "rb:0x%"PRIx64"\n"), bsize, bsize2,
    1067             :                                           blk, rb_addr);
    1068           6 :                                 *known_bsize = bsize2;
    1069           6 :                                 break;
    1070             :                         }
    1071             :                 }
    1072           6 :                 if (!(*known_bsize)) {
    1073           0 :                         sdp->sd_bsize = LGFS2_DEFAULT_BSIZE;
    1074           0 :                         continue;
    1075             :                 }
    1076             : 
    1077           6 :                 sdp->sd_bsize = *known_bsize;
    1078           6 :                 log_warn(_("Block size determined to be: %d\n"), *known_bsize);
    1079           6 :                 return 0;
    1080             :         }
    1081           0 :         return 0;
    1082             : }
    1083             : 
    1084             : /**
    1085             :  * peruse_metadata - check a range of blocks for metadata
    1086             :  * Assumes: device is open.
    1087             :  */
    1088           6 : static int peruse_metadata(struct fsck_cx *cx, uint64_t startblock)
    1089             : {
    1090           6 :         struct lgfs2_sbd *sdp = cx->sdp;
    1091             :         uint64_t blk, max_rg_size;
    1092             :         struct lgfs2_buffer_head *bh;
    1093             :         struct lgfs2_inode *ip;
    1094             : 
    1095           6 :         max_rg_size = 2147483648ull / sdp->sd_bsize;
    1096             :         /* Max RG size is 2GB. 2G / bsize. */
    1097     3145734 :         for (blk = startblock; blk < startblock + max_rg_size; blk++) {
    1098     3145728 :                 bh = lgfs2_bread(sdp, blk);
    1099     3145728 :                 if (lgfs2_check_meta(bh->b_data, GFS2_METATYPE_DI)) {
    1100     3145656 :                         lgfs2_brelse(bh);
    1101     3145656 :                         continue;
    1102             :                 }
    1103          72 :                 ip = lgfs2_inode_get(sdp, bh);
    1104          72 :                 if (ip == NULL)
    1105           0 :                         return -1;
    1106          72 :                 ip->bh_owned = 1; /* lgfs2_inode_put() will free the bh */
    1107          72 :                 if (ip->i_flags & GFS2_DIF_SYSTEM)
    1108          66 :                         peruse_system_dinode(cx, ip);
    1109             :                 else
    1110           6 :                         peruse_user_dinode(cx, ip);
    1111             :         }
    1112           6 :         return 0;
    1113             : }
    1114             : 
    1115             : /**
    1116             :  * sb_repair - repair a damaged superblock
    1117             :  * Assumes: device is open.
    1118             :  *          The biggest RG size is 2GB
    1119             :  */
    1120           6 : static int sb_repair(struct fsck_cx *cx)
    1121             : {
    1122           6 :         struct lgfs2_sbd *sdp = cx->sdp;
    1123             :         uint64_t half;
    1124           6 :         uint32_t known_bsize = 0;
    1125           6 :         int error = 0;
    1126             : 
    1127           6 :         memset(&fix_md, 0, sizeof(fix_md));
    1128             :         /* Step 1 - First we need to determine the correct block size. */
    1129           6 :         sdp->sd_bsize = LGFS2_DEFAULT_BSIZE;
    1130           6 :         log_warn(_("Gathering information to repair the gfs2 superblock.  "
    1131             :                    "This may take some time.\n"));
    1132           6 :         error = find_rgs_for_bsize(sdp, (GFS2_SB_ADDR * GFS2_BASIC_BLOCK) /
    1133             :                                    LGFS2_DEFAULT_BSIZE, &known_bsize);
    1134           6 :         if (error)
    1135           0 :                 return error;
    1136           6 :         if (!known_bsize) {
    1137           0 :                 log_warn(_("Block size not apparent; checking elsewhere.\n"));
    1138             :                 /* First, figure out the device size.  We need that so we can
    1139             :                    find a suitable start point to determine what's what. */
    1140           0 :                 half = sdp->dinfo.size / 2; /* in bytes */
    1141           0 :                 half /= sdp->sd_bsize;
    1142             :                 /* Start looking halfway through the device for gfs2
    1143             :                    structures.  If there aren't any at all, forget it. */
    1144           0 :                 error = find_rgs_for_bsize(sdp, half, &known_bsize);
    1145           0 :                 if (error)
    1146           0 :                         return error;
    1147             :         }
    1148           6 :         if (!known_bsize) {
    1149           0 :                 log_err(_("Unable to determine the block size; this "
    1150             :                           "does not look like a gfs2 file system.\n"));
    1151           0 :                 return -1;
    1152             :         }
    1153             :         /* Step 2 - look for the sytem dinodes */
    1154           6 :         error = peruse_metadata(cx, (GFS2_SB_ADDR * GFS2_BASIC_BLOCK) /
    1155             :                                 LGFS2_DEFAULT_BSIZE);
    1156           6 :         if (error)
    1157           0 :                 return error;
    1158           6 :         if (!sdp->sd_meta_dir.in_addr) {
    1159           0 :                 log_err(_("Unable to locate the system master  directory.\n"));
    1160           0 :                 return -1;
    1161             :         }
    1162           6 :         if (!sdp->sd_root_dir.in_addr) {
    1163           0 :                 log_err(_("Unable to locate the root directory.\n"));
    1164           0 :                 if (possible_root == HIGHEST_BLOCK) {
    1165             :                         /* Take advantage of the fact that mkfs.gfs2
    1166             :                            creates master immediately after root. */
    1167           0 :                         log_err(_("Can't find any dinodes that might "
    1168             :                                   "be the root; using master - 1.\n"));
    1169           0 :                         possible_root = sdp->sd_meta_dir.in_addr - 1;
    1170             :                 }
    1171           0 :                 log_err(_("Found a possible root at: 0x%"PRIx64"\n"), possible_root);
    1172           0 :                 sdp->sd_root_dir.in_addr = possible_root;
    1173           0 :                 sdp->md.rooti = lgfs2_inode_read(sdp, possible_root);
    1174           0 :                 if (!sdp->md.rooti || sdp->md.rooti->i_magic != GFS2_MAGIC) {
    1175           0 :                         struct lgfs2_buffer_head *bh = NULL;
    1176             :                         struct lgfs2_inum inum;
    1177             : 
    1178           0 :                         log_err(_("The root dinode block is destroyed.\n"));
    1179           0 :                         log_err(_("At this point I recommend "
    1180             :                                   "reinitializing it.\n"
    1181             :                                   "Hopefully everything will later "
    1182             :                                   "be put into lost+found.\n"));
    1183           0 :                         if (!query(cx, _("Okay to reinitialize the root "
    1184             :                                      "dinode? (y/n)"))) {
    1185           0 :                                 log_err(_("The root dinode was not "
    1186             :                                           "reinitialized; aborting.\n"));
    1187           0 :                                 return -1;
    1188             :                         }
    1189           0 :                         inum.in_formal_ino = 1;
    1190           0 :                         inum.in_addr = possible_root;
    1191           0 :                         error = lgfs2_init_dinode(sdp, &bh, &inum, S_IFDIR | 0755, 0, &inum);
    1192           0 :                         if (error != 0)
    1193           0 :                                 return -1;
    1194           0 :                         lgfs2_brelse(bh);
    1195             :                 }
    1196             :         }
    1197             :         /* Step 3 - Rebuild the lock protocol and file system table name */
    1198           6 :         if (query(cx, _("Okay to fix the GFS2 superblock? (y/n)"))) {
    1199           6 :                 log_info(_("Found system master directory at: 0x%"PRIx64"\n"),
    1200             :                          sdp->sd_meta_dir.in_addr);
    1201           6 :                 sdp->master_dir = lgfs2_inode_read(sdp, sdp->sd_meta_dir.in_addr);
    1202           6 :                 if (sdp->master_dir == NULL) {
    1203           0 :                         log_crit(_("Error reading master inode: %s\n"), strerror(errno));
    1204           0 :                         return -1;
    1205             :                 }
    1206           6 :                 sdp->master_dir->i_num.in_addr = sdp->sd_meta_dir.in_addr;
    1207           6 :                 log_info(_("Found the root directory at: 0x%"PRIx64"\n"),
    1208             :                          sdp->sd_root_dir.in_addr);
    1209           6 :                 sdp->md.rooti = lgfs2_inode_read(sdp, sdp->sd_root_dir.in_addr);
    1210           6 :                 if (sdp->md.rooti == NULL) {
    1211           0 :                         log_crit(_("Error reading root inode: %s\n"), strerror(errno));
    1212           0 :                         return -1;
    1213             :                 }
    1214           6 :                 sdp->sd_fs_format = GFS2_FORMAT_FS;
    1215           6 :                 lgfs2_sb_write(sdp, sdp->device_fd);
    1216           6 :                 lgfs2_inode_put(&sdp->md.rooti);
    1217           6 :                 lgfs2_inode_put(&sdp->master_dir);
    1218           6 :                 sb_fixed = 1;
    1219             :         } else {
    1220           0 :                 log_crit(_("GFS2 superblock not fixed; fsck cannot proceed "
    1221             :                            "without a valid superblock.\n"));
    1222           0 :                 return -1;
    1223             :         }
    1224           6 :         return 0;
    1225             : }
    1226             : 
    1227             : /**
    1228             :  * fill_super_block
    1229             :  * @sdp:
    1230             :  *
    1231             :  * Returns: 0 on success, -1 on failure
    1232             :  */
    1233          57 : static int fill_super_block(struct fsck_cx *cx)
    1234             : {
    1235          57 :         struct lgfs2_sbd *sdp = cx->sdp;
    1236             :         int ret;
    1237             : 
    1238          57 :         sync();
    1239             : 
    1240          57 :         log_info( _("Initializing lists...\n"));
    1241          57 :         sdp->rgtree.osi_node = NULL;
    1242             : 
    1243          57 :         sdp->sd_bsize = LGFS2_DEFAULT_BSIZE;
    1244          57 :         if (lgfs2_compute_constants(sdp)) {
    1245           0 :                 log_crit("%s\n", _("Failed to compute file system constants"));
    1246           0 :                 return FSCK_ERROR;
    1247             :         }
    1248          57 :         ret = lgfs2_read_sb(sdp);
    1249          57 :         if (ret < 0) {
    1250           6 :                 if (sb_repair(cx) != 0)
    1251           0 :                         return -1; /* unrepairable, so exit */
    1252             :                 /* Now that we've tried to repair it, re-read it. */
    1253           6 :                 ret = lgfs2_read_sb(sdp);
    1254           6 :                 if (ret < 0)
    1255           0 :                         return FSCK_ERROR;
    1256             :         }
    1257          57 :         if (sdp->sd_fs_format > FSCK_MAX_FORMAT) {
    1258           1 :                 log_crit(_("Unsupported gfs2 format found: %"PRIu32"\n"), sdp->sd_fs_format);
    1259           1 :                 log_crit(_("A newer fsck.gfs2 is required to check this file system.\n"));
    1260           1 :                 return FSCK_USAGE;
    1261             :         }
    1262          56 :         return 0;
    1263             : }
    1264             : 
    1265             : /**
    1266             :  * init_rindex - read in the rindex file
    1267             :  */
    1268          56 : static int init_rindex(struct fsck_cx *cx)
    1269             : {
    1270          56 :         struct lgfs2_sbd *sdp = cx->sdp;
    1271             :         struct lgfs2_inode *ip;
    1272             : 
    1273          56 :         sdp->md.riinode = lgfs2_lookupi(sdp->master_dir, "rindex", 6);
    1274          56 :         if (sdp->md.riinode)
    1275          56 :                 return 0;
    1276             : 
    1277           0 :         if (!query(cx, _("The gfs2 system rindex inode is missing. "
    1278             :                       "Okay to rebuild it? (y/n) "))) {
    1279           0 :                 log_crit(_("Error: Cannot proceed without a valid rindex.\n"));
    1280           0 :                 return -1;
    1281             :         }
    1282           0 :         ip = lgfs2_build_rindex(sdp);
    1283           0 :         if (ip == NULL) {
    1284           0 :                 log_crit(_("Error rebuilding rindex: %s\n"), strerror(errno));
    1285           0 :                 return -1;
    1286             :         }
    1287           0 :         lgfs2_inode_put(&ip);
    1288           0 :         return 0;
    1289             : }
    1290             : 
    1291             : /**
    1292             :  * initialize - initialize superblock pointer
    1293             :  *
    1294             :  */
    1295          57 : int initialize(struct fsck_cx *cx, int *all_clean)
    1296             : {
    1297          57 :         struct lgfs2_sbd *sdp = cx->sdp;
    1298          57 :         int clean_journals = 0, open_flag;
    1299             :         int err;
    1300             : 
    1301          57 :         *all_clean = 0;
    1302             : 
    1303          57 :         if (cx->opts->no)
    1304          42 :                 open_flag = O_RDONLY;
    1305             :         else
    1306          15 :                 open_flag = O_RDWR | O_EXCL;
    1307             : 
    1308          57 :         sdp->device_fd = open(cx->opts->device, open_flag);
    1309          57 :         if (sdp->device_fd < 0) {
    1310             :                 struct mntent *mnt;
    1311           0 :                 if (open_flag == O_RDONLY || errno != EBUSY) {
    1312           0 :                         log_crit( _("Unable to open device: %s\n"),
    1313             :                                  cx->opts->device);
    1314           0 :                         return FSCK_USAGE;
    1315             :                 }
    1316             :                 /* We can't open it EXCL.  It may be already open rw (in which
    1317             :                    case we want to deny them access) or it may be mounted as
    1318             :                    the root file system at boot time (in which case we need to
    1319             :                    allow it.)
    1320             :                    If the device is busy, but not because it's mounted, fail.
    1321             :                    This protects against cases where the file system is LVM
    1322             :                    and perhaps mounted on a different node.
    1323             :                    Try opening without O_EXCL. */
    1324           0 :                 sdp->device_fd = lgfs2_open_mnt_dev(cx->opts->device, O_RDWR, &mnt);
    1325           0 :                 if (sdp->device_fd < 0)
    1326           0 :                         goto mount_fail;
    1327             :                 /* If the device is mounted, but not mounted RO, fail.  This
    1328             :                    protects them against cases where the file system is
    1329             :                    mounted RW, but still allows us to check our own root
    1330             :                    file system. */
    1331           0 :                 if (!hasmntopt(mnt, MNTOPT_RO))
    1332           0 :                         goto close_fail;
    1333             :                 /* The device is mounted RO, so it's likely our own root
    1334             :                    file system.  We can only do so much to protect the users
    1335             :                    from themselves. */
    1336           0 :                 was_mounted_ro = 1;
    1337             :         }
    1338             : 
    1339          57 :         if (lgfs2_get_dev_info(sdp->device_fd, &sdp->dinfo)) {
    1340           0 :                 perror(cx->opts->device);
    1341           0 :                 return FSCK_ERROR;
    1342             :         }
    1343             : 
    1344             :         /* read in sb from disk */
    1345          57 :         err = fill_super_block(cx);
    1346          57 :         if (err != FSCK_OK)
    1347           1 :                 return err;
    1348             : 
    1349             :         /* Change lock protocol to be fsck_* instead of lock_* */
    1350          56 :         if (!cx->opts->no && preen_is_safe(sdp, cx->opts)) {
    1351          14 :                 if (block_mounters(sdp, 1)) {
    1352           0 :                         log_err( _("Unable to block other mounters\n"));
    1353           0 :                         return FSCK_USAGE;
    1354             :                 }
    1355             :         }
    1356             : 
    1357          56 :         sdp->master_dir = lgfs2_inode_read(sdp, sdp->sd_meta_dir.in_addr);
    1358          56 :         if (sdp->master_dir->i_magic != GFS2_MAGIC ||
    1359          56 :             sdp->master_dir->i_mh_type != GFS2_METATYPE_DI ||
    1360          56 :             !sdp->master_dir->i_size) {
    1361           0 :                 lgfs2_inode_put(&sdp->master_dir);
    1362           0 :                 rebuild_sysdir(cx);
    1363           0 :                 sdp->master_dir = lgfs2_inode_read(sdp, sdp->sd_meta_dir.in_addr);
    1364           0 :                 if (sdp->master_dir == NULL) {
    1365           0 :                         log_crit(_("Error reading master directory: %s\n"), strerror(errno));
    1366           0 :                         return FSCK_ERROR;
    1367             :                 }
    1368             :         }
    1369             : 
    1370             :         /* Look up the "per_node" inode.  If there are journals missing, we
    1371             :            need to figure out what's missing from per_node. And we need all
    1372             :            our journals to be there before we can replay them. */
    1373          56 :         lookup_per_node(cx, 0);
    1374             : 
    1375             :         /* We need rindex first in case jindex is missing and needs to read
    1376             :            in the rgrps before rebuilding it. However, note that if the rindex
    1377             :            is damaged, we need the journals to repair it. That's because the
    1378             :            journals likely contain rgrps and bitmaps, which we need to ignore
    1379             :            when we're trying to find the rgrps. */
    1380          56 :         if (init_rindex(cx))
    1381           0 :                 return FSCK_ERROR;
    1382             : 
    1383          56 :         if (fetch_rgrps(cx))
    1384           0 :                 return FSCK_ERROR;
    1385             : 
    1386             :         /* We need to read in jindex in order to replay the journals. If
    1387             :            there's an error, we may proceed and let init_system_inodes
    1388             :            try to rebuild it. */
    1389          56 :         if (init_jindex(cx, 1) == 0) {
    1390          56 :                 if (replay_journals(cx, &clean_journals)) {
    1391           0 :                         if (!cx->opts->no && preen_is_safe(sdp, cx->opts))
    1392           0 :                                 block_mounters(sdp, 0);
    1393           0 :                         stack;
    1394           0 :                         return FSCK_ERROR;
    1395             :                 }
    1396          56 :                 if (sdp->md.journals == clean_journals)
    1397          55 :                         *all_clean = 1;
    1398           1 :                 else if (cx->opts->force || !cx->opts->preen)
    1399           1 :                         log_notice( _("\nJournal recovery complete.\n"));
    1400             : 
    1401          56 :                 if (!cx->opts->force && *all_clean && cx->opts->preen)
    1402           0 :                         return FSCK_OK;
    1403             :         }
    1404             : 
    1405          56 :         if (init_system_inodes(cx))
    1406           0 :                 return FSCK_ERROR;
    1407             : 
    1408          56 :         return FSCK_OK;
    1409             : 
    1410           0 : close_fail:
    1411           0 :         close(sdp->device_fd);
    1412           0 : mount_fail:
    1413           0 :         log_crit( _("Device %s is busy.\n"), cx->opts->device);
    1414           0 :         return FSCK_USAGE;
    1415             : }
    1416             : 
    1417          56 : void destroy(struct fsck_cx *cx)
    1418             : {
    1419          56 :         struct lgfs2_sbd *sdp = cx->sdp;
    1420             : 
    1421          56 :         if (!cx->opts->no) {
    1422          14 :                 if (block_mounters(sdp, 0)) {
    1423           0 :                         log_warn( _("Unable to unblock other mounters - manual intervention required\n"));
    1424           0 :                         log_warn( _("Use 'gfs2_tool sb <device> proto' to fix\n"));
    1425             :                 }
    1426          14 :                 log_info( _("Syncing the device.\n"));
    1427          14 :                 fsync(sdp->device_fd);
    1428             :         }
    1429          56 :         empty_super_block(cx);
    1430          56 :         close(sdp->device_fd);
    1431          56 :         if (was_mounted_ro && errors_corrected) {
    1432           0 :                 sdp->device_fd = open("/proc/sys/vm/drop_caches", O_WRONLY);
    1433           0 :                 if (sdp->device_fd >= 0) {
    1434           0 :                         if (write(sdp->device_fd, "2", 1) == 2) {
    1435           0 :                                 close(sdp->device_fd);
    1436           0 :                                 return;
    1437             :                         }
    1438           0 :                         close(sdp->device_fd);
    1439             :                 }
    1440           0 :                 log_warn(_("fsck.gfs2: Could not flush caches (non-fatal).\n"));
    1441             :         }
    1442             : }

Generated by: LCOV version 1.14