Whamcloud - gitweb
Update release notes, etc., for the 1.45.6 release
[tools/e2fsprogs.git] / e2fsck / pass2.c
index e922876..cb1e587 100644 (file)
@@ -71,8 +71,8 @@ static int allocate_dir_block(e2fsck_t ctx,
                              struct ext2_db_entry2 *dir_blocks_info,
                              char *buf, struct problem_context *pctx);
 static void clear_htree(e2fsck_t ctx, ext2_ino_t ino);
-static int htree_depth(struct dx_dir_info *dx_dir,
-                      struct dx_dirblock_info *dx_db);
+static short htree_depth(struct dx_dir_info *dx_dir,
+                        struct dx_dirblock_info *dx_db);
 static EXT2_QSORT_TYPE special_dir_block_cmp(const void *a, const void *b);
 
 struct check_dir_struct {
@@ -88,7 +88,7 @@ struct check_dir_struct {
 static void update_parents(struct dx_dir_info *dx_dir, int type)
 {
        struct dx_dirblock_info *dx_db, *dx_parent, *dx_previous;
-       int b;
+       blk_t b;
 
        for (b = 0, dx_db = dx_dir->dx_block;
             b < dx_dir->numblocks;
@@ -129,9 +129,10 @@ void e2fsck_pass2(e2fsck_t ctx)
 #endif
        struct check_dir_struct cd;
        struct dx_dir_info      *dx_dir;
-       struct dx_dirblock_info *dx_db, *dx_parent;
-       int                     b;
-       int                     i, depth;
+       struct dx_dirblock_info *dx_db;
+       blk_t                   b;
+       ext2_ino_t              i;
+       short                   depth;
        problem_t               code;
        int                     bad_dir;
        int (*check_dir_func)(ext2_filsys fs,
@@ -310,10 +311,10 @@ cleanup:
 }
 
 #define MAX_DEPTH 32000
-static int htree_depth(struct dx_dir_info *dx_dir,
-                      struct dx_dirblock_info *dx_db)
+static short htree_depth(struct dx_dir_info *dx_dir,
+                        struct dx_dirblock_info *dx_db)
 {
-       int     depth = 0;
+       short depth = 0;
 
        while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) {
                dx_db = &dx_dir->dx_block[dx_db->parent];
@@ -569,8 +570,8 @@ static void parse_int_node(ext2_filsys fs,
                           struct dx_dir_info   *dx_dir,
                           char *block_buf, int failed_csum)
 {
-       struct          ext2_dx_root_info  *root;
-       struct          ext2_dx_entry *ent;
+       struct          ext2_dx_root_info  *root;
+       struct          ext2_dx_entry *ent;
        struct          ext2_dx_countlimit *limit;
        struct dx_dirblock_info *dx_db;
        int             i, expect_limit, count;
@@ -586,10 +587,10 @@ static void parse_int_node(ext2_filsys fs,
 #ifdef DX_DEBUG
                printf("Root node dump:\n");
                printf("\t Reserved zero: %u\n", root->reserved_zero);
-               printf("\t Hash Version: %d\n", root->hash_version);
-               printf("\t Info length: %d\n", root->info_length);
-               printf("\t Indirect levels: %d\n", root->indirect_levels);
-               printf("\t Flags: %d\n", root->unused_flags);
+               printf("\t Hash Version: %u\n", root->hash_version);
+               printf("\t Info length: %u\n", root->info_length);
+               printf("\t Indirect levels: %u\n", root->indirect_levels);
+               printf("\t Flags: %x\n", root->unused_flags);
 #endif
 
                ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length);
@@ -645,7 +646,7 @@ static void parse_int_node(ext2_filsys fs,
 #endif
                blk = ext2fs_le32_to_cpu(ent[i].block) & EXT4_DX_BLOCK_MASK;
                /* Check to make sure the block is valid */
-               if (blk >= (blk_t) dx_dir->numblocks) {
+               if (blk >= dx_dir->numblocks) {
                        cd->pctx.blk = blk;
                        if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK,
                                        &cd->pctx))
@@ -933,6 +934,8 @@ static int check_dir_block(ext2_filsys fs,
        int     filetype = 0;
        int     encrypted = 0;
        size_t  max_block_size;
+       int     hash_flags = 0;
+       static char *eop_read_dirblock = NULL;
 
        cd = (struct check_dir_struct *) priv_data;
        ibuf = buf = cd->buf;
@@ -979,7 +982,8 @@ static int check_dir_block(ext2_filsys fs,
         * very large and then the files are deleted. For now, all that is
         * needed is to avoid e2fsck filling in these holes as part of
         * feature flag. */
-       if (db->blk == 0 && ext2fs_has_feature_largedir(fs->super))
+       if (db->blk == 0 && ext2fs_has_feature_largedir(fs->super) &&
+           !ext2fs_has_feature_inline_data(fs->super))
                return 0;
 
        if (db->blk == 0 && !inline_data_size) {
@@ -1002,7 +1006,9 @@ static int check_dir_block(ext2_filsys fs,
               db->blockcnt, ino);
 #endif
 
-       ehandler_operation(_("reading directory block"));
+       if (!eop_read_dirblock)
+               eop_read_dirblock = (char *) _("reading directory block");
+       ehandler_operation(eop_read_dirblock);
        if (inline_data_size) {
                memset(buf, 0, fs->blocksize - inline_data_size);
                cd->pctx.errcode = ext2fs_inline_data_get(fs, ino, 0, buf, 0);
@@ -1426,9 +1432,13 @@ skip_checksum:
                        dir_modified++;
 
                if (dx_db) {
-                       ext2fs_dirhash(dx_dir->hashversion, dirent->name,
-                                      ext2fs_dirent_name_len(dirent),
-                                      fs->super->s_hash_seed, &hash, 0);
+                       if (dx_dir->casefolded_hash)
+                               hash_flags = EXT4_CASEFOLD_FL;
+
+                       ext2fs_dirhash2(dx_dir->hashversion, dirent->name,
+                                       ext2fs_dirent_name_len(dirent),
+                                       fs->encoding, hash_flags,
+                                       fs->super->s_hash_seed, &hash, 0);
                        if (hash < dx_db->min_hash)
                                dx_db->min_hash = hash;
                        if (hash > dx_db->max_hash)
@@ -1610,6 +1620,7 @@ abort_free_dict:
 struct del_block {
        e2fsck_t        ctx;
        e2_blkcnt_t     num;
+       blk64_t last_cluster;
 };
 
 /*
@@ -1624,14 +1635,20 @@ static int deallocate_inode_block(ext2_filsys fs,
                                  void *priv_data)
 {
        struct del_block *p = priv_data;
+       blk64_t cluster = EXT2FS_B2C(fs, *block_nr);
 
        if (*block_nr == 0)
                return 0;
+
+       if (cluster == p->last_cluster)
+               return 0;
+
+       p->last_cluster = cluster;
        if ((*block_nr < fs->super->s_first_data_block) ||
            (*block_nr >= ext2fs_blocks_count(fs->super)))
                return 0;
-       if ((*block_nr % EXT2FS_CLUSTER_RATIO(fs)) == 0)
-               ext2fs_block_alloc_stats2(fs, *block_nr, -1);
+
+        ext2fs_block_alloc_stats2(fs, *block_nr, -1);
        p->num++;
        return 0;
 }
@@ -1692,6 +1709,7 @@ static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
 
        del_block.ctx = ctx;
        del_block.num = 0;
+       del_block.last_cluster = 0;
        pctx.errcode = ext2fs_block_iterate3(fs, ino, 0, block_buf,
                                             deallocate_inode_block,
                                             &del_block);