2011-11-18 10:55:40

by Robin Dong

[permalink] [raw]
Subject: [PATCH 0/5 bigalloc] e2fsprogs: change unit of extent's ee_block and ee_len from block to cluster for bigalloc

From: Robin Dong <[email protected]>

Hi,

After the kernel patch series which change ee_block and ee_len (of extent) 's unit from "block" to "cluster",
We need e2fsprogs to support this too.


2011-11-18 10:55:46

by Robin Dong

[permalink] [raw]
Subject: [PATCH 2/5 bigalloc] debugfs: support cluster unit of ee_block and ee_len

From: Robin Dong <[email protected]>

Signed-off-by: Robin Dong <[email protected]>
---
debugfs/debugfs.c | 8 +++++---
lib/ext2fs/block.c | 15 +++++++++------
lib/ext2fs/bmap.c | 8 ++++++--
lib/ext2fs/extent.c | 13 ++++++++-----
4 files changed, 28 insertions(+), 16 deletions(-)

diff --git a/debugfs/debugfs.c b/debugfs/debugfs.c
index 1fb8f44..e9c0510 100644
--- a/debugfs/debugfs.c
+++ b/debugfs/debugfs.c
@@ -662,7 +662,8 @@ static void dump_extents(FILE *f, const char *prefix, ext2_ino_t ino,
physical_width,
extent.e_pblk,
physical_width,
- extent.e_pblk + (extent.e_len - 1),
+ extent.e_pblk + ((extent.e_len <<
+ current_fs->cluster_ratio_bits) - 1),
extent.e_len,
extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT ?
"Uninit" : "");
@@ -671,7 +672,7 @@ static void dump_extents(FILE *f, const char *prefix, ext2_ino_t ino,

if (extent.e_len == 0)
continue;
- else if (extent.e_len == 1)
+ else if (extent.e_len == 1 && current_fs->cluster_ratio_bits == 1)
fprintf(f,
"%s(%lld%s):%lld",
printed ? ", " : "",
@@ -688,7 +689,8 @@ static void dump_extents(FILE *f, const char *prefix, ext2_ino_t ino,
extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT ?
"[u]" : "",
extent.e_pblk,
- extent.e_pblk + (extent.e_len - 1));
+ extent.e_pblk + ((extent.e_len <<
+ current_fs->cluster_ratio_bits) - 1));
printed = 1;
}
if (printed)
diff --git a/lib/ext2fs/block.c b/lib/ext2fs/block.c
index 6a5c10d..212989d 100644
--- a/lib/ext2fs/block.c
+++ b/lib/ext2fs/block.c
@@ -337,6 +337,7 @@ errcode_t ext2fs_block_iterate3(ext2_filsys fs,
struct block_context ctx;
int limit;
blk64_t blk64;
+ blk64_t lblk;

EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);

