From dc8ce3463791366ac844d3f0436709511fa09c49 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Thu, 6 Jan 2005 00:04:24 -0500 Subject: [PATCH] Fix resize inode handling on big endian systems, by adding new routines that read/write indirect blocks, byte swapping them if necessary. --- e2fsck/ChangeLog | 5 +++ e2fsck/super.c | 4 +- lib/ext2fs/ChangeLog | 13 +++++++ lib/ext2fs/Makefile.in | 2 + lib/ext2fs/block.c | 99 +++++++++----------------------------------------- lib/ext2fs/ext2fs.h | 4 ++ lib/ext2fs/ind_block.c | 66 +++++++++++++++++++++++++++++++++ lib/ext2fs/res_gdt.c | 8 ++-- 8 files changed, 114 insertions(+), 87 deletions(-) create mode 100644 lib/ext2fs/ind_block.c diff --git a/e2fsck/ChangeLog b/e2fsck/ChangeLog index b843459..25a6780 100644 --- a/e2fsck/ChangeLog +++ b/e2fsck/ChangeLog @@ -1,3 +1,8 @@ +2005-01-06 Theodore Ts'o + + * super.c (check_resize_inode): Use ext2fs_{read,write}_ind_block + so that byte swapping is handled on big-endian systems. + 2004-12-24 Theodore Ts'o * pass1.c (e2fsck_pass1): At the end of the pass 1 processing, if diff --git a/e2fsck/super.c b/e2fsck/super.c index 71968ea..ef799f9 100644 --- a/e2fsck/super.c +++ b/e2fsck/super.c @@ -392,7 +392,7 @@ void check_resize_inode(e2fsck_t ctx) "resize dind buffer"); ind_buf = (__u32 *) ((char *) dind_buf + fs->blocksize); - retval = io_channel_read_blk(fs->io, blk, 1, dind_buf); + retval = ext2fs_read_ind_block(fs, blk, dind_buf); if (retval) goto resize_inode_invalid; @@ -403,7 +403,7 @@ void check_resize_inode(e2fsck_t ctx) gdt_off %= fs->blocksize/4; if (dind_buf[gdt_off] != pblk) goto resize_inode_invalid; - retval = io_channel_read_blk(fs->io, pblk, 1, ind_buf); + retval = ext2fs_read_ind_block(fs, pblk, ind_buf); if (retval) goto resize_inode_invalid; ind_off = 0; diff --git a/lib/ext2fs/ChangeLog b/lib/ext2fs/ChangeLog index 048bb4f..1eb5ed5 100644 --- a/lib/ext2fs/ChangeLog +++ b/lib/ext2fs/ChangeLog @@ -1,5 +1,18 @@ 2005-01-05 Theodore Ts'o + * block.c (block_iterate_ind, block_iterate_dind, + block_iterate_tind): Move the code which byte swaps and + read/writes indirect blocks to ext2fs_{read,write}_ind_block. + This saves 400 bytes, and we need them for the + resize_inode handling. + + * ind_block.c (ext2fs_read_ind_block, ext2fs_write_ind_block): New + functions. + + * res_gdt.c (ext2fs_create_resize_inode): Use + ext2fs_{read,write}_ind_block so that byte swapping is + handled on big-endian systems. + * dupfs.c (ext2fs_dup_handle): Make sure the new filesystem handle has its own copy of the orig_super data structure. (This is a better way of fixing a double-free problem in diff --git a/lib/ext2fs/Makefile.in b/lib/ext2fs/Makefile.in index 5929c70..931e9b0 100644 --- a/lib/ext2fs/Makefile.in +++ b/lib/ext2fs/Makefile.in @@ -43,6 +43,7 @@ OBJS= $(DEBUGFS_LIB_OBJS) $(RESIZE_LIB_OBJS) $(E2IMAGE_LIB_OBJS) \ getsize.o \ getsectsize.o \ icount.o \ + ind_block.o \ initialize.o \ inline.o \ inode.o \ @@ -98,6 +99,7 @@ SRCS= ext2_err.c \ $(srcdir)/getsize.c \ $(srcdir)/getsectsize.c \ $(srcdir)/icount.c \ + $(srcdir)/ind_block.c \ $(srcdir)/initialize.c \ $(srcdir)/inline.c \ $(srcdir)/inode.c \ diff --git a/lib/ext2fs/block.c b/lib/ext2fs/block.c index 88ce286..7685680 100644 --- a/lib/ext2fs/block.c +++ b/lib/ext2fs/block.c @@ -59,25 +59,13 @@ static int block_iterate_ind(blk_t *ind_block, blk_t ref_block, ret |= BLOCK_ERROR; return ret; } - if ((ctx->fs->flags & EXT2_FLAG_IMAGE_FILE) && - (ctx->fs->io != ctx->fs->image_io)) { - ctx->errcode = 0; - memset(ctx->ind_buf, 0, ctx->fs->blocksize); - } else - ctx->errcode = io_channel_read_blk(ctx->fs->io, *ind_block, - 1, ctx->ind_buf); + ctx->errcode = ext2fs_read_ind_block(ctx->fs, *ind_block, + ctx->ind_buf); if (ctx->errcode) { ret |= BLOCK_ERROR; return ret; } -#ifdef EXT2FS_ENABLE_SWAPFS - if (ctx->fs->flags & (EXT2_FLAG_SWAP_BYTES | - EXT2_FLAG_SWAP_BYTES_READ)) { - block_nr = (blk_t *) ctx->ind_buf; - for (i = 0; i < limit; i++, block_nr++) - *block_nr = ext2fs_swab32(*block_nr); - } -#endif + block_nr = (blk_t *) ctx->ind_buf; offset = 0; if (ctx->flags & BLOCK_FLAG_APPEND) { @@ -107,18 +95,9 @@ static int block_iterate_ind(blk_t *ind_block, blk_t ref_block, offset += sizeof(blk_t); } } - if (!(ctx->fs->flags & EXT2_FLAG_IMAGE_FILE) && - (changed & BLOCK_CHANGED)) { -#ifdef EXT2FS_ENABLE_SWAPFS - if (ctx->fs->flags & (EXT2_FLAG_SWAP_BYTES | - EXT2_FLAG_SWAP_BYTES_WRITE)) { - block_nr = (blk_t *) ctx->ind_buf; - for (i = 0; i < limit; i++, block_nr++) - *block_nr = ext2fs_swab32(*block_nr); - } -#endif - ctx->errcode = io_channel_write_blk(ctx->fs->io, *ind_block, - 1, ctx->ind_buf); + if (changed & BLOCK_CHANGED) { + ctx->errcode = ext2fs_write_ind_block(ctx->fs, *ind_block, + ctx->ind_buf); if (ctx->errcode) ret |= BLOCK_ERROR | BLOCK_ABORT; } @@ -154,25 +133,13 @@ static int block_iterate_dind(blk_t *dind_block, blk_t ref_block, ret |= BLOCK_ERROR; return ret; } - if ((ctx->fs->flags & EXT2_FLAG_IMAGE_FILE) && - (ctx->fs->io != ctx->fs->image_io)) { - ctx->errcode = 0; - memset(ctx->dind_buf, 0, ctx->fs->blocksize); - } else - ctx->errcode = io_channel_read_blk(ctx->fs->io, *dind_block, - 1, ctx->dind_buf); + ctx->errcode = ext2fs_read_ind_block(ctx->fs, *dind_block, + ctx->dind_buf); if (ctx->errcode) { ret |= BLOCK_ERROR; return ret; } -#ifdef EXT2FS_ENABLE_SWAPFS - if (ctx->fs->flags & (EXT2_FLAG_SWAP_BYTES | - EXT2_FLAG_SWAP_BYTES_READ)) { - block_nr = (blk_t *) ctx->dind_buf; - for (i = 0; i < limit; i++, block_nr++) - *block_nr = ext2fs_swab32(*block_nr); - } -#endif + block_nr = (blk_t *) ctx->dind_buf; offset = 0; if (ctx->flags & BLOCK_FLAG_APPEND) { @@ -204,18 +171,9 @@ static int block_iterate_dind(blk_t *dind_block, blk_t ref_block, offset += sizeof(blk_t); } } - if (!(ctx->fs->flags & EXT2_FLAG_IMAGE_FILE) && - (changed & BLOCK_CHANGED)) { -#ifdef EXT2FS_ENABLE_SWAPFS - if (ctx->fs->flags & (EXT2_FLAG_SWAP_BYTES | - EXT2_FLAG_SWAP_BYTES_WRITE)) { - block_nr = (blk_t *) ctx->dind_buf; - for (i = 0; i < limit; i++, block_nr++) - *block_nr = ext2fs_swab32(*block_nr); - } -#endif - ctx->errcode = io_channel_write_blk(ctx->fs->io, *dind_block, - 1, ctx->dind_buf); + if (changed & BLOCK_CHANGED) { + ctx->errcode = ext2fs_write_ind_block(ctx->fs, *dind_block, + ctx->dind_buf); if (ctx->errcode) ret |= BLOCK_ERROR | BLOCK_ABORT; } @@ -251,25 +209,13 @@ static int block_iterate_tind(blk_t *tind_block, blk_t ref_block, ret |= BLOCK_ERROR; return ret; } - if ((ctx->fs->flags & EXT2_FLAG_IMAGE_FILE) && - (ctx->fs->io != ctx->fs->image_io)) { - ctx->errcode = 0; - memset(ctx->tind_buf, 0, ctx->fs->blocksize); - } else - ctx->errcode = io_channel_read_blk(ctx->fs->io, *tind_block, - 1, ctx->tind_buf); + ctx->errcode = ext2fs_read_ind_block(ctx->fs, *tind_block, + ctx->tind_buf); if (ctx->errcode) { ret |= BLOCK_ERROR; return ret; } -#ifdef EXT2FS_ENABLE_SWAPFS - if (ctx->fs->flags & (EXT2_FLAG_SWAP_BYTES | - EXT2_FLAG_SWAP_BYTES_READ)) { - block_nr = (blk_t *) ctx->tind_buf; - for (i = 0; i < limit; i++, block_nr++) - *block_nr = ext2fs_swab32(*block_nr); - } -#endif + block_nr = (blk_t *) ctx->tind_buf; offset = 0; if (ctx->flags & BLOCK_FLAG_APPEND) { @@ -301,18 +247,9 @@ static int block_iterate_tind(blk_t *tind_block, blk_t ref_block, offset += sizeof(blk_t); } } - if (!(ctx->fs->flags & EXT2_FLAG_IMAGE_FILE) && - (changed & BLOCK_CHANGED)) { -#ifdef EXT2FS_ENABLE_SWAPFS - if (ctx->fs->flags & (EXT2_FLAG_SWAP_BYTES | - EXT2_FLAG_SWAP_BYTES_WRITE)) { - block_nr = (blk_t *) ctx->tind_buf; - for (i = 0; i < limit; i++, block_nr++) - *block_nr = ext2fs_swab32(*block_nr); - } -#endif - ctx->errcode = io_channel_write_blk(ctx->fs->io, *tind_block, - 1, ctx->tind_buf); + if (changed & BLOCK_CHANGED) { + ctx->errcode = ext2fs_write_ind_block(ctx->fs, *tind_block, + ctx->tind_buf); if (ctx->errcode) ret |= BLOCK_ERROR | BLOCK_ABORT; } diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h index 55bc547..1b7e1b0 100644 --- a/lib/ext2fs/ext2fs.h +++ b/lib/ext2fs/ext2fs.h @@ -757,6 +757,10 @@ extern errcode_t ext2fs_image_super_read(ext2_filsys fs, int fd, int flags); extern errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags); extern errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags); +/* 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); + /* initialize.c */ extern errcode_t ext2fs_initialize(const char *name, int flags, struct ext2_super_block *param, diff --git a/lib/ext2fs/ind_block.c b/lib/ext2fs/ind_block.c new file mode 100644 index 0000000..9f77a07 --- /dev/null +++ b/lib/ext2fs/ind_block.c @@ -0,0 +1,66 @@ +/* + * ind_block.c --- indirect block I/O routines + * + * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, + * 2001, 2002, 2003, 2004, 2005 by Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +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)) + memset(buf, 0, fs->blocksize); + else { + retval = io_channel_read_blk(fs->io, blk, 1, buf); + if (retval) + retval; + } +#ifdef EXT2FS_ENABLE_SWAPFS + if (fs->flags & (EXT2_FLAG_SWAP_BYTES | EXT2_FLAG_SWAP_BYTES_READ)) { + block_nr = (blk_t *) buf; + for (i = 0; i < limit; i++, block_nr++) + *block_nr = ext2fs_swab32(*block_nr); + } +#endif + return 0; +} + +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; + for (i = 0; i < limit; i++, block_nr++) + *block_nr = ext2fs_swab32(*block_nr); + } +#endif + return io_channel_write_blk(fs->io, blk, 1, buf); +} + + diff --git a/lib/ext2fs/res_gdt.c b/lib/ext2fs/res_gdt.c index 4706589..1fdb1d4 100644 --- a/lib/ext2fs/res_gdt.c +++ b/lib/ext2fs/res_gdt.c @@ -91,7 +91,7 @@ errcode_t ext2fs_create_resize_inode(ext2_filsys fs) #ifdef RES_GDT_DEBUG printf("reading GDT dindir %u\n", dindir_blk); #endif - retval = io_channel_read_blk(fs->io, dindir_blk, 1, dindir_buf); + retval = ext2fs_read_ind_block(fs, dindir_blk, dindir_buf); if (retval) goto out_inode; } else { @@ -154,7 +154,7 @@ errcode_t ext2fs_create_resize_inode(ext2_filsys fs) #ifdef RES_GDT_DEBUG printf("reading primary GDT block %u\n", gdt_blk); #endif - retval = io_channel_read_blk(fs->io,gdt_blk,1,gdt_buf); + retval = ext2fs_read_ind_block(fs, gdt_blk, gdt_buf); if (retval) goto out_dindir; } else { @@ -192,7 +192,7 @@ errcode_t ext2fs_create_resize_inode(ext2_filsys fs) #ifdef RES_GDT_DEBUG printf("writing primary GDT block %u\n", gdt_blk); #endif - retval = io_channel_write_blk(fs->io,gdt_blk,1,gdt_buf); + retval = ext2fs_write_ind_block(fs, gdt_blk, gdt_buf); if (retval) goto out_dindir; } @@ -200,7 +200,7 @@ errcode_t ext2fs_create_resize_inode(ext2_filsys fs) out_dindir: if (dindir_dirty) { - retval2 = io_channel_write_blk(fs->io, dindir_blk,1,dindir_buf); + retval2 = ext2fs_write_ind_block(fs, dindir_blk, dindir_buf); if (!retval) retval = retval2; } -- 1.8.3.1