Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 103087 Details for
Bug 156697
Patch e2fsprogs for ext4
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
e2fsprogs-1.39-ext4-extents.patch
e2fsprogs-1.39-ext4-extents.patch (text/plain), 65.82 KB, created by
Conrad Kostecki
on 2006-12-01 00:48:06 UTC
(
hide
)
Description:
e2fsprogs-1.39-ext4-extents.patch
Filename:
MIME Type:
Creator:
Conrad Kostecki
Created:
2006-12-01 00:48:06 UTC
Size:
65.82 KB
patch
obsolete
>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, info@clusterfs.com >+ * Written by Alex Tomas <alex@clusterfs.com> >+ * >+ * 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 <alex@clusterfs.com> >+ * Copyright (C) 2006 Andreas Dilger <adilger@clusterfs.com> >+ * >+ * %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
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 156697
:
103083
|
103084
|
103085
|
103087
|
103088
|
103089
|
103090
|
103091
|
103092
|
103093
|
103094
|
103095
|
103096
|
103859