Whamcloud - gitweb
e2fsck: force all block allocations to use block_found_map
authorDarrick J. Wong <darrick.wong@oracle.com>
Fri, 18 Jul 2014 22:53:41 +0000 (15:53 -0700)
committerTheodore Ts'o <tytso@mit.edu>
Fri, 25 Jul 2014 02:16:59 +0000 (22:16 -0400)
During the later passes of efsck, we sometimes need to allocate and
map blocks into a file.  This can happen either by fsck directly
calling new_block() or indirectly by the library calling new_block
because it needs to allocate a block for lower level metadata (bmap2()
with BMAP_SET; block_iterate3() with BLOCK_CHANGED).

We need to force new_block to allocate blocks from the found block
map, because the FS block map could be inaccurate for various reasons:
the map is wrong, there are missing blocks, the checksum failed, etc.

Therefore, any time fsck does something that could to allocate blocks,
we need to intercept allocation requests so that they're sourced from
the found block map.  Remove the previous code that swapped bitmap
pointers as this is now unneeded.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
e2fsck/e2fsck.h
e2fsck/pass1.c
e2fsck/pass1b.c
e2fsck/pass2.c
e2fsck/pass3.c
e2fsck/rehash.c

index 998abdc..cee74a3 100644 (file)
@@ -475,6 +475,7 @@ extern int e2fsck_pass1_check_symlink(ext2_filsys fs, ext2_ino_t ino,
 extern void e2fsck_clear_inode(e2fsck_t ctx, ext2_ino_t ino,
                               struct ext2_inode *inode, int restart_flag,
                               const char *source);
+extern void e2fsck_intercept_block_allocations(e2fsck_t ctx);
 
 /* pass2.c */
 extern int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
index 784195a..7a887de 100644 (file)
@@ -691,6 +691,7 @@ void e2fsck_pass1(e2fsck_t ctx)
        block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 3,
                                                    "block interate buffer");
        e2fsck_use_inode_shortcuts(ctx, 1);
+       e2fsck_intercept_block_allocations(ctx);
        old_op = ehandler_operation(_("opening inode scan"));
        pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
                                              &scan);
@@ -1185,10 +1186,6 @@ void e2fsck_pass1(e2fsck_t ctx)
        }
 
        if (ctx->flags & E2F_FLAG_RESIZE_INODE) {
-               ext2fs_block_bitmap save_bmap;
-
-               save_bmap = fs->block_map;
-               fs->block_map = ctx->block_found_map;
                clear_problem_context(&pctx);
                pctx.errcode = ext2fs_create_resize_inode(fs);
                if (pctx.errcode) {
@@ -1206,7 +1203,6 @@ void e2fsck_pass1(e2fsck_t ctx)
                        e2fsck_write_inode(ctx, EXT2_RESIZE_INO, inode,
                                           "recreate inode");
                }
-               fs->block_map = save_bmap;
                ctx->flags &= ~E2F_FLAG_RESIZE_INODE;
        }
 
@@ -2937,11 +2933,6 @@ void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int use_shortcuts)
                fs->read_inode = pass1_read_inode;
                fs->write_inode = pass1_write_inode;
                ctx->stashed_ino = 0;
-               ext2fs_set_alloc_block_callback(fs, e2fsck_get_alloc_block,
-                                               0);
-               ext2fs_set_block_alloc_stats_callback(fs,
-                                                     e2fsck_block_alloc_stats,
-                                                     0);
        } else {
                fs->get_blocks = 0;
                fs->check_directory = 0;
@@ -2949,3 +2940,10 @@ void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int use_shortcuts)
                fs->write_inode = 0;
        }
 }
