LCOV - code coverage report
Current view: top level - fsck - initialize.c (source / functions) Coverage Total Hit
Test: gfs2-utils.info Lines: 54.5 % 778 424
Test Date: 2024-03-07 16:24:06 Functions: 96.0 % 25 24

            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           57 : static void dup_free(struct fsck_cx *cx)
      70              : {
      71              :         struct osi_node *n;
      72              :         struct duptree *dt;
      73              : 
      74           57 :         while ((n = osi_first(&cx->dup_blocks))) {
      75            0 :                 dt = (struct duptree *)n;
      76            0 :                 dup_delete(cx, dt);
      77              :         }
      78           57 : }
      79              : 
      80           57 : static void dirtree_free(struct fsck_cx *cx)
      81              : {
      82              :         struct osi_node *n;
      83              :         struct dir_info *dt;
      84              : 
      85          285 :         while ((n = osi_first(&cx->dirtree))) {
      86          228 :                 dt = (struct dir_info *)n;
      87          228 :                 dirtree_delete(cx, dt);
      88              :         }
      89           57 : }
      90              : 
      91           57 : static void inodetree_free(struct fsck_cx *cx)
      92              : {
      93              :         struct osi_node *n;
      94              :         struct inode_info *dt;
      95              : 
      96           57 :         while ((n = osi_first(&cx->inodetree))) {
      97            0 :                 dt = (struct inode_info *)n;
      98            0 :                 inodetree_delete(cx, dt);
      99              :         }
     100           57 : }
     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           57 : static void empty_super_block(struct fsck_cx *cx)
     112              : {
     113           57 :         log_info( _("Freeing buffers.\n"));
     114           57 :         lgfs2_rgrp_free(cx->sdp, &cx->sdp->rgtree);
     115              : 
     116           57 :         inodetree_free(cx);
     117           57 :         dirtree_free(cx);
     118           57 :         dup_free(cx);
     119           57 : }
     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           57 : static int set_block_ranges(struct lgfs2_sbd *sdp)
     132              : {
     133           57 :         struct osi_node *n, *next = NULL;
     134              :         struct lgfs2_rgrp_tree *rgd;
     135           57 :         uint64_t rmax = 0;
     136           57 :         uint64_t rmin = 0;
     137              :         ssize_t count;
     138              :         char *buf;
     139              : 
     140           57 :         log_info( _("Setting block ranges..."));
     141              : 
     142         4497 :         for (n = osi_first(&sdp->rgtree); n; n = next) {
     143         4440 :                 next = osi_next(n);
     144         4440 :                 rgd = (struct lgfs2_rgrp_tree *)n;
     145         4440 :                 if (rgd->rt_data0 + rgd->rt_data &&
     146         4440 :                     rgd->rt_data0 + rgd->rt_data - 1 > rmax)
     147         4440 :                         rmax = rgd->rt_data0 + rgd->rt_data - 1;
     148         4440 :                 if (!rmin || rgd->rt_data0 < rmin)
     149           57 :                         rmin = rgd->rt_data0;
     150              :         }
     151              : 
     152           57 :         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           57 :         last_data_block = rmax;
     161           57 :         first_data_block = rmin;
     162              : 
     163           57 :         buf = calloc(1, sdp->sd_bsize);
     164           57 :         if (buf == NULL) {
     165            0 :                 log_crit(_("Failed to determine file system boundaries: %s\n"), strerror(errno));
     166            0 :                 return -1;
     167              :         }
     168           57 :         count = pread(sdp->device_fd, buf, sdp->sd_bsize, (last_fs_block * sdp->sd_bsize));
     169           57 :         free(buf);
     170           57 :         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           57 :         log_info(_("0x%"PRIx64" to 0x%"PRIx64"\n"), first_data_block, last_data_block);
     177           57 :         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         4440 : 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         4440 :         int rgb, x, y, off, bytes_to_check, total_bytes_to_check, asked = 0;
     193         4440 :         struct lgfs2_sbd *sdp = cx->sdp;
     194              :         unsigned int state;
     195              :         uint64_t diblock;
     196              :         struct lgfs2_buffer_head *bh;
     197              : 
     198         4440 :         rg_free = rg_reclaimed = rg_unlinked = rg_usedmeta = rg_useddi = 0;
     199         4440 :         total_bytes_to_check = rgd->rt_bitbytes;
     200              : 
     201         4440 :         *this_rg_fixed = *this_rg_bad = *this_rg_cleaned = 0;
     202              : 
     203         4440 :         diblock = rgd->rt_data0;
     204       137306 :         for (rgb = 0; rgb < rgd->rt_length; rgb++){
     205              :                 /* Count up the free blocks in the bitmap */
     206       132866 :                 off = (rgb) ? sizeof(struct gfs2_meta_header) :
     207              :                         sizeof(struct gfs2_rgrp);
     208       132866 :                 if (total_bytes_to_check <= sdp->sd_bsize - off)
     209         4440 :                         bytes_to_check = total_bytes_to_check;
     210              :                 else
     211       128426 :                         bytes_to_check = sdp->sd_bsize - off;
     212       132866 :                 total_bytes_to_check -= bytes_to_check;
     213    120818786 :                 for (x = 0; x < bytes_to_check; x++) {
     214              :                         unsigned char *byte;
     215              : 
     216    120685920 :                         byte = (unsigned char *)&rgd->rt_bits[rgb].bi_data[off + x];
     217    120685920 :                         if (*byte == 0x55) {
     218       499377 :                                 diblock += GFS2_NBBY;
     219       499377 :                                 continue;
     220              :                         }
     221    120186543 :                         if (*byte == 0x00) {
     222    120186227 :                                 diblock += GFS2_NBBY;
     223    120186227 :                                 rg_free += GFS2_NBBY;
     224    120186227 :                                 continue;
     225              :                         }
     226         1580 :                         for (y = 0; y < GFS2_NBBY; y++) {
     227         1264 :                                 state = (*byte >>
     228         1264 :                                          (GFS2_BIT_SIZE * y)) & GFS2_BIT_MASK;
     229         1264 :                                 if (state == GFS2_BLKST_USED) {
     230          468 :                                         diblock++;
     231          468 :                                         continue;
     232              :                                 }
     233          796 :                                 if (state == GFS2_BLKST_DINODE) {
     234          712 :                                         diblock++;
     235          712 :                                         continue;
     236              :                                 }
     237           84 :                                 if (state == GFS2_BLKST_FREE) {
     238           84 :                                         diblock++;
     239           84 :                                         rg_free++;
     240           84 :                                         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         4440 :         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         4440 :         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         4440 : }
     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           57 : static void check_rgrps_integrity(struct fsck_cx *cx)
     326              : {
     327           57 :         struct osi_node *n, *next = NULL;
     328           57 :         int rgs_good = 0, rgs_bad = 0, rgs_fixed = 0, rgs_cleaned = 0;
     329           57 :         int was_bad = 0, was_fixed = 0, was_cleaned = 0;
     330              :         struct lgfs2_rgrp_tree *rgd;
     331           57 :         int reclaim_unlinked = 0;
     332              : 
     333           57 :         log_info( _("Checking the integrity of all resource groups.\n"));
     334         4497 :         for (n = osi_first(&cx->sdp->rgtree); n; n = next) {
     335         4440 :                 next = osi_next(n);
     336         4440 :                 rgd = (struct lgfs2_rgrp_tree *)n;
     337         4440 :                 if (fsck_abort)
     338            0 :                         return;
     339         4440 :                 check_rgrp_integrity(cx, rgd, &reclaim_unlinked,
     340              :                                      &was_fixed, &was_bad, &was_cleaned);
     341         4440 :                 if (was_fixed)
     342            4 :                         rgs_fixed++;
     343         4440 :                 if (was_cleaned)
     344            0 :                         rgs_cleaned++;
     345         4440 :                 else if (was_bad)
     346            4 :                         rgs_bad++;
     347              :                 else
     348         4436 :                         rgs_good++;
     349              :         }
     350           57 :         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          114 : static void lookup_per_node(struct fsck_cx *cx, int allow_rebuild)
     530              : {
     531          114 :         struct lgfs2_sbd *sdp = cx->sdp;
     532              : 
     533          114 :         if (sdp->md.pinode)
     534           57 :                 return;
     535              : 
     536           57 :         sdp->md.pinode = lgfs2_lookupi(sdp->master_dir, "per_node", 8);
     537           57 :         if (sdp->md.pinode)
     538           57 :                 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         1022 : 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        14280 :         for (i = 0; i < RA_WINDOW; i++, n = osi_next(n)) {
     576        14103 :                 if (n == NULL)
     577          845 :                         return i;
     578        13258 :                 if (i < cur_window)
     579         8732 :                         continue;
     580         4526 :                 rgd = (struct lgfs2_rgrp_tree *)n;
     581         4526 :                 start = rgd->rt_addr * sdp->sd_bsize;
     582         4526 :                 len = rgd->rt_length * sdp->sd_bsize;
     583         4526 :                 (void)posix_fadvise(sdp->device_fd, start, len, POSIX_FADV_WILLNEED);
     584              :         }
     585              : 
     586          177 :         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           61 : static int read_rgrps(struct lgfs2_sbd *sdp, uint64_t expected)
     600              : {
     601              :         struct lgfs2_rgrp_tree *rgd;
     602           61 :         uint64_t count = 0;
     603           61 :         uint64_t errblock = 0;
     604           61 :         uint64_t rmax = 0;
     605           61 :         struct osi_node *n, *next = NULL;
     606           61 :         unsigned ra_window = 0;
     607              : 
     608              :         /* Turn off generic readhead */
     609           61 :         (void)posix_fadvise(sdp->device_fd, 0, 0, POSIX_FADV_RANDOM);
     610              : 
     611         4503 :         for (n = osi_first(&sdp->rgtree); n; n = next) {
     612         4446 :                 next = osi_next(n);
     613         4446 :                 rgd = (struct lgfs2_rgrp_tree *)n;
     614              :                 /* Readahead resource group headers */
     615         4446 :                 if (ra_window < RA_WINDOW/2)
     616         1022 :                         ra_window = rgrp_reada(sdp, ra_window, n);
     617              :                 /* Read resource group header */
     618         4446 :                 errblock = lgfs2_rgrp_read(sdp, rgd);
     619         4446 :                 if (errblock)
     620            4 :                         return errblock;
     621         4442 :                 ra_window--;
     622         4442 :                 count++;
     623         4442 :                 if (rgd->rt_data0 + rgd->rt_data - 1 > rmax)
     624         4442 :                         rmax = rgd->rt_data0 + rgd->rt_data - 1;
     625              :         }
     626              : 
     627           57 :         sdp->fssize = rmax;
     628           57 :         if (count != expected)
     629            0 :                 goto fail;
     630              : 
     631           57 :         (void)posix_fadvise(sdp->device_fd, 0, 0, POSIX_FADV_NORMAL);
     632           57 :         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           69 : static int fetch_rgrps_level(struct fsck_cx *cx, enum rgindex_trust_level lvl, uint64_t *count, int *ok)
     641              : {
     642           69 :         int ret = 1;
     643              : 
     644           69 :         const char *level_desc[] = {
     645           69 :                 _("Checking if all rgrp and rindex values are good"),
     646           69 :                 _("Checking if rindex values may be easily repaired"),
     647           69 :                 _("Calculating where the rgrps should be if evenly spaced"),
     648           69 :                 _("Trying to rebuild rindex assuming evenly spaced rgrps"),
     649           69 :                 _("Trying to rebuild rindex assuming unevenly spaced rgrps"),
     650              :         };
     651           69 :         const char *fail_desc[] = {
     652           69 :                 _("Some damage was found; we need to take remedial measures"),
     653           69 :                 _("rindex is unevenly spaced: either gfs1-style or corrupt"),
     654           69 :                 _("rindex calculations don't match: uneven rgrp boundaries"),
     655           69 :                 _("Too many rgrp misses: rgrps must be unevenly spaced"),
     656           69 :                 _("Too much damage found: we cannot rebuild this rindex"),
     657              :         };
     658              : 
     659           69 :         log_notice(_("Level %d resource group check: %s.\n"), lvl + 1, level_desc[lvl]);
     660              : 
     661           69 :         if (rindex_repair(cx, lvl, ok) != 0)
     662            6 :                 goto fail;
     663              : 
     664           63 :         if (lgfs2_rindex_read(cx->sdp, count, ok) != 0 || !*ok)
     665            2 :                 goto fail;
     666              : 
     667           61 :         ret = read_rgrps(cx->sdp, *count);
     668           61 :         if (ret != 0)
     669            4 :                 goto fail;
     670              : 
     671           57 :         log_notice(_("(level %d passed)\n"), lvl + 1);
     672           57 :         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           57 : static int fetch_rgrps(struct fsck_cx *cx)
     686              : {
     687              :         enum rgindex_trust_level trust_lvl;
     688              :         uint64_t rgcount;
     689           57 :         int ok = 1;
     690              : 
     691           57 :         log_notice(_("Validating resource group index.\n"));
     692           69 :         for (trust_lvl = BLIND_FAITH; trust_lvl <= INDIGNATION; trust_lvl++) {
     693           69 :                 int ret = 0;
     694              : 
     695           69 :                 ret = fetch_rgrps_level(cx, trust_lvl, &rgcount, &ok);
     696           69 :                 if (ret == 0)
     697           57 :                         break;
     698           12 :                 if (fsck_abort)
     699            0 :                         break;
     700              :         }
     701           57 :         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           57 :         log_info( _("%"PRIu64" resource groups found.\n"), rgcount);
     707              : 
     708           57 :         check_rgrps_integrity(cx);
     709           57 :         return 0;
     710              : }
     711              : 
     712              : /**
     713              :  * init_system_inodes
     714              :  *
     715              :  * Returns: 0 on success, -1 on failure
     716              :  */
     717           57 : static int init_system_inodes(struct fsck_cx *cx)
     718              : {
     719           57 :         struct lgfs2_sbd *sdp = cx->sdp;
     720           57 :         __be64 inumbuf = 0;
     721              :         char *buf;
     722              :         int err;
     723              : 
     724           57 :         log_info( _("Initializing special inodes...\n"));
     725              : 
     726              :         /* Get root dinode */
     727           57 :         sdp->md.rooti = lgfs2_inode_read(sdp, sdp->sd_root_dir.in_addr);
     728           57 :         if (sdp->md.rooti == NULL)
     729            0 :                 return -1;
     730              : 
     731              :         /* Look for "inum" entry in master dinode */
     732           57 :         sdp->md.inum = lgfs2_lookupi(sdp->master_dir, "inum", 4);
     733           57 :         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           57 :         err = lgfs2_readi(sdp->md.inum, &inumbuf, 0,
     753           57 :                          sdp->md.inum->i_size);
     754           57 :         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           57 :         sdp->md.next_inum = be64_to_cpu(inumbuf);
     761              : 
     762           57 :         sdp->md.statfs = lgfs2_lookupi(sdp->master_dir, "statfs", 6);
     763           57 :         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           57 :         if (sdp->md.statfs->i_size) {
     785           57 :                 buf = malloc(sdp->md.statfs->i_size);
     786           57 :                 if (buf) {
     787           57 :                         err = lgfs2_readi(sdp->md.statfs, buf, 0,
     788           57 :                                          sdp->md.statfs->i_size);
     789           57 :                         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           57 :                         free(buf);
     796              :                 }
     797              :         }
     798              : 
     799           57 :         sdp->md.qinode = lgfs2_lookupi(sdp->master_dir, "quota", 5);
     800           57 :         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           57 :         lookup_per_node(cx, 1);
     823              : 
     824              :         /*******************************************************************
     825              :          *******  Now, set boundary fields in the super block  *************
     826              :          *******************************************************************/
     827           57 :         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           57 :         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           58 : static int fill_super_block(struct fsck_cx *cx)
    1234              : {
    1235           58 :         struct lgfs2_sbd *sdp = cx->sdp;
    1236              :         int ret;
    1237              : 
    1238           58 :         sync();
    1239              : 
    1240           58 :         log_info( _("Initializing lists...\n"));
    1241           58 :         sdp->rgtree.osi_node = NULL;
    1242              : 
    1243           58 :         sdp->sd_bsize = LGFS2_DEFAULT_BSIZE;
    1244           58 :         if (lgfs2_compute_constants(sdp)) {
    1245            0 :                 log_crit("%s\n", _("Failed to compute file system constants"));
    1246            0 :                 return FSCK_ERROR;
    1247              :         }
    1248           58 :         ret = lgfs2_read_sb(sdp);
    1249           58 :         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           58 :         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           57 :         return 0;
    1263              : }
    1264              : 
    1265              : /**
    1266              :  * init_rindex - read in the rindex file
    1267              :  */
    1268           57 : static int init_rindex(struct fsck_cx *cx)
    1269              : {
    1270           57 :         struct lgfs2_sbd *sdp = cx->sdp;
    1271              :         struct lgfs2_inode *ip;
    1272              : 
    1273           57 :         sdp->md.riinode = lgfs2_lookupi(sdp->master_dir, "rindex", 6);
    1274           57 :         if (sdp->md.riinode)
    1275           57 :                 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           58 : int initialize(struct fsck_cx *cx, int *all_clean)
    1296              : {
    1297           58 :         struct lgfs2_sbd *sdp = cx->sdp;
    1298           58 :         int clean_journals = 0, open_flag;
    1299              :         int err;
    1300              : 
    1301           58 :         *all_clean = 0;
    1302              : 
    1303           58 :         if (cx->opts->no)
    1304           43 :                 open_flag = O_RDONLY;
    1305              :         else
    1306           15 :                 open_flag = O_RDWR | O_EXCL;
    1307              : 
    1308           58 :         sdp->device_fd = open(cx->opts->device, open_flag);
    1309           58 :         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           58 :         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           58 :         err = fill_super_block(cx);
    1346           58 :         if (err != FSCK_OK)
    1347            1 :                 return err;
    1348              : 
    1349              :         /* Change lock protocol to be fsck_* instead of lock_* */
    1350           57 :         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           57 :         sdp->master_dir = lgfs2_inode_read(sdp, sdp->sd_meta_dir.in_addr);
    1358           57 :         if (sdp->master_dir->i_magic != GFS2_MAGIC ||
    1359           57 :             sdp->master_dir->i_mh_type != GFS2_METATYPE_DI ||
    1360           57 :             !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           57 :         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           57 :         if (init_rindex(cx))
    1381            0 :                 return FSCK_ERROR;
    1382              : 
    1383           57 :         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           57 :         if (init_jindex(cx, 1) == 0) {
    1390           57 :                 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           57 :                 if (sdp->md.journals == clean_journals)
    1397           56 :                         *all_clean = 1;
    1398            1 :                 else if (cx->opts->force || !cx->opts->preen)
    1399            1 :                         log_notice( _("\nJournal recovery complete.\n"));
    1400              : 
    1401           57 :                 if (!cx->opts->force && *all_clean && cx->opts->preen)
    1402            0 :                         return FSCK_OK;
    1403              :         }
    1404              : 
    1405           57 :         if (init_system_inodes(cx))
    1406            0 :                 return FSCK_ERROR;
    1407              : 
    1408           57 :         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           57 : void destroy(struct fsck_cx *cx)
    1418              : {
    1419           57 :         struct lgfs2_sbd *sdp = cx->sdp;
    1420              : 
    1421           57 :         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           57 :         empty_super_block(cx);
    1430           57 :         close(sdp->device_fd);
    1431           57 :         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 2.0-1