From 5d17119d14fe1276936c85d7986695a4543b1aa1 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 11 Nov 2006 06:32:03 -0500 Subject: [PATCH] On-disk format definition for huge files - EXT4_FEATURE_RO_COMPAT_HUGE_FILE (0x0008) - change i_blocks to be in units of s_blocksize units instead of 512-byte sectors, use l_i_frag and l_i_fsize as i_blocks_hi (could also be part of 64BIT). E2fsck and debugfs changed to support i_blocks_hi instead of l_i_frag and l_i_fsize. Signed-off-by: "Theodore Ts'o" --- debugfs/debugfs.c | 26 +++++++++++++------------ debugfs/set_fields.c | 5 +++-- e2fsck/ChangeLog | 8 ++++++++ e2fsck/pass1.c | 9 +++++---- e2fsck/pass2.c | 15 ++++++++++---- e2fsck/problem.c | 5 +++++ e2fsck/problem.h | 3 +++ lib/ext2fs/ChangeLog | 9 +++++++++ lib/ext2fs/ext2_fs.h | 7 +++---- lib/ext2fs/swapfs.c | 4 ++-- tests/ChangeLog | 5 +++++ tests/f_bad_disconnected_inode/expect.1 | 5 +---- tests/f_badinode/expect.1 | 2 +- 13 files changed, 70 insertions(+), 33 deletions(-) diff --git a/debugfs/debugfs.c b/debugfs/debugfs.c index 8d937957..6eba9aee 100644 --- a/debugfs/debugfs.c +++ b/debugfs/debugfs.c @@ -541,7 +541,7 @@ void internal_dump_inode(FILE *out, const char *prefix, fprintf(out, "%lld\n", i_size); } else fprintf(out, "%d\n", inode->i_size); - if (current_fs->super->s_creator_os == EXT2_OS_HURD) + if (os == EXT2_OS_HURD) fprintf(out, "%sFile ACL: %d Directory ACL: %d Translator: %d\n", prefix, @@ -551,13 +551,16 @@ void internal_dump_inode(FILE *out, const char *prefix, fprintf(out, "%sFile ACL: %d Directory ACL: %d\n", prefix, inode->i_file_acl, LINUX_S_ISDIR(inode->i_mode) ? inode->i_dir_acl : 0); - fprintf(out, "%sLinks: %d Blockcount: %u\n", - prefix, inode->i_links_count, inode->i_blocks); + if (os == EXT2_OS_LINUX) + fprintf(out, "%sLinks: %d Blockcount: %llu\n", + prefix, inode->i_links_count, + (((unsigned long long) + inode->osd2.linux2.l_i_blocks_hi << 32)) + + inode->i_blocks); + else + fprintf(out, "%sLinks: %d Blockcount: %u\n", + prefix, inode->i_links_count, inode->i_blocks); switch (os) { - case EXT2_OS_LINUX: - frag = inode->osd2.linux2.l_i_frag; - fsize = inode->osd2.linux2.l_i_fsize; - break; case EXT2_OS_HURD: frag = inode->osd2.hurd2.h_i_frag; fsize = inode->osd2.hurd2.h_i_fsize; @@ -867,6 +870,9 @@ void do_modify_inode(int argc, char *argv[]) modify_u32(argv[0], "Access time", decimal_format, &inode.i_atime); modify_u32(argv[0], "Deletion time", decimal_format, &inode.i_dtime); modify_u16(argv[0], "Link count", decimal_format, &inode.i_links_count); + if (os == EXT2_OS_LINUX) + modify_u16(argv[0], "Block count high", unsignedlong_format, + &inode.osd2.linux2.l_i_blocks_hi); modify_u32(argv[0], "Block count", unsignedlong_format, &inode.i_blocks); modify_u32(argv[0], "File flags", hex_format, &inode.i_flags); modify_u32(argv[0], "Generation", hex_format, &inode.i_generation); @@ -879,16 +885,12 @@ void do_modify_inode(int argc, char *argv[]) else modify_u32(argv[0], "High 32bits of size", decimal_format, &inode.i_size_high); - if (current_fs->super->s_creator_os == EXT2_OS_HURD) + if (os == EXT2_OS_HURD) modify_u32(argv[0], "Translator Block", decimal_format, &inode.osd1.hurd1.h_i_translator); modify_u32(argv[0], "Fragment address", decimal_format, &inode.i_faddr); switch (os) { - case EXT2_OS_LINUX: - frag = &inode.osd2.linux2.l_i_frag; - fsize = &inode.osd2.linux2.l_i_fsize; - break; case EXT2_OS_HURD: frag = &inode.osd2.hurd2.h_i_frag; fsize = &inode.osd2.hurd2.h_i_fsize; diff --git a/debugfs/set_fields.c b/debugfs/set_fields.c index 014420a9..5bbddfb4 100644 --- a/debugfs/set_fields.c +++ b/debugfs/set_fields.c @@ -136,8 +136,9 @@ static struct field_set_info inode_fields[] = { { "file_acl", &set_inode.i_file_acl, 4, parse_uint }, { "dir_acl", &set_inode.i_dir_acl, 4, parse_uint }, { "faddr", &set_inode.i_faddr, 4, parse_uint }, - { "frag", &set_inode.osd2.linux2.l_i_frag, 1, parse_uint }, - { "fsize", &set_inode.osd2.linux2.l_i_fsize, 1, parse_uint }, + { "blocks_hi", &set_inode.osd2.linux2.l_i_blocks_hi, 2, parse_uint }, + { "frag", &set_inode.osd2.hurd2.h_i_frag, 1, parse_uint }, + { "fsize", &set_inode.osd2.hurd2.h_i_fsize, 1, parse_uint }, { "uid_high", &set_inode.osd2.linux2.l_i_uid_high, 2, parse_uint }, { "gid_high", &set_inode.osd2.linux2.l_i_gid_high, 2, parse_uint }, { "author", &set_inode.osd2.hurd2.h_i_author, 4, parse_uint }, diff --git a/e2fsck/ChangeLog b/e2fsck/ChangeLog index ce80f5cd..2f11bd75 100644 --- a/e2fsck/ChangeLog +++ b/e2fsck/ChangeLog @@ -1,3 +1,11 @@ +2006-11-11 Theodore Tso + + * problem.c, problem.h (PR_2_BLOCKS_HI_ZERO): Add new problem code. + + * pass1.c (e2fsck_pass1), pass2.c (e2fsck_process_bad_inode): + Replace check for l_i_frag and l_i_fsize with one for + i_blocks_hi. + 2006-11-08 Theodore Tso * badblocks.c (read_bad_blocks_file): Change the last_block diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c index 9a84b783..9650fe1f 100644 --- a/e2fsck/pass1.c +++ b/e2fsck/pass1.c @@ -731,10 +731,6 @@ void e2fsck_pass1(e2fsck_t ctx) ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino); switch (fs->super->s_creator_os) { - case EXT2_OS_LINUX: - frag = inode->osd2.linux2.l_i_frag; - fsize = inode->osd2.linux2.l_i_fsize; - break; case EXT2_OS_HURD: frag = inode->osd2.hurd2.h_i_frag; fsize = inode->osd2.hurd2.h_i_fsize; @@ -750,6 +746,11 @@ void e2fsck_pass1(e2fsck_t ctx) if (inode->i_faddr || frag || fsize || (LINUX_S_ISDIR(inode->i_mode) && inode->i_dir_acl)) mark_inode_bad(ctx, ino); + if ((fs->super->s_creator_os == EXT2_OS_LINUX) && + !(fs->super->s_feature_ro_compat & + EXT4_FEATURE_RO_COMPAT_HUGE_FILE) && + (inode->osd2.linux2.l_i_blocks_hi != 0)) + mark_inode_bad(ctx, ino); if (inode->i_flags & EXT2_IMAGIC_FL) { if (imagic_fs) { if (!ctx->inode_imagic_map) diff --git a/e2fsck/pass2.c b/e2fsck/pass2.c index e47e9500..8bcb3d18 100644 --- a/e2fsck/pass2.c +++ b/e2fsck/pass2.c @@ -1251,10 +1251,6 @@ extern int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir, } switch (fs->super->s_creator_os) { - case EXT2_OS_LINUX: - frag = &inode.osd2.linux2.l_i_frag; - fsize = &inode.osd2.linux2.l_i_fsize; - break; case EXT2_OS_HURD: frag = &inode.osd2.hurd2.h_i_frag; fsize = &inode.osd2.hurd2.h_i_fsize; @@ -1285,6 +1281,17 @@ extern int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir, pctx.num = 0; } + if ((fs->super->s_creator_os == EXT2_OS_LINUX) && + !(fs->super->s_feature_ro_compat & + EXT4_FEATURE_RO_COMPAT_HUGE_FILE) && + (inode.osd2.linux2.l_i_blocks_hi != 0)) { + pctx.num = inode.osd2.linux2.l_i_blocks_hi; + if (fix_problem(ctx, PR_2_BLOCKS_HI_ZERO, &pctx)) { + inode.osd2.linux2.l_i_blocks_hi = 0; + inode_modified++; + } + } + if (inode.i_file_acl && ((inode.i_file_acl < fs->super->s_first_data_block) || (inode.i_file_acl >= fs->super->s_blocks_count))) { diff --git a/e2fsck/problem.c b/e2fsck/problem.c index 2dc3073a..7f6add40 100644 --- a/e2fsck/problem.c +++ b/e2fsck/problem.c @@ -1173,6 +1173,11 @@ static struct e2fsck_problem problem_table[] = { N_("Duplicate @e '%Dn' found.\n\tMarking %p (%i) to be rebuilt.\n\n"), PROMPT_NONE, 0 }, + /* i_blocks_hi should be zero */ + { PR_2_BLOCKS_HI_ZERO, + N_("i_blocks_hi @F %N, @s zero.\n"), + PROMPT_CLEAR, 0 }, + /* Pass 3 errors */ /* Pass 3: Checking directory connectivity */ diff --git a/e2fsck/problem.h b/e2fsck/problem.h index 12f29ec0..4561c618 100644 --- a/e2fsck/problem.h +++ b/e2fsck/problem.h @@ -699,6 +699,9 @@ struct problem_context { /* Duplicate directory entry found */ #define PR_2_REPORT_DUP_DIRENT 0x020043 +/* i_blocks_hi should be zero */ +#define PR_2_BLOCKS_HI_ZERO 0x020044 + /* * Pass 3 errors */ diff --git a/lib/ext2fs/ChangeLog b/lib/ext2fs/ChangeLog index a76d96b7..024363d9 100644 --- a/lib/ext2fs/ChangeLog +++ b/lib/ext2fs/ChangeLog @@ -1,3 +1,12 @@ +2006-11-11 Theodore Tso + + * swapfs.c (ext2fs_swap_inode_full): Byte swap inode->l_i_blocks_hi + + * ext2_fs.h: Add definition of EXT4_FEATURE_RO_COMPAT_HUGE_FILE, + which changes i_blocks to be in units of s_blocksize units + instead of 512-byte sectors, use l_i_frag and l_i_fsize as + i_blocks_hi. + 2006-10-02 Eric Sandeen * getsize.c (ext2fs_get_device_size): Check to make sure that the diff --git a/lib/ext2fs/ext2_fs.h b/lib/ext2fs/ext2_fs.h index d3e39f2b..c6c9aca1 100644 --- a/lib/ext2fs/ext2_fs.h +++ b/lib/ext2fs/ext2_fs.h @@ -299,8 +299,7 @@ struct ext2_inode { __u32 i_faddr; /* Fragment address */ union { struct { - __u8 l_i_frag; /* Fragment number */ - __u8 l_i_fsize; /* Fragment size */ + __u16 l_i_blocks_hi; __u16 i_pad1; __u16 l_i_uid_high; /* these 2 fields */ __u16 l_i_gid_high; /* were reserved2[0] */ @@ -356,8 +355,7 @@ struct ext2_inode_large { __u32 i_faddr; /* Fragment address */ union { struct { - __u8 l_i_frag; /* Fragment number */ - __u8 l_i_fsize; /* Fragment size */ + __u16 l_i_blocks_hi; __u16 i_pad1; __u16 l_i_uid_high; /* these 2 fields */ __u16 l_i_gid_high; /* were reserved2[0] */ @@ -576,6 +574,7 @@ struct ext2_super_block { #define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001 #define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002 /* #define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004 not used */ +#define EXT4_FEATURE_RO_COMPAT_HUGE_FILE 0x0008 #define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001 #define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002 diff --git a/lib/ext2fs/swapfs.c b/lib/ext2fs/swapfs.c index a4c66980..39e23b2b 100644 --- a/lib/ext2fs/swapfs.c +++ b/lib/ext2fs/swapfs.c @@ -159,8 +159,8 @@ void ext2fs_swap_inode_full(ext2_filsys fs, struct ext2_inode_large *t, case EXT2_OS_LINUX: t->osd1.linux1.l_i_reserved1 = ext2fs_swab32(f->osd1.linux1.l_i_reserved1); - t->osd2.linux2.l_i_frag = f->osd2.linux2.l_i_frag; - t->osd2.linux2.l_i_fsize = f->osd2.linux2.l_i_fsize; + t->osd2.linux2.l_i_blocks_hi = + ext2fs_swab16(f->osd2.linux2.l_i_blocks_hi); t->osd2.linux2.i_pad1 = ext2fs_swab16(f->osd2.linux2.i_pad1); t->osd2.linux2.l_i_uid_high = ext2fs_swab16 (f->osd2.linux2.l_i_uid_high); diff --git a/tests/ChangeLog b/tests/ChangeLog index 6c9152a0..7de19f86 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,8 @@ +2006-11-11 Theodore Tso + + * f_badinode, f_bad_disconnected_inode: Update expect scripts to + show check for i_blocks_hi instead of i_frag and i_fsize. + 2006-08-30 Eric Sandeen * m_raid_opt/expect.1: diff --git a/tests/f_bad_disconnected_inode/expect.1 b/tests/f_bad_disconnected_inode/expect.1 index deba68ba..b4851f05 100644 --- a/tests/f_bad_disconnected_inode/expect.1 +++ b/tests/f_bad_disconnected_inode/expect.1 @@ -30,10 +30,7 @@ Clear? yes i_faddr for inode 16 (...) is 1003914917, should be zero. Clear? yes -i_frag for inode 16 (...) is 42, should be zero. -Clear? yes - -i_fsize for inode 16 (...) is 245, should be zero. +i_blocks_hi for inode 16 (...) is 62762, should be zero. Clear? yes Unattached inode 16 diff --git a/tests/f_badinode/expect.1 b/tests/f_badinode/expect.1 index ccda818d..8caa2ccf 100644 --- a/tests/f_badinode/expect.1 +++ b/tests/f_badinode/expect.1 @@ -10,7 +10,7 @@ Clear? yes i_file_acl for inode 13 (/timings) is 39, should be zero. Clear? yes -i_fsize for inode 13 (/timings) is 4, should be zero. +i_blocks_hi for inode 13 (/timings) is 1024, should be zero. Clear? yes Inode 14 (/block_dev) is an illegal block device.