From 91327df4575d1ee4eb57e586943a10b20a41cec8 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Mon, 5 Mar 2018 12:52:13 -0800 Subject: [PATCH] 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 --- e2fsck/e2fsck.8.in | 9 ++ e2fsck/e2fsck.h | 1 + e2fsck/pass1.c | 4 +- e2fsck/pass1b.c | 36 +++++++- e2fsck/unix.c | 4 + tests/f_unshare_blocks_no_space/expect.1 | 136 +++++++++++++++++++++++++++++++ tests/f_unshare_blocks_no_space/expect.2 | 7 ++ tests/f_unshare_blocks_no_space/image.gz | Bin 0 -> 1490 bytes tests/f_unshare_blocks_no_space/name | 1 + tests/f_unshare_blocks_no_space/script | 2 + tests/f_unshare_blocks_ok/expect.1 | 26 ++++++ tests/f_unshare_blocks_ok/expect.2 | 7 ++ tests/f_unshare_blocks_ok/image.gz | Bin 0 -> 831 bytes tests/f_unshare_blocks_ok/name | 1 + tests/f_unshare_blocks_ok/script | 2 + 15 files changed, 233 insertions(+), 3 deletions(-) create mode 100644 tests/f_unshare_blocks_no_space/expect.1 create mode 100644 tests/f_unshare_blocks_no_space/expect.2 create mode 100644 tests/f_unshare_blocks_no_space/image.gz create mode 100644 tests/f_unshare_blocks_no_space/name create mode 100644 tests/f_unshare_blocks_no_space/script create mode 100644 tests/f_unshare_blocks_ok/expect.1 create mode 100644 tests/f_unshare_blocks_ok/expect.2 create mode 100644 tests/f_unshare_blocks_ok/image.gz create mode 100644 tests/f_unshare_blocks_ok/name create mode 100644 tests/f_unshare_blocks_ok/script diff --git a/e2fsck/e2fsck.8.in b/e2fsck/e2fsck.8.in index 1a3bd46..8b43c9c 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 5269650..d1ee367 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 35a0503..c5149e5 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 392ff2c..241669c 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 55e21ea..b369c1e 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 0000000..b2f6ab1 --- /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 0000000..8137dc7 --- /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 0000000000000000000000000000000000000000..8fff6d4b478c5244cbbf603941f78d6eef9c2c3b GIT binary patch literal 1490 zcmdUtZA@Bc6vs{6CYedqWNp^9R$cI=v52k7Y$b}Rv(8$?CVdm8#HI5Ee4AZ$QVZ#< zX&W_eR;9aCN!3LiDpjZG3|y7CszuSNI1oXLf{4m20$#arXUX=#E%U>^?f>C9IXS=c z&pA(yS1AfL*iuV!a?Z#~N&C`iLqUFc<@WJ`Eu<{2mz7VLBU9sRDwBFvOPbYd@_EwOaFy1~W))SAzu;DD0% ztt5uLj?#veMO@6jDSG36Xu-BH<*)2B6#VEVM4(A=TTqkUd!o$?Q9n9(ng8OTx)sGGGT@&lAyH+eeS!)ZO;Xw!q~6PsnU{9%f7$ z^f2|*MB1e?>5*mH(fbE0fQpUl86&A^luqNPcocl^kIi z+A+VWt@B9YW5G>vI)-^;sCDn%8H(Q8SaI84U(JJp+?am-ybw_F$j32vv@dT3RP^NK zw1vZv3E?Nn^i0QM+bZl`8)BZeco8MY%vF=}v$uR>*X7+^=J>I${3fly&T?#i&bUi) z)HGOz4eMwI`f*aX>;Q3eMe?iWCX%eD-RO->G70uMXtK}O`g@SP;5aZJ0Ms`Zj3Zoq7&31X)1lZILBDx77G{iOU` iVIQ@ZXi}f6k^QIpkBrOzUm$E1=EU@Z!80W>v0syWVnjr;qLAjz6HRN6?R*~_e|h#1)8fjy{rCRQEk0lS z{NMYxcm2NasjgOJ_`lk#XPtzu;k08f&fM~jY&lpJvgsSAuwF^Kfz6(mwL+8DpDy(b z^Ex0ijTug}NFf2c?Z z`@i+Nr_HBrIkEXaZx{aY^laW%lrzUt?BoOSJM&DxEO=4Nz;G9?$u z)ybWWbK=fwoBf})^yoADpBrxc>CSI8s89-fS7vJQf6|*XziX9$t1D02-T&NY!sUqv zlRoqFip;Kmbmhm@<&XWt7k^wXqP2C?#~;Dxl=}bWD#qAuEY6krcWCE~@7_yZ`<1KN p%l=n;ex^R_!SO%oNiy=s|AfzbatD{AX)9j8_PmhzN}wGq3;