2006-09-26 14:33:52

by Alexandre Ratchov

[permalink] [raw]
Subject: rfc: 2fsprogs update

hello,

i've updated e2fsprogs to be in sync with the latest kernel changes; here is
a summary of all changes:

01-head_20060918

this is a diff between 1.39 and a mercurial snapshot from sep 18,
2006. It's here just to allow people to apply the patch set on
e2fsprogs-1.39

02-percent

fixes division by zero in e2p_percent(), already posted few days ago

The following are the patches that Andreas posted, no changes:

03-inode_prealloc
04-extents
05-extents_htree
06-eacheck

The following are for 64bit support; they do the same as the patch set i
posted the last time but with various bugs fixed; they are reorganised and
cleaned up:

07-pblk_ondisk_blocknum

convert all 32bit on-disk block number definitions (currently __u32,
blk_t, unsigned long, unsigned int...) to pblk_t that is defined as
__u32. In this way we are sure that blk_t is used only in memory.
Later, this would allow to make blk_t 64bit without disturbing any
programs (this would just eat more momory and use 64bit arithmetic).


08-use_64bit_io

use 64bit offsets and block numbers (unsigned long long) in
*_read_blk, *_write_blk, and friends.

09-use_64bit_block_numbers

add the 64BIT incompat feature (make blk_t 64bit and add "_hi" bits
un super block and descruptors)

10-extents_48bit_block_numbers

makes extents code use *_hi bits: updated according Andreas'
comments.

11-desc_size

allow larger block group descriptors. The in memory ext2_group_desc
structure can have an arbitrary size (the on-disk on still have to
be a power of 2). This change is necessary in order to enlarge block
groups later.

12-move_block_number_hi_bits

moves group descriptors "*_hi" bits to the larger part of the
ext2_group_desc structure.

I've successfully tested them on a x84_64 arch with a 20TB device with the
latest kernel patches.

The complete e2fsprogs and kernel patch sets are available here:

http://www.bullopensource.org/ext4/20060926/

Comments?

-- Alexandre


2006-09-26 14:46:40

by Alexandre Ratchov

[permalink] [raw]
Subject: [patch 03/12] rfc: 2fsprogs update

Allow regular files to be preallocated on-disk up to the next multiple
of the system PAGE_SIZE without complaining about extra blocks.

Index: e2fsprogs/e2fsck/pass1.c
===================================================================
--- e2fsprogs.orig/e2fsck/pass1.c 2006-07-05 12:11:09.000000000 -0600
+++ e2fsprogs/e2fsck/pass1.c 2006-07-05 14:23:49.000000000 -0600
@@ -1486,9 +1486,14 @@ static void check_blocks(e2fsck_t ctx, s
bad_size = 2;
}
} else {
+ e2_blkcnt_t blkpg = getpagesize() / fs->blocksize;
+
size = EXT2_I_SIZE(inode);
if ((pb.last_block >= 0) &&
- (size < (__u64) pb.last_block * fs->blocksize))
+ /* allow allocated blocks to end of PAGE_SIZE */
+ (size < (__u64)pb.last_block * fs->blocksize) &&
+ (pb.last_block / blkpg * blkpg != pb.last_block ||
+ size < (__u64)(pb.last_block & ~(blkpg-1)) *fs->blocksize))
bad_size = 3;
else if (size > ext2_max_sizes[fs->super->s_log_block_size])
bad_size = 4;

Cheers, Andreas
--
Andreas Dilger
Principal Software Engineer
Cluster File Systems, Inc.


2006-09-26 14:45:50

by Alexandre Ratchov

[permalink] [raw]
Subject: [patch 02/12] rfc: 2fsprogs update

Signed-off-by: Alexandre Ratchov <[email protected]>

Index: e2fsprogs-1.39/lib/e2p/percent.c
===================================================================
--- e2fsprogs-1.39.orig/lib/e2p/percent.c 2006-09-20 12:07:05.000000000 +0200
+++ e2fsprogs-1.39/lib/e2p/percent.c 2006-09-20 12:36:32.000000000 +0200
@@ -7,25 +7,50 @@
* Public License
*/

+/*
#include "e2p.h"
+*/

#include <stdlib.h>

/*
* We work really hard to calculate this accurately, while avoiding
* an overflow. "Is there a hyphen in anal-retentive?" :-)
+ *
+ * -- "Yes there is, as in hair-splitting and nit-picking"
*/
unsigned int e2p_percent(int percent, unsigned int base)
{
- unsigned int mask = ~((1 << (sizeof(unsigned int) - 1) * 8) - 1);
+ unsigned hi, lo, q, r;

- if (100 % percent == 0)
- return base / (100 / percent);
- if (mask & base)
- return (base / 100) * percent;
- return base * percent / 100;
+ /*
+ * in order to avoid overflow we write 'base' as:
+ *
+ * base = hi * 2^16 + lo
+ *
+ * then we do all computations separately on 'hi' and 'lo'.
+ * By using the definition of division:
+ *
+ * precent * base = result * 100 + reminder
+ *
+ * (reminder < 100), we obtain the exact value of 'result'
+ * as follows:
+ */
+#define BITS 16
+#define MASK ((1 << BITS) - 1)
+
+ hi = percent * (base >> BITS);
+ lo = percent * (base & MASK);
+
+ q = ((hi / 100) << BITS) + lo / 100;
+ r = ((hi % 100) << BITS) + lo % 100;
+
+ return q + r / 100;
+#undef BITS
+#undef MASK
}

+
#ifdef DEBUG
#include <unistd.h>
#include <stdio.h>

2006-09-26 14:47:31

by Alexandre Ratchov

[permalink] [raw]
Subject: [patch 04/12] rfc: 2fsprogs update

from Andreas:

Support for checking 32-bit extents format inodes.

Clear the high 16 bits of extents and index entries, since the
extents patches did not do this explicitly. Some parts of this
code need fixing for checking > 32-bit block filesystems,
marked "XXX: 48-bit".

Verify extent headers in blocks, logical ordering of extents,
logical ordering of indexes.

Add explicit checking of {d,t,}indirect and index blocks to detect
corruption instead of implicitly doing this by checking the referred
blocks and only block-at-a-time correctness. This avoids incorrectly
invoking the very lengthy duplicate blocks pass for bad indirect/index
blocks. We may want to tune the "threshold" for how many errors make
a "bad" indirect/index block.

Add ability to split or remove extents in order to allow extent
reallocation during the duplicate blocks pass.

NOTE: also attachment for tests/f_extents/image.gz (do not gunzip)

