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

Generated by: LCOV version 1.14