Whamcloud - gitweb
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 8b43c9c..da9f618 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 241669c..5693b9c 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 b369c1e..e604f42 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))) {