2007-06-29 06:41:55

by Girish Shilamkar

[permalink] [raw]
Subject: [PATCH] Add in-inode extents swabbing.

Hi,
On big-endian machines the regressions tests for extents failed.
Upon further investigations I found that ext2fs_swap_inode_full() didn't
take into consideration whether extent map or block map is used hence even
if an inode contains extents, i_block was swabbed using ext2fs_swab32(),
without considering the extents format.

Even after this three tests failed:
f_extents_eh_magic:
In pass1 as magic is incorrect the extents flag in inode->i_flag is reset.
Hence when check_blocks calls *_ind_verify and as now i_blocks are interpreted
as u32 instead of extents format. and qsorts does a diff sort and hence
different output is generated by regression test.

f_extents_eh_max : Same as above.

f_extents :
Inode 13 has inode->i_flags not set for extents hence while swapping it
assumes
it to be block map.

The patch needs to be further improved by taking into consideration that
inode->i_flags might be corrupt.

Regards,
Girish

Signed-off-by: Girish Shilamkar <[email protected]>

Index: e2fsprogs-1.39/lib/ext2fs/swapfs.c
===================================================================
--- e2fsprogs-1.39.orig/lib/ext2fs/swapfs.c
+++ e2fsprogs-1.39/lib/ext2fs/swapfs.c
@@ -168,7 +168,7 @@ void ext2fs_swap_inode_full(ext2_filsys
struct ext2_inode_large *f, int hostorder,
int bufsize)
{
- unsigned i, has_data_blocks, extra_isize;
+ unsigned i, has_data_blocks, extra_isize, has_extents;
int islnk = 0;
__u32 *eaf, *eat;

@@ -192,15 +192,44 @@ void ext2fs_swap_inode_full(ext2_filsys
if (!hostorder)
has_data_blocks = ext2fs_inode_data_blocks(fs,
(struct ext2_inode *) t);
+ if (hostorder)
+ has_extents = (f->i_flags & EXT4_EXTENTS_FL);
t->i_flags = ext2fs_swab32(f->i_flags);
+ if (!hostorder)
+ has_extents = (t->i_flags & EXT4_EXTENTS_FL);
t->i_file_acl = ext2fs_swab32(f->i_file_acl);
t->i_dir_acl = ext2fs_swab32(f->i_dir_acl);
- if (!islnk || has_data_blocks ) {
- for (i = 0; i < EXT2_N_BLOCKS; i++)
- t->i_block[i] = ext2fs_swab32(f->i_block[i]);
- } else if (t != f) {
- for (i = 0; i < EXT2_N_BLOCKS; i++)
- t->i_block[i] = f->i_block[i];
+ if (has_extents) {
+ struct ext3_extent_header *eh;
+ int max = ((EXT2_N_BLOCKS * sizeof(__u32)) - sizeof(*eh));
+
+ if (!islnk || has_data_blocks ) {
+ memcpy(t->i_block, f->i_block, sizeof(f->i_block));
+ eh = (struct ext3_extent_header *)t->i_block;
+ ext2fs_swap_extent_header(eh);
+
+ if (!eh->eh_depth) {
+ struct ext3_extent *ex = EXT_FIRST_EXTENT(eh);
+ max = max / sizeof(struct ext3_extent);
+ for (i = 0; i < max; i++, ex++)
+ ext2fs_swap_extent(ex);
+ } else {
+ struct ext3_extent_idx *ix =
+ EXT_FIRST_INDEX(eh);
+ max = max / sizeof(struct ext3_extent_idx);
+ for (i = 0; i < max; i++, ix++)
+ ext2fs_swap_extent_index(ix);
+ }
+ } else if (t != f)
+ memcpy(t->i_block, f->i_block, sizeof(f->i_block));
+ } else {
+ if (!islnk || has_data_blocks ) {
+ for (i = 0; i < EXT2_N_BLOCKS; i++)
+ t->i_block[i] = ext2fs_swab32(f->i_block[i]);
+ } else if (t != f) {
+ for (i = 0; i < EXT2_N_BLOCKS; i++)
+ t->i_block[i] = f->i_block[i];
+ }
}
t->i_generation = ext2fs_swab32(f->i_generation);
t->i_faddr = ext2fs_swab32(f->i_faddr);