@@ -459,14 +460,16 @@ errcode_t ext2fs_block_iterate3(ext2_filsys fs,
extent.e_lblk, extent.e_pblk,
extent.e_len, blockcnt);
#endif
- if (extent.e_lblk + extent.e_len <= blockcnt)
+ if (((extent.e_lblk + extent.e_len) <<
+ fs->cluster_ratio_bits) <= blockcnt)
continue;
- if (extent.e_lblk > blockcnt)
- blockcnt = extent.e_lblk;
- j = blockcnt - extent.e_lblk;
+ lblk = extent.e_lblk << fs->cluster_ratio_bits;
+ if (lblk > blockcnt)
+ blockcnt = lblk;
+ j = blockcnt - lblk;
blk += j;
- for (blockcnt = extent.e_lblk, j = 0;
- j < extent.e_len;
+ for (blockcnt = lblk, j = 0;
+ j < (extent.e_len << fs->cluster_ratio_bits);
blk++, blockcnt++, j++) {
new_blk = blk;
r = (*ctx.func)(fs, &new_blk, blockcnt,
diff --git a/lib/ext2fs/bmap.c b/lib/ext2fs/bmap.c
index 16d51e0..3e71fdf 100644
--- a/lib/ext2fs/bmap.c
+++ b/lib/ext2fs/bmap.c
@@ -175,6 +175,8 @@ static errcode_t extent_bmap(ext2_filsys fs, ext2_ino_t ino,
unsigned int offset;
errcode_t retval = 0;
blk64_t blk64 = 0;
+ blk64_t lblk = 0;
+ blk64_t len = 0;
int alloc = 0;

if (bmap_flags & BMAP_SET) {
@@ -192,8 +194,10 @@ static errcode_t extent_bmap(ext2_filsys fs, ext2_ino_t ino,
retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &extent);
if (retval)
return retval;
- offset = block - extent.e_lblk;
- if (block >= extent.e_lblk && (offset <= extent.e_len)) {
+ lblk = extent.e_lblk << fs->cluster_ratio_bits;
+ len = extent.e_len << fs->cluster_ratio_bits;
+ offset = block - lblk;
+ if (block >= lblk && (offset <= len)) {
*phys_blk = extent.e_pblk + offset;
if (ret_flags && extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT)
*ret_flags |= BMAP_RET_UNINIT;
diff --git a/lib/ext2fs/extent.c b/lib/ext2fs/extent.c
index eb096d6..32eb171 100644
--- a/lib/ext2fs/extent.c
+++ b/lib/ext2fs/extent.c
@@ -636,10 +636,13 @@ static errcode_t extent_goto(ext2_extent_handle_t handle,
while (1) {
if (handle->max_depth - handle->level == leaf_level) {
/* block is in this &extent */
- if ((blk >= extent.e_lblk) &&
- (blk < extent.e_lblk + extent.e_len))
+ if ((blk >= (extent.e_lblk <<
+ handle->fs->cluster_ratio_bits)) &&
+ (blk < ((extent.e_lblk + extent.e_len) <<
+ handle->fs->cluster_ratio_bits)))
return 0;
- if (blk < extent.e_lblk) {
+ if (blk < (extent.e_lblk <<
+ handle->fs->cluster_ratio_bits)) {
retval = ext2fs_extent_get(handle,
EXT2_EXTENT_PREV_SIB,
&extent);
@@ -665,9 +668,9 @@ static errcode_t extent_goto(ext2_extent_handle_t handle,
#ifdef DEBUG_GOTO_EXTENTS
dbg_print_extent("next", &extent);
#endif
- if (blk == extent.e_lblk)
+ if (blk == (extent.e_lblk << handle->fs->cluster_ratio_bits))
goto go_down;
- if (blk > extent.e_lblk)
+ if (blk > (extent.e_lblk << handle->fs->cluster_ratio_bits))
continue;

retval = ext2fs_extent_get(handle, EXT2_EXTENT_PREV_SIB,
--
1.7.3.2


2011-11-18 10:55:43

by Robin Dong

[permalink] [raw]
Subject: [PATCH 1/5 bigalloc] e2fsprogs: add tool e2wreck to corrupt fs for e2fsck testing

From: Robin Dong <[email protected]>

We need a tool to wreck filesystem to test e2fsck

Signed-off-by: Robin Dong <[email protected]>
---
misc/Makefile.in | 10 +-
misc/e2wreck.c | 549 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 611 insertions(+), 2 deletions(-)
create mode 100644 misc/e2wreck.c

diff --git a/misc/Makefile.in b/misc/Makefile.in
index cb3c6d9..c5597b4 100644
--- a/misc/Makefile.in
+++ b/misc/Makefile.in
@@ -26,7 +26,7 @@ INSTALL = @INSTALL@
@BLKID_CMT@FINDFS_LINK= findfs
@BLKID_CMT@FINDFS_MAN= findfs.8

-SPROGS= mke2fs badblocks tune2fs dumpe2fs $(BLKID_PROG) logsave \
+SPROGS= mke2fs badblocks tune2fs dumpe2fs e2wreck $(BLKID_PROG) logsave \
$(E2IMAGE_PROG) @FSCK_PROG@ e2undo
USPROGS= mklost+found filefrag e2freefrag $(UUIDD_PROG) $(E4DEFRAG_PROG)
SMANPAGES= tune2fs.8 mklost+found.8 mke2fs.8 dumpe2fs.8 badblocks.8 \
@@ -50,6 +50,7 @@ UUIDD_OBJS= uuidd.o
DUMPE2FS_OBJS= dumpe2fs.o
BADBLOCKS_OBJS= badblocks.o
E2IMAGE_OBJS= e2image.o
+E2WRECK_OBJS= e2wreck.o
FSCK_OBJS= fsck.o base_device.o ismounted.o
BLKID_OBJS= blkid.o
FILEFRAG_OBJS= filefrag.o
@@ -68,6 +69,7 @@ PROFILED_UUIDD_OBJS= profiled/uuidd.o
PROFILED_DUMPE2FS_OBJS= profiled/dumpe2fs.o
PROFILED_BADBLOCKS_OBJS= profiled/badblocks.o
PROFILED_E2IMAGE_OBJS= profiled/e2image.o
+PROFILED_E2WRECK_OBJS= profiled/e2wreck.o
PROFILED_FSCK_OBJS= profiled/fsck.o profiled/base_device.o \
profiled/ismounted.o
PROFILED_BLKID_OBJS= profiled/blkid.o
@@ -191,6 +193,10 @@ e2image.profiled: $(PROFILED_E2IMAGE_OBJS) $(PROFILED_DEPLIBS)
$(Q) $(CC) $(ALL_LDFLAGS) -g -pg -o e2image.profiled \
$(PROFILED_E2IMAGE_OBJS) $(PROFILED_LIBS) $(LIBINTL)

+e2wreck: $(E2WRECK_OBJS) $(DEPLIBS)
+ $(E) " LD $@"
+ $(Q) $(CC) $(ALL_LDFLAGS) -o e2wreck $(E2WRECK_OBJS) $(LIBS) $(LIBINTL)
+
e2undo: $(E2UNDO_OBJS) $(DEPLIBS)
$(E) " LD $@"
$(Q) $(CC) $(ALL_LDFLAGS) -o e2undo $(E2UNDO_OBJS) $(LIBS) $(LIBINTL)
@@ -556,7 +562,7 @@ clean:
$(FMANPAGES) profile.h \
base_device base_device.out mke2fs.static filefrag e2freefrag \
e2initrd_helper partinfo prof_err.[ch] default_profile.c \
- uuidd e2image tune2fs.static tst_ismounted fsck.profiled \
+ uuidd e2image e2wreck tune2fs.static tst_ismounted fsck.profiled \
blkid.profiled tune2fs.profiled e2image.profiled \
e2undo.profiled mke2fs.profiled dumpe2fs.profiled \
logsave.profiled filefrag.profiled uuidgen.profiled \
diff --git a/misc/e2wreck.c b/misc/e2wreck.c
new file mode 100644
index 0000000..2d7194b
--- /dev/null
+++ b/misc/e2wreck.c
@@ -0,0 +1,549 @@
+/*
+ * e2wreck.c --- Program which writes an image file backing up
+ * critical metadata for the filesystem.
+ *
+ * Copyright 2000, 2001 by Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#define _LARGEFILE_SOURCE
+#define _LARGEFILE64_SOURCE
+
+#include <fcntl.h>
+#include <grp.h>
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#else
+#endif
+#include <pwd.h>
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <assert.h>
+
+#include "ext2fs/ext2_fs.h"
+#include "ext2fs/ext2fs.h"
+#include "et/com_err.h"
+#include "uuid/uuid.h"
+#include "e2p/e2p.h"
+
+#include "../version.h"
+#include "nls-enable.h"
+
+#define QCOW_OFLAG_COPIED (1LL << 63)
+
+const char *program_name = "e2wreck";
+
+static void wreck_file_block_bitmap(ext2_filsys fs, const char *name, int flag);
+static void wreck_dirent(ext2_filsys fs, const char *name, int flag);
+static void wreck_zero_inode(ext2_filsys fs, const char *name, int flag);
+static void wreck_inode_field(ext2_filsys fs, const char *name, int flag);
+
+#define DIRENT_ZERO_DIR 1
+#define DIRENT_DUP_DOT 2
+#define DIRENT_INVALID_DOTDOT 3
+#define DIRENT_INVALID_RECLEN 4
+
+#define INODE_GENERATION 1
+#define INODE_MODE 2
+#define INODE_LINKS 3
+#define INODE_DTIME 4
+#define INODE_BLOCK 5
+#define INODE_BLOCKS 6
+#define INODE_SIZE 7
+#define EXTENT_BLOCK 8
+#define EXTENT_LEN 9
+
+struct command {
+ char name[256];
+ void (*func) (ext2_filsys fs, const char *name, int flag);
+ int flag;
+};
+
+struct command cmd_table[] = { {
+ .name = "ZERO_INODE",
+ .func = wreck_zero_inode,
+ .flag = 0,
+ }, {
+ .name = "CLEAR_BITMAP",
+ .func = wreck_file_block_bitmap,
+ .flag = 0,
+ }, {
+ .name = "INODE_GENERATION",
+ .func = wreck_inode_field,
+ .flag = INODE_GENERATION,
+ }, {
+ .name = "INODE_MODE",
+ .func = wreck_inode_field,
+ .flag = INODE_MODE,
+ }, {
+ .name = "INODE_SIZE",
+ .func = wreck_inode_field,
+ .flag = INODE_SIZE,
+ }, {
+ .name = "INODE_LINKS",
+ .func = wreck_inode_field,
+ .flag = INODE_LINKS,
+ }, {
+ .name = "INODE_DTIME",
+ .func = wreck_inode_field,
+ .flag = INODE_DTIME,
+ }, {
+ .name = "INODE_BLOCK",
+ .func = wreck_inode_field,
+ .flag = INODE_BLOCK,
+ }, {
+ .name = "INODE_BLOCKS",
+ .func = wreck_inode_field,
+ .flag = INODE_BLOCKS,
+ }, {
+ .name = "EXTENT_BLOCK",
+ .func = wreck_inode_field,
+ .flag = EXTENT_BLOCK,
+ }, {
+ .name = "EXTENT_LEN",
+ .func = wreck_inode_field,
+ .flag = EXTENT_LEN,
+ }, {
+ .name = "DIRENT_ZERO_DIR",
+ .func = wreck_dirent,
+ .flag = DIRENT_ZERO_DIR,
+ }, {
+ .name = "DIRENT_DUP_DOT",
+ .func = wreck_dirent,
+ .flag = DIRENT_DUP_DOT,
+ }, {
+ .name = "DIRENT_INVALID_DOTDOT",
+ .func = wreck_dirent,
+ .flag = DIRENT_INVALID_DOTDOT,
+ }, {
+ .name = "DIRENT_INVALID_RECLEN",
+ .func = wreck_dirent,
+ .flag = DIRENT_INVALID_RECLEN,
+ }
+};
+
+struct link_struct {
+ const char *name;
+ int namelen;
+ ext2_ino_t inode;
+ int flags;
+ struct ext2_dir_entry *prev;
+ int done;
+};
+
+static void usage(void)
+{
+ int i;
+ fprintf(stderr, _("Usage: %s OPTION file_name device_name\n"),
+ program_name);
+ fprintf(stderr, _(" option:\n"));
+ for (i = 0; i < sizeof(cmd_table) / sizeof(struct command); i++)
+ fprintf(stderr, _("\t%s\n"), cmd_table[i].name);
+ exit(1);
+}
+
+/*
+ * This routine is used whenever a command needs to turn a string into
+ * an inode.
+ */
+static ext2_ino_t string_to_inode(ext2_filsys fs, const char *str)
+{
+ ext2_ino_t ino;
+ int len = strlen(str);
+ char *end;
+ int retval;
+
+ /*
+ * If the string is of the form <ino>, then treat it as an
+ * inode number.
+ */
+ if ((len > 2) && (str[0] == '<') && (str[len-1] == '>')) {
+ ino = strtoul(str+1, &end, 0);
+ if (*end == '>')
+ return ino;
+ }
+
+ retval = ext2fs_namei(fs, 2, 2, str, &ino);
+ if (retval) {
+ com_err(str, retval, 0);
+ return 0;
+ }
+ return ino;
+}
+
+#define DUMP_LEAF_EXTENTS 0x01
+#define DUMP_NODE_EXTENTS 0x02
+#define DUMP_EXTENT_TABLE 0x04
+
+static void dump_extents(ext2_filsys fs, FILE *f, const char *prefix,
+ ext2_ino_t ino, int flags,
+ int logical_width, int physical_width)
+{
+ ext2_extent_handle_t handle;
+ struct ext2fs_extent extent;
+ struct ext2_extent_info info;
+ int op = EXT2_EXTENT_ROOT;
+ errcode_t errcode;
+ blk64_t i;
+
+ errcode = ext2fs_extent_open(fs, ino, &handle);
+ if (errcode)
+ return;
+
+ while (1) {
+ errcode = ext2fs_extent_get(handle, op, &extent);
+
+ if (errcode)
+ break;
+
+ op = EXT2_EXTENT_NEXT;
+
+ if (extent.e_flags & EXT2_EXTENT_FLAGS_SECOND_VISIT)
+ continue;
+
+ if (extent.e_flags & EXT2_EXTENT_FLAGS_LEAF) {
+ if ((flags & DUMP_LEAF_EXTENTS) == 0)
+ continue;
+ } else {
+ if ((flags & DUMP_NODE_EXTENTS) == 0)
+ continue;
+ }
+
+ errcode = ext2fs_extent_get_info(handle, &info);
+ if (errcode)
+ continue;
+
+ if (!(extent.e_flags & EXT2_EXTENT_FLAGS_LEAF)) {
+ if (extent.e_flags & EXT2_EXTENT_FLAGS_SECOND_VISIT)
+ continue;
+
+ continue;
+ }
+
+ if (extent.e_len == 0)
+ continue;
+
+ for (i = extent.e_lblk; i < extent.e_lblk + extent.e_len; i++) {
+ blk64_t b;
+ b = extent.e_pblk + i;
+ ext2fs_unmark_block_bitmap2(fs->block_map, b);
+ }
+ }
+}
+
+static void wreck_file_block_bitmap(ext2_filsys fs, const char *name, int flag)
+{
+ ext2_ino_t ino;
+ struct ext2_inode *inode_buf;
+ __u32 inode_size = EXT2_INODE_SIZE(fs->super);
+
+ inode_buf = (struct ext2_inode *) malloc(inode_size);
+ if (!inode_buf) {
+ printf("malloc inode_buf fail\n");
+ return;
+ }
+
+ ino = string_to_inode(fs, name);
+ if (!ino) {
+ printf("fetch inode fail\n");
+ return;
+ }
+
+ if (ext2fs_read_inode_full(fs, ino, inode_buf, inode_size)) {
+ printf("read inode fail\n");
+ goto out;
+ }
+
+ if (ext2fs_read_bitmaps(fs)) {
+ printf("read bitmap fail\n");
+ return;
+ }
+
+ dump_extents(fs, stdout, "{", ino, DUMP_LEAF_EXTENTS, 0, 0);
+ ext2fs_mark_bb_dirty(fs);
+
+ if (ext2fs_write_bitmaps(fs))
+ printf("write bitmap fail\n");
+
+out:
+ free(inode_buf);
+}
+
+static int clear_proc(struct ext2_dir_entry *dirent,
+ int offset,
+ int blocksize EXT2FS_ATTR((unused)),
+ char *buf EXT2FS_ATTR((unused)),
+ void *priv_data)
+{
+ dirent->inode = 0;
+
+ return DIRENT_CHANGED;
+}
+
+static int dup_proc(struct ext2_dir_entry *dirent,
+ int offset,
+ int blocksize EXT2FS_ATTR((unused)),
+ char *buf EXT2FS_ATTR((unused)),
+ void *priv_data)
+{
+ struct link_struct *ls = (struct link_struct *) priv_data;
+ struct ext2_dir_entry *prev;
+
+ prev = ls->prev;
+ ls->prev = dirent;
+
+ if ((dirent->name_len & 0xFF) == 2 &&
+ dirent->name[0] == '.' &&
+ dirent->name[1] == '.') {
+ dirent->name_len = 1;
+ return DIRENT_ABORT|DIRENT_CHANGED;
+ }
+ return 0;
+}
+
+static int invalid_dotdot_proc(struct ext2_dir_entry *dirent,
+ int offset,
+ int blocksize EXT2FS_ATTR((unused)),
+ char *buf EXT2FS_ATTR((unused)),
+ void *priv_data)
+{
+ struct link_struct *ls = (struct link_struct *) priv_data;
+ struct ext2_dir_entry *prev;
+
+ prev = ls->prev;
+ ls->prev = dirent;
+
+ if ((dirent->name_len & 0xFF) == 2 &&
+ dirent->name[0] == '.' &&
+ dirent->name[1] == '.') {
+ dirent->name[0] = 'a';
+ dirent->name[1] = 'b';
+ return DIRENT_ABORT|DIRENT_CHANGED;
+ }
+ return 0;
+}
+
+static int invalid_reclen_proc(struct ext2_dir_entry *dirent,
+ int offset,
+ int blocksize EXT2FS_ATTR((unused)),
+ char *buf EXT2FS_ATTR((unused)),
+ void *priv_data)
+{
+ struct link_struct *ls = (struct link_struct *) priv_data;
+ struct ext2_dir_entry *prev;
+
+ prev = ls->prev;
+ ls->prev = dirent;
+
+ if ((dirent->name_len & 0xFF) == 2 &&
+ dirent->name[0] == '1' &&
+ dirent->name[1] == '9') {
+ dirent->rec_len = 25;
+ return DIRENT_ABORT|DIRENT_CHANGED;
+ }
+ return 0;
+}
+
+static void wreck_dirent(ext2_filsys fs, const char *name, int flag)
+{
+ ext2_ino_t ino;
+ __u32 inode_size = EXT2_INODE_SIZE(fs->super);
+ struct link_struct ls;
+ int retval;
+
+ ino = string_to_inode(fs, name);
+ if (!ino) {
+ printf("fetch inode fail\n");
+ goto out;
+ }
+
+ switch (flag) {
+ case DIRENT_ZERO_DIR:
+ retval = ext2fs_dir_iterate(fs, ino,
+ DIRENT_FLAG_INCLUDE_EMPTY, 0, clear_proc, &ls);
+ case DIRENT_DUP_DOT:
+ retval = ext2fs_dir_iterate(fs, ino,
+ DIRENT_FLAG_INCLUDE_EMPTY, 0, dup_proc, &ls);
+ break;
+ case DIRENT_INVALID_DOTDOT:
+ retval = ext2fs_dir_iterate(fs, ino,
+ DIRENT_FLAG_INCLUDE_EMPTY, 0,
+ invalid_dotdot_proc, &ls);
+ break;
+ case DIRENT_INVALID_RECLEN:
+ retval = ext2fs_dir_iterate(fs, ino,
+ DIRENT_FLAG_INCLUDE_EMPTY, 0,
+ invalid_reclen_proc, &ls);
+ break;
+ default:
+ goto out;
+ }
+
+ if (retval) {
+ printf("iterate dir fail\n");
+ goto out;
+ }
+
+out:
+ return;
+}
+
+static void wreck_zero_inode(ext2_filsys fs, const char *name, int flag)
+{
+ ext2_ino_t ino;
+ struct ext2_inode *inode_buf;
+ __u32 inode_size = EXT2_INODE_SIZE(fs->super);
+
+ inode_buf = (struct ext2_inode *) malloc(inode_size);
+ if (!inode_buf) {
+ printf("malloc inode_buf fail\n");
+ return;
+ }
+
+ ino = string_to_inode(fs, name);
+ if (!ino) {
+ printf("fetch inode fail\n");
+ return;
+ }
+
+ memset(inode_buf, 0, inode_size);
+ if (ext2fs_write_inode_full(fs, ino, inode_buf, inode_size)) {
+ printf("write inode fail\n");
+ goto out;
+ }
+out:
+ free(inode_buf);
+}
+
+static void wreck_inode_field(ext2_filsys fs, const char *name, int field)
+{
+ ext2_ino_t ino;
+ struct ext2_inode *inode_buf;
+ struct ext3_extent *ex;
+ struct ext3_extent_header *eh;
+ __u32 inode_size = EXT2_INODE_SIZE(fs->super);
+ int i;
+
+ inode_buf = (struct ext2_inode *) malloc(inode_size);
+ if (!inode_buf) {
+ printf("malloc inode_buf fail\n");
+ return;
+ }
+
+ ino = string_to_inode(fs, name);
+ if (!ino) {
+ printf("fetch inode fail\n");
+ return;
+ }
+
+ if (ext2fs_read_inode_full(fs, ino, inode_buf,
+ sizeof(struct ext2_inode))) {
+ printf("read inode fail\n");
+ goto out;
+ }
+
+ switch (field) {
+ case INODE_GENERATION:
+ inode_buf->i_generation = 0;
+ break;
+ case INODE_MODE:
+ inode_buf->i_mode = 0;
+ break;
+ case INODE_LINKS:
+ inode_buf->i_links_count = 0;
+ break;
+ case INODE_DTIME:
+ inode_buf->i_dtime = 0;
+ break;
+ case INODE_BLOCK:
+ for (i = 0; i < EXT2_N_BLOCKS; i++)
+ inode_buf->i_block[i] = 0;
+ break;
+ case INODE_BLOCKS:
+ inode_buf->i_blocks = 0;
+ break;
+ case INODE_SIZE:
+ inode_buf->i_size = 0;
+ break;
+ case EXTENT_BLOCK:
+ eh = (struct ext3_extent_header *)(inode_buf->i_block);
+ ex = EXT_FIRST_EXTENT(eh);
+ ex->ee_block = 60;
+ break;
+ case EXTENT_LEN:
+ eh = (struct ext3_extent_header *)(inode_buf->i_block);
+ ex = EXT_FIRST_EXTENT(eh);
+ ex->ee_len = 60;
+ break;
+ default:
+ goto out;
+ }
+
+ if (ext2fs_write_inode_full(fs, ino, inode_buf, inode_size)) {
+ printf("write inode fail\n");
+ goto out;
+ }
+out:
+ free(inode_buf);
+}
+
+int main(int argc, char **argv)
+{
+ errcode_t retval;
+ ext2_filsys fs;
+ int open_flag = EXT2_FLAG_64BITS | EXT2_FLAG_RW | EXT2_FLAG_BB_DIRTY;
+ int ret = 0;
+ unsigned int i;
+
+#ifdef ENABLE_NLS
+ setlocale(LC_MESSAGES, "");
+ setlocale(LC_CTYPE, "");
+ bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
+ textdomain(NLS_CAT_NAME);
+#endif
+ fprintf(stderr, "e2wreck %s (%s)\n", E2FSPROGS_VERSION,
+ E2FSPROGS_DATE);
+ if (argc < 4) {
+ usage();
+ goto out;
+ }
+
+ if (argc && *argv)
+ program_name = *argv;
+
+ add_error_table(&et_ext2_error_table);
+
+ device_name = argv[3];
+
+ retval = ext2fs_open(device_name, open_flag, 0, 0,
+ unix_io_manager, &fs);
+ if (retval) {
+ com_err(program_name, retval, _("while trying to open %s"),
+ device_name);
+ fputs(_("Couldn't find valid filesystem superblock.\n"),
+ stdout);
+ exit(1);
+ }
+
+ for (i = 0; i < sizeof(cmd_table) / sizeof(struct command); i++)
+ if (!strcmp(cmd_table[i].name, argv[1]))
+ cmd_table[i].func(fs, argv[2], cmd_table[i].flag);
+
+ ext2fs_close(fs);
+out:
+ remove_error_table(&et_ext2_error_table);
+ return ret;
+}
--
1.7.3.2


2011-11-18 10:55:51

by Robin Dong

[permalink] [raw]
Subject: [PATCH 4/5 bigalloc] e2fsck: support cluster unit of ee_block and ee_len

From: Robin Dong <[email protected]>

Signed-off-by: Robin Dong <[email protected]>
---
e2fsck/pass1.c | 63 +++++++++++++++++++++++++++++++++++++++----------------
1 files changed, 44 insertions(+), 19 deletions(-)

diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c
index 532e132..70d26df 100644
--- a/e2fsck/pass1.c
+++ b/e2fsck/pass1.c
@@ -1741,6 +1741,8 @@ static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx,
{
struct ext2fs_extent extent;
blk64_t blk;
+ blk64_t elblk;
+ __u32 elen;
e2_blkcnt_t blockcnt;
unsigned int i;
int is_dir, is_leaf;
@@ -1753,6 +1755,8 @@ static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx,

pctx->errcode = ext2fs_extent_get(ehandle, EXT2_EXTENT_FIRST_SIB,
&extent);
+ elblk = extent.e_lblk << ctx->fs->cluster_ratio_bits;
+ elen = extent.e_len << ctx->fs->cluster_ratio_bits;
while (!pctx->errcode && info.num_entries-- > 0) {
is_leaf = extent.e_flags & EXT2_EXTENT_FLAGS_LEAF;
is_dir = LINUX_S_ISDIR(pctx->inode->i_mode);
@@ -1762,18 +1766,18 @@ static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx,
extent.e_pblk < ctx->fs->super->s_first_data_block ||
extent.e_pblk >= ext2fs_blocks_count(ctx->fs->super))
problem = PR_1_EXTENT_BAD_START_BLK;
- else if (extent.e_lblk < start_block)
+ else if (elblk < start_block)
problem = PR_1_OUT_OF_ORDER_EXTENTS;
else if (is_leaf &&
- (extent.e_pblk + extent.e_len) >
+ (extent.e_pblk + elen) >
ext2fs_blocks_count(ctx->fs->super))
problem = PR_1_EXTENT_ENDS_BEYOND;

if (problem) {
report_problem:
pctx->blk = extent.e_pblk;
- pctx->blk2 = extent.e_lblk;
- pctx->num = extent.e_len;
+ pctx->blk2 = elblk;
+ pctx->num = elen;
if (fix_problem(ctx, problem, pctx)) {
e2fsck_read_bitmaps(ctx);
pctx->errcode =
@@ -1785,6 +1789,10 @@ static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx,
pctx->errcode = ext2fs_extent_get(ehandle,
EXT2_EXTENT_CURRENT,
&extent);
+ elblk = extent.e_lblk <<
+ ctx->fs->cluster_ratio_bits;
+ elen = extent.e_len <<
+ ctx->fs->cluster_ratio_bits;
if (pctx->errcode == EXT2_ET_NO_CURRENT_NODE) {
pctx->errcode = 0;
break;
@@ -1805,11 +1813,13 @@ static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx,
goto report_problem;
return;
}
- scan_extent_node(ctx, pctx, pb, extent.e_lblk, ehandle);
+ scan_extent_node(ctx, pctx, pb, elblk, ehandle);
if (pctx->errcode)
return;
pctx->errcode = ext2fs_extent_get(ehandle,
EXT2_EXTENT_UP, &extent);
+ elblk = extent.e_lblk << ctx->fs->cluster_ratio_bits;
+ elen = extent.e_len << ctx->fs->cluster_ratio_bits;
if (pctx->errcode) {
pctx->str = "EXT2_EXTENT_UP";
return;
@@ -1835,12 +1845,12 @@ static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx,
(unsigned long) pctx->ino, type,
(unsigned long) pb->previous_block+1,
(unsigned long) extent.e_pblk,
- (unsigned long) extent.e_lblk,
- (unsigned long) extent.e_len);
+ (unsigned long) elblk,
+ (unsigned long) elen);
}
pb->fragmented = 1;
}
- while (is_dir && ++pb->last_db_block < extent.e_lblk) {
+ while (is_dir && ++pb->last_db_block < elblk) {
pctx->errcode = ext2fs_add_dir_block2(ctx->fs->dblist,
pb->ino, 0,
pb->last_db_block);
@@ -1850,8 +1860,7 @@ static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx,
goto failed_add_dir_block;
}
}
- for (blk = extent.e_pblk, blockcnt = extent.e_lblk, i = 0;
- i < extent.e_len;
+ for (blk = extent.e_pblk, blockcnt = elblk, i = 0; i < elen;
blk++, blockcnt++, i++) {
if (!(ctx->fs->cluster_ratio_bits &&
pb->previous_block &&
@@ -1865,7 +1874,8 @@ static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx,

pb->previous_block = blk;

- if (is_dir) {
+ if (is_dir && i < (pctx->inode->i_size /
+ ctx->fs->blocksize)) {
pctx->errcode = ext2fs_add_dir_block2(ctx->fs->dblist, pctx->ino, blk, blockcnt);
if (pctx->errcode) {
pctx->blk = blk;
@@ -1878,14 +1888,16 @@ static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx,
}
}
}
- if (is_dir && extent.e_len > 0)
+ if (is_dir && elen > 0)
pb->last_db_block = blockcnt - 1;
- pb->previous_block = extent.e_pblk + extent.e_len - 1;
- start_block = pb->last_block = extent.e_lblk + extent.e_len - 1;
+ pb->previous_block = extent.e_pblk + elen - 1;
+ start_block = pb->last_block = elblk + elen - 1;
next:
pctx->errcode = ext2fs_extent_get(ehandle,
EXT2_EXTENT_NEXT_SIB,
&extent);
+ elblk = extent.e_lblk << ctx->fs->cluster_ratio_bits;
+ elen = extent.e_len << ctx->fs->cluster_ratio_bits;
}
if (pctx->errcode == EXT2_ET_EXTENT_NO_NEXT)
pctx->errcode = 0;
@@ -1944,6 +1956,7 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
int dirty_inode = 0;
int extent_fs;
__u64 size;
+ __u32 last_cluster;

pb.ino = ino;
pb.num_blocks = 0;
@@ -2055,9 +2068,15 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
else if (nblock > (pb.last_block + 1))
bad_size = 1;
else if (nblock < (pb.last_block + 1)) {
- if (((pb.last_block + 1) - nblock) >
- fs->super->s_prealloc_dir_blocks)
- bad_size = 2;
+ if (fs->cluster_ratio_bits > 0) {
+ if ((EXT2FS_B2C(fs, pb.last_block) -
+ EXT2FS_B2C(fs, nblock)) > 1)
+ bad_size = 2;
+ } else {
+ if (((pb.last_block + 1) - nblock) >
+ fs->super->s_prealloc_dir_blocks)
+ bad_size = 2;
+ }
}
} else {
e2_blkcnt_t blkpg = ctx->blocks_per_page;
@@ -2068,8 +2087,14 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
(size < (__u64)pb.last_block * fs->blocksize) &&
(pb.last_block / blkpg * blkpg != pb.last_block ||
size < (__u64)(pb.last_block & ~(blkpg-1)) *fs->blocksize) &&
- !(inode->i_flags & EXT4_EOFBLOCKS_FL))
- bad_size = 3;
+ !(inode->i_flags & EXT4_EOFBLOCKS_FL)) {
+ last_cluster = EXT2FS_NUM_B2C(fs, (size + fs->blocksize
+ - 1) / fs->blocksize);
+ if (fs->cluster_ratio_bits <= 0 ||
+ last_cluster < ((pb.last_block + 1) >>
+ fs->cluster_ratio_bits))
+ bad_size = 3;
+ }
else if (!(extent_fs && (inode->i_flags & EXT4_EXTENTS_FL)) &&
size > ext2_max_sizes[fs->super->s_log_block_size])
/* too big for a direct/indirect-mapped file */
--
1.7.3.2


2011-11-18 10:55:54

by Robin Dong

[permalink] [raw]
Subject: [PATCH 5/5 bigalloc] e2fsprogs: make ext2fs_extent_set_bmap() to support cluster unit of ee_block and ee_len

From: Robin Dong <[email protected]>

Signed-off-by: Robin Dong <[email protected]>
---
lib/ext2fs/extent.c | 76 ++++++++++++++++++++++++++++++---------------------
1 files changed, 45 insertions(+), 31 deletions(-)

diff --git a/lib/ext2fs/extent.c b/lib/ext2fs/extent.c
index 32eb171..c646604 100644
--- a/lib/ext2fs/extent.c
+++ b/lib/ext2fs/extent.c
@@ -516,7 +516,7 @@ retry:
ix++;
end_blk = ext2fs_le32_to_cpu(ix->ei_block);
} else
- end_blk = path->end_blk;
+ end_blk = EXT2FS_B2C(handle->fs, path->end_blk);

extent->e_len = end_blk - extent->e_lblk;
}
@@ -854,7 +854,7 @@ static errcode_t extent_node_split(ext2_extent_handle_t handle)

/* save the position we were originally splitting... */
orig_height = info.max_depth - info.curr_level;
- orig_lblk = extent.e_lblk;
+ orig_lblk = EXT2FS_C2B(handle->fs, extent.e_lblk);

/* Is there room in the parent for a new entry? */
if (handle->level &&
@@ -1000,7 +1000,8 @@ static errcode_t extent_node_split(ext2_extent_handle_t handle)

extent.e_lblk = new_node_start;
extent.e_pblk = new_node_pblk;
- extent.e_len = handle->path[0].end_blk - extent.e_lblk;
+ extent.e_len = EXT2FS_B2C(handle->fs, handle->path[0].end_blk -
+ EXT2FS_C2B(handle->fs, extent.e_lblk));
retval = ext2fs_extent_replace(handle, 0, &extent);
if (retval)
goto done;
@@ -1157,6 +1158,7 @@ errcode_t ext2fs_extent_set_bmap(ext2_extent_handle_t handle,
struct ext2fs_extent extent, next_extent, prev_extent;
struct ext2fs_extent newextent;
struct ext2_extent_info info;
+ ext2_filsys fs = handle->fs;

EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE);

@@ -1182,7 +1184,7 @@ errcode_t ext2fs_extent_set_bmap(ext2_extent_handle_t handle,
if (physical) {
newextent.e_len = 1;
newextent.e_pblk = physical;
- newextent.e_lblk = logical;
+ newextent.e_lblk = EXT2FS_B2C(handle->fs, logical);
newextent.e_flags = EXT2_EXTENT_FLAGS_LEAF;
if (new_uninit)
newextent.e_flags |= EXT2_EXTENT_FLAGS_UNINIT;
@@ -1204,7 +1206,7 @@ errcode_t ext2fs_extent_set_bmap(ext2_extent_handle_t handle,
if ((retval = ext2fs_extent_get_info(handle, &info)))
return retval;
orig_height = info.max_depth - info.curr_level;
- orig_lblk = extent.e_lblk;
+ orig_lblk = EXT2FS_C2B(handle->fs, extent.e_lblk);

/* go to the logical spot we want to (re/un)map */
retval = ext2fs_extent_goto(handle, logical);
@@ -1267,7 +1269,8 @@ errcode_t ext2fs_extent_set_bmap(ext2_extent_handle_t handle,

/* check if already pointing to the requested physical */
if (mapped && (new_uninit == extent_uninit) &&
- (extent.e_pblk + (logical - extent.e_lblk) == physical)) {
+ (extent.e_pblk + (logical - EXT2FS_C2B(handle->fs, extent.e_lblk))
+ == physical)) {
#ifdef DEBUG
printf("physical block (at %llu) unchanged\n", logical);
#endif
@@ -1278,25 +1281,30 @@ errcode_t ext2fs_extent_set_bmap(ext2_extent_handle_t handle,
#ifdef DEBUG
printf("mapping unmapped logical block %llu\n", logical);
#endif
- if ((logical == extent.e_lblk + extent.e_len) &&
- (physical == extent.e_pblk + extent.e_len) &&
+ if ((logical == EXT2FS_C2B(fs, extent.e_lblk + extent.e_len)) &&
+ (physical == extent.e_pblk +
+ EXT2FS_C2B(fs, extent.e_len)) &&
(new_uninit == extent_uninit) &&
- ((int) extent.e_len < max_len-1)) {
+ ((int) EXT2FS_C2B(fs, extent.e_len) < max_len - 1)) {
extent.e_len++;
retval = ext2fs_extent_replace(handle, 0, &extent);
- } else if ((logical == extent.e_lblk - 1) &&
- (physical == extent.e_pblk - 1) &&
+ } else if ((logical == EXT2FS_C2B(fs, extent.e_lblk - 1)) &&
+ (physical == extent.e_pblk -
+ EXT2FS_CLUSTER_RATIO(fs)) &&
(new_uninit == extent_uninit) &&
- ((int) extent.e_len < max_len - 1)) {
+ ((int) EXT2FS_C2B(fs, extent.e_len) < max_len - 1)) {
extent.e_len++;
extent.e_lblk--;
- extent.e_pblk--;
+ extent.e_pblk -= EXT2FS_CLUSTER_RATIO(fs);
retval = ext2fs_extent_replace(handle, 0, &extent);
} else if (has_next &&
- (logical == next_extent.e_lblk - 1) &&
- (physical == next_extent.e_pblk - 1) &&
+ (logical == EXT2FS_C2B(fs,
+ next_extent.e_lblk - 1)) &&
+ (physical == next_extent.e_pblk -
+ EXT2FS_CLUSTER_RATIO(fs)) &&
(new_uninit == next_uninit) &&
- ((int) next_extent.e_len < max_len - 1)) {
+ ((int) EXT2FS_C2B(fs, next_extent.e_len) <
+ max_len - 1)) {
retval = ext2fs_extent_get(handle,
EXT2_EXTENT_NEXT_LEAF,
&next_extent);
@@ -1304,9 +1312,9 @@ errcode_t ext2fs_extent_set_bmap(ext2_extent_handle_t handle,
goto done;
next_extent.e_len++;
next_extent.e_lblk--;
- next_extent.e_pblk--;
+ next_extent.e_pblk -= EXT2FS_CLUSTER_RATIO(fs);
retval = ext2fs_extent_replace(handle, 0, &next_extent);
- } else if (logical < extent.e_lblk)
+ } else if (logical < EXT2FS_C2B(fs, extent.e_lblk))
retval = ext2fs_extent_insert(handle, 0, &newextent);
else
retval = ext2fs_extent_insert(handle,
@@ -1316,7 +1324,8 @@ errcode_t ext2fs_extent_set_bmap(ext2_extent_handle_t handle,
retval = ext2fs_extent_fix_parents(handle);
if (retval)
goto done;
- } else if ((logical == extent.e_lblk) && (extent.e_len == 1)) {
+ } else if ((logical == EXT2FS_C2B(fs, extent.e_lblk)) &&
+ (extent.e_len == 1)) {
#ifdef DEBUG
printf("(re/un)mapping only block in extent\n");
#endif
@@ -1333,23 +1342,27 @@ errcode_t ext2fs_extent_set_bmap(ext2_extent_handle_t handle,

if (retval)
goto done;
- } else if (logical == extent.e_lblk + extent.e_len - 1) {
+ } else if (logical == EXT2FS_C2B(fs, extent.e_lblk +
+ extent.e_len - 1)) {
#ifdef DEBUG
printf("(re/un)mapping last block in extent\n");
#endif
if (physical) {
if (has_next &&
- (logical == (next_extent.e_lblk - 1)) &&
- (physical == (next_extent.e_pblk - 1)) &&
+ (logical == (EXT2FS_C2B(fs,
+ next_extent.e_lblk - 1))) &&
+ (physical == (next_extent.e_pblk -
+ EXT2FS_CLUSTER_RATIO(fs))) &&
(new_uninit == next_uninit) &&
- ((int) next_extent.e_len < max_len - 1)) {
+ ((int) EXT2FS_C2B(fs, next_extent.e_len) <
+ max_len - 1)) {
retval = ext2fs_extent_get(handle,
EXT2_EXTENT_NEXT_LEAF, &next_extent);
if (retval)
goto done;
next_extent.e_len++;
next_extent.e_lblk--;
- next_extent.e_pblk--;
+ next_extent.e_pblk -= EXT2FS_CLUSTER_RATIO(fs);
retval = ext2fs_extent_replace(handle, 0,
&next_extent);
if (retval)
@@ -1370,18 +1383,19 @@ errcode_t ext2fs_extent_set_bmap(ext2_extent_handle_t handle,
retval = ext2fs_extent_replace(handle, 0, &extent);
if (retval)
goto done;
- } else if (logical == extent.e_lblk) {
+ } else if (logical == EXT2FS_C2B(fs, extent.e_lblk)) {
#ifdef DEBUG
printf("(re/un)mapping first block in extent\n");
#endif
if (physical) {
if (has_prev &&
- (logical == (prev_extent.e_lblk +
+ (logical == EXT2FS_C2B(fs, prev_extent.e_lblk +
prev_extent.e_len)) &&
(physical == (prev_extent.e_pblk +
- prev_extent.e_len)) &&
+ EXT2FS_C2B(fs, prev_extent.e_len))) &&
(new_uninit == prev_uninit) &&
- ((int) prev_extent.e_len < max_len-1)) {
+ ((int) EXT2FS_C2B(fs, prev_extent.e_len) <
+ max_len - 1)) {
retval = ext2fs_extent_get(handle,
EXT2_EXTENT_PREV_LEAF, &prev_extent);
if (retval)
@@ -1400,7 +1414,7 @@ errcode_t ext2fs_extent_set_bmap(ext2_extent_handle_t handle,
if (retval)
goto done;
}
- extent.e_pblk++;
+ extent.e_pblk += EXT2FS_CLUSTER_RATIO(fs);
extent.e_lblk++;
extent.e_len--;
retval = ext2fs_extent_replace(handle, 0, &extent);
@@ -1417,7 +1431,7 @@ errcode_t ext2fs_extent_set_bmap(ext2_extent_handle_t handle,
orig_length = extent.e_len;

/* shorten pre-split extent */
- extent.e_len = (logical - extent.e_lblk);
+ extent.e_len = (EXT2FS_B2C(fs, logical) - extent.e_lblk);
retval = ext2fs_extent_replace(handle, 0, &extent);
if (retval)
goto done;
@@ -1430,7 +1444,7 @@ errcode_t ext2fs_extent_set_bmap(ext2_extent_handle_t handle,
goto done;
}
/* add post-split extent */
- extent.e_pblk += extent.e_len + 1;
+ extent.e_pblk += EXT2FS_C2B(fs, extent.e_len + 1);
extent.e_lblk += extent.e_len + 1;
extent.e_len = orig_length - extent.e_len - 1;
retval = ext2fs_extent_insert(handle,
--
1.7.3.2


2011-11-18 10:55:49

by Robin Dong

[permalink] [raw]
Subject: [PATCH 3/5 bigalloc] e2fsprogs: make ext2fs_mkdir to support cluster unit of directory

From: Robin Dong <[email protected]>

Signed-off-by: Robin Dong <[email protected]>
---
lib/ext2fs/block.c | 3 ++-
lib/ext2fs/mkdir.c | 19 +++++++++++++++++++
misc/mke2fs.c | 8 ++++++++
3 files changed, 29 insertions(+), 1 deletions(-)

diff --git a/lib/ext2fs/block.c b/lib/ext2fs/block.c
index 212989d..468538a 100644
--- a/lib/ext2fs/block.c
+++ b/lib/ext2fs/block.c
@@ -469,7 +469,8 @@ errcode_t ext2fs_block_iterate3(ext2_filsys fs,
j = blockcnt - lblk;
blk += j;
for (blockcnt = lblk, j = 0;
- j < (extent.e_len << fs->cluster_ratio_bits);
+ j < (extent.e_len << fs->cluster_ratio_bits) &&
+ ((j * (fs->blocksize)) < (inode.i_size));
blk++, blockcnt++, j++) {
new_blk = blk;
r = (*ctx.func)(fs, &new_blk, blockcnt,
diff --git a/lib/ext2fs/mkdir.c b/lib/ext2fs/mkdir.c
index b12bf2d..de42107 100644
--- a/lib/ext2fs/mkdir.c
+++ b/lib/ext2fs/mkdir.c
@@ -40,7 +40,9 @@ errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum,
ext2_ino_t ino = inum;
ext2_ino_t scratch_ino;
blk64_t blk;
+ int i = 0;
char *block = 0;
+ char *empty_block = 0;

EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);

@@ -69,6 +71,13 @@ errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum,
goto cleanup;

/*
+ * Create a empty dir block
+ */
+ retval = ext2fs_new_dir_block(fs, 0, 0, &empty_block);
+ if (retval)
+ goto cleanup;
+
+ /*
* Get the parent's inode, if necessary
*/
if (parent != ino) {
@@ -98,6 +107,14 @@ errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum,
retval = ext2fs_write_dir_block(fs, blk, block);
if (retval)
goto cleanup;
+ if (fs->cluster_ratio_bits > 0) {
+ for (i = 1; i < (1 << fs->cluster_ratio_bits); i++) {
+ retval = ext2fs_write_dir_block(fs, blk + i,
+ empty_block);
+ if (retval)
+ goto cleanup;
+ }
+ }
retval = ext2fs_write_new_inode(fs, ino, &inode);
if (retval)
goto cleanup;
@@ -149,6 +166,8 @@ errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum,
cleanup:
if (block)
ext2fs_free_mem(&block);
+ if (empty_block)
+ ext2fs_free_mem(&empty_block);
return retval;

}
diff --git a/misc/mke2fs.c b/misc/mke2fs.c
index 0ef2531..b0d7025 100644
--- a/misc/mke2fs.c
+++ b/misc/mke2fs.c
@@ -392,6 +392,7 @@ static void create_lost_and_found(ext2_filsys fs)
unsigned int lpf_size = 0;
errcode_t retval;
ext2_ino_t ino;
+ struct ext2_inode inode;
const char *name = "lost+found";
int i;

@@ -410,6 +411,13 @@ static void create_lost_and_found(ext2_filsys fs)
exit(1);
}

+ if (fs->cluster_ratio_bits > 0) {
+ retval = ext2fs_read_inode(fs, ino, &inode);
+ inode.i_size = 16*1024;
+ ext2fs_write_inode(fs, ino, &inode);
+ return;
+ }
+
for (i=1; i < EXT2_NDIR_BLOCKS; i++) {
/* Ensure that lost+found is at least 2 blocks, so we always
* test large empty blocks for big-block filesystems. */
--
1.7.3.2


2011-11-19 03:31:48

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH 1/5 bigalloc] e2fsprogs: add tool e2wreck to corrupt fs for e2fsck testing

On Fri, Nov 18, 2011 at 06:55:26PM +0800, Robin Dong wrote:
> From: Robin Dong <[email protected]>
>
> We need a tool to wreck filesystem to test e2fsck
>
> Signed-off-by: Robin Dong <[email protected]>

I don't understand why you need this tool. Debugfs is a more general
tool that will do pretty much everything your proposed e2wreck tool
will do.

The one exception to this is low-level extent tree modifications ---
that functionality is there in the tst_extent program, which is a
debugging program I used when developing the extent support for
e2fsck. Go to the lib/ext2fs directory, and run "make tst_extents".
It's been on my todo list to get a more cleaner support for low-level
extent manipulation to debugfs, but I haven't gotten around to it,
since tst_extents is a serviceable enough, if hacky, substitute.

- Ted