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 <tytso@mit.edu>

Google-Bug-Id: 64109868
Test: f_unshare_blocks_no_space, f_unshare_blocks_ok
Change-Id: I8821353e9e6200c6c0c71dd22f4f43d796fc720c
From AOSP commit: 8ba190e3135d61501d3a694b6960c2fbee98e7a6
This commit is contained in:
David Anderson 2018-03-05 12:52:13 -08:00 committed by Theodore Ts'o
parent 9c5413b1ae
commit 91327df457
15 changed files with 233 additions and 3 deletions

View File

@ -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

View File

@ -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

View File

@ -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"),

View File

@ -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;

View File

@ -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=<buffer size>\n"), stderr);
fputs("\tbmap2extent\n", stderr);
fputs("\tunshare_blocks\n", stderr);
fputs("\tfixes_only\n", stderr);
fputc('\n', stderr);
exit(1);

View File

@ -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

View File

@ -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

Binary file not shown.

View File

@ -0,0 +1 @@
unshare blocks should fail with no free space

View File

@ -0,0 +1,2 @@
FSCK_OPT="-yf -E unshare_blocks"
. $cmd_dir/run_e2fsck

View File

@ -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

View File

@ -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

Binary file not shown.

View File

@ -0,0 +1 @@
unshare blocks successfully

View File

@ -0,0 +1,2 @@
FSCK_OPT="-yf -E unshare_blocks"
. $cmd_dir/run_e2fsck