From: Theodore Ts'o Date: Thu, 3 Oct 2002 02:07:17 +0000 (-0400) Subject: Fix endian problems in the htree code for e2fsck and debugfs. X-Git-Tag: E2FSPROGS-1_30~31 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=8132d840c8f6b0d90ab5048d6f8529f74e1aa0b3;p=tools%2Fe2fsprogs.git Fix endian problems in the htree code for e2fsck and debugfs. When byte-swapping a filesystem on a PPC architecture, byte-swap the bitmaps since the historical big-endian ext2 variant had byte-swapped bitmaps, and the ext2fs library assumes this. Otherwise the regression test suite will fail... --- diff --git a/debugfs/ChangeLog b/debugfs/ChangeLog index 6f17d31..a038554 100644 --- a/debugfs/ChangeLog +++ b/debugfs/ChangeLog @@ -1,3 +1,8 @@ +2002-10-02 Theodore Y. Ts'o + + * htree.c (htree_dump_leaf_node): Use ext2fs_read_dir_block2 so + that the directory entries are appropriately byte-swapped. + 2001-09-24 Theodore Tso * Release of E2fsprogs 1.29 diff --git a/debugfs/htree.c b/debugfs/htree.c index c719e4e..9ae2f11 100644 --- a/debugfs/htree.c +++ b/debugfs/htree.c @@ -49,7 +49,7 @@ static void htree_dump_leaf_node(ext2_filsys fs, ext2_ino_t ino, return; } - errcode = io_channel_read_blk(current_fs->io, pblk, 1, buf); + errcode = ext2fs_read_dir_block2(current_fs, pblk, buf, 0); if (errcode) { com_err("htree_dump_leaf_node", errcode, "while reading block %d\n", blk); diff --git a/e2fsck/ChangeLog b/e2fsck/ChangeLog index 8feceff..3f19a40 100644 --- a/e2fsck/ChangeLog +++ b/e2fsck/ChangeLog @@ -1,3 +1,14 @@ +2002-10-02 Theodore Y. Ts'o + + * pass2.c (parse_int_node, check_dir_block): Add byte-swap + functions around the htree code, so that it works on + big-endian machines. + + * swapfs.c (swap_filesys): For PPC machines, byte-swap the bitmap, + since PPC big-endian filesystems were historically wierd. + This is just for the regression test, since no one + actually uses them anymore... + 2002-09-30 Theodore Ts'o * problem.c, problem.h (PR_2_HTREE_BAD_LIMIT, diff --git a/e2fsck/pass2.c b/e2fsck/pass2.c index b08223c..1555f5a 100644 --- a/e2fsck/pass2.c +++ b/e2fsck/pass2.c @@ -543,20 +543,22 @@ static void parse_int_node(ext2_filsys fs, limit = (struct ext2_dx_countlimit *) ent; #ifdef DX_DEBUG - printf("Number of entries (count): %d\n", limit->count); - printf("Number of entries (limit): %d\n", limit->limit); + printf("Number of entries (count): %d\n", + ext2fs_le16_to_cpu(limit->count)); + printf("Number of entries (limit): %d\n", + ext2fs_le16_to_cpu(limit->limit)); #endif - count = limit->count; + count = ext2fs_le16_to_cpu(limit->count); expect_limit = (fs->blocksize - ((char *) ent - block_buf)) / sizeof(struct ext2_dx_entry); - if (limit->limit != expect_limit) { - cd->pctx.num = limit->limit; + if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) { + cd->pctx.num = ext2fs_le16_to_cpu(limit->limit); if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx)) goto clear_and_exit; } - if (limit->count > expect_limit) { - cd->pctx.num = limit->count; + if (count > expect_limit) { + cd->pctx.num = count; if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx)) goto clear_and_exit; count = expect_limit; @@ -564,12 +566,12 @@ static void parse_int_node(ext2_filsys fs, for (i=0; i < count; i++) { prev_hash = hash; - hash = i ? (ent[i].hash & ~1) : 0; + hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0; #ifdef DX_DEBUG printf("Entry #%d: Hash 0x%08x, block %d\n", i, - hash, ent[i].block); + hash, ext2fs_le32_to_cpu(ent[i].block)); #endif - blk = ent[i].block & 0x0ffffff; + blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff; /* Check to make sure the block is valid */ if (blk > dx_dir->numblocks) { cd->pctx.blk = blk; @@ -592,8 +594,9 @@ static void parse_int_node(ext2_filsys fs, if (hash > max_hash) max_hash = hash; dx_db->node_min_hash = hash; - if ((i+1) < limit->count) - dx_db->node_max_hash = (ent[i+1].hash & ~1); + if ((i+1) < count) + dx_db->node_max_hash = + ext2fs_le32_to_cpu(ent[i+1].hash) & ~1; else { dx_db->node_max_hash = 0xfffffffe; dx_db->flags |= DX_FLAG_LAST; @@ -782,8 +785,9 @@ static int check_dir_block(ext2_filsys fs, } else if ((dirent->inode == 0) && (dirent->rec_len == fs->blocksize) && (dirent->name_len == 0) && - (limit->limit == ((fs->blocksize-8) / - sizeof(struct ext2_dx_entry)))) + (ext2fs_le16_to_cpu(limit->limit) == + ((fs->blocksize-8) / + sizeof(struct ext2_dx_entry)))) dx_db->type = DX_DIRBLOCK_NODE; } #endif /* ENABLE_HTREE */ diff --git a/e2fsck/swapfs.c b/e2fsck/swapfs.c index 513859b..b59079c 100644 --- a/e2fsck/swapfs.c +++ b/e2fsck/swapfs.c @@ -183,6 +183,31 @@ static void swap_inodes(e2fsck_t ctx) e2fsck_use_inode_shortcuts(ctx, 0); } +#if defined(__powerpc__) && defined(EXT2FS_ENABLE_SWAPFS) +/* + * On the PowerPC, the big-endian variant of the ext2 filesystem + * has its bitmaps stored as 32-bit words with bit 0 as the LSB + * of each word. Thus a bitmap with only bit 0 set would be, as + * a string of bytes, 00 00 00 01 00 ... + * To cope with this, we byte-reverse each word of a bitmap if + * we have a big-endian filesystem, that is, if we are *not* + * byte-swapping other word-sized numbers. + */ +#define EXT2_BIG_ENDIAN_BITMAPS +#endif + +#ifdef EXT2_BIG_ENDIAN_BITMAPS +static void ext2fs_swap_bitmap(ext2fs_generic_bitmap bmap) +{ + __u32 *p = (__u32 *) bmap->bitmap; + int n, nbytes = (bmap->end - bmap->start + 7) / 8; + + for (n = nbytes / sizeof(__u32); n > 0; --n, ++p) + *p = ext2fs_swab32(*p); +} +#endif + + void swap_filesys(e2fsck_t ctx) { ext2_filsys fs = ctx->fs; @@ -222,6 +247,13 @@ void swap_filesys(e2fsck_t ctx) fs->flags |= EXT2_FLAG_SWAP_BYTES; fs->flags &= ~(EXT2_FLAG_SWAP_BYTES_READ| EXT2_FLAG_SWAP_BYTES_WRITE); + +#ifdef EXT2_BIG_ENDIAN_BITMAPS + e2fsck_read_bitmaps(ctx); + ext2fs_swap_bitmap(fs->inode_map); + ext2fs_swap_bitmap(fs->block_map); + fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY; +#endif ext2fs_flush(fs); #ifdef RESOURCE_TRACK diff --git a/lib/ext2fs/ChangeLog b/lib/ext2fs/ChangeLog index b70364c..320643f 100644 --- a/lib/ext2fs/ChangeLog +++ b/lib/ext2fs/ChangeLog @@ -1,3 +1,13 @@ +2002-10-02 Theodore Y. Ts'o + + * rw_bitmaps.c (ext2fs_write_block_bitmap, + ext2fs_read_block_bitmap): Don't set the CHANGED bit just + because the bitmap is getting written to disk. Make + ext2fs_swap_bitmap be a static function, since it's not + intended to be exported. + + * swapfs.c (ext2fs_swap_super): Byte-swap the hash seed + 2001-09-24 Theodore Tso * Release of E2fsprogs 1.29 diff --git a/lib/ext2fs/rw_bitmaps.c b/lib/ext2fs/rw_bitmaps.c index 89557db..4d47da4 100644 --- a/lib/ext2fs/rw_bitmaps.c +++ b/lib/ext2fs/rw_bitmaps.c @@ -41,7 +41,7 @@ #endif #ifdef EXT2_BIG_ENDIAN_BITMAPS -void ext2fs_swap_bitmap(ext2_filsys fs, char *bitmap, int nbytes) +static void ext2fs_swap_bitmap(ext2_filsys fs, char *bitmap, int nbytes) { __u32 *p = (__u32 *) bitmap; int n; @@ -88,7 +88,6 @@ errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs) } inode_bitmap += nbytes; } - fs->flags |= EXT2_FLAG_CHANGED; fs->flags &= ~EXT2_FLAG_IB_DIRTY; ext2fs_free_mem((void **) &bitmap_block); return 0; @@ -141,7 +140,6 @@ errcode_t ext2fs_write_block_bitmap (ext2_filsys fs) } block_bitmap += nbytes; } - fs->flags |= EXT2_FLAG_CHANGED; fs->flags &= ~EXT2_FLAG_BB_DIRTY; ext2fs_free_mem((void **) &bitmap_block); return 0; diff --git a/lib/ext2fs/swapfs.c b/lib/ext2fs/swapfs.c index f50a795..14165cb 100644 --- a/lib/ext2fs/swapfs.c +++ b/lib/ext2fs/swapfs.c @@ -1,7 +1,7 @@ /* * swapfs.c --- swap ext2 filesystem data structures * - * Copyright (C) 1995, 1996 Theodore Ts'o. + * Copyright (C) 1995, 1996, 2002 Theodore Ts'o. * * %Begin-Header% * This file may be redistributed under the terms of the GNU Public @@ -21,6 +21,7 @@ #ifdef EXT2FS_ENABLE_SWAPFS void ext2fs_swap_super(struct ext2_super_block * sb) { + int i; sb->s_inodes_count = ext2fs_swab32(sb->s_inodes_count); sb->s_blocks_count = ext2fs_swab32(sb->s_blocks_count); sb->s_r_blocks_count = ext2fs_swab32(sb->s_r_blocks_count); @@ -56,6 +57,8 @@ void ext2fs_swap_super(struct ext2_super_block * sb) 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); + for (i=0; i < 4; i++) + sb->s_hash_seed[i] = ext2fs_swab32(sb->s_hash_seed[i]); } void ext2fs_swap_group_desc(struct ext2_group_desc *gdp)