2011-10-23 09:10:52

by Yongqiang Yang

[permalink] [raw]
Subject: e2fsprogs: add exclude bitmap support in e2fsprogs


Hi,

Exclude bitmap(also known as snapshot bitmap) feature is needed
by ext4 snapshot. This patch series add exlcude bitmap in e2fsprogs
except resize. Kernel-side patches for resize which can support
exclude bitmap and bigalloc are still waiting for merging.


Yongqiang.


2011-10-23 09:10:59

by Yongqiang Yang

[permalink] [raw]
Subject: [PATCH 3/8] e2fsprogs: check the exclude bitmap

From: Amir Goldstein <[email protected]>

Excluding snapshot blocks from COW is done by setting their bit in
the exclude bitmap. There is one exclude bitmap block per block group.
Fsck checks that all (and only) snapshot file blocks are excluded.

Signed-off-by: Amir Goldstein <[email protected]>
Signed-off-by: Yongqiang Yang <[email protected]>
---
e2fsck/e2fsck.h | 1 +
e2fsck/pass1.c | 17 ++++++-
e2fsck/pass5.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
e2fsck/problem.c | 31 ++++++++++++
e2fsck/problem.h | 19 +++++++
5 files changed, 211 insertions(+), 1 deletions(-)

diff --git a/e2fsck/e2fsck.h b/e2fsck/e2fsck.h
index d225d89..44909c3 100644
--- a/e2fsck/e2fsck.h
+++ b/e2fsck/e2fsck.h
@@ -241,6 +241,7 @@ struct e2fsck_struct {
ext2fs_inode_bitmap inode_reg_map; /* Inodes which are regular files*/

ext2fs_block_bitmap block_found_map; /* Blocks which are in use */
+ ext2fs_block_bitmap block_excluded_map; /* Blocks which are excluded */
ext2fs_block_bitmap block_dup_map; /* Blks referenced more than once */
ext2fs_block_bitmap block_ea_map; /* Blocks which are used by EA's */

diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c
index f45831f..3587dff 100644
--- a/e2fsck/pass1.c
+++ b/e2fsck/pass1.c
@@ -80,7 +80,7 @@ static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
struct process_block_struct {
ext2_ino_t ino;
unsigned is_dir:1, is_reg:1, clear:1, suppress:1,
- fragmented:1, compressed:1, bbcheck:1;
+ fragmented:1, compressed:1, bbcheck:1, snapfile:1;
blk64_t num_blocks;
blk64_t max_blocks;
e2_blkcnt_t last_block;
@@ -627,6 +627,16 @@ void e2fsck_pass1(e2fsck_t ctx)
ctx->flags |= E2F_FLAG_ABORT;
return;
}
+ if (sb->s_feature_compat & EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP)
+ pctx.errcode = ext2fs_allocate_block_bitmap(fs,
+ _("excluded block map"),
+ &ctx->block_excluded_map);
+ if (pctx.errcode) {
+ pctx.num = 1;
+ fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
+ ctx->flags |= E2F_FLAG_ABORT;
+ return;
+ }
e2fsck_setup_tdb_icount(ctx, 0, &ctx->inode_link_info);
if (!ctx->inode_link_info)
pctx.errcode = ext2fs_create_icount2(fs, 0, 0, 0,
@@ -1940,6 +1950,7 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
pb.previous_block = 0;
pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
pb.is_reg = LINUX_S_ISREG(inode->i_mode);
+ pb.snapfile = (pb.is_reg && (inode->i_flags & EXT4_SNAPFILE_FL));
pb.max_blocks = 1 << (31 - fs->super->s_log_block_size);
pb.inode = inode;
pb.pctx = pctx;
@@ -2296,6 +2307,10 @@ static int process_block(ext2_filsys fs,
(blk & EXT2FS_CLUSTER_MASK(ctx->fs)) ==
(blockcnt & EXT2FS_CLUSTER_MASK(ctx->fs)))) {
mark_block_used(ctx, blk);
+ /* mark snapshot file blocks excluded */
+ if (p->snapfile && ctx->block_excluded_map)
+ ext2fs_fast_mark_block_bitmap2(ctx->block_excluded_map,
+ blk);
p->num_blocks++;
}
if (blockcnt >= 0)
diff --git a/e2fsck/pass5.c b/e2fsck/pass5.c
index a60e84a..0dda1b3 100644
--- a/e2fsck/pass5.c
+++ b/e2fsck/pass5.c
@@ -24,6 +24,7 @@
#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))

static void check_block_bitmaps(e2fsck_t ctx);
+static void check_exclude_bitmaps(e2fsck_t ctx);
static void check_inode_bitmaps(e2fsck_t ctx);
static void check_inode_end(e2fsck_t ctx);
static void check_block_end(e2fsck_t ctx);
@@ -54,6 +55,9 @@ void e2fsck_pass5(e2fsck_t ctx)
check_block_bitmaps(ctx);
if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
return;
+ check_exclude_bitmaps(ctx);
+ if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+ return;
check_inode_bitmaps(ctx);
if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
return;
@@ -70,6 +74,9 @@ void e2fsck_pass5(e2fsck_t ctx)
ctx->inode_dir_map = 0;
ext2fs_free_block_bitmap(ctx->block_found_map);
ctx->block_found_map = 0;
+ if (ctx->block_excluded_map)
+ ext2fs_free_block_bitmap(ctx->block_excluded_map);
+ ctx->block_excluded_map = 0;

print_resource_track(ctx, _("Pass 5"), &rtrack, ctx->fs->io);
}
@@ -112,6 +119,18 @@ static void print_bitmap_problem(e2fsck_t ctx, int problem,
else
problem = PR_5_BLOCK_RANGE_USED;
break;
+ case PR_5_BLOCK_NOTEXCLUDED:
+ if (pctx->blk == pctx->blk2)
+ pctx->blk2 = 0;
+ else
+ problem = PR_5_BLOCK_RANGE_NOTEXCLUDED;
+ break;
+ case PR_5_BLOCK_EXCLUDED:
+ if (pctx->blk == pctx->blk2)
+ pctx->blk2 = 0;
+ else
+ problem = PR_5_BLOCK_RANGE_EXCLUDED;
+ break;
case PR_5_INODE_UNUSED:
if (pctx->ino == pctx->ino2)
pctx->ino2 = 0;
@@ -416,6 +435,131 @@ errout:
ext2fs_free_mem(&free_array);
}

