]> git.ipfire.org Git - thirdparty/e2fsprogs.git/commitdiff
AOSP: e2fsck: allow read-only testing if -E unshare_blocks will succeed
authorDavid Anderson <dvander@google.com>
Fri, 27 Apr 2018 23:10:29 +0000 (16:10 -0700)
committerTheodore Ts'o <tytso@mit.edu>
Thu, 21 Jun 2018 14:11:40 +0000 (10:11 -0400)
If -E unshare_blocks is used with -n, it will normally fail since the
filesystem is read-only. For Android's "adb remount" it is more useful
to report whether or not the unshare operation would succeed, were the
filesystem writable. We do that here by ignoring certain write
operations if -E unshare_blocks is specified with -n. It is not perfect,
since the actual unshare operation could still fail (for example if
new extents need to consume additional blocks).

Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Google-Bug-Id: 64109868
Test: e2fsck -f -n -E unshare_blocks on deduplicated image
Change-Id: Ia50ceb7b3745fdf8766cff06c697818f07411635
From AOSP commit: 9e76dc0f65d8a8dec27f57b9020e81cbbbe12faf

e2fsck/e2fsck.8.in
e2fsck/pass1b.c
e2fsck/unix.c

index 8b43c9c1dab375856748c0a380c47d7373434eee..da9f61852752727548dc8df930baa6bd2d98616e 100644 (file)
@@ -275,6 +275,11 @@ 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.
+.IP
+Note that unshare_blocks requires the "-f" option to ensure that all passes
+are run. Additionally, if "-n" is also specified, e2fsck will simulate trying
+to allocate enough space to deduplicate. If this fails, the exit code will
+be non-zero.
 .RE
 .TP
 .B \-f
index 241669c59f9c145e1ea1591b13cead8bd3424937..5693b9cfcc5afbd749b7ac102d2cd87f7e4ae86b 100644 (file)
@@ -257,7 +257,7 @@ void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf)
                        ctx->fs->super->s_first_data_block,
                        ext2fs_blocks_count(ctx->fs->super) - 1,
                        &next);
-               if (result == ENOENT) {
+               if (result == ENOENT && !(ctx->options & E2F_OPT_NO)) {
                        ext2fs_clear_feature_shared_blocks(ctx->fs->super);
                        ext2fs_mark_super_dirty(ctx->fs);
                }
@@ -796,6 +796,7 @@ static int clone_file_block(ext2_filsys fs,
        e2fsck_t ctx;
        blk64_t c;
        int is_meta = 0;
+       int should_write = 1;
 
        ctx = cs->ctx;
        deferred_dec_badcount(cs);
@@ -803,6 +804,11 @@ static int clone_file_block(ext2_filsys fs,
        if (*block_nr == 0)
                return 0;
 
+       if (ext2fs_has_feature_shared_blocks(ctx->fs->super) &&
+           (ctx->options & E2F_OPT_UNSHARE_BLOCKS) &&
+           (ctx->options & E2F_OPT_NO))
+               should_write = 0;
+
        c = EXT2FS_B2C(fs, blockcnt);
        if (check_if_fs_cluster(ctx, EXT2FS_B2C(fs, *block_nr)))
                is_meta = 1;
@@ -875,16 +881,25 @@ cluster_alloc_ok:
                        cs->errcode = retval;
                        return BLOCK_ABORT;
                }
-               retval = io_channel_write_blk64(fs->io, new_block, 1, cs->buf);
-               if (retval) {
-                       cs->errcode = retval;
-                       return BLOCK_ABORT;
+               if (should_write) {
+                       retval = io_channel_write_blk64(fs->io, new_block, 1, cs->buf);
+                       if (retval) {
+                               cs->errcode = retval;
+                               return BLOCK_ABORT;
+                       }
                }
                cs->save_dup_cluster = (is_meta ? NULL : p);
                cs->save_blocknr = *block_nr;
                *block_nr = new_block;
                ext2fs_mark_block_bitmap2(ctx->block_found_map, new_block);
                ext2fs_mark_block_bitmap2(fs->block_map, new_block);
+
+               if (!should_write) {
+                       /* Don't try to change extent information; we want e2fsck to
+                        * return success.
+                        */
+                       return 0;
+               }
                return BLOCK_CHANGED;
        }
        return 0;
index b369c1ec0f0285e6eaa79a5c8afbaabe8d34415b..e604f4253481f9fb42a9275754307706d7453f62 100644 (file)
@@ -1948,6 +1948,14 @@ no_journal:
                ext2fs_mark_super_dirty(fs);
        }
 
+       if (ext2fs_has_feature_shared_blocks(ctx->fs->super) &&
+           (ctx->options & E2F_OPT_UNSHARE_BLOCKS) &&
+           (ctx->options & E2F_OPT_NO))
+               /* Don't try to write or flush I/O, we just wanted to know whether or
+                * not there were enough free blocks to undo deduplication.
+                */
+               goto skip_write;
+
        if (!(ctx->options & E2F_OPT_READONLY)) {
                e2fsck_write_bitmaps(ctx);
                if (fs->flags & EXT2_FLAG_DIRTY) {
@@ -1984,6 +1992,8 @@ no_journal:
                        exit_value |= FSCK_REBOOT;
                }
        }
+
+skip_write:
        if (!ext2fs_test_valid(fs) ||
            ((exit_value & FSCK_CANCELED) &&
             (sb->s_state & EXT2_ERROR_FS))) {