+
+void e2fsck_intercept_block_allocations(e2fsck_t ctx)
+{
+       ext2fs_set_alloc_block_callback(ctx->fs, e2fsck_get_alloc_block, 0);
+       ext2fs_set_block_alloc_stats_callback(ctx->fs,
+                                               e2fsck_block_alloc_stats, 0);
+}
index b4cc532..9b38977 100644 (file)
@@ -611,7 +611,6 @@ static int delete_file_block(ext2_filsys fs,
                            _("internal error: can't find dup_blk for %llu\n"),
                                *block_nr);
        } else {
-               ext2fs_unmark_block_bitmap2(ctx->block_found_map, *block_nr);
                ext2fs_block_alloc_stats2(fs, *block_nr, -1);
                pb->dup_blocks++;
        }
index 7277a7b..517adaa 100644 (file)
@@ -1171,7 +1171,6 @@ static int deallocate_inode_block(ext2_filsys fs,
        if ((*block_nr < fs->super->s_first_data_block) ||
            (*block_nr >= ext2fs_blocks_count(fs->super)))
                return 0;
-       ext2fs_unmark_block_bitmap2(p->ctx->block_found_map, *block_nr);
        ext2fs_block_alloc_stats2(fs, *block_nr, -1);
        p->num++;
        return 0;
@@ -1214,8 +1213,6 @@ static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
                        return;
                }
                if (count == 0) {
-                       ext2fs_unmark_block_bitmap2(ctx->block_found_map,
-                                       ext2fs_file_acl_block(fs, &inode));
                        ext2fs_block_alloc_stats2(fs,
                                  ext2fs_file_acl_block(fs, &inode), -1);
                }
index 32c05b5..f9d4aae 100644 (file)
@@ -761,27 +761,6 @@ static int expand_dir_proc(ext2_filsys fs,
                return BLOCK_CHANGED;
 }
 
-/*
- * Ensure that all blocks are marked in the block_found_map, since it's
- * possible that the library allocated an extent node block or a block map
- * block during the directory rebuilding; these new allocations are not
- * captured in block_found_map.  This is bad since we could later use
- * block_found_map to allocate more blocks.
- */
-static int find_new_blocks_proc(ext2_filsys fs,
-                               blk64_t *blocknr,
-                               e2_blkcnt_t     blockcnt,
-                               blk64_t ref_block EXT2FS_ATTR((unused)),
-                               int ref_offset EXT2FS_ATTR((unused)),
-                               void    *priv_data)
-{
-       struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data;
-       e2fsck_t        ctx = es->ctx;
-
-       ext2fs_mark_block_bitmap2(ctx->block_found_map, *blocknr);
-       return 0;
-}
-
 errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
                                  int num, int guaranteed_size)
 {
@@ -811,27 +790,11 @@ errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
        es.newblocks = 0;
        es.ctx = ctx;
 
-       before = ext2fs_free_blocks_count(fs->super);
        retval = ext2fs_block_iterate3(fs, dir, BLOCK_FLAG_APPEND,
                                       0, expand_dir_proc, &es);
 
        if (es.err)
                return es.err;
-       after = ext2fs_free_blocks_count(fs->super);
-
-       /*
-        * If the free block count has dropped by more than the blocks we
-        * allocated ourselves, then we must've allocated some extent/map
-        * blocks.  Therefore, we must iterate this dir's blocks again to
-        * ensure that all newly allocated blocks are captured in
-        * block_found_map.
-        */
-       if ((before - after) > es.newblocks) {
-               retval = ext2fs_block_iterate3(fs, dir, BLOCK_FLAG_READ_ONLY,
-                                              0, find_new_blocks_proc, &es);
-               if (es.err)
-                       return es.err;
-       }
 
        /*
         * Update the size and block count fields in the inode.
index 3aafbb1..2769622 100644 (file)
@@ -654,8 +654,6 @@ static int write_dir_block(ext2_filsys fs,
                 * once.
                 */
                if (blk % EXT2FS_CLUSTER_RATIO(fs) == 0) {
-                       ext2fs_unmark_block_bitmap2(wd->ctx->block_found_map,
-                                                   blk);
                        ext2fs_block_alloc_stats2(fs, blk, -1);
                        wd->cleared++;
                }