From: Girish Shilamkar Subject: [PATCH] Add in-inode extents swabbing. Date: Fri, 29 Jun 2007 12:11:52 +0530 Message-ID: <1183099312.3043.2.camel@dhcp7.linsyssoft.com> Mime-Version: 1.0 Content-Type: text/plain Content-Transfer-Encoding: 7bit Cc: Andreas Dilger , Theodore Tso To: Ext4 Mailing List Return-path: Received: from mail.clusterfs.com ([206.168.112.78]:53584 "EHLO mail.clusterfs.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750732AbXF2Glz (ORCPT ); Fri, 29 Jun 2007 02:41:55 -0400 Sender: linux-ext4-owner@vger.kernel.org List-Id: linux-ext4.vger.kernel.org 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 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);