From: David Anderson Date: Mon, 5 Mar 2018 20:52:13 +0000 (-0800) Subject: AOSP: e2fsck: Add an extended option for unsharing blocks. X-Git-Tag: v1.44.3-rc1~49 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=91327df4575d1ee4eb57e586943a10b20a41cec8;p=thirdparty%2Fe2fsprogs.git AOSP: e2fsck: Add an extended option for unsharing blocks. Add an -E unshare_blocks flag for unsharing blocks that were created for a filesystem with block sharing enabled. If the filesystem does not have this feature enabled, the flag has no effect. If the filesystem does not have free space, e2fsck will error. Signed-off-by: Theodore Ts'o Google-Bug-Id: 64109868 Test: f_unshare_blocks_no_space, f_unshare_blocks_ok Change-Id: I8821353e9e6200c6c0c71dd22f4f43d796fc720c From AOSP commit: 8ba190e3135d61501d3a694b6960c2fbee98e7a6 --- diff --git a/e2fsck/e2fsck.8.in b/e2fsck/e2fsck.8.in index 1a3bd4683..8b43c9c1d 100644 --- a/e2fsck/e2fsck.8.in +++ b/e2fsck/e2fsck.8.in @@ -266,6 +266,15 @@ Convert block-mapped files to extent-mapped files. Only fix damaged metadata; do not optimize htree directories or compress extent trees. This option is incompatible with the -D and -E bmap2extent options. +.TP +.BI unshare_blocks +If the filesystem has shared blocks, with the shared blocks read-only feature +enabled, then this will unshare all shared blocks and unset the read-only +feature bit. If there is not enough free space then the operation will fail. +If the filesystem does not have the read-only feature bit, but has shared +blocks anyway, then this option will have no effect. Note when using this +option, if there is no free space to clone blocks, there is no prompt to +delete files and instead the operation will fail. .RE .TP .B \-f diff --git a/e2fsck/e2fsck.h b/e2fsck/e2fsck.h index 5269650f7..d1ee367c7 100644 --- a/e2fsck/e2fsck.h +++ b/e2fsck/e2fsck.h @@ -172,6 +172,7 @@ struct resource_track { #define E2F_OPT_FIXES_ONLY 0x8000 /* skip all optimizations */ #define E2F_OPT_NOOPT_EXTENTS 0x10000 /* don't optimize extents */ #define E2F_OPT_ICOUNT_FULLMAP 0x20000 /* use an array for inode counts */ +#define E2F_OPT_UNSHARE_BLOCKS 0x40000 /* * E2fsck flags diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c index 35a05037c..c5149e5d7 100644 --- a/e2fsck/pass1.c +++ b/e2fsck/pass1.c @@ -2261,8 +2261,10 @@ static _INLINE_ void mark_block_used(e2fsck_t ctx, blk64_t block) clear_problem_context(&pctx); if (ext2fs_fast_test_block_bitmap2(ctx->block_found_map, block)) { - if (ext2fs_has_feature_shared_blocks(ctx->fs->super)) + if (ext2fs_has_feature_shared_blocks(ctx->fs->super) && + !(ctx->options & E2F_OPT_UNSHARE_BLOCKS)) { return; + } if (!ctx->block_dup_map) { pctx.errcode = e2fsck_allocate_block_bitmap(ctx->fs, _("multiply claimed block map"), diff --git a/e2fsck/pass1b.c b/e2fsck/pass1b.c index 392ff2c62..241669c59 100644 --- a/e2fsck/pass1b.c +++ b/e2fsck/pass1b.c @@ -245,6 +245,24 @@ void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf) pass1d(ctx, block_buf); print_resource_track(ctx, "Pass 1d", &rtrack, ctx->fs->io); + if (ext2fs_has_feature_shared_blocks(ctx->fs->super) && + (ctx->options & E2F_OPT_UNSHARE_BLOCKS)) { + /* + * If we successfully managed to unshare all blocks, unset the + * shared block feature. + */ + blk64_t next; + int result = ext2fs_find_first_set_block_bitmap2( + ctx->block_dup_map, + ctx->fs->super->s_first_data_block, + ext2fs_blocks_count(ctx->fs->super) - 1, + &next); + if (result == ENOENT) { + ext2fs_clear_feature_shared_blocks(ctx->fs->super); + ext2fs_mark_super_dirty(ctx->fs); + } + } + /* * Time to free all of the accumulated data structures that we * don't need anymore. @@ -582,14 +600,21 @@ static void pass1d(e2fsck_t ctx, char *block_buf) fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx); continue; } - if (fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) { + if ((ctx->options & E2F_OPT_UNSHARE_BLOCKS) || + fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) { pctx.errcode = clone_file(ctx, ino, p, block_buf); if (pctx.errcode) fix_problem(ctx, PR_1D_CLONE_ERROR, &pctx); else continue; } - if (fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx)) + /* + * Note: When unsharing blocks, we don't prompt to delete + * files. If the clone operation fails than the unshare + * operation should fail too. + */ + if (!(ctx->options & E2F_OPT_UNSHARE_BLOCKS) && + fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx)) delete_file(ctx, ino, p, block_buf); else ext2fs_unmark_valid(fs); @@ -820,6 +845,13 @@ static int clone_file_block(ext2_filsys fs, cs->errcode = retval; return BLOCK_ABORT; } + if (ext2fs_has_feature_shared_blocks(fs->super)) { + /* + * Update the block stats so we don't get a prompt to fix block + * counts in the final pass. + */ + ext2fs_block_alloc_stats2(fs, new_block, +1); + } cluster_alloc_ok: cs->alloc_block = new_block; diff --git a/e2fsck/unix.c b/e2fsck/unix.c index 55e21ea0a..b369c1ec0 100644 --- a/e2fsck/unix.c +++ b/e2fsck/unix.c @@ -740,6 +740,9 @@ static void parse_extended_opts(e2fsck_t ctx, const char *opts) } else if (strcmp(token, "fixes_only") == 0) { ctx->options |= E2F_OPT_FIXES_ONLY; continue; + } else if (strcmp(token, "unshare_blocks") == 0) { + ctx->options |= E2F_OPT_UNSHARE_BLOCKS; + continue; } else { fprintf(stderr, _("Unknown extended option: %s\n"), token); @@ -764,6 +767,7 @@ static void parse_extended_opts(e2fsck_t ctx, const char *opts) fputs("\tno_inode_count_fullmap\n", stderr); fputs(_("\treadahead_kb=\n"), stderr); fputs("\tbmap2extent\n", stderr); + fputs("\tunshare_blocks\n", stderr); fputs("\tfixes_only\n", stderr); fputc('\n', stderr); exit(1); diff --git a/tests/f_unshare_blocks_no_space/expect.1 b/tests/f_unshare_blocks_no_space/expect.1 new file mode 100644 index 000000000..b2f6ab183 --- /dev/null +++ b/tests/f_unshare_blocks_no_space/expect.1 @@ -0,0 +1,136 @@ +Pass 1: Checking inodes, blocks, and sizes + +Running additional passes to resolve blocks claimed by more than one inode... +Pass 1B: Rescanning for multiply-claimed blocks +Multiply-claimed block(s) in inode 24: 10 +Multiply-claimed block(s) in inode 25: 9 9 9--10 +Multiply-claimed block(s) in inode 26: 9 9 9--10 +Multiply-claimed block(s) in inode 27: 9 9 9--10 +Multiply-claimed block(s) in inode 28: 9 9 9--10 +Multiply-claimed block(s) in inode 29: 9 9 9--10 +Multiply-claimed block(s) in inode 30: 9 9 9--10 +Multiply-claimed block(s) in inode 31: 9 9 9--10 +Multiply-claimed block(s) in inode 32: 9 9 9--10 +Pass 1C: Scanning directories for inodes with multiply-claimed blocks +Pass 1D: Reconciling multiply-claimed blocks +(There are 9 inodes containing multiply-claimed blocks.) + +File /file4.txt (inode #24, mod time Mon Mar 5 20:30:04 2018) + has 1 multiply-claimed block(s), shared with 8 file(s): + /file18.txt (inode #32, mod time Mon Mar 5 20:30:04 2018) + /file6.txt (inode #31, mod time Mon Mar 5 20:30:04 2018) + /file12.txt (inode #30, mod time Mon Mar 5 20:30:04 2018) + /file3.txt (inode #29, mod time Mon Mar 5 20:30:04 2018) + /file9.txt (inode #28, mod time Mon Mar 5 20:30:04 2018) + /file8.txt (inode #27, mod time Mon Mar 5 20:30:04 2018) + /file15.txt (inode #26, mod time Mon Mar 5 20:30:04 2018) + /file20.txt (inode #25, mod time Mon Mar 5 20:30:04 2018) +clone_file: Could not allocate block in ext2 filesystem returned from clone_file_block +Couldn't clone file: Could not allocate block in ext2 filesystem +File /file20.txt (inode #25, mod time Mon Mar 5 20:30:04 2018) + has 4 multiply-claimed block(s), shared with 8 file(s): + /file18.txt (inode #32, mod time Mon Mar 5 20:30:04 2018) + /file6.txt (inode #31, mod time Mon Mar 5 20:30:04 2018) + /file12.txt (inode #30, mod time Mon Mar 5 20:30:04 2018) + /file3.txt (inode #29, mod time Mon Mar 5 20:30:04 2018) + /file9.txt (inode #28, mod time Mon Mar 5 20:30:04 2018) + /file8.txt (inode #27, mod time Mon Mar 5 20:30:04 2018) + /file15.txt (inode #26, mod time Mon Mar 5 20:30:04 2018) + /file4.txt (inode #24, mod time Mon Mar 5 20:30:04 2018) +clone_file: Could not allocate block in ext2 filesystem returned from clone_file_block +Couldn't clone file: Could not allocate block in ext2 filesystem +File /file15.txt (inode #26, mod time Mon Mar 5 20:30:04 2018) + has 4 multiply-claimed block(s), shared with 8 file(s): + /file18.txt (inode #32, mod time Mon Mar 5 20:30:04 2018) + /file6.txt (inode #31, mod time Mon Mar 5 20:30:04 2018) + /file12.txt (inode #30, mod time Mon Mar 5 20:30:04 2018) + /file3.txt (inode #29, mod time Mon Mar 5 20:30:04 2018) + /file9.txt (inode #28, mod time Mon Mar 5 20:30:04 2018) + /file8.txt (inode #27, mod time Mon Mar 5 20:30:04 2018) + /file20.txt (inode #25, mod time Mon Mar 5 20:30:04 2018) + /file4.txt (inode #24, mod time Mon Mar 5 20:30:04 2018) +clone_file: Could not allocate block in ext2 filesystem returned from clone_file_block +Couldn't clone file: Could not allocate block in ext2 filesystem +File /file8.txt (inode #27, mod time Mon Mar 5 20:30:04 2018) + has 4 multiply-claimed block(s), shared with 8 file(s): + /file18.txt (inode #32, mod time Mon Mar 5 20:30:04 2018) + /file6.txt (inode #31, mod time Mon Mar 5 20:30:04 2018) + /file12.txt (inode #30, mod time Mon Mar 5 20:30:04 2018) + /file3.txt (inode #29, mod time Mon Mar 5 20:30:04 2018) + /file9.txt (inode #28, mod time Mon Mar 5 20:30:04 2018) + /file15.txt (inode #26, mod time Mon Mar 5 20:30:04 2018) + /file20.txt (inode #25, mod time Mon Mar 5 20:30:04 2018) + /file4.txt (inode #24, mod time Mon Mar 5 20:30:04 2018) +clone_file: Could not allocate block in ext2 filesystem returned from clone_file_block +Couldn't clone file: Could not allocate block in ext2 filesystem +File /file9.txt (inode #28, mod time Mon Mar 5 20:30:04 2018) + has 4 multiply-claimed block(s), shared with 8 file(s): + /file18.txt (inode #32, mod time Mon Mar 5 20:30:04 2018) + /file6.txt (inode #31, mod time Mon Mar 5 20:30:04 2018) + /file12.txt (inode #30, mod time Mon Mar 5 20:30:04 2018) + /file3.txt (inode #29, mod time Mon Mar 5 20:30:04 2018) + /file8.txt (inode #27, mod time Mon Mar 5 20:30:04 2018) + /file15.txt (inode #26, mod time Mon Mar 5 20:30:04 2018) + /file20.txt (inode #25, mod time Mon Mar 5 20:30:04 2018) + /file4.txt (inode #24, mod time Mon Mar 5 20:30:04 2018) +clone_file: Could not allocate block in ext2 filesystem returned from clone_file_block +Couldn't clone file: Could not allocate block in ext2 filesystem +File /file3.txt (inode #29, mod time Mon Mar 5 20:30:04 2018) + has 4 multiply-claimed block(s), shared with 8 file(s): + /file18.txt (inode #32, mod time Mon Mar 5 20:30:04 2018) + /file6.txt (inode #31, mod time Mon Mar 5 20:30:04 2018) + /file12.txt (inode #30, mod time Mon Mar 5 20:30:04 2018) + /file9.txt (inode #28, mod time Mon Mar 5 20:30:04 2018) + /file8.txt (inode #27, mod time Mon Mar 5 20:30:04 2018) + /file15.txt (inode #26, mod time Mon Mar 5 20:30:04 2018) + /file20.txt (inode #25, mod time Mon Mar 5 20:30:04 2018) + /file4.txt (inode #24, mod time Mon Mar 5 20:30:04 2018) +clone_file: Could not allocate block in ext2 filesystem returned from clone_file_block +Couldn't clone file: Could not allocate block in ext2 filesystem +File /file12.txt (inode #30, mod time Mon Mar 5 20:30:04 2018) + has 4 multiply-claimed block(s), shared with 8 file(s): + /file18.txt (inode #32, mod time Mon Mar 5 20:30:04 2018) + /file6.txt (inode #31, mod time Mon Mar 5 20:30:04 2018) + /file3.txt (inode #29, mod time Mon Mar 5 20:30:04 2018) + /file9.txt (inode #28, mod time Mon Mar 5 20:30:04 2018) + /file8.txt (inode #27, mod time Mon Mar 5 20:30:04 2018) + /file15.txt (inode #26, mod time Mon Mar 5 20:30:04 2018) + /file20.txt (inode #25, mod time Mon Mar 5 20:30:04 2018) + /file4.txt (inode #24, mod time Mon Mar 5 20:30:04 2018) +clone_file: Could not allocate block in ext2 filesystem returned from clone_file_block +Couldn't clone file: Could not allocate block in ext2 filesystem +File /file6.txt (inode #31, mod time Mon Mar 5 20:30:04 2018) + has 4 multiply-claimed block(s), shared with 8 file(s): + /file18.txt (inode #32, mod time Mon Mar 5 20:30:04 2018) + /file12.txt (inode #30, mod time Mon Mar 5 20:30:04 2018) + /file3.txt (inode #29, mod time Mon Mar 5 20:30:04 2018) + /file9.txt (inode #28, mod time Mon Mar 5 20:30:04 2018) + /file8.txt (inode #27, mod time Mon Mar 5 20:30:04 2018) + /file15.txt (inode #26, mod time Mon Mar 5 20:30:04 2018) + /file20.txt (inode #25, mod time Mon Mar 5 20:30:04 2018) + /file4.txt (inode #24, mod time Mon Mar 5 20:30:04 2018) +clone_file: Could not allocate block in ext2 filesystem returned from clone_file_block +Couldn't clone file: Could not allocate block in ext2 filesystem +File /file18.txt (inode #32, mod time Mon Mar 5 20:30:04 2018) + has 4 multiply-claimed block(s), shared with 8 file(s): + /file6.txt (inode #31, mod time Mon Mar 5 20:30:04 2018) + /file12.txt (inode #30, mod time Mon Mar 5 20:30:04 2018) + /file3.txt (inode #29, mod time Mon Mar 5 20:30:04 2018) + /file9.txt (inode #28, mod time Mon Mar 5 20:30:04 2018) + /file8.txt (inode #27, mod time Mon Mar 5 20:30:04 2018) + /file15.txt (inode #26, mod time Mon Mar 5 20:30:04 2018) + /file20.txt (inode #25, mod time Mon Mar 5 20:30:04 2018) + /file4.txt (inode #24, mod time Mon Mar 5 20:30:04 2018) +clone_file: Could not allocate block in ext2 filesystem returned from clone_file_block +Couldn't clone file: Could not allocate block in ext2 filesystem +Pass 2: Checking directory structure +Pass 3: Checking directory connectivity +Pass 4: Checking reference counts +Pass 5: Checking group summary information + +test_filesys: ***** FILE SYSTEM WAS MODIFIED ***** + +test_filesys: ********** WARNING: Filesystem still has errors ********** + +test_filesys: 32/32 files (34.4% non-contiguous), 64/64 blocks +Exit status is 4 diff --git a/tests/f_unshare_blocks_no_space/expect.2 b/tests/f_unshare_blocks_no_space/expect.2 new file mode 100644 index 000000000..8137dc7d6 --- /dev/null +++ b/tests/f_unshare_blocks_no_space/expect.2 @@ -0,0 +1,7 @@ +Pass 1: Checking inodes, blocks, and sizes +Pass 2: Checking directory structure +Pass 3: Checking directory connectivity +Pass 4: Checking reference counts +Pass 5: Checking group summary information +test_filesys: 32/32 files (34.4% non-contiguous), 64/64 blocks +Exit status is 1 diff --git a/tests/f_unshare_blocks_no_space/image.gz b/tests/f_unshare_blocks_no_space/image.gz new file mode 100644 index 000000000..8fff6d4b4 Binary files /dev/null and b/tests/f_unshare_blocks_no_space/image.gz differ diff --git a/tests/f_unshare_blocks_no_space/name b/tests/f_unshare_blocks_no_space/name new file mode 100644 index 000000000..ca323a68a --- /dev/null +++ b/tests/f_unshare_blocks_no_space/name @@ -0,0 +1 @@ +unshare blocks should fail with no free space diff --git a/tests/f_unshare_blocks_no_space/script b/tests/f_unshare_blocks_no_space/script new file mode 100644 index 000000000..bc44354ff --- /dev/null +++ b/tests/f_unshare_blocks_no_space/script @@ -0,0 +1,2 @@ +FSCK_OPT="-yf -E unshare_blocks" +. $cmd_dir/run_e2fsck diff --git a/tests/f_unshare_blocks_ok/expect.1 b/tests/f_unshare_blocks_ok/expect.1 new file mode 100644 index 000000000..e0ea7646d --- /dev/null +++ b/tests/f_unshare_blocks_ok/expect.1 @@ -0,0 +1,26 @@ +Pass 1: Checking inodes, blocks, and sizes + +Running additional passes to resolve blocks claimed by more than one inode... +Pass 1B: Rescanning for multiply-claimed blocks +Multiply-claimed block(s) in inode 12: 9 +Multiply-claimed block(s) in inode 13: 9 +Pass 1C: Scanning directories for inodes with multiply-claimed blocks +Pass 1D: Reconciling multiply-claimed blocks +(There are 2 inodes containing multiply-claimed blocks.) + +File /file2.txt (inode #12, mod time Sat Mar 3 02:12:33 2018) + has 1 multiply-claimed block(s), shared with 1 file(s): + /file1.txt (inode #13, mod time Sat Mar 3 02:12:15 2018) +File /file1.txt (inode #13, mod time Sat Mar 3 02:12:15 2018) + has 1 multiply-claimed block(s), shared with 1 file(s): + /file2.txt (inode #12, mod time Sat Mar 3 02:12:33 2018) +Multiply-claimed blocks already reassigned or cloned. + +Pass 2: Checking directory structure +Pass 3: Checking directory connectivity +Pass 4: Checking reference counts +Pass 5: Checking group summary information + +test_filesys: ***** FILE SYSTEM WAS MODIFIED ***** +test_filesys: 13/32 files (0.0% non-contiguous), 13/64 blocks +Exit status is 0 diff --git a/tests/f_unshare_blocks_ok/expect.2 b/tests/f_unshare_blocks_ok/expect.2 new file mode 100644 index 000000000..b2153829d --- /dev/null +++ b/tests/f_unshare_blocks_ok/expect.2 @@ -0,0 +1,7 @@ +Pass 1: Checking inodes, blocks, and sizes +Pass 2: Checking directory structure +Pass 3: Checking directory connectivity +Pass 4: Checking reference counts +Pass 5: Checking group summary information +test_filesys: 13/32 files (0.0% non-contiguous), 13/64 blocks +Exit status is 0 diff --git a/tests/f_unshare_blocks_ok/image.gz b/tests/f_unshare_blocks_ok/image.gz new file mode 100644 index 000000000..db747e271 Binary files /dev/null and b/tests/f_unshare_blocks_ok/image.gz differ diff --git a/tests/f_unshare_blocks_ok/name b/tests/f_unshare_blocks_ok/name new file mode 100644 index 000000000..e051a62ad --- /dev/null +++ b/tests/f_unshare_blocks_ok/name @@ -0,0 +1 @@ +unshare blocks successfully diff --git a/tests/f_unshare_blocks_ok/script b/tests/f_unshare_blocks_ok/script new file mode 100644 index 000000000..bc44354ff --- /dev/null +++ b/tests/f_unshare_blocks_ok/script @@ -0,0 +1,2 @@ +FSCK_OPT="-yf -E unshare_blocks" +. $cmd_dir/run_e2fsck