]> git.ipfire.org Git - thirdparty/e2fsprogs.git/commitdiff
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 998abdc113c63ee438d73ae6cf3c6af91c6c2d0b..cee74a35c9755629ae9026960584e9999456195c 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 784195a004a029ff9cbfb29b5fa3f5a8c987f686..7a887de14ba2362f03919beb2d753bc75ccaca61 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 b4cc5321bb4f5d1da5acc93e564937a2c86534ad..9b38977a16b19e1cedc4c381819fa8e9f869096c 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 7277a7b3f3c5f62c8dcae4e488ac4913b5de479a..517adaa972b4f6ff165f379818ed5835bc2af183 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 32c05b5b7c3fcf4d86bb0696319e7d45d4c963de..f9d4aae367ef98a01010b7bc3720591f04c83003 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 3aafbb12833ba5aca5848443014202e69d4a69e1..2769622458883289b1237bef8bade427bff3909c 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++;
                }