LCOV - code coverage report
Current view: top level - fsck - pass2.c (source / functions) Hit Total Coverage
Test: gfs2-utils.info Lines: 235 1028 22.9 %
Date: 2023-09-27 13:48:55 Functions: 16 33 48.5 %

          Line data    Source code
       1             : #include "clusterautoconfig.h"
       2             : 
       3             : #include <dirent.h>
       4             : #include <stdio.h>
       5             : #include <stdlib.h>
       6             : #include <string.h>
       7             : #include <inttypes.h>
       8             : #include <sys/stat.h>
       9             : #include <libintl.h>
      10             : #define _(String) gettext(String)
      11             : 
      12             : #include <logging.h>
      13             : #include "libgfs2.h"
      14             : #include "fsck.h"
      15             : #include "util.h"
      16             : #include "metawalk.h"
      17             : #include "link.h"
      18             : #include "lost_n_found.h"
      19             : #include "inode_hash.h"
      20             : #include "afterpass1_common.h"
      21             : #include "fs_recovery.h"
      22             : 
      23             : #define MAX_FILENAME 256
      24             : 
      25             : static struct metawalk_fxns pass2_fxns;
      26             : 
      27             : static struct metawalk_fxns delete_eattrs = {
      28             :         .check_eattr_indir = delete_eattr_indir,
      29             :         .check_eattr_leaf = delete_eattr_leaf,
      30             :         .check_eattr_entry = delete_eattr_entry,
      31             :         .check_eattr_extentry = delete_eattr_extentry,
      32             : };
      33             : 
      34             : /* Set children's parent inode in dir_info structure - ext2 does not set
      35             :  * dotdot inode here, but instead in pass3 - should we? */
      36         112 : static int set_parent_dir(struct fsck_cx *cx, struct lgfs2_inum child, struct lgfs2_inum parent)
      37             : {
      38             :         struct dir_info *di;
      39             : 
      40         112 :         di = dirtree_find(cx, child.in_addr);
      41         112 :         if (!di) {
      42           0 :                 log_err(_("Unable to find block %"PRIu64" (0x%"PRIx64") in dir_info list\n"),
      43             :                         child.in_addr, child.in_addr);
      44           0 :                 return -1;
      45             :         }
      46             : 
      47         112 :         if (di->dinode.in_addr == child.in_addr &&
      48         112 :             di->dinode.in_formal_ino == child.in_formal_ino) {
      49         112 :                 if (di->treewalk_parent) {
      50           0 :                         log_err(_("Another directory at block %"PRIu64" (0x%"PRIx64") "
      51             :                                   "already contains this child %"PRIu64" (0x%"PRIx64")"
      52             :                                   " - checking parent %"PRIu64" (0x%"PRIx64")\n"),
      53             :                                 di->treewalk_parent, di->treewalk_parent, child.in_addr,
      54             :                                 child.in_addr, parent.in_addr, parent.in_addr);
      55           0 :                         return 1;
      56             :                 }
      57         112 :                 log_debug(_("Child %"PRIu64" (0x%"PRIx64") has parent %"PRIu64" (0x%"PRIx64")\n"),
      58             :                           child.in_addr, child.in_addr, parent.in_addr, parent.in_addr);
      59         112 :                 di->treewalk_parent = parent.in_addr;
      60             :         }
      61             : 
      62         112 :         return 0;
      63             : }
      64             : 
      65             : /* Set's the child's '..' directory inode number in dir_info structure */
      66         224 : static int set_dotdot_dir(struct fsck_cx *cx, uint64_t childblock, struct lgfs2_inum parent)
      67             : {
      68             :         struct dir_info *di;
      69             : 
      70         224 :         di = dirtree_find(cx, childblock);
      71         224 :         if (!di) {
      72           0 :                 log_err( _("Unable to find block %"PRIu64" (0x%" PRIx64
      73             :                            ") in dir_info tree\n"), childblock, childblock);
      74           0 :                 return -1;
      75             :         }
      76         224 :         if (di->dinode.in_addr != childblock) {
      77           0 :                 log_debug("'..' doesn't point to what we found: childblock "
      78             :                           "(0x%"PRIx64") != dinode (0x%"PRIx64")\n",
      79             :                           childblock, di->dinode.in_addr);
      80           0 :                 return -1;
      81             :         }
      82             :         /* Special case for root inode because we set it earlier */
      83         224 :         if (di->dotdot_parent.in_addr &&
      84           0 :             cx->sdp->md.rooti->i_num.in_addr != di->dinode.in_addr) {
      85             :                 /* This should never happen */
      86           0 :                 log_crit(_("Dotdot parent already set for block %"PRIu64" (0x%"PRIx64") "
      87             :                            "-> %"PRIu64" (0x%"PRIx64")\n"),
      88             :                          childblock, childblock, di->dotdot_parent.in_addr, di->dotdot_parent.in_addr);
      89           0 :                 return -1;
      90             :         }
      91         224 :         log_debug("Setting '..' for directory block (0x%"PRIx64") to parent (0x%"PRIx64")\n",
      92             :                   childblock, parent.in_addr);
      93         224 :         di->dotdot_parent.in_addr = parent.in_addr;
      94         224 :         di->dotdot_parent.in_formal_ino = parent.in_formal_ino;
      95         224 :         return 0;
      96             : }
      97             : 
      98           0 : static int check_eattr_indir(struct fsck_cx *cx, struct lgfs2_inode *ip, uint64_t block,
      99             :                              uint64_t parent, struct lgfs2_buffer_head **bh,
     100             :                              void *private)
     101             : {
     102           0 :         *bh = lgfs2_bread(ip->i_sbd, block);
     103           0 :         return 0;
     104             : }
     105           0 : static int check_eattr_leaf(struct fsck_cx *cx, struct lgfs2_inode *ip, uint64_t block,
     106             :                             uint64_t parent, struct lgfs2_buffer_head **bh,
     107             :                             void *private)
     108             : {
     109           0 :         *bh = lgfs2_bread(ip->i_sbd, block);
     110           0 :         return 0;
     111             : }
     112             : 
     113           0 : static const char *de_type_string(uint8_t de_type)
     114             : {
     115           0 :         const char *de_types[15] = {"unknown", "fifo", "chrdev", "invalid",
     116             :                                     "directory", "invalid", "blkdev", "invalid",
     117             :                                     "file", "invalid", "symlink", "invalid",
     118             :                                     "socket", "invalid", "wht"};
     119           0 :         if (de_type < 15)
     120           0 :                 return de_types[de_type];
     121           0 :         return de_types[3]; /* invalid */
     122             : }
     123             : 
     124        1036 : static int check_file_type(struct fsck_cx *cx, uint64_t block, uint8_t de_type, int q,
     125             :                            int *isdir)
     126             : {
     127             :         struct dir_info *dt;
     128             : 
     129        1036 :         *isdir = 0;
     130        1036 :         if (q != GFS2_BLKST_DINODE) {
     131           0 :                 log_err( _("Invalid block type\n"));
     132           0 :                 return -1;
     133             :         }
     134        1036 :         if (de_type == DT_DIR)
     135         560 :                 *isdir = 1;
     136             :         /* Check if the dinode is in the dir tree */
     137        1036 :         dt = dirtree_find(cx, block);
     138             :         /* This is a bit confusing, so let me explain:
     139             :            If the dirent says the inode supposed to be for a directory,
     140             :            it should be in the dir tree. If it is, no problem, return 0.
     141             :            If it's not, return 1 (wrong type). If it's not supposed to be
     142             :            a directory, it shouldn't be in the dir tree. */
     143        1036 :         if (dt)
     144         560 :                 return !(*isdir);
     145         476 :         return *isdir;
     146             : }
     147             : 
     148             : static struct metawalk_fxns pass2_fxns_delete = {
     149             :         .private = NULL,
     150             :         .check_metalist = delete_metadata,
     151             :         .check_data = delete_data,
     152             :         .check_leaf = delete_leaf,
     153             :         .check_eattr_indir = delete_eattr_indir,
     154             :         .check_eattr_leaf = delete_eattr_leaf,
     155             :         .check_eattr_entry = delete_eattr_entry,
     156             :         .check_eattr_extentry = delete_eattr_extentry,
     157             : };
     158             : 
     159             : /* bad_formal_ino - handle mismatches in formal inode number
     160             :  * Returns: 0 if the dirent was repaired
     161             :  *          1 if the caller should delete the dirent
     162             :  */
     163           0 : static int bad_formal_ino(struct fsck_cx *cx, struct lgfs2_inode *ip, struct gfs2_dirent *dent,
     164             :                           struct lgfs2_inum entry, const char *tmp_name,
     165             :                           int q, struct lgfs2_dirent *d,
     166             :                           struct lgfs2_buffer_head *bh)
     167             : {
     168             :         struct inode_info *ii;
     169           0 :         struct dir_info *di = NULL;
     170             :         struct lgfs2_inode *child_ip;
     171             :         struct lgfs2_inum childs_dotdot;
     172           0 :         struct lgfs2_sbd *sdp = ip->i_sbd;
     173             :         int error;
     174           0 :         struct lgfs2_inum inum = {0};
     175             : 
     176           0 :         ii = inodetree_find(cx, entry.in_addr);
     177           0 :         if (ii)
     178           0 :                 inum = ii->num;
     179             :         else {
     180           0 :                 di = dirtree_find(cx, entry.in_addr);
     181           0 :                 if (di)
     182           0 :                         inum = di->dinode;
     183           0 :                 else if (link1_type(&clink1map, entry.in_addr) == 1) {
     184             :                         struct lgfs2_inode *dent_ip;
     185             : 
     186           0 :                         dent_ip = fsck_load_inode(ip->i_sbd, entry.in_addr);
     187           0 :                         inum.in_addr = dent_ip->i_num.in_addr;
     188           0 :                         inum.in_formal_ino = dent_ip->i_num.in_formal_ino;
     189           0 :                         fsck_inode_put(&dent_ip);
     190             :                 }
     191             :         }
     192           0 :         log_err(_("Directory entry '%s' pointing to block %"PRIu64" (0x%"PRIx64") in "
     193             :                   "directory %"PRIu64" (0x%"PRIx64") has the wrong 'formal' inode number.\n"),
     194             :                 tmp_name, entry.in_addr, entry.in_addr, ip->i_num.in_addr, ip->i_num.in_addr);
     195           0 :         log_err(_("The directory entry has %"PRIu64" (0x%"PRIx64") "
     196             :                   "but the inode has %"PRIu64" (0x%"PRIx64")\n"),
     197             :                 entry.in_formal_ino, entry.in_formal_ino,
     198             :                 inum.in_formal_ino, inum.in_formal_ino);
     199           0 :         if (q != GFS2_BLKST_DINODE || !strcmp("..", tmp_name)) {
     200           0 :                 if (query(cx, _("Remove the corrupt directory entry? (y/n) ")))
     201           0 :                         return 1;
     202           0 :                 log_err( _("Corrupt directory entry not removed.\n"));
     203           0 :                 return 0;
     204             :         }
     205             :         /* We have a directory pointing to another directory, but the
     206             :            formal inode number still doesn't match. If that directory
     207             :            has a '..' pointing back, just fix up the no_formal_ino. */
     208           0 :         child_ip = lgfs2_inode_read(sdp, entry.in_addr);
     209           0 :         error = lgfs2_dir_search(child_ip, "..", 2, NULL, &childs_dotdot);
     210           0 :         if (!error && childs_dotdot.in_addr == ip->i_num.in_addr) {
     211           0 :                 log_err( _("The entry points to another directory with intact "
     212             :                            "linkage.\n"));
     213           0 :                 if (query(cx, _("Fix the bad directory entry? (y/n) "))) {
     214           0 :                         log_err( _("Fixing the corrupt directory entry.\n"));
     215           0 :                         entry.in_formal_ino = inum.in_formal_ino;
     216           0 :                         d->dr_inum.in_formal_ino = entry.in_formal_ino;
     217           0 :                         lgfs2_dirent_out(d, dent);
     218           0 :                         lgfs2_bmodified(bh);
     219           0 :                         incr_link_count(cx, entry, ip, _("fixed reference"));
     220           0 :                         set_parent_dir(cx, entry, ip->i_num);
     221             :                 } else {
     222           0 :                         log_err( _("Directory entry not fixed.\n"));
     223             :                 }
     224             :         } else {
     225           0 :                 if (query(cx, _("Remove the corrupt directory entry? (y/n) "))) {
     226           0 :                         lgfs2_inode_put(&child_ip);
     227           0 :                         return 1;
     228             :                 }
     229           0 :                 log_err( _("Corrupt directory entry not removed.\n"));
     230             :         }
     231           0 :         lgfs2_inode_put(&child_ip);
     232           0 :         return 0;
     233             : }
     234             : 
     235          46 : static int hash_table_index(uint32_t hash, struct lgfs2_inode *ip)
     236             : {
     237          46 :         return hash >> (32 - ip->i_depth);
     238             : }
     239             : 
     240          46 : static int hash_table_max(int lindex, struct lgfs2_inode *ip,
     241             :                    struct lgfs2_buffer_head *bh)
     242             : {
     243          46 :         struct gfs2_leaf *leaf = (struct gfs2_leaf *)bh->b_data;
     244          46 :         return (1 << (ip->i_depth - be16_to_cpu(leaf->lf_depth))) +
     245          46 :                 lindex - 1;
     246             : }
     247             : 
     248           9 : static int check_leaf_depth(struct fsck_cx *cx, struct lgfs2_inode *ip, uint64_t leaf_no,
     249             :                             int ref_count, struct lgfs2_buffer_head *lbh)
     250             : {
     251           9 :         struct gfs2_leaf *leaf = (struct gfs2_leaf *)lbh->b_data;
     252           9 :         int cur_depth = be16_to_cpu(leaf->lf_depth);
     253           9 :         int exp_count = 1 << (ip->i_depth - cur_depth);
     254             :         int divisor;
     255             :         int factor, correct_depth;
     256             : 
     257           9 :         if (exp_count == ref_count)
     258           9 :                 return 0;
     259             : 
     260           0 :         factor = 0;
     261           0 :         divisor = ref_count;
     262           0 :         while (divisor > 1) {
     263           0 :                 factor++;
     264           0 :                 divisor >>= 1;
     265             :         }
     266           0 :         if (ip->i_depth < factor) /* can't be fixed--leaf must be on the
     267             :                                            wrong dinode. */
     268           0 :                 return -1;
     269           0 :         correct_depth = ip->i_depth - factor;
     270           0 :         if (cur_depth == correct_depth)
     271           0 :                 return 0;
     272             : 
     273           0 :         log_err(_("Leaf block %"PRIu64" (0x%"PRIx64") in dinode %"PRIu64" (0x%"PRIx64") has the "
     274             :                   "wrong depth: is %d (length %d), should be %d (length %d).\n"),
     275             :                 leaf_no, leaf_no, ip->i_num.in_addr, ip->i_num.in_addr,
     276             :                 cur_depth, ref_count, correct_depth, exp_count);
     277           0 :         if (!query(cx, _("Fix the leaf block? (y/n)"))) {
     278           0 :                 log_err( _("The leaf block was not fixed.\n"));
     279           0 :                 return 0;
     280             :         }
     281             : 
     282           0 :         leaf->lf_depth = cpu_to_be16(correct_depth);
     283           0 :         lgfs2_bmodified(lbh);
     284           0 :         log_err( _("The leaf block depth was fixed.\n"));
     285           0 :         return 1;
     286             : }
     287             : 
     288             : /* wrong_leaf: Deal with a dirent discovered to be on the wrong leaf block
     289             :  *
     290             :  * Returns: 1 if the dirent is to be removed, 0 if it needs to be kept,
     291             :  *          or -1 on error
     292             :  */
     293           0 : static int wrong_leaf(struct fsck_cx *cx, struct lgfs2_inode *ip, struct lgfs2_inum *entry,
     294             :                       const char *tmp_name, int *lindex, int lindex_max,
     295             :                       int hash_index, struct lgfs2_buffer_head *bh,
     296             :                       struct dir_status *ds, struct gfs2_dirent *dent,
     297             :                       struct lgfs2_dirent *d, struct gfs2_dirent *prev_de,
     298             :                       uint32_t *count, int q)
     299             : {
     300           0 :         struct lgfs2_sbd *sdp = ip->i_sbd;
     301             :         struct lgfs2_buffer_head *dest_lbh;
     302             :         uint64_t planned_leaf, real_leaf;
     303             :         int li, dest_ref, error;
     304             :         __be64 *tbl;
     305             :         int di_depth;
     306             : 
     307           0 :         log_err(_("Directory entry '%s' at block %"PRIu64" (0x%"PRIx64") is on the wrong leaf block.\n"),
     308             :                 tmp_name, entry->in_addr, entry->in_addr);
     309           0 :         log_err(_("Leaf index is: 0x%x. The range for this leaf block is "
     310             :                   "0x%x - 0x%x\n"), hash_index, *lindex, lindex_max);
     311           0 :         if (!query(cx, _("Move the misplaced directory entry to a valid leaf block? (y/n) "))) {
     312           0 :                 log_err( _("Misplaced directory entry not moved.\n"));
     313           0 :                 return 0;
     314             :         }
     315             : 
     316             :         /* check the destination leaf block's depth */
     317           0 :         tbl = get_dir_hash(ip);
     318           0 :         if (tbl == NULL) {
     319           0 :                 perror("get_dir_hash");
     320           0 :                 return -1;
     321             :         }
     322           0 :         planned_leaf = be64_to_cpu(tbl[hash_index]);
     323           0 :         log_err(_("Moving it from leaf %"PRIu64" (0x%"PRIx64") to %"PRIu64" (0x%"PRIx64")\n"),
     324             :                 be64_to_cpu(tbl[*lindex]), be64_to_cpu(tbl[*lindex]), planned_leaf, planned_leaf);
     325             :         /* Can't trust lf_depth; we have to count */
     326           0 :         dest_ref = 0;
     327           0 :         for (li = 0; li < (1 << ip->i_depth); li++) {
     328           0 :                 if (be64_to_cpu(tbl[li]) == planned_leaf)
     329           0 :                         dest_ref++;
     330           0 :                 else if (dest_ref)
     331           0 :                         break;
     332             :         }
     333           0 :         dest_lbh = lgfs2_bread(sdp, planned_leaf);
     334           0 :         check_leaf_depth(cx, ip, planned_leaf, dest_ref, dest_lbh);
     335           0 :         lgfs2_brelse(dest_lbh);
     336           0 :         free(tbl);
     337             : 
     338             :         /* check if it's already on the correct leaf block */
     339           0 :         error = lgfs2_dir_search(ip, tmp_name, d->dr_name_len, NULL, &d->dr_inum);
     340           0 :         if (!error) {
     341           0 :                 log_err(_("The misplaced directory entry already appears on "
     342             :                           "the correct leaf block.\n"));
     343           0 :                 log_err( _("The bad duplicate directory entry "
     344             :                            "'%s' was cleared.\n"), tmp_name);
     345           0 :                 return 1; /* nuke the dent upon return */
     346             :         }
     347             : 
     348           0 :         di_depth = ip->i_depth;
     349           0 :         if (lgfs2_dir_add(ip, tmp_name, d->dr_name_len, &d->dr_inum, d->dr_type) == 0) {
     350           0 :                 log_err(_("The misplaced directory entry was moved to a "
     351             :                           "valid leaf block.\n"));
     352           0 :                 if (ip->i_depth > di_depth) {
     353           0 :                         log_err(_("Directory hash table was doubled.\n"));
     354           0 :                         hash_index <<= (ip->i_depth - di_depth);
     355           0 :                         (*lindex) <<= (ip->i_depth - di_depth);
     356             :                 }
     357           0 :                 if (lgfs2_get_leaf_ptr(ip, hash_index, &real_leaf)) {
     358           0 :                         log_err(_("Could not read leaf %d in dinode %"PRIu64": %s\n"), hash_index,
     359             :                                 ip->i_num.in_addr, strerror(errno));
     360             :                 }
     361           0 :                 if (real_leaf != planned_leaf) {
     362           0 :                         log_err(_("The planned leaf was split. The new leaf "
     363             :                                   "is: %"PRIu64" (0x%"PRIx64"). di_blocks=%"PRIu64"\n"),
     364             :                                 real_leaf, real_leaf, ip->i_blocks);
     365           0 :                         fsck_bitmap_set(cx, ip, real_leaf, _("split leaf"), GFS2_BLKST_USED);
     366             :                 }
     367             :                 /* If the misplaced dirent was supposed to be earlier in the
     368             :                    hash table, we need to adjust our counts for the blocks
     369             :                    that have already been processed. If it's supposed to
     370             :                    appear later, we'll count it has part of our normal
     371             :                    processing when we get to that leaf block later on in the
     372             :                    hash table. */
     373           0 :                 if (hash_index > *lindex) {
     374           0 :                         log_err(_("Accounting deferred.\n"));
     375           0 :                         return 1; /* nuke the dent upon return */
     376             :                 }
     377             :                 /* If we get here, it's because we moved a dent to another
     378             :                    leaf, but that leaf has already been processed. So we have
     379             :                    to nuke the dent from this leaf when we return, but we
     380             :                    still need to do the "good dent" accounting. */
     381           0 :                 if (d->dr_type == DT_DIR) {
     382           0 :                         error = set_parent_dir(cx, d->dr_inum, ip->i_num);
     383           0 :                         if (error > 0)
     384             :                                 /* This is a bit of a kludge, but returning 0
     385             :                                    in this case causes the caller to go through
     386             :                                    function set_parent_dir a second time and
     387             :                                    deal properly with the hard link. */
     388           0 :                                 return 0;
     389             :                 }
     390           0 :                 error = incr_link_count(cx, *entry, ip, _("moved valid reference"));
     391           0 :                 if (error > 0 &&
     392           0 :                     bad_formal_ino(cx, ip, dent, *entry, tmp_name, q, d, bh) == 1)
     393           0 :                         return 1; /* nuke it */
     394             : 
     395             :                 /* You cannot do this:
     396             :                    (*count)++;
     397             :                    The reason is: *count is the count of dentries on the leaf,
     398             :                    and we moved the dentry to a previous leaf within the same
     399             :                    directory dinode. So the directory counts still get
     400             :                    incremented, but not leaf entries. When we called lgfs2_dir_add
     401             :                    above, it should have fixed that prev leaf's lf_entries. */
     402           0 :                 ds->entry_count++;
     403           0 :                 return 1;
     404             :         } else {
     405           0 :                 log_err(_("Error moving directory entry.\n"));
     406           0 :                 return 1; /* nuke it */
     407             :         }
     408             : }
     409             : 
     410             : /* basic_dentry_checks - fundamental checks for directory entries
     411             :  *
     412             :  * @ip: pointer to the incode inode structure
     413             :  * @entry: pointer to the inum info
     414             :  * @tmp_name: user-friendly file name
     415             :  * @count: pointer to the entry count
     416             :  * @de: pointer to the directory entry
     417             :  *
     418             :  * Returns: 1 means corruption, nuke the dentry, 0 means checks pass
     419             :  */
     420        1036 : static int basic_dentry_checks(struct fsck_cx *cx, struct lgfs2_inode *ip, struct gfs2_dirent *dent,
     421             :                                struct lgfs2_inum *entry, const char *tmp_name,
     422             :                                uint32_t *count, struct lgfs2_dirent *d,
     423             :                                struct dir_status *ds, int *q,
     424             :                                struct lgfs2_buffer_head *bh, int *isdir)
     425             : {
     426        1036 :         struct lgfs2_sbd *sdp = ip->i_sbd;
     427             :         uint32_t calculated_hash;
     428        1036 :         struct lgfs2_inode *entry_ip = NULL;
     429             :         int error;
     430             :         struct inode_info *ii;
     431        1036 :         struct dir_info *di = NULL;
     432        1036 :         struct lgfs2_inum inum = {0};
     433             : 
     434        1036 :         *isdir = 0;
     435        1036 :         if (!valid_block_ip(ip, entry->in_addr)) {
     436           0 :                 log_err(_("Block # referenced by directory entry %s in inode %"PRIu64
     437             :                           " (0x%"PRIx64") is invalid\n"),
     438             :                         tmp_name, ip->i_num.in_addr, ip->i_num.in_addr);
     439           0 :                 if (query(cx, _("Clear directory entry to out of range block? (y/n) "))) {
     440           0 :                         return 1;
     441             :                 } else {
     442           0 :                         log_err( _("Directory entry to out of range block remains\n"));
     443           0 :                         (*count)++;
     444           0 :                         ds->entry_count++;
     445             :                         /* can't do this because the block is out of range:
     446             :                            incr_link_count(entry); */
     447           0 :                         return 0;
     448             :                 }
     449             :         }
     450             : 
     451        1036 :         if (d->dr_rec_len < GFS2_DIRENT_SIZE(d->dr_name_len) ||
     452        1036 :             d->dr_name_len > GFS2_FNAMESIZE) {
     453           0 :                 log_err( _("Dir entry with bad record or name length\n"
     454             :                         "\tRecord length = %u\n\tName length = %u\n"),
     455             :                         d->dr_rec_len, d->dr_name_len);
     456           0 :                 if (!query(cx, _("Clear the directory entry? (y/n) "))) {
     457           0 :                         log_err( _("Directory entry not fixed.\n"));
     458           0 :                         return 0;
     459             :                 }
     460             :                 /* Don't be tempted to do this:
     461             :                 fsck_bitmap_set(ip, ip->i_di.di_num.no_addr,
     462             :                                 _("corrupt directory entry"),
     463             :                                 GFS2_BLKST_FREE);
     464             :                 We can't free it because another dir may have a valid reference
     465             :                 to it. Just return 1 so we can delete the bad dirent. */
     466           0 :                 log_err( _("Bad directory entry deleted.\n"));
     467           0 :                 return 1;
     468             :         }
     469             : 
     470        1036 :         calculated_hash = lgfs2_disk_hash(tmp_name, d->dr_name_len);
     471        1036 :         if (d->dr_hash != calculated_hash){
     472           0 :                 log_err( _("Dir entry with bad hash or name length\n"
     473             :                            "\tHash found         = %u (0x%x)\n"
     474             :                            "\tFilename           = %s\n"),
     475             :                          d->dr_hash, d->dr_hash, tmp_name);
     476           0 :                 log_err( _("\tName length found  = %u\n"
     477             :                            "\tHash expected      = %u (0x%x)\n"),
     478             :                          d->dr_name_len, calculated_hash, calculated_hash);
     479           0 :                 if (!query(cx, _("Fix directory hash for %s? (y/n) "),
     480             :                            tmp_name)) {
     481           0 :                         log_err( _("Directory entry hash for %s not "
     482             :                                    "fixed.\n"), tmp_name);
     483           0 :                         return 0;
     484             :                 }
     485           0 :                 d->dr_hash = calculated_hash;
     486           0 :                 lgfs2_dirent_out(d, dent);
     487           0 :                 lgfs2_bmodified(bh);
     488           0 :                 log_err( _("Directory entry hash for %s fixed.\n"),
     489             :                          tmp_name);
     490             :         }
     491             : 
     492        1036 :         *q = bitmap_type(sdp, entry->in_addr);
     493             :         /* Get the status of the directory inode */
     494             :         /**
     495             :          * 1. Blocks marked "invalid" were invalidated due to duplicate
     496             :          * block references.  Pass1b should have already taken care of deleting
     497             :          * their metadata, so here we only need to delete the directory entries
     498             :          * pointing to them.  We delete the metadata in pass1b because we need
     499             :          * to eliminate the inode referencing the duplicate-referenced block
     500             :          * from the list of candidates to keep.  So we have a delete-as-we-go
     501             :          * policy.
     502             :          *
     503             :          * 2. Blocks marked "bad" need to have their entire
     504             :          * metadata tree deleted.
     505             :         */
     506        1036 :         if (*q != GFS2_BLKST_DINODE) {
     507           0 :                 log_err(_("Directory entry '%s' referencing inode %"PRIu64" (0x%"PRIx64") "
     508             :                           "in dir inode %"PRIu64" (0x%"PRIx64") block type %d: %s.\n"),
     509             :                         tmp_name, entry->in_addr, entry->in_addr, ip->i_num.in_addr, ip->i_num.in_addr,
     510             :                          *q, *q == GFS2_BLKST_FREE ?
     511             :                          _("was previously marked invalid") :
     512             :                          _("was deleted or is not an inode"));
     513             : 
     514           0 :                 if (!query(cx, _("Clear directory entry to non-inode block? (y/n) "))) {
     515           0 :                         log_err( _("Directory entry to non-inode block remains\n"));
     516           0 :                         return 0;
     517             :                 }
     518             : 
     519             :                 /* Don't decrement the link here: Here in pass2, we increment
     520             :                    only when we know it's okay.
     521             :                    decr_link_count(ip->i_di.di_num.no_addr, blah); */
     522             :                 /* If it was previously marked invalid (i.e. known
     523             :                    to be bad, not just a free block, etc.) then the temptation
     524             :                    would be to delete any metadata it holds.  The trouble is:
     525             :                    if it's invalid, we may or _may_not_ have traversed its
     526             :                    metadata tree, and therefore may or may not have marked the
     527             :                    blocks it points to as a metadata type, or as a duplicate.
     528             :                    If there is really a duplicate reference, but we didn't
     529             :                    process the metadata tree because it's invalid, some other
     530             :                    inode has a reference to the metadata block, in which case
     531             :                    freeing it would do more harm than good.  IOW we cannot
     532             :                    count on "delete_block_if_notdup" knowing whether it's
     533             :                    really a duplicate block if we never traversed the metadata
     534             :                    tree for the invalid inode. */
     535           0 :                 return 1;
     536             :         }
     537             : 
     538        1036 :         error = check_file_type(cx, entry->in_addr, d->dr_type, *q, isdir);
     539        1036 :         if (error < 0) {
     540           0 :                 log_err(_("Error: directory entry type is incompatible with block type at block %"PRIu64
     541             :                           " (0x%"PRIx64") in directory inode %"PRIu64" (0x%"PRIx64").\n"),
     542             :                         entry->in_addr, entry->in_addr, ip->i_num.in_addr, ip->i_num.in_addr);
     543           0 :                 log_err( _("Directory entry type is %d, block type is %d.\n"),
     544             :                         d->dr_type, *q);
     545           0 :                 stack;
     546           0 :                 return -1;
     547             :         }
     548        1036 :         if (error > 0) {
     549           0 :                 log_err( _("Type '%s' in dir entry (%s, %"PRIu64"/0x%"PRIx64") conflicts"
     550             :                          " with type '%s' in dinode. (Dir entry is stale.)\n"),
     551             :                          de_type_string(d->dr_type), tmp_name,
     552             :                          entry->in_addr, entry->in_addr,
     553             :                          block_type_string(*q));
     554           0 :                 if (!query(cx, _("Clear stale directory entry? (y/n) "))) {
     555           0 :                         log_err( _("Stale directory entry remains\n"));
     556           0 :                         return 0;
     557             :                 }
     558           0 :                 if (ip->i_num.in_addr == entry->in_addr)
     559           0 :                         entry_ip = ip;
     560             :                 else
     561           0 :                         entry_ip = fsck_load_inode(sdp, entry->in_addr);
     562           0 :                 check_inode_eattr(cx, entry_ip, &delete_eattrs);
     563           0 :                 if (entry_ip != ip)
     564           0 :                         fsck_inode_put(&entry_ip);
     565           0 :                 return 1;
     566             :         }
     567             :         /* We need to verify the formal inode number matches. If it doesn't,
     568             :            it needs to be deleted. */
     569        1036 :         ii = inodetree_find(cx, entry->in_addr);
     570        1036 :         if (ii)
     571           0 :                 inum = ii->num;
     572             :         else {
     573        1036 :                 di = dirtree_find(cx, entry->in_addr);
     574        1036 :                 if (di)
     575         560 :                         inum = di->dinode;
     576         476 :                 else if (link1_type(&nlink1map, entry->in_addr) == 1) {
     577             :                         /* Since we don't have ii or di, the only way to
     578             :                            validate formal_ino is to read in the inode, which
     579             :                            would kill performance. So skip it for now. */
     580         476 :                         return 0;
     581             :                 }
     582             :         }
     583         560 :         if (inum.in_formal_ino != entry->in_formal_ino) {
     584           0 :                 log_err(_("Directory entry '%s' pointing to block %"PRIu64" (0x%"PRIx64") "
     585             :                           "in directory %"PRIu64" (0x%"PRIx64") has the wrong 'formal' inode number.\n"),
     586             :                         tmp_name, entry->in_addr, entry->in_addr, ip->i_num.in_addr, ip->i_num.in_addr);
     587           0 :                 log_err(_("The directory entry has %"PRIu64" (0x%"PRIx64") but the "
     588             :                           "inode has %"PRIu64" (0x%"PRIx64")\n"),
     589             :                         entry->in_formal_ino, entry->in_formal_ino,
     590             :                         inum.in_formal_ino, inum.in_formal_ino);
     591           0 :                 return 1;
     592             :         }
     593         560 :         return 0;
     594             : }
     595             : 
     596           0 : static int dirref_find(struct fsck_cx *cx, struct lgfs2_inode *ip, struct gfs2_dirent *dent,
     597             :                        struct gfs2_dirent *prev, struct lgfs2_buffer_head *bh,
     598             :                        char *filename, uint32_t *count, int *lindex,
     599             :                        void *private)
     600             : {
     601             :         /* the metawalk_fxn's private field must be set to the dentry
     602             :          * block we want to clear */
     603           0 :         struct lgfs2_inum *entry = private;
     604             :         struct lgfs2_dirent dentry;
     605             :         char fn[MAX_FILENAME];
     606             : 
     607           0 :         memset(&dentry, 0, sizeof(dentry));
     608           0 :         lgfs2_dirent_in(&dentry, dent);
     609             : 
     610           0 :         if (dentry.dr_inum.in_addr != entry->in_addr) {
     611           0 :                 (*count)++;
     612           0 :                 return 0;
     613             :         }
     614           0 :         if (dentry.dr_inum.in_formal_ino == entry->in_formal_ino) {
     615           0 :                 log_debug("Formal inode number matches; must be a hard "
     616             :                           "link.\n");
     617           0 :                 goto out;
     618             :         }
     619           0 :         log_err(_("The original reference to inode %"PRIu64" (0x%"PRIx64") from "
     620             :                   "directory %"PRIu64" (0x%"PRIx64") has the wrong 'formal' inode "
     621             :                   "number.\n"), entry->in_addr, entry->in_addr, ip->i_num.in_addr, ip->i_num.in_addr);
     622           0 :         memset(fn, 0, sizeof(fn));
     623           0 :         if (dentry.dr_name_len < MAX_FILENAME)
     624           0 :                 strncpy(fn, filename, dentry.dr_name_len);
     625             :         else
     626           0 :                 strncpy(fn, filename, MAX_FILENAME - 1);
     627           0 :         log_err(_("The bad reference '%s' had formal inode number: %"PRIu64
     628             :                   " (0x%"PRIx64") but the correct value is: %"PRIu64" (0x%"PRIx64")\n"),
     629             :                 fn, dentry.dr_inum.in_formal_ino, dentry.dr_inum.in_formal_ino,
     630             :                 entry->in_formal_ino, entry->in_formal_ino);
     631           0 :         if (!query(cx, _("Delete the bad directory entry? (y/n) "))) {
     632           0 :                 log_err(_("The corrupt directory entry was not fixed.\n"));
     633           0 :                 goto out;
     634             :         }
     635           0 :         decr_link_count(cx, entry->in_addr, ip->i_num.in_addr, _("bad original reference"));
     636           0 :         lgfs2_dirent2_del(ip, bh, prev, dent);
     637           0 :         log_err(_("The corrupt directory entry '%s' was deleted.\n"), fn);
     638           0 : out:
     639           0 :         return -1; /* force check_dir to stop; don't waste time. */
     640             : }
     641             : 
     642             : /**
     643             :  * check_suspicious_dirref - double-check a questionable first dentry ref
     644             :  *
     645             :  * This function is called when a dentry has caused us to increment the
     646             :  * link count to a file from 1 to 2, and we know the object pointed to is
     647             :  * not a directory. (Most likely, it'a a file). The second directory to
     648             :  * reference the dinode has the correct formal inode number, but when we
     649             :  * created the original reference in the counted links bitmap (clink1map),
     650             :  * we had no way to check the formal inode number. (Well, we could have read
     651             :  * in the dinode, but that would kill fsck.gfs2 performance.)
     652             :  * So now we have to walk through the directory tree and find that original
     653             :  * reference so make sure it's a valid reference. If the formal inode number
     654             :  * is the same, it's a hard link (which is unlikely for gfs2). If it's not
     655             :  * the same, that's an error, and we need to delete the damaged original
     656             :  * dentry, since we failed to detect the problem earlier.
     657             :  */
     658           0 : static int check_suspicious_dirref(struct fsck_cx *cx, struct lgfs2_inum *entry)
     659             : {
     660           0 :         struct osi_node *tmp, *next = NULL;
     661             :         struct dir_info *dt;
     662             :         struct lgfs2_inode *ip;
     663             :         uint64_t dirblk;
     664           0 :         int error = FSCK_OK;
     665           0 :         struct metawalk_fxns dirref_hunt = {
     666             :                 .private = entry,
     667             :                 .check_dentry = dirref_find,
     668             :         };
     669             : 
     670           0 :         log_debug("This dentry is good, but since this is a second "
     671             :                   "reference to block 0x%"PRIx64", we need to check the "
     672             :                   "original.\n", entry->in_addr);
     673           0 :         for (tmp = osi_first(&cx->dirtree); tmp; tmp = next) {
     674           0 :                 next = osi_next(tmp);
     675           0 :                 dt = (struct dir_info *)tmp;
     676           0 :                 dirblk = dt->dinode.in_addr;
     677           0 :                 if (skip_this_pass || fsck_abort) /* asked to skip the rest */
     678             :                         break;
     679           0 :                 ip = fsck_load_inode(cx->sdp, dirblk);
     680           0 :                 if (ip == NULL) {
     681           0 :                         stack;
     682           0 :                         return FSCK_ERROR;
     683             :                 }
     684           0 :                 error = check_dir(cx, ip, &dirref_hunt);
     685           0 :                 fsck_inode_put(&ip);
     686             :                 /* Error just means we found the dentry and dealt with it. */
     687           0 :                 if (error)
     688           0 :                         break;
     689             :         }
     690           0 :         log_debug("Original reference check complete. Found = %d.\n",
     691             :                   error ? 1 : 0);
     692           0 :         return 0;
     693             : }
     694             : 
     695             : /* FIXME: should maybe refactor this a bit - but need to deal with
     696             :  * FIXMEs internally first */
     697        1036 : static int check_dentry(struct fsck_cx *cx, struct lgfs2_inode *ip, struct gfs2_dirent *dent,
     698             :                         struct gfs2_dirent *prev_de,
     699             :                         struct lgfs2_buffer_head *bh, char *filename,
     700             :                         uint32_t *count, int *lindex, void *priv)
     701             : {
     702        1036 :         struct lgfs2_sbd *sdp = ip->i_sbd;
     703        1036 :         int q = 0;
     704             :         char tmp_name[MAX_FILENAME];
     705             :         struct lgfs2_inum entry;
     706        1036 :         struct dir_status *ds = (struct dir_status *) priv;
     707             :         int error;
     708        1036 :         struct lgfs2_inode *entry_ip = NULL;
     709             :         struct lgfs2_dirent d;
     710             :         int hash_index; /* index into the hash table based on the hash */
     711             :         int lindex_max; /* largest acceptable hash table index for hash */
     712             :         int isdir;
     713             : 
     714        1036 :         lgfs2_dirent_in(&d, dent);
     715             : 
     716        1036 :         entry.in_addr = d.dr_inum.in_addr;
     717        1036 :         entry.in_formal_ino = d.dr_inum.in_formal_ino;
     718             : 
     719             :         /* Start of checks */
     720        1036 :         memset(tmp_name, 0, MAX_FILENAME);
     721        1036 :         if (d.dr_name_len < MAX_FILENAME)
     722        1036 :                 strncpy(tmp_name, filename, d.dr_name_len);
     723             :         else
     724           0 :                 strncpy(tmp_name, filename, MAX_FILENAME - 1);
     725             : 
     726        1036 :         error = basic_dentry_checks(cx, ip, dent, &entry, tmp_name, count, &d,
     727             :                                     ds, &q, bh, &isdir);
     728        1036 :         if (error)
     729           0 :                 goto nuke_dentry;
     730             : 
     731        1036 :         if (!strcmp(".", tmp_name)) {
     732         224 :                 log_debug(_("Found . dentry in directory %"PRIu64" (0x%"PRIx64")\n"),
     733             :                           ip->i_num.in_addr, ip->i_num.in_addr);
     734             : 
     735         224 :                 if (ds->dotdir) {
     736           0 :                         log_err(_("Already found '.' entry in directory %"PRIu64" (0x%"PRIx64")\n"),
     737             :                                 ip->i_num.in_addr, ip->i_num.in_addr);
     738           0 :                         if (!query(cx, _("Clear duplicate '.' entry? (y/n) "))) {
     739           0 :                                 log_err( _("Duplicate '.' entry remains\n"));
     740             :                                 /* FIXME: Should we continue on here
     741             :                                  * and check the rest of the '.' entry? */
     742           0 :                                 goto dentry_is_valid;
     743             :                         }
     744           0 :                         if (ip->i_num.in_addr == entry.in_addr)
     745           0 :                                 entry_ip = ip;
     746             :                         else
     747           0 :                                 entry_ip = fsck_load_inode(sdp, entry.in_addr);
     748           0 :                         check_inode_eattr(cx, entry_ip, &delete_eattrs);
     749           0 :                         if (entry_ip != ip)
     750           0 :                                 fsck_inode_put(&entry_ip);
     751           0 :                         goto nuke_dentry;
     752             :                 }
     753             : 
     754             :                 /* GFS2 does not rely on '.' being in a certain
     755             :                  * location */
     756             : 
     757             :                 /* check that '.' refers to this inode */
     758         224 :                 if (entry.in_addr != ip->i_num.in_addr) {
     759           0 :                         log_err(_("'.' entry's value incorrect in directory %"PRIu64" (0x%"PRIx64")."
     760             :                                   " Points to %"PRIu64" (0x%"PRIx64") when it should point to %"PRIu64
     761             :                                   " (0x%"PRIx64").\n"),
     762             :                                 entry.in_addr, entry.in_addr, entry.in_addr, entry.in_addr,
     763             :                                 ip->i_num.in_addr, ip->i_num.in_addr);
     764           0 :                         if (!query(cx, _("Remove '.' reference? (y/n) "))) {
     765           0 :                                 log_err( _("Invalid '.' reference remains\n"));
     766             :                                 /* Not setting ds->dotdir here since
     767             :                                  * this '.' entry is invalid */
     768           0 :                                 goto dentry_is_valid;
     769             :                         }
     770           0 :                         if (ip->i_num.in_addr == entry.in_addr)
     771           0 :                                 entry_ip = ip;
     772             :                         else
     773           0 :                                 entry_ip = fsck_load_inode(sdp, entry.in_addr);
     774           0 :                         check_inode_eattr(cx, entry_ip, &delete_eattrs);
     775           0 :                         if (entry_ip != ip)
     776           0 :                                 fsck_inode_put(&entry_ip);
     777           0 :                         goto nuke_dentry;
     778             :                 }
     779             : 
     780         224 :                 ds->dotdir = 1;
     781         224 :                 goto dentry_is_valid;
     782             :         }
     783         812 :         if (!strcmp("..", tmp_name)) {
     784         224 :                 log_debug(_("Found '..' dentry in directory %"PRIu64" (0x%"PRIx64")\n"),
     785             :                           ip->i_num.in_addr, ip->i_num.in_addr);
     786         224 :                 if (ds->dotdotdir) {
     787           0 :                         log_err(_("Already had a '..' entry in directory %"PRIu64" (0x%"PRIx64")\n"),
     788             :                                 ip->i_num.in_addr, ip->i_num.in_addr);
     789           0 :                         if (!query(cx, _("Clear duplicate '..' entry? (y/n) "))) {
     790           0 :                                 log_err( _("Duplicate '..' entry remains\n"));
     791             :                                 /* FIXME: Should we continue on here
     792             :                                  * and check the rest of the '..'
     793             :                                  * entry? */
     794           0 :                                 goto dentry_is_valid;
     795             :                         }
     796             : 
     797           0 :                         if (ip->i_num.in_addr == entry.in_addr)
     798           0 :                                 entry_ip = ip;
     799             :                         else
     800           0 :                                 entry_ip = fsck_load_inode(sdp, entry.in_addr);
     801           0 :                         check_inode_eattr(cx, entry_ip, &delete_eattrs);
     802           0 :                         if (entry_ip != ip)
     803           0 :                                 fsck_inode_put(&entry_ip);
     804             : 
     805           0 :                         goto nuke_dentry;
     806             :                 }
     807         224 :                 if (!isdir) {
     808           0 :                         log_err(_("Found '..' entry in directory %"PRIu64" (0x%"PRIx64") "
     809             :                                 "pointing to something that's not a directory"),
     810             :                                 ip->i_num.in_addr, ip->i_num.in_addr);
     811           0 :                         if (!query(cx, _("Clear bad '..' directory entry? (y/n) "))) {
     812           0 :                                 log_err( _("Bad '..' directory entry remains\n"));
     813           0 :                                 goto dentry_is_valid;
     814             :                         }
     815           0 :                         if (ip->i_num.in_addr == entry.in_addr)
     816           0 :                                 entry_ip = ip;
     817             :                         else
     818           0 :                                 entry_ip = fsck_load_inode(sdp, entry.in_addr);
     819           0 :                         check_inode_eattr(cx, entry_ip, &delete_eattrs);
     820           0 :                         if (entry_ip != ip)
     821           0 :                                 fsck_inode_put(&entry_ip);
     822             : 
     823           0 :                         goto nuke_dentry;
     824             :                 }
     825             :                 /* GFS2 does not rely on '..' being in a certain location */
     826             : 
     827             :                 /* Add the address this entry is pointing to
     828             :                  * to this inode's dotdot_parent in
     829             :                  * dir_info */
     830         224 :                 if (set_dotdot_dir(cx, ip->i_num.in_addr, entry)) {
     831           0 :                         stack;
     832           0 :                         return -1;
     833             :                 }
     834             : 
     835         224 :                 ds->dotdotdir = 1;
     836         224 :                 goto dentry_is_valid;
     837             :         }
     838             :         /* If this is an exhash directory, make sure the dentries in the leaf
     839             :            block have a hash table index that fits */
     840         588 :         if (ip->i_flags & GFS2_DIF_EXHASH) {
     841          46 :                 hash_index = hash_table_index(d.dr_hash, ip);
     842          46 :                 lindex_max = hash_table_max(*lindex, ip, bh);
     843          46 :                 if (hash_index < *lindex || hash_index > lindex_max) {
     844             :                         int nuke_dent;
     845             : 
     846           0 :                         nuke_dent = wrong_leaf(cx, ip, &entry, tmp_name, lindex,
     847             :                                                lindex_max, hash_index, bh, ds,
     848             :                                                dent, &d, prev_de, count, q);
     849           0 :                         if (nuke_dent)
     850           0 :                                 goto nuke_dentry;
     851             :                 }
     852             :         }
     853             : 
     854             :         /* After this point we're only concerned with directories */
     855         588 :         if (!isdir) {
     856         476 :                 log_debug(_("Found non-dir inode dentry pointing to %"PRIu64" (0x%"PRIx64")\n"),
     857             :                           entry.in_addr, entry.in_addr);
     858         476 :                 goto dentry_is_valid;
     859             :         }
     860             : 
     861             :         /*log_debug( _("Found plain directory dentry\n"));*/
     862         112 :         error = set_parent_dir(cx, entry, ip->i_num);
     863         112 :         if (error > 0) {
     864           0 :                 log_err(_("%s: Hard link to block %"PRIu64" (0x%"PRIx64") detected.\n"),
     865             :                         tmp_name, entry.in_addr, entry.in_addr);
     866             : 
     867           0 :                 if (query(cx, _("Clear hard link to directory? (y/n) ")))
     868           0 :                         goto nuke_dentry;
     869             :                 else {
     870           0 :                         log_err( _("Hard link to directory remains\n"));
     871           0 :                         goto dentry_is_valid;
     872             :                 }
     873         112 :         } else if (error < 0) {
     874           0 :                 stack;
     875           0 :                 return -1;
     876             :         }
     877         112 : dentry_is_valid:
     878             :         /* This directory inode links to this inode via this dentry */
     879        1036 :         error = incr_link_count(cx, entry, ip, _("valid reference"));
     880        1036 :         if (error == INCR_LINK_CHECK_ORIG) {
     881           0 :                 error = check_suspicious_dirref(cx, &entry);
     882        1036 :         } else if (error == INCR_LINK_INO_MISMATCH) {
     883           0 :                 log_err("incr_link_count err=%d.\n", error);
     884           0 :                 if (bad_formal_ino(cx, ip, dent, entry, tmp_name, q, &d, bh) == 1)
     885           0 :                         goto nuke_dentry;
     886             :         }
     887        1036 :         (*count)++;
     888        1036 :         ds->entry_count++;
     889             :         /* End of checks */
     890        1036 :         return 0;
     891             : 
     892           0 : nuke_dentry:
     893           0 :         lgfs2_dirent2_del(ip, bh, prev_de, dent);
     894           0 :         log_err( _("Bad directory entry '%s' cleared.\n"), tmp_name);
     895           0 :         return 1;
     896             : }
     897             : 
     898             : /*
     899             :  * write_new_leaf - allocate and write a new leaf to cover a gap in hash table
     900             :  * @dip: the directory inode
     901             :  * @start_lindex: where in the hash table to start writing
     902             :  * @num_copies: number of copies of the pointer to write into hash table
     903             :  * @before_or_after: desc. of whether this is being added before/after/etc.
     904             :  * @bn: pointer to return the newly allocated leaf's block number
     905             :  */
     906           0 : static int write_new_leaf(struct fsck_cx *cx, struct lgfs2_inode *dip, int start_lindex,
     907             :                           int num_copies, const char *before_or_after,
     908             :                           uint64_t *bn)
     909             : {
     910             :         struct lgfs2_buffer_head *nbh;
     911             :         struct gfs2_leaf *leaf;
     912             :         struct gfs2_dirent *dent;
     913             :         int count, i;
     914           0 :         int factor = 0, pad_size;
     915             :         __be64 *padbuf, *cpyptr;
     916           0 :         int divisor = num_copies;
     917           0 :         int end_lindex = start_lindex + num_copies;
     918             : 
     919           0 :         padbuf = calloc(num_copies, sizeof(__be64));
     920           0 :         if (padbuf == NULL)
     921           0 :                 return -1;
     922             :         /* calculate the depth needed for the new leaf */
     923           0 :         while (divisor > 1) {
     924           0 :                 factor++;
     925           0 :                 divisor /= 2;
     926             :         }
     927             :         /* Make sure the number of copies is properly a factor of 2 */
     928           0 :         if ((1 << factor) != num_copies) {
     929           0 :                 log_err(_("Program error: num_copies not a factor of 2.\n"));
     930           0 :                 log_err(_("num_copies=%d, dinode = %"PRIu64" (0x%"PRIx64")\n"),
     931             :                         num_copies, dip->i_num.in_addr, dip->i_num.in_addr);
     932           0 :                 log_err(_("lindex = %d (0x%x)\n"), start_lindex, start_lindex);
     933           0 :                 stack;
     934           0 :                 free(padbuf);
     935           0 :                 return -1;
     936             :         }
     937             : 
     938             :         /* allocate and write out a new leaf block */
     939           0 :         if (lgfs2_meta_alloc(dip, bn)) {
     940           0 :                 log_err( _("Error: allocation failed while fixing directory leaf "
     941             :                            "pointers.\n"));
     942           0 :                 free(padbuf);
     943           0 :                 return -1;
     944             :         }
     945           0 :         fsck_bitmap_set(cx, dip, *bn, _("directory leaf"), GFS2_BLKST_USED);
     946           0 :         log_err(_("A new directory leaf was allocated at block %"PRIu64" "
     947             :                   "(0x%"PRIx64") to fill the %d (0x%x) pointer gap %s the existing "
     948             :                   "pointer at index %d (0x%x).\n"), *bn, *bn,
     949             :                 num_copies, num_copies,
     950             :                 before_or_after, start_lindex, start_lindex);
     951           0 :         dip->i_blocks++;
     952           0 :         lgfs2_bmodified(dip->i_bh);
     953           0 :         nbh = lgfs2_bget(dip->i_sbd, *bn);
     954           0 :         memset(nbh->b_data, 0, dip->i_sbd->sd_bsize);
     955           0 :         leaf = (struct gfs2_leaf *)nbh->b_data;
     956           0 :         leaf->lf_header.mh_magic = cpu_to_be32(GFS2_MAGIC);
     957           0 :         leaf->lf_header.mh_type = cpu_to_be32(GFS2_METATYPE_LF);
     958           0 :         leaf->lf_header.mh_format = cpu_to_be32(GFS2_FORMAT_LF);
     959           0 :         leaf->lf_depth = cpu_to_be16(dip->i_depth - factor);
     960             : 
     961             :         /* initialize the first dirent on the new leaf block */
     962           0 :         dent = (struct gfs2_dirent *)(nbh->b_data + sizeof(struct gfs2_leaf));
     963           0 :         dent->de_rec_len = cpu_to_be16(dip->i_sbd->sd_bsize -
     964             :                                        sizeof(struct gfs2_leaf));
     965           0 :         lgfs2_bmodified(nbh);
     966           0 :         lgfs2_brelse(nbh);
     967             : 
     968             :         /* pad the hash table with the new leaf block */
     969           0 :         cpyptr = padbuf;
     970           0 :         for (i = start_lindex; i < end_lindex; i++) {
     971           0 :                 *cpyptr = cpu_to_be64(*bn);
     972           0 :                 cpyptr++;
     973             :         }
     974           0 :         pad_size = num_copies * sizeof(uint64_t);
     975           0 :         log_err(_("Writing to the hash table of directory %"PRIu64
     976             :                   " (0x%"PRIx64") at index: 0x%x for 0x%lx pointers.\n"),
     977             :                 dip->i_num.in_addr, dip->i_num.in_addr,
     978             :                 start_lindex, (unsigned long)pad_size / sizeof(uint64_t));
     979           0 :         count = lgfs2_writei(dip, padbuf, start_lindex * sizeof(uint64_t), pad_size);
     980           0 :         free(padbuf);
     981           0 :         if (count != pad_size) {
     982           0 :                 log_err( _("Error: bad write while fixing directory leaf "
     983             :                            "pointers.\n"));
     984           0 :                 return -1;
     985             :         }
     986           0 :         return 0;
     987             : }
     988             : 
     989             : /* pad_with_leafblks - pad a hash table with pointers to new leaf blocks
     990             :  *
     991             :  * @ip: pointer to the dinode structure
     992             :  * @tbl: pointer to the hash table in memory
     993             :  * @lindex: index location within the hash table to pad
     994             :  * @len: number of pointers to be padded
     995             :  */
     996           0 : static void pad_with_leafblks(struct fsck_cx *cx, struct lgfs2_inode *ip, __be64 *tbl,
     997             :                               int lindex, int len)
     998             : {
     999             :         int new_len, i;
    1000           0 :         uint32_t proper_start = lindex;
    1001             :         uint64_t new_leaf_blk;
    1002             : 
    1003           0 :         log_err(_("Padding inode %"PRIu64" (0x%"PRIx64") hash table at offset %d (0x%x) "
    1004             :                   "for %d pointers.\n"),
    1005             :                 ip->i_num.in_addr, ip->i_num.in_addr, lindex, lindex, len);
    1006           0 :         while (len) {
    1007           0 :                 new_len = 1;
    1008             :                 /* Determine the next factor of 2 down from extras. We can't
    1009             :                    just write out a leaf block on a power-of-two boundary.
    1010             :                    We also need to make sure it has a length that will
    1011             :                    ensure a "proper start" block as well. */
    1012           0 :                 while ((new_len << 1) <= len) {
    1013             :                         /* Translation: If doubling the size of the new leaf
    1014             :                            will make its start boundary wrong, we have to
    1015             :                            settle for a smaller length (and iterate more). */
    1016           0 :                         proper_start = (lindex & ~((new_len << 1) - 1));
    1017           0 :                         if (lindex != proper_start)
    1018           0 :                                 break;
    1019           0 :                         new_len <<= 1;
    1020             :                 }
    1021           0 :                 write_new_leaf(cx, ip, lindex, new_len, "after", &new_leaf_blk);
    1022           0 :                 log_err(_("New leaf block was allocated at %"PRIu64" (0x%"PRIx64") for "
    1023             :                           "index %d (0x%x), length %d\n"),
    1024             :                         new_leaf_blk, new_leaf_blk, lindex, lindex, new_len);
    1025           0 :                 fsck_bitmap_set(cx, ip, new_leaf_blk, _("pad leaf"), GFS2_BLKST_USED);
    1026             :                 /* Fix the hash table in memory to have the new leaf */
    1027           0 :                 for (i = 0; i < new_len; i++)
    1028           0 :                         tbl[lindex + i] = cpu_to_be64(new_leaf_blk);
    1029           0 :                 len -= new_len;
    1030           0 :                 lindex += new_len;
    1031             :         }
    1032           0 : }
    1033             : 
    1034             : /* lost_leaf - repair a leaf block that's on the wrong directory inode
    1035             :  *
    1036             :  * If the correct index is less than the starting index, we have a problem.
    1037             :  * Since we process the index sequentially, the previous index has already
    1038             :  * been processed, fixed, and is now correct. But this leaf wants to overwrite
    1039             :  * a previously written good leaf. The only thing we can do is move all the
    1040             :  * directory entries to lost+found so we don't overwrite the good leaf. Then
    1041             :  * we need to pad the gap we leave.
    1042             :  */
    1043           0 : static int lost_leaf(struct fsck_cx *cx, struct lgfs2_inode *ip, __be64 *tbl, uint64_t leafno,
    1044             :                      int ref_count, int lindex, struct lgfs2_buffer_head *bh)
    1045             : {
    1046             :         char *filename;
    1047           0 :         char *bh_end = bh->b_data + ip->i_sbd->sd_bsize;
    1048             :         struct gfs2_dirent *dent;
    1049             :         struct lgfs2_dirent de;
    1050             :         int error;
    1051           0 :         int isdir = 0;
    1052             : 
    1053           0 :         log_err(_("Leaf block %"PRIu64" (0x%"PRIx64") seems to be out of place and its "
    1054             :                   "contents need to be moved to lost+found.\n"),
    1055             :                 leafno, leafno);
    1056           0 :         if (!query(cx, _("Attempt to fix it? (y/n) "))) {
    1057           0 :                 log_err( _("Directory leaf was not fixed.\n"));
    1058           0 :                 return 0;
    1059             :         }
    1060           0 :         make_sure_lf_exists(cx, ip);
    1061             : 
    1062           0 :         dent = (struct gfs2_dirent *)(bh->b_data + sizeof(struct gfs2_leaf));
    1063           0 :         while (1) {
    1064             :                 char tmp_name[PATH_MAX];
    1065             : 
    1066           0 :                 memset(&de, 0, sizeof(de));
    1067           0 :                 lgfs2_dirent_in(&de, dent);
    1068           0 :                 filename = (char *)dent + sizeof(struct gfs2_dirent);
    1069           0 :                 memset(tmp_name, 0, sizeof(tmp_name));
    1070           0 :                 if (de.dr_name_len > sizeof(filename)) {
    1071           0 :                         log_debug(_("Encountered bad filename length; "
    1072             :                                     "stopped processing.\n"));
    1073           0 :                         break;
    1074             :                 }
    1075           0 :                 memcpy(tmp_name, filename, de.dr_name_len);
    1076           0 :                 if ((de.dr_name_len == 1 && filename[0] == '.')) {
    1077           0 :                         log_debug(_("Skipping entry '.'\n"));
    1078           0 :                 } else if (de.dr_name_len == 2 && filename[0] == '.' &&
    1079           0 :                            filename[1] == '.') {
    1080           0 :                         log_debug(_("Skipping entry '..'\n"));
    1081           0 :                 } else if (!de.dr_inum.in_formal_ino) { /* sentinel */
    1082           0 :                         log_debug(_("Skipping sentinel '%s'\n"), tmp_name);
    1083             :                 } else {
    1084           0 :                         uint32_t count = 0;
    1085           0 :                         struct dir_status ds = {0};
    1086           0 :                         int q = 0;
    1087             : 
    1088           0 :                         error = basic_dentry_checks(cx, ip, dent, &de.dr_inum,
    1089             :                                                     tmp_name, &count, &de,
    1090             :                                                     &ds, &q, bh, &isdir);
    1091           0 :                         if (error) {
    1092           0 :                                 log_err(_("Not relocating corrupt entry "
    1093             :                                           "\"%s\".\n"), tmp_name);
    1094             :                         } else {
    1095             : 
    1096           0 :                                 error = lgfs2_dir_add(lf_dip, filename,
    1097           0 :                                                 de.dr_name_len, &de.dr_inum,
    1098           0 :                                                 de.dr_type);
    1099           0 :                                 if (error && error != -EEXIST) {
    1100           0 :                                         log_err(_("Error %d encountered while "
    1101             :                                                   "trying to relocate \"%s\" "
    1102             :                                                   "to lost+found.\n"), error,
    1103             :                                                 tmp_name);
    1104           0 :                                         return error;
    1105             :                                 }
    1106             :                                 /* This inode is linked from lost+found */
    1107           0 :                                 incr_link_count(cx, de.dr_inum, lf_dip,
    1108           0 :                                                 _("from lost+found"));
    1109             :                                 /* If it's a directory, lost+found is
    1110             :                                    back-linked to it via .. */
    1111           0 :                                 if (isdir) {
    1112           0 :                                         struct lgfs2_inum no = lf_dip->i_num;
    1113           0 :                                         incr_link_count(cx, no, NULL, _("to lost+found"));
    1114             :                                 }
    1115           0 :                                 log_err(_("Relocated \"%s\", block %"PRIu64" (0x%"PRIx64") to lost+found.\n"),
    1116             :                                         tmp_name, de.dr_inum.in_addr, de.dr_inum.in_addr);
    1117             :                         }
    1118             :                 }
    1119           0 :                 if ((char *)dent + de.dr_rec_len >= bh_end)
    1120           0 :                         break;
    1121           0 :                 dent = (struct gfs2_dirent *)((char *)dent + de.dr_rec_len);
    1122             :         }
    1123           0 :         log_err(_("Directory entries from misplaced leaf block were relocated "
    1124             :                   "to lost+found.\n"));
    1125             :         /* Free the lost leaf. */
    1126           0 :         fsck_bitmap_set(cx, ip, leafno, _("lost leaf"), GFS2_BLKST_FREE);
    1127           0 :         ip->i_blocks--;
    1128           0 :         lgfs2_bmodified(ip->i_bh);
    1129             :         /* Now we have to deal with the bad hash table entries pointing to the
    1130             :            misplaced leaf block. But we can't just fill the gap with a single
    1131             :            leaf. We have to write on nice power-of-two boundaries, and we have
    1132             :            to pad out any extra pointers. */
    1133           0 :         pad_with_leafblks(cx, ip, tbl, lindex, ref_count);
    1134           0 :         return 1;
    1135             : }
    1136             : 
    1137           0 : static int basic_check_dentry(struct fsck_cx *cx, struct lgfs2_inode *ip, struct gfs2_dirent *dent,
    1138             :                               struct gfs2_dirent *prev_de,
    1139             :                               struct lgfs2_buffer_head *bh, char *filename,
    1140             :                               uint32_t *count, int *lindex, void *priv)
    1141             : {
    1142           0 :         int q = 0;
    1143             :         char tmp_name[MAX_FILENAME];
    1144             :         struct lgfs2_inum entry;
    1145           0 :         struct dir_status *ds = (struct dir_status *) priv;
    1146             :         struct lgfs2_dirent dentry, *de;
    1147             :         int error;
    1148             :         int isdir;
    1149             : 
    1150           0 :         memset(&dentry, 0, sizeof(dentry));
    1151           0 :         lgfs2_dirent_in(&dentry, dent);
    1152           0 :         de = &dentry;
    1153             : 
    1154           0 :         entry.in_addr = de->dr_inum.in_addr;
    1155           0 :         entry.in_formal_ino = de->dr_inum.in_formal_ino;
    1156             : 
    1157             :         /* Start of checks */
    1158           0 :         memset(tmp_name, 0, MAX_FILENAME);
    1159           0 :         if (de->dr_name_len < MAX_FILENAME)
    1160           0 :                 strncpy(tmp_name, filename, de->dr_name_len);
    1161             :         else
    1162           0 :                 strncpy(tmp_name, filename, MAX_FILENAME - 1);
    1163             : 
    1164           0 :         error = basic_dentry_checks(cx, ip, dent, &entry, tmp_name, count, de,
    1165             :                                     ds, &q, bh, &isdir);
    1166           0 :         if (error) {
    1167           0 :                 lgfs2_dirent2_del(ip, bh, prev_de, dent);
    1168           0 :                 log_err( _("Bad directory entry '%s' cleared.\n"), tmp_name);
    1169           0 :                 return 1;
    1170             :         } else {
    1171           0 :                 (*count)++;
    1172           0 :                 return 0;
    1173             :         }
    1174             : }
    1175             : 
    1176             : /* pass2_repair_leaf - Warn the user of an error and ask permission to fix it
    1177             :  * Process a bad leaf pointer and ask to repair the first time.
    1178             :  * The repair process involves extending the previous leaf's entries
    1179             :  * so that they replace the bad ones.  We have to hack up the old
    1180             :  * leaf a bit, but it's better than deleting the whole directory,
    1181             :  * which is what used to happen before. */
    1182           0 : static int pass2_repair_leaf(struct fsck_cx *cx, struct lgfs2_inode *ip, uint64_t *leaf_no,
    1183             :                              int lindex, int ref_count, const char *msg)
    1184             : {
    1185           0 :         int new_leaf_blks = 0, error, refs;
    1186           0 :         uint64_t bn = 0;
    1187             : 
    1188           0 :         log_err(_("Directory Inode %"PRIu64" (0x%"PRIx64") points to leaf %"PRIu64" (0x%"PRIx64") %s.\n"),
    1189             :                 ip->i_num.in_addr, ip->i_num.in_addr, *leaf_no, *leaf_no, msg);
    1190           0 :         if (!query(cx, _("Attempt to patch around it? (y/n) "))) {
    1191           0 :                 log_err( _("Bad leaf left in place.\n"));
    1192           0 :                 goto out;
    1193             :         }
    1194             :         /* We can only write leafs in quantities that are factors of
    1195             :            two, since leaves are doubled, not added sequentially.
    1196             :            So if we have a hole that's not a factor of 2, we have to
    1197             :            break it down into separate leaf blocks that are. */
    1198           0 :         while (ref_count) {
    1199           0 :                 refs = 1;
    1200           0 :                 while (refs <= ref_count) {
    1201           0 :                         if (refs * 2 > ref_count)
    1202           0 :                                 break;
    1203           0 :                         refs *= 2;
    1204             :                 }
    1205           0 :                 error = write_new_leaf(cx, ip, lindex, refs, _("replacing"), &bn);
    1206           0 :                 if (error)
    1207           0 :                         return error;
    1208             : 
    1209           0 :                 new_leaf_blks++;
    1210           0 :                 lindex += refs;
    1211           0 :                 ref_count -= refs;
    1212             :         }
    1213           0 :         log_err(_("Directory Inode %"PRIu64" (0x%"PRIx64") repaired.\n"),
    1214             :                 ip->i_num.in_addr, ip->i_num.in_addr);
    1215           0 : out:
    1216           0 :         *leaf_no = bn;
    1217           0 :         return new_leaf_blks;
    1218             : }
    1219             : 
    1220             : /* The purpose of leafck_fxns is to provide a means for function fix_hashtable
    1221             :  * to do basic sanity checks on leaf blocks before manipulating them, for
    1222             :  * example, splitting them. If they're corrupt, splitting them or trying to
    1223             :  * move their contents can cause a segfault. We can't really use the standard
    1224             :  * pass2_fxns because that will do things we don't want. For example, it will
    1225             :  * find '.' and '..' and increment the directory link count, which would be
    1226             :  * done a second time when the dirent is really checked in pass2_fxns.
    1227             :  * We don't want it to do the "wrong leaf" thing, or set_parent_dir either.
    1228             :  * We just want a basic sanity check on pointers and lengths.
    1229             :  */
    1230             : static struct metawalk_fxns leafck_fxns = {
    1231             :         .check_leaf_depth = check_leaf_depth,
    1232             :         .check_dentry = basic_check_dentry,
    1233             :         .repair_leaf = pass2_repair_leaf,
    1234             : };
    1235             : 
    1236             : /* fix_hashtable - fix a corrupt hash table
    1237             :  *
    1238             :  * The main intent of this function is to sort out hash table problems.
    1239             :  * That is, it needs to determine if leaf blocks are in the wrong place,
    1240             :  * if the count of pointers is wrong, and if there are extra pointers.
    1241             :  * Everything should be placed on correct power-of-two boundaries appropriate
    1242             :  * to their leaf depth, and extra pointers should be correctly padded with new
    1243             :  * leaf blocks.
    1244             :  *
    1245             :  * @ip: the directory dinode structure pointer
    1246             :  * @tbl: hash table that's already read into memory
    1247             :  * @hsize: hash table size, as dictated by the dinode's di_depth
    1248             :  * @leafblk: the leaf block number that appears at this lindex in the tbl
    1249             :  * @lindex: leaf index that has a problem
    1250             :  * @proper_start: where this leaf's pointers should start, as far as the
    1251             :  *                hash table is concerned (sight unseen; trusting the leaf
    1252             :  *                really belongs here).
    1253             :  * @len: count of pointers in the hash table to this leafblk
    1254             :  * @proper_len: pointer to return the proper number of pointers, as the kernel
    1255             :  *              calculates it, based on the leaf depth.
    1256             :  * @factor: the proper depth, given this number of pointers (rounded down).
    1257             :  *
    1258             :  * Returns: 0 - no changes made, or X if changes were made
    1259             :  */
    1260           0 : static int fix_hashtable(struct fsck_cx *cx, struct lgfs2_inode *ip, __be64 *tbl, unsigned hsize,
    1261             :                          uint64_t leafblk, int lindex, uint32_t proper_start,
    1262             :                          int len, int *proper_len, int factor)
    1263             : {
    1264             :         struct lgfs2_buffer_head *lbh;
    1265             :         struct lgfs2_dirent dentry;
    1266             :         struct lgfs2_leaf leaf;
    1267             :         struct gfs2_dirent *de;
    1268           0 :         int changes = 0, error, i, extras, hash_index;
    1269             :         uint64_t new_leaf_blk;
    1270             :         uint64_t leaf_no;
    1271             :         uint32_t leaf_proper_start;
    1272             : 
    1273           0 :         *proper_len = len;
    1274           0 :         log_err(_("Dinode %"PRIu64" (0x%"PRIx64") has a hash table error at index "
    1275             :                   "0x%x, length 0x%x: leaf block %"PRIu64" (0x%"PRIx64")\n"),
    1276             :                 ip->i_num.in_addr, ip->i_num.in_addr, lindex, len, leafblk, leafblk);
    1277           0 :         if (!query(cx, _("Fix the hash table? (y/n) "))) {
    1278           0 :                 log_err(_("Hash table not fixed.\n"));
    1279           0 :                 return 0;
    1280             :         }
    1281             : 
    1282           0 :         memset(&leaf, 0, sizeof(leaf));
    1283           0 :         leaf_no = leafblk;
    1284           0 :         error = check_leaf(cx, ip, lindex, &leafck_fxns, &leaf_no, &leaf, &len);
    1285           0 :         if (error)
    1286           0 :                 log_debug("Leaf repaired while fixing the hash table.\n");
    1287           0 :         lbh = lgfs2_bread(ip->i_sbd, leafblk);
    1288             :         /* If the leaf's depth is out of range for this dinode, it's obviously
    1289             :            attached to the wrong dinode. Move the dirents to lost+found. */
    1290           0 :         if (leaf.lf_depth > ip->i_depth) {
    1291           0 :                 log_err(_("This leaf block's depth (%d) is too big for this "
    1292             :                           "dinode's depth (%d)\n"),
    1293             :                         leaf.lf_depth, ip->i_depth);
    1294           0 :                 error = lost_leaf(cx, ip, tbl, leafblk, len, lindex, lbh);
    1295           0 :                 lgfs2_brelse(lbh);
    1296           0 :                 return error;
    1297             :         }
    1298             : 
    1299           0 :         memset(&dentry, 0, sizeof(dentry));
    1300           0 :         de = (struct gfs2_dirent *)(lbh->b_data + sizeof(struct gfs2_leaf));
    1301           0 :         lgfs2_dirent_in(&dentry, de);
    1302             : 
    1303             :         /* If this is an empty leaf, we can just delete it and pad. */
    1304           0 :         if ((dentry.dr_rec_len == ip->i_sbd->sd_bsize - sizeof(struct gfs2_leaf)) &&
    1305           0 :             (dentry.dr_inum.in_formal_ino == 0)) {
    1306           0 :                 lgfs2_brelse(lbh);
    1307           0 :                 lgfs2_free_block(ip->i_sbd, leafblk);
    1308           0 :                 ip->i_blocks--;
    1309           0 :                 log_err(_("Out of place leaf block %"PRIu64" (0x%"PRIx64") had no "
    1310             :                         "entries, so it was deleted.\n"),
    1311             :                         leafblk, leafblk);
    1312           0 :                 pad_with_leafblks(cx, ip, tbl, lindex, len);
    1313           0 :                 log_err(_("Reprocessing index 0x%x (case 1).\n"), lindex);
    1314           0 :                 return 1;
    1315             :         }
    1316             : 
    1317             :         /* Calculate the proper number of pointers based on the leaf depth. */
    1318           0 :         *proper_len = 1 << (ip->i_depth - leaf.lf_depth);
    1319             : 
    1320             :         /* Look at the first dirent and check its hash value to see if it's
    1321             :            at the proper starting offset. */
    1322           0 :         hash_index = hash_table_index(dentry.dr_hash, ip);
    1323             :         /* Need to use len here, not *proper_len because the leaf block may
    1324             :            be valid within the range, but starts too soon in the hash table. */
    1325           0 :         if (hash_index < lindex ||  hash_index > lindex + len) {
    1326           0 :                 log_err(_("This leaf block has hash index %d, which is out of "
    1327             :                           "bounds for where it appears in the hash table "
    1328             :                           "(%d - %d)\n"),
    1329             :                         hash_index, lindex, lindex + *proper_len);
    1330           0 :                 error = lost_leaf(cx, ip, tbl, leafblk, len, lindex, lbh);
    1331           0 :                 lgfs2_brelse(lbh);
    1332           0 :                 return error;
    1333             :         }
    1334             : 
    1335             :         /* Now figure out where this leaf should start, and pad any pointers
    1336             :            up to that point with new leaf blocks. */
    1337           0 :         leaf_proper_start = (hash_index & ~(*proper_len - 1));
    1338           0 :         if (lindex < leaf_proper_start) {
    1339           0 :                 log_err(_("Leaf pointers start at %d (0x%x), should be %d "
    1340             :                           "(%x).\n"), lindex, lindex,
    1341             :                         leaf_proper_start, leaf_proper_start);
    1342           0 :                 pad_with_leafblks(cx, ip, tbl, lindex, leaf_proper_start - lindex);
    1343           0 :                 lgfs2_brelse(lbh);
    1344           0 :                 return 1; /* reprocess the starting lindex */
    1345             :         }
    1346             :         /* If the proper start according to the leaf's hash index is later
    1347             :            than the proper start according to the hash table, it's once
    1348             :            again lost and we have to relocate it. The same applies if the
    1349             :            leaf's hash index is prior to the proper state, but the leaf is
    1350             :            already at its maximum depth. */
    1351           0 :         if ((leaf_proper_start < proper_start) ||
    1352           0 :             ((*proper_len > len || lindex > leaf_proper_start) &&
    1353           0 :              leaf.lf_depth == ip->i_depth)) {
    1354           0 :                 log_err(_("Leaf block should start at 0x%x, but it appears at "
    1355             :                           "0x%x in the hash table.\n"), leaf_proper_start,
    1356             :                         proper_start);
    1357           0 :                 error = lost_leaf(cx, ip, tbl, leafblk, len, lindex, lbh);
    1358           0 :                 lgfs2_brelse(lbh);
    1359           0 :                 return error;
    1360             :         }
    1361             : 
    1362             :         /* If we SHOULD have more pointers than we do, we can solve the
    1363             :            problem by splitting the block to a lower depth. Then we may have
    1364             :            the right number of pointers. If the leaf block pointers start
    1365             :            later than they should, we can split the leaf to give it a smaller
    1366             :            footprint in the hash table. */
    1367           0 :         if ((*proper_len > len || lindex > leaf_proper_start) &&
    1368           0 :             ip->i_depth > leaf.lf_depth) {
    1369           0 :                 log_err(_("For depth %d, length %d, the proper start is: "
    1370             :                           "0x%x.\n"), factor, len, proper_start);
    1371           0 :                 changes++;
    1372           0 :                 new_leaf_blk = find_free_blk(ip->i_sbd);
    1373           0 :                 if (lgfs2_dir_split_leaf(ip, lindex, leafblk, lbh)) {
    1374           0 :                         log_crit(_("Failed to split directory leaf block at 0x%"PRIx64": %s\n"),
    1375             :                                  ip->i_num.in_addr, strerror(errno));
    1376           0 :                         exit(1);
    1377             :                 }
    1378             :                 /* re-read the leaf to pick up lgfs2_dir_split_leaf's changes */
    1379           0 :                 lgfs2_leaf_in(&leaf, lbh->b_data);
    1380           0 :                 *proper_len = 1 << (ip->i_depth - leaf.lf_depth);
    1381           0 :                 log_err(_("Leaf block %"PRIu64" (0x%"PRIx64") was split from length %d to %d\n"),
    1382             :                         leafblk, leafblk, len, *proper_len);
    1383           0 :                 if (*proper_len < 0) {
    1384           0 :                         log_err(_("Programming error: proper_len=%d, "
    1385             :                                   "di_depth = %d, lf_depth = %d.\n"),
    1386             :                                 *proper_len, ip->i_depth, leaf.lf_depth);
    1387           0 :                         exit(FSCK_ERROR);
    1388             :                 }
    1389           0 :                 log_err(_("New split-off leaf block was allocated at %"PRIu64" "
    1390             :                           "(0x%"PRIx64") for index %d (0x%x)\n"),
    1391             :                         new_leaf_blk, new_leaf_blk, lindex, lindex);
    1392           0 :                 fsck_bitmap_set(cx, ip, new_leaf_blk, _("split leaf"), GFS2_BLKST_USED);
    1393           0 :                 log_err(_("Hash table repaired.\n"));
    1394             :                 /* Fix up the hash table in memory to include the new leaf */
    1395           0 :                 for (i = 0; i < *proper_len; i++)
    1396           0 :                         tbl[lindex + i] = cpu_to_be64(new_leaf_blk);
    1397           0 :                 if (*proper_len < (len >> 1)) {
    1398           0 :                         log_err(_("One leaf split is not enough. The hash "
    1399             :                                   "table will need to be reprocessed.\n"));
    1400           0 :                         lgfs2_brelse(lbh);
    1401           0 :                         return changes;
    1402             :                 }
    1403           0 :                 lindex += (*proper_len); /* skip the new leaf from the split */
    1404           0 :                 len -= (*proper_len);
    1405             :         }
    1406           0 :         if (*proper_len < len) {
    1407           0 :                 log_err(_("There are %d pointers, but leaf 0x%"PRIx64"'s "
    1408             :                           "depth, %d, only allows %d\n"),
    1409             :                         len, leafblk, leaf.lf_depth,
    1410             :                         *proper_len);
    1411             :         }
    1412           0 :         lgfs2_brelse(lbh);
    1413             :         /* At this point, lindex should be at the proper end of the pointers.
    1414             :            Now we need to replace any extra duplicate pointers to the old
    1415             :            (original) leafblk (that ran off the end) with new leaf blocks. */
    1416           0 :         lindex += (*proper_len); /* Skip past the normal good pointers */
    1417           0 :         len -= (*proper_len);
    1418           0 :         extras = 0;
    1419           0 :         for (i = 0; i < len; i++) {
    1420           0 :                 if (be64_to_cpu(tbl[lindex + i]) == leafblk)
    1421           0 :                         extras++;
    1422             :                 else
    1423           0 :                         break;
    1424             :         }
    1425           0 :         if (extras) {
    1426           0 :                 log_err(_("Found %d extra pointers to leaf %"PRIu64" (0x%"PRIx64")\n"),
    1427             :                         extras, leafblk, leafblk);
    1428           0 :                 pad_with_leafblks(cx, ip, tbl, lindex, extras);
    1429           0 :                 log_err(_("Reprocessing index 0x%x (case 2).\n"), lindex);
    1430           0 :                 return 1;
    1431             :         }
    1432           0 :         return changes;
    1433             : }
    1434             : 
    1435             : /* check_hash_tbl_dups - check for the same leaf in multiple places */
    1436           9 : static int check_hash_tbl_dups(struct fsck_cx *cx, struct lgfs2_inode *ip, __be64 *tbl,
    1437             :                                unsigned hsize, int lindex, int len)
    1438             : {
    1439             :         int l, len2;
    1440             :         uint64_t leafblk, leaf_no;
    1441             :         struct lgfs2_buffer_head *lbh;
    1442             :         struct gfs2_leaf leaf;
    1443             :         struct lgfs2_dirent dentry;
    1444             :         struct gfs2_dirent *de;
    1445             :         int hash_index; /* index into the hash table based on the hash */
    1446             : 
    1447           9 :         leafblk = be64_to_cpu(tbl[lindex]);
    1448          82 :         for (l = 0; l < hsize; l++) {
    1449          73 :                 if (l == lindex) { /* skip the valid reference */
    1450           9 :                         l += len - 1;
    1451           9 :                         continue;
    1452             :                 }
    1453          64 :                 if (be64_to_cpu(tbl[l]) != leafblk)
    1454          64 :                         continue;
    1455             : 
    1456           0 :                 for (len2 = 0; l + len2 < hsize; len2++) {
    1457           0 :                         if (l + len2 == lindex)
    1458           0 :                                 break;
    1459           0 :                         if (be64_to_cpu(tbl[l + len2]) != leafblk)
    1460           0 :                                 break;
    1461             :                 }
    1462           0 :                 log_err(_("Dinode %"PRIu64" (0x%"PRIx64") has duplicate leaf pointers "
    1463             :                           "to block %"PRIu64" (0x%"PRIx64") at offsets %u (0x%x) "
    1464             :                           "(for 0x%x) and %u (0x%x) (for 0x%x)\n"),
    1465             :                         ip->i_num.in_addr, ip->i_num.in_addr, leafblk, leafblk, lindex, lindex,
    1466             :                         len, l, l, len2);
    1467             : 
    1468             :                 /* See which set of references is valid: the one passed in
    1469             :                    or the duplicate we found. */
    1470           0 :                 memset(&leaf, 0, sizeof(leaf));
    1471           0 :                 leaf_no = leafblk;
    1472           0 :                 if (!valid_block_ip(ip, leaf_no)) /* Checked later */
    1473           0 :                         continue;
    1474             : 
    1475           0 :                 lbh = lgfs2_bread(ip->i_sbd, leafblk);
    1476           0 :                 if (lgfs2_check_meta(lbh->b_data, GFS2_METATYPE_LF)) { /* Chked later */
    1477           0 :                         lgfs2_brelse(lbh);
    1478           0 :                         continue;
    1479             :                 }
    1480             : 
    1481           0 :                 memset(&dentry, 0, sizeof(dentry));
    1482           0 :                 de = (struct gfs2_dirent *)(lbh->b_data + sizeof(struct gfs2_leaf));
    1483           0 :                 lgfs2_dirent_in(&dentry, de);
    1484           0 :                 hash_index = hash_table_index(dentry.dr_hash, ip);
    1485           0 :                 lgfs2_brelse(lbh);
    1486             :                 /* check the duplicate ref first */
    1487           0 :                 if (hash_index < l ||  hash_index > l + len2) {
    1488           0 :                         log_err(_("This leaf block has hash index %d, which "
    1489             :                                   "is out of bounds for lindex (%d - %d)\n"),
    1490             :                                 hash_index, l, l + len2);
    1491           0 :                         if (!query(cx, _("Fix the hash table? (y/n) "))) {
    1492           0 :                                 log_err(_("Hash table not fixed.\n"));
    1493           0 :                                 return 0;
    1494             :                         }
    1495             :                         /* Adjust the ondisk block count. The original value
    1496             :                            may have been correct without the duplicates but
    1497             :                            pass1 would have counted them and adjusted the
    1498             :                            count to include them. So we must subtract them. */
    1499           0 :                         ip->i_blocks--;
    1500           0 :                         lgfs2_bmodified(ip->i_bh);
    1501           0 :                         pad_with_leafblks(cx, ip, tbl, l, len2);
    1502             :                 } else {
    1503           0 :                         log_debug(_("Hash index 0x%x is the proper reference to leaf 0x%"PRIx64".\n"),
    1504             :                                   l, leafblk);
    1505             :                 }
    1506             :                 /* Check the original ref: both references might be bad.
    1507             :                    If both were bad, just return and if we encounter it
    1508             :                    again, we'll treat it as new. If the original ref is not
    1509             :                    bad, keep looking for (and fixing) other instances. */
    1510           0 :                 if (hash_index < lindex ||  hash_index > lindex + len) {
    1511           0 :                         log_err(_("This leaf block has hash index %d, which "
    1512             :                                   "is out of bounds for lindex (%d - %d).\n"),
    1513             :                                 hash_index, lindex, lindex + len);
    1514           0 :                         if (!query(cx, _("Fix the hash table? (y/n) "))) {
    1515           0 :                                 log_err(_("Hash table not fixed.\n"));
    1516           0 :                                 return 0;
    1517             :                         }
    1518           0 :                         ip->i_blocks--;
    1519           0 :                         lgfs2_bmodified(ip->i_bh);
    1520           0 :                         pad_with_leafblks(cx, ip, tbl, lindex, len);
    1521             :                         /* At this point we know both copies are bad, so we
    1522             :                            return to start fresh */
    1523           0 :                         return -EFAULT;
    1524             :                 } else {
    1525           0 :                         log_debug(_("Hash index 0x%x is the proper reference to leaf 0x%"PRIx64".\n"),
    1526             :                                   lindex, leafblk);
    1527             :                 }
    1528             :         }
    1529           9 :         return 0;
    1530             : }
    1531             : 
    1532             : /* check_hash_tbl - check that the hash table is sane
    1533             :  *
    1534             :  * We've got to make sure the hash table is sane. Each leaf needs to
    1535             :  * be counted a proper power of 2. We can't just have 3 pointers to a leaf.
    1536             :  * The number of pointers must correspond to the proper leaf depth, and they
    1537             :  * must all fall on power-of-two boundaries. The leaf block pointers all need
    1538             :  * to fall properly on these boundaries, otherwise the kernel code's
    1539             :  * calculations will land it on the wrong leaf block while it's searching,
    1540             :  * and the result will be files you can see with ls, but can't open, delete
    1541             :  * or use them.
    1542             :  *
    1543             :  * The goal of this function is to check the hash table to make sure the
    1544             :  * boundaries and lengths all line up properly, and if not, to fix it.
    1545             :  *
    1546             :  * Note: There's a delicate balance here, because this function gets called
    1547             :  *       BEFORE leaf blocks are checked by function check_leaf from function
    1548             :  *       check_leaf_blks: the hash table has to be sane before we can start
    1549             :  *       checking all the leaf blocks. And yet if there's hash table corruption
    1550             :  *       we may need to reference leaf blocks to fix it, which means we need
    1551             :  *       to check and/or fix a leaf block along the way.
    1552             :  */
    1553           7 : static int check_hash_tbl(struct fsck_cx *cx, struct lgfs2_inode *ip, __be64 *tbl,
    1554             :                           unsigned hsize, void *private)
    1555             : {
    1556           7 :         int error = 0;
    1557           7 :         int lindex, len, proper_len, i, changes = 0;
    1558             :         uint64_t leafblk;
    1559             :         struct lgfs2_leaf leaf;
    1560             :         struct lgfs2_buffer_head *lbh;
    1561             :         int factor;
    1562             :         uint32_t proper_start;
    1563             :         int anomaly;
    1564             : 
    1565           7 :         lindex = 0;
    1566          16 :         while (lindex < hsize) {
    1567           9 :                 if (fsck_abort)
    1568           0 :                         return changes;
    1569           9 :                 len = 1;
    1570           9 :                 factor = 0;
    1571           9 :                 leafblk = be64_to_cpu(tbl[lindex]);
    1572           9 :                 anomaly = 0;
    1573          49 :                 while (lindex + (len << 1) - 1 < hsize) {
    1574             :                         uint32_t next_proper_start;
    1575          42 :                         if (be64_to_cpu(tbl[lindex + (len << 1) - 1]) !=
    1576             :                             leafblk)
    1577           2 :                                 break;
    1578          40 :                         next_proper_start = (lindex & ~((len << 1) - 1));
    1579          40 :                         if (lindex != next_proper_start)
    1580           0 :                                 anomaly = 1;
    1581             :                         /* Check if there are other values written between
    1582             :                            here and the next factor. */
    1583         255 :                         for (i = len; !anomaly && i + lindex < hsize &&
    1584         463 :                                      i < (len << 1); i++)
    1585         215 :                                 if (be64_to_cpu(tbl[lindex + i]) != leafblk)
    1586           0 :                                         anomaly = 1;
    1587          40 :                         if (anomaly)
    1588           0 :                                 break;
    1589          40 :                         len <<= 1;
    1590          40 :                         factor++;
    1591             :                 }
    1592             : 
    1593             :                 /* Check for leftover pointers after the factor of two: */
    1594           9 :                 proper_len = len; /* A factor of 2 that fits nicely */
    1595          11 :                 while (lindex + len < hsize &&
    1596           2 :                        be64_to_cpu(tbl[lindex + len]) == leafblk)
    1597           0 :                         len++;
    1598             : 
    1599             :                 /* See if that leaf block is valid. If not, write a new one
    1600             :                    that falls on a proper boundary. If it doesn't naturally,
    1601             :                    we may need more. */
    1602           9 :                 if (!valid_block_ip(ip, leafblk)) {
    1603             :                         uint64_t new_leafblk;
    1604             : 
    1605           0 :                         log_err(_("Dinode %"PRIu64" (0x%"PRIx64") has bad leaf pointers "
    1606             :                                   "at offset %d for %d\n"),
    1607             :                                 ip->i_num.in_addr, ip->i_num.in_addr, lindex, len);
    1608           0 :                         if (!query(cx, _("Fix the hash table? (y/n) "))) {
    1609           0 :                                 log_err(_("Hash table not fixed.\n"));
    1610           0 :                                 lindex += len;
    1611           0 :                                 continue;
    1612             :                         }
    1613           0 :                         error = write_new_leaf(cx, ip, lindex, proper_len,
    1614           0 :                                                _("replacing"), &new_leafblk);
    1615           0 :                         if (error)
    1616           0 :                                 return error;
    1617             : 
    1618           0 :                         for (i = lindex; i < lindex + proper_len; i++)
    1619           0 :                                 tbl[i] = cpu_to_be64(new_leafblk);
    1620           0 :                         lindex += proper_len;
    1621           0 :                         continue;
    1622             :                 }
    1623             : 
    1624           9 :                 if (check_hash_tbl_dups(cx, ip, tbl, hsize, lindex, len))
    1625           0 :                         continue;
    1626             : 
    1627             :                 /* Make sure they call on proper leaf-split boundaries. This
    1628             :                    is the calculation used by the kernel, and lgfs2_dir_split_leaf */
    1629           9 :                 proper_start = (lindex & ~(proper_len - 1));
    1630           9 :                 if (lindex != proper_start) {
    1631           0 :                         log_debug(_("lindex 0x%x is not a proper starting "
    1632             :                                     "point for leaf %"PRIu64" (0x%"PRIx64"): 0x%"PRIx32"\n"),
    1633             :                                   lindex, leafblk, leafblk, proper_start);
    1634           0 :                         changes = fix_hashtable(cx, ip, tbl, hsize, leafblk,
    1635             :                                                 lindex, proper_start, len,
    1636             :                                                 &proper_len, factor);
    1637             :                         /* Check if we need to split more leaf blocks */
    1638           0 :                         if (changes) {
    1639           0 :                                 if (proper_len < (len >> 1))
    1640           0 :                                         log_err(_("More leaf splits are "
    1641             :                                                   "needed; "));
    1642           0 :                                 log_err(_("Reprocessing index 0x%x (case 3).\n"),
    1643             :                                         lindex);
    1644           0 :                                 continue; /* Make it reprocess the lindex */
    1645             :                         }
    1646             :                 }
    1647             :                 /* Check for extra pointers to this leaf. At this point, len
    1648             :                    is the number of pointers we have. proper_len is the proper
    1649             :                    number of pointers if the hash table is assumed correct.
    1650             :                    Function fix_hashtable will read in the leaf block and
    1651             :                    determine the "actual" proper length based on the leaf
    1652             :                    depth, and adjust the hash table accordingly. */
    1653           9 :                 if (len != proper_len) {
    1654           0 :                         log_err(_("Length %d (0x%x) is not a proper length "
    1655             :                                   "for leaf %"PRIu64" (0x%"PRIx64"). Valid boundary "
    1656             :                                   "assumed to be %d (0x%x).\n"), len, len,
    1657             :                                 leafblk, leafblk, proper_len, proper_len);
    1658           0 :                         lbh = lgfs2_bread(ip->i_sbd, leafblk);
    1659           0 :                         lgfs2_leaf_in(&leaf, lbh->b_data);
    1660           0 :                         if (lgfs2_check_meta(lbh->b_data, GFS2_METATYPE_LF) ||
    1661           0 :                             leaf.lf_depth > ip->i_depth)
    1662           0 :                                 leaf.lf_depth = factor;
    1663           0 :                         lgfs2_brelse(lbh);
    1664           0 :                         changes = fix_hashtable(cx, ip, tbl, hsize, leafblk,
    1665             :                                                 lindex, lindex, len,
    1666           0 :                                                 &proper_len, leaf.lf_depth);
    1667             :                         /* If fixing the hash table made changes, we can no
    1668             :                            longer count on the leaf block pointers all pointing
    1669             :                            to the same leaf (which is checked below). To avoid
    1670             :                            flagging another error, reprocess the offset. */
    1671           0 :                         if (changes) {
    1672           0 :                                 log_err(_("Reprocessing index 0x%x (case 4).\n"),
    1673             :                                         lindex);
    1674           0 :                                 continue; /* Make it reprocess the lindex */
    1675             :                         }
    1676             :                 }
    1677             : 
    1678             :                 /* Now make sure they're all the same pointer */
    1679         233 :                 for (i = lindex; i < lindex + proper_len; i++) {
    1680         224 :                         if (fsck_abort)
    1681           0 :                                 return changes;
    1682             : 
    1683         224 :                         if (be64_to_cpu(tbl[i]) == leafblk) /* No problem */
    1684         224 :                                 continue;
    1685             : 
    1686           0 :                         log_err(_("Dinode %"PRIu64" (0x%"PRIx64") has a hash table "
    1687             :                                   "inconsistency at index %d (0x%x) for %d\n"),
    1688             :                                 ip->i_num.in_addr, ip->i_num.in_addr,
    1689             :                                 i, i, len);
    1690           0 :                         if (!query(cx, _("Fix the hash table? (y/n) "))) {
    1691           0 :                                 log_err(_("Hash table not fixed.\n"));
    1692           0 :                                 continue;
    1693             :                         }
    1694           0 :                         changes++;
    1695             :                         /* Now we have to determine if the hash table is
    1696             :                            corrupt, or if the leaf has the wrong depth. */
    1697           0 :                         lbh = lgfs2_bread(ip->i_sbd, leafblk);
    1698           0 :                         lgfs2_leaf_in(&leaf, lbh->b_data);
    1699           0 :                         lgfs2_brelse(lbh);
    1700             :                         /* Calculate the expected pointer count based on the
    1701             :                            leaf depth. */
    1702           0 :                         proper_len = 1 << (ip->i_depth - leaf.lf_depth);
    1703           0 :                         if (proper_len != len) {
    1704           0 :                                 log_debug(_("Length 0x%x is not proper for "
    1705             :                                             "leaf %"PRIu64" (0x%"PRIx64"): 0x%x\n"),
    1706             :                                           len, leafblk, leafblk,
    1707             :                                           proper_len);
    1708           0 :                                 changes = fix_hashtable(cx, ip, tbl, hsize,
    1709             :                                                         leafblk, lindex,
    1710             :                                                         lindex, len,
    1711             :                                                         &proper_len,
    1712           0 :                                                         leaf.lf_depth);
    1713           0 :                                 break;
    1714             :                         }
    1715             :                 }
    1716           9 :                 lindex += proper_len;
    1717             :         }
    1718           7 :         if (!error && changes)
    1719           0 :                 error = 1;
    1720           7 :         return error;
    1721             : }
    1722             : 
    1723             : static struct metawalk_fxns pass2_fxns = {
    1724             :         .private = NULL,
    1725             :         .check_leaf_depth = check_leaf_depth,
    1726             :         .check_leaf = NULL,
    1727             :         .check_metalist = NULL,
    1728             :         .check_data = NULL,
    1729             :         .check_eattr_indir = check_eattr_indir,
    1730             :         .check_eattr_leaf = check_eattr_leaf,
    1731             :         .check_dentry = check_dentry,
    1732             :         .check_eattr_entry = NULL,
    1733             :         .check_hash_tbl = check_hash_tbl,
    1734             :         .repair_leaf = pass2_repair_leaf,
    1735             : };
    1736             : 
    1737         326 : static int check_metalist_qc(struct fsck_cx *cx, struct iptr iptr, struct lgfs2_buffer_head **bh, int h,
    1738             :                              int *is_valid, int *was_duplicate, void *private)
    1739             : {
    1740         326 :         struct lgfs2_inode *ip = iptr.ipt_ip;
    1741         326 :         uint64_t block = iptr_block(iptr);
    1742             : 
    1743         326 :         *was_duplicate = 0;
    1744         326 :         *is_valid = 1;
    1745         326 :         *bh = lgfs2_bread(ip->i_sbd, block);
    1746         326 :         return META_IS_GOOD;
    1747             : }
    1748             : 
    1749       48384 : static int check_data_qc(struct fsck_cx *cx, struct lgfs2_inode *ip, uint64_t metablock,
    1750             :                          uint64_t block, void *private,
    1751             :                          struct lgfs2_buffer_head *bbh, __be64 *ptr)
    1752             : {
    1753             :         struct lgfs2_buffer_head *bh;
    1754             : 
    1755             :         /* At this point, basic data block checks have already been done,
    1756             :            so we only need to make sure they're QC blocks. */
    1757       48384 :         if (!valid_block_ip(ip, block))
    1758           0 :                 return -1;
    1759             : 
    1760       48384 :         bh = lgfs2_bread(ip->i_sbd, block);
    1761       48384 :         if (lgfs2_check_meta(bh->b_data, GFS2_METATYPE_QC) != 0) {
    1762           0 :                 log_crit(_("Error: quota_change block at %"PRIu64" (0x%"PRIx64") is "
    1763             :                            "the wrong metadata type.\n"),
    1764             :                          block, block);
    1765           0 :                 lgfs2_brelse(bh);
    1766           0 :                 return -1;
    1767             :         }
    1768       48384 :         lgfs2_brelse(bh);
    1769       48384 :         return 0;
    1770             : }
    1771             : 
    1772             : static struct metawalk_fxns quota_change_fxns = {
    1773             :         .check_metalist = check_metalist_qc,
    1774             :         .check_data = check_data_qc,
    1775             : };
    1776             : 
    1777             : /* check_pernode_for - verify a file within the system per_node directory
    1778             :  * @x - index number X
    1779             :  * @per_node - pointer to the per_node inode
    1780             :  * @fn - system file name
    1781             :  * @filelen - the file length the system file needs to be
    1782             :  * @multiple - the file length must be a multiple (versus the exact value)
    1783             :  * @pass - a metawalk function for checking the data blocks (if any)
    1784             :  * @builder - a rebuild function for the file
    1785             :  *
    1786             :  * Returns: 0 if all went well, else error. */
    1787         189 : static int check_pernode_for(struct fsck_cx *cx, int x, struct lgfs2_inode *pernode, const char *fn,
    1788             :                              size_t filelen, int multiple,
    1789             :                              struct metawalk_fxns *pass,
    1790             :                              int builder(struct lgfs2_inode *per_node,
    1791             :                                          unsigned int j))
    1792             : {
    1793             :         struct lgfs2_inode *ip;
    1794         189 :         int error, valid_size = 1;
    1795             : 
    1796         189 :         log_debug(_("Checking system file %s\n"), fn);
    1797             :         /* coverity[identity_transfer:SUPPRESS] */
    1798         189 :         ip = lgfs2_lookupi(pernode, fn, strlen(fn));
    1799         189 :         if (ip == NULL) {
    1800           0 :                 log_err(_("System file %s is missing.\n"), fn);
    1801           0 :                 if (!query(cx, _("Rebuild the system file? (y/n) ")))
    1802           0 :                         return 0;
    1803           0 :                 goto build_it;
    1804             :         }
    1805         189 :         if (!ip->i_size)
    1806           0 :                 valid_size = 0;
    1807         189 :         else if (!multiple && ip->i_size != filelen)
    1808           0 :                 valid_size = 0;
    1809         189 :         else if (multiple && (ip->i_size % filelen))
    1810           0 :                 valid_size = 0;
    1811         189 :         if (!valid_size) {
    1812           0 :                 log_err(_("System file %s has an invalid size. Is %"PRIu64", should be %zu.\n"),
    1813             :                         fn, ip->i_size, filelen);
    1814           0 :                 if (!query(cx, _("Rebuild the system file? (y/n) ")))
    1815           0 :                         goto out_good;
    1816           0 :                 fsck_inode_put(&ip);
    1817           0 :                 goto build_it;
    1818             :         }
    1819         189 :         if (pass) {
    1820          63 :                 error = check_metatree(cx, ip, pass);
    1821          63 :                 if (!error)
    1822          63 :                         goto out_good;
    1823           0 :                 log_err(_("System file %s has bad contents.\n"), fn);
    1824           0 :                 if (!query(cx, _("Delete and rebuild the system file? (y/n) ")))
    1825           0 :                         goto out_good;
    1826           0 :                 check_metatree(cx, ip, &pass2_fxns_delete);
    1827           0 :                 fsck_inode_put(&ip);
    1828           0 :                 lgfs2_dirent_del(pernode, fn, strlen(fn));
    1829           0 :                 goto build_it;
    1830             :         }
    1831         126 : out_good:
    1832         189 :         fsck_inode_put(&ip);
    1833         189 :         return 0;
    1834             : 
    1835           0 : build_it:
    1836           0 :         if (builder(pernode, x)) {
    1837           0 :                 log_err(_("Error building %s\n"), fn);
    1838           0 :                 return -1;
    1839             :         }
    1840           0 :         ip = lgfs2_lookupi(pernode, fn, strlen(fn));
    1841           0 :         if (ip == NULL) {
    1842           0 :                 log_err(_("Error rebuilding %s.\n"), fn);
    1843           0 :                 return -1;
    1844             :         }
    1845           0 :         fsck_bitmap_set(cx, ip, ip->i_num.in_addr, fn, GFS2_BLKST_DINODE);
    1846           0 :         log_err(_("System file %s rebuilt.\n"), fn);
    1847           0 :         goto out_good;
    1848             : }
    1849             : 
    1850           0 : static int build_inum_range(struct lgfs2_inode *per_node, unsigned int n)
    1851             : {
    1852           0 :         struct lgfs2_inode *ip = lgfs2_build_inum_range(per_node, n);
    1853             : 
    1854           0 :         if (ip == NULL)
    1855           0 :                 return 1;
    1856           0 :         lgfs2_inode_put(&ip);
    1857           0 :         return 0;
    1858             : }
    1859             : 
    1860           0 : static int build_statfs_change(struct lgfs2_inode *per_node, unsigned int n)
    1861             : {
    1862           0 :         struct lgfs2_inode *ip = lgfs2_build_statfs_change(per_node, n);
    1863             : 
    1864           0 :         if (ip == NULL)
    1865           0 :                 return 1;
    1866           0 :         lgfs2_inode_put(&ip);
    1867           0 :         return 0;
    1868             : }
    1869             : 
    1870           0 : static int build_quota_change(struct lgfs2_inode *per_node, unsigned int n)
    1871             : {
    1872           0 :         struct lgfs2_inode *ip = lgfs2_build_quota_change(per_node, n);
    1873             : 
    1874           0 :         if (ip == NULL)
    1875           0 :                 return 1;
    1876           0 :         lgfs2_inode_put(&ip);
    1877           0 :         return 0;
    1878             : }
    1879             : 
    1880             : /* Check system directory inode                                           */
    1881             : /* Should work for all system directories: root, master, jindex, per_node */
    1882         224 : static int check_system_dir(struct fsck_cx *cx, struct lgfs2_inode *sysinode, const char *dirname,
    1883             :                      int builder(struct lgfs2_sbd *sdp))
    1884             : {
    1885         224 :         uint64_t iblock = 0;
    1886         224 :         struct dir_status ds = {0};
    1887         224 :         int error = 0;
    1888             : 
    1889         224 :         log_info( _("Checking system directory inode '%s'\n"), dirname);
    1890             : 
    1891         224 :         if (!sysinode) {
    1892           0 :                 log_err( _("Failed to check '%s': sysinode is null\n"), dirname);
    1893           0 :                 stack;
    1894           0 :                 return -1;
    1895             :         }
    1896             : 
    1897         224 :         iblock = sysinode->i_num.in_addr;
    1898         224 :         ds.q = bitmap_type(sysinode->i_sbd, iblock);
    1899             : 
    1900         224 :         pass2_fxns.private = (void *) &ds;
    1901         224 :         if (ds.q == GFS2_BLKST_FREE) {
    1902             :                 /* First check that the directory's metatree is valid */
    1903           0 :                 error = check_metatree(cx, sysinode, &pass2_fxns);
    1904           0 :                 if (error < 0) {
    1905           0 :                         stack;
    1906           0 :                         return error;
    1907             :                 }
    1908             :         }
    1909         224 :         error = check_dir(cx, sysinode, &pass2_fxns);
    1910         224 :         if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
    1911           0 :                 return FSCK_OK;
    1912         224 :         if (error < 0) {
    1913           0 :                 stack;
    1914           0 :                 return -1;
    1915             :         }
    1916         224 :         if (error > 0)
    1917           0 :                 fsck_bitmap_set(cx, sysinode, iblock, dirname, GFS2_BLKST_FREE);
    1918             : 
    1919         224 :         if (check_inode_eattr(cx, sysinode, &pass2_fxns)) {
    1920           0 :                 stack;
    1921           0 :                 return -1;
    1922             :         }
    1923         224 :         if (!ds.dotdir) {
    1924           0 :                 log_err( _("No '.' entry found for %s directory.\n"), dirname);
    1925           0 :                 if (query(cx, _("Is it okay to add '.' entry? (y/n) "))) {
    1926           0 :                         struct lgfs2_inum no = sysinode->i_num;
    1927           0 :                         log_warn( _("Adding '.' entry\n"));
    1928           0 :                         error = lgfs2_dir_add(sysinode, ".", 1, &no, DT_DIR);
    1929           0 :                         if (error) {
    1930           0 :                                 log_err(_("Error adding directory %s: %s\n"), "'.'",
    1931             :                                          strerror(errno));
    1932           0 :                                 return -errno;
    1933             :                         }
    1934             :                         /* This system inode is linked to itself via '.' */
    1935           0 :                         incr_link_count(cx, no, sysinode, "sysinode \".\"");
    1936           0 :                         ds.entry_count++;
    1937             :                 } else
    1938           0 :                         log_err( _("The directory was not fixed.\n"));
    1939             :         }
    1940         224 :         if (sysinode->i_entries != ds.entry_count) {
    1941           0 :                 log_err(_("%s inode %"PRIu64" (0x%"PRIx64"): Entries is %d - should be %d\n"),
    1942             :                         dirname, sysinode->i_num.in_addr, sysinode->i_num.in_addr, sysinode->i_entries,
    1943             :                         ds.entry_count);
    1944           0 :                 if (query(cx, _("Fix entries for %s inode %"PRIu64" (0x%"PRIx64")? (y/n) "),
    1945             :                           dirname, sysinode->i_num.in_addr, sysinode->i_num.in_addr)) {
    1946           0 :                         sysinode->i_entries = ds.entry_count;
    1947           0 :                         lgfs2_bmodified(sysinode->i_bh);
    1948           0 :                         log_warn( _("Entries updated\n"));
    1949             :                 } else {
    1950           0 :                         log_err(_("Entries for inode %"PRIu64" (0x%"PRIx64") left out of sync\n"),
    1951             :                                 sysinode->i_num.in_addr, sysinode->i_num.in_addr);
    1952             :                 }
    1953             :         }
    1954         224 :         error = 0;
    1955         224 :         if (sysinode == sysinode->i_sbd->md.pinode) {
    1956             :                 int j;
    1957             :                 char fn[64];
    1958             : 
    1959             :                 /* Make sure all the per_node files are there, and valid */
    1960         119 :                 for (j = 0; j < sysinode->i_sbd->md.journals; j++) {
    1961          63 :                         sprintf(fn, "inum_range%d", j);
    1962          63 :                         error += check_pernode_for(cx, j, sysinode, fn, 16, 0,
    1963             :                                                    NULL, build_inum_range);
    1964          63 :                         sprintf(fn, "statfs_change%d", j);
    1965          63 :                         error += check_pernode_for(cx, j, sysinode, fn, 24, 0,
    1966             :                                                    NULL, build_statfs_change);
    1967          63 :                         sprintf(fn, "quota_change%d", j);
    1968          63 :                         error += check_pernode_for(cx, j, sysinode, fn, 1048576, 1,
    1969             :                                                    &quota_change_fxns,
    1970             :                                                    build_quota_change);
    1971             :                 }
    1972             :         }
    1973         224 :         return error;
    1974             : }
    1975             : 
    1976             : /**
    1977             :  * is_system_dir - determine if a given block is for a system directory.
    1978             :  */
    1979         224 : static inline int is_system_dir(struct lgfs2_sbd *sdp, uint64_t block)
    1980             : {
    1981         224 :         if (block == sdp->md.rooti->i_num.in_addr ||
    1982         168 :             block == sdp->md.jiinode->i_num.in_addr ||
    1983         112 :             block == sdp->md.pinode->i_num.in_addr ||
    1984          56 :             block == sdp->master_dir->i_num.in_addr)
    1985         224 :                 return 1;
    1986           0 :         return 0;
    1987             : }
    1988             : 
    1989           0 : static int pass2_check_dir(struct fsck_cx *cx, struct lgfs2_inode *ip)
    1990             : {
    1991           0 :         uint64_t dirblk = ip->i_num.in_addr;
    1992           0 :         struct dir_status ds = {0};
    1993             :         int error;
    1994             : 
    1995           0 :         pass2_fxns.private = &ds;
    1996           0 :         error = check_dir(cx, ip, &pass2_fxns);
    1997           0 :         if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
    1998           0 :                 return FSCK_OK;
    1999           0 :         if (error < 0) {
    2000           0 :                 stack;
    2001           0 :                 return FSCK_ERROR;
    2002             :         }
    2003           0 :         if (error > 0) {
    2004             :                 struct dir_info *di;
    2005             : 
    2006           0 :                 di = dirtree_find(cx, dirblk);
    2007           0 :                 if (!di) {
    2008           0 :                         stack;
    2009           0 :                         return FSCK_ERROR;
    2010             :                 }
    2011           0 :                 if (query(cx, _("Remove directory entry for bad inode %"PRIu64" (0x%"PRIx64") in %"PRIu64" (0x%"PRIx64")? (y/n)"),
    2012             :                           dirblk, dirblk, di->treewalk_parent, di->treewalk_parent)) {
    2013           0 :                         error = remove_dentry_from_dir(cx, di->treewalk_parent, dirblk);
    2014           0 :                         if (error < 0) {
    2015           0 :                                 stack;
    2016           0 :                                 return FSCK_ERROR;
    2017             :                         }
    2018           0 :                         if (error > 0) {
    2019           0 :                                 log_warn(_("Unable to find dentry for %"PRIu64" (0x%"PRIx64") in %"PRIu64" (0x%"PRIx64")\n"),
    2020             :                                          dirblk, dirblk, di->treewalk_parent, di->treewalk_parent);
    2021             :                         }
    2022           0 :                         log_warn(_("Directory entry removed\n"));
    2023             :                 } else
    2024           0 :                         log_err(_("Directory entry to invalid inode remains.\n"));
    2025             : 
    2026           0 :                 log_debug(_("Directory block %"PRIu64" (0x%"PRIx64") is now marked as 'invalid'\n"),
    2027             :                           dirblk, dirblk);
    2028           0 :                 check_n_fix_bitmap(cx, ip->i_rgd, dirblk, 0, GFS2_BLKST_FREE);
    2029             :         }
    2030             : 
    2031           0 :         if (!ds.dotdir) {
    2032           0 :                 log_err(_("No '.' entry found for directory inode at block %"PRIu64" (0x%"PRIx64")\n"),
    2033             :                         dirblk, dirblk);
    2034             : 
    2035           0 :                 if (query(cx, _("Is it okay to add '.' entry? (y/n) "))) {
    2036           0 :                         struct lgfs2_inum no = ip->i_num;
    2037           0 :                         error = lgfs2_dir_add(ip, ".", 1, &no, DT_DIR);
    2038           0 :                         if (error) {
    2039           0 :                                 log_err(_("Error adding directory %s: %s\n"), "'.'",
    2040             :                                         strerror(errno));
    2041           0 :                                 return -errno;
    2042             :                         }
    2043             :                         /* directory links to itself via '.' */
    2044           0 :                         incr_link_count(cx, no, ip, _("\". (itself)\""));
    2045           0 :                         ds.entry_count++;
    2046           0 :                         log_err(_("The directory was fixed.\n"));
    2047             :                 } else {
    2048           0 :                         log_err(_("The directory was not fixed.\n"));
    2049             :                 }
    2050             :         }
    2051             : 
    2052           0 :         if (!fsck_abort && ip->i_entries != ds.entry_count) {
    2053           0 :                 log_err(_("Entries is %d - should be %d for inode block %"PRIu64" (0x%"PRIx64")\n"),
    2054             :                         ip->i_entries, ds.entry_count, ip->i_num.in_addr, ip->i_num.in_addr);
    2055           0 :                 if (query(cx, _("Fix the entry count? (y/n) "))) {
    2056           0 :                         ip->i_entries = ds.entry_count;
    2057           0 :                         lgfs2_bmodified(ip->i_bh);
    2058             :                 } else {
    2059           0 :                         log_err(_("The entry count was not fixed.\n"));
    2060             :                 }
    2061             :         }
    2062           0 :         return FSCK_OK;
    2063             : }
    2064             : 
    2065             : /* What i need to do in this pass is check that the dentries aren't
    2066             :  * pointing to invalid blocks...and verify the contents of each
    2067             :  * directory. and start filling in the directory info structure*/
    2068             : 
    2069             : /**
    2070             :  * pass2 - check pathnames
    2071             :  *
    2072             :  * verify root inode
    2073             :  * directory name length
    2074             :  * entries in range
    2075             :  */
    2076          56 : int pass2(struct fsck_cx *cx)
    2077             : {
    2078          56 :         struct lgfs2_sbd *sdp = cx->sdp;
    2079          56 :         struct osi_node *tmp, *next = NULL;
    2080             :         struct lgfs2_inode *ip;
    2081             :         struct dir_info *dt;
    2082             :         uint64_t dirblk;
    2083             :         int error;
    2084             : 
    2085             :         /* Check all the system directory inodes. */
    2086          56 :         if (check_system_dir(cx, sdp->md.jiinode, "jindex", build_jindex)) {
    2087           0 :                 stack;
    2088           0 :                 return FSCK_ERROR;
    2089             :         }
    2090          56 :         if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
    2091           0 :                 return FSCK_OK;
    2092          56 :         if (check_system_dir(cx, sdp->md.pinode, "per_node", build_per_node)) {
    2093           0 :                 stack;
    2094           0 :                 return FSCK_ERROR;
    2095             :         }
    2096          56 :         if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
    2097           0 :                 return FSCK_OK;
    2098          56 :         if (check_system_dir(cx, sdp->master_dir, "master", lgfs2_build_master)) {
    2099           0 :                 stack;
    2100           0 :                 return FSCK_ERROR;
    2101             :         }
    2102          56 :         if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
    2103           0 :                 return FSCK_OK;
    2104          56 :         if (check_system_dir(cx, sdp->md.rooti, "root", lgfs2_build_root)) {
    2105           0 :                 stack;
    2106           0 :                 return FSCK_ERROR;
    2107             :         }
    2108          56 :         if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
    2109           0 :                 return FSCK_OK;
    2110          56 :         log_info( _("Checking directory inodes.\n"));
    2111             :         /* Grab each directory inode, and run checks on it */
    2112         280 :         for (tmp = osi_first(&cx->dirtree); tmp; tmp = next) {
    2113         224 :                 next = osi_next(tmp);
    2114             : 
    2115         224 :                 dt = (struct dir_info *)tmp;
    2116         224 :                 dirblk = dt->dinode.in_addr;
    2117         224 :                 display_progress(dirblk);
    2118         224 :                 if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
    2119           0 :                         return FSCK_OK;
    2120             : 
    2121             :                 /* Skip the system inodes - they're checked above */
    2122         224 :                 if (is_system_dir(sdp, dirblk))
    2123         224 :                         continue;
    2124             : 
    2125             :                 /* If we created lost+found, its links should have been
    2126             :                    properly adjusted, so don't check it. */
    2127           0 :                 if (lf_was_created && (dirblk == lf_dip->i_num.in_addr)) {
    2128           0 :                         log_debug(_("Pass2 skipping the new lost+found.\n"));
    2129           0 :                         continue;
    2130             :                 }
    2131             : 
    2132           0 :                 log_debug(_("Checking directory inode at block %"PRIu64" (0x%"PRIx64")\n"),
    2133             :                           dirblk, dirblk);
    2134             : 
    2135           0 :                 ip = fsck_load_inode(sdp, dirblk);
    2136           0 :                 if (ip == NULL) {
    2137           0 :                         stack;
    2138           0 :                         return FSCK_ERROR;
    2139             :                 }
    2140           0 :                 error = pass2_check_dir(cx, ip);
    2141           0 :                 fsck_inode_put(&ip);
    2142             : 
    2143           0 :                 if (skip_this_pass || fsck_abort)
    2144           0 :                         return FSCK_OK;
    2145             : 
    2146           0 :                 if (error != FSCK_OK) {
    2147           0 :                         stack;
    2148           0 :                         return error;
    2149             :                 }
    2150             :         }
    2151          56 :         return FSCK_OK;
    2152             : }

Generated by: LCOV version 1.14