[ext2resize] [PATCH] large inode support
Status: Inactive
Brought to you by:
adilger
From: Andreas D. <ad...@cl...> - 2006-06-10 18:36:36
|
This patch adds handling for large inodes to resizing. It uses a buffer large enough for the maximum inode size for the few places we read inodes, and reads and writes the full inode size instead of just the main body. Patch is untested. Suggested method for testing: - create small new filesystem with large inodes (-I 256) - mount with newer kernel (at least 2.6.10) - create new files in root dir, add EA with setfattr - unmount - verify with debugfs -R "stat <inum>" that EA is in inode - resize or prepare filesystem to add new group block - verify with debugfs -R "stat <inum>" that EA was moved with inode (or mount and use getfattr) ============================================================================ diff -u -p -r1.34 ext2.c --- src/ext2.c 10 Jun 2006 07:45:55 -0000 1.34 +++ src/ext2.c 10 Jun 2006 18:07:21 -0000 @@ -220,9 +220,7 @@ off_t ext2_get_inode_offset(struct ext2_ inode--; group = inode / fs->sb.s_inodes_per_group; - offset = (inode % fs->sb.s_inodes_per_group) * - (fs->sb.s_rev_level == EXT2_GOOD_OLD_REV ? - EXT2_GOOD_OLD_INODE_SIZE : fs->sb.s_inode_size); + offset = (inode % fs->sb.s_inodes_per_group) * fs->inode_size; *block = fs->gd[group].bg_inode_table + (offset >> fs->logsize); @@ -256,7 +254,7 @@ void ext2_read_inode(struct ext2_fs *fs, off = ext2_get_inode_offset(fs, ino, &blk); bh = ext2_bread(fs, blk); - memcpy(inode, bh->data + off, sizeof(struct ext2_inode)); + memcpy(inode, bh->data + off, fs->inode_size); ext2_brelse(bh, 0); } @@ -454,21 +454,21 @@ void ext2_write_inode(struct ext2_fs *fs if (fs->flags & FL_ONLINE) { fs->devhandle->ops->direct_write(fs->devhandle->cookie, (const void *)inode, (loff_t)blk * fs->blocksize + off, - sizeof(struct ext2_inode)); + fs->inode_size); } else { bh = ext2_bread(fs, blk); bh->dirty = 1; - memcpy(bh->data + off, inode, sizeof(struct ext2_inode)); + memcpy(bh->data + off, inode, fs->inode_size); ext2_brelse(bh, 0); } } void ext2_zero_inode(struct ext2_fs *fs, ino_t ino) { - struct ext2_inode inode; + char inode_buf[EXT2_MAX_BLOCK_SIZE]; - memset(&inode, 0, sizeof(struct ext2_inode)); - ext2_write_inode(fs, ino, &inode); + memset(inode_buf, 0, fs->inode_size); + ext2_write_inode(fs, ino, (void *)inode_buf); } unsigned int ext2_list_backups(struct ext2_fs *fs, unsigned int *three, @@ -860,7 +860,8 @@ struct ext2_fs *ext2_open(struct ext2_de int flags) { struct ext2_fs *fs; - struct ext2_inode inode; + char inode_buf[EXT2_MAX_BLOCK_SIZE]; + struct ext2_inode *inode = (void *)inode_buf; int maxgroups; blk_t devsize; blk_t residue; @@ -942,6 +943,19 @@ struct ext2_fs *ext2_open(struct ext2_de fs->blocksize = 1 << fs->logsize; fs->u32perblock = fs->blocksize >> 2; + if (fs->sb.s_rev_level > EXT2_GOOD_OLD_REV) { + fs->inode_size = fs->sb.s_inode_size; + if (fs->inode_size < EXT2_GOOD_OLD_INODE_SIZE || + fs->inode_size & (fs->inode_size - 1) || + fs->inode_size > fs->blocksize) { + fprintf(stderr, "superblock inode size %u is invalid\n", + fs->inode_size); + goto error_free_fs; + } + } else { + fs->inode_size = EXT2_GOOD_OLD_INODE_SIZE; + } + devsize = handle->ops->get_size(fs->devhandle->cookie); if (newblocks == 0) newblocks = devsize; @@ -956,8 +970,8 @@ struct ext2_fs *ext2_open(struct ext2_de fs->sb.s_blocks_per_group); fs->gdblocks = howmany(fs->numgroups * sizeof(struct ext2_group_desc), fs->blocksize); - fs->inodeblocks = howmany(fs->sb.s_inodes_per_group * - sizeof(struct ext2_inode), fs->blocksize); + fs->inodeblocks = howmany(fs->sb.s_inodes_per_group * fs->inode_size, + fs->blocksize); fs->r_frac = howmany(100 * (loff_t)fs->sb.s_r_blocks_count, fs->sb.s_blocks_count); @@ -1011,8 +1025,8 @@ struct ext2_fs *ext2_open(struct ext2_de if (!ext2_determine_itoffset(fs)) goto error_free_gd; - ext2_read_inode(fs, EXT2_BAD_INO, &inode); - if (inode.i_blocks > 0) { + ext2_read_inode(fs, EXT2_BAD_INO, inode); + if (inode->i_blocks > 0) { fprintf(stderr, "%s: ext2_open: Can't handle fs with bad blocks!!\n" "Contact <ext...@li...> to " @@ -1021,8 +1035,8 @@ struct ext2_fs *ext2_open(struct ext2_de } /* Bring in Mr. Bond */ - ext2_read_inode(fs, EXT2_RESIZE_INO, &inode); - fs->resgdblocks = ext2_get_reserved(fs, &inode); + ext2_read_inode(fs, EXT2_RESIZE_INO, inode); + fs->resgdblocks = ext2_get_reserved(fs, inode); #if 0 ext2_journal_init(fs); diff -u -p -r1.28 ext2.h --- src/ext2.h 10 Jun 2006 07:45:55 -0000 1.28 +++ src/ext2.h 10 Jun 2006 18:07:21 -0000 @@ -115,6 +115,7 @@ struct ext2_fs int flags; /* See FL_* defines */ int blocksize; + int inode_size; /* inode size in bytes */ int u32perblock; /* #blocks per indirect block */ int logsize; /* base 2 log of blocksize */ blk_t newblocks; /* blocks in resized fs */ diff -u -p -r1.22 ext2_block_relocator.c --- src/ext2_block_relocator.c 10 Jun 2006 07:45:55 -0000 1.22 +++ src/ext2_block_relocator.c 10 Jun 2006 18:07:21 -0000 @@ -249,8 +249,8 @@ static int dotindblock(struct ext2_fs *f static int doinode(struct ext2_fs *fs, struct ext2_block_relocator_state *state, ino_t ino) { - struct ext2_inode tmp; - struct ext2_inode *inode = &tmp; + char inode_buf[EXT2_MAX_BLOCK_SIZE]; + struct ext2_inode *inode = (void *)inode_buf; ext2_read_inode(fs, ino, inode); @@ -628,8 +634,8 @@ static int ext2_block_relocator_mark(str static int ext2_block_relocate_grow(struct ext2_fs *fs, struct ext2_block_relocator_state *state) { - struct ext2_inode tmp; - struct ext2_inode *inode = &tmp; + char inode_buf[EXT2_MAX_BLOCK_SIZE]; + struct ext2_inode *inode = (void *)inode_buf; int newitoffset; blk_t start; int group; @@ -793,8 +799,8 @@ static int ext2_block_relocate_grow(stru static int ext2_block_relocate_shrink(struct ext2_fs *fs, struct ext2_block_relocator_state *state) { - struct ext2_inode tmp; - struct ext2_inode *inode = &tmp; + char inode_buf[EXT2_MAX_BLOCK_SIZE]; + struct ext2_inode *inode = (void *)inode_buf; int group; blk_t start; diff -u -p -r1.8 ext2_fs.h --- src/ext2_fs.h 3 Jul 2002 17:52:24 -0000 1.8 +++ src/ext2_fs.h 10 Jun 2006 18:07:21 -0000 @@ -75,7 +75,7 @@ * Macro-instructions used to manage several block sizes */ #define EXT2_MIN_BLOCK_LOG_SIZE 10 /* 1024 */ -#define EXT2_MAX_BLOCK_LOG_SIZE 13 /* 8192 */ +#define EXT2_MAX_BLOCK_LOG_SIZE 16 /* 8192 */ #define EXT2_MIN_BLOCK_SIZE (1 << EXT2_MIN_BLOCK_LOG_SIZE) #define EXT2_MAX_BLOCK_SIZE (1 << EXT2_MAX_BLOCK_LOG_SIZE) #ifdef __KERNEL__ diff -u -p -r1.18 ext2_inode_relocator.c --- src/ext2_inode_relocator.c 10 Jun 2006 07:45:55 -0000 1.18 +++ src/ext2_inode_relocator.c 10 Jun 2006 18:07:21 -0000 @@ -208,11 +208,10 @@ static int dotindblock(struct ext2_fs *f static int doinode(struct ext2_fs *fs, struct ext2_inode_relocator_state *state, ino_t ino) { - struct ext2_inode tmp; - struct ext2_inode *inode = &tmp; + char inode_buf[EXT2_MAX_BLOCK_SIZE]; + struct ext2_inode *inode = (void *)inode_buf; int i; - ext2_read_inode(fs, ino, inode); if (S_ISDIR(inode->i_mode)) { @@ -306,7 +309,8 @@ static void ext2_inode_relocator_copy(st int i; for (i = 0; i < state->used_entries; i++) { - struct ext2_inode inode; + char inode_buf[EXT2_MAX_BLOCK_SIZE]; + struct ext2_inode *inode = (void *)inode_buf; struct ext2_inode_entry *entry; entry = &state->inode[i]; @@ -315,10 +319,10 @@ static void ext2_inode_relocator_copy(st ext2_get_inode_state(fs, entry->dest)) fprintf(stderr, "inode bitmap error\n"); - ext2_read_inode(fs, entry->ino, &inode); - ext2_write_inode(fs, entry->dest, &inode); + ext2_read_inode(fs, entry->ino, inode); + ext2_write_inode(fs, entry->dest, inode); - entry->isdir = S_ISDIR(inode.i_mode) ? 1 : 0; + entry->isdir = S_ISDIR(inode->i_mode) ? 1 : 0; } if (fs->flags & FL_SAFE) @@ -472,21 +476,22 @@ static int ext2_inode_relocator_mark(str struct ext2_inode_relocator_state *state, ino_t ino) { - struct ext2_inode inode; + char inode_buf[EXT2_MAX_BLOCK_SIZE]; + struct ext2_inode *inode = (void *)inode_buf; struct ext2_inode_entry *ent; void *adv; void *rec; int i; - ext2_read_inode(fs, ino, &inode); + ext2_read_inode(fs, ino, inode); adv = state->inode + state->used_entries + 1; - rec = state->last - inode.i_links_count; + rec = state->last - inode->i_links_count; if (adv >= rec) ext2_inode_relocator_flush(fs, state); - state->last -= inode.i_links_count; + state->last -= inode->i_links_count; ent = &state->inode[state->used_entries]; ent->ino = ino; diff -u -p -r1.11 ext2_journal.c --- src/ext2_journal.c 10 Oct 2000 18:34:33 -0000 1.11 +++ src/ext2_journal.c 10 Jun 2006 18:07:21 -0000 @@ -50,7 +50,8 @@ struct ext2_journal static int create_journal_inode(struct ext2_fs *fs, struct ext2_journal *j) { - struct ext2_inode inode; + char inode_buf[EXT2_MAX_BLOCK_SIZE]; + struct ext2_inode *inode = (void *)inode_buf; ino_t inodenum; if (!fs->sb.s_free_inodes_count) { @@ -60,21 +61,21 @@ static int create_journal_inode(struct e inodenum = ext2_find_free_inode(fs); - memset(&inode, 0, sizeof(inode)); - inode.i_mode = 0100400; - inode.i_size = 4 << fs->logsize; - inode.i_atime = JOURNAL_SIG0; - inode.i_ctime = JOURNAL_SIG1; - inode.i_mtime = JOURNAL_SIG2; - inode.i_dtime = JOURNAL_SIG3; - inode.i_links_count = 1; - inode.i_blocks = 8 << fs->logsize; - inode.i_block[0] = j->block[0]; - inode.i_block[1] = j->block[1]; - inode.i_block[2] = j->block[2]; - inode.i_block[3] = j->block[3]; + memset(inode, 0, fs->inode_size); + inode->i_mode = 0100400; + inode->i_size = 4 << fs->logsize; + inode->i_atime = JOURNAL_SIG0; + inode->i_ctime = JOURNAL_SIG1; + inode->i_mtime = JOURNAL_SIG2; + inode->i_dtime = JOURNAL_SIG3; + inode->i_links_count = 1; + inode->i_blocks = 8 << fs->logsize; + inode->i_block[0] = j->block[0]; + inode->i_block[1] = j->block[1]; + inode->i_block[2] = j->block[2]; + inode->i_block[3] = j->block[3]; - ext2_write_inode(fs, inodenum, &inode); + ext2_write_inode(fs, inodenum, inode); ext2_set_inode_state(fs, inodenum, 1, 1); return 1; @@ -85,13 +86,14 @@ static ino_t find_journal_inode(struct e ino_t i; for (i = 1; i < fs->sb.s_inodes_count; i++) { - struct ext2_inode inode; + char inode_buf[EXT2_MAX_BLOCK_SIZE]; + struct ext2_inode *inode = (void *)inode_buf; - ext2_read_inode(fs, i, &inode); - if (inode.i_atime == JOURNAL_SIG0 && - inode.i_ctime == JOURNAL_SIG1 && - inode.i_mtime == JOURNAL_SIG2) { - if (inode.i_dtime != JOURNAL_SIG3) + ext2_read_inode(fs, i, inode); + if (inode->i_atime == JOURNAL_SIG0 && + inode->i_ctime == JOURNAL_SIG1 && + inode->i_mtime == JOURNAL_SIG2) { + if (inode->i_dtime != JOURNAL_SIG3) fprintf(stderr, "you ran e2fsck after ext2resize crashed? Hm.\n"); diff -u -p -r1.10 ext2_mkfs.c --- src/ext2_mkfs.c 4 Sep 2001 18:13:49 -0000 1.10 +++ src/ext2_mkfs.c 10 Jun 2006 18:07:21 -0000 @@ -115,9 +115,12 @@ void ext2_mkfs_write_meta(struct ext2_de blocksize = 1 << (sb->s_log_block_size + 13); - numgroups = howmany(sb->s_blocks_count - sb->s_first_data_block, sb->s_blocks_per_group); - itsize = howmany(sizeof(struct ext2_inode) * sb->s_inodes_per_group, (1024 << sb->s_log_block_size)); - gdtsize = howmany(sizeof(struct ext2_group_desc) * numgroups, (1024 << sb->s_log_block_size)); + numgroups = howmany(sb->s_blocks_count - sb->s_first_data_block, + sb->s_blocks_per_group); + itsize = howmany(sb->s_inode_size * sb->s_inodes_per_group, + (1024 << sb->s_log_block_size)); + gdtsize = howmany(sizeof(struct ext2_group_desc) * numgroups, + (1024 << sb->s_log_block_size)); bb = malloc(1024 << sb->s_log_block_size); ib = malloc(1024 << sb->s_log_block_size); @@ -199,7 +202,8 @@ int ext2_mkfs_create_lost_and_found_inod blk_t blocks[12]; __u32 data[fs->blocksize / 4]; int i; - struct ext2_inode inode; + char inode_buf[EXT2_MAX_BLOCK_SIZE]; + struct ext2_inode *inode = (void *)inode_buf; for (i = 0; i < EXT2_NDIR_BLOCKS; i++) { if (!(blocks[i] = ext2_find_free_block(fs))) @@ -230,16 +234,16 @@ int ext2_mkfs_create_lost_and_found_inod ext2_brelse(bh, 1); } - memset(&inode, 0, sizeof(struct ext2_inode)); - inode.i_mode = S_IFDIR | 0755; - inode.i_size = EXT2_NDIR_BLOCKS * fs->blocksize; - inode.i_atime = inode.i_ctime = inode.i_mtime = time(NULL); - inode.i_links_count = 2; - inode.i_blocks = (EXT2_NDIR_BLOCKS * fs->blocksize) >> 9; + memset(inode, 0, fs->inode_size); + inode->i_mode = S_IFDIR | 0755; + inode->i_size = EXT2_NDIR_BLOCKS * fs->blocksize; + inode->i_atime = inode->i_ctime = inode->i_mtime = time(NULL); + inode->i_links_count = 2; + inode->i_blocks = (EXT2_NDIR_BLOCKS * fs->blocksize) >> 9; for (i = 0; i < EXT2_NDIR_BLOCKS; i++) - inode.i_block[i] = blocks[i]; + inode->i_block[i] = blocks[i]; - ext2_write_inode(fs, EXT2_GOOD_OLD_FIRST_INO, &inode); + ext2_write_inode(fs, EXT2_GOOD_OLD_FIRST_INO, inode); ext2_set_inode_state(fs, EXT2_GOOD_OLD_FIRST_INO, 1, 1); fs->gd[0].bg_used_dirs_count++; fs->metadirty |= EXT2_META_GD; @@ -252,7 +256,8 @@ int ext2_mkfs_create_root_inode(struct e struct ext2_buffer_head *bh; blk_t block; __u32 data[fs->blocksize / 4]; - struct ext2_inode inode; + char inode_buf[EXT2_MAX_BLOCK_SIZE]; + struct ext2_inode *inode = (void *)inode_buf; if (!(block = ext2_find_free_block(fs))) return 0; @@ -275,15 +280,15 @@ int ext2_mkfs_create_root_inode(struct e bh->dirty = 1; ext2_brelse(bh, 1); - memset(&inode, 0, sizeof(struct ext2_inode)); - inode.i_mode = S_IFDIR | 0755; - inode.i_size = fs->blocksize; - inode.i_atime = inode.i_ctime = inode.i_mtime = time(NULL); - inode.i_links_count = 3; - inode.i_blocks = fs->blocksize >> 9; - inode.i_block[0] = block; + memset(inode, 0, fs->inode_size); + inode->i_mode = S_IFDIR | 0755; + inode->i_size = fs->blocksize; + inode->i_atime = inode->i_ctime = inode->i_mtime = time(NULL); + inode->i_links_count = 3; + inode->i_blocks = fs->blocksize >> 9; + inode->i_block[0] = block; - ext2_write_inode(fs, 2, &inode); + ext2_write_inode(fs, 2, inode); fs->gd[0].bg_used_dirs_count++; fs->metadirty |= EXT2_META_GD; @@ -370,11 +375,11 @@ struct ext2_fs *ext2_mkfs(struct ext2_de sb.s_lastcheck = 0; sb.s_checkinterval = 0; sb.s_creator_os = 0; - sb.s_rev_level = 0; + sb.s_rev_level = EXT2_DYNAMIC_REV; sb.s_def_resuid = 0; sb.s_def_resgid = 0; sb.s_first_ino = 12; - sb.s_inode_size = 128; + sb.s_inode_size = EXT2_GOOD_OLD_INODE_SIZE; sb.s_block_group_nr = 0; sb.s_feature_compat = 0; sb.s_feature_incompat = 0; Index: src/ext2_resize.c =================================================================== RCS file: /cvsroot/ext2resize/ext2resize/src/ext2_resize.c,v retrieving revision 1.19 diff -u -p -r1.19 ext2_resize.c --- src/ext2_resize.c 10 Jun 2006 06:45:22 -0000 1.19 +++ src/ext2_resize.c 10 Jun 2006 18:07:21 -0000 @@ -28,8 +28,8 @@ static const char _ext2_resize_c[] = "$I static int ext2_add_group(struct ext2_fs *fs, blk_t bpg) { - struct ext2_inode tmp; - struct ext2_inode *inode = &tmp; + char inode_buf[EXT2_MAX_BLOCK_SIZE]; + struct ext2_inode *inode = (void *)inode_buf; blk_t admin; int group = fs->numgroups; blk_t start; @@ -225,8 +225,8 @@ static int ext2_del_group(struct ext2_fs sizeof(struct ext2_group_desc), fs->blocksize); if (new_gdblocks != fs->gdblocks) { - struct ext2_inode tmp; - struct ext2_inode *inode = &tmp; + char inode_buf[EXT2_MAX_BLOCK_SIZE]; + struct ext2_inode *inode = (void *)inode_buf; blk_t start; ext2_read_inode(fs, EXT2_RESIZE_INO, inode); diff -u -p -r1.21 ext2prepare.c --- src/ext2prepare.c 10 Jun 2006 07:15:24 -0000 1.21 +++ src/ext2prepare.c 10 Jun 2006 18:07:21 -0000 @@ -129,8 +129,8 @@ static int check_inode_ind(struct ext2_f static int create_resize_inode(struct ext2_fs *fs) { - struct ext2_inode tmp; - struct ext2_inode *inode = &tmp; + char inode_buf[EXT2_MAX_BLOCK_SIZE]; + struct ext2_inode *inode = (void *)inode_buf; int diff; int i; blk_t block; @@ -143,7 +143,7 @@ static int create_resize_inode(struct ex if (fs->flags & FL_VERBOSE) printf("creating resize inode (%03d)\n", EXT2_RESIZE_INO); - memset(inode, 0, sizeof(struct ext2_inode)); + memset(inode, 0, fs->inode_size); inode->i_mode = S_IFREG | S_IRUSR | S_IWUSR; inode->i_ctime = time(NULL); inode->i_links_count = 1; Cheers, Andreas -- Andreas Dilger Principal Software Engineer Cluster File Systems, Inc. |