Index: e2fsprogs-1.39/e2fsck/Makefile.in
===================================================================
--- e2fsprogs-1.39.orig/e2fsck/Makefile.in 2006-03-27 07:44:11.000000000 +0200
+++ e2fsprogs-1.39/e2fsck/Makefile.in 2006-09-18 17:23:02.000000000 +0200
@@ -261,6 +261,7 @@ super.o: $(srcdir)/super.c $(top_srcdir)
pass1.o: $(srcdir)/pass1.c $(srcdir)/e2fsck.h \
$(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \
$(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext2_fs.h \
+ $(top_srcdir)/lib/ext2fs/ext4_extents.h \
$(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/ext2fs/ext2_io.h \
$(top_builddir)/lib/ext2fs/ext2_err.h $(top_srcdir)/lib/ext2fs/bitops.h \
$(top_srcdir)/lib/blkid/blkid.h $(top_builddir)/lib/blkid/blkid_types.h \
Index: e2fsprogs-1.39/e2fsck/e2fsck.h
===================================================================
--- e2fsprogs-1.39.orig/e2fsck/e2fsck.h 2006-09-18 16:55:08.000000000 +0200
+++ e2fsprogs-1.39/e2fsck/e2fsck.h 2006-09-18 17:24:28.000000000 +0200
@@ -327,6 +327,7 @@ struct e2fsck_struct {
__u32 large_files;
__u32 fs_ext_attr_inodes;
__u32 fs_ext_attr_blocks;
+ __u32 extent_files;

time_t now;

Index: e2fsprogs-1.39/e2fsck/pass1.c
===================================================================
--- e2fsprogs-1.39.orig/e2fsck/pass1.c 2006-09-18 17:14:00.000000000 +0200
+++ e2fsprogs-1.39/e2fsck/pass1.c 2006-09-18 17:23:02.000000000 +0200
@@ -46,6 +46,7 @@

#include "e2fsck.h"
#include <ext2fs/ext2_ext_attr.h>
+#include <ext2fs/ext4_extents.h>

#include "problem.h"

@@ -79,7 +80,7 @@ static void adjust_extattr_refcount(e2fs
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, extent:1;
blk_t num_blocks;
blk_t max_blocks;
e2_blkcnt_t last_block;
@@ -89,6 +90,7 @@ struct process_block_struct {
struct problem_context *pctx;
ext2fs_block_bitmap fs_meta_blocks;
e2fsck_t ctx;
+ void *block_buf;
};

struct process_inode_block {
@@ -137,7 +139,7 @@ int e2fsck_pass1_check_device_inode(ext2
* this is a bogus device/fifo/socket
*/
if ((ext2fs_inode_data_blocks(fs, inode) != 0) ||
- (inode->i_flags & EXT2_INDEX_FL))
+ (inode->i_flags & (EXT2_INDEX_FL | EXT4_EXTENTS_FL)))
return 0;

/*
@@ -171,7 +173,7 @@ int e2fsck_pass1_check_symlink(ext2_fils
blk_t blocks;

if ((inode->i_size_high || inode->i_size == 0) ||
- (inode->i_flags & EXT2_INDEX_FL))
+ (inode->i_flags & (EXT2_INDEX_FL | EXT4_EXTENTS_FL)))
return 0;

blocks = ext2fs_inode_data_blocks(fs, inode);
@@ -389,7 +391,8 @@ void e2fsck_pass1(e2fsck_t ctx)
struct problem_context pctx;
struct scan_callback_struct scan_struct;
struct ext2_super_block *sb = ctx->fs->super;
- int imagic_fs;
+ struct ext4_extent_header *eh;
+ int imagic_fs, extent_fs;
int busted_fs_time = 0;
int inode_size;

@@ -423,6 +426,7 @@ void e2fsck_pass1(e2fsck_t ctx)
#undef EXT2_BPP

imagic_fs = (sb->s_feature_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES);
+ extent_fs = (sb->s_feature_incompat & EXT4_FEATURE_INCOMPAT_EXTENTS);

/*
* Allocate bitmaps structures
@@ -793,8 +797,7 @@ void e2fsck_pass1(e2fsck_t ctx)
check_blocks(ctx, &pctx, block_buf);
continue;
}
- }
- else if (LINUX_S_ISFIFO (inode->i_mode) &&
+ } else if (LINUX_S_ISFIFO (inode->i_mode) &&
e2fsck_pass1_check_device_inode(fs, inode)) {
check_immutable(ctx, &pctx);
check_size(ctx, &pctx);
@@ -806,21 +809,73 @@ void e2fsck_pass1(e2fsck_t ctx)
ctx->fs_sockets_count++;
} else
mark_inode_bad(ctx, ino);
- if (inode->i_block[EXT2_IND_BLOCK])
- ctx->fs_ind_count++;
- if (inode->i_block[EXT2_DIND_BLOCK])
- ctx->fs_dind_count++;
- if (inode->i_block[EXT2_TIND_BLOCK])
- ctx->fs_tind_count++;
- if (inode->i_block[EXT2_IND_BLOCK] ||
- inode->i_block[EXT2_DIND_BLOCK] ||
- inode->i_block[EXT2_TIND_BLOCK] ||
- inode->i_file_acl) {
- inodes_to_process[process_inode_count].ino = ino;
- inodes_to_process[process_inode_count].inode = *inode;
- process_inode_count++;
- } else
- check_blocks(ctx, &pctx, block_buf);
+
+ eh = (struct ext4_extent_header *)inode->i_block;
+ if ((inode->i_flags & EXT4_EXTENTS_FL)) {
+ if ((LINUX_S_ISREG(inode->i_mode) ||
+ LINUX_S_ISDIR(inode->i_mode)) &&
+ ext2fs_extent_header_verify(eh, EXT2_N_BLOCKS *
+ sizeof(__u32)) == 0) {
+ if (!extent_fs &&
+ fix_problem(ctx,PR_1_EXTENT_FEATURE,&pctx)){
+ sb->s_feature_incompat |=
+ EXT4_FEATURE_INCOMPAT_EXTENTS;
+ ext2fs_mark_super_dirty(fs);
+ extent_fs = 1;
+ }
+ } else if (fix_problem(ctx, PR_1_SET_EXTENT_FL, &pctx)){
+ inode->i_flags &= ~EXT4_EXTENTS_FL;
+ e2fsck_write_inode(ctx, ino, inode, "pass1");
+ }
+ } else if (extent_fs &&
+ (LINUX_S_ISREG(inode->i_mode) ||
+ LINUX_S_ISDIR(inode->i_mode)) &&
+ ext2fs_extent_header_verify(eh, EXT2_N_BLOCKS *
+ sizeof(__u32)) == 0 &&
+ fix_problem(ctx, PR_1_UNSET_EXTENT_FL, &pctx)) {
+ inode->i_flags |= EXT4_EXTENTS_FL;
+ e2fsck_write_inode(ctx, ino, inode, "pass1");
+ }
+ if (extent_fs && inode->i_flags & EXT4_EXTENTS_FL) {
+ ctx->extent_files++;
+ switch(eh->eh_depth) {
+ case 0:
+ break;
+ case 1:
+ ctx->fs_ind_count++;
+ break;
+ case 2:
+ ctx->fs_dind_count++;
+ break;
+ default:
+ ctx->fs_tind_count++;
+ break;
+ }
+ if (eh->eh_depth > 0) {
+ inodes_to_process[process_inode_count].ino = ino;
+ inodes_to_process[process_inode_count].inode = *inode;
+ process_inode_count++;
+ } else {
+ check_blocks(ctx, &pctx, block_buf);
+ }
+ } else {
+ if (inode->i_block[EXT2_IND_BLOCK])
+ ctx->fs_ind_count++;
+ if (inode->i_block[EXT2_DIND_BLOCK])
+ ctx->fs_dind_count++;
+ if (inode->i_block[EXT2_TIND_BLOCK])
+ ctx->fs_tind_count++;
+ if (inode->i_block[EXT2_IND_BLOCK] ||
+ inode->i_block[EXT2_DIND_BLOCK] ||
+ inode->i_block[EXT2_TIND_BLOCK] ||
+ inode->i_file_acl) {
+ inodes_to_process[process_inode_count].ino = ino;
+ inodes_to_process[process_inode_count].inode = *inode;
+ process_inode_count++;
+ } else {
+ check_blocks(ctx, &pctx, block_buf);
+ }
+ }

if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
return;
@@ -1363,6 +1418,132 @@ static int handle_htree(e2fsck_t ctx, st
return 0;
}

+/* sort 0 to the end of the list so we can exit early */
+static EXT2_QSORT_TYPE verify_ind_cmp(const void *a, const void *b)
+{
+ const __u32 blk_a = *(__u32 *)a - 1, blk_b = *(__u32 *)b - 1;
+
+ return blk_b > blk_a ? -1 : blk_a - blk_b;
+}
+
+/* Verify whether an indirect block is sane. If it has multiple references
+ * to the same block, or if it has a large number of bad or duplicate blocks
+ * chances are that it is corrupt and we should just clear it instead of
+ * trying to salvage it.
+ * NOTE: this needs to get a copy of the blocks, since it reorders them */
+static int e2fsck_ind_block_verify(struct process_block_struct *p,
+ void *block_buf, int buflen)
+{
+ __u32 blocks[EXT2_N_BLOCKS], *indir = block_buf;
+ int num_indir = buflen / sizeof(*indir);
+ int i, bad = 0;
+
+ if (num_indir == EXT2_N_BLOCKS) {
+ memcpy(blocks, block_buf, buflen);
+ indir = blocks;
+ }
+ qsort(indir, num_indir, sizeof(*indir), verify_ind_cmp);
+
+ for (i = 0; i < num_indir; i++) {
+ if (indir[i] == 0)
+ break;
+
+ /* bad block number, or duplicate block */
+ if (indir[i] < p->ctx->fs->super->s_first_data_block ||
+ indir[i] > p->ctx->fs->super->s_blocks_count ||
+ ext2fs_fast_test_block_bitmap(p->ctx->block_found_map,
+ indir[i]))
+ bad++;
+
+ /* shouldn't reference the same block twice within a block */
+ if (i > 0 && indir[i] == indir[i - 1])
+ bad++;
+ }
+
+ if ((num_indir <= EXT2_N_BLOCKS && bad > 4) || bad > 8)
+ return PR_1_INDIRECT_BAD;
+
+#if DEBUG_E2FSCK
+ /* For debugging, clobber buffer to ensure it doesn't appear sane */
+ memset(indir, 0xca, buflen);
+#endif
+ return 0;
+}
+
+/* we have already verified the header in e2fsck_pass1() before calling this */
+static int e2fsck_ext_block_verify(struct process_block_struct *p,
+ void *block_buf, int buflen)
+{
+ struct ext4_extent_header *eh = block_buf;
+ e2fsck_t ctx = p->ctx;
+ struct problem_context *pctx = p->pctx;
+ int i, bad = 0, changed = 0;
+
+ if (eh->eh_depth == 0) {
+ struct ext4_extent *ex = EXT_FIRST_EXTENT(eh), *ex_prev = NULL;
+
+ for (i = 0; i < eh->eh_entries; i++, ex++) {
+ /* FIXME: 48-bit check for s_blocks_count_hi */
+ if (ex->ee_start_hi && fix_problem(ctx, PR_1_EXTENT_HI,
+ pctx)) {
+ ex->ee_start_hi = 0;
+ changed++;
+ }
+
+ if (ext2fs_extent_verify(ctx->fs, ex, ex_prev, NULL,0)){
+ pctx->blkcount = ex->ee_start;
+ pctx->num = ex->ee_len;
+ pctx->blk = ex->ee_block;
+ if (fix_problem(ctx, PR_1_EXTENT_BAD, pctx)) {
+ ext2fs_extent_remove(eh, ex);
+ i--; ex--; /* check next (moved) item */
+ changed++;
+ continue;
+ } else {
+ bad++;
+ }
+ }
+
+ ex_prev = ex;
+ }
+ } else {
+ struct ext4_extent_idx *ix =EXT_FIRST_INDEX(eh), *ix_prev =NULL;
+
+ for (i = 0; i < eh->eh_entries; i++, ix++) {
+ /* FIXME: 48-bit check for s_blocks_count_hi */
+ if (ix->ei_leaf_hi && fix_problem(ctx, PR_1_EXTENT_HI,
+ pctx)) {
+ ix->ei_leaf_hi = ix->ei_unused = 0;
+ changed++;
+ }
+
+ if (ext2fs_extent_index_verify(ctx->fs, ix, ix_prev)) {
+ pctx->blkcount = ix->ei_leaf;;
+ pctx->num = i;
+ pctx->blk = ix->ei_block;
+ if (fix_problem(ctx, PR_1_EXTENT_IDX_BAD,pctx)){
+ ext2fs_extent_index_remove(eh, ix);
+ i--; ix--; /* check next (moved) item */
+ changed++;
+ continue;
+ } else {
+ bad++;
+ }
+ }
+
+ ix_prev = ix;
+ }
+ }
+
+ if ((eh->eh_entries < 8 && bad > 2) || bad > 6)
+ return PR_1_EXTENT_BAD;
+
+ if (changed)
+ return PR_1_EXTENT_HI;
+
+ return 0;
+}
+
/*
* This subroutine is called on each inode to account for all of the
* blocks used by that inode.
@@ -1385,6 +1566,7 @@ static void check_blocks(e2fsck_t ctx, s
pb.suppress = 0; pb.clear = 0;
pb.fragmented = 0;
pb.compressed = 0;
+ pb.extent = !!(inode->i_flags & EXT4_EXTENTS_FL);
pb.previous_block = 0;
pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
pb.is_reg = LINUX_S_ISREG(inode->i_mode);
@@ -1392,6 +1574,7 @@ static void check_blocks(e2fsck_t ctx, s
pb.inode = inode;
pb.pctx = pctx;
pb.ctx = ctx;
+ pb.block_buf = block_buf;
pctx->ino = ino;
pctx->errcode = 0;

@@ -1410,10 +1593,27 @@ static void check_blocks(e2fsck_t ctx, s
if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf))
pb.num_blocks++;

- if (ext2fs_inode_has_valid_blocks(inode))
- pctx->errcode = ext2fs_block_iterate2(fs, ino,
- pb.is_dir ? BLOCK_FLAG_HOLE : 0,
- block_buf, process_block, &pb);
+ if (ext2fs_inode_has_valid_blocks(inode)) {
+ int problem = 0;
+
+ if (pb.extent)
+ problem = e2fsck_ext_block_verify(&pb, inode->i_block,
+ sizeof(inode->i_block));
+ else
+ problem = e2fsck_ind_block_verify(&pb, inode->i_block,
+ sizeof(inode->i_block));
+ if (problem == PR_1_EXTENT_HI) {
+ dirty_inode++;
+ problem = 0;
+ }
+
+ if (problem && fix_problem(ctx, problem, pctx))
+ pb.clear = 1;
+ else
+ pctx->errcode = ext2fs_block_iterate2(fs, ino,
+ pb.is_dir ? BLOCK_FLAG_HOLE : 0,
+ block_buf, process_block, &pb);
+ }
end_problem_latch(ctx, PR_LATCH_BLOCK);
end_problem_latch(ctx, PR_LATCH_TOOBIG);
if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
@@ -1577,6 +1777,9 @@ static char *describe_illegal_block(ext2
}
#endif

+#define IND_BLKCNT(_b) ((_b) == BLOCK_COUNT_IND || (_b) == BLOCK_COUNT_DIND ||\
+ (_b) == BLOCK_COUNT_TIND)
+
/*
* This is a helper function for check_blocks().
*/
@@ -1655,7 +1858,8 @@ static int process_block(ext2_filsys fs,
* file be contiguous. (Which can never be true for really
* big files that are greater than a block group.)
*/
- if (!HOLE_BLKADDR(p->previous_block)) {
+ if (!HOLE_BLKADDR(p->previous_block) &&
+ !(p->extent && IND_BLKCNT(blockcnt))) {
if (p->previous_block+1 != blk)
p->fragmented = 1;
}
@@ -1672,6 +1876,32 @@ static int process_block(ext2_filsys fs,
blk >= fs->super->s_blocks_count)
problem = PR_1_ILLEGAL_BLOCK_NUM;

+ if (!problem && IND_BLKCNT(blockcnt) && p->ino != EXT2_RESIZE_INO) {
+ if (p->extent) {
+ problem = ext2fs_read_ext_block(ctx->fs, blk,
+ p->block_buf);
+ if (problem)
+ problem = PR_1_BLOCK_ITERATE;
+ else
+ problem = e2fsck_ext_block_verify(p,
+ p->block_buf,
+ fs->blocksize);
+ if (problem == PR_1_EXTENT_HI)
+ problem = ext2fs_write_ext_block(ctx->fs, blk,
+ p->block_buf);
+
+ } else {
+ problem = ext2fs_read_ind_block(ctx->fs, blk,
+ p->block_buf);
+ if (problem)
+ problem = PR_1_BLOCK_ITERATE;
+ else
+ problem = e2fsck_ind_block_verify(p,
+ p->block_buf,
+ fs->blocksize);
+ }
+ }
+
if (problem) {
p->num_illegal_blocks++;
if (!p->suppress && (p->num_illegal_blocks % 12) == 0) {
Index: e2fsprogs-1.39/e2fsck/pass2.c
===================================================================
--- e2fsprogs-1.39.orig/e2fsck/pass2.c 2006-03-19 03:34:00.000000000 +0100
+++ e2fsprogs-1.39/e2fsck/pass2.c 2006-09-18 17:23:02.000000000 +0200
@@ -280,7 +280,16 @@ void e2fsck_pass2(e2fsck_t ctx)
ext2fs_mark_super_dirty(fs);
}
}
-
+
+ if (!ctx->extent_files &&
+ (sb->s_feature_incompat & EXT4_FEATURE_INCOMPAT_EXTENTS)) {
+ if (fs->flags & EXT2_FLAG_RW) {
+ sb->s_feature_incompat &=
+ ~EXT4_FEATURE_INCOMPAT_EXTENTS;
+ ext2fs_mark_super_dirty(fs);
+ }
+ }
+
#ifdef RESOURCE_TRACK
if (ctx->options & E2F_OPT_TIME2) {
e2fsck_clear_progbar(ctx);
Index: e2fsprogs-1.39/e2fsck/problem.c
===================================================================
--- e2fsprogs-1.39.orig/e2fsck/problem.c 2006-03-09 04:02:50.000000000 +0100
+++ e2fsprogs-1.39/e2fsck/problem.c 2006-09-18 17:23:02.000000000 +0200
@@ -774,6 +774,46 @@ static struct e2fsck_problem problem_tab
N_("@a in @i %i has a hash (%N) which is @n (must be 0)\n"),
PROMPT_CLEAR, PR_PREEN_OK },

+ /* indirect block corrupt */
+ { PR_1_INDIRECT_BAD,
+ N_("@i %i has corrupt indirect block\n"),
+ PROMPT_CLEAR, PR_PREEN_OK },
+
+ /* inode has extents, superblock missing INCOMPAT_EXTENTS feature */
+ { PR_1_EXTENT_FEATURE,
+ N_("@i %i is in extent format, but @S is missing EXTENTS feature\n"),
+ PROMPT_FIX, PR_PREEN_OK },
+
+ /* inode has EXTENTS_FL set, but is not an extent inode */
+ { PR_1_SET_EXTENT_FL,
+ N_("@i %i has EXTENT_FL set, but is not in extents format\n"),
+ PROMPT_FIX, PR_PREEN_OK },
+
+ /* inode missing EXTENTS_FL, but is an extent inode */
+ { PR_1_UNSET_EXTENT_FL,
+ N_("@i %i missing EXTENT_FL, but is in extents format\n"),
+ PROMPT_FIX, PR_PREEN_OK },
+
+ /* extent index corrupt */
+ { PR_1_EXTENT_BAD,
+ N_("@i %i has corrupt extent at @b %b (logical %B) length %N\n"),
+ PROMPT_CLEAR, PR_PREEN_OK },
+
+ /* extent index corrupt */
+ { PR_1_EXTENT_IDX_BAD,
+ N_("@i %i has corrupt extent index at @b %b (logical %B) entry %N\n"),
+ PROMPT_CLEAR, PR_PREEN_OK },
+
+ /* extent has high 16 bits set */
+ { PR_1_EXTENT_HI,
+ N_("High 16 bits of extent/index block set\n"),
+ PROMPT_CLEAR, PR_LATCH_EXTENT_HI | PR_PREEN_OK | PR_NO_OK },
+
+ /* extent has high 16 bits set header */
+ { PR_1_EXTENT_HI_LATCH,
+ N_("@i %i has high 16 bits of extent/index block set\n"),
+ PROMPT_CLEAR, PR_PREEN_OK | PR_NO_OK },
+
/* Pass 1b errors */

/* Pass 1B: Rescan for duplicate/bad blocks */
@@ -1498,6 +1538,7 @@ static struct latch_descr pr_latch_info[
{ PR_LATCH_LOW_DTIME, PR_1_ORPHAN_LIST_REFUGEES, 0 },
{ PR_LATCH_TOOBIG, PR_1_INODE_TOOBIG, 0 },
{ PR_LATCH_OPTIMIZE_DIR, PR_3A_OPTIMIZE_DIR_HEADER, PR_3A_OPTIMIZE_DIR_END },
+ { PR_LATCH_EXTENT_HI, PR_1_EXTENT_HI_LATCH, 0 },
{ -1, 0, 0 },
};

Index: e2fsprogs-1.39/e2fsck/problem.h
===================================================================
--- e2fsprogs-1.39.orig/e2fsck/problem.h 2006-03-09 03:58:28.000000000 +0100
+++ e2fsprogs-1.39/e2fsck/problem.h 2006-09-18 17:23:02.000000000 +0200
@@ -38,6 +38,7 @@ struct problem_context {
#define PR_LATCH_LOW_DTIME 0x0070 /* Latch for pass1 orphaned list refugees */
#define PR_LATCH_TOOBIG 0x0080 /* Latch for file to big errors */
#define PR_LATCH_OPTIMIZE_DIR 0x0090 /* Latch for optimize directories */
+#define PR_LATCH_EXTENT_HI 0x00A0 /* Latch for optimize directories */

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

@@ -449,6 +450,30 @@ struct problem_context {
/* wrong EA hash value */
#define PR_1_ATTR_HASH 0x010054

+/* indirect block corrupt */
+#define PR_1_INDIRECT_BAD 0x010059
+
+/* wrong EXT4_FEATURE_INCOMPAT_EXTENTS flag */
+#define PR_1_EXTENT_FEATURE 0x010060
+
+/* EXT4_EXTENT_FL flag set on non-extent file */
+#define PR_1_SET_EXTENT_FL 0x010061
+
+/* EXT4_EXTENT_FL flag not set extent file */
+#define PR_1_UNSET_EXTENT_FL 0x010062
+
+/* extent index corrupt */
+#define PR_1_EXTENT_BAD 0x010063
+
+/* extent index corrupt */
+#define PR_1_EXTENT_IDX_BAD 0x010064
+
+/* extent/index has high 16 bits set - header */
+#define PR_1_EXTENT_HI 0x010065
+
+/* extent/index has high 16 bits set */
+#define PR_1_EXTENT_HI_LATCH 0x010066
+
/*
* Pass 1b errors
*/
Index: e2fsprogs-1.39/lib/ext2fs/Makefile.in
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/Makefile.in 2006-04-09 04:02:02.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/Makefile.in 2006-09-18 17:23:02.000000000 +0200
@@ -35,6 +35,7 @@ OBJS= $(DEBUGFS_LIB_OBJS) $(RESIZE_LIB_O
dir_iterate.o \
expanddir.o \
ext_attr.o \
+ extents.o \
finddev.o \
flushb.o \
freefs.o \
@@ -90,6 +91,7 @@ SRCS= ext2_err.c \
$(srcdir)/dupfs.c \
$(srcdir)/expanddir.c \
$(srcdir)/ext_attr.c \
+ $(srcdir)/extents.c \
$(srcdir)/fileio.c \
$(srcdir)/finddev.c \
$(srcdir)/flushb.c \
@@ -134,7 +136,8 @@ SRCS= ext2_err.c \
$(srcdir)/tst_getsize.c \
$(srcdir)/tst_iscan.c

-HFILES= bitops.h ext2fs.h ext2_io.h ext2_fs.h ext2_ext_attr.h
+HFILES= bitops.h ext2fs.h ext2_io.h ext2_fs.h ext2_ext_attr.h block.h \
+ ext4_extents.h
HFILES_IN= ext2_err.h ext2_types.h

LIBRARY= libext2fs
@@ -372,6 +375,10 @@ ext_attr.o: $(srcdir)/ext_attr.c $(srcdi
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2_ext_attr.h \
$(srcdir)/ext2fs.h $(srcdir)/ext2_fs.h $(top_srcdir)/lib/et/com_err.h \
$(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
+extents.o: $(srcdir)/extents.c $(srcdir)/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext4_extents.h \
+ $(srcdir)/ext2fs.h $(srcdir)/ext2_fs.h $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
fileio.o: $(srcdir)/fileio.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext2_fs.h $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
@@ -516,6 +523,7 @@ unlink.o: $(srcdir)/unlink.c $(srcdir)/e
$(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
valid_blk.o: $(srcdir)/valid_blk.c $(srcdir)/ext2_fs.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
+ $(srcdir)/ext4_extents.h \
$(srcdir)/ext2_fs.h $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
$(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
version.o: $(srcdir)/version.c $(srcdir)/ext2_fs.h \
Index: e2fsprogs-1.39/lib/ext2fs/block.c
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/block.c 2005-09-06 11:40:14.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/block.c 2006-09-18 17:23:02.000000000 +0200
@@ -17,24 +17,16 @@

#include "ext2_fs.h"
#include "ext2fs.h"
+#include "block.h"

-struct block_context {
- ext2_filsys fs;
- int (*func)(ext2_filsys fs,
- blk_t *blocknr,
- e2_blkcnt_t bcount,
- blk_t ref_blk,
- int ref_offset,
- void *priv_data);
- e2_blkcnt_t bcount;
- int bsize;
- int flags;
- errcode_t errcode;
- char *ind_buf;
- char *dind_buf;
- char *tind_buf;
- void *priv_data;
-};
+#ifdef EXT_DEBUG
+void show_inode(ext2_ino_t ino)
+{
+ printf("inode: %u\n", ino);
+}
+#else
+#define show_inode(ino) do { } while (0)
+#endif

static int block_iterate_ind(blk_t *ind_block, blk_t ref_block,
int ref_offset, struct block_context *ctx)
@@ -276,29 +268,30 @@ errcode_t ext2fs_block_iterate2(ext2_fil
void *priv_data)
{
int i;
- int got_inode = 0;
int ret = 0;
blk_t blocks[EXT2_N_BLOCKS]; /* directory data blocks */
struct ext2_inode inode;
errcode_t retval;
struct block_context ctx;
int limit;
+ struct ext4_extent_header *eh;

EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);

+ ctx.errcode = ext2fs_read_inode(fs, ino, &inode);
+ if (ctx.errcode)
+ return ctx.errcode;
+
/*
* Check to see if we need to limit large files
*/
if (flags & BLOCK_FLAG_NO_LARGE) {
- ctx.errcode = ext2fs_read_inode(fs, ino, &inode);
- if (ctx.errcode)
- return ctx.errcode;
- got_inode = 1;
if (!LINUX_S_ISDIR(inode.i_mode) &&
(inode.i_size_high != 0))
return EXT2_ET_FILE_TOO_BIG;
}

+ /* The in-memory inode may have been changed by e2fsck */
retval = ext2fs_get_blocks(fs, ino, blocks);
if (retval)
return retval;
@@ -325,10 +318,6 @@ errcode_t ext2fs_block_iterate2(ext2_fil
*/
if ((fs->super->s_creator_os == EXT2_OS_HURD) &&
!(flags & BLOCK_FLAG_DATA_ONLY)) {
- ctx.errcode = ext2fs_read_inode(fs, ino, &inode);
- if (ctx.errcode)
- goto abort_exit;
- got_inode = 1;
if (inode.osd1.hurd1.h_i_translator) {
ret |= (*ctx.func)(fs,
&inode.osd1.hurd1.h_i_translator,
@@ -338,7 +327,20 @@ errcode_t ext2fs_block_iterate2(ext2_fil
goto abort_exit;
}
}
-
+
+ /* Iterate over normal data blocks with extents. We checked that
+ * EXT4_EXTENTS_FL and EXT4_EXT_MAGIC match in e2fsck_pass1(). */
+ if (inode.i_flags & EXT4_EXTENTS_FL) {
+ eh = (struct ext4_extent_header *)blocks;
+ if (eh->eh_magic == EXT4_EXT_MAGIC) {
+ show_inode(ino);
+ ret |= block_iterate_extents(eh, 0, 0, &ctx);
+ } else {
+ ret |= BLOCK_ERROR;
+ }
+ goto abort_exit;
+ }
+
/*
* Iterate over normal data blocks
*/
@@ -373,11 +375,6 @@ errcode_t ext2fs_block_iterate2(ext2_fil

abort_exit:
if (ret & BLOCK_CHANGED) {
- if (!got_inode) {
- retval = ext2fs_read_inode(fs, ino, &inode);
- if (retval)
- return retval;
- }
for (i=0; i < EXT2_N_BLOCKS; i++)
inode.i_block[i] = blocks[i];
retval = ext2fs_write_inode(fs, ino, &inode);
Index: e2fsprogs-1.39/lib/ext2fs/block.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ e2fsprogs-1.39/lib/ext2fs/block.h 2006-09-18 17:23:02.000000000 +0200
@@ -0,0 +1,36 @@
+/*
+ * block.h --- header for block iteration in block.c, extent.c
+ *
+ * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include "ext4_extents.h"
+
+struct block_context {
+ ext2_filsys fs;
+ int (*func)(ext2_filsys fs,
+ blk_t *blocknr,
+ e2_blkcnt_t bcount,
+ blk_t ref_blk,
+ int ref_offset,
+ void *priv_data);
+ e2_blkcnt_t bcount;
+ int bsize;
+ int flags;
+ errcode_t errcode;
+ char *ind_buf;
+ char *dind_buf;
+ char *tind_buf;
+ void *priv_data;
+};
+
+/* Internal function, in extent.c */
+extern int block_iterate_extents(struct ext4_extent_header *eh,
+ blk_t ref_block,
+ int ref_offset EXT2FS_ATTR((unused)),
+ struct block_context *ctx);
Index: e2fsprogs-1.39/lib/ext2fs/bmap.c
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/bmap.c 2005-09-06 11:40:14.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/bmap.c 2006-09-18 17:23:02.000000000 +0200
@@ -17,6 +17,7 @@

#include "ext2_fs.h"
#include "ext2fs.h"
+#include "ext4_extents.h"

#if defined(__GNUC__) && !defined(NO_INLINE_FUNCS)
#define _BMAP_INLINE_ __inline__
@@ -31,6 +32,64 @@ extern errcode_t ext2fs_bmap(ext2_filsys

#define inode_bmap(inode, nr) ((inode)->i_block[(nr)])

+/* see also block_iterate_extents() */
+static errcode_t block_bmap_extents(struct ext4_extent_header *eh,
+ ext2_filsys fs, blk_t block,
+ blk_t *phys_blk)
+{
+ struct ext4_extent *ex;
+ errcode_t ret = 0;
+ int i;
+
+ if (eh->eh_depth == 0) {
+ ex = EXT_FIRST_EXTENT(eh);
+ for (i = 0; i < eh->eh_entries; i++, ex++) {
+ if ((ex->ee_block <= block) &&
+ (block < ex->ee_block + ex->ee_len)) {
+ *phys_blk = ex->ee_start +
+ (block - ex->ee_block);
+ return 0;
+ }
+ }
+
+ return BLOCK_ERROR;
+ } else {
+ struct ext4_extent_idx *ix;
+ char *block_buf;
+
+ ret = ext2fs_get_mem(fs->blocksize, &block_buf);
+ if (ret)
+ return ret;
+
+ ix = EXT_FIRST_INDEX(eh);
+ for (i = 0; i < eh->eh_entries; i++, ix++) {
+ struct ext4_extent_header *nh;
+
+ if (ix->ei_block < block)
+ continue;
+
+ ret = io_channel_read_blk(fs->io, ix->ei_leaf, 1,
+ block_buf);
+ if (ret) {
+ ret = BLOCK_ERROR;
+ goto free_buf;
+ }
+
+ nh = (struct ext4_extent_header *)block_buf;
+ if (nh->eh_magic != EXT4_EXT_MAGIC) {
+ ret = BLOCK_ERROR;
+ goto free_buf;
+ }
+
+ ret = block_bmap_extents(nh, fs, block, phys_blk);
+ }
+
+ free_buf:
+ ext2fs_free_mem(&block_buf);
+ }
+ return ret;
+}
+
static _BMAP_INLINE_ errcode_t block_ind_bmap(ext2_filsys fs, int flags,
blk_t ind, char *block_buf,
int *blocks_alloc,
@@ -155,6 +214,17 @@ errcode_t ext2fs_bmap(ext2_filsys fs, ex
return retval;
inode = &inode_buf;
}
+
+ if (inode->i_flags & EXT4_EXTENTS_FL) {
+ struct ext4_extent_header * eh;
+ eh = (struct ext4_extent_header *)&inode_bmap(inode, 0);
+ if (eh->eh_magic == EXT4_EXT_MAGIC)
+ retval = block_bmap_extents(eh, fs, block, phys_blk);
+ else
+ retval = BLOCK_ERROR;
+ goto done;
+ }
+
addr_per_block = (blk_t) fs->blocksize >> 2;

if (!block_buf) {
Index: e2fsprogs-1.39/lib/ext2fs/ext2_err.et.in
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/ext2_err.et.in 2005-09-06 11:40:14.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/ext2_err.et.in 2006-09-18 17:23:02.000000000 +0200
@@ -296,5 +296,17 @@ ec EXT2_ET_RESIZE_INODE_CORRUPT,
ec EXT2_ET_SET_BMAP_NO_IND,
"Missing indirect block not present"

+ec EXT2_ET_EXTENT_HEADER_BAD,
+ "Corrupt extent header"
+
+ec EXT2_ET_EXTENT_INDEX_BAD,
+ "Corrupt extent index"
+
+ec EXT2_ET_EXTENT_LEAF_BAD,
+ "Corrupt extent"
+
+ec EXT2_ET_EXTENT_NO_SPACE,
+ "No free space in extent map"
+
end

Index: e2fsprogs-1.39/lib/ext2fs/ext2fs.h
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/ext2fs.h 2006-09-18 16:55:08.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/ext2fs.h 2006-09-18 17:29:08.000000000 +0200
@@ -65,9 +65,11 @@ extern "C" {
#if EXT2_FLAT_INCLUDES
#include "e2_types.h"
#include "ext2_fs.h"
+#include "ext4_extents.h"
#else
#include <ext2fs/ext2_types.h>
#include <ext2fs/ext2_fs.h>
+#include <ext2fs/ext4_extents.h>
#endif /* EXT2_FLAT_INCLUDES */

typedef __u32 ext2_ino_t;
@@ -449,12 +451,14 @@ typedef struct ext2_icount *ext2_icount_
EXT2_FEATURE_INCOMPAT_COMPRESSION|\
EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|\
EXT2_FEATURE_INCOMPAT_META_BG|\
- EXT3_FEATURE_INCOMPAT_RECOVER)
+ EXT3_FEATURE_INCOMPAT_RECOVER|\
+ EXT4_FEATURE_INCOMPAT_EXTENTS)
#else
#define EXT2_LIB_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE|\
EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|\
EXT2_FEATURE_INCOMPAT_META_BG|\
- EXT3_FEATURE_INCOMPAT_RECOVER)
+ EXT3_FEATURE_INCOMPAT_RECOVER|\
+ EXT4_FEATURE_INCOMPAT_EXTENTS)
#endif
#define EXT2_LIB_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|\
EXT2_FEATURE_RO_COMPAT_LARGE_FILE)
@@ -707,6 +711,21 @@ extern errcode_t ext2fs_adjust_ea_refcou
char *block_buf,
int adjust, __u32 *newcount);

+/* extent.c */
+errcode_t ext2fs_extent_header_verify(struct ext4_extent_header *eh, int size);
+errcode_t ext2fs_extent_verify(ext2_filsys fs, struct ext4_extent *ex,
+ struct ext4_extent *ex_prev,
+ struct ext4_extent_idx *ix, int ix_len);
+errcode_t ext2fs_extent_index_verify(ext2_filsys fs,
+ struct ext4_extent_idx *ix,
+ struct ext4_extent_idx *ix_prev);
+errcode_t ext2fs_extent_remove(struct ext4_extent_header *eh,
+ struct ext4_extent *ex);
+errcode_t ext2fs_extent_split(struct ext4_extent_header *eh,
+ struct ext4_extent *ex, int count);
+errcode_t ext2fs_extent_index_remove(struct ext4_extent_header *eh,
+ struct ext4_extent_idx *ix);
+
/* fileio.c */
extern errcode_t ext2fs_file_open2(ext2_filsys fs, ext2_ino_t ino,
struct ext2_inode *inode,
@@ -761,6 +780,8 @@ extern errcode_t ext2fs_image_bitmap_rea
/* ind_block.c */
errcode_t ext2fs_read_ind_block(ext2_filsys fs, blk_t blk, void *buf);
errcode_t ext2fs_write_ind_block(ext2_filsys fs, blk_t blk, void *buf);
+errcode_t ext2fs_read_ext_block(ext2_filsys fs, blk_t blk, void *buf);
+errcode_t ext2fs_write_ext_block(ext2_filsys fs, blk_t blk, void *buf);

/* initialize.c */
extern errcode_t ext2fs_initialize(const char *name, int flags,
Index: e2fsprogs-1.39/lib/ext2fs/ext4_extents.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ e2fsprogs-1.39/lib/ext2fs/ext4_extents.h 2006-09-18 17:23:02.000000000 +0200
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2003,2004 Cluster File Systems, Inc, [email protected]
+ * Written by Alex Tomas <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public Licens
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-
+ */
+
+#ifndef _LINUX_EXT4_EXTENTS
+#define _LINUX_EXT4_EXTENTS
+
+/*
+ * with AGRESSIVE_TEST defined capacity of index/leaf blocks
+ * become very little, so index split, in-depth growing and
+ * other hard changes happens much more often
+ * this is for debug purposes only
+ */
+#define AGRESSIVE_TEST_
+
+/*
+ * if CHECK_BINSEARCH defined, then results of binary search
+ * will be checked by linear search
+ */
+#define CHECK_BINSEARCH_
+
+/*
+ * if EXT_DEBUG is defined you can use 'extdebug' mount option
+ * to get lots of info what's going on
+ */
+//#define EXT_DEBUG
+#ifdef EXT_DEBUG
+#define ext_debug(tree,fmt,a...) \
+do { \
+ if (test_opt((tree)->inode->i_sb, EXTDEBUG)) \
+ printk(fmt, ##a); \
+} while (0);
+#else
+#define ext_debug(tree,fmt,a...)
+#endif
+
+/*
+ * if EXT_STATS is defined then stats numbers are collected
+ * these number will be displayed at umount time
+ */
+#define EXT_STATS_
+
+
+#define EXT4_ALLOC_NEEDED 3 /* block bitmap + group desc. + sb */
+
+/*
+ * ext4_inode has i_block array (total 60 bytes)
+ * first 4 bytes are used to store:
+ * - tree depth (0 mean there is no tree yet. all extents in the inode)
+ * - number of alive extents in the inode
+ */
+
+/*
+ * this is extent on-disk structure
+ * it's used at the bottom of the tree
+ */
+struct ext4_extent {
+ __u32 ee_block; /* first logical block extent covers */
+ __u16 ee_len; /* number of blocks covered by extent */
+ __u16 ee_start_hi; /* high 16 bits of physical block */
+ __u32 ee_start; /* low 32 bigs of physical block */
+};
+
+/*
+ * this is index on-disk structure
+ * it's used at all the levels, but the bottom
+ */
+struct ext4_extent_idx {
+ __u32 ei_block; /* index covers logical blocks from 'block' */
+ __u32 ei_leaf; /* pointer to the physical block of the next *
+ * level. leaf or next index could bet here */
+ __u16 ei_leaf_hi; /* high 16 bits of physical block */
+ __u16 ei_unused;
+};
+
+/*
+ * each block (leaves and indexes), even inode-stored has header
+ */
+struct ext4_extent_header {
+ __u16 eh_magic; /* probably will support different formats */
+ __u16 eh_entries; /* number of valid entries */
+ __u16 eh_max; /* capacity of store in entries */
+ __u16 eh_depth; /* has tree real underlaying blocks? */
+ __u32 eh_generation; /* generation of the tree */
+};
+
+#define EXT4_EXT_MAGIC 0xf30a
+
+/*
+ * array of ext4_ext_path contains path to some extent
+ * creation/lookup routines use it for traversal/splitting/etc
+ * truncate uses it to simulate recursive walking
+ */
+struct ext4_ext_path {
+ __u32 p_block;
+ __u16 p_depth;
+ struct ext4_extent *p_ext;
+ struct ext4_extent_idx *p_idx;
+ struct ext4_extent_header *p_hdr;
+ struct buffer_head *p_bh;
+};
+
+/*
+ * structure for external API
+ */
+
+#define EXT_CONTINUE 0
+#define EXT_BREAK 1
+#define EXT_REPEAT 2
+
+
+#define EXT_MAX_BLOCK 0xffffffff
+#define EXT_CACHE_MARK 0xffff
+
+
+#define EXT_FIRST_EXTENT(__hdr__) \
+ ((struct ext4_extent *) (((char *) (__hdr__)) + \
+ sizeof(struct ext4_extent_header)))
+#define EXT_FIRST_INDEX(__hdr__) \
+ ((struct ext4_extent_idx *) (((char *) (__hdr__)) + \
+ sizeof(struct ext4_extent_header)))
+#define EXT_HAS_FREE_INDEX(__path__) \
+ ((__path__)->p_hdr->eh_entries < (__path__)->p_hdr->eh_max)
+#define EXT_LAST_EXTENT(__hdr__) \
+ (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_entries - 1)
+#define EXT_LAST_INDEX(__hdr__) \
+ (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_entries - 1)
+#define EXT_MAX_EXTENT(__hdr__) \
+ (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_max - 1)
+#define EXT_MAX_INDEX(__hdr__) \
+ (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_max - 1)
+
+#define EXT_ROOT_HDR(tree) \
+ ((struct ext4_extent_header *) (tree)->root)
+#define EXT_BLOCK_HDR(bh) \
+ ((struct ext4_extent_header *) (bh)->b_data)
+#define EXT_DEPTH(_t_) \
+ (((struct ext4_extent_header *)((_t_)->root))->eh_depth)
+#define EXT_GENERATION(_t_) \
+ (((struct ext4_extent_header *)((_t_)->root))->eh_generation)
+
+
+#define EXT_ASSERT(__x__) if (!(__x__)) BUG();
+
+
+/*
+ * this structure is used to gather extents from the tree via ioctl
+ */
+struct ext4_extent_buf {
+ unsigned long start;
+ int buflen;
+ void *buffer;
+ void *cur;
+ int err;
+};
+
+/*
+ * this structure is used to collect stats info about the tree
+ */
+struct ext4_extent_tree_stats {
+ int depth;
+ int extents_num;
+ int leaf_num;
+};
+
+#ifdef __KERNEL__
+/*
+ * ext4_extents_tree is used to pass initial information
+ * to top-level extents API
+ */
+struct ext4_extents_helpers;
+struct ext4_extents_tree {
+ struct inode *inode; /* inode which tree belongs to */
+ void *root; /* ptr to data top of tree resides at */
+ void *buffer; /* will be passed as arg to ^^ routines */
+ int buffer_len;
+ void *private;
+ struct ext4_extent *cex;/* last found extent */
+ struct ext4_extents_helpers *ops;
+};
+
+struct ext4_extents_helpers {
+ int (*get_write_access)(handle_t *h, void *buffer);
+ int (*mark_buffer_dirty)(handle_t *h, void *buffer);
+ int (*mergable)(struct ext4_extent *ex1, struct ext4_extent *ex2);
+ int (*remove_extent_credits)(struct ext4_extents_tree *,
+ struct ext4_extent *, unsigned long,
+ unsigned long);
+ int (*remove_extent)(struct ext4_extents_tree *,
+ struct ext4_extent *, unsigned long,
+ unsigned long);
+ int (*new_block)(handle_t *, struct ext4_extents_tree *,
+ struct ext4_ext_path *, struct ext4_extent *,
+ int *);
+};
+
+/*
+ * to be called by ext4_ext_walk_space()
+ * negative retcode - error
+ * positive retcode - signal for ext4_ext_walk_space(), see below
+ * callback must return valid extent (passed or newly created)
+ */
+typedef int (*ext_prepare_callback)(struct ext4_extents_tree *,
+ struct ext4_ext_path *,
+ struct ext4_extent *, int);
+void ext4_init_tree_desc(struct ext4_extents_tree *, struct inode *);
+extern int ext4_extent_tree_init(handle_t *, struct ext4_extents_tree *);
+extern int ext4_ext_calc_credits_for_insert(struct ext4_extents_tree *, struct ext4_ext_path *);
+extern int ext4_ext_insert_extent(handle_t *, struct ext4_extents_tree *, struct ext4_ext_path *, struct ext4_extent *);
+extern int ext4_ext_walk_space(struct ext4_extents_tree *, unsigned long, unsigned long, ext_prepare_callback);
+extern int ext4_ext_remove_space(struct ext4_extents_tree *, unsigned long, unsigned long);
+extern struct ext4_ext_path * ext4_ext_find_extent(struct ext4_extents_tree *, int, struct ext4_ext_path *);
+
+static inline void
+ext4_ext_invalidate_cache(struct ext4_extents_tree *tree)
+{
+ if (tree->cex)
+ tree->cex->ee_len = 0;
+}
+#endif /* __KERNEL__ */
+
+
+#endif /* _LINUX_EXT4_EXTENTS */
+
Index: e2fsprogs-1.39/lib/ext2fs/extents.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ e2fsprogs-1.39/lib/ext2fs/extents.c 2006-09-18 17:23:02.000000000 +0200
@@ -0,0 +1,340 @@
+/*
+ * extent.c --- iterate over all blocks in an extent-mapped inode
+ *
+ * Copyright (C) 2005 Alex Tomas <[email protected]>
+ * Copyright (C) 2006 Andreas Dilger <[email protected]>
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+#include "block.h"
+
+#ifdef EXT_DEBUG
+void show_header(struct ext4_extent_header *eh)
+{
+ printf("header: magic=%x entries=%u max=%u depth=%u generation=%u\n",
+ eh->eh_magic, eh->eh_entries, eh->eh_max, eh->eh_depth,
+ eh->eh_generation);
+}
+
+void show_index(struct ext4_extent_idx *ix)
+{
+ printf("index: block=%u leaf=%u leaf_hi=%u unused=%u\n",
+ ix->ei_block, ix->ei_leaf, ix->ei_leaf_hi, ix->ei_unused);
+}
+
+void show_extent(struct ext4_extent *ex)
+{
+ printf("extent: block=%u-%u len=%u start=%u start_hi=%u\n",
+ ex->ee_block, ex->ee_block + ex->ee_len - 1,
+ ex->ee_len, ex->ee_start, ex->ee_start_hi);
+}
+#else
+#define show_header(eh) do { } while (0)
+#define show_index(ix) do { } while (0)
+#define show_extent(ex) do { } while (0)
+#endif
+
+errcode_t ext2fs_extent_header_verify(struct ext4_extent_header *eh, int size)
+{
+ int eh_max, entry_size;
+
+ show_header(eh);
+ if (eh->eh_magic != EXT4_EXT_MAGIC)
+ return EXT2_ET_EXTENT_HEADER_BAD;
+ if (eh->eh_entries > eh->eh_max)
+ return EXT2_ET_EXTENT_HEADER_BAD;
+ if (eh->eh_depth == 0)
+ entry_size = sizeof(struct ext4_extent);
+ else
+ entry_size = sizeof(struct ext4_extent_idx);
+
+ eh_max = (size - sizeof(*eh)) / entry_size;
+ if (eh->eh_max > eh_max || eh->eh_max < eh_max - 2)
+ return EXT2_ET_EXTENT_HEADER_BAD;
+
+ return 0;
+}
+
+errcode_t ext2fs_extent_verify(ext2_filsys fs, struct ext4_extent *ex,
+ struct ext4_extent *ex_prev,
+ struct ext4_extent_idx *ix, int ix_len)
+{
+ show_extent(ex);
+ /* FIXME: 48-bit support */
+ if (ex->ee_start > fs->super->s_blocks_count)
+ return EXT2_ET_EXTENT_LEAF_BAD;
+
+ if (ex->ee_len == 0)
+ return EXT2_ET_EXTENT_LEAF_BAD;
+
+ if (ex_prev) {
+ /* We can't have a zero logical block except for first index */
+ if (ex->ee_block == 0)
+ return EXT2_ET_EXTENT_LEAF_BAD;
+
+ /* FIXME: 48-bit support */
+ /* extents must be in logical offset order */
+ if (ex->ee_block < ex_prev->ee_block + ex_prev->ee_len)
+ return EXT2_ET_EXTENT_LEAF_BAD;
+
+ /* extents must not overlap physical blocks */
+ if ((ex->ee_start < ex_prev->ee_start + ex_prev->ee_len) &&
+ (ex->ee_start + ex->ee_len > ex_prev->ee_start))
+ return EXT2_ET_EXTENT_LEAF_BAD;
+ }
+
+ if (ix) {
+ /* FIXME: 48-bit support */
+ if (ex->ee_block < ix->ei_block)
+ return EXT2_ET_EXTENT_LEAF_BAD;
+
+ if (ix_len && ex->ee_block + ex->ee_len > ix->ei_block + ix_len)
+ return EXT2_ET_EXTENT_LEAF_BAD;
+ }
+
+ return 0;
+}
+
+errcode_t ext2fs_extent_index_verify(ext2_filsys fs, struct ext4_extent_idx *ix,
+ struct ext4_extent_idx *ix_prev)
+{
+ show_index(ix);
+ /* FIXME: 48-bit support */
+ if (ix->ei_leaf > fs->super->s_blocks_count)
+ return EXT2_ET_EXTENT_INDEX_BAD;
+
+ if (ix_prev == NULL)
+ return 0;
+
+ /* We can't have a zero logical block except for first index */
+ if (ix->ei_block == 0)
+ return EXT2_ET_EXTENT_INDEX_BAD;
+
+ if (ix->ei_block <= ix_prev->ei_block)
+ return EXT2_ET_EXTENT_INDEX_BAD;
+
+ return 0;
+}
+
+errcode_t ext2fs_extent_remove(struct ext4_extent_header *eh,
+ struct ext4_extent *ex)
+{
+ int entry = ex - EXT_FIRST_EXTENT(eh);
+
+ if (entry < 0 || entry > eh->eh_entries)
+ return EXT2_ET_EXTENT_LEAF_BAD;
+
+ memmove(ex, ex + 1, (eh->eh_entries - entry - 1) * sizeof(*ex));
+ --eh->eh_entries;
+
+ return 0;
+}
+
+errcode_t ext2fs_extent_split(struct ext4_extent_header *eh,
+ struct ext4_extent *ex, int count)
+{
+ int entry = ex - EXT_FIRST_EXTENT(eh);
+ struct ext4_extent *ex_new = ex + 1;
+
+ if (entry < 0 || entry > eh->eh_entries)
+ return EXT2_ET_EXTENT_LEAF_BAD;
+
+ if (eh->eh_entries >= eh->eh_max)
+ return EXT2_ET_EXTENT_NO_SPACE;
+
+ if (count > ex->ee_len)
+ return EXT2_ET_EXTENT_LEAF_BAD;
+
+ if (count > ex->ee_len)
+ return EXT2_ET_EXTENT_LEAF_BAD;
+
+ memmove(ex_new, ex, (eh->eh_entries - entry) * sizeof(*ex));
+ ++eh->eh_entries;
+
+ ex->ee_len = count;
+ /* FIXME: 48-bit support */
+ ex_new->ee_len -= count;
+ ex_new->ee_block += count;
+ ex_new->ee_start += count;
+
+ return 0;
+}
+
+errcode_t ext2fs_extent_index_remove(struct ext4_extent_header *eh,
+ struct ext4_extent_idx *ix)
+{
+ struct ext4_extent_idx *first = EXT_FIRST_INDEX(eh);
+ int count = ix - first;
+
+ memmove(ix, ix + 1, (eh->eh_entries - count - 1) * sizeof(*ix));
+ --eh->eh_entries;
+
+ return 0;
+}
+
+/* Internal function for ext2fs_block_iterate().
+ * See also block_bmap_extents(). */
+int block_iterate_extents(struct ext4_extent_header *eh, blk_t ref_block,
+ int ref_offset EXT2FS_ATTR((unused)),
+ struct block_context *ctx)
+{
+ int ret = 0;
+ int i, j, flags;
+ blk_t block_address;
+ struct ext4_extent *ex, *ex_prev = NULL;
+
+ if (eh->eh_depth == 0) {
+ ex = EXT_FIRST_EXTENT(eh);
+ for (i = 0; i < eh->eh_entries; i++, ex++) {
+ show_extent(ex);
+ for (j = 0; j < ex->ee_len; j++) {
+ block_address = ex->ee_start + j;
+ flags = (*ctx->func)(ctx->fs, &block_address,
+ (ex->ee_block + j),
+ ref_block, i,
+ ctx->priv_data);
+ if (flags & BLOCK_ABORT) {
+ ret |= BLOCK_ABORT;
+ return ret;
+ }
+ if (!(flags & BLOCK_CHANGED))
+ continue;
+
+#ifdef EXT_DEBUG
+ printf("ugh, extent leaf changed: "
+ "block was %u+%u = %u, now %u\n",
+ ex->ee_start, j,
+ ex->ee_start + j, block_address);
+#endif
+
+ /* FIXME: 48-bit support */
+ if (ex_prev &&
+ block_address ==
+ ex_prev->ee_start + ex_prev->ee_len &&
+ ex->ee_block + j ==
+ ex_prev->ee_block + ex_prev->ee_len) {
+ /* can merge block with prev extent */
+ ex_prev->ee_len++;
+
+ ex->ee_len--;
+ if (ex->ee_len == 0) {
+ /* no blocks left in this one */
+ ext2fs_extent_remove(eh, ex);
+ i--; ex--;
+ break;
+ } else {
+ ex->ee_start++;
+ ex->ee_block++;
+ j--;
+ }
+ ret |= BLOCK_CHANGED;
+
+ } else if (ex->ee_len == 1) {
+ /* single-block extent is easy -
+ * change extent directly */
+ ex->ee_start = block_address;
+ ret |= BLOCK_CHANGED;
+
+ } else if (ext2fs_extent_split(eh, ex, j)) {
+ /* split for new block failed */
+ /* No multi-level split yet */
+ ret |= BLOCK_ABORT | BLOCK_ERROR;
+ return ret;
+
+ } else if (j > 0 && (ex + 1)->ee_len > 1 &&
+ ext2fs_extent_split(eh, ex + 1, 1)) {
+ /* split after new block failed */
+ /* No multi-level split yet */
+ ret |= BLOCK_ABORT | BLOCK_ERROR;
+ return ret;
+
+ } else if (j == 0) {
+ if (ex->ee_len != 1) {
+ /* this is an internal error */
+ ret |= BLOCK_ABORT |BLOCK_ERROR;
+ return ret;
+ }
+ ex->ee_start = block_address;
+ ret |= BLOCK_CHANGED;
+
+ } else {
+ ex++;
+ i++;
+ if (ex->ee_len != 1) {
+ /* this is an internal error */
+ ret |= BLOCK_ABORT |BLOCK_ERROR;
+ return ret;
+ }
+ ex->ee_start = block_address;
+ ret |= BLOCK_CHANGED;
+ }
+ }
+ ex_prev = ex;
+ }
+ } else {
+ char *block_buf;
+ struct ext4_extent_idx *ix;
+ struct ext4_extent_header *nh;
+
+ ret = ext2fs_get_mem(ctx->fs->blocksize, &block_buf);
+ if (ret)
+ return ret;
+
+ show_header(eh);
+ ix = EXT_FIRST_INDEX(eh);
+ for (i = 0; i < eh->eh_entries; i++, ix++) {
+ show_index(ix);
+ if (!(ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
+ !(ctx->flags & BLOCK_FLAG_DATA_ONLY)) {
+ ret |= (*ctx->func)(ctx->fs, &ix->ei_leaf,
+ BLOCK_COUNT_IND, ref_block,
+ i, ctx->priv_data);
+ if (ret & BLOCK_ABORT)
+ goto free_buf;
+ }
+ ctx->errcode = ext2fs_read_ext_block(ctx->fs,
+ ix->ei_leaf,
+ block_buf);
+ if (ctx->errcode) {
+ ret |= BLOCK_ERROR;
+ goto free_buf;
+ }
+ nh = (struct ext4_extent_header *)block_buf;
+ if (ext2fs_extent_header_verify(nh,ctx->fs->blocksize)){
+ ret |= BLOCK_ERROR;
+ goto free_buf;
+ }
+ flags = block_iterate_extents(nh, ix->ei_leaf, i, ctx);
+ if (flags & BLOCK_CHANGED)
+ ctx->errcode =
+ ext2fs_write_ext_block(ctx->fs,
+ ix->ei_leaf,
+ block_buf);
+ if (flags & BLOCK_ABORT) {
+ ret |= BLOCK_ABORT;
+ goto free_buf;
+ }
+ if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
+ !(ctx->flags & BLOCK_FLAG_DATA_ONLY))
+ ret |= (*ctx->func)(ctx->fs, &ix->ei_leaf,
+ BLOCK_COUNT_IND, ref_block,
+ i, ctx->priv_data);
+ }
+
+ free_buf:
+ ext2fs_free_mem(&block_buf);
+ }
+ return ret;
+}
Index: e2fsprogs-1.39/lib/ext2fs/ind_block.c
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/ind_block.c 2005-09-06 11:40:14.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/ind_block.c 2006-09-18 17:23:02.000000000 +0200
@@ -22,9 +22,6 @@
errcode_t ext2fs_read_ind_block(ext2_filsys fs, blk_t blk, void *buf)
{
errcode_t retval;
- blk_t *block_nr;
- int i;
- int limit = fs->blocksize >> 2;

if ((fs->flags & EXT2_FLAG_IMAGE_FILE) &&
(fs->io != fs->image_io))
@@ -36,7 +33,10 @@ errcode_t ext2fs_read_ind_block(ext2_fil
}
#ifdef EXT2FS_ENABLE_SWAPFS
if (fs->flags & (EXT2_FLAG_SWAP_BYTES | EXT2_FLAG_SWAP_BYTES_READ)) {
- block_nr = (blk_t *) buf;
+ int limit = fs->blocksize >> 2;
+ blk_t *block_nr = (blk_t *)buf;
+ int i;
+
for (i = 0; i < limit; i++, block_nr++)
*block_nr = ext2fs_swab32(*block_nr);
}
@@ -46,16 +46,15 @@ errcode_t ext2fs_read_ind_block(ext2_fil

errcode_t ext2fs_write_ind_block(ext2_filsys fs, blk_t blk, void *buf)
{
- blk_t *block_nr;
- int i;
- int limit = fs->blocksize >> 2;
-
if (fs->flags & EXT2_FLAG_IMAGE_FILE)
return 0;

#ifdef EXT2FS_ENABLE_SWAPFS
if (fs->flags & (EXT2_FLAG_SWAP_BYTES | EXT2_FLAG_SWAP_BYTES_WRITE)) {
- block_nr = (blk_t *) buf;
+ int limit = fs->blocksize >> 2;
+ blk_t *block_nr = (blk_t *)buf;
+ int i;
+
for (i = 0; i < limit; i++, block_nr++)
*block_nr = ext2fs_swab32(*block_nr);
}
@@ -64,3 +63,82 @@ errcode_t ext2fs_write_ind_block(ext2_fi
}


+errcode_t ext2fs_read_ext_block(ext2_filsys fs, blk_t blk, void *buf)
+{
+ errcode_t retval;
+
+ if ((fs->flags & EXT2_FLAG_IMAGE_FILE) &&
+ (fs->io != fs->image_io))
+ memset(buf, 0, fs->blocksize);
+ else {
+ retval = io_channel_read_blk(fs->io, blk, 1, buf);
+ if (retval)
+ return retval;
+ }
+#ifdef EXT2FS_ENABLE_SWAPFS
+ if (fs->flags & (EXT2_FLAG_SWAP_BYTES | EXT2_FLAG_SWAP_BYTES_READ)) {
+ struct ext4_extent_header *eh = buf;
+ int i, limit;
+
+ ext2fs_swap_extent_header(eh);
+
+ if (eh->eh_depth == 0) {
+ struct ext4_extent *ex = EXT_FIRST_EXTENT(eh);
+
+ limit = (fs->blocksize - sizeof(*eh)) / sizeof(*ex);
+ if (eh->eh_entries < limit)
+ limit = eh->eh_entries;
+
+ for (i = 0; i < limit; i++, ex++)
+ ext2fs_swap_extent(ex);
+ } else {
+ struct ext4_extent_idx *ix = EXT_FIRST_INDEX(eh);
+
+ limit = (fs->blocksize - sizeof(*eh)) / sizeof(*ix);
+ if (eh->eh_entries < limit)
+ limit = eh->eh_entries;
+
+ for (i = 0; i < limit; i++, ix++)
+ ext2fs_swap_extent_index(ix);
+ }
+ }
+#endif
+ return 0;
+}
+
+errcode_t ext2fs_write_ext_block(ext2_filsys fs, blk_t blk, void *buf)
+{
+ if (fs->flags & EXT2_FLAG_IMAGE_FILE)
+ return 0;
+
+#ifdef EXT2FS_ENABLE_SWAPFS
+ if (fs->flags & (EXT2_FLAG_SWAP_BYTES | EXT2_FLAG_SWAP_BYTES_WRITE)) {
+ struct ext4_extent_header *eh = buf;
+ int i, limit;
+
+ if (eh->eh_depth == 0) {
+ struct ext4_extent *ex = EXT_FIRST_EXTENT(eh);
+
+ limit = (fs->blocksize - sizeof(*eh)) / sizeof(*ex);
+ if (eh->eh_entries < limit)
+ limit = eh->eh_entries;
+
+ for (i = 0; i < limit; i++, ex++)
+ ext2fs_swap_extent(ex);
+ } else {
+ struct ext4_extent_idx *ix = EXT_FIRST_INDEX(eh);
+
+ limit = (fs->blocksize - sizeof(*eh)) / sizeof(*ix);
+ if (eh->eh_entries < limit)
+ limit = eh->eh_entries;
+
+ for (i = 0; i < limit; i++, ix++)
+ ext2fs_swap_extent_index(ix);
+ }
+
+ ext2fs_swap_extent_header(eh);
+ }
+#endif
+ return io_channel_write_blk(fs->io, blk, 1, buf);
+}
+
Index: e2fsprogs-1.39/lib/ext2fs/swapfs.c
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/swapfs.c 2006-04-23 18:47:16.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/swapfs.c 2006-09-18 17:23:02.000000000 +0200
@@ -120,6 +120,28 @@ void ext2fs_swap_ext_attr(char *to, char
}
}

+void ext2fs_swap_extent_header(struct ext4_extent_header *eh) {
+ eh->eh_magic = ext2fs_swab16(eh->eh_magic);
+ eh->eh_entries = ext2fs_swab16(eh->eh_entries);
+ eh->eh_max = ext2fs_swab16(eh->eh_max);
+ eh->eh_depth = ext2fs_swab16(eh->eh_depth);
+ eh->eh_generation = ext2fs_swab32(eh->eh_generation);
+}
+
+void ext2fs_swap_extent_index(struct ext4_extent_idx *ix) {
+ ix->ei_block = ext2fs_swab32(ix->ei_block);
+ ix->ei_leaf = ext2fs_swab32(ix->ei_leaf);
+ ix->ei_leaf_hi = ext2fs_swab16(ix->ei_leaf_hi);
+ ix->ei_unused = ext2fs_swab16(ix->ei_unused);
+}
+
+void ext2fs_swap_extent(struct ext4_extent *ex) {
+ ex->ee_block = ext2fs_swab32(ex->ee_block);
+ ex->ee_len = ext2fs_swab16(ex->ee_len);
+ ex->ee_start_hi =ext2fs_swab16(ex->ee_start_hi);
+ ex->ee_start = ext2fs_swab32(ex->ee_start);
+}
+
void ext2fs_swap_inode_full(ext2_filsys fs, struct ext2_inode_large *t,
struct ext2_inode_large *f, int hostorder,
int bufsize)
Index: e2fsprogs-1.39/lib/ext2fs/valid_blk.c
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/valid_blk.c 2005-09-06 11:40:14.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/valid_blk.c 2006-09-18 17:23:02.000000000 +0200
@@ -19,6 +19,7 @@

#include "ext2_fs.h"
#include "ext2fs.h"
+#include "ext4_extents.h"

/*
* This function returns 1 if the inode's block entries actually
@@ -41,12 +42,23 @@ int ext2fs_inode_has_valid_blocks(struct
if (LINUX_S_ISLNK (inode->i_mode)) {
if (inode->i_file_acl == 0) {
/* With no EA block, we can rely on i_blocks */
- if (inode->i_blocks == 0)
- return 0;
+ if (inode->i_flags & EXT4_EXTENTS_FL) {
+ struct ext4_extent_header *eh;
+ eh = (struct ext4_extent_header *)inode->i_block;
+ if (eh->eh_entries == 0)
+ return 0;
+ } else {
+ if (inode->i_blocks == 0)
+ return 0;
+ }
} else {
/* With an EA block, life gets more tricky */
if (inode->i_size >= EXT2_N_BLOCKS*4)
return 1; /* definitely using i_block[] */
+ /*
+ * we cant have EA + extents, so assume we aren't
+ * using extents
+ */
if (inode->i_size > 4 && inode->i_block[1] == 0)
return 1; /* definitely using i_block[] */
return 0; /* Probably a fast symlink */
Index: e2fsprogs-1.39/tests/f_bad_disconnected_inode/expect.1
===================================================================
--- e2fsprogs-1.39.orig/tests/f_bad_disconnected_inode/expect.1 2005-09-06 11:40:14.000000000 +0200
+++ e2fsprogs-1.39/tests/f_bad_disconnected_inode/expect.1 2006-09-18 17:23:02.000000000 +0200
@@ -1,4 +1,10 @@
Pass 1: Checking inodes, blocks, and sizes
+Inode 15 has EXTENT_FL set, but is not in extents format
+Fix? yes
+
+Inode 16 has EXTENT_FL set, but is not in extents format
+Fix? yes
+
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
/lost+found not found. Create? yes
Index: e2fsprogs-1.39/tests/f_bbfile/expect.1
===================================================================
--- e2fsprogs-1.39.orig/tests/f_bbfile/expect.1 2005-09-06 11:40:14.000000000 +0200
+++ e2fsprogs-1.39/tests/f_bbfile/expect.1 2006-09-18 17:23:02.000000000 +0200
@@ -3,46 +3,60 @@ Filesystem did not have a UUID; generati
Pass 1: Checking inodes, blocks, and sizes
Group 0's inode bitmap (4) is bad. Relocate? yes

+Inode 11 has corrupt indirect block
+Clear? yes
+
Relocating group 0's inode bitmap from 4 to 43...
+Restarting e2fsck from the beginning...
+Pass 1: Checking inodes, blocks, and sizes

Running additional passes to resolve blocks claimed by more than one inode...
Pass 1B: Rescanning for multiply-claimed blocks
Multiply-claimed block(s) in inode 2: 21
-Multiply-claimed block(s) in inode 11: 9 10 11 12 13 14 15 16 17 18 19 20
Multiply-claimed block(s) in inode 12: 25 26
Pass 1C: Scanning directories for inodes with multiply-claimed blocks
Pass 1D: Reconciling multiply-claimed blocks
-(There are 3 inodes containing multiply-claimed blocks.)
+(There are 2 inodes containing multiply-claimed blocks.)

File / (inode #2, mod time Sun Jan 2 08:29:13 1994)
has 1 multiply-claimed block(s), shared with 1 file(s):
<The bad blocks inode> (inode #1, mod time Sun Jul 17 00:47:58 1994)
Clone multiply-claimed blocks? yes

-File /lost+found (inode #11, mod time Sun Jan 2 08:28:40 1994)
- has 12 multiply-claimed block(s), shared with 1 file(s):
- <The bad blocks inode> (inode #1, mod time Sun Jul 17 00:47:58 1994)
-Clone multiply-claimed blocks? yes
-
File /termcap (inode #12, mod time Sun Jan 2 08:29:13 1994)
has 2 multiply-claimed block(s), shared with 1 file(s):
<The bad blocks inode> (inode #1, mod time Sun Jul 17 00:47:58 1994)
Clone multiply-claimed blocks? yes

Pass 2: Checking directory structure
+Entry 'lost+found' in / (2) has deleted/unused inode 11. Clear? yes
+
Pass 3: Checking directory connectivity
+/lost+found not found. Create? yes
+
Pass 4: Checking reference counts
+Inode 2 ref count is 4, should be 3. Fix? yes
+
Pass 5: Checking group summary information
Block bitmap differences: +43
Fix? yes

-Free blocks count wrong for group #0 (57, counted=41).
+Free blocks count wrong for group #0 (56, counted=52).
+Fix? yes
+
+Free blocks count wrong (56, counted=52).
+Fix? yes
+
+Free inodes count wrong for group #0 (19, counted=20).
+Fix? yes
+
+Directories count wrong for group #0 (3, counted=2).
Fix? yes

-Free blocks count wrong (57, counted=41).
+Free inodes count wrong (19, counted=20).
Fix? yes


test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
-test_filesys: 12/32 files (0.0% non-contiguous), 59/100 blocks
+test_filesys: 12/32 files (0.0% non-contiguous), 48/100 blocks
Exit status is 1
Index: e2fsprogs-1.39/tests/f_bbfile/expect.2
===================================================================
--- e2fsprogs-1.39.orig/tests/f_bbfile/expect.2 2005-09-06 11:40:14.000000000 +0200
+++ e2fsprogs-1.39/tests/f_bbfile/expect.2 2006-09-18 17:23:02.000000000 +0200
@@ -3,5 +3,5 @@ Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
-test_filesys: 12/32 files (8.3% non-contiguous), 59/100 blocks
+test_filesys: 12/32 files (8.3% non-contiguous), 48/100 blocks
Exit status is 0
Index: e2fsprogs-1.39/tests/f_extents/expect.1
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ e2fsprogs-1.39/tests/f_extents/expect.1 2006-09-18 17:23:02.000000000 +0200
@@ -0,0 +1,61 @@
+Pass 1: Checking inodes, blocks, and sizes
+Inode 12 is in extent format, but superblock is missing EXTENTS feature
+Fix? yes
+
+Inode 13 missing EXTENT_FL, but is in extents format
+Fix? yes
+
+Inode 16 has corrupt extent at block 3 (logical 4613) length 2
+Clear? yes
+
+Inode 16, i_blocks is 16, should be 12. Fix? yes
+
+Inode 18 has EXTENT_FL set, but is not in extents format
+Fix? yes
+
+Inode 19 has EXTENT_FL set, but is not in extents format
+Fix? yes
+
+Inode 17 has high 16 bits of extent/index block set
+Clear? yes
+
+High 16 bits of extent/index block set
+CLEARED.
+High 16 bits of extent/index block set
+CLEARED.
+
+Running additional passes to resolve blocks claimed by more than one inode...
+Pass 1B: Rescanning for multiply-claimed blocks
+Multiply-claimed block(s) in inode 12: 5133 5124 5125 5129 5132 5133 5142 5143 5144 5145
+Multiply-claimed block(s) in inode 17: 5124 5125 5129 5132 5142 5143 5144 5145
+Pass 1C: Scanning directories for inodes with multiply-claimed blocks
+Pass 1D: Reconciling multiply-claimed blocks
+(There are 2 inodes containing multiply-claimed blocks.)
+
+File /fdup1 (inode #12, mod time Wed Jul 5 21:55:26 2006)
+ has 10 multiply-claimed block(s), shared with 1 file(s):
+ /fdup2 (inode #17, mod time Wed Jul 5 21:55:27 2006)
+Clone multiply-claimed blocks? yes
+
+File /fdup2 (inode #17, mod time Wed Jul 5 21:55:27 2006)
+ has 8 multiply-claimed block(s), shared with 1 file(s):
+ /fdup1 (inode #12, mod time Wed Jul 5 21:55:26 2006)
+Multiply-claimed blocks already reassigned or cloned.
+
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+Block bitmap differences: +4611 -(4613--4614) -(5121--5122) +(5143--5146)
+Fix? yes
+
+Free blocks count wrong for group #0 (7081, counted=7066).
+Fix? yes
+
+Free blocks count wrong (7081, counted=7066).
+Fix? yes
+
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 19/256 files (15.8% non-contiguous), 1126/8192 blocks
+Exit status is 1
Index: e2fsprogs-1.39/tests/f_extents/expect.2
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ e2fsprogs-1.39/tests/f_extents/expect.2 2006-09-18 17:23:02.000000000 +0200
@@ -0,0 +1,7 @@
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+test_filesys: 19/256 files (15.8% non-contiguous), 1126/8192 blocks
+Exit status is 0
Index: e2fsprogs-1.39/tests/f_extents/name
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ e2fsprogs-1.39/tests/f_extents/name 2006-09-18 17:23:02.000000000 +0200
@@ -0,0 +1 @@
+extent-mapped files with errors
Index: e2fsprogs-1.39/tests/f_lotsbad/expect.1
===================================================================
--- e2fsprogs-1.39.orig/tests/f_lotsbad/expect.1 2005-09-06 11:40:14.000000000 +0200
+++ e2fsprogs-1.39/tests/f_lotsbad/expect.1 2006-09-18 17:23:02.000000000 +0200
@@ -8,54 +8,41 @@ Inode 13, i_size is 15360, should be 122

Inode 13, i_blocks is 32, should be 30. Fix? yes

-Inode 12 has illegal block(s). Clear? yes
+Inode 12 has corrupt indirect block
+Clear? yes

-Illegal block #12 (778398818) in inode 12. CLEARED.
-Illegal block #13 (1768444960) in inode 12. CLEARED.
-Illegal block #14 (1752375411) in inode 12. CLEARED.
-Illegal block #15 (1684829551) in inode 12. CLEARED.
-Illegal block #16 (1886349344) in inode 12. CLEARED.
-Illegal block #17 (1819633253) in inode 12. CLEARED.
-Illegal block #18 (1663072620) in inode 12. CLEARED.
-Illegal block #19 (1735287144) in inode 12. CLEARED.
-Illegal block #20 (1310731877) in inode 12. CLEARED.
-Illegal block #21 (560297071) in inode 12. CLEARED.
-Illegal block #22 (543512352) in inode 12. CLEARED.
-Too many illegal blocks in inode 12.
-Clear inode? yes
+Inode 12, i_blocks is 34, should be 24. Fix? yes

-Restarting e2fsck from the beginning...
-Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
-Entry 'termcap' in / (2) has deleted/unused inode 12. Clear? yes
+Directory inode 13 has an unallocated block #16580876. Allocate? yes

Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Inode 2 ref count is 5, should be 4. Fix? yes

Pass 5: Checking group summary information
-Block bitmap differences: -(27--41) -(44--45) -(74--90)
+Block bitmap differences: -(38--41) -(74--90)
Fix? yes

-Free blocks count wrong for group #0 (9, counted=43).
+Free blocks count wrong for group #0 (9, counted=30).
Fix? yes

-Free blocks count wrong (9, counted=43).
+Free blocks count wrong (9, counted=30).
Fix? yes

-Inode bitmap differences: -12 -14
+Inode bitmap differences: -14
Fix? yes

-Free inodes count wrong for group #0 (18, counted=20).
+Free inodes count wrong for group #0 (18, counted=19).
Fix? yes

Directories count wrong for group #0 (4, counted=3).
Fix? yes

-Free inodes count wrong (18, counted=20).
+Free inodes count wrong (18, counted=19).
Fix? yes


test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
-test_filesys: 12/32 files (0.0% non-contiguous), 57/100 blocks
+test_filesys: 13/32 files (7.7% non-contiguous), 70/100 blocks
Exit status is 1
Index: e2fsprogs-1.39/tests/f_messy_inode/expect.1
===================================================================
--- e2fsprogs-1.39.orig/tests/f_messy_inode/expect.1 2005-09-06 11:40:15.000000000 +0200
+++ e2fsprogs-1.39/tests/f_messy_inode/expect.1 2006-09-18 17:23:02.000000000 +0200
@@ -1,38 +1,36 @@
Filesystem did not have a UUID; generating one.

Pass 1: Checking inodes, blocks, and sizes
-Inode 14 has illegal block(s). Clear? yes
-
-Illegal block #2 (4294901760) in inode 14. CLEARED.
-Illegal block #3 (4294901760) in inode 14. CLEARED.
-Illegal block #4 (4294901760) in inode 14. CLEARED.
-Illegal block #5 (4294901760) in inode 14. CLEARED.
-Illegal block #6 (4294901760) in inode 14. CLEARED.
-Illegal block #7 (4294901760) in inode 14. CLEARED.
-Illegal block #8 (4294901760) in inode 14. CLEARED.
-Illegal block #9 (4294901760) in inode 14. CLEARED.
-Illegal block #10 (4294901760) in inode 14. CLEARED.
-Inode 14, i_size is 18446462598732849291, should be 2048. Fix? yes
-
-Inode 14, i_blocks is 18, should be 4. Fix? yes
+Inode 14 has corrupt indirect block
+Clear? yes

+Restarting e2fsck from the beginning...
+Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
-i_file_acl for inode 14 (/MAKEDEV) is 4294901760, should be zero.
-Clear? yes
+Entry 'MAKEDEV' in / (2) has deleted/unused inode 14. Clear? yes

Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
-Block bitmap differences: -(43--49)
+Block bitmap differences: -(41--49)
+Fix? yes
+
+Free blocks count wrong for group #0 (68, counted=77).
+Fix? yes
+
+Free blocks count wrong (68, counted=77).
+Fix? yes
+
+Inode bitmap differences: -14
Fix? yes

-Free blocks count wrong for group #0 (68, counted=75).
+Free inodes count wrong for group #0 (3, counted=4).
Fix? yes

-Free blocks count wrong (68, counted=75).
+Free inodes count wrong (3, counted=4).
Fix? yes


test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
-test_filesys: 29/32 files (3.4% non-contiguous), 25/100 blocks
+test_filesys: 28/32 files (0.0% non-contiguous), 23/100 blocks
Exit status is 1
Index: e2fsprogs-1.39/tests/f_messy_inode/expect.2
===================================================================
--- e2fsprogs-1.39.orig/tests/f_messy_inode/expect.2 2005-09-06 11:40:15.000000000 +0200
+++ e2fsprogs-1.39/tests/f_messy_inode/expect.2 2006-09-18 17:23:02.000000000 +0200
@@ -3,5 +3,5 @@ Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
-test_filesys: 29/32 files (0.0% non-contiguous), 25/100 blocks
+test_filesys: 28/32 files (0.0% non-contiguous), 23/100 blocks
Exit status is 0
Index: e2fsprogs-1.39/lib/e2p/feature.c
===================================================================
--- e2fsprogs-1.39.orig/lib/e2p/feature.c 2006-05-04 18:06:50.000000000 +0200
+++ e2fsprogs-1.39/lib/e2p/feature.c 2006-09-18 17:32:10.000000000 +0200
@@ -49,7 +49,7 @@ static struct feature feature_list[] = {
"needs_recovery" },
{ E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_JOURNAL_DEV,
"journal_dev" },
- { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_EXTENTS,
+ { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_EXTENTS,
"extents" },
{ E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_META_BG,
"meta_bg" },
Index: e2fsprogs-1.39/lib/ext2fs/ext2_fs.h
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/ext2_fs.h 2006-09-18 17:30:56.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/ext2_fs.h 2006-09-18 17:31:24.000000000 +0200
@@ -582,7 +582,7 @@ struct ext2_super_block {
#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */
#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */
#define EXT2_FEATURE_INCOMPAT_META_BG 0x0010
-#define EXT3_FEATURE_INCOMPAT_EXTENTS 0x0040
+#define EXT4_FEATURE_INCOMPAT_EXTENTS 0x0040


#define EXT2_FEATURE_COMPAT_SUPP 0

2006-09-26 14:48:45

by Alexandre Ratchov

[permalink] [raw]
Subject: [patch 07/12] rfc: 2fsprogs update

convert all 32bit on-disk block number definitions (currently __u32,
blk_t, unsigned long, unsigned int...) to pblk_t that is defined as
__u32. In this way we are sure that blk_t is used only in memory.
Later, this would allow to make blk_t 64bit without disturbing any
programs (this would just eat more momory and use 64bit arithmetic).

Signed-off-by: Laurent Vivier <[email protected]>
Signed-off-by: Alexandre Ratchov <[email protected]>


Index: e2fsprogs-1.39/debugfs/debugfs.c
===================================================================
--- e2fsprogs-1.39.orig/debugfs/debugfs.c 2006-09-19 19:18:10.000000000 +0200
+++ e2fsprogs-1.39/debugfs/debugfs.c 2006-09-19 20:50:30.000000000 +0200
@@ -1673,7 +1673,8 @@ void do_features(int argc, char *argv[])
void do_bmap(int argc, char *argv[])
{
ext2_ino_t ino;
- blk_t blk, pblk;
+ blk_t blk;
+ blk_t pblk;
int err;
errcode_t errcode;

@@ -1698,7 +1699,8 @@ void do_bmap(int argc, char *argv[])
void do_imap(int argc, char *argv[])
{
ext2_ino_t ino;
- unsigned long group, block, block_nr, offset;
+ unsigned long group, offset;
+ blk_t block, block_nr;

if (common_args_process(argc, argv, 2, 2, argv[0],
"<file>", 0))
@@ -1721,7 +1723,7 @@ void do_imap(int argc, char *argv[])
offset &= (EXT2_BLOCK_SIZE(current_fs->super) - 1);

printf("Inode %d is part of block group %lu\n"
- "\tlocated at block %lu, offset 0x%04lx\n", ino, group,
+ "\tlocated at block %u, offset 0x%04lx\n", ino, group,
block_nr, offset);

}
Index: e2fsprogs-1.39/debugfs/icheck.c
===================================================================
--- e2fsprogs-1.39.orig/debugfs/icheck.c 2006-09-19 19:18:10.000000000 +0200
+++ e2fsprogs-1.39/debugfs/icheck.c 2006-09-19 20:50:27.000000000 +0200
@@ -112,8 +112,10 @@ void do_icheck(int argc, char **argv)
bw.inode = ino;

if (inode.i_file_acl) {
- icheck_proc(current_fs, &inode.i_file_acl, 0,
+ blk_t i_file_acl = inode.i_file_acl;
+ icheck_proc(current_fs, &i_file_acl, 0,
0, 0, &bw);
+ inode.i_file_acl = i_file_acl;
if (bw.blocks_left == 0)
break;
}
Index: e2fsprogs-1.39/debugfs/logdump.c
===================================================================
--- e2fsprogs-1.39.orig/debugfs/logdump.c 2006-09-19 19:18:10.000000000 +0200
+++ e2fsprogs-1.39/debugfs/logdump.c 2006-09-19 20:50:27.000000000 +0200
@@ -36,11 +36,13 @@ extern char *optarg;

enum journal_location {JOURNAL_IS_INTERNAL, JOURNAL_IS_EXTERNAL};

-#define ANY_BLOCK ((unsigned int) -1)
+#define ANY_BLOCK ((blk_t) -1)

int dump_all, dump_contents, dump_descriptors;
-unsigned int block_to_dump, group_to_dump, bitmap_to_dump;
-unsigned int inode_block_to_dump, inode_offset_to_dump, bitmap_to_dump;
+blk_t block_to_dump, bitmap_to_dump;
+unsigned int group_to_dump;
+blk_t inode_block_to_dump;
+unsigned int inode_offset_to_dump;
ext2_ino_t inode_to_dump;

struct journal_source
@@ -364,8 +366,8 @@ static void dump_journal(char *cmdname,
if (dump_all) {
fprintf(out_file, "\tuuid=%s\n", jsb_buffer);
fprintf(out_file, "\tblocksize=%d\n", blocksize);
- fprintf(out_file, "\tjournal data size %ld\n",
- (long) sb->s_blocks_count);
+ fprintf(out_file, "\tjournal data size %lu\n",
+ (unsigned long) sb->s_blocks_count);
}
}

Index: e2fsprogs-1.39/e2fsck/jfs_user.h
===================================================================
--- e2fsprogs-1.39.orig/e2fsck/jfs_user.h 2006-09-19 19:18:10.000000000 +0200
+++ e2fsprogs-1.39/e2fsck/jfs_user.h 2006-09-19 19:20:58.000000000 +0200
@@ -103,7 +103,7 @@ _INLINE_ void do_cache_destroy(kmem_cach
/*
* Kernel compatibility functions are defined in journal.c
*/
-int journal_bmap(journal_t *journal, blk_t block, unsigned long *phys);
+int journal_bmap(journal_t *journal, blk_t block, blk_t *phys);
struct buffer_head *getblk(kdev_t ctx, blk_t blocknr, int blocksize);
void sync_blockdev(kdev_t kdev);
void ll_rw_block(int rw, int dummy, struct buffer_head *bh[]);
Index: e2fsprogs-1.39/e2fsck/journal.c
===================================================================
--- e2fsprogs-1.39.orig/e2fsck/journal.c 2006-09-19 19:18:10.000000000 +0200
+++ e2fsprogs-1.39/e2fsck/journal.c 2006-09-19 20:50:27.000000000 +0200
@@ -43,7 +43,7 @@ static int bh_count = 0;
* to use the recovery.c file virtually unchanged from the kernel, so we
* don't have to do much to keep kernel and user recovery in sync.
*/
-int journal_bmap(journal_t *journal, blk_t block, unsigned long *phys)
+int journal_bmap(journal_t *journal, blk_t block, blk_t *phys)
{
#ifdef USE_INODE_IO
*phys = block;
@@ -51,7 +51,6 @@ int journal_bmap(journal_t *journal, blk
#else
struct inode *inode = journal->j_inode;
errcode_t retval;
- blk_t pblk;

if (!inode) {
*phys = block;
@@ -59,8 +58,7 @@ int journal_bmap(journal_t *journal, blk
}

retval= ext2fs_bmap(inode->i_ctx->fs, inode->i_ino,
- &inode->i_ext2, NULL, 0, block, &pblk);
- *phys = pblk;
+ &inode->i_ext2, NULL, 0, block, phys);
return (retval);
#endif
}
@@ -201,7 +199,7 @@ static errcode_t e2fsck_get_journal(e2fs
journal_t *journal = NULL;
errcode_t retval = 0;
io_manager io_ptr = 0;
- unsigned long start = 0;
+ blk_t start = 0;
blk_t blk;
int ext_journal = 0;
int tried_backup_jnl = 0;
Index: e2fsprogs-1.39/e2fsck/pass1.c
===================================================================
--- e2fsprogs-1.39.orig/e2fsck/pass1.c 2006-09-19 19:20:58.000000000 +0200
+++ e2fsprogs-1.39/e2fsck/pass1.c 2006-09-19 20:50:27.000000000 +0200
@@ -1777,7 +1777,7 @@ static char *describe_illegal_block(ext2
sprintf(problem, "< FIRSTBLOCK (%u)", super);
return(problem);
} else if (block >= fs->super->s_blocks_count) {
- sprintf(problem, "> BLOCKS (%u)", fs->super->s_blocks_count);
+ sprintf(problem, "> BLOCKS (%lu)", fs->super->s_blocks_count);
return(problem);
}
for (i = 0; i < fs->group_desc_count; i++) {
@@ -2226,20 +2226,26 @@ static void handle_fs_bad_blocks(e2fsck_
blk_t first_block;

for (i = 0; i < fs->group_desc_count; i++) {
+ blk_t blk;
first_block = ext2fs_group_first_block(fs, i);

if (ctx->invalid_block_bitmap_flag[i]) {
+ blk = fs->group_desc[i].bg_block_bitmap;
new_table_block(ctx, first_block, i, _("block bitmap"),
- 1, &fs->group_desc[i].bg_block_bitmap);
+ 1, &blk);
+ fs->group_desc[i].bg_block_bitmap = blk;
}
if (ctx->invalid_inode_bitmap_flag[i]) {
+ blk = fs->group_desc[i].bg_inode_bitmap;
new_table_block(ctx, first_block, i, _("inode bitmap"),
- 1, &fs->group_desc[i].bg_inode_bitmap);
+ 1, &blk);
+ fs->group_desc[i].bg_inode_bitmap = blk;
}
if (ctx->invalid_inode_table_flag[i]) {
+ blk = fs->group_desc[i].bg_inode_table;
new_table_block(ctx, first_block, i, _("inode table"),
- fs->inode_blocks_per_group,
- &fs->group_desc[i].bg_inode_table);
+ fs->inode_blocks_per_group, &blk);
+ fs->group_desc[i].bg_inode_table = blk;
ctx->flags |= E2F_FLAG_RESTART;
}
}
@@ -2330,7 +2336,7 @@ static void mark_table_blocks(e2fsck_t c
* the inode again.
*/
static errcode_t pass1_get_blocks(ext2_filsys fs, ext2_ino_t ino,
- blk_t *blocks)
+ pblk_t *blocks)
{
e2fsck_t ctx = (e2fsck_t) fs->priv_data;
int i;
Index: e2fsprogs-1.39/e2fsck/pass1b.c
===================================================================
--- e2fsprogs-1.39.orig/e2fsck/pass1b.c 2006-09-19 19:18:10.000000000 +0200
+++ e2fsprogs-1.39/e2fsck/pass1b.c 2006-09-19 20:50:27.000000000 +0200
@@ -289,9 +289,12 @@ static void pass1b(e2fsck_t ctx, char *b
(ino == EXT2_BAD_INO))
pctx.errcode = ext2fs_block_iterate2(fs, ino,
0, block_buf, process_pass1b_block, &pb);
- if (inode.i_file_acl)
- process_pass1b_block(fs, &inode.i_file_acl,
+ if (inode.i_file_acl) {
+ blk_t i_file_acl = inode.i_file_acl;
+ process_pass1b_block(fs, &i_file_acl,
BLOCK_COUNT_EXTATTR, 0, 0, &pb);
+ inode.i_file_acl = i_file_acl;
+ }
if (pb.dup_blocks) {
end_problem_latch(ctx, PR_LATCH_DBLOCK);
if (ino >= EXT2_FIRST_INODE(fs->super) ||
@@ -617,9 +620,12 @@ static void delete_file(e2fsck_t ctx, ex
*/
if ((count == 0) ||
ext2fs_test_block_bitmap(ctx->block_dup_map,
- inode.i_file_acl))
- delete_file_block(fs, &inode.i_file_acl,
+ inode.i_file_acl)) {
+ blk_t i_file_acl = inode.i_file_acl;
+ delete_file_block(fs, &i_file_acl,
BLOCK_COUNT_EXTATTR, 0, 0, &pb);
+ inode.i_file_acl = i_file_acl;
+ }
}
e2fsck_write_inode(ctx, ino, &inode, "delete_file");
}
@@ -706,10 +712,12 @@ static int clone_file(e2fsck_t ctx, ext2
struct clone_struct cs;
struct problem_context pctx;
blk_t blk;
+ blk_t i_file_acl;
dnode_t *n;
struct inode_el *ino_el;
struct dup_block *db;
struct dup_inode *di;
+ int ret;

clear_problem_context(&pctx);
cs.errcode = 0;
@@ -742,9 +750,10 @@ static int clone_file(e2fsck_t ctx, ext2
/* The inode may have changed on disk, so we have to re-read it */
e2fsck_read_inode(ctx, ino, &dp->inode, "clone file EA");
blk = dp->inode.i_file_acl;
- if (blk && (clone_file_block(fs, &dp->inode.i_file_acl,
- BLOCK_COUNT_EXTATTR, 0, 0, &cs) ==
- BLOCK_CHANGED)) {
+ i_file_acl = dp->inode.i_file_acl;
+ ret = clone_file_block(fs, &i_file_acl, BLOCK_COUNT_EXTATTR, 0, 0, &cs);
+ dp->inode.i_file_acl = i_file_acl;
+ if (blk && (ret == BLOCK_CHANGED)) {
e2fsck_write_inode(ctx, ino, &dp->inode, "clone file EA");
/*
* If we cloned the EA block, find all other inodes
Index: e2fsprogs-1.39/e2fsck/pass5.c
===================================================================
--- e2fsprogs-1.39.orig/e2fsck/pass5.c 2006-09-19 19:18:10.000000000 +0200
+++ e2fsprogs-1.39/e2fsck/pass5.c 2006-09-19 20:50:27.000000000 +0200
@@ -114,8 +114,8 @@ static void check_block_bitmaps(e2fsck_t
blk_t i, super;
int *free_array;
int group = 0;
- unsigned int blocks = 0;
- unsigned int free_blocks = 0;
+ blk_t blocks = 0;
+ blk_t free_blocks = 0;
int group_free = 0;
int actual, bitmap;
struct problem_context pctx;
Index: e2fsprogs-1.39/e2fsck/recovery.c
===================================================================
--- e2fsprogs-1.39.orig/e2fsck/recovery.c 2006-09-19 19:18:10.000000000 +0200
+++ e2fsprogs-1.39/e2fsck/recovery.c 2006-09-19 19:20:58.000000000 +0200
@@ -70,7 +70,7 @@ static int do_readahead(journal_t *journ
{
int err;
unsigned int max, nbufs, next;
- unsigned long blocknr;
+ blk_t blocknr;
struct buffer_head *bh;

struct buffer_head * bufs[MAXBUF];
@@ -132,7 +132,7 @@ static int jread(struct buffer_head **bh
unsigned int offset)
{
int err;
- unsigned long blocknr;
+ blk_t blocknr;
struct buffer_head *bh;

*bhp = NULL;
Index: e2fsprogs-1.39/e2fsck/super.c
===================================================================
--- e2fsprogs-1.39.orig/e2fsck/super.c 2006-09-19 19:18:10.000000000 +0200
+++ e2fsprogs-1.39/e2fsck/super.c 2006-09-19 20:50:27.000000000 +0200
@@ -23,8 +23,8 @@
#define MAX_CHECK 2

static void check_super_value(e2fsck_t ctx, const char *descr,
- unsigned long value, int flags,
- unsigned long min_val, unsigned long max_val)
+ blk_t value, int flags,
+ blk_t min_val, blk_t max_val)
{
struct problem_context pctx;

@@ -114,7 +114,7 @@ static int release_inode_block(ext2_fils
*/
if (blockcnt < 0) {
int i, limit;
- blk_t *bp;
+ pblk_t *bp;

pb->errcode = io_channel_read_blk(fs->io, blk, 1,
pb->buf);
@@ -122,7 +122,7 @@ static int release_inode_block(ext2_fils
goto return_abort;

limit = fs->blocksize >> 2;
- for (i = 0, bp = (blk_t *) pb->buf;
+ for (i = 0, bp = (pblk_t *) pb->buf;
i < limit; i++, bp++)
if (*bp)
return 0;
@@ -423,7 +423,7 @@ void check_resize_inode(e2fsck_t ctx)
for (j = 1; j < fs->group_desc_count; j++) {
if (!ext2fs_bg_has_super(fs, j))
continue;
- expect = pblk + (j * fs->super->s_blocks_per_group);
+ expect = pblk + (j * (blk_t)fs->super->s_blocks_per_group);
if (ind_buf[ind_off] != expect)
goto resize_inode_invalid;
ind_off++;
Index: e2fsprogs-1.39/ext2ed/blockbitmap_com.c
===================================================================
--- e2fsprogs-1.39.orig/ext2ed/blockbitmap_com.c 2006-09-19 19:18:10.000000000 +0200
+++ e2fsprogs-1.39/ext2ed/blockbitmap_com.c 2006-09-19 19:20:58.000000000 +0200
@@ -249,7 +249,7 @@ The current position (as known from bloc
wprintw (show_win,"Block bitmap of block group %ld\n",block_bitmap_info.group_num);
/* Show the block number */

- block_num=block_bitmap_info.entry_num+block_bitmap_info.group_num*file_system_info.super_block.s_blocks_per_group;
+ block_num=block_bitmap_info.entry_num+block_bitmap_info.group_num*(blk_t)file_system_info.super_block.s_blocks_per_group;
block_num+=file_system_info.super_block.s_first_data_block;

wprintw (show_win,"Status of block %ld - ",block_num); /* and the allocation status */
Index: e2fsprogs-1.39/ext2ed/ext2ed.h
===================================================================
--- e2fsprogs-1.39.orig/ext2ed/ext2ed.h 2006-09-19 19:18:10.000000000 +0200
+++ e2fsprogs-1.39/ext2ed/ext2ed.h 2006-09-19 19:20:58.000000000 +0200
@@ -202,7 +202,7 @@ extern int ForceDefault;
extern char device_name [80];
extern char last_command_line [80];
extern FILE *device_handle;
-extern long device_offset;
+extern blk_t device_offset;
extern int mounted;

extern short block_size;
Index: e2fsprogs-1.39/ext2ed/group_com.c
===================================================================
--- e2fsprogs-1.39.orig/ext2ed/group_com.c 2006-09-19 19:18:10.000000000 +0200
+++ e2fsprogs-1.39/ext2ed/group_com.c 2006-09-19 20:50:27.000000000 +0200
@@ -90,7 +90,7 @@ void type_ext2_group_desc___gocopy (char

copy_num=atol (buffer);

- offset=file_system_info.first_group_desc_offset+copy_num*file_system_info.super_block.s_blocks_per_group*file_system_info.block_size;
+ offset=file_system_info.first_group_desc_offset+copy_num*(blk_t)file_system_info.super_block.s_blocks_per_group*file_system_info.block_size;

if (offset > file_system_info.file_system_size) {
wprintw (command_win,"Error - Copy number out of bounds\n");refresh_command_win ();return;
@@ -134,39 +134,39 @@ void type_ext2_group_desc___show (char *
void type_ext2_group_desc___inode (char *command_line)

{
- long inode_offset;
+ blk_t inode_offset;
char buffer [80];

inode_offset=type_data.u.t_ext2_group_desc.bg_inode_table;
- sprintf (buffer,"setoffset block %ld",inode_offset);dispatch (buffer);
+ sprintf (buffer,"setoffset block %lu",inode_offset);dispatch (buffer);
sprintf (buffer,"settype ext2_inode");dispatch (buffer);
}

void type_ext2_group_desc___blockbitmap (char *command_line)

{
- long block_bitmap_offset;
+ blk_t block_bitmap_offset;
char buffer [80];

block_bitmap_info.entry_num=0;
block_bitmap_info.group_num=group_info.group_num;

block_bitmap_offset=type_data.u.t_ext2_group_desc.bg_block_bitmap;
- sprintf (buffer,"setoffset block %ld",block_bitmap_offset);dispatch (buffer);
+ sprintf (buffer,"setoffset block %lu",block_bitmap_offset);dispatch (buffer);
sprintf (buffer,"settype block_bitmap");dispatch (buffer);
}

void type_ext2_group_desc___inodebitmap (char *command_line)

{
- long inode_bitmap_offset;
+ blk_t inode_bitmap_offset;
char buffer [80];

inode_bitmap_info.entry_num=0;
inode_bitmap_info.group_num=group_info.group_num;

inode_bitmap_offset=type_data.u.t_ext2_group_desc.bg_inode_bitmap;
- sprintf (buffer,"setoffset block %ld",inode_bitmap_offset);dispatch (buffer);
+ sprintf (buffer,"setoffset block %lu",inode_bitmap_offset);dispatch (buffer);
sprintf (buffer,"settype inode_bitmap");dispatch (buffer);
}

Index: e2fsprogs-1.39/ext2ed/inode_com.c
===================================================================
--- e2fsprogs-1.39.orig/ext2ed/inode_com.c 2006-09-19 19:18:10.000000000 +0200
+++ e2fsprogs-1.39/ext2ed/inode_com.c 2006-09-19 20:50:27.000000000 +0200
@@ -25,7 +25,8 @@ void type_ext2_inode___prev (char *comma

char *ptr,buffer [80];

- long group_num,group_offset,entry_num,block_num,first_entry,last_entry;
+ blk_t block_num,group_offset;
+ long group_num,entry_num,first_entry,last_entry;
long inode_num,mult=1;
struct ext2_group_desc desc;

@@ -52,7 +53,7 @@ void type_ext2_inode___prev (char *comma
device_offset-=sizeof (struct ext2_inode)*mult;
entry_num-=mult;

- sprintf (buffer,"setoffset %ld",device_offset);dispatch (buffer);
+ sprintf (buffer,"setoffset %lu",device_offset);dispatch (buffer);
strcpy (buffer,"show");dispatch (buffer);
}

@@ -72,7 +73,8 @@ void type_ext2_inode___next (char *comma

char *ptr,buffer [80];

- long group_num,group_offset,entry_num,block_num,first_entry,last_entry;
+ blk_t group_offset,block_num;
+ long group_num,entry_num,first_entry,last_entry;
long inode_num,mult=1;
struct ext2_group_desc desc;

@@ -123,7 +125,8 @@ void type_ext2_inode___show (char *comma
unsigned short temp;
int i;

- long group_num,group_offset,entry_num,block_num,first_entry,last_entry,inode_num;
+ blk_t group_offset,block_num;
+ long group_num,entry_num,first_entry,last_entry,inode_num;
struct ext2_group_desc desc;

block_num=device_offset/file_system_info.block_size;
@@ -284,7 +287,8 @@ void type_ext2_inode___entry (char *comm
{
char *ptr,buffer [80];

- long group_num,group_offset,entry_num,block_num,wanted_entry;
+ blk_t group_offset,block_num;
+ long group_num,entry_num,wanted_entry;
struct ext2_group_desc desc;

ptr=parse_word (command_line,buffer);
@@ -372,7 +376,8 @@ long inode_offset_to_group_num (long ino
int found=0;
struct ext2_group_desc desc;

- long block_num,group_offset,group_num;
+ blk_t block_num,group_offset;
+ long group_num;

block_num=inode_offset/file_system_info.block_size;

@@ -399,7 +404,8 @@ long inode_offset_to_group_num (long ino
long int inode_offset_to_inode_num (long inode_offset)

{
- long group_num,group_offset,entry_num,block_num,first_entry,last_entry,inode_num;
+ blk_t group_offset, block_num;
+ long group_num,entry_num,first_entry,last_entry,inode_num;
struct ext2_group_desc desc;

block_num=inode_offset/file_system_info.block_size;
@@ -409,7 +415,9 @@ long int inode_offset_to_inode_num (long

low_read ((char *) &desc,sizeof (struct ext2_group_desc),group_offset);

- entry_num=(inode_offset-desc.bg_inode_table*file_system_info.block_size)/sizeof (struct ext2_inode);
+ entry_num=((inode_offset-desc.bg_inode_table*file_system_info.block_size)/sizeof(struct ext2_inode);
+ file_system_info.block_size)/
+ sizeof (struct ext2_inode);
first_entry=0;last_entry=file_system_info.super_block.s_inodes_per_group-1;
inode_num=group_num*file_system_info.super_block.s_inodes_per_group+1;
inode_num+=entry_num;
@@ -420,7 +428,8 @@ long int inode_offset_to_inode_num (long
long int inode_num_to_inode_offset (long inode_num)

{
- long group_num,group_offset,inode_offset,inode_entry;
+ blk_t group_offset, inode_offset;
+ long group_num,inode_entry;
struct ext2_group_desc desc;

inode_num--;
Index: e2fsprogs-1.39/ext2ed/main.c
===================================================================
--- e2fsprogs-1.39.orig/ext2ed/main.c 2006-09-19 19:18:10.000000000 +0200
+++ e2fsprogs-1.39/ext2ed/main.c 2006-09-19 19:20:58.000000000 +0200
@@ -69,7 +69,7 @@ char last_command_line [80]; /* A simp

char device_name [80]; /* The location of the filesystem */
FILE *device_handle=NULL; /* This is passed to the fopen / fread ... commands */
-long device_offset; /* The current position in the filesystem */
+blk_t device_offset; /* The current position in the filesystem */
/* Note that we have a 2 GB limitation */

int mounted=0; /* This is set when we find that the filesystem is mounted */
Index: e2fsprogs-1.39/lib/ext2fs/badblocks.c
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/badblocks.c 2006-09-19 19:18:10.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/badblocks.c 2006-09-19 19:20:58.000000000 +0200
@@ -42,15 +42,15 @@ static errcode_t make_u32_list(int size,
bb->magic = EXT2_ET_MAGIC_BADBLOCKS_LIST;
bb->size = size ? size : 10;
bb->num = num;
- retval = ext2fs_get_mem(bb->size * sizeof(blk_t), &bb->list);
+ retval = ext2fs_get_mem(bb->size * sizeof(pblk_t), &bb->list);
if (!bb->list) {
ext2fs_free_mem(&bb);
return retval;
}
if (list)
- memcpy(bb->list, list, bb->size * sizeof(blk_t));
+ memcpy(bb->list, list, bb->size * sizeof(pblk_t));
else
- memset(bb->list, 0, bb->size * sizeof(blk_t));
+ memset(bb->list, 0, bb->size * sizeof(pblk_t));
*ret = bb;
return 0;
}
@@ -282,8 +282,13 @@ int ext2fs_u32_list_iterate(ext2_u32_ite

int ext2fs_badblocks_list_iterate(ext2_badblocks_iterate iter, blk_t *blk)
{
- return ext2fs_u32_list_iterate((ext2_u32_iterate) iter,
- (__u32 *) blk);
+ int ret;
+ __u32 b = *blk;
+
+ ret = ext2fs_u32_list_iterate((ext2_u32_iterate) iter,
+ &b);
+ *blk = b;
+ return ret;
}


@@ -310,7 +315,7 @@ int ext2fs_u32_list_equal(ext2_u32_list
if (bb1->num != bb2->num)
return 0;

- if (memcmp(bb1->list, bb2->list, bb1->num * sizeof(blk_t)) != 0)
+ if (memcmp(bb1->list, bb2->list, bb1->num * sizeof(pblk_t)) != 0)
return 0;
return 1;
}
Index: e2fsprogs-1.39/lib/ext2fs/bb_inode.c
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/bb_inode.c 2006-09-19 19:18:10.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/bb_inode.c 2006-09-19 20:50:27.000000000 +0200
@@ -33,7 +33,7 @@
struct set_badblock_record {
ext2_badblocks_iterate bb_iter;
int bad_block_count;
- blk_t *ind_blocks;
+ pblk_t *ind_blocks;
int max_ind_blocks;
int ind_blocks_size;
int ind_blocks_ptr;
@@ -68,11 +68,11 @@ errcode_t ext2fs_update_bb_inode(ext2_fi
rec.bad_block_count = 0;
rec.ind_blocks_size = rec.ind_blocks_ptr = 0;
rec.max_ind_blocks = 10;
- retval = ext2fs_get_mem(rec.max_ind_blocks * sizeof(blk_t),
+ retval = ext2fs_get_mem(rec.max_ind_blocks * sizeof(pblk_t),
&rec.ind_blocks);
if (retval)
return retval;
- memset(rec.ind_blocks, 0, rec.max_ind_blocks * sizeof(blk_t));
+ memset(rec.ind_blocks, 0, rec.max_ind_blocks * sizeof(pblk_t));
retval = ext2fs_get_mem(fs->blocksize, &rec.block_buf);
if (retval)
goto cleanup;
@@ -174,10 +174,10 @@ static int clear_bad_block_proc(ext2_fil

if (blockcnt < 0) {
if (rec->ind_blocks_size >= rec->max_ind_blocks) {
- old_size = rec->max_ind_blocks * sizeof(blk_t);
+ old_size = rec->max_ind_blocks * sizeof(pblk_t);
rec->max_ind_blocks += 10;
retval = ext2fs_resize_mem(old_size,
- rec->max_ind_blocks * sizeof(blk_t),
+ rec->max_ind_blocks * sizeof(pblk_t),
&rec->ind_blocks);
if (retval) {
rec->max_ind_blocks -= 10;
Index: e2fsprogs-1.39/lib/ext2fs/bitmaps.c
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/bitmaps.c 2006-09-19 19:18:10.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/bitmaps.c 2006-09-19 20:52:15.000000000 +0200
@@ -27,7 +27,7 @@
#include "ext2_fs.h"
#include "ext2fs.h"

-static errcode_t make_bitmap(__u32 start, __u32 end, __u32 real_end,
+static errcode_t make_bitmap(blk_t start, blk_t end, blk_t real_end,
const char *descr, char *init_map,
ext2fs_generic_bitmap *ret)
{
@@ -72,9 +72,9 @@ static errcode_t make_bitmap(__u32 start
return 0;
}

-errcode_t ext2fs_allocate_generic_bitmap(__u32 start,
- __u32 end,
- __u32 real_end,
+errcode_t ext2fs_allocate_generic_bitmap(blk_t start,
+ blk_t end,
+ blk_t real_end,
const char *descr,
ext2fs_generic_bitmap *ret)
{
@@ -100,7 +100,7 @@ errcode_t ext2fs_copy_bitmap(ext2fs_gene

void ext2fs_set_bitmap_padding(ext2fs_generic_bitmap map)
{
- __u32 i, j;
+ blk_t i, j;

/* Protect loop from wrap-around if map->real_end is maxed */
for (i=map->end+1, j = i - map->start;
@@ -117,7 +117,7 @@ errcode_t ext2fs_allocate_inode_bitmap(e
{
ext2fs_inode_bitmap bitmap;
errcode_t retval;
- __u32 start, end, real_end;
+ blk_t start, end, real_end;

EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);

@@ -146,7 +146,7 @@ errcode_t ext2fs_allocate_block_bitmap(e
{
ext2fs_block_bitmap bitmap;
errcode_t retval;
- __u32 start, end, real_end;
+ blk_t start, end, real_end;

EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);

Index: e2fsprogs-1.39/lib/ext2fs/block.c
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/block.c 2006-09-19 19:20:58.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/block.c 2006-09-19 20:50:27.000000000 +0200
@@ -33,7 +33,7 @@ static int block_iterate_ind(blk_t *ind_
{
int ret = 0, changed = 0;
int i, flags, limit, offset;
- blk_t *block_nr;
+ pblk_t *block_nr;

limit = ctx->fs->blocksize >> 2;
if (!(ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
@@ -58,33 +58,38 @@ static int block_iterate_ind(blk_t *ind_
return ret;
}

- block_nr = (blk_t *) ctx->ind_buf;
+ block_nr = (pblk_t *) ctx->ind_buf;
offset = 0;
if (ctx->flags & BLOCK_FLAG_APPEND) {
for (i = 0; i < limit; i++, ctx->bcount++, block_nr++) {
- flags = (*ctx->func)(ctx->fs, block_nr, ctx->bcount,
+ blk_t b = *block_nr;
+ flags = (*ctx->func)(ctx->fs, &b, ctx->bcount,
*ind_block, offset,
ctx->priv_data);
+ *block_nr = b;
changed |= flags;
if (flags & BLOCK_ABORT) {
ret |= BLOCK_ABORT;
break;
}
- offset += sizeof(blk_t);
+ offset += sizeof(pblk_t);
}
} else {
for (i = 0; i < limit; i++, ctx->bcount++, block_nr++) {
+ blk_t b;
if (*block_nr == 0)
continue;
- flags = (*ctx->func)(ctx->fs, block_nr, ctx->bcount,
+ b = *block_nr;
+ flags = (*ctx->func)(ctx->fs, &b, ctx->bcount,
*ind_block, offset,
ctx->priv_data);
+ *block_nr = b;
changed |= flags;
if (flags & BLOCK_ABORT) {
ret |= BLOCK_ABORT;
break;
}
- offset += sizeof(blk_t);
+ offset += sizeof(pblk_t);
}
}
if (changed & BLOCK_CHANGED) {
@@ -107,7 +112,7 @@ static int block_iterate_dind(blk_t *din
{
int ret = 0, changed = 0;
int i, flags, limit, offset;
- blk_t *block_nr;
+ pblk_t *block_nr;

limit = ctx->fs->blocksize >> 2;
if (!(ctx->flags & (BLOCK_FLAG_DEPTH_TRAVERSE |
@@ -132,35 +137,41 @@ static int block_iterate_dind(blk_t *din
return ret;
}

- block_nr = (blk_t *) ctx->dind_buf;
+ block_nr = (pblk_t *) ctx->dind_buf;
offset = 0;
if (ctx->flags & BLOCK_FLAG_APPEND) {
for (i = 0; i < limit; i++, block_nr++) {
- flags = block_iterate_ind(block_nr,
+ blk_t b;
+ b = *block_nr;
+ flags = block_iterate_ind(&b,
*dind_block, offset,
ctx);
+ *block_nr = b;
changed |= flags;
if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
break;
}
- offset += sizeof(blk_t);
+ offset += sizeof(pblk_t);
}
} else {
for (i = 0; i < limit; i++, block_nr++) {
+ blk_t b;
if (*block_nr == 0) {
ctx->bcount += limit;
continue;
}
- flags = block_iterate_ind(block_nr,
+ b = *block_nr;
+ flags = block_iterate_ind(&b,
*dind_block, offset,
ctx);
+ *block_nr = b;
changed |= flags;
if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
break;
}
- offset += sizeof(blk_t);
+ offset += sizeof(pblk_t);
}
}
if (changed & BLOCK_CHANGED) {
@@ -183,7 +194,7 @@ static int block_iterate_tind(blk_t *tin
{
int ret = 0, changed = 0;
int i, flags, limit, offset;
- blk_t *block_nr;
+ pblk_t *block_nr;

limit = ctx->fs->blocksize >> 2;
if (!(ctx->flags & (BLOCK_FLAG_DEPTH_TRAVERSE |
@@ -208,35 +219,41 @@ static int block_iterate_tind(blk_t *tin
return ret;
}

- block_nr = (blk_t *) ctx->tind_buf;
+ block_nr = (pblk_t *) ctx->tind_buf;
offset = 0;
if (ctx->flags & BLOCK_FLAG_APPEND) {
for (i = 0; i < limit; i++, block_nr++) {
- flags = block_iterate_dind(block_nr,
+ blk_t b;
+ b = *block_nr;
+ flags = block_iterate_dind(&b,
*tind_block,
offset, ctx);
+ *block_nr = b;
changed |= flags;
if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
break;
}
- offset += sizeof(blk_t);
+ offset += sizeof(pblk_t);
}
} else {
for (i = 0; i < limit; i++, block_nr++) {
+ blk_t b;
if (*block_nr == 0) {
ctx->bcount += limit*limit;
continue;
}
- flags = block_iterate_dind(block_nr,
+ b = *block_nr;
+ flags = block_iterate_dind(&b,
*tind_block,
offset, ctx);
+ *block_nr = b;
changed |= flags;
if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
break;
}
- offset += sizeof(blk_t);
+ offset += sizeof(pblk_t);
}
}
if (changed & BLOCK_CHANGED) {
@@ -269,7 +286,7 @@ errcode_t ext2fs_block_iterate2(ext2_fil
{
int i;
int ret = 0;
- blk_t blocks[EXT2_N_BLOCKS]; /* directory data blocks */
+ pblk_t blocks[EXT2_N_BLOCKS]; /* directory data blocks */
struct ext2_inode inode;
errcode_t retval;
struct block_context ctx;
@@ -319,10 +336,12 @@ errcode_t ext2fs_block_iterate2(ext2_fil
if ((fs->super->s_creator_os == EXT2_OS_HURD) &&
!(flags & BLOCK_FLAG_DATA_ONLY)) {
if (inode.osd1.hurd1.h_i_translator) {
+ blk_t h_i_translator = inode.osd1.hurd1.h_i_translator;
ret |= (*ctx.func)(fs,
- &inode.osd1.hurd1.h_i_translator,
+ &h_i_translator,
BLOCK_COUNT_TRANSLATOR,
0, 0, priv_data);
+ inode.osd1.hurd1.h_i_translator = h_i_translator;
if (ret & BLOCK_ABORT)
goto abort_exit;
}
@@ -346,29 +365,38 @@ errcode_t ext2fs_block_iterate2(ext2_fil
*/
for (i = 0; i < EXT2_NDIR_BLOCKS ; i++, ctx.bcount++) {
if (blocks[i] || (flags & BLOCK_FLAG_APPEND)) {
- ret |= (*ctx.func)(fs, &blocks[i],
+ blk_t b = blocks[i];
+ ret |= (*ctx.func)(fs, &b,
ctx.bcount, 0, i, priv_data);
+ blocks[i] = b;
if (ret & BLOCK_ABORT)
goto abort_exit;
}
}
if (*(blocks + EXT2_IND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) {
- ret |= block_iterate_ind(blocks + EXT2_IND_BLOCK,
+ blk_t b;
+ b = *(blocks + EXT2_IND_BLOCK);
+ ret |= block_iterate_ind(&b,
0, EXT2_IND_BLOCK, &ctx);
+ *(blocks + EXT2_IND_BLOCK) = b;
if (ret & BLOCK_ABORT)
goto abort_exit;
} else
ctx.bcount += limit;
if (*(blocks + EXT2_DIND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) {
- ret |= block_iterate_dind(blocks + EXT2_DIND_BLOCK,
+ blk_t b = *(blocks + EXT2_DIND_BLOCK);
+ ret |= block_iterate_dind(&b,
0, EXT2_DIND_BLOCK, &ctx);
+ *(blocks + EXT2_DIND_BLOCK) = b;
if (ret & BLOCK_ABORT)
goto abort_exit;
} else
ctx.bcount += limit * limit;
if (*(blocks + EXT2_TIND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) {
- ret |= block_iterate_tind(blocks + EXT2_TIND_BLOCK,
+ blk_t b = *(blocks + EXT2_TIND_BLOCK);
+ ret |= block_iterate_tind(&b,
0, EXT2_TIND_BLOCK, &ctx);
+ *(blocks + EXT2_TIND_BLOCK) = b;
if (ret & BLOCK_ABORT)
goto abort_exit;
}
Index: e2fsprogs-1.39/lib/ext2fs/bmap.c
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/bmap.c 2006-09-19 19:20:58.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/bmap.c 2006-09-19 20:50:27.000000000 +0200
@@ -115,11 +115,11 @@ static _BMAP_INLINE_ errcode_t block_ind
(fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))
b = ext2fs_swab32(b);
#endif
- ((blk_t *) block_buf)[nr] = b;
+ ((pblk_t *) block_buf)[nr] = b;
return io_channel_write_blk(fs->io, ind, 1, block_buf);
}

- b = ((blk_t *) block_buf)[nr];
+ b = ((pblk_t *) block_buf)[nr];

#ifdef EXT2FS_ENABLE_SWAPFS
if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
@@ -128,7 +128,7 @@ static _BMAP_INLINE_ errcode_t block_ind
#endif

if (!b && (flags & BMAP_ALLOC)) {
- b = nr ? ((blk_t *) block_buf)[nr-1] : 0;
+ b = nr ? ((pblk_t *) block_buf)[nr-1] : 0;
retval = ext2fs_alloc_block(fs, b,
block_buf + fs->blocksize, &b);
if (retval)
@@ -137,10 +137,10 @@ static _BMAP_INLINE_ errcode_t block_ind
#ifdef EXT2FS_ENABLE_SWAPFS
if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
(fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))
- ((blk_t *) block_buf)[nr] = ext2fs_swab32(b);
+ ((pblk_t *) block_buf)[nr] = ext2fs_swab32(b);
else
#endif
- ((blk_t *) block_buf)[nr] = b;
+ ((pblk_t *) block_buf)[nr] = b;

retval = io_channel_write_blk(fs->io, ind, 1, block_buf);
if (retval)
Index: e2fsprogs-1.39/lib/ext2fs/ext2fs.h
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/ext2fs.h 2006-09-19 19:20:58.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/ext2fs.h 2006-09-19 20:50:27.000000000 +0200
@@ -74,6 +74,7 @@ extern "C" {

typedef __u32 ext2_ino_t;
typedef __u32 blk_t;
+typedef __u32 pblk_t;
typedef __u32 dgrp_t;
typedef __u32 ext2_off_t;
typedef __s64 e2_blkcnt_t;
@@ -105,8 +106,8 @@ typedef struct struct_ext2_filsys *ext2_
struct ext2fs_struct_generic_bitmap {
errcode_t magic;
ext2_filsys fs;
- __u32 start, end;
- __u32 real_end;
+ blk_t start, end;
+ blk_t real_end;
char * description;
char * bitmap;
errcode_t base_error_code;
@@ -217,7 +218,7 @@ struct struct_ext2_filsys {
int inode_blocks_per_group;
ext2fs_inode_bitmap inode_map;
ext2fs_block_bitmap block_map;
- errcode_t (*get_blocks)(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks);
+ errcode_t (*get_blocks)(ext2_filsys fs, ext2_ino_t ino, pblk_t *blocks);
errcode_t (*check_directory)(ext2_filsys fs, ext2_ino_t ino);
errcode_t (*write_bitmaps)(ext2_filsys fs);
errcode_t (*read_inode)(ext2_filsys fs, ext2_ino_t ino,
@@ -427,7 +428,7 @@ typedef struct ext2_icount *ext2_icount_
/*
* For ext2 compression support
*/
-#define EXT2FS_COMPRESSED_BLKADDR ((blk_t) 0xffffffff)
+#define EXT2FS_COMPRESSED_BLKADDR ((blk_t) -1)
#define HOLE_BLKADDR(_b) ((_b) == 0 || (_b) == EXT2FS_COMPRESSED_BLKADDR)

/*
@@ -500,10 +501,10 @@ extern errcode_t ext2fs_allocate_group_t
extern errcode_t ext2fs_u32_list_create(ext2_u32_list *ret, int size);
extern errcode_t ext2fs_u32_list_add(ext2_u32_list bb, __u32 blk);
extern int ext2fs_u32_list_find(ext2_u32_list bb, __u32 blk);
-extern int ext2fs_u32_list_test(ext2_u32_list bb, blk_t blk);
+extern int ext2fs_u32_list_test(ext2_u32_list bb, pblk_t blk);
extern errcode_t ext2fs_u32_list_iterate_begin(ext2_u32_list bb,
ext2_u32_iterate *ret);
-extern int ext2fs_u32_list_iterate(ext2_u32_iterate iter, blk_t *blk);
+extern int ext2fs_u32_list_iterate(ext2_u32_iterate iter, pblk_t *blk);
extern void ext2fs_u32_list_iterate_end(ext2_u32_iterate iter);
extern errcode_t ext2fs_u32_copy(ext2_u32_list src, ext2_u32_list *dest);
extern int ext2fs_u32_list_equal(ext2_u32_list bb1, ext2_u32_list bb2);
@@ -547,9 +548,9 @@ extern errcode_t ext2fs_write_inode_bitm
extern errcode_t ext2fs_write_block_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_allocate_generic_bitmap(__u32 start,
- __u32 end,
- __u32 real_end,
+extern errcode_t ext2fs_allocate_generic_bitmap(blk_t start,
+ blk_t end,
+ blk_t real_end,
const char *descr,
ext2fs_generic_bitmap *ret);
extern errcode_t ext2fs_allocate_block_bitmap(ext2_filsys fs,
@@ -845,7 +846,7 @@ extern errcode_t ext2fs_write_inode(ext2
struct ext2_inode * inode);
extern errcode_t ext2fs_write_new_inode(ext2_filsys fs, ext2_ino_t ino,
struct ext2_inode * inode);
-extern errcode_t ext2fs_get_blocks(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks);
+extern errcode_t ext2fs_get_blocks(ext2_filsys fs, ext2_ino_t ino, pblk_t *blocks);
extern errcode_t ext2fs_check_directory(ext2_filsys fs, ext2_ino_t ino);

/* inode_io.c */
Index: e2fsprogs-1.39/lib/ext2fs/ind_block.c
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/ind_block.c 2006-09-19 19:20:58.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/ind_block.c 2006-09-19 19:20:58.000000000 +0200
@@ -34,7 +34,7 @@ errcode_t ext2fs_read_ind_block(ext2_fil
#ifdef EXT2FS_ENABLE_SWAPFS
if (fs->flags & (EXT2_FLAG_SWAP_BYTES | EXT2_FLAG_SWAP_BYTES_READ)) {
int limit = fs->blocksize >> 2;
- blk_t *block_nr = (blk_t *)buf;
+ pblk_t *block_nr = (pblk_t *)buf;
int i;

for (i = 0; i < limit; i++, block_nr++)
@@ -52,7 +52,7 @@ errcode_t ext2fs_write_ind_block(ext2_fi
#ifdef EXT2FS_ENABLE_SWAPFS
if (fs->flags & (EXT2_FLAG_SWAP_BYTES | EXT2_FLAG_SWAP_BYTES_WRITE)) {
int limit = fs->blocksize >> 2;
- blk_t *block_nr = (blk_t *)buf;
+ pblk_t *block_nr = (pblk_t *)buf;
int i;

for (i = 0; i < limit; i++, block_nr++)
Index: e2fsprogs-1.39/lib/ext2fs/inode.c
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/inode.c 2006-09-19 19:18:10.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/inode.c 2006-09-19 20:50:27.000000000 +0200
@@ -107,7 +107,7 @@ errcode_t ext2fs_open_inode_scan(ext2_fi
{
ext2_inode_scan scan;
errcode_t retval;
- errcode_t (*save_get_blocks)(ext2_filsys f, ext2_ino_t ino, blk_t *blocks);
+ errcode_t (*save_get_blocks)(ext2_filsys f, ext2_ino_t ino, pblk_t *blocks);

EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);

@@ -502,7 +502,8 @@ errcode_t ext2fs_get_next_inode(ext2_ino
errcode_t ext2fs_read_inode_full(ext2_filsys fs, ext2_ino_t ino,
struct ext2_inode * inode, int bufsize)
{
- unsigned long group, block, block_nr, offset;
+ unsigned long group, block, offset;
+ blk_t block_nr;
char *ptr;
errcode_t retval;
int clen, i, inodes_per_block, length;
@@ -608,7 +609,8 @@ errcode_t ext2fs_read_inode(ext2_filsys
errcode_t ext2fs_write_inode_full(ext2_filsys fs, ext2_ino_t ino,
struct ext2_inode * inode, int bufsize)
{
- unsigned long group, block, block_nr, offset;
+ unsigned long group, block, offset;
+ blk_t block_nr;
errcode_t retval = 0;
struct ext2_inode_large temp_inode, *w_inode;
char *ptr;
@@ -753,7 +755,7 @@ errcode_t ext2fs_write_new_inode(ext2_fi
}


-errcode_t ext2fs_get_blocks(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks)
+errcode_t ext2fs_get_blocks(ext2_filsys fs, ext2_ino_t ino, pblk_t *blocks)
{
struct ext2_inode inode;
int i;
Index: e2fsprogs-1.39/lib/ext2fs/res_gdt.c
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/res_gdt.c 2006-09-19 19:18:10.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/res_gdt.c 2006-09-19 19:20:58.000000000 +0200
@@ -166,7 +166,7 @@ errcode_t ext2fs_create_resize_inode(ext

while ((grp = list_backups(fs, &three, &five, &seven)) <
fs->group_desc_count) {
- blk_t expect = gdt_blk + grp * sb->s_blocks_per_group;
+ blk_t expect = gdt_blk + grp * (blk_t)sb->s_blocks_per_group;

if (!gdt_buf[last]) {
#ifdef RES_GDT_DEBUG
Index: e2fsprogs-1.39/lib/ext2fs/tst_iscan.c
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/tst_iscan.c 2006-09-19 19:18:10.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/tst_iscan.c 2006-09-19 20:50:27.000000000 +0200
@@ -171,7 +171,7 @@ static void iterate(void)
static void check_map(void)
{
int i, j, first=1;
- unsigned long blk;
+ blk_t blk;

for (i=0; test_vec[i]; i++) {
if (ext2fs_test_block_bitmap(touched_map, test_vec[i])) {
Index: e2fsprogs-1.39/misc/dumpe2fs.c
===================================================================
--- e2fsprogs-1.39.orig/misc/dumpe2fs.c 2006-09-19 19:18:10.000000000 +0200
+++ e2fsprogs-1.39/misc/dumpe2fs.c 2006-09-19 20:50:27.000000000 +0200
@@ -55,20 +55,20 @@ static void usage(void)
exit (1);
}

-static void print_number(unsigned long num)
+static void print_number(blk_t num)
{
if (hex_format)
- printf("0x%04lx", num);
+ printf("0x%04x", num);
else
- printf("%lu", num);
+ printf("%u", num);
}

-static void print_range(unsigned long a, unsigned long b)
+static void print_range(blk_t a, blk_t b)
{
if (hex_format)
- printf("0x%04lx-0x%04lx", a, b);
+ printf("0x%04x-0x%04x", a, b);
else
- printf("%lu-%lu", a, b);
+ printf("%u-%u", a, b);
}

static void print_free (unsigned long group, char * bitmap,
Index: e2fsprogs-1.39/misc/e2image.c
===================================================================
--- e2fsprogs-1.39.orig/misc/e2image.c 2006-09-19 19:18:10.000000000 +0200
+++ e2fsprogs-1.39/misc/e2image.c 2006-09-19 20:50:27.000000000 +0200
@@ -165,7 +165,7 @@ static struct ext2_inode *stashed_inode;

static errcode_t meta_get_blocks(ext2_filsys fs EXT2FS_ATTR((unused)),
ext2_ino_t ino,
- blk_t *blocks)
+ pblk_t *blocks)
{
int i;

Index: e2fsprogs-1.39/misc/mke2fs.c
===================================================================
--- e2fsprogs-1.39.orig/misc/mke2fs.c 2006-09-19 19:18:10.000000000 +0200
+++ e2fsprogs-1.39/misc/mke2fs.c 2006-09-19 20:50:27.000000000 +0200
@@ -684,10 +684,10 @@ static void show_stats(ext2_filsys fs)
100.0 * s->s_r_blocks_count / s->s_blocks_count);
printf(_("First data block=%u\n"), s->s_first_data_block);
if (s->s_reserved_gdt_blocks)
- printf(_("Maximum filesystem blocks=%lu\n"),
- (s->s_reserved_gdt_blocks + fs->desc_blocks) *
+ printf(_("Maximum filesystem blocks=%u\n"),
+ (blk_t)((s->s_reserved_gdt_blocks + fs->desc_blocks) *
(fs->blocksize / sizeof(struct ext2_group_desc)) *
- s->s_blocks_per_group);
+ s->s_blocks_per_group));
if (fs->group_desc_count > 1)
printf(_("%u block groups\n"), fs->group_desc_count);
else
@@ -1399,13 +1399,6 @@ static void PRS(int argc, char *argv[])
}
}

- if (!force && fs_param.s_blocks_count >= (1 << 31)) {
- com_err(program_name, 0,
- _("Filesystem too large. No more than 2**31-1 blocks\n"
- "\t (8TB using a blocksize of 4k) are currently supported."));
- exit(1);
- }
-
if ((blocksize > 4096) &&
(fs_param.s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
fprintf(stderr, _("\nWarning: some 2.4 kernels do not support "
Index: e2fsprogs-1.39/misc/tune2fs.c
===================================================================
--- e2fsprogs-1.39.orig/misc/tune2fs.c 2006-09-19 19:18:10.000000000 +0200
+++ e2fsprogs-1.39/misc/tune2fs.c 2006-09-19 20:50:27.000000000 +0200
@@ -64,7 +64,8 @@ static int m_flag, M_flag, r_flag, s_fla
static time_t last_check_time;
static int print_label;
static int max_mount_count, mount_count, mount_flags;
-static unsigned long interval, reserved_blocks;
+static unsigned long interval;
+static blk_t reserved_blocks;
static double reserved_ratio;
static unsigned long resgid, resuid;
static unsigned short errors;
@@ -832,13 +833,13 @@ int main (int argc, char ** argv)
if (r_flag) {
if (reserved_blocks >= sb->s_blocks_count/2) {
com_err (program_name, 0,
- _("reserved blocks count is too big (%lu)"),
+ _("reserved blocks count is too big (%u)"),
reserved_blocks);
exit (1);
}
sb->s_r_blocks_count = reserved_blocks;
ext2fs_mark_super_dirty(fs);
- printf (_("Setting reserved blocks count to %lu\n"),
+ printf (_("Setting reserved blocks count to %u\n"),
reserved_blocks);
}
if (s_flag == 1) {
Index: e2fsprogs-1.39/resize/resize2fs.c
===================================================================
--- e2fsprogs-1.39.orig/resize/resize2fs.c 2006-09-19 19:18:10.000000000 +0200
+++ e2fsprogs-1.39/resize/resize2fs.c 2006-09-19 20:50:27.000000000 +0200
@@ -901,7 +901,8 @@ static blk_t get_new_block(ext2_resize_t

static errcode_t block_mover(ext2_resize_t rfs)
{
- blk_t blk, old_blk, new_blk;
+ blk_t blk;
+ pblk_t old_blk, new_blk;
ext2_filsys fs = rfs->new_fs;
ext2_filsys old_fs = rfs->old_fs;
errcode_t retval;
Index: e2fsprogs-1.39/lib/ext2fs/bitops.c
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/bitops.c 2006-09-19 20:50:27.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/bitops.c 2006-09-19 20:52:15.000000000 +0200
@@ -30,7 +30,7 @@
* systems, as well as non-32 bit systems.
*/

-int ext2fs_set_bit(unsigned int nr,void * addr)
+int ext2fs_set_bit(blk_t nr,void * addr)
{
int mask, retval;
unsigned char *ADDR = (unsigned char *) addr;
@@ -42,7 +42,7 @@ int ext2fs_set_bit(unsigned int nr,void
return retval;
}

-int ext2fs_clear_bit(unsigned int nr, void * addr)
+int ext2fs_clear_bit(blk_t nr, void * addr)
{
int mask, retval;
unsigned char *ADDR = (unsigned char *) addr;
@@ -54,7 +54,7 @@ int ext2fs_clear_bit(unsigned int nr, vo
return retval;
}

-int ext2fs_test_bit(unsigned int nr, const void * addr)
+int ext2fs_test_bit(blk_t nr, const void * addr)
{
int mask;
const unsigned char *ADDR = (const unsigned char *) addr;
Index: e2fsprogs-1.39/lib/ext2fs/gen_bitmap.c
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/gen_bitmap.c 2006-09-19 20:50:27.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/gen_bitmap.c 2006-09-19 20:52:15.000000000 +0200
@@ -28,7 +28,7 @@
#include "ext2fs.h"

int ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap,
- __u32 bitno)
+ blk_t bitno)
{
if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
ext2fs_warn_bitmap2(bitmap, EXT2FS_MARK_ERROR, bitno);
Index: e2fsprogs-1.39/lib/ext2fs/bitops.h
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/bitops.h 2006-09-19 20:50:27.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/bitops.h 2006-09-19 20:52:15.000000000 +0200
@@ -14,11 +14,11 @@
*/


-extern int ext2fs_set_bit(unsigned int nr,void * addr);
-extern int ext2fs_clear_bit(unsigned int nr, void * addr);
-extern int ext2fs_test_bit(unsigned int nr, const void * addr);
-extern void ext2fs_fast_set_bit(unsigned int nr,void * addr);
-extern void ext2fs_fast_clear_bit(unsigned int nr, void * addr);
+extern int ext2fs_set_bit(blk_t nr,void * addr);
+extern int ext2fs_clear_bit(blk_t nr, void * addr);
+extern int ext2fs_test_bit(blk_t nr, const void * addr);
+extern void ext2fs_fast_set_bit(blk_t nr,void * addr);
+extern void ext2fs_fast_clear_bit(blk_t nr, void * addr);
extern __u16 ext2fs_swab16(__u16 val);
extern __u32 ext2fs_swab32(__u32 val);

@@ -105,7 +105,7 @@ extern void ext2fs_set_bitmap_padding(ex

/* These two routines moved to gen_bitmap.c */
extern int ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap,
- __u32 bitno);
+ blk_t bitno);
extern int ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap,
blk_t bitno);
/*
@@ -140,7 +140,7 @@ extern int ext2fs_unmark_generic_bitmap(
* previous bit value.
*/

-_INLINE_ void ext2fs_fast_set_bit(unsigned int nr,void * addr)
+_INLINE_ void ext2fs_fast_set_bit(blk_t nr,void * addr)
{
unsigned char *ADDR = (unsigned char *) addr;

@@ -148,7 +148,7 @@ _INLINE_ void ext2fs_fast_set_bit(unsign
*ADDR |= (1 << (nr & 0x07));
}

-_INLINE_ void ext2fs_fast_clear_bit(unsigned int nr, void * addr)
+_INLINE_ void ext2fs_fast_clear_bit(blk_t nr, void * addr)
{
unsigned char *ADDR = (unsigned char *) addr;

@@ -158,7 +158,8 @@ _INLINE_ void ext2fs_fast_clear_bit(unsi


#if ((defined __GNUC__) && !defined(_EXT2_USE_C_VERSIONS_) && \
- (defined(__i386__) || defined(__i486__) || defined(__i586__)))
+ (defined(__i386__) || defined(__i486__) || defined(__i586__)) && \
+ !(defined(_EXT2_64BIT_BLK_T) && (SIZEOF_LONG == 4)))

#define _EXT2_HAVE_ASM_BITOPS_
#define _EXT2_HAVE_ASM_SWAB_
@@ -179,7 +180,7 @@ struct __dummy_h { unsigned long a[100];
#define EXT2FS_ADDR (*(struct __dummy_h *) addr)
#define EXT2FS_CONST_ADDR (*(const struct __dummy_h *) addr)

-_INLINE_ int ext2fs_set_bit(unsigned int nr, void * addr)
+_INLINE_ int ext2fs_set_bit(blk_t nr, void * addr)
{
int oldbit;

@@ -190,7 +191,7 @@ _INLINE_ int ext2fs_set_bit(unsigned int
return oldbit;
}

-_INLINE_ int ext2fs_clear_bit(unsigned int nr, void * addr)
+_INLINE_ int ext2fs_clear_bit(blk_t nr, void * addr)
{
int oldbit;

@@ -201,7 +202,7 @@ _INLINE_ int ext2fs_clear_bit(unsigned i
return oldbit;
}

-_INLINE_ int ext2fs_test_bit(unsigned int nr, const void * addr)
+_INLINE_ int ext2fs_test_bit(blk_t nr, const void * addr)
{
int oldbit;

@@ -305,7 +306,7 @@ _INLINE_ __u64 ext2fs_swab64(__u64 val)

#define _EXT2_HAVE_ASM_BITOPS_

-_INLINE_ int ext2fs_set_bit(unsigned int nr,void * addr)
+_INLINE_ int ext2fs_set_bit(blk_t nr,void * addr)
{
char retval;

@@ -315,7 +316,7 @@ _INLINE_ int ext2fs_set_bit(unsigned int
return retval;
}

-_INLINE_ int ext2fs_clear_bit(unsigned int nr, void * addr)
+_INLINE_ int ext2fs_clear_bit(blk_t nr, void * addr)
{
char retval;

@@ -325,7 +326,7 @@ _INLINE_ int ext2fs_clear_bit(unsigned i
return retval;
}

-_INLINE_ int ext2fs_test_bit(unsigned int nr, const void * addr)
+_INLINE_ int ext2fs_test_bit(blk_t nr, const void * addr)
{
char retval;


2006-09-26 14:48:17

by Alexandre Ratchov

[permalink] [raw]
Subject: [patch 06/12] rfc: 2fsprogs update

From: Andreas Dilger

Verify in-inode EA structure.
Allow in-inode EAs to have a checksum.
Connect zero-length inodes that have an EA to lost+found.

Index: e2fsprogs-1.39/e2fsck/e2fsck.h
===================================================================
--- e2fsprogs-1.39.orig/e2fsck/e2fsck.h 2006-09-18 17:43:00.000000000 +0200
+++ e2fsprogs-1.39/e2fsck/e2fsck.h 2006-09-18 17:48:52.000000000 +0200
@@ -466,6 +466,9 @@ extern void init_resource_track(struct r
extern int inode_has_valid_blocks(struct ext2_inode *inode);
extern void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
struct ext2_inode * inode, const char * proc);
+extern void e2fsck_read_inode_full(e2fsck_t ctx, unsigned long ino,
+ struct ext2_inode *inode,
+ const int bufsize, const char *proc);
extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
struct ext2_inode * inode, const char * proc);
extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
Index: e2fsprogs-1.39/e2fsck/pass1.c
===================================================================
--- e2fsprogs-1.39.orig/e2fsck/pass1.c 2006-09-18 17:45:27.000000000 +0200
+++ e2fsprogs-1.39/e2fsck/pass1.c 2006-09-18 20:44:26.000000000 +0200
@@ -248,13 +248,13 @@ static void check_ea_in_inode(e2fsck_t c
struct ext2_super_block *sb = ctx->fs->super;
struct ext2_inode_large *inode;
struct ext2_ext_attr_entry *entry;
- char *start, *end, *name;
+ char *start, *end;
int storage_size, remain, offs;
int problem = 0;

inode = (struct ext2_inode_large *) pctx->inode;
- storage_size = EXT2_INODE_SIZE(ctx->fs->super) - EXT2_GOOD_OLD_INODE_SIZE -
- inode->i_extra_isize;
+ storage_size = EXT2_INODE_SIZE(ctx->fs->super) -
+ EXT2_GOOD_OLD_INODE_SIZE - inode->i_extra_isize;
start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
inode->i_extra_isize + sizeof(__u32);
end = (char *) inode + EXT2_INODE_SIZE(ctx->fs->super);
@@ -267,6 +267,7 @@ static void check_ea_in_inode(e2fsck_t c
offs = end - start;

while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
+ __u32 hash;

/* header eats this space */
remain -= sizeof(struct ext2_ext_attr_entry);
@@ -291,7 +292,9 @@ static void check_ea_in_inode(e2fsck_t c
/* check value placement */
if (entry->e_value_offs +
EXT2_XATTR_SIZE(entry->e_value_size) != offs) {
- printf("(entry->e_value_offs + entry->e_value_size: %d, offs: %d)\n", entry->e_value_offs + entry->e_value_size, offs);
+ printf("entry->e_value_offs + entry->e_value_size: "
+ "%d, offs: %d\n",
+ entry->e_value_offs + entry->e_value_size, offs);
pctx->num = entry->e_value_offs;
problem = PR_1_ATTR_VALUE_OFFSET;
goto fix;
@@ -304,8 +307,11 @@ static void check_ea_in_inode(e2fsck_t c
goto fix;
}

- /* e_hash must be 0 in inode's ea */
- if (entry->e_hash != 0) {
+ hash = ext2fs_ext_attr_hash_entry(entry,
+ start + entry->e_value_offs);
+
+ /* e_hash may be 0 in older inode's ea */
+ if (entry->e_hash != 0 && entry->e_hash != hash) {
pctx->num = entry->e_hash;
problem = PR_1_ATTR_HASH;
goto fix;
@@ -321,15 +327,12 @@ fix:
* it seems like a corruption. it's very unlikely we could repair
* EA(s) in automatic fashion -bzzz
*/
-#if 0
- problem = PR_1_ATTR_HASH;
-#endif
if (problem == 0 || !fix_problem(ctx, problem, pctx))
return;

- /* simple remove all possible EA(s) */
+ /* simple remove all remaining EA(s) */
*((__u32 *)start) = 0UL;
- e2fsck_write_inode_full(ctx, pctx->ino, inode,
+ e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode,
EXT2_INODE_SIZE(sb), "pass1");
}

@@ -1320,10 +1323,13 @@ static int check_ext_attr(e2fsck_t ctx,
entry = (struct ext2_ext_attr_entry *)(header+1);
end = block_buf + fs->blocksize;
while ((char *)entry < end && *(__u32 *)entry) {
+ __u32 hash;
+
if (region_allocate(region, (char *)entry - (char *)header,
EXT2_EXT_ATTR_LEN(entry->e_name_len))) {
if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
goto clear_extattr;
+ break;
}
if ((ctx->ext_attr_ver == 1 &&
(entry->e_name_len == 0 || entry->e_name_index != 0)) ||
@@ -1331,6 +1337,7 @@ static int check_ext_attr(e2fsck_t ctx,
entry->e_name_index == 0)) {
if (fix_problem(ctx, PR_1_EA_BAD_NAME, pctx))
goto clear_extattr;
+ break;
}
if (entry->e_value_block != 0) {
if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx))
@@ -1342,6 +1349,17 @@ static int check_ext_attr(e2fsck_t ctx,
if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
goto clear_extattr;
}
+
+ hash = ext2fs_ext_attr_hash_entry(entry, block_buf +
+ entry->e_value_offs);
+
+ if (entry->e_hash != hash) {
+ pctx->num = entry->e_hash;
+ if (fix_problem(ctx, PR_1_ATTR_HASH, pctx))
+ goto clear_extattr;
+ entry->e_hash = hash;
+ }
+
entry = EXT2_EXT_ATTR_NEXT(entry);
}
if (region_allocate(region, (char *)entry - (char *)header, 4)) {
@@ -1604,8 +1622,11 @@ static void check_blocks(e2fsck_t ctx, s
}
}

- if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf))
+ if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf)) {
+ if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+ goto out;
pb.num_blocks++;
+ }

if (ext2fs_inode_has_valid_blocks(inode)) {
int problem = 0;
Index: e2fsprogs-1.39/e2fsck/pass4.c
===================================================================
--- e2fsprogs-1.39.orig/e2fsck/pass4.c 2006-09-18 17:42:57.000000000 +0200
+++ e2fsprogs-1.39/e2fsck/pass4.c 2006-09-18 17:51:01.000000000 +0200
@@ -15,6 +15,7 @@

#include "e2fsck.h"
#include "problem.h"
+#include <ext2fs/ext2_ext_attr.h>

/*
* This routine is called when an inode is not connected to the
@@ -23,31 +24,42 @@
* This subroutine returns 1 then the caller shouldn't bother with the
* rest of the pass 4 tests.
*/
-static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i)
+static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i,
+ struct ext2_inode *inode)
{
ext2_filsys fs = ctx->fs;
- struct ext2_inode inode;
struct problem_context pctx;
-
- e2fsck_read_inode(ctx, i, &inode, "pass4: disconnect_inode");
+ __u32 eamagic = 0;
+ int extra_size = 0;
+ int rc = 0;
+
+ if (EXT2_INODE_SIZE(fs->super) > EXT2_GOOD_OLD_INODE_SIZE) {
+ e2fsck_read_inode_full(ctx, i, inode,EXT2_INODE_SIZE(fs->super),
+ "pass4: disconnect_inode");
+ extra_size = ((struct ext2_inode_large *)inode)->i_extra_isize;
+ } else {
+ e2fsck_read_inode(ctx, i, inode, "pass4: disconnect_inode");
+ }
clear_problem_context(&pctx);
pctx.ino = i;
- pctx.inode = &inode;
+ pctx.inode = inode;

+ if (EXT2_INODE_SIZE(fs->super) -EXT2_GOOD_OLD_INODE_SIZE -extra_size >0)
+ eamagic = *(__u32 *)(((char *)inode) +EXT2_GOOD_OLD_INODE_SIZE +
+ extra_size);
/*
* Offer to delete any zero-length files that does not have
* blocks. If there is an EA block, it might have useful
* information, so we won't prompt to delete it, but let it be
* reconnected to lost+found.
*/
- if (!inode.i_blocks && (LINUX_S_ISREG(inode.i_mode) ||
- LINUX_S_ISDIR(inode.i_mode))) {
+ if (!inode->i_blocks && eamagic != EXT2_EXT_ATTR_MAGIC &&
+ (LINUX_S_ISREG(inode->i_mode) || LINUX_S_ISDIR(inode->i_mode))) {
if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) {
ext2fs_icount_store(ctx->inode_link_info, i, 0);
- inode.i_links_count = 0;
- inode.i_dtime = ctx->now;
- e2fsck_write_inode(ctx, i, &inode,
- "disconnect_inode");
+ inode->i_links_count = 0;
+ inode->i_dtime = ctx->now;
+ e2fsck_write_inode(ctx, i, inode, "disconnect_inode");
/*
* Fix up the bitmaps...
*/
@@ -55,7 +67,7 @@ static int disconnect_inode(e2fsck_t ctx
ext2fs_unmark_inode_bitmap(ctx->inode_used_map, i);
ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, i);
ext2fs_inode_alloc_stats2(fs, i, -1,
- LINUX_S_ISDIR(inode.i_mode));
+ LINUX_S_ISDIR(inode->i_mode));
return 0;
}
}
@@ -83,7 +95,7 @@ void e2fsck_pass4(e2fsck_t ctx)
{
ext2_filsys fs = ctx->fs;
ext2_ino_t i;
- struct ext2_inode inode;
+ struct ext2_inode *inode;
#ifdef RESOURCE_TRACK
struct resource_track rtrack;
#endif
@@ -111,6 +123,9 @@ void e2fsck_pass4(e2fsck_t ctx)
if ((ctx->progress)(ctx, 4, 0, maxgroup))
return;

+ inode = e2fsck_allocate_memory(ctx, EXT2_INODE_SIZE(fs->super),
+ "scratch inode");
+
/* Protect loop from wrap-around if s_inodes_count maxed */
for (i=1; i <= fs->super->s_inodes_count && i > 0; i++) {
if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
@@ -138,7 +153,7 @@ void e2fsck_pass4(e2fsck_t ctx)
fs->blocksize, "bad_inode buffer");
if (e2fsck_process_bad_inode(ctx, 0, i, buf))
continue;
- if (disconnect_inode(ctx, i))
+ if (disconnect_inode(ctx, i, inode))
continue;
ext2fs_icount_fetch(ctx->inode_link_info, i,
&link_count);
@@ -146,18 +161,18 @@ void e2fsck_pass4(e2fsck_t ctx)
&link_counted);
}
if (link_counted != link_count) {
- e2fsck_read_inode(ctx, i, &inode, "pass4");
+ e2fsck_read_inode(ctx, i, inode, "pass4");
pctx.ino = i;
- pctx.inode = &inode;
- if (link_count != inode.i_links_count) {
+ pctx.inode = inode;
+ if (link_count != inode->i_links_count) {
pctx.num = link_count;
fix_problem(ctx,
PR_4_INCONSISTENT_COUNT, &pctx);
}
pctx.num = link_counted;
if (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
- inode.i_links_count = link_counted;
- e2fsck_write_inode(ctx, i, &inode, "pass4");
+ inode->i_links_count = link_counted;
+ e2fsck_write_inode(ctx, i, inode, "pass4");
}
}
}
@@ -169,6 +184,8 @@ void e2fsck_pass4(e2fsck_t ctx)
ctx->inode_imagic_map = 0;
if (buf)
ext2fs_free_mem(&buf);
+
+ ext2fs_free_mem(&inode);
#ifdef RESOURCE_TRACK
if (ctx->options & E2F_OPT_TIME2) {
e2fsck_clear_progbar(ctx);
Index: e2fsprogs-1.39/e2fsck/problem.c
===================================================================
--- e2fsprogs-1.39.orig/e2fsck/problem.c 2006-09-18 17:43:00.000000000 +0200
+++ e2fsprogs-1.39/e2fsck/problem.c 2006-09-18 17:48:52.000000000 +0200
@@ -771,7 +771,7 @@ static struct e2fsck_problem problem_tab

/* invalid ea entry->e_hash */
{ PR_1_ATTR_HASH,
- N_("@a in @i %i has a hash (%N) which is @n (must be 0)\n"),
+ N_("@a in @i %i has a hash (%N) which is @n\n"),
PROMPT_CLEAR, PR_PREEN_OK },

/* indirect block corrupt */
Index: e2fsprogs-1.39/e2fsck/util.c
===================================================================
--- e2fsprogs-1.39.orig/e2fsck/util.c 2006-04-24 18:18:04.000000000 +0200
+++ e2fsprogs-1.39/e2fsck/util.c 2006-09-18 17:48:52.000000000 +0200
@@ -361,6 +361,20 @@ void e2fsck_read_inode(e2fsck_t ctx, uns
}
}

+void e2fsck_read_inode_full(e2fsck_t ctx, unsigned long ino,
+ struct ext2_inode *inode, int bufsize,
+ const char *proc)
+{
+ int retval;
+
+ retval = ext2fs_read_inode_full(ctx->fs, ino, inode, bufsize);
+ if (retval) {
+ com_err("ext2fs_read_inode_full", retval,
+ _("while reading inode %ld in %s"), ino, proc);
+ fatal_error(ctx, 0);
+ }
+}
+
extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
struct ext2_inode * inode, int bufsize,
const char *proc)
Index: e2fsprogs-1.39/lib/ext2fs/ext2_ext_attr.h
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/ext2_ext_attr.h 2006-09-18 17:42:57.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/ext2_ext_attr.h 2006-09-18 17:48:52.000000000 +0200
@@ -30,7 +30,7 @@ struct ext2_ext_attr_entry {
__u32 e_value_block; /* disk block attribute is stored on (n/i) */
__u32 e_value_size; /* size of attribute value */
__u32 e_hash; /* hash value of name and value */
-#if 0
+#if 1
char e_name[0]; /* attribute name */
#endif
};
Index: e2fsprogs-1.39/lib/ext2fs/ext2fs.h
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/ext2fs.h 2006-09-18 17:43:00.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/ext2fs.h 2006-09-18 20:44:26.000000000 +0200
@@ -83,10 +83,12 @@ typedef __u32 ext2_dirhash_t;
#include "com_err.h"
#include "ext2_io.h"
#include "ext2_err.h"
+#include "ext2_ext_attr.h"
#else
#include <et/com_err.h>
#include <ext2fs/ext2_io.h>
#include <ext2fs/ext2_err.h>
+#include <ext2fs/ext2_ext_attr.h>
#endif

/*
@@ -704,6 +706,8 @@ extern errcode_t ext2fs_dup_handle(ext2_
extern errcode_t ext2fs_expand_dir(ext2_filsys fs, ext2_ino_t dir);

/* ext_attr.c */
+extern __u32 ext2fs_ext_attr_hash_entry(struct ext2_ext_attr_entry *entry,
+ void *data);
extern errcode_t ext2fs_read_ext_attr(ext2_filsys fs, blk_t block, void *buf);
extern errcode_t ext2fs_write_ext_attr(ext2_filsys fs, blk_t block,
void *buf);
Index: e2fsprogs-1.39/lib/ext2fs/ext_attr.c
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/ext_attr.c 2005-09-06 11:40:14.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/ext_attr.c 2006-09-18 17:48:52.000000000 +0200
@@ -23,6 +23,42 @@

#include "ext2fs.h"

+#define NAME_HASH_SHIFT 5
+#define VALUE_HASH_SHIFT 16
+
+/*
+ * ext2_xattr_hash_entry()
+ *
+ * Compute the hash of an extended attribute.
+ */
+__u32 ext2fs_ext_attr_hash_entry(struct ext2_ext_attr_entry *entry, void *data)
+{
+ __u32 hash = 0;
+ char *name = entry->e_name;
+ int n;
+
+ for (n = 0; n < entry->e_name_len; n++) {
+ hash = (hash << NAME_HASH_SHIFT) ^
+ (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
+ *name++;
+ }
+
+ if (entry->e_value_block == 0 && entry->e_value_size != 0) {
+ __u32 *value = (__u32 *)data;
+ for (n = (entry->e_value_size + EXT2_EXT_ATTR_ROUND) >>
+ EXT2_EXT_ATTR_PAD_BITS; n; n--) {
+ hash = (hash << VALUE_HASH_SHIFT) ^
+ (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^
+ *value++;
+ }
+ }
+
+ return hash;
+}
+
+#undef NAME_HASH_SHIFT
+#undef VALUE_HASH_SHIFT
+
errcode_t ext2fs_read_ext_attr(ext2_filsys fs, blk_t block, void *buf)
{
errcode_t retval;
Index: e2fsprogs-1.39/lib/ext2fs/swapfs.c
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/swapfs.c 2006-09-18 17:43:00.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/swapfs.c 2006-09-18 17:48:52.000000000 +0200
@@ -101,6 +101,7 @@ void ext2fs_swap_ext_attr(char *to, char
to_header->h_magic = ext2fs_swab32(from_header->h_magic);
to_header->h_blocks = ext2fs_swab32(from_header->h_blocks);
to_header->h_refcount = ext2fs_swab32(from_header->h_refcount);
+ to_header->h_hash = ext2fs_swab32(from_header->h_hash);
for (n=0; n<4; n++)
to_header->h_reserved[n] =
ext2fs_swab32(from_header->h_reserved[n]);
@@ -115,6 +116,7 @@ void ext2fs_swap_ext_attr(char *to, char
ext2fs_swab32(from_entry->e_value_block);
to_entry->e_value_size =
ext2fs_swab32(from_entry->e_value_size);
+ to_entry->e_hash = ext2fs_swab32(from_entry->e_hash);
from_entry = EXT2_EXT_ATTR_NEXT(from_entry);
to_entry = EXT2_EXT_ATTR_NEXT(to_entry);
}

2006-09-26 14:49:24

by Alexandre Ratchov

[permalink] [raw]
Subject: [patch 08/12] rfc: 2fsprogs update

use 64bit offsets and block numbers (unsigned long long) in
*_read_blk, *_write_blk, and friends.

Signed-off-by: Alexandre Ratchov <[email protected]>


Index: e2fsprogs-1.39/debugfs/debugfs.c
===================================================================
--- e2fsprogs-1.39.orig/debugfs/debugfs.c 2006-09-19 17:29:59.000000000 +0200
+++ e2fsprogs-1.39/debugfs/debugfs.c 2006-09-19 17:30:00.000000000 +0200
@@ -149,13 +149,13 @@ void do_open_filesys(int argc, char **ar
data_filename = optarg;
break;
case 'b':
- blocksize = parse_ulong(optarg, argv[0],
+ blocksize = parse_ullong(optarg, argv[0],
"block size", &err);
if (err)
return;
break;
case 's':
- superblock = parse_ulong(optarg, argv[0],
+ superblock = parse_ullong(optarg, argv[0],
"superblock number", &err);
if (err)
return;
@@ -232,7 +232,7 @@ void do_init_filesys(int argc, char **ar
return;

memset(&param, 0, sizeof(struct ext2_super_block));
- param.s_blocks_count = parse_ulong(argv[2], argv[0],
+ param.s_blocks_count = parse_ullong(argv[2], argv[0],
"blocks count", &err);
if (err)
return;
@@ -1685,7 +1685,7 @@ void do_bmap(int argc, char *argv[])
ino = string_to_inode(argv[1]);
if (!ino)
return;
- blk = parse_ulong(argv[2], argv[0], "logical_block", &err);
+ blk = parse_ullong(argv[2], argv[0], "logical_block", &err);

errcode = ext2fs_bmap(current_fs, ino, 0, 0, 0, blk, &pblk);
if (errcode) {
@@ -1823,11 +1823,11 @@ int main(int argc, char **argv)
open_flags |= EXT2_FLAG_RW;
break;
case 'b':
- blocksize = parse_ulong(optarg, argv[0],
+ blocksize = parse_ullong(optarg, argv[0],
"block size", 0);
break;
case 's':
- superblock = parse_ulong(optarg, argv[0],
+ superblock = parse_ullong(optarg, argv[0],
"superblock number", 0);
break;
case 'c':
Index: e2fsprogs-1.39/debugfs/debugfs.h
===================================================================
--- e2fsprogs-1.39.orig/debugfs/debugfs.h 2006-09-19 17:29:54.000000000 +0200
+++ e2fsprogs-1.39/debugfs/debugfs.h 2006-09-19 17:30:00.000000000 +0200
@@ -32,7 +32,7 @@ extern int check_fs_bitmaps(char *name);
extern ext2_ino_t string_to_inode(char *str);
extern char *time_to_string(__u32);
extern time_t string_to_time(const char *);
-extern unsigned long parse_ulong(const char *str, const char *cmd,
+extern unsigned long long parse_ullong(const char *str, const char *cmd,
const char *descr, int *err);
extern int strtoblk(const char *cmd, const char *str, blk_t *ret);
extern int common_args_process(int argc, char *argv[], int min_argc,
Index: e2fsprogs-1.39/debugfs/util.c
===================================================================
--- e2fsprogs-1.39.orig/debugfs/util.c 2006-09-19 17:29:54.000000000 +0200
+++ e2fsprogs-1.39/debugfs/util.c 2006-09-19 17:30:00.000000000 +0200
@@ -238,16 +238,16 @@ extern time_t string_to_time(const char
}

/*
- * This function will convert a string to an unsigned long, printing
+ * This function will convert a string to an unsigned long long, printing
* an error message if it fails, and returning success or failure in err.
*/
-unsigned long parse_ulong(const char *str, const char *cmd,
+unsigned long long parse_ullong(const char *str, const char *cmd,
const char *descr, int *err)
{
char *tmp;
- unsigned long ret;
+ unsigned long long ret;

- ret = strtoul(str, &tmp, 0);
+ ret = strtoull(str, &tmp, 0);
if (*tmp == 0) {
if (err)
*err = 0;
@@ -270,7 +270,7 @@ int strtoblk(const char *cmd, const char
blk_t blk;
int err;

- blk = parse_ulong(str, cmd, "block number", &err);
+ blk = parse_ullong(str, cmd, "block number", &err);
*ret = blk;
if (err == 0 && blk == 0) {
com_err(cmd, 0, "Invalid block number 0");
@@ -336,7 +336,7 @@ int common_block_args_process(int argc,
if (strtoblk(argv[0], argv[1], block))
return 1;
if (argc > 2) {
- *count = parse_ulong(argv[2], argv[0], "count", &err);
+ *count = parse_ullong(argv[2], argv[0], "count", &err);
if (err)
return 1;
}
Index: e2fsprogs-1.39/e2fsck/ehandler.c
===================================================================
--- e2fsprogs-1.39.orig/e2fsck/ehandler.c 2006-09-19 17:29:54.000000000 +0200
+++ e2fsprogs-1.39/e2fsck/ehandler.c 2006-09-19 17:30:00.000000000 +0200
@@ -20,7 +20,7 @@
static const char *operation;

static errcode_t e2fsck_handle_read_error(io_channel channel,
- unsigned long block,
+ unsigned long long block,
int count,
void *data,
size_t size EXT2FS_ATTR((unused)),
@@ -66,7 +66,7 @@ static errcode_t e2fsck_handle_read_erro
}

static errcode_t e2fsck_handle_write_error(io_channel channel,
- unsigned long block,
+ unsigned long long block,
int count,
const void *data,
size_t size EXT2FS_ATTR((unused)),
Index: e2fsprogs-1.39/lib/e2p/e2p.h
===================================================================
--- e2fsprogs-1.39.orig/lib/e2p/e2p.h 2006-09-19 17:29:54.000000000 +0200
+++ e2fsprogs-1.39/lib/e2p/e2p.h 2006-09-19 17:30:00.000000000 +0200
@@ -46,7 +46,7 @@ const char *e2p_mntopt2string(unsigned i
int e2p_string2mntopt(char *string, unsigned int *mask);
int e2p_edit_mntopts(const char *str, __u32 *mntopts, __u32 ok);

-unsigned long parse_num_blocks(const char *arg, int log_block_size);
+unsigned long long parse_num_blocks(const char *arg, int log_block_size);

char *e2p_os2string(int os_type);
int e2p_string2os(char *str);
Index: e2fsprogs-1.39/lib/e2p/parse_num.c
===================================================================
--- e2fsprogs-1.39.orig/lib/e2p/parse_num.c 2006-09-19 17:29:54.000000000 +0200
+++ e2fsprogs-1.39/lib/e2p/parse_num.c 2006-09-19 17:30:00.000000000 +0200
@@ -11,7 +11,7 @@

#include <stdlib.h>

-unsigned long parse_num_blocks(const char *arg, int log_block_size)
+unsigned long long parse_num_blocks(const char *arg, int log_block_size)
{
char *p;
unsigned long long num;
Index: e2fsprogs-1.39/lib/ext2fs/ext2_io.h
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/ext2_io.h 2006-09-19 17:29:54.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/ext2_io.h 2006-09-19 17:30:00.000000000 +0200
@@ -35,14 +35,14 @@ struct struct_io_channel {
char *name;
int block_size;
errcode_t (*read_error)(io_channel channel,
- unsigned long block,
+ unsigned long long block,
int count,
void *data,
size_t size,
int actual_bytes_read,
errcode_t error);
errcode_t (*write_error)(io_channel channel,
- unsigned long block,
+ unsigned long long block,
int count,
const void *data,
size_t size,
@@ -61,12 +61,12 @@ struct struct_io_manager {
errcode_t (*open)(const char *name, int flags, io_channel *channel);
errcode_t (*close)(io_channel channel);
errcode_t (*set_blksize)(io_channel channel, int blksize);
- errcode_t (*read_blk)(io_channel channel, unsigned long block,
+ errcode_t (*read_blk)(io_channel channel, unsigned long long block,
int count, void *data);
- errcode_t (*write_blk)(io_channel channel, unsigned long block,
+ errcode_t (*write_blk)(io_channel channel, unsigned long long block,
int count, const void *data);
errcode_t (*flush)(io_channel channel);
- errcode_t (*write_byte)(io_channel channel, unsigned long offset,
+ errcode_t (*write_byte)(io_channel channel, unsigned long long offset,
int count, const void *data);
errcode_t (*set_option)(io_channel channel, const char *option,
const char *arg);
@@ -99,9 +99,9 @@ extern io_manager unix_io_manager;
/* test_io.c */
extern io_manager test_io_manager, test_io_backing_manager;
extern void (*test_io_cb_read_blk)
- (unsigned long block, int count, errcode_t err);
+ (unsigned long long block, int count, errcode_t err);
extern void (*test_io_cb_write_blk)
- (unsigned long block, int count, errcode_t err);
+ (unsigned long long block, int count, errcode_t err);
extern void (*test_io_cb_set_blksize)
(int blksize, errcode_t err);

Index: e2fsprogs-1.39/lib/ext2fs/inode_io.c
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/inode_io.c 2006-09-19 17:29:54.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/inode_io.c 2006-09-19 17:30:00.000000000 +0200
@@ -49,12 +49,12 @@ static int ino_unique = 0;
static errcode_t inode_open(const char *name, int flags, io_channel *channel);
static errcode_t inode_close(io_channel channel);
static errcode_t inode_set_blksize(io_channel channel, int blksize);
-static errcode_t inode_read_blk(io_channel channel, unsigned long block,
+static errcode_t inode_read_blk(io_channel channel, unsigned long long block,
int count, void *data);
-static errcode_t inode_write_blk(io_channel channel, unsigned long block,
+static errcode_t inode_write_blk(io_channel channel, unsigned long long block,
int count, const void *data);
static errcode_t inode_flush(io_channel channel);
-static errcode_t inode_write_byte(io_channel channel, unsigned long offset,
+static errcode_t inode_write_byte(io_channel channel, unsigned long long offset,
int size, const void *data);

static struct struct_io_manager struct_inode_manager = {
@@ -197,7 +197,7 @@ static errcode_t inode_set_blksize(io_ch
}


-static errcode_t inode_read_blk(io_channel channel, unsigned long block,
+static errcode_t inode_read_blk(io_channel channel, unsigned long long block,
int count, void *buf)
{
struct inode_private_data *data;
@@ -217,7 +217,7 @@ static errcode_t inode_read_blk(io_chann
return ext2fs_file_read(data->file, buf, count, 0);
}

-static errcode_t inode_write_blk(io_channel channel, unsigned long block,
+static errcode_t inode_write_blk(io_channel channel, unsigned long long block,
int count, const void *buf)
{
struct inode_private_data *data;
@@ -237,7 +237,7 @@ static errcode_t inode_write_blk(io_chan
return ext2fs_file_write(data->file, buf, count, 0);
}

-static errcode_t inode_write_byte(io_channel channel, unsigned long offset,
+static errcode_t inode_write_byte(io_channel channel, unsigned long long offset,
int size, const void *buf)
{
struct inode_private_data *data;
Index: e2fsprogs-1.39/lib/ext2fs/test_io.c
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/test_io.c 2006-09-19 17:29:54.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/test_io.c 2006-09-19 17:30:00.000000000 +0200
@@ -48,21 +48,21 @@ struct test_private_data {
FILE *outfile;
unsigned long block;
int read_abort_count, write_abort_count;
- void (*read_blk)(unsigned long block, int count, errcode_t err);
- void (*write_blk)(unsigned long block, int count, errcode_t err);
+ void (*read_blk)(unsigned long long block, int count, errcode_t err);
+ void (*write_blk)(unsigned long long block, int count, errcode_t err);
void (*set_blksize)(int blksize, errcode_t err);
- void (*write_byte)(unsigned long block, int count, errcode_t err);
+ void (*write_byte)(unsigned long long block, int count, errcode_t err);
};

static errcode_t test_open(const char *name, int flags, io_channel *channel);
static errcode_t test_close(io_channel channel);
static errcode_t test_set_blksize(io_channel channel, int blksize);
-static errcode_t test_read_blk(io_channel channel, unsigned long block,
+static errcode_t test_read_blk(io_channel channel, unsigned long long block,
int count, void *data);
-static errcode_t test_write_blk(io_channel channel, unsigned long block,
+static errcode_t test_write_blk(io_channel channel, unsigned long long block,
int count, const void *data);
static errcode_t test_flush(io_channel channel);
-static errcode_t test_write_byte(io_channel channel, unsigned long offset,
+static errcode_t test_write_byte(io_channel channel, unsigned long long offset,
int count, const void *buf);
static errcode_t test_set_option(io_channel channel, const char *option,
const char *arg);
@@ -88,13 +88,13 @@ io_manager test_io_manager = &struct_tes
*/
io_manager test_io_backing_manager = 0;
void (*test_io_cb_read_blk)
- (unsigned long block, int count, errcode_t err) = 0;
+ (unsigned long long block, int count, errcode_t err) = 0;
void (*test_io_cb_write_blk)
- (unsigned long block, int count, errcode_t err) = 0;
+ (unsigned long long block, int count, errcode_t err) = 0;
void (*test_io_cb_set_blksize)
(int blksize, errcode_t err) = 0;
void (*test_io_cb_write_byte)
- (unsigned long block, int count, errcode_t err) = 0;
+ (unsigned long long block, int count, errcode_t err) = 0;

/*
* Test flags
@@ -108,7 +108,7 @@ void (*test_io_cb_write_byte)

static void test_dump_block(io_channel channel,
struct test_private_data *data,
- unsigned long block, const void *buf)
+ unsigned long long block, const void *buf)
{
const unsigned char *cp;
FILE *f = data->outfile;
@@ -118,7 +118,7 @@ static void test_dump_block(io_channel c
for (i=0, cp = buf; i < channel->block_size; i++, cp++) {
cksum += *cp;
}
- fprintf(f, "Contents of block %lu, checksum %08lu: \n", block, cksum);
+ fprintf(f, "Contents of block %llu, checksum %08lu: \n", block, cksum);
for (i=0, cp = buf; i < channel->block_size; i++, cp++) {
if ((i % 16) == 0)
fprintf(f, "%04x: ", i);
@@ -126,7 +126,7 @@ static void test_dump_block(io_channel c
}
}

-static void test_abort(io_channel channel, unsigned long block)
+static void test_abort(io_channel channel, unsigned long long block)
{
struct test_private_data *data;
FILE *f;
@@ -135,7 +135,7 @@ static void test_abort(io_channel channe
f = data->outfile;
test_flush(channel);

- fprintf(f, "Aborting due to I/O to block %lu\n", block);
+ fprintf(f, "Aborting due to I/O to block %llu\n", block);
fflush(f);
abort();
}
@@ -286,7 +286,7 @@ static errcode_t test_set_blksize(io_cha
}


-static errcode_t test_read_blk(io_channel channel, unsigned long block,
+static errcode_t test_read_blk(io_channel channel, unsigned long long block,
int count, void *buf)
{
struct test_private_data *data;
@@ -302,7 +302,7 @@ static errcode_t test_read_blk(io_channe
data->read_blk(block, count, retval);
if (data->flags & TEST_FLAG_READ)
fprintf(data->outfile,
- "Test_io: read_blk(%lu, %d) returned %s\n",
+ "Test_io: read_blk(%llu, %d) returned %s\n",
block, count, retval ? error_message(retval) : "OK");
if (data->block && data->block == block) {
if (data->flags & TEST_FLAG_DUMP)
@@ -313,7 +313,7 @@ static errcode_t test_read_blk(io_channe
return retval;
}

-static errcode_t test_write_blk(io_channel channel, unsigned long block,
+static errcode_t test_write_blk(io_channel channel, unsigned long long block,
int count, const void *buf)
{
struct test_private_data *data;
@@ -329,7 +329,7 @@ static errcode_t test_write_blk(io_chann
data->write_blk(block, count, retval);
if (data->flags & TEST_FLAG_WRITE)
fprintf(data->outfile,
- "Test_io: write_blk(%lu, %d) returned %s\n",
+ "Test_io: write_blk(%llu, %d) returned %s\n",
block, count, retval ? error_message(retval) : "OK");
if (data->block && data->block == block) {
if (data->flags & TEST_FLAG_DUMP)
@@ -340,7 +340,7 @@ static errcode_t test_write_blk(io_chann
return retval;
}

-static errcode_t test_write_byte(io_channel channel, unsigned long offset,
+static errcode_t test_write_byte(io_channel channel, unsigned long long offset,
int count, const void *buf)
{
struct test_private_data *data;
@@ -356,7 +356,7 @@ static errcode_t test_write_byte(io_chan
data->write_byte(offset, count, retval);
if (data->flags & TEST_FLAG_WRITE)
fprintf(data->outfile,
- "Test_io: write_byte(%lu, %d) returned %s\n",
+ "Test_io: write_byte(%llu, %d) returned %s\n",
offset, count, retval ? error_message(retval) : "OK");
return retval;
}
Index: e2fsprogs-1.39/lib/ext2fs/unix_io.c
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/unix_io.c 2006-09-19 17:29:54.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/unix_io.c 2006-09-19 17:30:42.000000000 +0200
@@ -75,12 +75,12 @@ struct unix_private_data {
static errcode_t unix_open(const char *name, int flags, io_channel *channel);
static errcode_t unix_close(io_channel channel);
static errcode_t unix_set_blksize(io_channel channel, int blksize);
-static errcode_t unix_read_blk(io_channel channel, unsigned long block,
+static errcode_t unix_read_blk(io_channel channel, unsigned long long block,
int count, void *data);
-static errcode_t unix_write_blk(io_channel channel, unsigned long block,
+static errcode_t unix_write_blk(io_channel channel, unsigned long long block,
int count, const void *data);
static errcode_t unix_flush(io_channel channel);
-static errcode_t unix_write_byte(io_channel channel, unsigned long offset,
+static errcode_t unix_write_byte(io_channel channel, unsigned long long offset,
int size, const void *data);
static errcode_t unix_set_option(io_channel channel, const char *option,
const char *arg);
@@ -522,7 +522,7 @@ static errcode_t unix_set_blksize(io_cha
}


-static errcode_t unix_read_blk(io_channel channel, unsigned long block,
+static errcode_t unix_read_blk(io_channel channel, unsigned long long block,
int count, void *buf)
{
struct unix_private_data *data;
@@ -587,7 +587,7 @@ static errcode_t unix_read_blk(io_channe
#endif /* NO_IO_CACHE */
}

-static errcode_t unix_write_blk(io_channel channel, unsigned long block,
+static errcode_t unix_write_blk(io_channel channel, unsigned long long block,
int count, const void *buf)
{
struct unix_private_data *data;
@@ -639,7 +639,7 @@ static errcode_t unix_write_blk(io_chann
#endif /* NO_IO_CACHE */
}

-static errcode_t unix_write_byte(io_channel channel, unsigned long offset,
+static errcode_t unix_write_byte(io_channel channel, unsigned long long offset,
int size, const void *buf)
{
struct unix_private_data *data;

2006-09-26 14:47:51

by Alexandre Ratchov

[permalink] [raw]
Subject: [patch 05/12] rfc: 2fsprogs update

Allow htree directories to be extent mapped.

Index: e2fsprogs/e2fsck/pass1.c
===================================================================
--- e2fsprogs.orig/e2fsck/pass1.c 2006-07-10 03:45:19.000000000 -0600
+++ e2fsprogs/e2fsck/pass1.c 2006-07-10 03:47:55.000000000 -0600
@@ -1364,10 +1364,23 @@ clear_extattr:
return 0;
}

+static int htree_blk_iter_cb(ext2_filsys fs EXT2FS_ATTR((unused)),
+ blk_t *blocknr,
+ e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)),
+ blk_t ref_blk EXT2FS_ATTR((unused)),
+ int ref_offset EXT2FS_ATTR((unused)),
+ void *priv_data)
+{
+ blk_t *blk = priv_data;
+
+ *blk = *blocknr;
+
+ return BLOCK_ABORT;
+}
+
/* Returns 1 if bad htree, 0 if OK */
static int handle_htree(e2fsck_t ctx, struct problem_context *pctx,
- ext2_ino_t ino EXT2FS_ATTR((unused)),
- struct ext2_inode *inode,
+ ext2_ino_t ino, struct ext2_inode *inode,
char *block_buf)
{
struct ext2_dx_root_info *root;
@@ -1381,7 +1394,8 @@ static int handle_htree(e2fsck_t ctx, st
fix_problem(ctx, PR_1_HTREE_SET, pctx)))
return 1;

- blk = inode->i_block[0];
+ ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_DATA_ONLY | BLOCK_FLAG_HOLE,
+ block_buf, htree_blk_iter_cb, &blk);
if (((blk == 0) ||
(blk < fs->super->s_first_data_block) ||
(blk >= fs->super->s_blocks_count)) &&

Cheers, Andreas
--
Andreas Dilger
Principal Software Engineer
Cluster File Systems, Inc.

2006-09-26 14:50:41

by Alexandre Ratchov

[permalink] [raw]
Subject: [patch 11/12] rfc: 2fsprogs update

allow larger block group descriptors

Signed-off-by: Alexandre Ratchov <[email protected]>

Index: e2fsprogs-1.39/lib/ext2fs/ext2fs.h
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/ext2fs.h 2006-09-22 15:52:50.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/ext2fs.h 2006-09-22 15:53:09.000000000 +0200
@@ -213,6 +213,7 @@ struct struct_ext2_filsys {
char * device_name;
struct ext2_super_block * super;
unsigned int blocksize;
+ unsigned int desc_size;
int fragsize;
dgrp_t group_desc_count;
unsigned long desc_blocks;
Index: e2fsprogs-1.39/lib/ext2fs/swapfs.c
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/swapfs.c 2006-09-22 15:52:50.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/swapfs.c 2006-09-22 15:53:09.000000000 +0200
@@ -63,6 +63,7 @@ void ext2fs_swap_super(struct ext2_super
sb->s_journal_inum = ext2fs_swab32(sb->s_journal_inum);
sb->s_journal_dev = ext2fs_swab32(sb->s_journal_dev);
sb->s_last_orphan = ext2fs_swab32(sb->s_last_orphan);
+ sb->s_desc_size = ext2fs_swab16(sb->s_desc_size);
sb->s_default_mount_opts = ext2fs_swab32(sb->s_default_mount_opts);
sb->s_first_meta_bg = ext2fs_swab32(sb->s_first_meta_bg);
sb->s_mkfs_time = ext2fs_swab32(sb->s_mkfs_time);
Index: e2fsprogs-1.39/misc/mke2fs.c
===================================================================
--- e2fsprogs-1.39.orig/misc/mke2fs.c 2006-09-22 15:52:50.000000000 +0200
+++ e2fsprogs-1.39/misc/mke2fs.c 2006-09-22 15:53:09.000000000 +0200
@@ -94,7 +94,7 @@ int linux_version_code = 0;
static void usage(void)
{
fprintf(stderr, _("Usage: %s [-c|-t|-l filename] [-b block-size] "
- "[-f fragment-size]\n\t[-i bytes-per-inode] [-I inode-size] "
+ "[-f fragment-size]\n\t[-i bytes-per-inode] [-I inode-size] [-D descriptor-size]"
"[-j] [-J journal-options]\n"
"\t[-N number-of-inodes] [-m reserved-blocks-percentage] "
"[-o creator-os]\n\t[-g blocks-per-group] [-L volume-label] "
@@ -680,6 +680,8 @@ static void show_stats(ext2_filsys fs)
s->s_log_block_size);
printf(_("Fragment size=%u (log=%u)\n"), fs->fragsize,
s->s_log_frag_size);
+ if (s->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
+ printf(_("Descriptor size=%u\n"), fs->desc_size);
printf(_("%u inodes, %llu blocks\n"), s->s_inodes_count,
EXT2_BLOCKS_COUNT(s));
printf(_("%llu blocks (%2.2f%%) reserved for the super user\n"),
@@ -689,7 +691,7 @@ static void show_stats(ext2_filsys fs)
if (s->s_reserved_gdt_blocks)
printf(_("Maximum filesystem blocks=%llu\n"),
(blk_t)((s->s_reserved_gdt_blocks + fs->desc_blocks) *
- (fs->blocksize / sizeof(struct ext2_group_desc)) *
+ (fs->blocksize / fs->desc_size) *
s->s_blocks_per_group));
if (fs->group_desc_count > 1)
printf(_("%u block groups\n"), fs->group_desc_count);
@@ -822,7 +824,7 @@ static void parse_extended_opts(struct e
bpg = param->s_blocks_per_group;
if (!bpg)
bpg = blocksize * 8;
- gdpb = blocksize / sizeof(struct ext2_group_desc);
+ gdpb = blocksize / EXT2_DESC_SIZE(param);
group_desc_count =
ext2fs_div_ceil(EXT2_BLOCKS_COUNT(param), bpg);
desc_blocks = (group_desc_count +
@@ -861,7 +863,8 @@ static __u32 ok_features[3] = {
EXT2_FEATURE_COMPAT_LAZY_BG, /* Compat */
EXT2_FEATURE_INCOMPAT_FILETYPE| /* Incompat */
EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|
- EXT2_FEATURE_INCOMPAT_META_BG,
+ EXT2_FEATURE_INCOMPAT_META_BG|
+ EXT4_FEATURE_INCOMPAT_64BIT,
EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER /* R/O compat */
};

@@ -896,6 +899,7 @@ static void PRS(int argc, char *argv[])
int blocksize = 0;
int inode_ratio = 0;
int inode_size = 0;
+ int desc_size = 0;
double reserved_ratio = 5.0;
int sector_size = 0;
int show_version_only = 0;
@@ -971,7 +975,7 @@ static void PRS(int argc, char *argv[])
}

while ((c = getopt (argc, argv,
- "b:cf:g:i:jl:m:no:qr:s:tvE:FI:J:L:M:N:O:R:ST:V")) != EOF) {
+ "b:cf:g:i:jl:m:no:qr:s:tvD:E:FI:J:L:M:N:O:R:ST:V")) != EOF) {
switch (c) {
case 'b':
blocksize = strtol(optarg, &tmp, 0);
@@ -1088,6 +1092,14 @@ static void PRS(int argc, char *argv[])
exit(1);
}
break;
+ case 'D':
+ desc_size = strtoul(optarg, &tmp, 0);
+ if (*tmp) {
+ com_err(program_name, 0,
+ _("invalid descriptor size - %s"), optarg);
+ exit(1);
+ }
+ break;
case 'v':
verbose = 1;
break;
@@ -1252,7 +1264,10 @@ static void PRS(int argc, char *argv[])
exit(1);
}
if (dev_size >> 31) {
- fs_param.s_feature_incompat |= EXT4_FEATURE_INCOMPAT_64BIT;
+ fs_param.s_feature_incompat |=
+ EXT4_FEATURE_INCOMPAT_64BIT;
+ fs_param.s_desc_size =
+ EXT2_MIN_DESC_SIZE_64BIT;
}
EXT2_BLOCKS_COUNT_SET(&fs_param, dev_size);
if (sys_page_size > EXT2_BLOCK_SIZE(&fs_param))
@@ -1438,6 +1453,26 @@ static void PRS(int argc, char *argv[])
inode_size);
fs_param.s_inode_size = inode_size;
}
+
+ if (desc_size) {
+ unsigned desc_size_min;
+
+ if (fs_param.s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
+ desc_size_min = EXT2_MIN_DESC_SIZE_64BIT;
+ else
+ desc_size_min = EXT2_MIN_DESC_SIZE;
+
+ if (desc_size < desc_size_min ||
+ desc_size > EXT2_MAX_DESC_SIZE ||
+ desc_size & (desc_size - 1)) {
+ com_err(program_name, 0,
+ _("invalid descriptor size %d (min %d/max %d)"),
+ desc_size, EXT2_MIN_DESC_SIZE,
+ EXT2_MAX_DESC_SIZE);
+ exit(1);
+ }
+ fs_param.s_desc_size = desc_size;
+ }

/* Make sure number of inodes specified will fit in 32 bits */
if (num_inodes == 0) {
Index: e2fsprogs-1.39/lib/ext2fs/openfs.c
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/openfs.c 2006-09-22 15:52:50.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/openfs.c 2006-09-22 15:53:09.000000000 +0200
@@ -39,7 +39,7 @@ blk_t ext2fs_descriptor_block_loc(ext2_f
(i < fs->super->s_first_meta_bg))
return (group_block + i + 1);

- bg = (fs->blocksize / sizeof (struct ext2_group_desc)) * i;
+ bg = (fs->blocksize / fs->desc_size) * i;
if (ext2fs_bg_has_super(fs, bg))
has_super = 1;
ret_blk = EXT2_GROUP_BASE(fs->super, bg) + has_super;
@@ -87,8 +87,10 @@ errcode_t ext2fs_open2(const char *name,
unsigned long i;
int j, groups_per_block, blocks_per_group, io_flags;
blk_t group_block, blk;
- char *dest, *cp;
+ char *cp;
struct ext2_group_desc *gdp;
+ char shadow_block[EXT2_MAX_BLOCK_SIZE];
+ size_t desc_buflen;

EXT2_CHECK_MAGIC(manager, EXT2_ET_MAGIC_IO_MANAGER);

@@ -231,6 +233,13 @@ errcode_t ext2fs_open2(const char *name,
goto cleanup;
}
}
+
+ if (fs->super->s_feature_incompat &
+ EXT4_FEATURE_INCOMPAT_64BIT) {
+ fs->desc_size = EXT2_DESC_SIZE(fs->super);
+ } else {
+ fs->desc_size = EXT2_MIN_DESC_SIZE;
+ }
/*
* Set the blocksize to the filesystem's blocksize.
*/
@@ -262,27 +271,32 @@ errcode_t ext2fs_open2(const char *name,
blocks_per_group);
fs->desc_blocks = ext2fs_div_ceil(fs->group_desc_count,
EXT2_DESC_PER_BLOCK(fs->super));
- retval = ext2fs_get_mem(fs->desc_blocks * fs->blocksize,
- &fs->group_desc);
+
+ desc_buflen = fs->desc_blocks * EXT2_DESC_PER_BLOCK(fs->super) *
+ sizeof(struct ext2_group_desc);
+ retval = ext2fs_get_mem(desc_buflen, &fs->group_desc);
if (retval)
goto cleanup;
+ memset(fs->group_desc, 0, desc_buflen);
+
if (!group_block)
group_block = fs->super->s_first_data_block;
- dest = (char *) fs->group_desc;
- groups_per_block = fs->blocksize / sizeof(struct ext2_group_desc);
+ gdp = fs->group_desc;
+ groups_per_block = fs->blocksize / fs->desc_size;
for (i=0 ; i < fs->desc_blocks; i++) {
blk = ext2fs_descriptor_block_loc(fs, group_block, i);
- retval = io_channel_read_blk(fs->io, blk, 1, dest);
+ retval = io_channel_read_blk(fs->io, blk, 1, shadow_block);
if (retval)
goto cleanup;
+
+ for (j=0; j < groups_per_block; j++) {
+ memcpy(gdp, shadow_block + j * fs->desc_size, fs->desc_size);
#ifdef EXT2FS_ENABLE_SWAPFS
- if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
- gdp = (struct ext2_group_desc *) dest;
- for (j=0; j < groups_per_block; j++)
- ext2fs_swap_group_desc(gdp++);
- }
+ if (fs->flags & EXT2_FLAG_SWAP_BYTES)
+ ext2fs_swap_group_desc(gdp);
#endif
- dest += fs->blocksize;
+ gdp++;
+ }
}

*ret_fs = fs;
Index: e2fsprogs-1.39/lib/ext2fs/closefs.c
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/closefs.c 2006-09-22 15:52:50.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/closefs.c 2006-09-22 15:53:09.000000000 +0200
@@ -80,7 +80,7 @@ int ext2fs_super_and_bgd_loc(ext2_filsys
super_blk = group_block;
numblocks--;
}
- meta_bg_size = (fs->blocksize / sizeof (struct ext2_group_desc));
+ meta_bg_size = (fs->blocksize / fs->desc_size);
meta_bg = group / meta_bg_size;

if (!(fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) ||
@@ -204,14 +204,14 @@ static errcode_t write_backup_super(ext2

errcode_t ext2fs_flush(ext2_filsys fs)
{
- dgrp_t i,j;
+ dgrp_t i;
errcode_t retval;
unsigned long fs_state;
struct ext2_super_block *super_shadow = 0;
- struct ext2_group_desc *group_shadow = 0;
- struct ext2_group_desc *s, *t;
- char *group_ptr;
- int old_desc_blocks;
+ struct ext2_group_desc *gd;
+ char *desc_shadow = NULL;
+ size_t desc_buflen;
+ int old_desc_blocks;

EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);

@@ -219,33 +219,36 @@ errcode_t ext2fs_flush(ext2_filsys fs)

fs->super->s_wtime = fs->now ? fs->now : time(NULL);
fs->super->s_block_group_nr = 0;
+
+ desc_buflen = fs->desc_blocks * fs->blocksize;
+ retval = ext2fs_get_mem(desc_buflen, &desc_shadow);
+ if (retval)
+ goto errout;
+ memset(desc_shadow, 0, desc_buflen);
+
+ /*
+ * copy the group descriptors adjusting size to the
+ * on-disk size. If needed, also bswap them on the fly
+ */
+ for (i = 0; i < fs->group_desc_count; i++) {
+ gd = (struct ext2_group_desc *)(desc_shadow + i * fs->desc_size);
+ memcpy(gd, &fs->group_desc[i], fs->desc_size);
+#ifdef EXT2FS_ENABLE_SWAPFS
+ if (fs->flags & EXT2_FLAG_SWAP_BYTES)
+ ext2fs_swap_group_desc(gd);
+#endif
+ }
+
#ifdef EXT2FS_ENABLE_SWAPFS
if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
- retval = EXT2_ET_NO_MEMORY;
retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &super_shadow);
if (retval)
goto errout;
- retval = ext2fs_get_mem((size_t)(fs->blocksize *
- fs->desc_blocks),
- &group_shadow);
- if (retval)
- goto errout;
- memset(group_shadow, 0, (size_t) fs->blocksize *
- fs->desc_blocks);
-
- /* swap the group descriptors */
- for (j=0, s=fs->group_desc, t=group_shadow;
- j < fs->group_desc_count; j++, t++, s++) {
- *t = *s;
- ext2fs_swap_group_desc(t);
- }
} else {
super_shadow = fs->super;
- group_shadow = fs->group_desc;
}
#else
super_shadow = fs->super;
- group_shadow = fs->group_desc;
#endif

/*
@@ -273,7 +276,6 @@ errcode_t ext2fs_flush(ext2_filsys fs)
* Write out the master group descriptors, and the backup
* superblocks and group descriptors.
*/
- group_ptr = (char *) group_shadow;
if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
old_desc_blocks = fs->super->s_first_meta_bg;
else
@@ -297,13 +299,14 @@ errcode_t ext2fs_flush(ext2_filsys fs)
if ((old_desc_blk) &&
(!(fs->flags & EXT2_FLAG_MASTER_SB_ONLY) || (i == 0))) {
retval = io_channel_write_blk(fs->io,
- old_desc_blk, old_desc_blocks, group_ptr);
+ old_desc_blk, old_desc_blocks, desc_shadow);
if (retval)
goto errout;
}
if (new_desc_blk) {
- retval = io_channel_write_blk(fs->io, new_desc_blk,
- 1, group_ptr + (meta_bg*fs->blocksize));
+ retval = io_channel_write_blk(
+ fs->io, new_desc_blk, 1,
+ desc_shadow + meta_bg * fs->blocksize);
if (retval)
goto errout;
}
@@ -352,8 +355,8 @@ errout:
if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
if (super_shadow)
ext2fs_free_mem(&super_shadow);
- if (group_shadow)
- ext2fs_free_mem(&group_shadow);
+ if (desc_shadow)
+ ext2fs_free_mem(&desc_shadow);
}
return retval;
}
Index: e2fsprogs-1.39/lib/ext2fs/ext2_fs.h
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/ext2_fs.h 2006-09-22 15:52:50.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/ext2_fs.h 2006-09-22 18:23:10.000000000 +0200
@@ -225,6 +225,12 @@ struct ext2_dx_countlimit {
/*
* Macro-instructions used to manage group descriptors
*/
+#define EXT2_MIN_DESC_SIZE 32
+#define EXT2_MIN_DESC_SIZE_64BIT 64
+#define EXT2_MAX_DESC_SIZE EXT2_MIN_BLOCK_SIZE
+#define EXT2_DESC_SIZE(s) \
+ ((EXT2_SB(s)->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) ? \
+ EXT2_SB(s)->s_desc_size : EXT2_MIN_DESC_SIZE)
#define EXT2_BLOCKS_PER_GROUP(s) ((__u64)EXT2_SB(s)->s_blocks_per_group)
#define EXT2_INODES_PER_GROUP(s) (EXT2_SB(s)->s_inodes_per_group)
#define EXT2_INODES_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s)/EXT2_INODE_SIZE(s))
@@ -235,7 +241,7 @@ struct ext2_dx_countlimit {
#define EXT2_DESC_PER_BLOCK(s) (EXT2_SB(s)->s_desc_per_block)
#define EXT2_DESC_PER_BLOCK_BITS(s) (EXT2_SB(s)->s_desc_per_block_bits)
#else
-#define EXT2_DESC_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc))
+#define EXT2_DESC_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / EXT2_DESC_SIZE(s))
#endif

/*
@@ -556,7 +562,7 @@ struct ext2_super_block {
__u32 s_hash_seed[4]; /* HTREE hash seed */
__u8 s_def_hash_version; /* Default hash version to use */
__u8 s_jnl_backup_type; /* Default type of journal backup */
- __u16 s_reserved_word_pad;
+ __u16 s_desc_size; /* size of group descriptor */
__u32 s_default_mount_opts;
__u32 s_first_meta_bg; /* First metablock group */
__u32 s_mkfs_time; /* When the filesystem was created */
Index: e2fsprogs-1.39/lib/ext2fs/initialize.c
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/initialize.c 2006-09-22 15:52:50.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/initialize.c 2006-09-22 15:53:09.000000000 +0200
@@ -67,7 +67,7 @@ static unsigned int calc_reserved_gdt_bl
{
struct ext2_super_block *sb = fs->super;
unsigned long bpg = sb->s_blocks_per_group;
- unsigned int gdpb = fs->blocksize / sizeof(struct ext2_group_desc);
+ unsigned int gdpb = fs->blocksize / fs->desc_size;
unsigned long max_blocks = 0xffffffff;
unsigned long rsv_groups;
unsigned int rsv_gdb;
@@ -106,6 +106,7 @@ errcode_t ext2fs_initialize(const char *
int io_flags;
char *buf;
blk_t inodes;
+ size_t desc_buflen;

if (!param || !EXT2_BLOCKS_COUNT(param))
return EXT2_ET_INVALID_ARGUMENT;
@@ -149,6 +150,7 @@ errcode_t ext2fs_initialize(const char *

set_field(s_log_block_size, 0); /* default blocksize: 1024 bytes */
set_field(s_log_frag_size, 0); /* default fragsize: 1024 bytes */
+ set_field(s_desc_size, 0);
set_field(s_first_data_block, super->s_log_block_size ? 0 : 1);
set_field(s_max_mnt_count, EXT2_DFL_MAX_MNT_COUNT);
set_field(s_errors, EXT2_ERRORS_DEFAULT);
@@ -178,6 +180,7 @@ errcode_t ext2fs_initialize(const char *

fs->blocksize = EXT2_BLOCK_SIZE(super);
fs->fragsize = EXT2_FRAG_SIZE(super);
+ fs->desc_size = EXT2_DESC_SIZE(super);
frags_per_block = fs->blocksize / fs->fragsize;

set_field(s_blocks_per_group, fs->blocksize * 8);
@@ -350,12 +353,12 @@ ipg_retry:

ext2fs_free_mem(&buf);

- retval = ext2fs_get_mem((size_t) fs->desc_blocks * fs->blocksize,
- &fs->group_desc);
+ desc_buflen = fs->desc_blocks * EXT2_DESC_PER_BLOCK(fs->super) *
+ sizeof(struct ext2_group_desc);
+ retval = ext2fs_get_mem(desc_buflen, &fs->group_desc);
if (retval)
goto cleanup;
-
- memset(fs->group_desc, 0, (size_t) fs->desc_blocks * fs->blocksize);
+ memset(fs->group_desc, 0, desc_buflen);

/*
* Reserve the superblock and group descriptors for each
Index: e2fsprogs-1.39/resize/resize2fs.c
===================================================================
--- e2fsprogs-1.39.orig/resize/resize2fs.c 2006-09-22 15:52:50.000000000 +0200
+++ e2fsprogs-1.39/resize/resize2fs.c 2006-09-22 15:53:09.000000000 +0200
@@ -187,6 +187,7 @@ errcode_t adjust_fs_info(ext2_filsys fs,
unsigned long i, j, old_desc_blocks, max_group;
unsigned int meta_bg, meta_bg_size;
int has_super;
+ size_t odesc_buflen, ndesc_buflen;
__u64 new_inodes; /* u64 to check for overflow */

EXT2_BLOCKS_COUNT_SET(fs->super, new_size);
@@ -276,17 +277,20 @@ retry:
* Reallocate the group descriptors as necessary.
*/
if (old_fs->desc_blocks != fs->desc_blocks) {
- retval = ext2fs_resize_mem(old_fs->desc_blocks *
- fs->blocksize,
- fs->desc_blocks * fs->blocksize,
+ odesc_buflen = old_fs->desc_blocks *
+ EXT2_DESC_PER_BLOCK(old_fs->super) *
+ sizeof(struct ext2_group_desc);
+ ndesc_buflen = fs->desc_blocks *
+ EXT2_DESC_PER_BLOCK(fs->super) *
+ sizeof(struct ext2_group_desc);
+ retval = ext2fs_resize_mem(odesc_buflen, ndesc_buflen,
&fs->group_desc);
if (retval)
goto errout;
if (fs->desc_blocks > old_fs->desc_blocks)
- memset((char *) fs->group_desc +
- (old_fs->desc_blocks * fs->blocksize), 0,
- (fs->desc_blocks - old_fs->desc_blocks) *
- fs->blocksize);
+ memset(&fs->group_desc[old_fs->group_desc_count], 0,
+ (fs->group_desc_count - old_fs->group_desc_count) *
+ sizeof(struct ext2_group_desc));
}

/*
@@ -365,8 +369,7 @@ retry:
fs->super->s_reserved_gdt_blocks;
for (i = old_fs->group_desc_count;
i < fs->group_desc_count; i++) {
- memset(&fs->group_desc[i], 0,
- sizeof(struct ext2_group_desc));
+ memset(&fs->group_desc[i], 0, sizeof(struct ext2_group_desc));
adjblocks = 0;

if (i == fs->group_desc_count-1) {
@@ -383,8 +386,7 @@ retry:
ext2fs_mark_block_bitmap(fs->block_map, group_block);
adjblocks++;
}
- meta_bg_size = (fs->blocksize /
- sizeof (struct ext2_group_desc));
+ meta_bg_size = fs->blocksize / fs->desc_size;
meta_bg = i / meta_bg_size;
if (!(fs->super->s_feature_incompat &
EXT2_FEATURE_INCOMPAT_META_BG) ||
@@ -550,7 +552,7 @@ static errcode_t mark_table_blocks(ext2_
unsigned long meta_bg_size;
unsigned int old_desc_blocks;

- meta_bg_size = (fs->blocksize / sizeof (struct ext2_group_desc));
+ meta_bg_size = fs->blocksize / fs->desc_size;
if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
old_desc_blocks = fs->super->s_first_meta_bg;
else
@@ -717,7 +719,7 @@ static errcode_t blocks_to_move(ext2_res
* If we're increasing the number of descriptor blocks, life
* gets interesting....
*/
- meta_bg_size = (fs->blocksize / sizeof (struct ext2_group_desc));
+ meta_bg_size = fs->blocksize / fs->desc_size;
for (i = 0; i < max_groups; i++) {
has_super = ext2fs_bg_has_super(fs, i);
if (has_super)
Index: e2fsprogs-1.39/lib/ext2fs/dupfs.c
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/dupfs.c 2006-09-22 15:08:12.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/dupfs.c 2006-09-22 15:53:09.000000000 +0200
@@ -23,6 +23,7 @@ errcode_t ext2fs_dup_handle(ext2_filsys
{
ext2_filsys fs;
errcode_t retval;
+ size_t desc_buflen;

EXT2_CHECK_MAGIC(src, EXT2_ET_MAGIC_EXT2FS_FILSYS);

@@ -59,12 +60,13 @@ errcode_t ext2fs_dup_handle(ext2_filsys
goto errout;
memcpy(fs->orig_super, src->orig_super, SUPERBLOCK_SIZE);

- retval = ext2fs_get_mem((size_t) fs->desc_blocks * fs->blocksize,
- &fs->group_desc);
+
+ desc_buflen = fs->desc_blocks * EXT2_DESC_PER_BLOCK(fs->super) *
+ sizeof(struct ext2_group_desc);
+ retval = ext2fs_get_mem(desc_buflen, &fs->group_desc);
if (retval)
goto errout;
- memcpy(fs->group_desc, src->group_desc,
- (size_t) fs->desc_blocks * fs->blocksize);
+ memcpy(fs->group_desc, src->group_desc, desc_buflen);

if (src->inode_map) {
retval = ext2fs_copy_bitmap(src->inode_map, &fs->inode_map);

2006-09-26 14:50:13

by Alexandre Ratchov

[permalink] [raw]
Subject: [patch 10/12] rfc: 2fsprogs update

use 48bit block numbers in extents

Signed-off-by: Alexandre Ratchov <[email protected]>

Index: e2fsprogs-1.39/lib/ext2fs/extents.c
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/extents.c 2006-09-22 20:26:55.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/extents.c 2006-09-22 20:27:12.000000000 +0200
@@ -72,8 +72,7 @@ errcode_t ext2fs_extent_verify(ext2_fils
struct ext4_extent_idx *ix, int ix_len)
{
show_extent(ex);
- /* FIXME: 48-bit support */
- if (ex->ee_start > fs->super->s_blocks_count)
+ if (EXT4_EE_START(ex) > EXT2_BLOCKS_COUNT(fs->super))
return EXT2_ET_EXTENT_LEAF_BAD;

if (ex->ee_len == 0)
@@ -84,19 +83,18 @@ errcode_t ext2fs_extent_verify(ext2_fils
if (ex->ee_block == 0)
return EXT2_ET_EXTENT_LEAF_BAD;

- /* FIXME: 48-bit support */
/* extents must be in logical offset order */
if (ex->ee_block < ex_prev->ee_block + ex_prev->ee_len)
return EXT2_ET_EXTENT_LEAF_BAD;

/* extents must not overlap physical blocks */
- if ((ex->ee_start < ex_prev->ee_start + ex_prev->ee_len) &&
- (ex->ee_start + ex->ee_len > ex_prev->ee_start))
+ if ((EXT4_EE_START(ex) <
+ EXT4_EE_START(ex_prev) + ex_prev->ee_len) &&
+ (EXT4_EE_START(ex) + ex->ee_len > EXT4_EE_START(ex_prev)))
return EXT2_ET_EXTENT_LEAF_BAD;
}

if (ix) {
- /* FIXME: 48-bit support */
if (ex->ee_block < ix->ei_block)
return EXT2_ET_EXTENT_LEAF_BAD;

@@ -111,8 +109,7 @@ errcode_t ext2fs_extent_index_verify(ext
struct ext4_extent_idx *ix_prev)
{
show_index(ix);
- /* FIXME: 48-bit support */
- if (ix->ei_leaf > fs->super->s_blocks_count)
+ if (EXT4_EI_LEAF(ix) > EXT2_BLOCKS_COUNT(fs->super))
return EXT2_ET_EXTENT_INDEX_BAD;

if (ix_prev == NULL)
@@ -164,10 +161,9 @@ errcode_t ext2fs_extent_split(struct ext
++eh->eh_entries;

ex->ee_len = count;
- /* FIXME: 48-bit support */
ex_new->ee_len -= count;
ex_new->ee_block += count;
- ex_new->ee_start += count;
+ EXT4_EE_START_SET(ex_new, EXT4_EE_START(ex_new) + count);

return 0;
}
@@ -200,7 +196,7 @@ int block_iterate_extents(struct ext4_ex
for (i = 0; i < eh->eh_entries; i++, ex++) {
show_extent(ex);
for (j = 0; j < ex->ee_len; j++) {
- block_address = ex->ee_start + j;
+ block_address = EXT4_EE_START(ex) + j;
flags = (*ctx->func)(ctx->fs, &block_address,
(ex->ee_block + j),
ref_block, i,
@@ -214,15 +210,14 @@ int block_iterate_extents(struct ext4_ex

#ifdef EXT_DEBUG
printf("ugh, extent leaf changed: "
- "block was %u+%u = %u, now %u\n",
- ex->ee_start, j,
- ex->ee_start + j, block_address);
+ "block was %llu+%llu = %llu, now %llu\n",
+ EXT4_EE_START(ex), j,
+ EXT4_EE_START(ex) + j, block_address);
#endif

- /* FIXME: 48-bit support */
if (ex_prev &&
block_address ==
- ex_prev->ee_start + ex_prev->ee_len &&
+ EXT4_EE_START(ex_prev) + ex_prev->ee_len &&
ex->ee_block + j ==
ex_prev->ee_block + ex_prev->ee_len) {
/* can merge block with prev extent */
@@ -235,7 +230,9 @@ int block_iterate_extents(struct ext4_ex
i--; ex--;
break;
} else {
- ex->ee_start++;
+ EXT4_EE_START_SET(
+ ex,
+ EXT4_EE_START(ex) + 1);
ex->ee_block++;
j--;
}
@@ -244,7 +241,7 @@ int block_iterate_extents(struct ext4_ex
} else if (ex->ee_len == 1) {
/* single-block extent is easy -
* change extent directly */
- ex->ee_start = block_address;
+ EXT4_EE_START_SET(ex, block_address);
ret |= BLOCK_CHANGED;

} else if (ext2fs_extent_split(eh, ex, j)) {
@@ -266,7 +263,7 @@ int block_iterate_extents(struct ext4_ex
ret |= BLOCK_ABORT |BLOCK_ERROR;
return ret;
}
- ex->ee_start = block_address;
+ EXT4_EE_START_SET(ex, block_address);
ret |= BLOCK_CHANGED;

} else {
@@ -277,7 +274,7 @@ int block_iterate_extents(struct ext4_ex
ret |= BLOCK_ABORT |BLOCK_ERROR;
return ret;
}
- ex->ee_start = block_address;
+ EXT4_EE_START_SET(ex, block_address);
ret |= BLOCK_CHANGED;
}
}
@@ -287,6 +284,7 @@ int block_iterate_extents(struct ext4_ex
char *block_buf;
struct ext4_extent_idx *ix;
struct ext4_extent_header *nh;
+ blk_t leaf;

ret = ext2fs_get_mem(ctx->fs->blocksize, &block_buf);
if (ret)
@@ -298,39 +296,46 @@ int block_iterate_extents(struct ext4_ex
show_index(ix);
if (!(ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
!(ctx->flags & BLOCK_FLAG_DATA_ONLY)) {
- ret |= (*ctx->func)(ctx->fs, &ix->ei_leaf,
+ leaf = EXT4_EI_LEAF(ix);
+ ret |= (*ctx->func)(ctx->fs, &leaf,
BLOCK_COUNT_IND, ref_block,
i, ctx->priv_data);
+ EXT4_EI_LEAF_SET(ix, leaf);
if (ret & BLOCK_ABORT)
goto free_buf;
}
- ctx->errcode = ext2fs_read_ext_block(ctx->fs,
- ix->ei_leaf,
- block_buf);
+ ctx->errcode = ext2fs_read_ext_block(
+ ctx->fs, EXT4_EI_LEAF(ix), block_buf);
if (ctx->errcode) {
ret |= BLOCK_ERROR;
goto free_buf;
}
nh = (struct ext4_extent_header *)block_buf;
- if (ext2fs_extent_header_verify(nh,ctx->fs->blocksize)){
+ if (ext2fs_extent_header_verify(
+ nh,ctx->fs->blocksize)) {
ret |= BLOCK_ERROR;
goto free_buf;
}
- flags = block_iterate_extents(nh, ix->ei_leaf, i, ctx);
+ flags = block_iterate_extents(
+ nh, EXT4_EI_LEAF(ix), i, ctx);
if (flags & BLOCK_CHANGED)
ctx->errcode =
- ext2fs_write_ext_block(ctx->fs,
- ix->ei_leaf,
- block_buf);
+ ext2fs_write_ext_block(
+ ctx->fs, EXT4_EI_LEAF(ix),
+ block_buf);
if (flags & BLOCK_ABORT) {
ret |= BLOCK_ABORT;
goto free_buf;
}
if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
- !(ctx->flags & BLOCK_FLAG_DATA_ONLY))
- ret |= (*ctx->func)(ctx->fs, &ix->ei_leaf,
- BLOCK_COUNT_IND, ref_block,
- i, ctx->priv_data);
+ !(ctx->flags & BLOCK_FLAG_DATA_ONLY)) {
+ leaf = EXT4_EI_LEAF(ix);
+ ret |= (*ctx->func)(ctx->fs, &leaf,
+ BLOCK_COUNT_IND,
+ ref_block,
+ i, ctx->priv_data);
+ EXT4_EI_LEAF_SET(ix, leaf);
+ }
}

free_buf:
Index: e2fsprogs-1.39/lib/ext2fs/ext4_extents.h
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/ext4_extents.h 2006-09-22 20:26:55.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/ext4_extents.h 2006-09-22 20:27:12.000000000 +0200
@@ -75,6 +75,13 @@ struct ext4_extent {
__u32 ee_start; /* low 32 bigs of physical block */
};

+#define EXT4_EE_START(e) (((__u64)(e)->ee_start_hi << 32) + (e)->ee_start)
+#define EXT4_EE_START_SET(e,blk) \
+do { \
+ (e)->ee_start = (blk); \
+ (e)->ee_start_hi = (blk) >> 32; \
+} while(0)
+
/*
* this is index on-disk structure
* it's used at all the levels, but the bottom
@@ -87,6 +94,13 @@ struct ext4_extent_idx {
__u16 ei_unused;
};

+#define EXT4_EI_LEAF(ix) (((__u64)(ix)->ei_leaf_hi << 32) + (ix)->ei_leaf)
+#define EXT4_EI_LEAF_SET(e,blk) \
+do { \
+ (ix)->ei_leaf = (blk); \
+ (ix)->ei_leaf_hi = (blk) >> 32; \
+} while(0)
+
/*
* each block (leaves and indexes), even inode-stored has header
*/
@@ -215,15 +229,22 @@ struct ext4_extents_helpers {
* callback must return valid extent (passed or newly created)
*/
typedef int (*ext_prepare_callback)(struct ext4_extents_tree *,
- struct ext4_ext_path *,
- struct ext4_extent *, int);
+ struct ext4_ext_path *,
+ struct ext4_extent *, int);
void ext4_init_tree_desc(struct ext4_extents_tree *, struct inode *);
extern int ext4_extent_tree_init(handle_t *, struct ext4_extents_tree *);
-extern int ext4_ext_calc_credits_for_insert(struct ext4_extents_tree *, struct ext4_ext_path *);
-extern int ext4_ext_insert_extent(handle_t *, struct ext4_extents_tree *, struct ext4_ext_path *, struct ext4_extent *);
-extern int ext4_ext_walk_space(struct ext4_extents_tree *, unsigned long, unsigned long, ext_prepare_callback);
-extern int ext4_ext_remove_space(struct ext4_extents_tree *, unsigned long, unsigned long);
-extern struct ext4_ext_path * ext4_ext_find_extent(struct ext4_extents_tree *, int, struct ext4_ext_path *);
+extern int ext4_ext_calc_credits_for_insert(struct ext4_extents_tree *,
+ struct ext4_ext_path *);
+extern int ext4_ext_insert_extent(handle_t *, struct ext4_extents_tree *,
+ struct ext4_ext_path *,
+ struct ext4_extent *);
+extern int ext4_ext_walk_space(struct ext4_extents_tree *, unsigned long,
+ unsigned long, ext_prepare_callback);
+extern int ext4_ext_remove_space(struct ext4_extents_tree *, unsigned long,
+ unsigned long);
+extern struct ext4_ext_path *ext4_ext_find_extent(struct ext4_extents_tree *,
+ int,
+ struct ext4_ext_path *);

static inline void
ext4_ext_invalidate_cache(struct ext4_extents_tree *tree)
Index: e2fsprogs-1.39/lib/ext2fs/bmap.c
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/bmap.c 2006-09-22 20:26:55.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/bmap.c 2006-09-22 20:27:12.000000000 +0200
@@ -46,7 +46,7 @@ static errcode_t block_bmap_extents(stru
for (i = 0; i < eh->eh_entries; i++, ex++) {
if ((ex->ee_block <= block) &&
(block < ex->ee_block + ex->ee_len)) {
- *phys_blk = ex->ee_start +
+ *phys_blk = EXT4_EE_START(ex) +
(block - ex->ee_block);
return 0;
}
@@ -68,7 +68,7 @@ static errcode_t block_bmap_extents(stru
if (ix->ei_block < block)
continue;

- ret = io_channel_read_blk(fs->io, ix->ei_leaf, 1,
+ ret = io_channel_read_blk(fs->io, EXT4_EI_LEAF(ix), 1,
block_buf);
if (ret) {
ret = BLOCK_ERROR;
Index: e2fsprogs-1.39/e2fsck/pass1.c
===================================================================
--- e2fsprogs-1.39.orig/e2fsck/pass1.c 2006-09-22 20:26:55.000000000 +0200
+++ e2fsprogs-1.39/e2fsck/pass1.c 2006-09-22 20:27:37.000000000 +0200
@@ -1509,14 +1509,18 @@ static int e2fsck_ext_block_verify(struc
e2fsck_t ctx = p->ctx;
struct problem_context *pctx = p->pctx;
int i, bad = 0, changed = 0;
+ int flag_64bit;
+
+ flag_64bit = p->ctx->fs->super->s_feature_incompat &
+ EXT4_FEATURE_INCOMPAT_64BIT;

if (eh->eh_depth == 0) {
struct ext4_extent *ex = EXT_FIRST_EXTENT(eh), *ex_prev = NULL;

for (i = 0; i < eh->eh_entries; i++, ex++) {
- /* FIXME: 48-bit check for s_blocks_count_hi */
- if (ex->ee_start_hi && fix_problem(ctx, PR_1_EXTENT_HI,
- pctx)) {
+ if (!flag_64bit &&
+ ex->ee_start_hi &&
+ fix_problem(ctx, PR_1_EXTENT_HI, pctx)) {
ex->ee_start_hi = 0;
changed++;
}
@@ -1541,9 +1545,9 @@ static int e2fsck_ext_block_verify(struc
struct ext4_extent_idx *ix =EXT_FIRST_INDEX(eh), *ix_prev =NULL;

for (i = 0; i < eh->eh_entries; i++, ix++) {
- /* FIXME: 48-bit check for s_blocks_count_hi */
- if (ix->ei_leaf_hi && fix_problem(ctx, PR_1_EXTENT_HI,
- pctx)) {
+ if (!flag_64bit &&
+ ix->ei_leaf_hi &&
+ fix_problem(ctx, PR_1_EXTENT_HI, pctx)) {
ix->ei_leaf_hi = ix->ei_unused = 0;
changed++;
}

2006-09-26 14:51:08

by Alexandre Ratchov

[permalink] [raw]
Subject: [patch 12/12] rfc: 2fsprogs update

move "*_hi" bits of bg_block_bitmap, bg_inode_bitmap, bg_inode_table
fields in the larger part of the block group descriptor

Index: e2fsprogs-1.39/lib/ext2fs/ext2_fs.h
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/ext2_fs.h 2006-09-25 13:22:21.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/ext2_fs.h 2006-09-25 13:22:27.000000000 +0200
@@ -144,10 +144,10 @@ struct ext2_group_desc
__u16 bg_free_inodes_count; /* Free inodes count */
__u16 bg_used_dirs_count; /* Directories count */
__u16 bg_flags;
- __u16 bg_block_bitmap_hi; /* Blocks bitmap block */
- __u16 bg_inode_bitmap_hi; /* Inodes bitmap block */
- __u16 bg_inode_table_hi; /* Inodes table block */
- __u16 bg_reserved[3];
+ __u32 bg_reserved[3];
+ __u32 bg_block_bitmap_hi; /* Blocks bitmap block */
+ __u32 bg_inode_bitmap_hi; /* Inodes bitmap block */
+ __u32 bg_inode_table_hi; /* Inodes table block */
};

#define EXT2_BG_INODE_UNINIT 0x0001 /* Inode table/bitmap not initialized */
@@ -156,35 +156,47 @@ struct ext2_group_desc
#define EXT2_GROUP_BASE(s,g) ((__u64)(s)->s_first_data_block + \
(__u64)(s)->s_blocks_per_group * (g))

-#define EXT2_BLOCK_BITMAP(bg) \
- ((bg)->bg_block_bitmap + ((__u64)(bg)->bg_block_bitmap_hi << 32))
-#define EXT2_INODE_BITMAP(bg) \
- ((bg)->bg_inode_bitmap + ((__u64)(bg)->bg_inode_bitmap_hi << 32))
-#define EXT2_INODE_TABLE(bg) \
- ((bg)->bg_inode_table + ((__u64)(bg)->bg_inode_table_hi << 32))
-
-#define EXT2_BLOCK_BITMAP_SET(bg, value) \
- do { \
- (bg)->bg_block_bitmap = (__u32)(value); \
- (bg)->bg_block_bitmap_hi = (value) >> 32; \
+#define EXT2_BLOCK_BITMAP(sb, bg) \
+ ((bg)->bg_block_bitmap + \
+ (EXT2_DESC_SIZE(sb) >= EXT2_MIN_DESC_SIZE_64BIT ? \
+ (blk_t)(bg)->bg_block_bitmap_hi << 32 : 0))
+#define EXT2_INODE_BITMAP(sb, bg) \
+ ((bg)->bg_inode_bitmap + \
+ (EXT2_DESC_SIZE(sb) >= EXT2_MIN_DESC_SIZE_64BIT ? \
+ (blk_t)(bg)->bg_inode_bitmap_hi << 32 : 0))
+#define EXT2_INODE_TABLE(sb, bg) \
+ ((bg)->bg_inode_table + \
+ (EXT2_DESC_SIZE(sb) >= EXT2_MIN_DESC_SIZE_64BIT ? \
+ (blk_t)(bg)->bg_inode_table_hi << 32 : 0))
+
+#define EXT2_BLOCK_BITMAP_SET(sb, bg, value) \
+ do { \
+ (bg)->bg_block_bitmap = (__u32)(value); \
+ if (EXT2_DESC_SIZE(sb) >= EXT2_MIN_DESC_SIZE_64BIT) \
+ (bg)->bg_block_bitmap_hi = (value) >> 32; \
} while(0)
-#define EXT2_INODE_BITMAP_SET(bg, value) \
- do { \
- (bg)->bg_inode_bitmap = (__u32)(value); \
- (bg)->bg_inode_bitmap_hi = (value) >> 32; \
+#define EXT2_INODE_BITMAP_SET(sb, bg, value) \
+ do { \
+ (bg)->bg_inode_bitmap = (__u32)(value); \
+ if (EXT2_DESC_SIZE(sb) >= EXT2_MIN_DESC_SIZE_64BIT) \
+ (bg)->bg_inode_bitmap_hi = (value) >> 32; \
} while(0)
-#define EXT2_INODE_TABLE_SET(bg, value) \
- do { \
- (bg)->bg_inode_table = (__u32)(value); \
- (bg)->bg_inode_table_hi = (value) >> 32; \
+#define EXT2_INODE_TABLE_SET(sb, bg, value) \
+ do { \
+ (bg)->bg_inode_table = (__u32)(value); \
+ if (EXT2_DESC_SIZE(sb) >= EXT2_MIN_DESC_SIZE_64BIT) \
+ (bg)->bg_inode_table_hi = (value) >> 32; \
} while(0)

-#define EXT2_IS_USED_BLOCK_BITMAP(bg) \
- ((bg)->bg_block_bitmap != 0 || (bg)->bg_block_bitmap_hi != 0)
-#define EXT2_IS_USED_INODE_BITMAP(bg) \
- ((bg)->bg_inode_bitmap != 0 || (bg)->bg_inode_bitmap_hi != 0)
-#define EXT2_IS_USED_INODE_TABLE(bg) \
- ((bg)->bg_inode_table != 0 || (bg)->bg_inode_table_hi != 0)
+#define EXT2_IS_USED_BLOCK_BITMAP(sb, bg) \
+ (EXT2_BLOCK_BITMAP((sb), (bg)) != 0)
+
+#define EXT2_IS_USED_INODE_BITMAP(sb, bg) \
+ (EXT2_INODE_BITMAP((sb), (bg)) != 0)
+
+#define EXT2_IS_USED_INODE_TABLE(sb, bg) \
+ (EXT2_INODE_TABLE((sb), (bg)) != 0)
+
/*
* Data structures used by the directory indexing feature
*
Index: e2fsprogs-1.39/lib/ext2fs/check_desc.c
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/check_desc.c 2006-09-25 13:00:26.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/check_desc.c 2006-09-25 13:22:27.000000000 +0200
@@ -45,22 +45,22 @@ errcode_t ext2fs_check_desc(ext2_filsys
* Check to make sure block bitmap for group is
* located within the group.
*/
- if (EXT2_BLOCK_BITMAP(&fs->group_desc[i]) < first_block ||
- EXT2_BLOCK_BITMAP(&fs->group_desc[i]) > last_block)
+ if (EXT2_BLOCK_BITMAP(fs->super, &fs->group_desc[i]) < first_block ||
+ EXT2_BLOCK_BITMAP(fs->super, &fs->group_desc[i]) > last_block)
return EXT2_ET_GDESC_BAD_BLOCK_MAP;
/*
* Check to make sure inode bitmap for group is
* located within the group
*/
- if (EXT2_INODE_BITMAP(&fs->group_desc[i]) < first_block ||
- EXT2_INODE_BITMAP(&fs->group_desc[i]) > last_block)
+ if (EXT2_INODE_BITMAP(fs->super, &fs->group_desc[i]) < first_block ||
+ EXT2_INODE_BITMAP(fs->super, &fs->group_desc[i]) > last_block)
return EXT2_ET_GDESC_BAD_INODE_MAP;
/*
* Check to make sure inode table for group is located
* within the group
*/
- if (EXT2_INODE_TABLE(&fs->group_desc[i]) < first_block ||
- ((EXT2_INODE_TABLE(&fs->group_desc[i]) +
+ if (EXT2_INODE_TABLE(fs->super, &fs->group_desc[i]) < first_block ||
+ ((EXT2_INODE_TABLE(fs->super, &fs->group_desc[i]) +
fs->inode_blocks_per_group) > last_block))
return EXT2_ET_GDESC_BAD_INODE_TABLE;
}
Index: e2fsprogs-1.39/lib/ext2fs/alloc_tables.c
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/alloc_tables.c 2006-09-25 13:00:26.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/alloc_tables.c 2006-09-25 13:22:27.000000000 +0200
@@ -56,7 +56,7 @@ errcode_t ext2fs_allocate_group_table(ex
} else
start_blk = group_blk;

- if (!EXT2_IS_USED_BLOCK_BITMAP(&fs->group_desc[group])) {
+ if (!EXT2_IS_USED_BLOCK_BITMAP(fs->super, &fs->group_desc[group])) {
retval = ext2fs_get_free_blocks(fs, start_blk, last_blk,
1, bmap, &new_blk);
if (retval == EXT2_ET_BLOCK_ALLOC_FAIL)
@@ -65,10 +65,11 @@ errcode_t ext2fs_allocate_group_table(ex
if (retval)
return retval;
ext2fs_mark_block_bitmap(bmap, new_blk);
- EXT2_BLOCK_BITMAP_SET(&fs->group_desc[group], new_blk);
+ EXT2_BLOCK_BITMAP_SET(fs->super,
+ &fs->group_desc[group], new_blk);
}

- if (!EXT2_IS_USED_INODE_BITMAP(&fs->group_desc[group])) {
+ if (!EXT2_IS_USED_INODE_BITMAP(fs->super, &fs->group_desc[group])) {
retval = ext2fs_get_free_blocks(fs, start_blk, last_blk,
1, bmap, &new_blk);
if (retval == EXT2_ET_BLOCK_ALLOC_FAIL)
@@ -77,13 +78,14 @@ errcode_t ext2fs_allocate_group_table(ex
if (retval)
return retval;
ext2fs_mark_block_bitmap(bmap, new_blk);
- EXT2_INODE_BITMAP_SET(&fs->group_desc[group], new_blk);
+ EXT2_INODE_BITMAP_SET(fs->super,
+ &fs->group_desc[group], new_blk);
}

/*
* Allocate the inode table
*/
- if (!EXT2_IS_USED_INODE_TABLE(&fs->group_desc[group])) {
+ if (!EXT2_IS_USED_INODE_TABLE(fs->super, &fs->group_desc[group])) {
retval = ext2fs_get_free_blocks(fs, group_blk, last_blk,
fs->inode_blocks_per_group,
bmap, &new_blk);
@@ -93,9 +95,9 @@ errcode_t ext2fs_allocate_group_table(ex
j < fs->inode_blocks_per_group;
j++, blk++)
ext2fs_mark_block_bitmap(bmap, blk);
- EXT2_INODE_TABLE_SET(&fs->group_desc[group], new_blk);
+ EXT2_INODE_TABLE_SET(fs->super,
+ &fs->group_desc[group], new_blk);
}
-

return 0;
}
Index: e2fsprogs-1.39/lib/ext2fs/imager.c
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/imager.c 2006-09-25 13:00:26.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/imager.c 2006-09-25 13:22:27.000000000 +0200
@@ -71,9 +71,11 @@ errcode_t ext2fs_image_inode_write(ext2_
return ENOMEM;

for (group = 0; group < fs->group_desc_count; group++) {
- if (!EXT2_IS_USED_INODE_TABLE(&fs->group_desc[(unsigned)group]))
+ if (!EXT2_IS_USED_INODE_TABLE(fs->super,
+ &fs->group_desc[(unsigned)group]))
return EXT2_ET_MISSING_INODE_TABLE;
- blk = EXT2_INODE_TABLE(&fs->group_desc[(unsigned)group]);
+ blk = EXT2_INODE_TABLE(fs->super,
+ &fs->group_desc[(unsigned)group]);
left = fs->inode_blocks_per_group;
while (left) {
c = BUF_BLOCKS;
@@ -143,11 +145,13 @@ errcode_t ext2fs_image_inode_read(ext2_f
return ENOMEM;

for (group = 0; group < fs->group_desc_count; group++) {
- if (!EXT2_IS_USED_INODE_TABLE(&fs->group_desc[(unsigned)group])) {
+ if (!EXT2_IS_USED_INODE_TABLE(fs->super,
+ &fs->group_desc[(unsigned)group])) {
retval = EXT2_ET_MISSING_INODE_TABLE;
goto errout;
}
- blk = EXT2_INODE_TABLE(&fs->group_desc[(unsigned)group]);
+ blk = EXT2_INODE_TABLE(fs->super,
+ &fs->group_desc[(unsigned)group]);
left = fs->inode_blocks_per_group;
while (left) {
c = BUF_BLOCKS;
Index: e2fsprogs-1.39/e2fsck/pass5.c
===================================================================
--- e2fsprogs-1.39.orig/e2fsck/pass5.c 2006-09-25 13:00:26.000000000 +0200
+++ e2fsprogs-1.39/e2fsck/pass5.c 2006-09-25 13:22:27.000000000 +0200
@@ -180,12 +180,16 @@ redo_counts:
(i <= super + fs->desc_blocks) &&
ext2fs_bg_has_super(fs, group))
bitmap = 1;
- else if (i == EXT2_BLOCK_BITMAP(&fs->group_desc[group]))
+ else if (i == EXT2_BLOCK_BITMAP(fs->super,
+ &fs->group_desc[group]))
bitmap = 1;
- else if (i == EXT2_INODE_BITMAP(&fs->group_desc[group]))
+ else if (i == EXT2_INODE_BITMAP(fs->super,
+ &fs->group_desc[group]))
bitmap = 1;
- else if (i >= EXT2_INODE_TABLE(&fs->group_desc[group]) &&
- (i < EXT2_INODE_TABLE(&fs->group_desc[group])
+ else if (i >= EXT2_INODE_TABLE(fs->super,
+ &fs->group_desc[group]) &&
+ (i < EXT2_INODE_TABLE(fs->super,
+ &fs->group_desc[group])
+ fs->inode_blocks_per_group))
bitmap = 1;
else
Index: e2fsprogs-1.39/lib/ext2fs/swapfs.c
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/swapfs.c 2006-09-25 13:22:21.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/swapfs.c 2006-09-25 13:22:27.000000000 +0200
@@ -74,11 +74,17 @@ void ext2fs_swap_super(struct ext2_super

}

-void ext2fs_swap_group_desc(struct ext2_group_desc *gdp)
+void ext2fs_swap_group_desc(struct ext2_super_block *sb,
+ struct ext2_group_desc *gdp)
{
gdp->bg_block_bitmap = ext2fs_swab32(gdp->bg_block_bitmap);
gdp->bg_inode_bitmap = ext2fs_swab32(gdp->bg_inode_bitmap);
gdp->bg_inode_table = ext2fs_swab32(gdp->bg_inode_table);
+ if (EXT2_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_64BIT)) {
+ gdp->bg_block_bitmap_hi = ext2fs_swab32(gdp->bg_block_bitmap_hi);
+ gdp->bg_inode_bitmap_hi = ext2fs_swab32(gdp->bg_inode_bitmap_hi);
+ gdp->bg_inode_table_hi = ext2fs_swab32(gdp->bg_inode_table_hi);
+ }
gdp->bg_free_blocks_count = ext2fs_swab16(gdp->bg_free_blocks_count);
gdp->bg_free_inodes_count = ext2fs_swab16(gdp->bg_free_inodes_count);
gdp->bg_used_dirs_count = ext2fs_swab16(gdp->bg_used_dirs_count);
Index: e2fsprogs-1.39/lib/ext2fs/rw_bitmaps.c
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/rw_bitmaps.c 2006-09-25 13:00:26.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/rw_bitmaps.c 2006-09-25 13:22:27.000000000 +0200
@@ -108,8 +108,8 @@ static errcode_t write_bitmaps(ext2_fils
for (j = nbits; j < fs->blocksize * 8; j++)
ext2fs_set_bit(j, block_buf);
}
- if (EXT2_IS_USED_BLOCK_BITMAP(&fs->group_desc[i])) {
- blk = EXT2_BLOCK_BITMAP(&fs->group_desc[i]);
+ if (EXT2_IS_USED_BLOCK_BITMAP(fs->super, &fs->group_desc[i])) {
+ blk = EXT2_BLOCK_BITMAP(fs->super, &fs->group_desc[i]);
#ifdef EXT2_BIG_ENDIAN_BITMAPS
if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
(fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)))
@@ -133,8 +133,8 @@ static errcode_t write_bitmaps(ext2_fils
goto skip_this_inode_bitmap;

memcpy(inode_buf, inode_bitmap, inode_nbytes);
- if (EXT2_IS_USED_INODE_BITMAP(&fs->group_desc[i])) {
- blk = EXT2_INODE_BITMAP(&fs->group_desc[i]);
+ if (EXT2_IS_USED_INODE_BITMAP(fs->super, &fs->group_desc[i])) {
+ blk = EXT2_INODE_BITMAP(fs->super, &fs->group_desc[i]);
#ifdef EXT2_BIG_ENDIAN_BITMAPS
if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
(fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)))
@@ -227,8 +227,10 @@ static errcode_t read_bitmaps(ext2_filsy

for (i = 0; i < fs->group_desc_count; i++) {
if (block_bitmap) {
- if (EXT2_IS_USED_BLOCK_BITMAP(&fs->group_desc[i])) {
- blk = EXT2_BLOCK_BITMAP(&fs->group_desc[i]);
+ if (EXT2_IS_USED_BLOCK_BITMAP(fs->super,
+ &fs->group_desc[i])) {
+ blk = EXT2_BLOCK_BITMAP(fs->super,
+ &fs->group_desc[i]);
if (lazy_flag && fs->group_desc[i].bg_flags &
EXT2_BG_BLOCK_UNINIT)
blk = 0;
@@ -248,8 +250,10 @@ static errcode_t read_bitmaps(ext2_filsy
block_bitmap += block_nbytes;
}
if (inode_bitmap) {
- if (EXT2_IS_USED_INODE_BITMAP(&fs->group_desc[i])) {
- blk = EXT2_INODE_BITMAP(&fs->group_desc[i]);
+ if (EXT2_IS_USED_INODE_BITMAP(fs->super,
+ &fs->group_desc[i])) {
+ blk = EXT2_INODE_BITMAP(fs->super,
+ &fs->group_desc[i]);
if (lazy_flag && fs->group_desc[i].bg_flags &
EXT2_BG_INODE_UNINIT)
blk = 0;
Index: e2fsprogs-1.39/resize/online.c
===================================================================
--- e2fsprogs-1.39.orig/resize/online.c 2006-09-25 13:00:26.000000000 +0200
+++ e2fsprogs-1.39/resize/online.c 2006-09-25 13:22:27.000000000 +0200
@@ -98,9 +98,12 @@ errcode_t online_resize_fs(ext2_filsys f
new_fs->super->s_reserved_gdt_blocks;

input.group = i;
- input.block_bitmap = EXT2_BLOCK_BITMAP(&new_fs->group_desc[i]);
- input.inode_bitmap = EXT2_INODE_BITMAP(&new_fs->group_desc[i]);
- input.inode_table = EXT2_INODE_TABLE(&new_fs->group_desc[i]);
+ input.block_bitmap = EXT2_BLOCK_BITMAP(new_fs->super,
+ &new_fs->group_desc[i]);
+ input.inode_bitmap = EXT2_INODE_BITMAP(new_fs->super,
+ &new_fs->group_desc[i]);
+ input.inode_table = EXT2_INODE_TABLE(new_fs->super,
+ &new_fs->group_desc[i]);
input.blocks_count = sb->s_blocks_per_group;
if (i == new_fs->group_desc_count-1) {
input.blocks_count = EXT2_BLOCKS_COUNT(new_fs->super) -
Index: e2fsprogs-1.39/debugfs/logdump.c
===================================================================
--- e2fsprogs-1.39.orig/debugfs/logdump.c 2006-09-25 13:00:26.000000000 +0200
+++ e2fsprogs-1.39/debugfs/logdump.c 2006-09-25 13:22:27.000000000 +0200
@@ -158,7 +158,8 @@ void do_logdump(int argc, char **argv)
/ sizeof(struct ext2_inode));

inode_block_to_dump =
- EXT2_INODE_TABLE(&current_fs->group_desc[inode_group]) +
+ EXT2_INODE_TABLE(current_fs->super,
+ &current_fs->group_desc[inode_group]) +
(group_offset / inodes_per_block);
inode_offset_to_dump = ((group_offset % inodes_per_block)
* sizeof(struct ext2_inode));
@@ -183,7 +184,9 @@ void do_logdump(int argc, char **argv)
group_to_dump = ((block_to_dump -
es->s_first_data_block)
/ es->s_blocks_per_group);
- bitmap_to_dump = EXT2_BLOCK_BITMAP(&current_fs->group_desc[group_to_dump]);
+ bitmap_to_dump = EXT2_BLOCK_BITMAP(
+ current_fs->super,
+ &current_fs->group_desc[group_to_dump]);
}

if (!journal_fn && check_fs_open(argv[0]))
Index: e2fsprogs-1.39/debugfs/debugfs.c
===================================================================
--- e2fsprogs-1.39.orig/debugfs/debugfs.c 2006-09-25 13:00:26.000000000 +0200
+++ e2fsprogs-1.39/debugfs/debugfs.c 2006-09-25 13:22:27.000000000 +0200
@@ -322,9 +322,9 @@ void do_show_super_stats(int argc, char
" %d free %s, "
"%d free %s, "
"%d used %s\n",
- i, EXT2_BLOCK_BITMAP(gdp),
- EXT2_INODE_BITMAP(gdp),
- EXT2_INODE_TABLE(gdp),
+ i, EXT2_BLOCK_BITMAP(current_fs->super, gdp),
+ EXT2_INODE_BITMAP(current_fs->super, gdp),
+ EXT2_INODE_TABLE(current_fs->super, gdp),
gdp->bg_free_blocks_count,
gdp->bg_free_blocks_count != 1 ? "blocks" : "block",
gdp->bg_free_inodes_count,
@@ -1714,13 +1714,15 @@ void do_imap(int argc, char *argv[])
offset = ((ino - 1) % EXT2_INODES_PER_GROUP(current_fs->super)) *
EXT2_INODE_SIZE(current_fs->super);
block = offset >> EXT2_BLOCK_SIZE_BITS(current_fs->super);
- if (!EXT2_IS_USED_INODE_TABLE(&current_fs->group_desc[(unsigned)group])) {
+ if (!EXT2_IS_USED_INODE_TABLE(current_fs->super,
+ &current_fs->group_desc[(unsigned)group])) {
com_err(argv[0], 0, "Inode table for group %lu is missing\n",
group);
return;
}

- block_nr = EXT2_INODE_TABLE(&current_fs->group_desc[(unsigned)group]) +
+ block_nr = EXT2_INODE_TABLE(current_fs->super,
+ &current_fs->group_desc[(unsigned)group]) +
block;
offset &= (EXT2_BLOCK_SIZE(current_fs->super) - 1);

Index: e2fsprogs-1.39/resize/resize2fs.c
===================================================================
--- e2fsprogs-1.39.orig/resize/resize2fs.c 2006-09-25 13:22:21.000000000 +0200
+++ e2fsprogs-1.39/resize/resize2fs.c 2006-09-25 13:22:27.000000000 +0200
@@ -53,9 +53,9 @@ static errcode_t ext2fs_calculate_summar
/*
* Some helper CPP macros
*/
-#define FS_BLOCK_BM(fs, i) ((fs)->group_desc[(i)].bg_block_bitmap)
-#define FS_INODE_BM(fs, i) ((fs)->group_desc[(i)].bg_inode_bitmap)
-#define FS_INODE_TB(fs, i) ((fs)->group_desc[(i)].bg_inode_table)
+#define FS_BLOCK_BM(fs, i) (EXT2_BLOCK_BITMAP((fs)->super, &(fs)->group_desc[(i)]))
+#define FS_INODE_BM(fs, i) (EXT2_INODE_BITMAP((fs)->super, &(fs)->group_desc[(i)]))
+#define FS_INODE_TB(fs, i) (EXT2_INODE_TABLE((fs)->super, &(fs)->group_desc[(i)]))

#define IS_BLOCK_BM(fs, i, blk) ((blk) == FS_BLOCK_BM((fs),(i)))
#define IS_INODE_BM(fs, i, blk) ((blk) == FS_INODE_BM((fs),(i)))
@@ -506,7 +506,8 @@ static errcode_t adjust_superblock(ext2_
* Write out the new inode table
*/
retval = io_channel_write_blk(fs->io,
- EXT2_INODE_TABLE(&fs->group_desc[i]),
+ EXT2_INODE_TABLE(fs->super,
+ &fs->group_desc[i]),
fs->inode_blocks_per_group,
rfs->itable_buf);
if (retval) goto errout;
@@ -564,7 +565,7 @@ static errcode_t mark_table_blocks(ext2_
/*
* Mark the blocks used for the inode table
*/
- for (j = 0, b = EXT2_INODE_TABLE(&fs->group_desc[i]);
+ for (j = 0, b = EXT2_INODE_TABLE(fs->super, &fs->group_desc[i]);
j < (unsigned int) fs->inode_blocks_per_group;
j++, b++)
ext2fs_mark_block_bitmap(bmap, b);
@@ -573,13 +574,15 @@ static errcode_t mark_table_blocks(ext2_
* Mark block used for the block bitmap
*/
ext2fs_mark_block_bitmap(bmap,
- EXT2_BLOCK_BITMAP(&fs->group_desc[i]));
+ EXT2_BLOCK_BITMAP(fs->super,
+ &fs->group_desc[i]));

/*
* Mark block used for the inode bitmap
*/
ext2fs_mark_block_bitmap(bmap,
- EXT2_INODE_BITMAP(&fs->group_desc[i]));
+ EXT2_INODE_BITMAP(fs->super,
+ &fs->group_desc[i]));
}
return 0;
}
@@ -604,13 +607,13 @@ static void mark_fs_metablock(ext2_resiz
* mark it as a block to be moved.
*/
if (IS_BLOCK_BM(fs, group, blk)) {
- FS_BLOCK_BM(fs, group) = 0;
+ EXT2_BLOCK_BITMAP_SET(fs->super, &fs->group_desc[group], 0ULL);
rfs->needed_blocks++;
} else if (IS_INODE_BM(fs, group, blk)) {
- FS_INODE_BM(fs, group) = 0;
+ EXT2_INODE_BITMAP_SET(fs->super, &fs->group_desc[group], 0ULL);
rfs->needed_blocks++;
} else if (IS_INODE_TB(fs, group, blk)) {
- FS_INODE_TB(fs, group) = 0;
+ EXT2_INODE_TABLE_SET(fs->super, &fs->group_desc[group], 0ULL);
rfs->needed_blocks++;
} else if (ext2fs_test_block_bitmap(rfs->old_fs->block_map, blk) &&
!ext2fs_test_block_bitmap(meta_bmap, blk)) {
@@ -745,23 +748,23 @@ static errcode_t blocks_to_move(ext2_res
group_blk + has_super);
}

- if (EXT2_IS_USED_INODE_TABLE(&fs->group_desc[i]) &&
- EXT2_IS_USED_INODE_BITMAP(&fs->group_desc[i]) &&
- EXT2_IS_USED_BLOCK_BITMAP(&fs->group_desc[i]))
+ if (EXT2_IS_USED_INODE_TABLE(fs->super, &fs->group_desc[i]) &&
+ EXT2_IS_USED_INODE_BITMAP(fs->super, &fs->group_desc[i]) &&
+ EXT2_IS_USED_BLOCK_BITMAP(fs->super, &fs->group_desc[i]))
goto next_group;

/*
* Reserve the existing meta blocks that we know
* aren't to be moved.
*/
- if (EXT2_IS_USED_BLOCK_BITMAP(&fs->group_desc[i]))
+ if (EXT2_IS_USED_BLOCK_BITMAP(fs->super, &fs->group_desc[i]))
ext2fs_mark_block_bitmap(rfs->reserve_blocks,
- EXT2_BLOCK_BITMAP(&fs->group_desc[i]));
- if (EXT2_IS_USED_INODE_BITMAP(&fs->group_desc[i]))
+ EXT2_BLOCK_BITMAP(fs->super, &fs->group_desc[i]));
+ if (EXT2_IS_USED_INODE_BITMAP(fs->super, &fs->group_desc[i]))
ext2fs_mark_block_bitmap(rfs->reserve_blocks,
- EXT2_INODE_BITMAP(&fs->group_desc[i]));
- if (EXT2_IS_USED_INODE_TABLE(&fs->group_desc[i]))
- for (blk = EXT2_INODE_TABLE(&fs->group_desc[i]), j=0;
+ EXT2_INODE_BITMAP(fs->super, &fs->group_desc[i]));
+ if (EXT2_IS_USED_INODE_TABLE(fs->super, &fs->group_desc[i]))
+ for (blk = EXT2_INODE_TABLE(fs->super, &fs->group_desc[i]), j=0;
j < fs->inode_blocks_per_group ; j++, blk++)
ext2fs_mark_block_bitmap(rfs->reserve_blocks,
blk);
@@ -812,7 +815,7 @@ static errcode_t blocks_to_move(ext2_res
* allocation bitmap, and move any blocks that might
* be necessary.
*/
- for (blk = EXT2_INODE_TABLE(&fs->group_desc[i]), j=0;
+ for (blk = EXT2_INODE_TABLE(fs->super, &fs->group_desc[i]), j=0;
j < fs->inode_blocks_per_group ; j++, blk++) {
ext2fs_mark_block_bitmap(fs->block_map, blk);
if (ext2fs_test_block_bitmap(old_fs->block_map, blk) &&
@@ -825,7 +828,8 @@ static errcode_t blocks_to_move(ext2_res
* Make sure the old inode table is reserved in the
* block reservation bitmap.
*/
- for (blk = EXT2_INODE_TABLE(&rfs->old_fs->group_desc[i]), j=0;
+ for (blk = EXT2_INODE_TABLE(rfs->old_fs->super,
+ &rfs->old_fs->group_desc[i]), j=0;
j < fs->inode_blocks_per_group ; j++, blk++)
ext2fs_mark_block_bitmap(rfs->reserve_blocks, blk);

@@ -1403,8 +1407,8 @@ static errcode_t move_itables(ext2_resiz
*/
to_move = moved = 0;
for (i=0; i < max_groups; i++) {
- if (EXT2_INODE_TABLE(&rfs->old_fs->group_desc[i]) !=
- EXT2_INODE_TABLE(&fs->group_desc[i]))
+ if (EXT2_INODE_TABLE(rfs->old_fs->super, &rfs->old_fs->group_desc[i]) !=
+ EXT2_INODE_TABLE(fs->super, &fs->group_desc[i]))
to_move++;
}

@@ -1421,8 +1425,10 @@ static errcode_t move_itables(ext2_resiz
rfs->old_fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;

for (i=0; i < max_groups; i++) {
- old_blk = EXT2_INODE_TABLE(&rfs->old_fs->group_desc[i]);
- new_blk = EXT2_INODE_TABLE(&fs->group_desc[i]);
+ old_blk = EXT2_INODE_TABLE(rfs->old_fs->super,
+ &rfs->old_fs->group_desc[i]);
+ new_blk = EXT2_INODE_TABLE(fs->super,
+ &fs->group_desc[i]);
diff = new_blk - old_blk;

#ifdef RESIZE2FS_DEBUG
@@ -1475,11 +1481,13 @@ static errcode_t move_itables(ext2_resiz
goto errout;
}

- for (blk = EXT2_INODE_TABLE(&rfs->old_fs->group_desc[i]), j=0;
+ for (blk = EXT2_INODE_TABLE(rfs->old_fs->super,
+ &rfs->old_fs->group_desc[i]), j=0;
j < fs->inode_blocks_per_group ; j++, blk++)
ext2fs_unmark_block_bitmap(fs->block_map, blk);

- EXT2_INODE_TABLE_SET(&rfs->old_fs->group_desc[i], new_blk);
+ EXT2_INODE_TABLE_SET(rfs->old_fs->super,
+ &rfs->old_fs->group_desc[i], new_blk);
ext2fs_mark_super_dirty(rfs->old_fs);
ext2fs_flush(rfs->old_fs);

Index: e2fsprogs-1.39/misc/dumpe2fs.c
===================================================================
--- e2fsprogs-1.39.orig/misc/dumpe2fs.c 2006-09-25 13:00:26.000000000 +0200
+++ e2fsprogs-1.39/misc/dumpe2fs.c 2006-09-25 13:22:27.000000000 +0200
@@ -188,20 +188,20 @@ static void list_desc (ext2_filsys fs)
if (has_super)
fputc('\n', stdout);
fputs(_(" Block bitmap at "), stdout);
- print_number(EXT2_BLOCK_BITMAP(&fs->group_desc[i]));
- diff = EXT2_BLOCK_BITMAP(&fs->group_desc[i]) - first_block;
+ print_number(EXT2_BLOCK_BITMAP(fs->super, &fs->group_desc[i]));
+ diff = EXT2_BLOCK_BITMAP(fs->super, &fs->group_desc[i]) - first_block;
if (diff >= 0)
printf(" (+%ld)", diff);
fputs(_(", Inode bitmap at "), stdout);
- print_number(EXT2_INODE_BITMAP(&fs->group_desc[i]));
- diff = EXT2_INODE_BITMAP(&fs->group_desc[i]) - first_block;
+ print_number(EXT2_INODE_BITMAP(fs->super, &fs->group_desc[i]));
+ diff = EXT2_INODE_BITMAP(fs->super, &fs->group_desc[i]) - first_block;
if (diff >= 0)
printf(" (+%ld)", diff);
fputs(_("\n Inode table at "), stdout);
- print_range(EXT2_INODE_TABLE(&fs->group_desc[i]),
- EXT2_INODE_TABLE(&fs->group_desc[i]) +
+ print_range(EXT2_INODE_TABLE(fs->super, &fs->group_desc[i]),
+ EXT2_INODE_TABLE(fs->super, &fs->group_desc[i]) +
inode_blocks_per_group - 1);
- diff = EXT2_INODE_TABLE(&fs->group_desc[i]) - first_block;
+ diff = EXT2_INODE_TABLE(fs->super, &fs->group_desc[i]) - first_block;
if (diff > 0)
printf(" (+%ld)", diff);
printf (_("\n %d free blocks, %d free inodes, "
Index: e2fsprogs-1.39/e2fsck/swapfs.c
===================================================================
--- e2fsprogs-1.39.orig/e2fsck/swapfs.c 2006-09-25 13:00:26.000000000 +0200
+++ e2fsprogs-1.39/e2fsck/swapfs.c 2006-09-25 13:22:27.000000000 +0200
@@ -131,7 +131,7 @@ static void swap_inodes(e2fsck_t ctx)
"block interate buffer");
for (group = 0; group < fs->group_desc_count; group++) {
retval = io_channel_read_blk(fs->io,
- EXT2_INODE_TABLE(&fs->group_desc[group]),
+ EXT2_INODE_TABLE(fs->super, &fs->group_desc[group]),
fs->inode_blocks_per_group, buf);
if (retval) {
com_err("swap_inodes", retval,
@@ -169,7 +169,7 @@ static void swap_inodes(e2fsck_t ctx)
ext2fs_swap_inode(fs, inode, inode, 1);
}
retval = io_channel_write_blk(fs->io,
- EXT2_INODE_TABLE(&fs->group_desc[group]),
+ EXT2_INODE_TABLE(fs->super, &fs->group_desc[group]),
fs->inode_blocks_per_group, buf);
if (retval) {
com_err("swap_inodes", retval,
Index: e2fsprogs-1.39/resize/main.c
===================================================================
--- e2fsprogs-1.39.orig/resize/main.c 2006-09-25 13:00:26.000000000 +0200
+++ e2fsprogs-1.39/resize/main.c 2006-09-25 13:22:27.000000000 +0200
@@ -106,11 +106,11 @@ static void determine_fs_stride(ext2_fil
has_sb = ext2fs_bg_has_super(fs, group);
if (group == 0 || has_sb != prev_has_sb)
goto next;
- b_stride = EXT2_BLOCK_BITMAP(&fs->group_desc[group]) -
- EXT2_BLOCK_BITMAP(&fs->group_desc[group-1]) -
+ b_stride = EXT2_BLOCK_BITMAP(fs->super, &fs->group_desc[group]) -
+ EXT2_BLOCK_BITMAP(fs->super, &fs->group_desc[group-1]) -
fs->super->s_blocks_per_group;
- i_stride = EXT2_INODE_BITMAP(&fs->group_desc[group]) -
- EXT2_INODE_BITMAP(&fs->group_desc[group-1]) -
+ i_stride = EXT2_INODE_BITMAP(fs->super, &fs->group_desc[group]) -
+ EXT2_INODE_BITMAP(fs->super, &fs->group_desc[group-1]) -
fs->super->s_blocks_per_group;
if (b_stride != i_stride ||
b_stride < 0)
Index: e2fsprogs-1.39/misc/mke2fs.c
===================================================================
--- e2fsprogs-1.39.orig/misc/mke2fs.c 2006-09-25 13:22:21.000000000 +0200
+++ e2fsprogs-1.39/misc/mke2fs.c 2006-09-25 13:22:27.000000000 +0200
@@ -419,7 +419,7 @@ static void write_inode_tables(ext2_fils
for (i = 0; i < fs->group_desc_count; i++) {
progress_update(&progress, i);

- blk = EXT2_INODE_TABLE(&fs->group_desc[i]);
+ blk = EXT2_INODE_TABLE(fs->super, &fs->group_desc[i]);
num = fs->inode_blocks_per_group;

if (!(lazy_flag &&
Index: e2fsprogs-1.39/lib/ext2fs/inode.c
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/inode.c 2006-09-25 13:00:26.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/inode.c 2006-09-25 13:22:27.000000000 +0200
@@ -142,7 +142,8 @@ errcode_t ext2fs_open_inode_scan(ext2_fi
scan->current_group = 0;
scan->groups_left = fs->group_desc_count - 1;
scan->inode_buffer_blocks = buffer_blocks ? buffer_blocks : 8;
- scan->current_block = EXT2_INODE_TABLE(&scan->fs->group_desc[scan->current_group]);
+ scan->current_block = EXT2_INODE_TABLE(scan->fs->super,
+ &scan->fs->group_desc[scan->current_group]);
scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super);
scan->blocks_left = scan->fs->inode_blocks_per_group;
retval = ext2fs_get_mem((size_t) (scan->inode_buffer_blocks *
@@ -220,7 +221,8 @@ static errcode_t get_next_blockgroup(ext
scan->current_group++;
scan->groups_left--;

- scan->current_block = EXT2_INODE_TABLE(&scan->fs->group_desc[scan->current_group]);
+ scan->current_block = EXT2_INODE_TABLE(scan->fs->super,
+ &scan->fs->group_desc[scan->current_group]);

scan->current_inode = scan->current_group *
EXT2_INODES_PER_GROUP(scan->fs->super);
@@ -545,9 +547,11 @@ errcode_t ext2fs_read_inode_full(ext2_fi
offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) *
EXT2_INODE_SIZE(fs->super);
block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super);
- if (!EXT2_IS_USED_INODE_TABLE(&fs->group_desc[(unsigned)group]))
+ if (!EXT2_IS_USED_INODE_TABLE(fs->super,
+ &fs->group_desc[(unsigned)group]))
return EXT2_ET_MISSING_INODE_TABLE;
- block_nr = EXT2_INODE_TABLE(&fs->group_desc[(unsigned)group]) +
+ block_nr = EXT2_INODE_TABLE(fs->super,
+ &fs->group_desc[(unsigned)group]) +
block;
io = fs->io;
}
@@ -669,9 +673,11 @@ errcode_t ext2fs_write_inode_full(ext2_f
offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) *
EXT2_INODE_SIZE(fs->super);
block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super);
- if (!EXT2_IS_USED_INODE_TABLE(&fs->group_desc[(unsigned) group]))
+ if (!EXT2_IS_USED_INODE_TABLE(fs->super,
+ &fs->group_desc[(unsigned) group]))
return EXT2_ET_MISSING_INODE_TABLE;
- block_nr = EXT2_INODE_TABLE(&fs->group_desc[(unsigned) group]) + block;
+ block_nr = EXT2_INODE_TABLE(fs->super,
+ &fs->group_desc[(unsigned) group]) + block;

offset &= (EXT2_BLOCK_SIZE(fs->super) - 1);

Index: e2fsprogs-1.39/e2fsck/pass1b.c
===================================================================
--- e2fsprogs-1.39.orig/e2fsck/pass1b.c 2006-09-25 13:00:26.000000000 +0200
+++ e2fsprogs-1.39/e2fsck/pass1b.c 2006-09-25 13:22:27.000000000 +0200
@@ -802,15 +802,15 @@ static int check_if_fs_block(e2fsck_t ct
}

/* Check the inode table */
- if ((EXT2_INODE_TABLE(&fs->group_desc[i]) &&
- (test_block >= EXT2_INODE_TABLE(&fs->group_desc[i])) &&
- (test_block < (EXT2_INODE_TABLE(&fs->group_desc[i]) +
+ if ((EXT2_INODE_TABLE(fs->super, &fs->group_desc[i]) &&
+ (test_block >= EXT2_INODE_TABLE(fs->super, &fs->group_desc[i])) &&
+ (test_block < (EXT2_INODE_TABLE(fs->super, &fs->group_desc[i]) +
fs->inode_blocks_per_group))))
return 1;

/* Check the bitmap blocks */
- if ((test_block == EXT2_BLOCK_BITMAP(&fs->group_desc[i])) ||
- (test_block == EXT2_INODE_BITMAP(&fs->group_desc[i])))
+ if ((test_block == EXT2_BLOCK_BITMAP(fs->super, &fs->group_desc[i])) ||
+ (test_block == EXT2_INODE_BITMAP(fs->super, &fs->group_desc[i])))
return 1;

first_block += fs->super->s_blocks_per_group;
Index: e2fsprogs-1.39/e2fsck/pass1.c
===================================================================
--- e2fsprogs-1.39.orig/e2fsck/pass1.c 2006-09-25 13:22:19.000000000 +0200
+++ e2fsprogs-1.39/e2fsck/pass1.c 2006-09-25 13:22:27.000000000 +0200
@@ -2106,22 +2106,22 @@ static int process_bad_block(ext2_filsys
return 0;
}
skip_super:
- if (blk == EXT2_BLOCK_BITMAP(&fs->group_desc[i])) {
+ if (blk == EXT2_BLOCK_BITMAP(fs->super, &fs->group_desc[i])) {
if (fix_problem(ctx, PR_1_BB_BAD_BLOCK, pctx)) {
ctx->invalid_block_bitmap_flag[i]++;
ctx->invalid_bitmaps++;
}
return 0;
}
- if (blk == EXT2_INODE_BITMAP(&fs->group_desc[i])) {
+ if (blk == EXT2_INODE_BITMAP(fs->super, &fs->group_desc[i])) {
if (fix_problem(ctx, PR_1_IB_BAD_BLOCK, pctx)) {
ctx->invalid_inode_bitmap_flag[i]++;
ctx->invalid_bitmaps++;
}
return 0;
}
- if ((blk >= EXT2_INODE_TABLE(&fs->group_desc[i])) &&
- (blk < (EXT2_INODE_TABLE(&fs->group_desc[i]) +
+ if ((blk >= EXT2_INODE_TABLE(fs->super, &fs->group_desc[i])) &&
+ (blk < (EXT2_INODE_TABLE(fs->super, &fs->group_desc[i]) +
fs->inode_blocks_per_group))) {
/*
* If there are bad blocks in the inode table,
@@ -2233,22 +2233,22 @@ static void handle_fs_bad_blocks(e2fsck_
first_block = ext2fs_group_first_block(fs, i);

if (ctx->invalid_block_bitmap_flag[i]) {
- blk = EXT2_BLOCK_BITMAP(&fs->group_desc[i]);
+ blk = EXT2_BLOCK_BITMAP(fs->super, &fs->group_desc[i]);
new_table_block(ctx, first_block, i, _("block bitmap"),
1, &blk);
- EXT2_BLOCK_BITMAP_SET(&fs->group_desc[i], blk);
+ EXT2_BLOCK_BITMAP_SET(fs->super, &fs->group_desc[i], blk);
}
if (ctx->invalid_inode_bitmap_flag[i]) {
- blk = EXT2_INODE_BITMAP(&fs->group_desc[i]);
+ blk = EXT2_INODE_BITMAP(fs->super, &fs->group_desc[i]);
new_table_block(ctx, first_block, i, _("inode bitmap"),
1, &blk);
- EXT2_INODE_BITMAP_SET(&fs->group_desc[i], blk);
+ EXT2_INODE_BITMAP_SET(fs->super, &fs->group_desc[i], blk);
}
if (ctx->invalid_inode_table_flag[i]) {
- blk = EXT2_INODE_TABLE(&fs->group_desc[i]);
+ blk = EXT2_INODE_TABLE(fs->super, &fs->group_desc[i]);
new_table_block(ctx, first_block, i, _("inode table"),
fs->inode_blocks_per_group, &blk);
- EXT2_INODE_TABLE_SET(&fs->group_desc[i], blk);
+ EXT2_INODE_TABLE_SET(fs->super, &fs->group_desc[i], blk);
ctx->flags |= E2F_FLAG_RESTART;
}
}
@@ -2277,8 +2277,8 @@ static void mark_table_blocks(e2fsck_t c
/*
* Mark the blocks used for the inode table
*/
- if (EXT2_IS_USED_INODE_TABLE(&fs->group_desc[i])) {
- for (j = 0, b = EXT2_INODE_TABLE(&fs->group_desc[i]);
+ if (EXT2_IS_USED_INODE_TABLE(fs->super, &fs->group_desc[i])) {
+ for (j = 0, b = EXT2_INODE_TABLE(fs->super, &fs->group_desc[i]);
j < fs->inode_blocks_per_group;
j++, b++) {
if (ext2fs_test_block_bitmap(ctx->block_found_map,
@@ -2299,34 +2299,40 @@ static void mark_table_blocks(e2fsck_t c
/*
* Mark block used for the block bitmap
*/
- if (EXT2_IS_USED_BLOCK_BITMAP(&fs->group_desc[i])) {
+ if (EXT2_IS_USED_BLOCK_BITMAP(fs->super, &fs->group_desc[i])) {
if (ext2fs_test_block_bitmap(ctx->block_found_map,
- EXT2_BLOCK_BITMAP(&fs->group_desc[i]))) {
- pctx.blk = EXT2_BLOCK_BITMAP(&fs->group_desc[i]);
+ EXT2_BLOCK_BITMAP(fs->super,
+ &fs->group_desc[i]))) {
+ pctx.blk = EXT2_BLOCK_BITMAP(fs->super,
+ &fs->group_desc[i]);
if (fix_problem(ctx, PR_1_BB_CONFLICT, &pctx)) {
ctx->invalid_block_bitmap_flag[i]++;
ctx->invalid_bitmaps++;
}
} else {
- ext2fs_mark_block_bitmap(ctx->block_found_map,
- EXT2_BLOCK_BITMAP(&fs->group_desc[i]));
+ ext2fs_mark_block_bitmap(ctx->block_found_map,
+ EXT2_BLOCK_BITMAP(fs->super,
+ &fs->group_desc[i]));
}

}
+
/*
* Mark block used for the inode bitmap
*/
- if (EXT2_IS_USED_INODE_BITMAP(&fs->group_desc[i])) {
+ if (EXT2_IS_USED_INODE_BITMAP(fs->super, &fs->group_desc[i])) {
if (ext2fs_test_block_bitmap(ctx->block_found_map,
- EXT2_INODE_BITMAP(&fs->group_desc[i]))) {
- pctx.blk = EXT2_INODE_BITMAP(&fs->group_desc[i]);
+ EXT2_INODE_BITMAP(fs->super, &fs->group_desc[i]))) {
+ pctx.blk = EXT2_INODE_BITMAP(fs->super,
+ &fs->group_desc[i]);
if (fix_problem(ctx, PR_1_IB_CONFLICT, &pctx)) {
ctx->invalid_inode_bitmap_flag[i]++;
ctx->invalid_bitmaps++;
}
} else {
- ext2fs_mark_block_bitmap(ctx->block_found_map,
- EXT2_INODE_BITMAP(&fs->group_desc[i]));
+ ext2fs_mark_block_bitmap(ctx->block_found_map,
+ EXT2_INODE_BITMAP(fs->super,
+ &fs->group_desc[i]));
}
}
}
Index: e2fsprogs-1.39/e2fsck/super.c
===================================================================
--- e2fsprogs-1.39.orig/e2fsck/super.c 2006-09-25 13:00:26.000000000 +0200
+++ e2fsprogs-1.39/e2fsck/super.c 2006-09-25 13:22:27.000000000 +0200
@@ -574,34 +574,34 @@ void check_super_block(e2fsck_t ctx)
first_block = ext2fs_group_first_block(fs, i);
last_block = ext2fs_group_last_block(fs, i);

- if ((EXT2_BLOCK_BITMAP(gd) < first_block) ||
- (EXT2_BLOCK_BITMAP(gd) > last_block)) {
- pctx.blk = EXT2_BLOCK_BITMAP(gd);
+ if ((EXT2_BLOCK_BITMAP(fs->super, gd) < first_block) ||
+ (EXT2_BLOCK_BITMAP(fs->super, gd) > last_block)) {
+ pctx.blk = EXT2_BLOCK_BITMAP(fs->super, gd);
if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx))
- EXT2_BLOCK_BITMAP_SET(gd, 0ULL);
+ EXT2_BLOCK_BITMAP_SET(fs->super, gd, 0ULL);
}
- if (!EXT2_IS_USED_BLOCK_BITMAP(gd)) {
+ if (!EXT2_IS_USED_BLOCK_BITMAP(fs->super, gd)) {
ctx->invalid_block_bitmap_flag[i]++;
ctx->invalid_bitmaps++;
}
- if ((EXT2_INODE_BITMAP(gd) < first_block) ||
- (EXT2_INODE_BITMAP(gd) > last_block)) {
- pctx.blk = EXT2_INODE_BITMAP(gd);
+ if ((EXT2_INODE_BITMAP(fs->super, gd) < first_block) ||
+ (EXT2_INODE_BITMAP(fs->super, gd) > last_block)) {
+ pctx.blk = EXT2_INODE_BITMAP(fs->super, gd);
if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx))
- EXT2_INODE_BITMAP_SET(gd, 0ULL);
+ EXT2_INODE_BITMAP_SET(fs->super, gd, 0ULL);
}
- if (!EXT2_IS_USED_INODE_BITMAP(gd)) {
+ if (!EXT2_IS_USED_INODE_BITMAP(fs->super, gd)) {
ctx->invalid_inode_bitmap_flag[i]++;
ctx->invalid_bitmaps++;
}
- if ((EXT2_INODE_TABLE(gd) < first_block) ||
- ((EXT2_INODE_TABLE(gd) +
+ if ((EXT2_INODE_TABLE(fs->super, gd) < first_block) ||
+ ((EXT2_INODE_TABLE(fs->super, gd) +
fs->inode_blocks_per_group - 1) > last_block)) {
- pctx.blk = EXT2_INODE_TABLE(gd);
+ pctx.blk = EXT2_INODE_TABLE(fs->super, gd);
if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx))
- EXT2_INODE_TABLE_SET(gd, 0ULL);
+ EXT2_INODE_TABLE_SET(fs->super, gd, 0ULL);
}
- if (!EXT2_IS_USED_INODE_TABLE(gd)) {
+ if (!EXT2_IS_USED_INODE_TABLE(fs->super, gd)) {
ctx->invalid_inode_table_flag[i]++;
ctx->invalid_bitmaps++;
}
Index: e2fsprogs-1.39/misc/e2image.c
===================================================================
--- e2fsprogs-1.39.orig/misc/e2image.c 2006-09-25 13:00:26.000000000 +0200
+++ e2fsprogs-1.39/misc/e2image.c 2006-09-25 13:22:27.000000000 +0200
@@ -265,8 +265,8 @@ static void mark_table_blocks(ext2_filsy
/*
* Mark the blocks used for the inode table
*/
- if (EXT2_IS_USED_INODE_TABLE(&fs->group_desc[i])) {
- for (j = 0, b = EXT2_INODE_TABLE(&fs->group_desc[i]);
+ if (EXT2_IS_USED_INODE_TABLE(fs->super, &fs->group_desc[i])) {
+ for (j = 0, b = EXT2_INODE_TABLE(fs->super, &fs->group_desc[i]);
j < (unsigned) fs->inode_blocks_per_group;
j++, b++)
ext2fs_mark_block_bitmap(meta_block_map, b);
@@ -275,17 +275,17 @@ static void mark_table_blocks(ext2_filsy
/*
* Mark block used for the block bitmap
*/
- if (EXT2_IS_USED_BLOCK_BITMAP(&fs->group_desc[i])) {
+ if (EXT2_IS_USED_BLOCK_BITMAP(fs->super, &fs->group_desc[i])) {
ext2fs_mark_block_bitmap(meta_block_map,
- EXT2_BLOCK_BITMAP(&fs->group_desc[i]));
+ EXT2_BLOCK_BITMAP(fs->super, &fs->group_desc[i]));
}

/*
* Mark block used for the inode bitmap
*/
- if (EXT2_IS_USED_INODE_BITMAP(&fs->group_desc[i])) {
+ if (EXT2_IS_USED_INODE_BITMAP(fs->super, &fs->group_desc[i])) {
ext2fs_mark_block_bitmap(meta_block_map,
- EXT2_INODE_BITMAP(&fs->group_desc[i]));
+ EXT2_INODE_BITMAP(fs->super, &fs->group_desc[i]));
}
}
}
Index: e2fsprogs-1.39/lib/ext2fs/ext2fs.h
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/ext2fs.h 2006-09-25 13:22:21.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/ext2fs.h 2006-09-25 13:22:27.000000000 +0200
@@ -956,7 +956,8 @@ extern errcode_t ext2fs_copy_bitmap(ext2
extern void ext2fs_swap_ext_attr(char *to, char *from, int bufsize,
int has_header);
extern void ext2fs_swap_super(struct ext2_super_block * super);
-extern void ext2fs_swap_group_desc(struct ext2_group_desc *gdp);
+extern void ext2fs_swap_group_desc(struct ext2_super_block *sb,
+ struct ext2_group_desc *gdp);
extern void ext2fs_swap_inode_full(ext2_filsys fs, struct ext2_inode_large *t,
struct ext2_inode_large *f, int hostorder,
int bufsize);
Index: e2fsprogs-1.39/lib/ext2fs/openfs.c
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/openfs.c 2006-09-25 13:22:21.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/openfs.c 2006-09-25 13:22:27.000000000 +0200
@@ -293,7 +293,7 @@ errcode_t ext2fs_open2(const char *name,
memcpy(gdp, shadow_block + j * fs->desc_size, fs->desc_size);
#ifdef EXT2FS_ENABLE_SWAPFS
if (fs->flags & EXT2_FLAG_SWAP_BYTES)
- ext2fs_swap_group_desc(gdp);
+ ext2fs_swap_group_desc(fs->super, gdp);
#endif
gdp++;
}
Index: e2fsprogs-1.39/lib/ext2fs/closefs.c
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/closefs.c 2006-09-25 13:22:21.000000000 +0200
+++ e2fsprogs-1.39/lib/ext2fs/closefs.c 2006-09-25 13:22:27.000000000 +0200
@@ -235,7 +235,7 @@ errcode_t ext2fs_flush(ext2_filsys fs)
memcpy(gd, &fs->group_desc[i], fs->desc_size);
#ifdef EXT2FS_ENABLE_SWAPFS
if (fs->flags & EXT2_FLAG_SWAP_BYTES)
- ext2fs_swap_group_desc(gd);
+ ext2fs_swap_group_desc(fs->super, gd);
#endif
}


2006-09-26 16:48:00

by Alexandre Ratchov

[permalink] [raw]
Subject: Re: rfc: 2fsprogs update

On Tue, Sep 26, 2006 at 04:33:43PM +0200, Alexandre Ratchov wrote:
> hello,
>
> i've updated e2fsprogs to be in sync with the latest kernel changes; here is
> a summary of all changes:
>
> 01-head_20060918
>
> this is a diff between 1.39 and a mercurial snapshot from sep 18,
> 2006. It's here just to allow people to apply the patch set on
> e2fsprogs-1.39
>

the patch seems too large for the mailing list server; so it can be found
here:

http://www.bullopensource.org/ext4/20060926/e2fsprogs-1.39/patches/01-head_20060918

cheers,

-- Alexandre Ratchov

2006-09-26 17:33:07

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [patch 04/12] rfc: 2fsprogs update

On Tue, Sep 26, 2006 at 04:47:16PM +0200, Alexandre Ratchov wrote:
> from Andreas:
>
> Support for checking 32-bit extents format inodes.

I made comments about this on linux-ext4, but I got no responses...
so I'm resposting those comments below. At the moment (when I can
find the time) I am breaking up the patch, and will hopefully shortly
commit in what I think is the right library interface, and then
hopefully I or someone else will be able to rework this patch (which
is way too big, and violates the namespace guidelines --- all
publically visible new symbols in the ext2fs library must be prefixed
by ext2fs_ in order to minimize namespace pollution issues) to use
the new interfaces.

- Ted


So I've been noodling over Andreas' patches to support 32-bit extents,
as well as glancing at the 48-bit and 64-bit patches, and I've come to
an initial plan for how to fold this into e2fsprogs in the most
ABI-preserving, backwards compatible way possible. This does mean that
the patches will have to get rototilled significantly before they get
merged in, as I want to make some major changes to the interfaces in
order to guarantee as much forwards compatibility as possible.

I also happen to be a very firm believer in Rusty's philosophy about
interface design, namely for big projects, that it's all about damage
control --- you want interfaces that are not just easy to use, but hard
to misuse, and that it's all about getting the interfaces right.

http://ozlabs.org/~rusty/ols-2003-keynote/img29.html

It gets worse given that for the ext2fs shared library, we need to make
sure we get the interfaces right once we release a stable version, since
I need to preserve ABI compatibility.


So the first thing I want to do is to define a new interface for dealing
with extents in libext2fs. It will look like this:

/*
* Generic (non-filesystem layout specific) extents structure
*/
struct ext2fs_extent {
blk64_t e_pblk; /* first physical block */
blk64_t e_lblk; /* first logical block extent covers */
int e_len; /* number of blocks covered by extent */
};


Note the use of blk64_t; yes, this means that blk_t will stay as a
32-bit value, and blk64_t will be used for new interfaces and be a
64-bit value. The basic idea is that as we add support for new extents
formats: 48-bit, 64-bit, bit-packing for compressing many extents inside
the inode, etc., I don't want this to be visible to most applications.
So we will define a new structure to pass extents informatoin between
the library and applications, which is independent of the on-disk
format.

This will get used to define an extent iterator function, that will look
something like this:

errcode_t ext2fs_extent_iterate(ext2_filsys fs,
ext2_ino_t ino,
int flags,
char *block_buf,
int (*func)(ext2_filsys fs,
struct ext2fs_extent *extent,
void *priv_data),
int (*meta_func)(ext2_filsys fs,
blk64_t blk,
int blk_type,
char *buf,
void *priv_data),
void *priv_data);

This interface will work for both extent and non-extent-based
inodes.... that is, if this interface is called on an inode which is
using direct and indirect blocks, the function will Do The Right Thing
and find contiguous blocks runs which it will use to fill extent
structures that will be passed to the callback function. This is fine,
since extent-based interfaces will be easier and more efficient to use
anyway.

We will also define two interfaces to manipulate the extents tree (and
which again, will Do The Right Thing on traditional non-extents based
inods):

errcode_t ext2fs_extent_set(ext2_filsys fs,
ext2_ino_t ino,
ext2_ino_t *block_buf,
struct_ext2fs_extent *extent);

errcode_t ext2fs_extent_delete(ext2_filsys fs,
ext2_ino_t ino,
ext2_ino_t *block_buf,
struct_ext2fs_extent *extent);


Both of these interfaces may require splitting an existing extent. For
example, if ext2fs_extent_set() is passed an extent which falls in the
middle of an extent in the inode, it could result in one extent turning
into three extents (namely the before extent, the new extent, and the
after extent). Similarly ext2fs_extent_delete() may be asked to delete
a sub-extent in the middle of an existing extent in the extent tree.
This would be logically equivalent to the Windows NT "punch" operation,
which is a more general version of truncate(), except it can remove
blocks from the middle of a file.


The other interface which I've started spec'ing out in my mind is a new
form interface and implementation for bitmaps(). The new-style bitmaps
will take a blk64_t type, but their biggest difference is that they will
allow multiple different types of interfaces, much like the io_manager
abstractions we have right now abstracts our I/O reoutines. Some
implementations may use an extents tree to keep track of used and unused
bits. Anothers might use a disk file as a LRU backing store (this will
be necessary to support really large storage devices on systems with
limited physical memory). And of course, at least initially the first
implementation we will support will be the old-fasheioned, "store the
whole thing in memory" approach.

So the basic idea is to implement new library abstractions which will
work well for 32-bit extents, but which can be easily extensible to
newer patches, and which can solve other problems as well while we're at
it (such as the people trying to use a cheap processor with small
amounts of memory with terabytes of storagte and their having problems
with fsck running out of memory, for example).

Comments?

- Ted


2006-09-26 17:37:13

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [patch 07/12] rfc: 2fsprogs update

On Tue, Sep 26, 2006 at 04:48:32PM +0200, Alexandre Ratchov wrote:
> convert all 32bit on-disk block number definitions (currently __u32,
> blk_t, unsigned long, unsigned int...) to pblk_t that is defined as
> __u32. In this way we are sure that blk_t is used only in memory.
> Later, this would allow to make blk_t 64bit without disturbing any
> programs (this would just eat more momory and use 64bit arithmetic).

I *really* dislike this approach, because it makes it very hard to
prove that we got all of the conversions right --- any mistakes about
which instances of blk_t need to become pblk_t, and which are supposed
to stay blk_t, and we end up breaking our ABI compatibility. And
let's just say I have higher standards than Greg KH has shown with
udev. :-)

I also don't like pblk_t, because it's not at all obvious what it
means. And what if we want to support 64-bit logicial blocks someday?
Then it's another painful exercise to figure out which blk_t get
separated to lblk_t, etc.


So my plan is to introduce a new type, blk64_t, and create new
interfaces, such as ext2fs_extent_iterate(), which will use the new
type --- and which will work with old-style indirect block inodes as
well (it will translate indirect blocks into extents).

- Ted

2006-09-26 19:54:52

by Andreas Dilger

[permalink] [raw]
Subject: Re: [patch 04/12] rfc: 2fsprogs update

On Sep 26, 2006 13:32 -0400, Theodore Tso wrote:
> hopefully I or someone else will be able to rework this patch (which
> is way too big, and violates the namespace guidelines --- all
> publically visible new symbols in the ext2fs library must be prefixed
> by ext2fs_ in order to minimize namespace pollution issues)

The only function which matches this description is block_iterate_extents()
but it is not desired that this be a public interface. It is just the
"bridge" function between the block iterator and the extent iterator.

> */
> struct ext2fs_extent {
> blk64_t e_pblk; /* first physical block */
> blk64_t e_lblk; /* first logical block extent covers */
> int e_len; /* number of blocks covered by extent */
> };
>
>
> Note the use of blk64_t; yes, this means that blk_t will stay as a
> 32-bit value, and blk64_t will be used for new interfaces and be a
> 64-bit value. The basic idea is that as we add support for new extents
> formats: 48-bit, 64-bit, bit-packing for compressing many extents inside
> the inode, etc., I don't want this to be visible to most applications.
> So we will define a new structure to pass extents informatoin between
> the library and applications, which is independent of the on-disk
> format.
>
> This will get used to define an extent iterator function, that will look
> something like this:
>
> errcode_t ext2fs_extent_iterate(ext2_filsys fs,
> ext2_ino_t ino,
> int flags,
> char *block_buf,
> int (*func)(ext2_filsys fs,
> struct ext2fs_extent *extent,
> void *priv_data),
> int (*meta_func)(ext2_filsys fs,
> blk64_t blk,
> int blk_type,
> char *buf,
> void *priv_data),
> void *priv_data);

Hmm, except that this interface isn't sufficient (at first glance) to
allow full correctness checking of the extent metadata blocks. It
would allow checking of a given indirect/index block but not parent/child
relationships between the index block and the extents/index it points to...

> This interface will work for both extent and non-extent-based
> inodes.... that is, if this interface is called on an inode which is
> using direct and indirect blocks, the function will Do The Right Thing
> and find contiguous blocks runs which it will use to fill extent
> structures that will be passed to the callback function. This is fine,
> since extent-based interfaces will be easier and more efficient to use
> anyway.

Do you think this will be CPU-intensive on non-extent filesystems?

> We will also define two interfaces to manipulate the extents tree (and
> which again, will Do The Right Thing on traditional non-extents based
> inods):
>
> errcode_t ext2fs_extent_set(ext2_filsys fs,
> ext2_ino_t ino,
> ext2_ino_t *block_buf,
> struct_ext2fs_extent *extent);
>
> errcode_t ext2fs_extent_delete(ext2_filsys fs,
> ext2_ino_t ino,
> ext2_ino_t *block_buf,
> struct_ext2fs_extent *extent);

Should the above "ext2_ino_t *block_buf" be "ext2_blk_t *block_buf"?

> The other interface which I've started spec'ing out in my mind is a new
> form interface and implementation for bitmaps(). The new-style bitmaps
> will take a blk64_t type, but their biggest difference is that they will
> allow multiple different types of interfaces, much like the io_manager
> abstractions we have right now abstracts our I/O reoutines. Some
> implementations may use an extents tree to keep track of used and unused
> bits. Anothers might use a disk file as a LRU backing store (this will
> be necessary to support really large storage devices on systems with
> limited physical memory). And of course, at least initially the first
> implementation we will support will be the old-fasheioned, "store the
> whole thing in memory" approach.

It sounds desirable, but is this going to be a requirement for 1.40? It
seems like a lot of non-critical work at a point where you have little free
time and there are other things awaiting the release of 1.40.

Cheers, Andreas
--
Andreas Dilger
Principal Software Engineer
Cluster File Systems, Inc.


2006-09-26 21:16:55

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [patch 04/12] rfc: 2fsprogs update

On Tue, Sep 26, 2006 at 01:54:49PM -0600, Andreas Dilger wrote:
> The only function which matches this description is block_iterate_extents()
> but it is not desired that this be a public interface. It is just the
> "bridge" function between the block iterator and the extent iterator.

Yes, and I thought about simply pouring your extent.c file into
block.c so I could make it a static function. That would have solved
the function, although made block.c a bit bulky. But then when I
started thinking about the interface, I realized I wasn't completely
happy with it anyway, so I started rethinking what we wanted to
export.

> > errcode_t ext2fs_extent_iterate(ext2_filsys fs,
> > ext2_ino_t ino,
> > int flags,
> > char *block_buf,
> > int (*func)(ext2_filsys fs,
> > struct ext2fs_extent *extent,
> > void *priv_data),
> > int (*meta_func)(ext2_filsys fs,
> > blk64_t blk,
> > int blk_type,
> > char *buf,
> > void *priv_data),
> > void *priv_data);
>
> Hmm, except that this interface isn't sufficient (at first glance) to
> allow full correctness checking of the extent metadata blocks. It
> would allow checking of a given indirect/index block but not parent/child
> relationships between the index block and the extents/index it points to...

I believe that if we do breadth-first descent through the tree, and
call meta_func three times for each interior node of the tree. So
when we hit an interior node, we call the meta_func() callback
function, and then we interate through all of the contents of the
node, calling either the func or meta_func callback as appropriate,
and then we call meta_func callback on the parent node again. If the
child nodes are interior nodes, we then descend down the tree by
taking each interior node in turn, treating each one as a parent,
i.e., calling the meta_func() callback first, then func() or
meta_func() for all of its children, and then meta_func() callback
again.

The blk_type would allow the callback function to determine whether it
is being called as PARENT_BEGIN_NODE, CHILD_ITERATE_NODE, or
PARENT_END_NODE.

> > This interface will work for both extent and non-extent-based
> > inodes.... that is, if this interface is called on an inode which is
> > using direct and indirect blocks, the function will Do The Right Thing
> > and find contiguous blocks runs which it will use to fill extent
> > structures that will be passed to the callback function. This is fine,
> > since extent-based interfaces will be easier and more efficient to use
> > anyway.
>
> Do you think this will be CPU-intensive on non-extent filesystems?

No, I don't think so.

For the application that needs to iterate over all of the blocks in
the file, whether we do it block by block, or do it inside the
block_interate_extent() function and then returning each extent one at
a time, it's the same amount of work. In fact, by coalescing adjacent
blocks into an extent, the result is probably more cache friendly and
might actually save execution time.

This is especially true for userspace callers, since they pretty much
all interate over the file sequentially. The only reason why we might
not want to do this in the kernel is because it may not make sense for
random access files ---- although as we've discussed before, for
certain files, like database files, which are opened, and then
accessed repeatedly via a random access pattern, it may make sense to
figure out all of the extents in advance, store the extent tree in
memory, to accelerate random access lookups.

> > The other interface which I've started spec'ing out in my mind is a new
> > form interface and implementation for bitmaps(). The new-style bitmaps
> > will take a blk64_t type, but their biggest difference is that they will
> > allow multiple different types of interfaces, much like the io_manager
> > abstractions we have right now abstracts our I/O reoutines. Some
> > implementations may use an extents tree to keep track of used and unused
> > bits.....
>
> It sounds desirable, but is this going to be a requirement for 1.40? It
> seems like a lot of non-critical work at a point where you have little free
> time and there are other things awaiting the release of 1.40.

No --- but that raises the question of what we need to get into 1.40,
and what time line. From my way of thinking of things, the big thing
we need to get into 1.40 is extent support, but I'd like to make the
interfaces be correct for 64-bits, even if we don't all get them
there.

Also, if we can get the interfaces _right_, it doesn't necessarily
have to me who does all of the coding. Others can hopefully do some
of the coding to for example adapt the e2fsck patches to use the new
interfaces --- and if we've gotten the interfaces right, that really
shouldn't be that difficult.

As far as the non-critical work of supporting extra bitmap types, we
don't have to do it all; we just have to do enough of the framework to
support them, and then implement the basic
store-the-whole-bitmap-in-memory one to get started. We can always do
the rest later.

Regards,

- Ted

2006-09-27 13:00:11

by Alexandre Ratchov

[permalink] [raw]
Subject: Re: [patch 04/12] rfc: 2fsprogs update

On Tue, Sep 26, 2006 at 01:32:53PM -0400, Theodore Tso wrote:
>
> /*
> * Generic (non-filesystem layout specific) extents structure
> */
> struct ext2fs_extent {
> blk64_t e_pblk; /* first physical block */
> blk64_t e_lblk; /* first logical block extent covers */
> int e_len; /* number of blocks covered by extent */
> };
>
>
> Note the use of blk64_t; yes, this means that blk_t will stay as a
> 32-bit value, and blk64_t will be used for new interfaces and be a
> 64-bit value.

if blk_t stays 32bit and we want to use e2fsprogs on 64bit file systems then
we will have to duplicate most of the current code. I mean, since ? 32bit
on-disk file system is a valid 64bit file system then the 64bit part of
e2fsprogs will have to deal also with the 32bit stuff like 32bit indirect
blocks, 32bit group descriptors etc. Thus we'll have to rewrite/dumplicate
all the blk_t code on a new blk64_t branch. So we will have to maintain 2
branches of code that do the same thing:

- "blk_t" branch: pure 32bit code

- "blk64_t" branch: 64bit code with 32bit compatibility

So my question is: do we want to (1) maintains both blk_t and blk64_t APIs
or (2) switch to the new "blk64_t" interface and just fix bugs in the old
interface until it dies.

Any thoughts here?

> This will get used to define an extent iterator function, that will look
> something like this:
>
> errcode_t ext2fs_extent_iterate(ext2_filsys fs,
> ext2_ino_t ino,
> int flags,
> char *block_buf,
> int (*func)(ext2_filsys fs,
> struct ext2fs_extent *extent,
> void *priv_data),
> int (*meta_func)(ext2_filsys fs,
> blk64_t blk,
> int blk_type,
> char *buf,
> void *priv_data),
> void *priv_data);
>
> This interface will work for both extent and non-extent-based
> inodes.... that is, if this interface is called on an inode which is
> using direct and indirect blocks, the function will Do The Right Thing
> and find contiguous blocks runs which it will use to fill extent
> structures that will be passed to the callback function. This is fine,
> since extent-based interfaces will be easier and more efficient to use
> anyway.
>
> We will also define two interfaces to manipulate the extents tree (and
> which again, will Do The Right Thing on traditional non-extents based
> inods):
>
> errcode_t ext2fs_extent_set(ext2_filsys fs,
> ext2_ino_t ino,
> ext2_ino_t *block_buf,
> struct_ext2fs_extent *extent);
>
> errcode_t ext2fs_extent_delete(ext2_filsys fs,
> ext2_ino_t ino,
> ext2_ino_t *block_buf,
> struct_ext2fs_extent *extent);
>
>
> Both of these interfaces may require splitting an existing extent. For
> example, if ext2fs_extent_set() is passed an extent which falls in the
> middle of an extent in the inode, it could result in one extent turning
> into three extents (namely the before extent, the new extent, and the
> after extent). Similarly ext2fs_extent_delete() may be asked to delete
> a sub-extent in the middle of an existing extent in the extent tree.
> This would be logically equivalent to the Windows NT "punch" operation,
> which is a more general version of truncate(), except it can remove
> blocks from the middle of a file.
>
>
> The other interface which I've started spec'ing out in my mind is a new
> form interface and implementation for bitmaps(). The new-style bitmaps
> will take a blk64_t type, but their biggest difference is that they will
> allow multiple different types of interfaces, much like the io_manager
> abstractions we have right now abstracts our I/O reoutines. Some
> implementations may use an extents tree to keep track of used and unused
> bits. Anothers might use a disk file as a LRU backing store (this will
> be necessary to support really large storage devices on systems with
> limited physical memory). And of course, at least initially the first
> implementation we will support will be the old-fasheioned, "store the
> whole thing in memory" approach.
>
> So the basic idea is to implement new library abstractions which will
> work well for 32-bit extents, but which can be easily extensible to
> newer patches, and which can solve other problems as well while we're at
> it (such as the people trying to use a cheap processor with small
> amounts of memory with terabytes of storagte and their having problems
> with fsck running out of memory, for example).
>

i really like the idea. Since the first time i've looked into the e2fsprogs
i'm wondering why don't we use such an interface for the library since the
beginning. I don't see much reasons to export functions and data structures
that deal with the details of the file system layout.

I see 2 different aspects for the libext2fs:

(1) iterate/read/modify/delete inodes, files and directories; that's what
programs to access ext{2,3,4} file systems without mounting them may
want to do. Or programs to defragment, produce statistics etc...

these tasks don't need to know anything about the layout of the
file-system;

(2) check and fix: that's what fsck does, that's a more complicated and
depends more closely on the file system layout.

IMO, interfaces you propose are perfect for (1) and do most of the job for
(2), but i don't know if they are enough for a tool like fsck. For instance
it's not clear for me how to check and repair extent indexes and headers;
how to check that the logical block number matches the block number within
the extent without using "lower level" routines.

Perhaps we can always check data structures "on the fly" in the iterator
function and just return an error code if an anomaly is found; in this case
the caller could delete the inode (or partially copy it in /lost+found,
etc...)

This point isn't clear for me; do you have any idea, here?

The same question holds for a future block allocation and for inode
allocation abstract interfaces.

-- Alexandre

2006-09-27 13:36:51

by Alexandre Ratchov

[permalink] [raw]
Subject: Re: [patch 07/12] rfc: 2fsprogs update

On Tue, Sep 26, 2006 at 01:37:00PM -0400, Theodore Tso wrote:
> On Tue, Sep 26, 2006 at 04:48:32PM +0200, Alexandre Ratchov wrote:
> > convert all 32bit on-disk block number definitions (currently __u32,
> > blk_t, unsigned long, unsigned int...) to pblk_t that is defined as
> > __u32. In this way we are sure that blk_t is used only in memory.
> > Later, this would allow to make blk_t 64bit without disturbing any
> > programs (this would just eat more momory and use 64bit arithmetic).
>
> I *really* dislike this approach, because it makes it very hard to
> prove that we got all of the conversions right --- any mistakes about
> which instances of blk_t need to become pblk_t, and which are supposed
> to stay blk_t, and we end up breaking our ABI compatibility. And
> let's just say I have higher standards than Greg KH has shown with
> udev. :-)
>
> I also don't like pblk_t, because it's not at all obvious what it
> means.

It just means "__u32". It's used in very very few places. Mainly to access
on-disk indirect blocks, typically as follows:

char *ind_block_buf;
pblk_t *pblk;
blk_t blk;

...

pblk = (pblk_t *)ind_block_buf;

for (i = 0, ; i < N; i++) {
blk = *pblk;
...
pblk++;
}

So, the only purpose on the typedef is to "tag" 32bit variables that are
used for such purposes and that have to stay 32bit forever. I expect in the
long term to remove the typedef and to simply use __u32 in such code. For me
this patch is a "temporary stage" in order to avoid confusion between blk_t,
__u32, int, long, etc... and to do the 32bit -> 64bit convertion of block
numbers in a safe manner.

> And what if we want to support 64-bit logicial blocks someday?
> Then it's another painful exercise to figure out which blk_t get
> separated to lblk_t, etc.
>

i fully agree here; personnaly, i would like to see only one type for block
numbers: blk_t (or blk64_t if you prefer). And in some sense this patch
contributes to reduce the number of types we use for block numbers. Indeed,
it replaces most int, long, __u32 etc... by blk_t and pblk_t.

>
> So my plan is to introduce a new type, blk64_t, and create new
> interfaces, such as ext2fs_extent_iterate(), which will use the new
> type --- and which will work with old-style indirect block inodes as
> well (it will translate indirect blocks into extents).

i think we want the same thing, except that i've called blk_t what you call
blk64_t.

In order to get the blk64_t interface working with old-style indirect block
inodes, we have to use __u32 pointers to access indirect blocks and blk64_t
for the rest. If we want to reuse the existing code, we have to walk through
it distinguishing between __u32, long, int, blk_t, and replacing some of them by
blk64_t. That's very close to what this patch does.

Perhaps it's not obvious, but thats my approach to get all of the
conversions right without rewriting everything from scratch ;-). I'm still
open to other approches.

cheers,

-- Alexandre

2006-09-27 14:10:18

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [patch 04/12] rfc: 2fsprogs update

On Wed, Sep 27, 2006 at 02:59:57PM +0200, Alexandre Ratchov wrote:
> if blk_t stays 32bit and we want to use e2fsprogs on 64bit file systems then
> we will have to duplicate most of the current code. I mean, since ? 32bit
> on-disk file system is a valid 64bit file system then the 64bit part of
> e2fsprogs will have to deal also with the 32bit stuff like 32bit indirect
> blocks, 32bit group descriptors etc. Thus we'll have to rewrite/dumplicate
> all the blk_t code on a new blk64_t branch. So we will have to maintain 2
> branches of code that do the same thing:
>
> - "blk_t" branch: pure 32bit code
>
> - "blk64_t" branch: 64bit code with 32bit compatibility
>
> So my question is: do we want to (1) maintains both blk_t and blk64_t APIs
> or (2) switch to the new "blk64_t" interface and just fix bugs in the old
> interface until it dies.

Well, as I discussed later, I think we'll end up needing to make
changes to a number of these interfaces anyway --- for example, if we
get the block iterators and the bitmap interfaces, what's left? Well,
let's see:

* The block allocation routines (ext2fs_new_block and friends) ---
which probably wants to be changed to be based on allocating
extents, anyway.
* The badblocks list functions --- trivial code, easy to maintain in
parallel.
* ext2fs_bmap() -- Yup, we'll need a 64-bit version, and then we'll probably
just implement the 32-bit version in terms of the 64-bit version
* ext2fs_read/write_dirblock, and a few others -- same thing as ext2fs_bmap()

The bottom line is that there really aren't that many interfaces, and
this also gives us the opportunity to clean up the interfaces as we go
along, and make sure we get them right. To me, that's far more
important than whether or not we get e2fsprogs 64-bit capable within
some tight time window. After all, we've missed the RHEL5 inclusion
window anyway, as far as I can tell, so I'd much rather trade off
long-term maintainability and cleanliness for a short-term getting
e2fsprogs 1.40 out the door.

> i really like the idea. Since the first time i've looked into the e2fsprogs
> i'm wondering why don't we use such an interface for the library since the
> beginning. I don't see much reasons to export functions and data structures
> that deal with the details of the file system layout.
>
> I see 2 different aspects for the libext2fs:
>
> (1) iterate/read/modify/delete inodes, files and directories; that's what
> programs to access ext{2,3,4} file systems without mounting them may
> want to do. Or programs to defragment, produce statistics etc...
>
> these tasks don't need to know anything about the layout of the
> file-system;
>
> (2) check and fix: that's what fsck does, that's a more complicated and
> depends more closely on the file system layout.
>
> IMO, interfaces you propose are perfect for (1) and do most of the job for
> (2), but i don't know if they are enough for a tool like fsck. For instance
> it's not clear for me how to check and repair extent indexes and headers;
> how to check that the logical block number matches the block number within
> the extent without using "lower level" routines.
>
> Perhaps we can always check data structures "on the fly" in the iterator
> function and just return an error code if an anomaly is found; in this case
> the caller could delete the inode (or partially copy it in /lost+found,
> etc...)
>
> This point isn't clear for me; do you have any idea, here?

It's not clear because I've never been rigid about this point. The
high level functions in ext2fs, such as those in fileio.c, absolutely
assume that the caller knows nothing about the filesystem layout, and
more importantly, that the filesystem is consistent. There are some
basic checks (and there should be more) to make sure that things
aren't blatently corrupted, and the functions will return an error
message if the checks fail, but they aren't intended for use by fsck.
That corresponds to your category (1) functions, above.

But there are also those lower-level functions which are designed to
return enough information so that e2fsck can check the filesystem for
consistency, and if necessary, repair the filesystem. A good example
of that is the block iterator functions. There is information
returned in the callback functions which are of use only to e2fsck.
Normal application programs just ignore it.

And that was in my design of the block_extent_iterator as well; in
particular, I would assume that normal applications would never pass
in a function pointer to meta_func(), and that they would just simply
want to iterate over all of the extents in logical block order.
E2fsck would probably continue to call the block iterators for
traditional inods, and only call the extent interator for extent-based
inodes, and e2fsck would pass in a meta_func() callback so it would
receive information about low-level format information which is
supposed to check and possibly repair. (See my reply to Andreas about
how meta_func would probably be called multiple times to allow e2fsck
to do what it needs to do.)

So this is a delicate balancing act, and yes, it means that we have to
balance interface cleanliness, ease of use, and efficiency across two
different use cases --- the normal application usage model, and the
e2fsck model. One thing which makes this easier is that I've always
assumed that e2fsck and libext2fs will be upgraded in parallel. So
e2fsck *can* depend on the low-level details about how the
extent_iterator will behave if e2fsck modifies interior node
information in the meta_func callback, since normal applications will
never use it.

Also, the general rule of thumb is that while basic consistency checks
--- enough to keep libext2fs from core dumping and from doing grevious
harm to the filesystem if it is slightly corrupted --- all of the
fine-grained consistency checks and repair logic belongs in e2fsck,
not in libext2fs. The only thing that we want to provide in libext2fs
is read/write access to low-level format data, hopefully in a useful
high-level abstraction such as the block and extent iterators, so that
e2fsck can do its job.

Does this help?

- Ted

P.S. This should probably be written up as documentation as part of
libext2fs design philosophy so that future patch writers can write
patches that I don't have to spend as much time rewriting. :-)

2006-09-27 14:37:58

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [patch 07/12] rfc: 2fsprogs update

On Wed, Sep 27, 2006 at 03:36:42PM +0200, Alexandre Ratchov wrote:
> Perhaps it's not obvious, but thats my approach to get all of the
> conversions right without rewriting everything from scratch ;-). I'm still
> open to other approches.

Yes, and I appreciate that concern. However, given that we need to
support an extents-based iterator anyway, and given that we need to
break the bitmap code anyway so that it gets away from using inline
functions and can __eventually__ support multiple back-end
implementation, we will end up needing to breaking and reimplementing
the interfaces anyway.... and for the other bits of code, simply
defining a new interface and changing blk_t to blk64_t isn't that hard
and isn't want I would call "rewriting".

The other thing I would mention is that my plan for the extent
iterator is that if the inode uses indirect blocks, what the extent
iterator would do is call the block iterator function, and then
coalesce the results into extents and call the extent callback
function. So the question of when to use __u32 pointers wouldn't
arise, since we would use the existing code to iterate through the
indirect blocks. Easy!

Similarly, what I would do for the block_iterator is *if* the inode is
extent based, and *if* the filesystem is less than 2**32 blocks, then
the block iterator would call the extent_iterator, and then translate
the extents into blocks and call the block iterator's callback
function multiple times. This would be a backwards compatibility
scaffolding, until other portions of the library were converted over
use the extent iterator directly.

So in this fashion it's possible to minimize the amount of code that
we need to maintain in parallel; each functionality is only
implemented in one place, and yet the result still has as much
backwards compatibility as possible.

- Ted