LCOV - code coverage report
Current view: top level - fsck - pass2.c (source / functions) Coverage Total Hit
Test: gfs2-utils.info Lines: 22.9 % 1028 235
Test Date: 2024-03-07 16:24:06 Functions: 48.5 % 33 16

            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          114 : 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          114 :         di = dirtree_find(cx, child.in_addr);
      41          114 :         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          114 :         if (di->dinode.in_addr == child.in_addr &&
      48          114 :             di->dinode.in_formal_ino == child.in_formal_ino) {
      49          114 :                 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          114 :                 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          114 :                 di->treewalk_parent = parent.in_addr;
      60              :         }
      61              : 
      62          114 :         return 0;
      63              : }
      64              : 
      65              : /* Set's the child's '..' directory inode number in dir_info structure */
      66          228 : static int set_dotdot_dir(struct fsck_cx *cx, uint64_t childblock, struct lgfs2_inum parent)
      67              : {
      68              :         struct dir_info *di;
      69              : 
      70          228 :         di = dirtree_find(cx, childblock);
      71          228 :         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          228 :         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          228 :         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          228 :         log_debug("Setting '..' for directory block (0x%"PRIx64") to parent (0x%"PRIx64")\n",
      92              :                   childblock, parent.in_addr);
      93          228 :         di->dotdot_parent.in_addr = parent.in_addr;
      94          228 :         di->dotdot_parent.in_formal_ino = parent.in_formal_ino;
      95          228 :         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         1054 : 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         1054 :         *isdir = 0;
     130         1054 :         if (q != GFS2_BLKST_DINODE) {
     131            0 :                 log_err( _("Invalid block type\n"));
     132            0 :                 return -1;
     133              :         }
     134         1054 :         if (de_type == DT_DIR)
     135          570 :                 *isdir = 1;
     136              :         /* Check if the dinode is in the dir tree */
     137         1054 :         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         1054 :         if (dt)
     144          570 :                 return !(*isdir);
     145          484 :         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         1054 : 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         1054 :         struct lgfs2_sbd *sdp = ip->i_sbd;
     427              :         uint32_t calculated_hash;
     428         1054 :         struct lgfs2_inode *entry_ip = NULL;
     429              :         int error;
     430              :         struct inode_info *ii;
     431         1054 :         struct dir_info *di = NULL;
     432         1054 :         struct lgfs2_inum inum = {0};
     433              : 
     434         1054 :         *isdir = 0;
     435         1054 :         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         1054 :         if (d->dr_rec_len < GFS2_DIRENT_SIZE(d->dr_name_len) ||
     452         1054 :             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         1054 :         calculated_hash = lgfs2_disk_hash(tmp_name, d->dr_name_len);
     471         1054 :         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         1054 :         *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         1054 :         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         1054 :         error = check_file_type(cx, entry->in_addr, d->dr_type, *q, isdir);
     539         1054 :         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         1054 :         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         1054 :         ii = inodetree_find(cx, entry->in_addr);
     570         1054 :         if (ii)
     571            0 :                 inum = ii->num;
     572              :         else {
     573         1054 :                 di = dirtree_find(cx, entry->in_addr);
     574         1054 :                 if (di)
     575          570 :                         inum = di->dinode;
     576          484 :                 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          484 :                         return 0;
     581              :                 }
     582              :         }
     583          570 :         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          570 :         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         1054 : 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         1054 :         struct lgfs2_sbd *sdp = ip->i_sbd;
     703         1054 :         int q = 0;
     704              :         char tmp_name[MAX_FILENAME];
     705              :         struct lgfs2_inum entry;
     706         1054 :         struct dir_status *ds = (struct dir_status *) priv;
     707              :         int error;
     708         1054 :         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         1054 :         lgfs2_dirent_in(&d, dent);
     715              : 
     716         1054 :         entry.in_addr = d.dr_inum.in_addr;
     717         1054 :         entry.in_formal_ino = d.dr_inum.in_formal_ino;
     718              : 
     719              :         /* Start of checks */
     720         1054 :         memset(tmp_name, 0, MAX_FILENAME);
     721         1054 :         if (d.dr_name_len < MAX_FILENAME)
     722         1054 :                 strncpy(tmp_name, filename, d.dr_name_len);
     723              :         else
     724            0 :                 strncpy(tmp_name, filename, MAX_FILENAME - 1);
     725              : 
     726         1054 :         error = basic_dentry_checks(cx, ip, dent, &entry, tmp_name, count, &d,
     727              :                                     ds, &q, bh, &isdir);
     728         1054 :         if (error)
     729            0 :                 goto nuke_dentry;
     730              : 
     731         1054 :         if (!strcmp(".", tmp_name)) {
     732          228 :                 log_debug(_("Found . dentry in directory %"PRIu64" (0x%"PRIx64")\n"),
     733              :                           ip->i_num.in_addr, ip->i_num.in_addr);
     734              : 
     735          228 :                 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          228 :                 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          228 :                 ds->dotdir = 1;
     781          228 :                 goto dentry_is_valid;
     782              :         }
     783          826 :         if (!strcmp("..", tmp_name)) {
     784          228 :                 log_debug(_("Found '..' dentry in directory %"PRIu64" (0x%"PRIx64")\n"),
     785              :                           ip->i_num.in_addr, ip->i_num.in_addr);
     786          228 :                 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          228 :                 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          228 :                 if (set_dotdot_dir(cx, ip->i_num.in_addr, entry)) {
     831            0 :                         stack;
     832            0 :                         return -1;
     833              :                 }
     834              : 
     835          228 :                 ds->dotdotdir = 1;
     836          228 :                 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          598 :         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          598 :         if (!isdir) {
     856          484 :                 log_debug(_("Found non-dir inode dentry pointing to %"PRIu64" (0x%"PRIx64")\n"),
     857              :                           entry.in_addr, entry.in_addr);
     858          484 :                 goto dentry_is_valid;
     859              :         }
     860              : 
     861              :         /*log_debug( _("Found plain directory dentry\n"));*/
     862          114 :         error = set_parent_dir(cx, entry, ip->i_num);
     863          114 :         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          114 :         } else if (error < 0) {
     874            0 :                 stack;
     875            0 :                 return -1;
     876              :         }
     877          114 : dentry_is_valid:
     878              :         /* This directory inode links to this inode via this dentry */
     879         1054 :         error = incr_link_count(cx, entry, ip, _("valid reference"));
     880         1054 :         if (error == INCR_LINK_CHECK_ORIG) {
     881            0 :                 error = check_suspicious_dirref(cx, &entry);
     882         1054 :         } 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         1054 :         (*count)++;
     888         1054 :         ds->entry_count++;
     889              :         /* End of checks */
     890         1054 :         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          293 : 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          293 :         struct lgfs2_inode *ip = iptr.ipt_ip;
    1741          293 :         uint64_t block = iptr_block(iptr);
    1742              : 
    1743          293 :         *was_duplicate = 0;
    1744          293 :         *is_valid = 1;
    1745          293 :         *bh = lgfs2_bread(ip->i_sbd, block);
    1746          293 :         return META_IS_GOOD;
    1747              : }
    1748              : 
    1749        32512 : 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        32512 :         if (!valid_block_ip(ip, block))
    1758            0 :                 return -1;
    1759              : 
    1760        32512 :         bh = lgfs2_bread(ip->i_sbd, block);
    1761        32512 :         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        32512 :         lgfs2_brelse(bh);
    1769        32512 :         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          192 : 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          192 :         int error, valid_size = 1;
    1795              : 
    1796          192 :         log_debug(_("Checking system file %s\n"), fn);
    1797              :         /* coverity[identity_transfer:SUPPRESS] */
    1798          192 :         ip = lgfs2_lookupi(pernode, fn, strlen(fn));
    1799          192 :         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          192 :         if (!ip->i_size)
    1806            0 :                 valid_size = 0;
    1807          192 :         else if (!multiple && ip->i_size != filelen)
    1808            0 :                 valid_size = 0;
    1809          192 :         else if (multiple && (ip->i_size % filelen))
    1810            0 :                 valid_size = 0;
    1811          192 :         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          192 :         if (pass) {
    1820           64 :                 error = check_metatree(cx, ip, pass);
    1821           64 :                 if (!error)
    1822           64 :                         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          128 : out_good:
    1832          192 :         fsck_inode_put(&ip);
    1833          192 :         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, LGFS2_DEFAULT_QCSIZE);
    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          228 : static int check_system_dir(struct fsck_cx *cx, struct lgfs2_inode *sysinode, const char *dirname,
    1883              :                      int builder(struct fsck_cx *cx))
    1884              : {
    1885          228 :         uint64_t iblock = 0;
    1886          228 :         struct dir_status ds = {0};
    1887          228 :         int error = 0;
    1888              : 
    1889          228 :         log_info( _("Checking system directory inode '%s'\n"), dirname);
    1890              : 
    1891          228 :         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          228 :         iblock = sysinode->i_num.in_addr;
    1898          228 :         ds.q = bitmap_type(sysinode->i_sbd, iblock);
    1899              : 
    1900          228 :         pass2_fxns.private = (void *) &ds;
    1901          228 :         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          228 :         error = check_dir(cx, sysinode, &pass2_fxns);
    1910          228 :         if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
    1911            0 :                 return FSCK_OK;
    1912          228 :         if (error < 0) {
    1913            0 :                 stack;
    1914            0 :                 return -1;
    1915              :         }
    1916          228 :         if (error > 0)
    1917            0 :                 fsck_bitmap_set(cx, sysinode, iblock, dirname, GFS2_BLKST_FREE);
    1918              : 
    1919          228 :         if (check_inode_eattr(cx, sysinode, &pass2_fxns)) {
    1920            0 :                 stack;
    1921            0 :                 return -1;
    1922              :         }
    1923          228 :         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          228 :         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          228 :         error = 0;
    1955          228 :         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          121 :                 for (j = 0; j < sysinode->i_sbd->md.journals; j++) {
    1961           64 :                         sprintf(fn, "inum_range%d", j);
    1962           64 :                         error += check_pernode_for(cx, j, sysinode, fn, 16, 0,
    1963              :                                                    NULL, build_inum_range);
    1964           64 :                         sprintf(fn, "statfs_change%d", j);
    1965           64 :                         error += check_pernode_for(cx, j, sysinode, fn, 24, 0,
    1966              :                                                    NULL, build_statfs_change);
    1967           64 :                         sprintf(fn, "quota_change%d", j);
    1968           64 :                         error += check_pernode_for(cx, j, sysinode, fn, 1048576, 1,
    1969              :                                                    &quota_change_fxns,
    1970              :                                                    build_quota_change);
    1971              :                 }
    1972              :         }
    1973          228 :         return error;
    1974              : }
    1975              : 
    1976              : /**
    1977              :  * is_system_dir - determine if a given block is for a system directory.
    1978              :  */
    1979          228 : static inline int is_system_dir(struct lgfs2_sbd *sdp, uint64_t block)
    1980              : {
    1981          228 :         if (block == sdp->md.rooti->i_num.in_addr ||
    1982          171 :             block == sdp->md.jiinode->i_num.in_addr ||
    1983          114 :             block == sdp->md.pinode->i_num.in_addr ||
    1984           57 :             block == sdp->master_dir->i_num.in_addr)
    1985          228 :                 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           57 : int pass2(struct fsck_cx *cx)
    2077              : {
    2078           57 :         struct lgfs2_sbd *sdp = cx->sdp;
    2079           57 :         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           57 :         if (check_system_dir(cx, sdp->md.jiinode, "jindex", build_jindex)) {
    2087            0 :                 stack;
    2088            0 :                 return FSCK_ERROR;
    2089              :         }
    2090           57 :         if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
    2091            0 :                 return FSCK_OK;
    2092           57 :         if (check_system_dir(cx, sdp->md.pinode, "per_node", build_per_node)) {
    2093            0 :                 stack;
    2094            0 :                 return FSCK_ERROR;
    2095              :         }
    2096           57 :         if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
    2097            0 :                 return FSCK_OK;
    2098           57 :         if (check_system_dir(cx, sdp->master_dir, "master", build_metadir)) {
    2099            0 :                 stack;
    2100            0 :                 return FSCK_ERROR;
    2101              :         }
    2102           57 :         if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
    2103            0 :                 return FSCK_OK;
    2104           57 :         if (check_system_dir(cx, sdp->md.rooti, "root", build_root)) {
    2105            0 :                 stack;
    2106            0 :                 return FSCK_ERROR;
    2107              :         }
    2108           57 :         if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
    2109            0 :                 return FSCK_OK;
    2110           57 :         log_info( _("Checking directory inodes.\n"));
    2111              :         /* Grab each directory inode, and run checks on it */
    2112          285 :         for (tmp = osi_first(&cx->dirtree); tmp; tmp = next) {
    2113          228 :                 next = osi_next(tmp);
    2114              : 
    2115          228 :                 dt = (struct dir_info *)tmp;
    2116          228 :                 dirblk = dt->dinode.in_addr;
    2117          228 :                 display_progress(dirblk);
    2118          228 :                 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          228 :                 if (is_system_dir(sdp, dirblk))
    2123          228 :                         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           57 :         return FSCK_OK;
    2152              : }
        

Generated by: LCOV version 2.0-1