+static void check_exclude_bitmaps(e2fsck_t ctx)
+{
+ ext2_filsys fs = ctx->fs;
+ blk64_t i;
+ int group = 0;
+ int blocks = 0;
+ int actual, bitmap;
+ struct problem_context pctx;
+ int problem, save_problem, fixit, had_problem;
+ errcode_t retval;
+ int csum_flag;
+ int skip_group = 0;
+
+ clear_problem_context(&pctx);
+
+ if (!(fs->super->s_feature_compat &
+ EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP))
+ return;
+
+ csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
+redo_counts:
+ had_problem = 0;
+ save_problem = 0;
+ pctx.blk = pctx.blk2 = NO_BLK;
+ if (csum_flag &&
+ (ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT)))
+ skip_group++;
+ for (i = fs->super->s_first_data_block;
+ i < ext2fs_blocks_count(fs->super);
+ i++) {
+ actual = ext2fs_fast_test_block_bitmap2(ctx->block_excluded_map, i);
+
+ if (skip_group) {
+ bitmap = 0;
+ actual = (actual != 0);
+ } else
+ bitmap = ext2fs_fast_test_block_bitmap2(fs->exclude_map, i);
+
+ if (actual == bitmap)
+ goto do_counts;
+
+ if (!actual && bitmap) {
+ /*
+ * Block not excluded, but marked in exclude bitmap.
+ */
+ problem = PR_5_BLOCK_NOTEXCLUDED;
+ } else {
+ /*
+ * Block excluded, but not marked in exclude bitmap.
+ */
+ problem = PR_5_BLOCK_EXCLUDED;
+
+ if (skip_group) {
+ struct problem_context pctx2;
+ pctx2.blk = i;
+ pctx2.group = group;
+ if (fix_problem(ctx, PR_5_BLOCK_UNINIT,&pctx2)){
+ ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT);
+ skip_group = 0;
+ }
+ }
+ }
+ if (pctx.blk == NO_BLK) {
+ pctx.blk = pctx.blk2 = i;
+ save_problem = problem;
+ } else {
+ if ((problem == save_problem) &&
+ (pctx.blk2 == i-1))
+ pctx.blk2++;
+ else {
+ print_bitmap_problem(ctx, save_problem, &pctx);
+ pctx.blk = pctx.blk2 = i;
+ save_problem = problem;
+ }
+ }
+ ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
+ had_problem++;
+
+ do_counts:
+ blocks ++;
+ if ((blocks == fs->super->s_blocks_per_group) ||
+ (i == fs->super->s_blocks_count-1)) {
+ group ++;
+ blocks = 0;
+ skip_group = 0;
+ if (ctx->progress)
+ if ((ctx->progress)(ctx, 5, group,
+ fs->group_desc_count*2))
+ return;
+ if (csum_flag &&
+ (i != ext2fs_blocks_count(fs->super)-1) &&
+ ext2fs_bg_flags_test(fs, group,
+ EXT2_BG_BLOCK_UNINIT))
+ skip_group++;
+ }
+ }
+ if (pctx.blk != NO_BLK)
+ print_bitmap_problem(ctx, save_problem, &pctx);
+ if (had_problem)
+ fixit = end_problem_latch(ctx, PR_LATCH_XBITMAP);
+ else
+ fixit = -1;
+ ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
+
+ if (fixit == 1) {
+ ext2fs_free_block_bitmap(fs->exclude_map);
+ retval = ext2fs_copy_bitmap(ctx->block_excluded_map,
+ &fs->exclude_map);
+ if (retval) {
+ clear_problem_context(&pctx);
+ fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
+ ctx->flags |= E2F_FLAG_ABORT;
+ return;
+ }
+ ext2fs_mark_eb_dirty(fs);
+ /* clear fix_exclude flag */
+ if (fs->super->s_flags & EXT2_FLAGS_FIX_EXCLUDE) {
+ fs->super->s_flags &= ~EXT2_FLAGS_FIX_EXCLUDE;
+ ext2fs_mark_super_dirty(fs);
+ }
+ } else if (fixit == 0)
+ ext2fs_unmark_valid(fs);
+}
+
static void check_inode_bitmaps(e2fsck_t ctx)
{
ext2_filsys fs = ctx->fs;
diff --git a/e2fsck/problem.c b/e2fsck/problem.c
index cf4a270..ad703c7 100644
--- a/e2fsck/problem.c
+++ b/e2fsck/problem.c
@@ -1578,6 +1578,26 @@ static struct e2fsck_problem problem_table[] = {
"\n",
PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },

+ /* Exclude bitmap differences header */
+ { PR_5_EXCLUDE_BITMAP_HEADER,
+ N_("Exclude @B differences: "),
+ PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG},
+
+ /* Block not excluded, but marked in exclude bitmap */
+ { PR_5_BLOCK_NOTEXCLUDED,
+ " -%b",
+ PROMPT_NONE, PR_LATCH_XBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
+
+ /* Block excluded, but not marked in exclude bitmap */
+ { PR_5_BLOCK_EXCLUDED,
+ " +%b",
+ PROMPT_NONE, PR_LATCH_XBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
+
+ /* Exclude bitmap differences end */
+ { PR_5_EXCLUDE_BITMAP_END,
+ "\n",
+ PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
+
/* Inode bitmap differences header */
{ PR_5_INODE_BITMAP_HEADER,
N_("@i @B differences: "),
@@ -1654,6 +1674,16 @@ static struct e2fsck_problem problem_table[] = {
" +(%b--%c)",
PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },

+ /* Block range not excluded, but marked in exclude bitmap */
+ { PR_5_BLOCK_RANGE_NOTEXCLUDED,
+ " -(%b--%c)",
+ PROMPT_NONE, PR_LATCH_XBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
+
+ /* Block range excluded, but not marked in exclude bitmap */
+ { PR_5_BLOCK_RANGE_EXCLUDED,
+ " +(%b--%c)",
+ PROMPT_NONE, PR_LATCH_XBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
+
/* Inode range not used, but marked in bitmap */
{ PR_5_INODE_RANGE_UNUSED,
" -(%i--%j)",
@@ -1695,6 +1725,7 @@ static struct latch_descr pr_latch_info[] = {
{ PR_LATCH_BBLOCK, PR_1_INODE_BBLOCK_LATCH, 0 },
{ PR_LATCH_IBITMAP, PR_5_INODE_BITMAP_HEADER, PR_5_INODE_BITMAP_END },
{ PR_LATCH_BBITMAP, PR_5_BLOCK_BITMAP_HEADER, PR_5_BLOCK_BITMAP_END },
+ { PR_LATCH_XBITMAP, PR_5_EXCLUDE_BITMAP_HEADER, PR_5_EXCLUDE_BITMAP_END },
{ PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 },
{ PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END },
{ PR_LATCH_LOW_DTIME, PR_1_ORPHAN_LIST_REFUGEES, 0 },
diff --git a/e2fsck/problem.h b/e2fsck/problem.h
index 17b0c10..3647f6e 100644
--- a/e2fsck/problem.h
+++ b/e2fsck/problem.h
@@ -39,6 +39,7 @@ struct problem_context {
#define PR_LATCH_TOOBIG 0x0080 /* Latch for file to big errors */
#define PR_LATCH_OPTIMIZE_DIR 0x0090 /* Latch for optimize directories */
#define PR_LATCH_BG_CHECKSUM 0x00A0 /* Latch for block group checksums */
+#define PR_LATCH_XBITMAP 0x00B0 /* Latch for pass 5 exclude bitmap proc. */

#define PR_LATCH(x) ((((x) & PR_LATCH_MASK) >> 4) - 1)

@@ -1010,6 +1011,24 @@ struct problem_context {
/* Inode in use but group is marked INODE_UNINIT */
#define PR_5_INODE_UNINIT 0x050019

+/* Exclude bitmap differences header */
+#define PR_5_EXCLUDE_BITMAP_HEADER 0x050100
+
+/* Block not excluded, but marked in exclude bitmap */
+#define PR_5_BLOCK_NOTEXCLUDED 0x050101
+
+/* Block excluded, but not marked in exclude bitmap */
+#define PR_5_BLOCK_EXCLUDED 0x050102
+
+/* Block range not excluded, but marked in exclude bitmap */
+#define PR_5_BLOCK_RANGE_NOTEXCLUDED 0x050103
+
+/* Block range excluded, but not marked in exclude bitmap */
+#define PR_5_BLOCK_RANGE_EXCLUDED 0x050104
+
+/* Exclude bitmap differences end */
+#define PR_5_EXCLUDE_BITMAP_END 0x050105
+
/*
* Post-Pass 5 errors
*/
--
1.7.5.1


2011-10-23 09:10:57

by Yongqiang Yang

[permalink] [raw]
Subject: [PATCH 2/8] e2fsprogs: add exclude bitmap support in mkfs

Exclude bitmap is needed by ext4 snapshot. This patch adds
exclude bitmap support in mkfs.

Signed-off-by: Yongqiang Yang <[email protected]>
---
misc/mke2fs.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/misc/mke2fs.c b/misc/mke2fs.c
index 3dcb3b7..2dc28e7 100644
--- a/misc/mke2fs.c
+++ b/misc/mke2fs.c
@@ -828,6 +828,7 @@ static void parse_extended_opts(struct ext2_super_block *param,
static __u32 ok_features[3] = {
/* Compat */
EXT3_FEATURE_COMPAT_HAS_JOURNAL |
+ EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP |
EXT2_FEATURE_COMPAT_RESIZE_INODE |
EXT2_FEATURE_COMPAT_DIR_INDEX |
EXT2_FEATURE_COMPAT_EXT_ATTR,
--
1.7.5.1


2011-10-23 09:10:55

by Yongqiang Yang

[permalink] [raw]
Subject: [PATCH 1/8] e2fsprogs: add exclude bitmap support in libext2fs

Exclude bitmap is needed by ext4 snapshot. This patch adds
exclude bitmap support in libext2fs.

Signed-off-by: Yongqiang Yang <[email protected]>
Signed-off-by: Amir Goldstein <[email protected]>
---
lib/e2p/ls.c | 13 ++++
lib/ext2fs/alloc.c | 3 +
lib/ext2fs/alloc_tables.c | 44 ++++++++++++++-
lib/ext2fs/bitmaps.c | 70 +++++++++++++++++++++++
lib/ext2fs/blknum.c | 27 +++++++++
lib/ext2fs/bmap64.h | 2 +
lib/ext2fs/csum.c | 5 +-
lib/ext2fs/dupfs.c | 5 ++
lib/ext2fs/ext2_err.et.in | 21 +++++++
lib/ext2fs/ext2_fs.h | 2 +
lib/ext2fs/ext2fs.h | 28 +++++++++
lib/ext2fs/freefs.c | 2 +
lib/ext2fs/gen_bitmap.c | 48 ++++++++++++++++
lib/ext2fs/gen_bitmap64.c | 3 +
lib/ext2fs/initialize.c | 16 +++++
lib/ext2fs/openfs.c | 2 +
lib/ext2fs/rw_bitmaps.c | 136 ++++++++++++++++++++++++++++++++++++++++-----
lib/ext2fs/swapfs.c | 2 +
18 files changed, 409 insertions(+), 20 deletions(-)

diff --git a/lib/e2p/ls.c b/lib/e2p/ls.c
index f05e16d..0cd5b37 100644
--- a/lib/e2p/ls.c
+++ b/lib/e2p/ls.c
@@ -161,6 +161,19 @@ static void print_super_flags(struct ext2_super_block * s, FILE *f)
fputs("test_filesystem ", f);
flags_found++;
}
+ if (s->s_flags & EXT2_FLAGS_IS_SNAPSHOT) {
+ fputs("is_snapshot ", f);
+ flags_found++;
+ }
+ if (s->s_flags & EXT2_FLAGS_FIX_SNAPSHOT) {
+ fputs("fix_snapshot ", f);
+ flags_found++;
+ }
+ if (s->s_flags & EXT2_FLAGS_FIX_EXCLUDE) {
+ fputs("fix_snapshot_bitmap ", f);
+ flags_found++;
+ }
+
if (flags_found)
fputs("\n", f);
else
diff --git a/lib/ext2fs/alloc.c b/lib/ext2fs/alloc.c
index 948a0ec..a0b91dd 100644
--- a/lib/ext2fs/alloc.c
+++ b/lib/ext2fs/alloc.c
@@ -65,6 +65,9 @@ static void check_block_uninit(ext2_filsys fs, ext2fs_block_bitmap map,
(blk < old_desc_blk + old_desc_blocks)) ||
(new_desc_blk && (blk == new_desc_blk)) ||
(blk == ext2fs_block_bitmap_loc(fs, group)) ||
+ (EXT2_HAS_COMPAT_FEATURE(fs->super,
+ EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP) &&
+ (blk == ext2fs_exclude_bitmap_loc(fs, group))) ||
(blk == ext2fs_inode_bitmap_loc(fs, group)) ||
(blk >= ext2fs_inode_table_loc(fs, group) &&
(blk < ext2fs_inode_table_loc(fs, group)
diff --git a/lib/ext2fs/alloc_tables.c b/lib/ext2fs/alloc_tables.c
index 9f3d4e0..b5e2f0c 100644
--- a/lib/ext2fs/alloc_tables.c
+++ b/lib/ext2fs/alloc_tables.c
@@ -87,7 +87,7 @@ errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group,
errcode_t retval;
blk64_t group_blk, start_blk, last_blk, new_blk, blk;
dgrp_t last_grp = 0;
- int rem_grps = 0, flexbg_size = 0;
+ int rem_grps = 0, flexbg_size = 0, exclude_bitmap = 0;

group_blk = ext2fs_group_first_block2(fs, group);
last_blk = ext2fs_group_last_block2(fs, group);
@@ -105,8 +105,12 @@ errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group,
rem_grps = last_grp - group + 1;
}

+ if (EXT2_HAS_COMPAT_FEATURE(fs->super,
+ EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP))
+ exclude_bitmap = 1;
+
/*
- * Allocate the block and inode bitmaps, if necessary
+ * Allocate the block, exclude and inode bitmaps, if necessary
*/
if (fs->stride) {
retval = ext2fs_get_free_blocks2(fs, group_blk, last_blk,
@@ -150,13 +154,47 @@ errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group,
}
}

+ if (exclude_bitmap && flexbg_size) {
+ blk64_t prev_block = 0;
+
+ if (group % flexbg_size)
+ prev_block = ext2fs_exclude_bitmap_loc(fs, group - 1) + 1;
+ else
+ prev_block = ext2fs_block_bitmap_loc(fs, group) +
+ flexbg_size;
+ start_blk = flexbg_offset(fs, group, prev_block, bmap,
+ rem_grps, 1);
+ last_blk = ext2fs_group_last_block2(fs, last_grp);
+ }
+
+ if (exclude_bitmap && !ext2fs_exclude_bitmap_loc(fs, group)) {
+ retval = ext2fs_get_free_blocks2(fs, start_blk, last_blk,
+ 1, bmap, &new_blk);
+ if (retval == EXT2_ET_BLOCK_ALLOC_FAIL)
+ retval = ext2fs_get_free_blocks2(fs, group_blk,
+ last_blk, 1, bmap, &new_blk);
+ if (retval)
+ return retval;
+ ext2fs_mark_block_bitmap2(bmap, new_blk);
+ ext2fs_exclude_bitmap_loc_set(fs, group, new_blk);
+ if (flexbg_size) {
+ dgrp_t gr = ext2fs_group_of_blk2(fs, new_blk);
+ ext2fs_bg_free_blocks_count_set(fs, gr,
+ ext2fs_bg_free_blocks_count(fs, gr) - 1);
+ ext2fs_free_blocks_count_add(fs->super, -1);
+ ext2fs_bg_flags_clear(fs, gr, EXT2_BG_BLOCK_UNINIT);
+ ext2fs_group_desc_csum_set(fs, gr);
+ }
+ }
+
if (flexbg_size) {
blk64_t prev_block = 0;
if (group % flexbg_size)
prev_block = ext2fs_inode_bitmap_loc(fs, group - 1) + 1;
else
- prev_block = ext2fs_block_bitmap_loc(fs, group) +
+ prev_block = ext2fs_exclude_bitmap_loc(fs, group) +
flexbg_size;
+
start_blk = flexbg_offset(fs, group, prev_block, bmap,
rem_grps, 1);
last_blk = ext2fs_group_last_block2(fs, last_grp);
diff --git a/lib/ext2fs/bitmaps.c b/lib/ext2fs/bitmaps.c
index e518295..4709fa2 100644
--- a/lib/ext2fs/bitmaps.c
+++ b/lib/ext2fs/bitmaps.c
@@ -35,6 +35,11 @@ void ext2fs_free_inode_bitmap(ext2fs_inode_bitmap bitmap)
ext2fs_free_generic_bmap(bitmap);
}

+void ext2fs_free_exclude_bitmap(ext2fs_exclude_bitmap bitmap)
+{
+ ext2fs_free_generic_bmap(bitmap);
+}
+
void ext2fs_free_block_bitmap(ext2fs_block_bitmap bitmap)
{
ext2fs_free_generic_bmap(bitmap);
@@ -82,6 +87,39 @@ errcode_t ext2fs_allocate_inode_bitmap(ext2_filsys fs,
(ext2fs_generic_bitmap *) ret));
}

+errcode_t ext2fs_allocate_exclude_bitmap(ext2_filsys fs,
+ const char *descr,
+ ext2fs_exclude_bitmap *ret)
+{
+ __u32 start, end, real_end;
+
+ if (!EXT2_HAS_COMPAT_FEATURE(fs->super,
+ EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP))
+ return 0;
+
+ EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+ fs->write_bitmaps = ext2fs_write_bitmaps;
+
+ start = fs->super->s_first_data_block;
+ end = fs->super->s_blocks_count-1;
+ real_end = (EXT2_BLOCKS_PER_GROUP(fs->super)
+ * fs->group_desc_count)-1 + start;
+
+ if (fs->flags & EXT2_FLAG_64BITS)
+ return ext2fs_alloc_generic_bmap(fs,
+ EXT2_ET_MAGIC_EXCLUDE_BITMAP64,
+ EXT2FS_BMAP64_BITARRAY,
+ start, end, real_end, descr, ret);
+
+ if ((end > ~0U) || (real_end > ~0U))
+ return EXT2_ET_CANT_USE_LEGACY_BITMAPS;
+
+ return ext2fs_make_generic_bitmap(EXT2_ET_MAGIC_EXCLUDE_BITMAP, fs,
+ start, end, real_end,
+ descr, 0, ret);
+}
+
errcode_t ext2fs_allocate_block_bitmap(ext2_filsys fs,
const char *descr,
ext2fs_block_bitmap *ret)
@@ -268,6 +306,38 @@ errcode_t ext2fs_get_inode_bitmap_range(ext2fs_inode_bitmap bmap,
start, num, out));
}

+errcode_t ext2fs_set_exclude_bitmap_range(ext2fs_exclude_bitmap bmap,
+ blk_t start, unsigned int num,
+ void *in)
+{
+ return ext2fs_set_generic_bitmap_range(bmap,
+ EXT2_ET_MAGIC_EXCLUDE_BITMAP,
+ start, num, in);
+}
+
+errcode_t ext2fs_set_exclude_bitmap_range2(ext2fs_exclude_bitmap bmap,
+ blk64_t start, size_t num,
+ void *in)
+{
+ return ext2fs_set_generic_bmap_range(bmap, start, num, in);
+}
+
+errcode_t ext2fs_get_exclude_bitmap_range(ext2fs_exclude_bitmap bmap,
+ blk_t start, unsigned int num,
+ void *out)
+{
+ return ext2fs_get_generic_bitmap_range(bmap,
+ EXT2_ET_MAGIC_EXCLUDE_BITMAP,
+ start, num, out);
+}
+
+errcode_t ext2fs_get_exclude_bitmap_range2(ext2fs_exclude_bitmap bmap,
+ blk64_t start, size_t num,
+ void *out)
+{
+ return ext2fs_get_generic_bmap_range(bmap, start, num, out);
+}
+
errcode_t ext2fs_get_inode_bitmap_range2(ext2fs_inode_bitmap bmap,
__u64 start, size_t num,
void *out)
diff --git a/lib/ext2fs/blknum.c b/lib/ext2fs/blknum.c
index fd203b4..17df8c7 100644
--- a/lib/ext2fs/blknum.c
+++ b/lib/ext2fs/blknum.c
@@ -230,6 +230,33 @@ void ext2fs_block_bitmap_loc_set(ext2_filsys fs, dgrp_t group, blk64_t blk)
}

/*
+ * Return the exclude bitmap block of a group
+ */
+blk64_t ext2fs_exclude_bitmap_loc(ext2_filsys fs, dgrp_t group)
+{
+ struct ext4_group_desc *gdp;
+
+ gdp = ext4fs_group_desc(fs, fs->group_desc, group);
+ return gdp->bg_exclude_bitmap_lo |
+ (fs->super->s_feature_incompat
+ & EXT4_FEATURE_INCOMPAT_64BIT ?
+ (__u64)gdp->bg_exclude_bitmap_hi << 32 : 0);
+}
+
+/*
+ * Set the exclude bitmap block of a group
+ */
+void ext2fs_exclude_bitmap_loc_set(ext2_filsys fs, dgrp_t group, blk64_t blk)
+{
+ struct ext4_group_desc *gdp;
+
+ gdp = ext4fs_group_desc(fs, fs->group_desc, group);
+ gdp->bg_exclude_bitmap_lo = blk;
+ if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
+ gdp->bg_exclude_bitmap_hi = (__u64) blk >> 32;
+}
+
+/*
* Return the inode bitmap block of a group
*/
blk64_t ext2fs_inode_bitmap_loc(ext2_filsys fs, dgrp_t group)
diff --git a/lib/ext2fs/bmap64.h b/lib/ext2fs/bmap64.h
index 3056544..d1baef2 100644
--- a/lib/ext2fs/bmap64.h
+++ b/lib/ext2fs/bmap64.h
@@ -25,11 +25,13 @@ struct ext2fs_struct_generic_bitmap {
#define EXT2FS_IS_32_BITMAP(bmap) \
(((bmap)->magic == EXT2_ET_MAGIC_GENERIC_BITMAP) || \
((bmap)->magic == EXT2_ET_MAGIC_BLOCK_BITMAP) || \
+ ((bmap)->magic == EXT2_ET_MAGIC_EXCLUDE_BITMAP) || \
((bmap)->magic == EXT2_ET_MAGIC_INODE_BITMAP))

#define EXT2FS_IS_64_BITMAP(bmap) \
(((bmap)->magic == EXT2_ET_MAGIC_GENERIC_BITMAP64) || \
((bmap)->magic == EXT2_ET_MAGIC_BLOCK_BITMAP64) || \
+ ((bmap)->magic == EXT2_ET_MAGIC_EXCLUDE_BITMAP64) || \
((bmap)->magic == EXT2_ET_MAGIC_INODE_BITMAP64))

struct ext2_bitmap_ops {
diff --git a/lib/ext2fs/csum.c b/lib/ext2fs/csum.c
index 596923e..d6158e1 100644
--- a/lib/ext2fs/csum.c
+++ b/lib/ext2fs/csum.c
@@ -229,8 +229,9 @@ int main(int argc, char **argv)

for (i=0; i < fs->group_desc_count; i++) {
ext2fs_block_bitmap_loc_set(fs, i, 124);
- ext2fs_inode_bitmap_loc_set(fs, i, 125);
- ext2fs_inode_table_loc_set(fs, i, 126);
+ ext2fs_exclude_bitmap_loc_set(fs, i, 125);
+ ext2fs_inode_bitmap_loc_set(fs, i, 126);
+ ext2fs_inode_table_loc_set(fs, i, 127);
ext2fs_bg_free_blocks_count_set(fs, i, 31119);
ext2fs_bg_free_inodes_count_set(fs, i, 15701);
ext2fs_bg_used_dirs_count_set(fs, i, 2);
diff --git a/lib/ext2fs/dupfs.c b/lib/ext2fs/dupfs.c
index 64d3124..e7c00c1 100644
--- a/lib/ext2fs/dupfs.c
+++ b/lib/ext2fs/dupfs.c
@@ -77,6 +77,11 @@ errcode_t ext2fs_dup_handle(ext2_filsys src, ext2_filsys *dest)
if (retval)
goto errout;
}
+ if (src->exclude_map) {
+ retval = ext2fs_copy_bitmap(src->exclude_map, &fs->exclude_map);
+ if (retval)
+ goto errout;
+ }
if (src->badblocks) {
retval = ext2fs_badblocks_copy(src->badblocks, &fs->badblocks);
if (retval)
diff --git a/lib/ext2fs/ext2_err.et.in b/lib/ext2fs/ext2_err.et.in
index e759b6f..c49f0d0 100644
--- a/lib/ext2fs/ext2_err.et.in
+++ b/lib/ext2fs/ext2_err.et.in
@@ -38,6 +38,9 @@ ec EXT2_ET_MAGIC_BLOCK_BITMAP,
ec EXT2_ET_MAGIC_INODE_BITMAP,
"Wrong magic number for inode_bitmap structure"

+ec EXT2_ET_MAGIC_EXCLUDE_BITMAP,
+ "Wrong magic number for snapshot_bitmap structure"
+
ec EXT2_ET_MAGIC_GENERIC_BITMAP,
"Wrong magic number for generic_bitmap structure"

@@ -101,6 +104,12 @@ ec EXT2_ET_BLOCK_BITMAP_WRITE,
ec EXT2_ET_BLOCK_BITMAP_READ,
"Can't read an block bitmap"

+ec EXT2_ET_EXCLUDE_BITMAP_WRITE,
+ "Can't write an snapshot bitmap"
+
+ec EXT2_ET_EXCLUDE_BITMAP_READ,
+ "Can't read an snapshot bitmap"
+
ec EXT2_ET_INODE_TABLE_WRITE,
"Can't write an inode table"

@@ -344,6 +353,9 @@ ec EXT2_ET_MAGIC_BLOCK_BITMAP64,
ec EXT2_ET_MAGIC_INODE_BITMAP64,
"Wrong magic number for 64-bit inode bitmap"

+ec EXT2_ET_MAGIC_EXCLUDE_BITMAP64,
+ "Wrong magic number for 64-bit exclude bitmap"
+
ec EXT2_ET_MAGIC_RESERVED_13,
"Wrong magic number --- RESERVED_13"

@@ -443,4 +455,13 @@ ec EXT2_ET_MMP_CHANGE_ABORT,
ec EXT2_ET_MMP_OPEN_DIRECT,
"MMP: open with O_DIRECT failed"

+ec EXT2_ET_BAD_EXCLUDE_TEST,
+ "Illegal block number passed to ext2fs_test_exclude_bitmap"
+
+ec EXT2_ET_BAD_EXCLUDE_MARK,
+ "Illegal block number passed to ext2fs_mark_exclude_bitmap"
+
+ec EXT2_ET_BAD_EXCLUDE_UNMARK,
+ "Illegal block number passed to ext2fs_unmark_exclude_bitmap"
+
end
diff --git a/lib/ext2fs/ext2_fs.h b/lib/ext2fs/ext2_fs.h
index 0f8cde8..a1e29d0 100644
--- a/lib/ext2fs/ext2_fs.h
+++ b/lib/ext2fs/ext2_fs.h
@@ -194,6 +194,7 @@ struct ext4_group_desc
#define EXT2_BG_INODE_UNINIT 0x0001 /* Inode table/bitmap not initialized */
#define EXT2_BG_BLOCK_UNINIT 0x0002 /* Block bitmap not initialized */
#define EXT2_BG_INODE_ZEROED 0x0004 /* On-disk itable initialized to zero */
+#define EXT2_BG_EXCLUDE_UNINIT 0x0008 /* Exclude bitmap not initialized */

/*
* Data structures used by the directory indexing feature
@@ -724,6 +725,7 @@ struct ext2_super_block {
#define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE| \
EXT4_FEATURE_INCOMPAT_MMP)
#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
+ EXT4_FEATURE_RO_COMPAT_HAS_SNAPSHOT|\
EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
EXT4_FEATURE_RO_COMPAT_DIR_NLINK| \
EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index 203d222..d1f0d98 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -113,7 +113,9 @@ typedef struct struct_ext2_filsys *ext2_filsys;

typedef struct ext2fs_struct_generic_bitmap *ext2fs_generic_bitmap;
typedef struct ext2fs_struct_generic_bitmap *ext2fs_inode_bitmap;
+typedef struct ext2fs_struct_generic_bitmap *ext2fs_exclude_bitmap;
typedef struct ext2fs_struct_generic_bitmap *ext2fs_block_bitmap;
+typedef struct ext2fs_struct_generic_bitmap *ext2fs_exclude_bitmap;

#define EXT2_FIRST_INODE(s) EXT2_FIRST_INO(s)

@@ -196,6 +198,7 @@ typedef struct ext2_file *ext2_file_t;
#define EXT2_FLAG_PRINT_PROGRESS 0x40000
#define EXT2_FLAG_DIRECT_IO 0x80000
#define EXT2_FLAG_SKIP_MMP 0x100000
+#define EXT2_FLAG_EB_DIRTY 0x200000

/*
* Special flag in the ext2 inode i_flag field that means that this is
@@ -225,6 +228,7 @@ struct struct_ext2_filsys {
unsigned int inode_blocks_per_group;
ext2fs_inode_bitmap inode_map;
ext2fs_block_bitmap block_map;
+ ext2fs_exclude_bitmap exclude_map;
/* XXX FIXME-64: not 64-bit safe, but not used? */
errcode_t (*get_blocks)(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks);
errcode_t (*check_directory)(ext2_filsys fs, ext2_ino_t ino);
@@ -543,6 +547,7 @@ typedef struct ext2_icount *ext2_icount_t;
#define EXT2_LIB_FEATURE_COMPAT_SUPP (EXT2_FEATURE_COMPAT_DIR_PREALLOC|\
EXT2_FEATURE_COMPAT_IMAGIC_INODES|\
EXT3_FEATURE_COMPAT_HAS_JOURNAL|\
+ EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP|\
EXT2_FEATURE_COMPAT_RESIZE_INODE|\
EXT2_FEATURE_COMPAT_DIR_INDEX|\
EXT2_FEATURE_COMPAT_EXT_ATTR)
@@ -721,8 +726,10 @@ extern errcode_t ext2fs_copy_bitmap(ext2fs_generic_bitmap src,
ext2fs_generic_bitmap *dest);
extern errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs);
extern errcode_t ext2fs_write_block_bitmap (ext2_filsys fs);
+extern errcode_t ext2fs_write_exclude_bitmap (ext2_filsys fs);
extern errcode_t ext2fs_read_inode_bitmap (ext2_filsys fs);
extern errcode_t ext2fs_read_block_bitmap(ext2_filsys fs);
+extern errcode_t ext2fs_read_exclude_bitmap (ext2_filsys fs);
extern errcode_t ext2fs_allocate_block_bitmap(ext2_filsys fs,
const char *descr,
ext2fs_block_bitmap *ret);
@@ -813,6 +820,9 @@ extern struct ext2_group_desc *ext2fs_group_desc(ext2_filsys fs,
extern blk64_t ext2fs_block_bitmap_loc(ext2_filsys fs, dgrp_t group);
extern void ext2fs_block_bitmap_loc_set(ext2_filsys fs, dgrp_t group,
blk64_t blk);
+extern blk64_t ext2fs_exclude_bitmap_loc(ext2_filsys fs, dgrp_t group);
+extern void ext2fs_block_exclude_loc_set(ext2_filsys fs, dgrp_t group,
+ blk64_t blk);
extern blk64_t ext2fs_inode_bitmap_loc(ext2_filsys fs, dgrp_t group);
extern void ext2fs_inode_bitmap_loc_set(ext2_filsys fs, dgrp_t group,
blk64_t blk);
@@ -1619,6 +1629,16 @@ _INLINE_ void ext2fs_mark_bb_dirty(ext2_filsys fs)
}

/*
+ * Mark the exclude bitmap as dirty
+ */
+_INLINE_ void ext2fs_mark_eb_dirty(ext2_filsys fs)
+{
+ if (EXT2_HAS_COMPAT_FEATURE(fs->super,
+ EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP))
+ fs->flags |= EXT2_FLAG_EB_DIRTY | EXT2_FLAG_CHANGED;
+}
+
+/*
* Check to see if a filesystem's inode bitmap is dirty
*/
_INLINE_ int ext2fs_test_ib_dirty(ext2_filsys fs)
@@ -1635,6 +1655,14 @@ _INLINE_ int ext2fs_test_bb_dirty(ext2_filsys fs)
}

/*
+ * Check to see if a filesystem's exclude bitmap is dirty
+ */
+_INLINE_ int ext2fs_test_eb_dirty(ext2_filsys fs)
+{
+ return fs->flags & EXT2_FLAG_EB_DIRTY;
+}
+
+/*
* Return the group # of a block
*/
_INLINE_ int ext2fs_group_of_blk(ext2_filsys fs, blk_t blk)
diff --git a/lib/ext2fs/freefs.c b/lib/ext2fs/freefs.c
index 28c4132..488f077 100644
--- a/lib/ext2fs/freefs.c
+++ b/lib/ext2fs/freefs.c
@@ -43,6 +43,8 @@ void ext2fs_free(ext2_filsys fs)
ext2fs_free_block_bitmap(fs->block_map);
if (fs->inode_map)
ext2fs_free_inode_bitmap(fs->inode_map);
+ if (fs->exclude_map)
+ ext2fs_free_exclude_bitmap(fs->exclude_map);

if (fs->badblocks)
ext2fs_badblocks_list_free(fs->badblocks);
diff --git a/lib/ext2fs/gen_bitmap.c b/lib/ext2fs/gen_bitmap.c
index 6679bff..0285c33 100644
--- a/lib/ext2fs/gen_bitmap.c
+++ b/lib/ext2fs/gen_bitmap.c
@@ -42,11 +42,13 @@ struct ext2fs_struct_generic_bitmap {
#define EXT2FS_IS_32_BITMAP(bmap) \
(((bmap)->magic == EXT2_ET_MAGIC_GENERIC_BITMAP) || \
((bmap)->magic == EXT2_ET_MAGIC_BLOCK_BITMAP) || \
+ ((bmap)->magic == EXT2_ET_MAGIC_EXCLUDE_BITMAP) || \
((bmap)->magic == EXT2_ET_MAGIC_INODE_BITMAP))

#define EXT2FS_IS_64_BITMAP(bmap) \
(((bmap)->magic == EXT2_ET_MAGIC_GENERIC_BITMAP64) || \
((bmap)->magic == EXT2_ET_MAGIC_BLOCK_BITMAP64) || \
+ ((bmap)->magic == EXT2_ET_MAGIC_EXCLUDE_BITMAP64) || \
((bmap)->magic == EXT2_ET_MAGIC_INODE_BITMAP64))

/*
@@ -69,6 +71,7 @@ static errcode_t check_magic(ext2fs_generic_bitmap bitmap)
{
if (!bitmap || !((bitmap->magic == EXT2_ET_MAGIC_GENERIC_BITMAP) ||
(bitmap->magic == EXT2_ET_MAGIC_INODE_BITMAP) ||
+ (bitmap->magic == EXT2_ET_MAGIC_EXCLUDE_BITMAP) ||
(bitmap->magic == EXT2_ET_MAGIC_BLOCK_BITMAP)))
return EXT2_ET_MAGIC_GENERIC_BITMAP;
return 0;
@@ -100,6 +103,9 @@ errcode_t ext2fs_make_generic_bitmap(errcode_t magic, ext2_filsys fs,
case EXT2_ET_MAGIC_BLOCK_BITMAP:
bitmap->base_error_code = EXT2_ET_BAD_BLOCK_MARK;
break;
+ case EXT2_ET_MAGIC_EXCLUDE_BITMAP:
+ bitmap->base_error_code = EXT2_ET_BAD_EXCLUDE_MARK;
+ break;
default:
bitmap->base_error_code = EXT2_ET_BAD_GENERIC_MARK;
}
@@ -517,6 +523,19 @@ int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
bitmap, block, num);
}

+int ext2fs_test_exlucde_bitmap_range(ext2fs_exclude_bitmap bitmap,
+ blk_t block, int num)
+{
+ EXT2_CHECK_MAGIC(bitmap, EXT2_ET_MAGIC_EXCLUDE_BITMAP);
+ if ((block < bitmap->start) || (block+num-1 > bitmap->real_end)) {
+ ext2fs_warn_bitmap(EXT2_ET_BAD_EXCLUDE_TEST,
+ block, bitmap->description);
+ return 0;
+ }
+ return ext2fs_test_clear_generic_bitmap_range((ext2fs_generic_bitmap)
+ bitmap, block, num);
+}
+
int ext2fs_test_inode_bitmap_range(ext2fs_inode_bitmap bitmap,
ino_t inode, int num)
{
@@ -558,3 +577,32 @@ void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
ext2fs_fast_clear_bit(block + i - bitmap->start,
bitmap->bitmap);
}
+
+void ext2fs_mark_exclude_bitmap_range(ext2fs_exclude_bitmap bitmap,
+ blk_t block, int num)
+{
+ int i;
+
+ if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
+ ext2fs_warn_bitmap(EXT2_ET_BAD_EXCLUDE_MARK, block,
+ bitmap->description);
+ return;
+ }
+ for (i = 0; i < num; i++)
+ ext2fs_fast_set_bit(block + i - bitmap->start, bitmap->bitmap);
+}
+
+void ext2fs_unmark_exclude_bitmap_range(ext2fs_exclude_bitmap bitmap,
+ blk_t block, int num)
+{
+ int i;
+
+ if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
+ ext2fs_warn_bitmap(EXT2_ET_BAD_EXCLUDE_UNMARK, block,
+ bitmap->description);
+ return;
+ }
+ for (i = 0; i < num; i++)
+ ext2fs_fast_clear_bit(block + i - bitmap->start,
+ bitmap->bitmap);
+}
diff --git a/lib/ext2fs/gen_bitmap64.c b/lib/ext2fs/gen_bitmap64.c
index 9dbbf9f..abceb0f 100644
--- a/lib/ext2fs/gen_bitmap64.c
+++ b/lib/ext2fs/gen_bitmap64.c
@@ -117,6 +117,9 @@ errcode_t ext2fs_alloc_generic_bmap(ext2_filsys fs, errcode_t magic,
bitmap->base_error_code = EXT2_ET_BAD_BLOCK_MARK;
bitmap->cluster_bits = fs->cluster_ratio_bits;
break;
+ case EXT2_ET_MAGIC_EXCLUDE_BITMAP64:
+ bitmap->base_error_code = EXT2_ET_BAD_EXCLUDE_MARK;
+ break;
default:
bitmap->base_error_code = EXT2_ET_BAD_GENERIC_MARK;
}
diff --git a/lib/ext2fs/initialize.c b/lib/ext2fs/initialize.c
index 47f0b1c..0dc8852 100644
--- a/lib/ext2fs/initialize.c
+++ b/lib/ext2fs/initialize.c
@@ -97,6 +97,7 @@ errcode_t ext2fs_initialize(const char *name, int flags,
int rsv_gdt;
int csum_flag;
int bigalloc_flag;
+ int exclude_flag;
int io_flags;
char *buf = 0;
char c;
@@ -407,6 +408,17 @@ ipg_retry:
if (retval)
goto cleanup;

+ exclude_flag = EXT2_HAS_COMPAT_FEATURE(fs->super,
+ EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP);
+ if (exclude_flag) {
+ strcpy(buf, "exclude bitmap for ");
+ strcat(buf, fs->device_name);
+ retval = ext2fs_allocate_exclude_bitmap(fs, buf,
+ &fs->exclude_map);
+ if (retval)
+ goto cleanup;
+ }
+
strcpy(buf, "inode bitmap for ");
strcat(buf, fs->device_name);
retval = ext2fs_allocate_inode_bitmap(fs, buf, &fs->inode_map);
@@ -445,6 +457,9 @@ ipg_retry:
if (i != fs->group_desc_count - 1)
ext2fs_bg_flags_set(fs, i,
EXT2_BG_BLOCK_UNINIT);
+ if (exclude_flag)
+ ext2fs_bg_flags_set(fs, i,
+ EXT2_BG_EXCLUDE_UNINIT);
ext2fs_bg_flags_set(fs, i, EXT2_BG_INODE_UNINIT);
numblocks = super->s_inodes_per_group;
if (i == 0)
@@ -473,6 +488,7 @@ ipg_retry:

ext2fs_mark_super_dirty(fs);
ext2fs_mark_bb_dirty(fs);
+ ext2fs_mark_eb_dirty(fs);
ext2fs_mark_ib_dirty(fs);

io_channel_set_blksize(fs->io, fs->blocksize);
diff --git a/lib/ext2fs/openfs.c b/lib/ext2fs/openfs.c
index 0cefe3f..a047d0d 100644
--- a/lib/ext2fs/openfs.c
+++ b/lib/ext2fs/openfs.c
@@ -376,6 +376,8 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,

for (group = 0; group < fs->group_desc_count; group++) {
ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT);
+ ext2fs_bg_flags_clear(fs, group,
+ EXT2_BG_EXCLUDE_UNINIT);
ext2fs_bg_flags_clear(fs, group, EXT2_BG_INODE_UNINIT);
ext2fs_bg_itable_unused_set(fs, group, 0);
}
diff --git a/lib/ext2fs/rw_bitmaps.c b/lib/ext2fs/rw_bitmaps.c
index 1d5f7b2..3126733 100644
--- a/lib/ext2fs/rw_bitmaps.c
+++ b/lib/ext2fs/rw_bitmaps.c
@@ -28,17 +28,21 @@
#include "ext2fs.h"
#include "e2image.h"

-static errcode_t write_bitmaps(ext2_filsys fs, int do_inode, int do_block)
+static errcode_t write_bitmaps(ext2_filsys fs, int do_inode, int do_block,
+ int do_exclude)
{
dgrp_t i;
unsigned int j;
int block_nbytes, inode_nbytes;
unsigned int nbits;
errcode_t retval;
- char *block_buf = NULL, *inode_buf = NULL;
+ char *block_buf = NULL, *inode_buf = NULL,
+ *exclude_buf = NULL;
int csum_flag = 0;
blk64_t blk;
blk64_t blk_itr = EXT2FS_B2C(fs, fs->super->s_first_data_block);
+ blk64_t exclude_itr =
+ EXT2FS_B2C(fs, fs->super->s_first_data_block);
ext2_ino_t ino_itr = 1;

EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
@@ -46,6 +50,10 @@ static errcode_t write_bitmaps(ext2_filsys fs, int do_inode, int do_block)
if (!(fs->flags & EXT2_FLAG_RW))
return EXT2_ET_RO_FILSYS;

+ if (!EXT2_HAS_COMPAT_FEATURE(fs->super,
+ EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP))
+ do_exclude = 0;
+
if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
EXT4_FEATURE_RO_COMPAT_GDT_CSUM))
csum_flag = 1;
@@ -59,6 +67,14 @@ static errcode_t write_bitmaps(ext2_filsys fs, int do_inode, int do_block)
goto errout;
memset(block_buf, 0xff, fs->blocksize);
}
+ if (do_exclude) {
+ block_nbytes = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
+ retval = ext2fs_get_memalign(fs->blocksize, fs->blocksize,
+ &exclude_buf);
+ if (retval)
+ return retval;
+ memset(exclude_buf, 0x0, fs->blocksize);
+ }
if (do_inode) {
inode_nbytes = (size_t)
((EXT2_INODES_PER_GROUP(fs->super)+7) / 8);
@@ -104,6 +120,26 @@ static errcode_t write_bitmaps(ext2_filsys fs, int do_inode, int do_block)
skip_this_block_bitmap:
blk_itr += block_nbytes << 3;
skip_block_bitmap:
+ if (!do_exclude)
+ goto skip_exclude_bitmap;
+ if (csum_flag && ext2fs_bg_flags_test(fs, i, EXT2_BG_EXCLUDE_UNINIT)
+ )
+ goto skip_this_exclude_bitmap;
+
+ retval = ext2fs_get_block_bitmap_range2(fs->exclude_map,
+ exclude_itr, block_nbytes << 3, exclude_buf);
+ if (retval)
+ goto errout;
+ blk = ext2fs_exclude_bitmap_loc(fs, i);
+ if (blk) {
+ retval = io_channel_write_blk64(fs->io, blk, 1,
+ exclude_buf);
+ if (retval)
+ return EXT2_ET_EXCLUDE_BITMAP_WRITE;
+ }
+ skip_this_exclude_bitmap:
+ exclude_itr += block_nbytes << 3;
+ skip_exclude_bitmap:

if (!do_inode)
continue;
@@ -126,7 +162,7 @@ static errcode_t write_bitmaps(ext2_filsys fs, int do_inode, int do_block)
goto errout;
}
}
- skip_this_inode_bitmap:
+skip_this_inode_bitmap:
ino_itr += inode_nbytes << 3;

}
@@ -134,6 +170,10 @@ static errcode_t write_bitmaps(ext2_filsys fs, int do_inode, int do_block)
fs->flags &= ~EXT2_FLAG_BB_DIRTY;
ext2fs_free_mem(&block_buf);
}
+ if (do_exclude) {
+ fs->flags &= ~EXT2_FLAG_EB_DIRTY;
+ ext2fs_free_mem(&exclude_buf);
+ }
if (do_inode) {
fs->flags &= ~EXT2_FLAG_IB_DIRTY;
ext2fs_free_mem(&inode_buf);
@@ -147,10 +187,11 @@ errout:
return retval;
}

-static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
+static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block,
+ int do_exclude)
{
dgrp_t i;
- char *block_bitmap = 0, *inode_bitmap = 0;
+ char *block_bitmap = 0, *inode_bitmap = 0, *exclude_bitmap = 0;
char *buf;
errcode_t retval;
int block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8;
@@ -168,6 +209,10 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)

fs->write_bitmaps = ext2fs_write_bitmaps;

+ if (!EXT2_HAS_COMPAT_FEATURE(fs->super,
+ EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP))
+ do_exclude = 0;
+
if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
EXT4_FEATURE_RO_COMPAT_GDT_CSUM))
csum_flag = 1;
@@ -192,7 +237,25 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)

if (retval)
goto cleanup;
- } else
+ }
+ if (do_exclude) {
+ if (fs->exclude_map)
+ ext2fs_free_block_bitmap(fs->exclude_map);
+ strcpy(buf, "exclude bitmap for ");
+ strcat(buf, fs->device_name);
+ retval = ext2fs_allocate_block_bitmap(fs, buf, &fs->exclude_map);
+ if (retval)
+ goto cleanup;
+ if (do_image)
+ retval = ext2fs_get_mem(fs->blocksize, &exclude_bitmap);
+ else
+ retval = ext2fs_get_memalign((unsigned) block_nbytes,
+ fs->blocksize,
+ &exclude_bitmap);
+ if (retval)
+ goto cleanup;
+ }
+ if (!do_block && !do_exclude)
block_nbytes = 0;
if (do_inode) {
if (fs->inode_map)
@@ -234,6 +297,11 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
blk_cnt = (blk64_t)EXT2_CLUSTERS_PER_GROUP(fs->super) *
fs->group_desc_count;
while (block_nbytes > 0) {
+ if (do_exclude) {
+ retval = EXT2_ET_EXCLUDE_BITMAP_READ;
+ goto cleanup;
+ }
+
retval = io_channel_read_blk64(fs->image_io, blk++,
1, block_bitmap);
if (retval)
@@ -273,8 +341,30 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
blk_itr, cnt, block_bitmap);
if (retval)
goto cleanup;
- blk_itr += block_nbytes << 3;
}
+ if (exclude_bitmap) {
+ blk = ext2fs_exclude_bitmap_loc(fs, i);
+ if (csum_flag &&
+ ext2fs_bg_flags_test(fs, i, EXT2_BG_EXCLUDE_UNINIT) &&
+ ext2fs_group_desc_csum_verify(fs, i))
+ blk = 0;
+ if (blk) {
+ retval = io_channel_read_blk64(fs->io, blk,
+ -block_nbytes, exclude_bitmap);
+ if (retval) {
+ retval = EXT2_ET_EXCLUDE_BITMAP_READ;
+ goto cleanup;
+ }
+ } else
+ memset(exclude_bitmap, 0, block_nbytes);
+ cnt = block_nbytes << 3;
+ retval = ext2fs_set_block_bitmap_range2(fs->exclude_map,
+ blk_itr, cnt, exclude_bitmap);
+ if (retval)
+ goto cleanup;
+ }
+ if (block_nbytes)
+ blk_itr += block_nbytes << 3;
if (inode_bitmap) {
blk = ext2fs_inode_bitmap_loc(fs, i);
if (csum_flag &&
@@ -303,6 +393,8 @@ success_cleanup:
ext2fs_free_mem(&inode_bitmap);
if (block_bitmap)
ext2fs_free_mem(&block_bitmap);
+ if (exclude_bitmap)
+ ext2fs_free_mem(&exclude_bitmap);
return 0;

cleanup:
@@ -318,6 +410,8 @@ cleanup:
ext2fs_free_mem(&inode_bitmap);
if (block_bitmap)
ext2fs_free_mem(&block_bitmap);
+ if (exclude_bitmap)
+ ext2fs_free_mem(&exclude_bitmap);
if (buf)
ext2fs_free_mem(&buf);
return retval;
@@ -325,39 +419,51 @@ cleanup:

errcode_t ext2fs_read_inode_bitmap(ext2_filsys fs)
{
- return read_bitmaps(fs, 1, 0);
+ return read_bitmaps(fs, 1, 0, 0);
}

errcode_t ext2fs_read_block_bitmap(ext2_filsys fs)
{
- return read_bitmaps(fs, 0, 1);
+ return read_bitmaps(fs, 0, 1, 0);
+}
+
+errcode_t ext2fs_read_exclude_bitmap (ext2_filsys fs)
+{
+ return read_bitmaps(fs, 0, 0, 1);
}

errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs)
{
- return write_bitmaps(fs, 1, 0);
+ return write_bitmaps(fs, 1, 0, 0);
}

errcode_t ext2fs_write_block_bitmap (ext2_filsys fs)
{
- return write_bitmaps(fs, 0, 1);
+ return write_bitmaps(fs, 0, 1, 0);
+}
+
+errcode_t ext2fs_write_exclude_bitmap (ext2_filsys fs)
+{
+ return write_bitmaps(fs, 0, 0, 1);
}

errcode_t ext2fs_read_bitmaps(ext2_filsys fs)
{
- if (fs->inode_map && fs->block_map)
+ if (fs->inode_map && fs->block_map && fs->exclude_map)
return 0;

- return read_bitmaps(fs, !fs->inode_map, !fs->block_map);
+ return read_bitmaps(fs, !fs->inode_map, !fs->block_map,
+ !fs->exclude_map);
}

errcode_t ext2fs_write_bitmaps(ext2_filsys fs)
{
int do_inode = fs->inode_map && ext2fs_test_ib_dirty(fs);
int do_block = fs->block_map && ext2fs_test_bb_dirty(fs);
+ int do_exclude = fs->exclude_map && ext2fs_test_eb_dirty(fs);

- if (!do_inode && !do_block)
+ if (!do_inode && !do_block && !do_exclude)
return 0;

- return write_bitmaps(fs, do_inode, do_block);
+ return write_bitmaps(fs, do_inode, do_block, do_exclude);
}
diff --git a/lib/ext2fs/swapfs.c b/lib/ext2fs/swapfs.c
index 7962472..07ba1cd 100644
--- a/lib/ext2fs/swapfs.c
+++ b/lib/ext2fs/swapfs.c
@@ -105,6 +105,7 @@ void ext2fs_swap_group_desc2(ext2_filsys fs, struct ext2_group_desc *gdp)
{
/* Do the 32-bit parts first */
gdp->bg_block_bitmap = ext2fs_swab32(gdp->bg_block_bitmap);
+ gdp->bg_exclude_bitmap = ext2fs_swab32(gdp->bg_exclude_bitmap);
gdp->bg_inode_bitmap = ext2fs_swab32(gdp->bg_inode_bitmap);
gdp->bg_inode_table = ext2fs_swab32(gdp->bg_inode_table);
gdp->bg_free_blocks_count = ext2fs_swab16(gdp->bg_free_blocks_count);
@@ -126,6 +127,7 @@ void ext2fs_swap_group_desc2(ext2_filsys fs, struct ext2_group_desc *gdp)
/* Swap the 64-bit parts */
struct ext4_group_desc *gdp4 = (struct ext4_group_desc *) gdp;
gdp4->bg_block_bitmap_hi = ext2fs_swab32(gdp4->bg_block_bitmap_hi);
+ gdp4->bg_exclude_bitmap_hi = ext2fs_swab32(gdp4->bg_exclude_bitmap_hi);
gdp4->bg_inode_bitmap_hi = ext2fs_swab32(gdp4->bg_inode_bitmap_hi);
gdp4->bg_inode_table_hi = ext2fs_swab32(gdp4->bg_inode_table_hi);
gdp4->bg_free_blocks_count_hi =
--
1.7.5.1


2011-10-23 09:11:01

by Yongqiang Yang

[permalink] [raw]
Subject: [PATCH 4/8] e2fsprogs: add exclude bitmap support in e2fsck

Exclude bitmap is a compat feature needed by exy4 snapshot. This
patch add exclude bitmap support in e2fsck.

Signed-off-by: Yongqiang Yang <[email protected]>
---
e2fsck/e2fsck.h | 1 +
e2fsck/pass1.c | 35 +++++++++++++++++++++++++++++++++++
e2fsck/pass1b.c | 5 +++++
e2fsck/pass5.c | 3 +++
e2fsck/problem.h | 6 ++++++
e2fsck/super.c | 18 ++++++++++++++++++
e2fsck/util.c | 9 ++++++---
lib/ext2fs/check_desc.c | 14 ++++++++++++++
8 files changed, 88 insertions(+), 3 deletions(-)

diff --git a/e2fsck/e2fsck.h b/e2fsck/e2fsck.h
index 44909c3..bd85683 100644
--- a/e2fsck/e2fsck.h
+++ b/e2fsck/e2fsck.h
@@ -260,6 +260,7 @@ struct e2fsck_struct {
*/
int *invalid_inode_bitmap_flag;
int *invalid_block_bitmap_flag;
+ int *invalid_exclude_bitmap_flag;
int *invalid_inode_table_flag;
int invalid_bitmaps; /* There are invalid bitmaps/itable */

diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c
index 3587dff..90eeff1 100644
--- a/e2fsck/pass1.c
+++ b/e2fsck/pass1.c
@@ -2462,6 +2462,15 @@ static int process_bad_block(ext2_filsys fs,
}
return 0;
}
+ if (EXT2_HAS_COMPAT_FEATURE(fs->super,
+ EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP) &&
+ blk == ext2fs_exclude_bitmap_loc(fs, i)) {
+ if (fix_problem(ctx, PR_1_BB_BAD_BLOCK, pctx)) {
+ ctx->invalid_exclude_bitmap_flag[i]++;
+ ctx->invalid_bitmaps++;
+ }
+ return 0;
+ }
if (blk == ext2fs_inode_bitmap_loc(fs, i)) {
if (fix_problem(ctx, PR_1_IB_BAD_BLOCK, pctx)) {
ctx->invalid_inode_bitmap_flag[i]++;
@@ -2613,6 +2622,13 @@ static void handle_fs_bad_blocks(e2fsck_t ctx)
1, &new_blk);
ext2fs_block_bitmap_loc_set(fs, i, new_blk);
}
+ if (EXT2_HAS_COMPAT_FEATURE(fs->super,
+ EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP) &&
+ ctx->invalid_exclude_bitmap_flag[i]) {
+ new_table_block(ctx, first_block, i,
+ _("exclude bitmap"), 1, &new_blk);
+ ext2fs_exclude_bitmap_loc_set(fs, i, new_blk);
+ }
if (ctx->invalid_inode_bitmap_flag[i]) {
new_blk = ext2fs_inode_bitmap_loc(fs, i);
new_table_block(ctx, first_block, i, _("inode bitmap"),
@@ -2691,6 +2707,25 @@ static void mark_table_blocks(e2fsck_t ctx)

}
/*
+ * Mark block used for the exclude bitmap
+ */
+ if (EXT2_HAS_COMPAT_FEATURE(fs->super,
+ EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP) &&
+ ext2fs_exclude_bitmap_loc(fs, i)) {
+ if (ext2fs_test_block_bitmap2(ctx->block_found_map,
+ ext2fs_exclude_bitmap_loc(fs, i))) {
+ pctx.blk = ext2fs_exclude_bitmap_loc(fs, i);
+ if (fix_problem(ctx, PR_1_EB_CONFLICT, &pctx)) {
+ ctx->invalid_exclude_bitmap_flag[i]++;
+ ctx->invalid_bitmaps++;
+ }
+ } else {
+ ext2fs_mark_block_bitmap2(ctx->block_found_map,
+ ext2fs_exclude_bitmap_loc(fs, i));
+ }
+
+ }
+ /*
* Mark block used for the inode bitmap
*/
if (ext2fs_inode_bitmap_loc(fs, i)) {
diff --git a/e2fsck/pass1b.c b/e2fsck/pass1b.c
index 5ff92c2..4994596 100644
--- a/e2fsck/pass1b.c
+++ b/e2fsck/pass1b.c
@@ -910,6 +910,11 @@ static int check_if_fs_block(e2fsck_t ctx, blk64_t test_block)
(test_block == ext2fs_inode_bitmap_loc(fs, i)))
return 1;

+ if (EXT2_HAS_COMPAT_FEATURE(fs->super,
+ EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP) &&
+ test_block == ext2fs_exclude_bitmap_loc(fs, i))
+ return 1;
+
first_block += fs->super->s_blocks_per_group;
}
return 0;
diff --git a/e2fsck/pass5.c b/e2fsck/pass5.c
index 0dda1b3..416e325 100644
--- a/e2fsck/pass5.c
+++ b/e2fsck/pass5.c
@@ -257,6 +257,9 @@ redo_counts:
LE_CLSTR(i, old_desc_blk + old_desc_blocks-1)) ||
(new_desc_blk && EQ_CLSTR(i, new_desc_blk)) ||
EQ_CLSTR(i, ext2fs_block_bitmap_loc(fs, group)) ||
+ (EXT2_HAS_COMPAT_FEATURE(fs->super,
+ EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP) &&
+ (EQ_CLSTR(i, ext2fs_exclude_bitmap_loc(fs, group)))) ||
EQ_CLSTR(i, ext2fs_inode_bitmap_loc(fs, group)) ||
(GE_CLSTR(i, ext2fs_inode_table_loc(fs, group)) &&
LE_CLSTR(i, (ext2fs_inode_table_loc(fs, group) +
diff --git a/e2fsck/problem.h b/e2fsck/problem.h
index 3647f6e..f2b2663 100644
--- a/e2fsck/problem.h
+++ b/e2fsck/problem.h
@@ -243,6 +243,8 @@ struct problem_context {
/* Superblock has invalid MMP magic. */
#define PR_0_MMP_INVALID_MAGIC 0x000043

+/* Exclude bitmap not in group */
+#define PR_0_EB_NOT_GROUP 0x000104

/*
* Pass 1 errors
@@ -548,6 +550,10 @@ struct problem_context {
/* Quota inode is user visible */
#define PR_1_QUOTA_INODE_NOT_HIDDEN 0x010064

+/* Block bitmap conflicts with some other fs block */
+#define PR_1_EB_CONFLICT 0x010101
+
+
/*
* Pass 1b errors
*/
diff --git a/e2fsck/super.c b/e2fsck/super.c
index 36e7309..63fd218 100644
--- a/e2fsck/super.c
+++ b/e2fsck/super.c
@@ -604,6 +604,20 @@ void check_super_block(e2fsck_t ctx)
ctx->invalid_block_bitmap_flag[i]++;
ctx->invalid_bitmaps++;
}
+ if (EXT2_HAS_COMPAT_FEATURE(fs->super,
+ EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP) &&
+ ((ext2fs_exclude_bitmap_loc(fs, i) < first_block) ||
+ (ext2fs_exclude_bitmap_loc(fs, i) > last_block))) {
+ pctx.blk = ext2fs_exclude_bitmap_loc(fs, i);
+ if (fix_problem(ctx, PR_0_EB_NOT_GROUP, &pctx))
+ ext2fs_exclude_bitmap_loc_set(fs, i, 0);
+ }
+ if (EXT2_HAS_COMPAT_FEATURE(fs->super,
+ EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP) &&
+ ext2fs_exclude_bitmap_loc(fs, i) == 0) {
+ ctx->invalid_exclude_bitmap_flag[i]++;
+ ctx->invalid_bitmaps++;
+ }
if ((ext2fs_inode_bitmap_loc(fs, i) < first_block) ||
(ext2fs_inode_bitmap_loc(fs, i) > last_block)) {
pctx.blk = ext2fs_inode_bitmap_loc(fs, i);
@@ -637,6 +651,8 @@ void check_super_block(e2fsck_t ctx)
if (!ext2fs_group_desc_csum_verify(fs, i)) {
if (fix_problem(ctx, PR_0_GDT_CSUM, &pctx)) {
ext2fs_bg_flags_clear(fs, i, EXT2_BG_BLOCK_UNINIT);
+ ext2fs_bg_flags_clear(fs, i,
+ EXT2_BG_EXCLUDE_UNINIT);
ext2fs_bg_flags_clear(fs, i, EXT2_BG_INODE_UNINIT);
ext2fs_bg_itable_unused_set(fs, i, 0);
should_be = 1;
@@ -646,10 +662,12 @@ void check_super_block(e2fsck_t ctx)

if (!csum_flag &&
(ext2fs_bg_flags_test(fs, i, EXT2_BG_BLOCK_UNINIT) ||
+ ext2fs_bg_flags_test(fs, i, EXT2_BG_EXCLUDE_UNINIT) ||
ext2fs_bg_flags_test(fs, i, EXT2_BG_INODE_UNINIT) ||
ext2fs_bg_itable_unused(fs, i) != 0)) {
if (fix_problem(ctx, PR_0_GDT_UNINIT, &pctx)) {
ext2fs_bg_flags_clear(fs, i, EXT2_BG_BLOCK_UNINIT);
+ ext2fs_bg_flags_clear(fs, i, EXT2_BG_EXCLUDE_UNINIT);
ext2fs_bg_flags_clear(fs, i, EXT2_BG_INODE_UNINIT);
ext2fs_bg_itable_unused_set(fs, i, 0);
should_be = 1;
diff --git a/e2fsck/util.c b/e2fsck/util.c
index 06daf12..45fa14c 100644
--- a/e2fsck/util.c
+++ b/e2fsck/util.c
@@ -226,7 +226,8 @@ void e2fsck_read_bitmaps(e2fsck_t ctx)
fatal_error(ctx, 0);
}

- old_op = ehandler_operation(_("reading inode and block bitmaps"));
+ old_op = ehandler_operation(_("reading inode, exclude and block "
+ "bitmaps"));
retval = ext2fs_read_bitmaps(fs);
ehandler_operation(old_op);
if (retval) {
@@ -243,12 +244,14 @@ void e2fsck_write_bitmaps(e2fsck_t ctx)
errcode_t retval;
const char *old_op;

- old_op = ehandler_operation(_("writing block and inode bitmaps"));
+ old_op = ehandler_operation(_("writing block, exclude "
+ "and inode bitmaps"));
retval = ext2fs_write_bitmaps(fs);
ehandler_operation(old_op);
if (retval) {
com_err(ctx->program_name, retval,
- _("while rewriting block and inode bitmaps for %s"),
+ _("while rewriting block, exclude "
+ "and inode bitmaps for %s"),
ctx->device_name);
fatal_error(ctx, 0);
}
diff --git a/lib/ext2fs/check_desc.c b/lib/ext2fs/check_desc.c
index a6fcc45..881959c 100644
--- a/lib/ext2fs/check_desc.c
+++ b/lib/ext2fs/check_desc.c
@@ -68,6 +68,20 @@ errcode_t ext2fs_check_desc(ext2_filsys fs)
ext2fs_mark_block_bitmap2(bmap, blk);

/*
+ * Check to make sure the exclude bitmap for group is sane
+ */
+ if (EXT2_HAS_COMPAT_FEATURE(fs->super,
+ EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP)) {
+ blk = ext2fs_exclude_bitmap_loc(fs, i);
+ if (blk < first_block || blk > last_block ||
+ ext2fs_test_block_bitmap2(bmap, blk)) {
+ retval = EXT2_ET_GDESC_BAD_BLOCK_MAP;
+ goto errout;
+ }
+ ext2fs_mark_block_bitmap2(bmap, blk);
+ }
+
+ /*
* Check to make sure the inode bitmap for group is sane
*/
blk = ext2fs_inode_bitmap_loc(fs, i);
--
1.7.5.1


2011-10-23 09:11:06

by Yongqiang Yang

[permalink] [raw]
Subject: [PATCH 6/8] e2fsprogs: add exclude bitmap support in tune2fs

Exclude bitmap is a feature needed by ext4 snapshot. This patch
adds exclude bitmap support in tune2fs.

Signed-off-by: Yongqiang Yang <[email protected]>
---
misc/tune2fs.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 136 insertions(+), 3 deletions(-)

diff --git a/misc/tune2fs.c b/misc/tune2fs.c
index e2fdb4a..02edcd6 100644
--- a/misc/tune2fs.c
+++ b/misc/tune2fs.c
@@ -129,7 +129,9 @@ static void usage(void)
static __u32 ok_features[3] = {
/* Compat */
EXT3_FEATURE_COMPAT_HAS_JOURNAL |
- EXT2_FEATURE_COMPAT_DIR_INDEX,
+ EXT2_FEATURE_COMPAT_DIR_INDEX |
+ EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP,
+
/* Incompat */
EXT2_FEATURE_INCOMPAT_FILETYPE |
EXT3_FEATURE_INCOMPAT_EXTENTS |
@@ -149,7 +151,8 @@ static __u32 clear_ok_features[3] = {
/* Compat */
EXT3_FEATURE_COMPAT_HAS_JOURNAL |
EXT2_FEATURE_COMPAT_RESIZE_INODE |
- EXT2_FEATURE_COMPAT_DIR_INDEX,
+ EXT2_FEATURE_COMPAT_DIR_INDEX |
+ EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP,
/* Incompat */
EXT2_FEATURE_INCOMPAT_FILETYPE |
EXT4_FEATURE_INCOMPAT_FLEX_BG |
@@ -288,6 +291,81 @@ static int release_blocks_proc(ext2_filsys fs, blk64_t *blocknr,
}

/*
+ * Add exclude bitmaps to the filesystem
+ */
+static void add_exclude_bitmaps(ext2_filsys fs)
+{
+ char *buf = 0;
+ int retval, i;
+
+ retval = ext2fs_get_mem(strlen(fs->device_name) + 80, &buf);
+ if (retval) {
+ fputs(_("Allocating memory failed.\n"), stderr);
+ exit(1);
+ }
+ strcpy(buf, "exclude bitmap for ");
+ strcat(buf, fs->device_name);
+
+ retval = ext2fs_allocate_exclude_bitmap(fs, buf,
+ &fs->exclude_map);
+ ext2fs_free_mem(&buf);
+ if (retval) {
+ fputs(_("Allocating exclude bitmap failed.\n"), stderr);
+ exit(1);
+ }
+
+ retval = ext2fs_read_block_bitmap(fs);
+ if (retval) {
+ ext2fs_free_exclude_bitmap(fs->exclude_map);
+ fputs(_("Reading block bitmap failed.\n"), stderr);
+ exit(1);
+ }
+
+ retval = ext2fs_allocate_tables(fs);
+ if (retval) {
+ ext2fs_free_exclude_bitmap(fs->exclude_map);
+ fputs(_("Allocating filesystem exclude bitmaps "
+ "failed.\n"), stderr);
+ exit(1);
+ }
+ fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
+ ext2fs_mark_bb_dirty(fs);
+ ext2fs_mark_eb_dirty(fs);
+ ext2fs_mark_super_dirty(fs);
+}
+
+/*
+ * Remove the exclude bitmaps from the filesystem
+ */
+static void remove_exclude_bitmaps(ext2_filsys fs)
+{
+ struct ext2_group_desc *gd;
+ int retval, i;
+
+ retval = ext2fs_read_block_bitmap(fs);
+ if (retval) {
+ fputs(_("Reading block bitmap failed.\n"), stderr);
+ exit(1);
+ }
+
+ for (i = 0; i < fs->group_desc_count; i++) {
+ blk64_t exclude_bitmap;
+ gd = ext2fs_group_desc(fs, fs->group_desc, i);
+ exclude_bitmap = ext2fs_exclude_bitmap_loc(fs, i);
+ release_blocks_proc(fs, &exclude_bitmap, 0, 0, 0, NULL);
+ ext2fs_exclude_bitmap_loc_set(fs, i, 0);
+ ext2fs_bg_flags_clear(fs, i, EXT2_BG_EXCLUDE_UNINIT);
+ if(EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM))
+ ext2fs_group_desc_csum_set(fs, i);
+ }
+
+ fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
+ ext2fs_mark_bb_dirty(fs);
+ ext2fs_mark_super_dirty(fs);
+}
+
+/*
* Remove the journal inode from the filesystem
*/
static errcode_t remove_journal_inode(ext2_filsys fs)
@@ -363,6 +441,32 @@ static void request_fsck_afterwards(ext2_filsys fs)
printf(_("(and reboot afterwards!)\n"));
}

+static int verify_clean_fs(ext2_filsys fs, int compat, unsigned int mask,
+ int on)
+{
+ struct ext2_super_block *sb= fs->super;
+
+ if ((mount_flags & EXT2_MF_MOUNTED) &&
+ !(mount_flags & EXT2_MF_READONLY)) {
+ fprintf(stderr, _("The '%s' feature may only be "
+ "%s when the filesystem is\n"
+ "unmounted or mounted read-only.\n"),
+ e2p_feature2string(compat, mask),
+ on ? "set" : "cleared");
+ exit(1);
+ }
+ if (sb->s_feature_incompat &
+ EXT3_FEATURE_INCOMPAT_RECOVER) {
+ fprintf(stderr, _("The needs_recovery flag is set. "
+ "Please run e2fsck before %s\n"
+ "the '%s' flag.\n"),
+ on ? "setting" : "clearing",
+ e2p_feature2string(compat, mask));
+ exit(1);
+ }
+ return 1;
+}
+
/*
* Update the feature set as provided by the user.
*/
@@ -380,6 +484,10 @@ static int update_feature_set(ext2_filsys fs, char *features)
!((&sb->s_feature_compat)[(type)] & (mask)))
#define FEATURE_CHANGED(type, mask) ((mask) & \
(old_features[(type)] ^ (&sb->s_feature_compat)[(type)]))
+#define FEATURE_ON_SAFE(compat, mask) \
+ (FEATURE_ON(compat, mask) && verify_clean_fs(fs, compat, mask, 1))
+#define FEATURE_OFF_SAFE(compat, mask) \
+ (FEATURE_OFF(compat, mask) && verify_clean_fs(fs, compat, mask, 0))

old_features[E2P_FEATURE_COMPAT] = sb->s_feature_compat;
old_features[E2P_FEATURE_INCOMPAT] = sb->s_feature_incompat;
@@ -507,6 +615,16 @@ mmp_error:
sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
}

+ if (FEATURE_OFF_SAFE(E2P_FEATURE_COMPAT,
+ EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP)) {
+ remove_exclude_bitmaps(fs);
+ }
+
+ if (FEATURE_ON_SAFE(E2P_FEATURE_COMPAT,
+ EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP)) {
+ add_exclude_bitmaps(fs);
+ }
+
if (FEATURE_ON(E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_DIR_INDEX)) {
if (!sb->s_def_hash_version)
sb->s_def_hash_version = EXT2_HASH_HALF_MD4;
@@ -551,7 +669,7 @@ mmp_error:
for (i = 0; i < fs->group_desc_count; i++) {
gd = ext2fs_group_desc(fs, fs->group_desc, i);
if ((gd->bg_flags & EXT2_BG_INODE_ZEROED) == 0) {
- /*
+ /*
* XXX what we really should do is zap
* uninitialized inode tables instead.
*/
@@ -1318,6 +1436,10 @@ static int ext2fs_is_meta_block(ext2_filsys fs, blk_t blk)
group = ext2fs_group_of_blk(fs, blk);
if (ext2fs_block_bitmap_loc(fs, group) == blk)
return 1;
+ if (EXT2_HAS_COMPAT_FEATURE(fs->super,
+ EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP) &&
+ ext2fs_exclude_bitmap_loc(fs, group) == blk)
+ return 1;
if (ext2fs_inode_bitmap_loc(fs, group) == blk)
return 1;
return 0;
@@ -1536,6 +1658,17 @@ static int group_desc_scan_and_fix(ext2_filsys fs, ext2fs_block_bitmap bmap)
ext2fs_block_bitmap_loc_set(fs, i, new_blk);
}

+ if (EXT2_HAS_COMPAT_FEATURE(fs->super,
+ EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP)) {
+ blk = ext2fs_exclude_bitmap_loc(fs, i);
+ if (ext2fs_test_block_bitmap(bmap, blk)) {
+ new_blk = translate_block(blk);
+ if (!new_blk)
+ continue;
+ ext2fs_exclude_bitmap_loc_set(fs, i, new_blk);
+ }
+ }
+
blk = ext2fs_inode_bitmap_loc(fs, i);
if (ext2fs_test_block_bitmap2(bmap, blk)) {
new_blk = translate_block(blk);
--
1.7.5.1


2011-10-23 09:11:10

by Yongqiang Yang

[permalink] [raw]
Subject: [PATCH 8/8] e2fsprogs: add exclude bitmap support in debugfs

Exclude bitmap is a feature needed by ext4 snapshot. This patch
adds exclude bitmap support in debugfs.

Signed-off-by: Yongqiang Yang <[email protected]>
---
debugfs/debug_cmds.ct | 9 +++++
debugfs/debugfs.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++--
debugfs/set_fields.c | 1 +
lib/ext2fs/bitops.h | 49 +++++++++++++++++++++++++++++
4 files changed, 136 insertions(+), 4 deletions(-)

diff --git a/debugfs/debug_cmds.ct b/debugfs/debug_cmds.ct
index ea677da..2098f29 100644
--- a/debugfs/debug_cmds.ct
+++ b/debugfs/debug_cmds.ct
@@ -88,6 +88,15 @@ request do_setb, "Set a block's in-use flag",
request do_testb, "Test a block's in-use flag",
testb;

+request do_freee, "Clear a block's exclude flag",
+ freee;
+
+request do_sete, "Set a block's exclude flag",
+ sete;
+
+request do_teste, "Test a block's exclude flag",
+ teste;
+
request do_modify_inode, "Modify an inode by structure",
modify_inode, mi;

diff --git a/debugfs/debugfs.c b/debugfs/debugfs.c
index dd1435b..f839563 100644
--- a/debugfs/debugfs.c
+++ b/debugfs/debugfs.c
@@ -98,6 +98,11 @@ static void open_filesystem(char *device, int open_flags, blk64_t superblock,
com_err(device, retval, "while reading inode bitmap");
goto errout;
}
+ retval = ext2fs_read_exclude_bitmap(current_fs);
+ if (retval) {
+ com_err(device, retval, "while reading exclude bitmap");
+ goto errout;
+ }
retval = ext2fs_read_block_bitmap(current_fs);
if (retval) {
com_err(device, retval, "while reading block bitmap");
@@ -352,12 +357,14 @@ void do_show_super_stats(int argc, char *argv[])
EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
for (i = 0; i < current_fs->group_desc_count; i++) {
fprintf(out, " Group %2d: block bitmap at %llu, "
+ "exlcude bitmap at %llu, "
"inode bitmap at %llu, "
"inode table at %llu\n"
" %u free %s%s, "
"%u free %s, "
"%u used %s%s",
i, ext2fs_block_bitmap_loc(current_fs, i),
+ ext2fs_exclude_bitmap_loc(current_fs, i),
ext2fs_inode_bitmap_loc(current_fs, i),
ext2fs_inode_table_loc(current_fs, i),
ext2fs_bg_free_blocks_count(current_fs, i), units,
@@ -375,10 +382,12 @@ void do_show_super_stats(int argc, char *argv[])
ext2fs_bg_itable_unused(current_fs, i) != 1 ?
"inodes" : "inode");
first = 1;
- print_bg_opts(current_fs, i, EXT2_BG_INODE_UNINIT, "Inode not init",
- &first, out);
- print_bg_opts(current_fs, i, EXT2_BG_BLOCK_UNINIT, "Block not init",
- &first, out);
+ print_bg_opts(current_fs, i, EXT2_BG_INODE_UNINIT,
+ "Inode not init", &first, out);
+ print_bg_opts(current_fs, i, EXT2_BG_EXCLUDE_UNINIT,
+ "Exclude not init", &first, out);
+ print_bg_opts(current_fs, i, EXT2_BG_BLOCK_UNINIT,
+ "Block not init", &first, out);
if (gdt_csum) {
fprintf(out, "%sChecksum 0x%04x",
first ? " [":", ", ext2fs_bg_checksum(current_fs, i));
@@ -1074,6 +1083,70 @@ void do_testb(int argc, char *argv[])
}
}

+void do_freee(int argc, char *argv[])
+{
+ blk64_t block;
+ blk64_t count = 1;
+
+ if (!EXT2_HAS_COMPAT_FEATURE(current_fs->super,
+ EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP))
+ return;
+ if (common_block_args_process(argc, argv, &block, &count))
+ return;
+ if (check_fs_read_write(argv[0]))
+ return;
+ while (count-- > 0) {
+ if (!ext2fs_test_exclude_bitmap2(current_fs->exclude_map,
+ block))
+ com_err(argv[0], 0, "Warning: block %llu already "
+ "not excluded", block);
+ ext2fs_unmark_exclude_bitmap2(current_fs->exclude_map, block);
+ block++;
+ }
+ ext2fs_mark_eb_dirty(current_fs);
+}
+
+void do_sete(int argc, char *argv[])
+{
+ blk64_t block;
+ blk64_t count = 1;
+
+ if (!EXT2_HAS_COMPAT_FEATURE(current_fs->super,
+ EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP))
+ return;
+ if (common_block_args_process(argc, argv, &block, &count))
+ return;
+ if (check_fs_read_write(argv[0]))
+ return;
+ while (count-- > 0) {
+ if (ext2fs_test_exclude_bitmap2(current_fs->exclude_map, block))
+ com_err(argv[0], 0, "Warning: block %llu already "
+ "excluded", block);
+ ext2fs_mark_exclude_bitmap2(current_fs->exclude_map, block);
+ block++;
+ }
+ ext2fs_mark_eb_dirty(current_fs);
+}
+
+void do_teste(int argc, char *argv[])
+{
+ blk64_t block;
+ blk64_t count = 1;
+
+ if (!EXT2_HAS_COMPAT_FEATURE(current_fs->super,
+ EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP))
+ return;
+ if (common_block_args_process(argc, argv, &block, &count))
+ return;
+ while (count-- > 0) {
+ if (ext2fs_test_exclude_bitmap2(current_fs->exclude_map, block))
+ printf("Block %llu marked excluded\n", block);
+ else
+ printf("Block %llu not excluded\n", block);
+ block++;
+ }
+}
+
static void modify_u8(char *com, const char *prompt,
const char *format, __u8 *val)
{
diff --git a/debugfs/set_fields.c b/debugfs/set_fields.c
index d461275..7ecf7d8 100644
--- a/debugfs/set_fields.c
+++ b/debugfs/set_fields.c
@@ -205,6 +205,7 @@ static struct field_set_info inode_fields[] = {

static struct field_set_info ext2_bg_fields[] = {
{ "block_bitmap", &set_gd.bg_block_bitmap, NULL, 4, parse_uint },
+ { "exclude_bitmap", &set_gd.bg_exclude_bitmap_lo, NULL, 4, parse_uint },
{ "inode_bitmap", &set_gd.bg_inode_bitmap, NULL, 4, parse_uint },
{ "inode_table", &set_gd.bg_inode_table, NULL, 4, parse_uint },
{ "free_blocks_count", &set_gd.bg_free_blocks_count, NULL, 2, parse_uint },
diff --git a/lib/ext2fs/bitops.h b/lib/ext2fs/bitops.h
index 83a01e4..64d14f9 100644
--- a/lib/ext2fs/bitops.h
+++ b/lib/ext2fs/bitops.h
@@ -72,6 +72,13 @@ extern int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
blk_t block);
extern int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block);

+extern int ext2fs_mark_exclude_bitmap(ext2fs_exclude_bitmap bitmap,
+ blk_t block);
+extern int ext2fs_unmark_exclude_bitmap(ext2fs_exclude_bitmap bitmap,
+ blk_t block);
+extern int ext2fs_test_exclude_bitmap(ext2fs_exclude_bitmap bitmap,
+ blk_t block);
+
extern int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap, ext2_ino_t inode);
extern int ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode);
@@ -415,6 +422,27 @@ _INLINE_ int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap,
block);
}

+_INLINE_ int ext2fs_mark_exclude_bitmap(ext2fs_exclude_bitmap bitmap,
+ blk_t block)
+{
+ return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
+ block);
+}
+
+_INLINE_ int ext2fs_unmark_exclude_bitmap(ext2fs_exclude_bitmap bitmap,
+ blk_t block)
+{
+ return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
+ block);
+}
+
+_INLINE_ int ext2fs_test_exclude_bitmap(ext2fs_exclude_bitmap bitmap,
+ blk_t block)
+{
+ return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
+ block);
+}
+
_INLINE_ int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode)
{
@@ -534,6 +562,27 @@ _INLINE_ int ext2fs_test_block_bitmap2(ext2fs_block_bitmap bitmap,
block);
}

+_INLINE_ int ext2fs_mark_exclude_bitmap2(ext2fs_exclude_bitmap bitmap,
+ blk64_t block)
+{
+ return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
+ block);
+}
+
+_INLINE_ int ext2fs_unmark_exclude_bitmap2(ext2fs_exclude_bitmap bitmap,
+ blk64_t block)
+{
+ return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
+ block);
+}
+
+_INLINE_ int ext2fs_test_exclude_bitmap2(ext2fs_exclude_bitmap bitmap,
+ blk64_t block)
+{
+ return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
+ block);
+}
+
_INLINE_ int ext2fs_mark_inode_bitmap2(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode)
{
--
1.7.5.1


2011-10-23 09:11:08

by Yongqiang Yang

[permalink] [raw]
Subject: [PATCH 7/8] e2fsprogs: add exclude bitmap support in e2image

Exclude bitmap is a feature needed by ext4 snapshot. This patch
Adds exclude bitmap support in e2image.

Signed-off-by: Yongqiang Yang <[email protected]>
---
lib/ext2fs/e2image.h | 1 +
lib/ext2fs/ext2fs.h | 1 +
lib/ext2fs/imager.c | 22 ++++++++++++++++++++++
lib/ext2fs/rw_bitmaps.c | 16 ++++++++++++++++
misc/e2image.c | 22 ++++++++++++++++++++++
5 files changed, 62 insertions(+), 0 deletions(-)

diff --git a/lib/ext2fs/e2image.h b/lib/ext2fs/e2image.h
index c918529..61d7ff9 100644
--- a/lib/ext2fs/e2image.h
+++ b/lib/ext2fs/e2image.h
@@ -41,6 +41,7 @@ struct ext2_image_hdr {
__u32 offset_super; /* Byte offset of the sb and descriptors */
__u32 offset_inode; /* Byte offset of the inode table */
__u32 offset_inodemap; /* Byte offset of the inode bitmaps */
+ __u32 offset_excludemap; /* Byte offset of the exclude bitmaps */
__u32 offset_blockmap; /* Byte offset of the inode bitmaps */
__u32 offset_reserved[8];
};
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index d1f0d98..dab5ad7 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -526,6 +526,7 @@ typedef struct ext2_icount *ext2_icount_t;
*/
#define IMAGER_FLAG_INODEMAP 1
#define IMAGER_FLAG_SPARSEWRITE 2
+#define IMAGER_FLAG_EXCLUDEMAP 3

/*
* For checking structure magic numbers...
diff --git a/lib/ext2fs/imager.c b/lib/ext2fs/imager.c
index a0fb81e..c6b5af2 100644
--- a/lib/ext2fs/imager.c
+++ b/lib/ext2fs/imager.c
@@ -296,6 +296,17 @@ errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags)
itr = 1;
cnt = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
size = (EXT2_INODES_PER_GROUP(fs->super) / 8);
+ } else if (flags & IMAGER_FLAG_EXCLUDEMAP) {
+ if (!fs->exclude_map) {
+ retval = ext2fs_read_exclude_bitmap(fs);
+ if (retval)
+ return retval;
+ }
+ bmap = fs->exclude_map;
+ err = EXT2_ET_MAGIC_EXCLUDE_BITMAP;
+ itr = fs->super->s_first_data_block;
+ cnt = EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count;
+ size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
} else {
if (!fs->block_map) {
retval = ext2fs_read_block_bitmap(fs);
@@ -373,6 +384,17 @@ errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags)
itr = 1;
cnt = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
size = (EXT2_INODES_PER_GROUP(fs->super) / 8);
+ } else if (flags & IMAGER_FLAG_EXCLUDEMAP) {
+ if (!fs->exclude_map) {
+ retval = ext2fs_read_exclude_bitmap(fs);
+ if (retval)
+ return retval;
+ }
+ bmap = fs->exclude_map;
+ err = EXT2_ET_MAGIC_EXCLUDE_BITMAP;
+ itr = fs->super->s_first_data_block;
+ cnt = EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count;
+ size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
} else {
if (!fs->block_map) {
retval = ext2fs_read_block_bitmap(fs);
diff --git a/lib/ext2fs/rw_bitmaps.c b/lib/ext2fs/rw_bitmaps.c
index 3126733..6c8179b 100644
--- a/lib/ext2fs/rw_bitmaps.c
+++ b/lib/ext2fs/rw_bitmaps.c
@@ -274,6 +274,7 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block,
ext2fs_free_mem(&buf);

if (fs->flags & EXT2_FLAG_IMAGE_FILE) {
+ blk64_t exclude_blk;
blk = (fs->image_header->offset_inodemap / fs->blocksize);
ino_cnt = fs->super->s_inodes_count;
while (inode_nbytes > 0) {
@@ -294,10 +295,25 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block,
}
blk = (fs->image_header->offset_blockmap /
fs->blocksize);
+ exclude_blk = (fs->image_header->offset_excludemap /
+ fs->blocksize);
blk_cnt = (blk64_t)EXT2_CLUSTERS_PER_GROUP(fs->super) *
fs->group_desc_count;
while (block_nbytes > 0) {
if (do_exclude) {
+ retval = io_channel_read_blk64(fs->image_io,
+ exclude_blk++, 1, exclude_bitmap);
+ if (retval)
+ goto cleanup;
+ cnt = fs->blocksize << 3;
+ if (cnt > blk_cnt)
+ cnt = blk_cnt;
+ retval = ext2fs_set_exclude_bitmap_range2(
+ fs->exclude_map,
+ blk_itr, cnt, exclude_bitmap);
+ if (retval)
+ goto cleanup;
+
retval = EXT2_ET_EXCLUDE_BITMAP_READ;
goto cleanup;
}
diff --git a/misc/e2image.c b/misc/e2image.c
index 4cd834a..44a602c 100644
--- a/misc/e2image.c
+++ b/misc/e2image.c
@@ -187,6 +187,18 @@ static void write_image_file(ext2_filsys fs, int fd)
exit(1);
}

+ if (EXT2_HAS_COMPAT_FEATURE(fs->super,
+ EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP)) {
+ hdr.offset_excludemap = lseek(fd, 0, SEEK_CUR);
+ retval = ext2fs_image_bitmap_write(fs, fd,
+ IMAGER_FLAG_EXCLUDEMAP);
+ if (retval) {
+ com_err(program_name, retval, _("while writing "
+ "exclude bitmap"));
+ exit(1);
+ }
+ }
+
hdr.offset_inodemap = ext2fs_llseek(fd, 0, SEEK_CUR);
retval = ext2fs_image_bitmap_write(fs, fd, IMAGER_FLAG_INODEMAP);
if (retval) {
@@ -359,6 +371,16 @@ static void mark_table_blocks(ext2_filsys fs)
}

/*
+ * Mark block used for the exclude bitmap
+ */
+ if (EXT2_HAS_COMPAT_FEATURE(fs->super,
+ EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP) &&
+ ext2fs_exclude_bitmap_loc(fs, i)) {
+ ext2fs_mark_block_bitmap2(meta_block_map,
+ ext2fs_exclude_bitmap_loc(fs, i));
+ }
+
+ /*
* Mark block used for the inode bitmap
*/
if (ext2fs_inode_bitmap_loc(fs, i)) {
--
1.7.5.1


2011-10-23 09:11:03

by Yongqiang Yang

[permalink] [raw]
Subject: [PATCH 5/8] e2fsprogs: add exclude bitmap support in dumpe2fs

Exclude bitmap feature is needed by ext4 snapshot. This patch adds
exclude bitmap support in dumpe2fs.

Signed-off-by: Yongqiang Yang <[email protected]>
---
misc/dumpe2fs.c | 28 +++++++++++++++++++++++++++-
1 files changed, 27 insertions(+), 1 deletions(-)

diff --git a/misc/dumpe2fs.c b/misc/dumpe2fs.c
index df241c2..6b39575 100644
--- a/misc/dumpe2fs.c
+++ b/misc/dumpe2fs.c
@@ -119,6 +119,8 @@ static void print_bg_opts(ext2_filsys fs, dgrp_t i)

print_bg_opt(bg_flags, EXT2_BG_INODE_UNINIT, "INODE_UNINIT",
&first);
+ print_bg_opt(bg_flags, EXT2_BG_EXCLUDE_UNINIT, "EXCLUDE_UNINIT",
+ &first);
print_bg_opt(bg_flags, EXT2_BG_BLOCK_UNINIT, "BLOCK_UNINIT",
&first);
print_bg_opt(bg_flags, EXT2_BG_INODE_ZEROED, "ITABLE_ZEROED",
@@ -148,12 +150,13 @@ static void list_desc (ext2_filsys fs)
unsigned long i;
blk64_t first_block, last_block;
blk64_t super_blk, old_desc_blk, new_desc_blk;
- char *block_bitmap=NULL, *inode_bitmap=NULL;
+ char *block_bitmap = NULL, *exclude_bitmap = NULL, *inode_bitmap = NULL;
const char *units = _("blocks");
int inode_blocks_per_group, old_desc_blocks, reserved_gdt;
int block_nbytes, inode_nbytes;
int has_super;
blk64_t blk_itr = EXT2FS_B2C(fs, fs->super->s_first_data_block);
+ blk64_t exclude_itr = blk_itr;
ext2_ino_t ino_itr = 1;

if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
@@ -165,6 +168,8 @@ static void list_desc (ext2_filsys fs)

if (fs->block_map)
block_bitmap = malloc(block_nbytes);
+ if (fs->exclude_map)
+ exclude_bitmap = malloc(block_nbytes);
if (fs->inode_map)
inode_bitmap = malloc(inode_nbytes);

@@ -222,6 +227,14 @@ static void list_desc (ext2_filsys fs)
print_number(ext2fs_block_bitmap_loc(fs, i));
print_bg_rel_offset(fs, ext2fs_block_bitmap_loc(fs, i), 0,
first_block, last_block);
+ if (fs->super->s_feature_compat &
+ EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP) {
+ fputs(_(", snapshot bitmap at "), stdout);
+ print_number(ext2fs_exclude_bitmap_loc(fs, i));
+ print_bg_rel_offset(fs,
+ ext2fs_exclude_bitmap_loc(fs, i),
+ 0, first_block, last_block);
+ }
fputs(_(", Inode bitmap at "), stdout);
print_number(ext2fs_inode_bitmap_loc(fs, i));
print_bg_rel_offset(fs, ext2fs_inode_bitmap_loc(fs, i), 0,
@@ -252,6 +265,17 @@ static void list_desc (ext2_filsys fs)
fputc('\n', stdout);
blk_itr += fs->super->s_clusters_per_group;
}
+ if (exclude_bitmap) {
+ fputs(_(" Non-snapshot blocks: "), stdout);
+ ext2fs_get_exclude_bitmap_range2(fs->exclude_map,
+ exclude_itr, block_nbytes << 3, exclude_bitmap);
+ print_free(i, block_bitmap,
+ fs->super->s_clusters_per_group,
+ fs->super->s_first_data_block,
+ EXT2FS_CLUSTER_RATIO(fs));
+ fputc('\n', stdout);
+ exclude_itr += fs->super->s_blocks_per_group;
+ }
if (inode_bitmap) {
fputs(_(" Free inodes: "), stdout);
ext2fs_get_inode_bitmap_range2(fs->inode_map,
@@ -264,6 +288,8 @@ static void list_desc (ext2_filsys fs)
}
if (block_bitmap)
free(block_bitmap);
+ if (exclude_bitmap)
+ free(exclude_bitmap);
if (inode_bitmap)
free(inode_bitmap);
}
--
1.7.5.1


2011-10-23 13:55:04

by Amir G.

[permalink] [raw]
Subject: Re: [PATCH 2/8] e2fsprogs: add exclude bitmap support in mkfs

This patch is missing some "meat".
Some parts of the previous patch should probably belong to this one,
like the patch to lib/ext2fs/alloc_tables.c.
Please keep this in mind for the next post.

Sorry for not noticing this when reviewing in github,
Amir.

On Sun, Oct 23, 2011 at 9:21 AM, Yongqiang Yang <[email protected]> wrote:
> Exclude bitmap is needed by ext4 snapshot. This patch adds
> exclude bitmap support in mkfs.
>
> Signed-off-by: Yongqiang Yang <[email protected]>
> ---
> ?misc/mke2fs.c | ? ?1 +
> ?1 files changed, 1 insertions(+), 0 deletions(-)
>
> diff --git a/misc/mke2fs.c b/misc/mke2fs.c
> index 3dcb3b7..2dc28e7 100644
> --- a/misc/mke2fs.c
> +++ b/misc/mke2fs.c
> @@ -828,6 +828,7 @@ static void parse_extended_opts(struct ext2_super_block *param,
> ?static __u32 ok_features[3] = {
> ? ? ? ?/* Compat */
> ? ? ? ?EXT3_FEATURE_COMPAT_HAS_JOURNAL |
> + ? ? ? ? ? ? ? EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP |
> ? ? ? ? ? ? ? ?EXT2_FEATURE_COMPAT_RESIZE_INODE |
> ? ? ? ? ? ? ? ?EXT2_FEATURE_COMPAT_DIR_INDEX |
> ? ? ? ? ? ? ? ?EXT2_FEATURE_COMPAT_EXT_ATTR,
> --
> 1.7.5.1
>
>