* add feature EXT4_FEATURE_RO_COMPAT_PROJECT * reuse obsolete inode field i_faddr as i_project * add field s_prj_quota_inum into superblock for project quota inode Signed-off-by: Konstantin Khlebnikov <khlebnikov@xxxxxxxxxxxxxx> --- debugfs/debugfs.c | 40 ++++++++++++++++++++++++++++------------ debugfs/set_fields.c | 4 +++- e2fsck/pass1.c | 5 ++++- e2fsck/pass2.c | 3 ++- lib/e2p/feature.c | 2 ++ lib/e2p/ls.c | 3 +++ lib/ext2fs/ext2_fs.h | 9 ++++++--- lib/ext2fs/ext2fs.h | 3 ++- lib/ext2fs/swapfs.c | 3 ++- lib/ext2fs/tst_inode_size.c | 2 +- lib/ext2fs/tst_super_size.c | 3 ++- misc/mke2fs.c | 3 ++- misc/tune2fs.c | 28 ++++++++++++++++++++++++++-- 13 files changed, 83 insertions(+), 25 deletions(-) diff --git a/debugfs/debugfs.c b/debugfs/debugfs.c index fe57366ffa98..066d9a7825f2 100644 --- a/debugfs/debugfs.c +++ b/debugfs/debugfs.c @@ -713,7 +713,7 @@ void internal_dump_inode(FILE *out, const char *prefix, int do_dump_blocks) { const char *i_type; - char frag, fsize; + struct ext2_super_block *sb = current_fs->super; int os = current_fs->super->s_creator_os; struct ext2_inode_large *large_inode; int is_large_inode = 0; @@ -741,8 +741,11 @@ void internal_dump_inode(FILE *out, const char *prefix, fprintf(out, "%sGeneration: %u Version: 0x%08x\n", prefix, inode->i_generation, inode->osd1.linux1.l_i_version); } - fprintf(out, "%sUser: %5d Group: %5d Size: ", + fprintf(out, "%sUser: %5d Group: %5d ", prefix, inode_uid(*inode), inode_gid(*inode)); + if (EXT2_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_PROJECT)) + fprintf(out, "Project: %5d ", large_inode->i_project); + fprintf(out, "Size: "); if (LINUX_S_ISREG(inode->i_mode)) fprintf(out, "%llu\n", EXT2_I_SIZE(inode)); else @@ -768,16 +771,22 @@ void internal_dump_inode(FILE *out, const char *prefix, else fprintf(out, "%sLinks: %d Blockcount: %u\n", prefix, inode->i_links_count, inode->i_blocks); - switch (os) { - case EXT2_OS_HURD: - frag = inode->osd2.hurd2.h_i_frag; - fsize = inode->osd2.hurd2.h_i_fsize; - break; - default: - frag = fsize = 0; + + if (!EXT2_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_PROJECT)) { + char frag, fsize; + + switch (os) { + case EXT2_OS_HURD: + frag = inode->osd2.hurd2.h_i_frag; + fsize = inode->osd2.hurd2.h_i_fsize; + break; + default: + frag = fsize = 0; + } + fprintf(out, "%sFragment: Address: %d Number: %d Size: %d\n", + prefix, inode->i_faddr, frag, fsize); } - fprintf(out, "%sFragment: Address: %d Number: %d Size: %d\n", - prefix, inode->i_faddr, frag, fsize); + if (is_large_inode && large_inode->i_extra_isize >= 24) { fprintf(out, "%s ctime: 0x%08x:%08x -- %s", prefix, inode->i_ctime, large_inode->i_ctime_extra, @@ -1256,7 +1265,14 @@ void do_modify_inode(int argc, char *argv[]) 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); + if (EXT2_HAS_RO_COMPAT_FEATURE(current_fs->super, + EXT4_FEATURE_RO_COMPAT_PROJECT)) + modify_u32(argv[0], "Project ID", decimal_format, + &inode.i_project); + else + modify_u32(argv[0], "Fragment address", decimal_format, + &inode.i_faddr); + switch (os) { case EXT2_OS_HURD: frag = &inode.osd2.hurd2.h_i_frag; diff --git a/debugfs/set_fields.c b/debugfs/set_fields.c index 37fd5ec0e6e8..81689bbb6611 100644 --- a/debugfs/set_fields.c +++ b/debugfs/set_fields.c @@ -167,6 +167,7 @@ static struct field_set_info super_fields[] = { { "last_error_line", &set_sb.s_last_error_line, NULL, 4, parse_uint }, { "encrypt_algos", &set_sb.s_encrypt_algos, NULL, 1, parse_uint, FLAG_ARRAY, 4 }, + { "prj_quota_inum", &set_sb.s_prj_quota_inum, NULL, 4, parse_uint }, { 0, 0, 0, 0 } }; @@ -200,7 +201,8 @@ static struct field_set_info inode_fields[] = { { "file_acl", &set_inode.i_file_acl, &set_inode.osd2.linux2.l_i_file_acl_high, 6, parse_uint }, { "dir_acl", &set_inode.i_dir_acl, NULL, 4, parse_uint, FLAG_ALIAS }, - { "faddr", &set_inode.i_faddr, NULL, 4, parse_uint }, + { "project", &set_inode.i_project, NULL, 4, parse_uint }, + { "faddr", &set_inode.i_faddr, NULL, 4, parse_uint, FLAG_ALIAS }, { "frag", &set_inode.osd2.hurd2.h_i_frag, NULL, 1, parse_uint, FLAG_ALIAS }, { "fsize", &set_inode.osd2.hurd2.h_i_fsize, NULL, 1, parse_uint }, { "checksum", &set_inode.osd2.linux2.l_i_checksum_lo, diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c index 319d23b84938..b5ac4a8587eb 100644 --- a/e2fsck/pass1.c +++ b/e2fsck/pass1.c @@ -1567,7 +1567,10 @@ void e2fsck_pass1(e2fsck_t ctx) frag = fsize = 0; } - if (inode->i_faddr || frag || fsize || + if (inode->i_faddr && !EXT2_HAS_RO_COMPAT_FEATURE(sb, + EXT4_FEATURE_RO_COMPAT_PROJECT)) + mark_inode_bad(ctx, ino); + if (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) && diff --git a/e2fsck/pass2.c b/e2fsck/pass2.c index 94665c6ed3dc..26af55c9d4dd 100644 --- a/e2fsck/pass2.c +++ b/e2fsck/pass2.c @@ -1746,7 +1746,8 @@ int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir, problem = 0; } - if (inode.i_faddr) { + if (inode.i_faddr && !EXT2_HAS_RO_COMPAT_FEATURE(fs->super, + EXT4_FEATURE_RO_COMPAT_PROJECT)) { if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) { inode.i_faddr = 0; inode_modified++; diff --git a/lib/e2p/feature.c b/lib/e2p/feature.c index 73884f2cf5bf..5b155a90252a 100644 --- a/lib/e2p/feature.c +++ b/lib/e2p/feature.c @@ -70,6 +70,8 @@ static struct feature feature_list[] = { "replica" }, { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_READONLY, "read-only" }, + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_PROJECT, + "project" }, { E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_COMPRESSION, "compression" }, diff --git a/lib/e2p/ls.c b/lib/e2p/ls.c index a7ea38a44136..182de2245c72 100644 --- a/lib/e2p/ls.c +++ b/lib/e2p/ls.c @@ -440,6 +440,9 @@ void list_super2(struct ext2_super_block * sb, FILE *f) if (sb->s_grp_quota_inum) fprintf(f, "Group quota inode: %u\n", sb->s_grp_quota_inum); + if (sb->s_prj_quota_inum) + fprintf(f, "Project quota inode: %u\n", + sb->s_prj_quota_inum); if (sb->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) { fprintf(f, "Checksum type: %s\n", diff --git a/lib/ext2fs/ext2_fs.h b/lib/ext2fs/ext2_fs.h index 6715d4e04a9a..5ff835e60657 100644 --- a/lib/ext2fs/ext2_fs.h +++ b/lib/ext2fs/ext2_fs.h @@ -398,7 +398,7 @@ struct ext2_inode { __u32 i_generation; /* File version (for NFS) */ __u32 i_file_acl; /* File ACL */ __u32 i_size_high; /* Formerly i_dir_acl, directory ACL */ - __u32 i_faddr; /* Fragment address */ + __u32 i_project; /* Formerly i_faddr, fragment address */ union { struct { __u16 l_i_blocks_hi; @@ -446,7 +446,7 @@ struct ext2_inode_large { __u32 i_generation; /* File version (for NFS) */ __u32 i_file_acl; /* File ACL */ __u32 i_size_high; /* Formerly i_dir_acl, directory ACL */ - __u32 i_faddr; /* Fragment address */ + __u32 i_project; /* Formerly i_faddr, fragment address */ union { struct { __u16 l_i_blocks_hi; @@ -480,6 +480,7 @@ struct ext2_inode_large { EXT2_GOOD_OLD_INODE_SIZE) #define i_dir_acl i_size_high +#define i_faddr i_project #define i_checksum_lo osd2.linux2.l_i_checksum_lo @@ -683,7 +684,8 @@ struct ext2_super_block { __u32 s_overhead_blocks; /* overhead blocks/clusters in fs */ __u32 s_backup_bgs[2]; /* If sparse_super2 enabled */ __u8 s_encrypt_algos[4]; /* Encryption algorithms in use */ - __u32 s_reserved[105]; /* Padding to the end of the block */ + __u32 s_prj_quota_inum; /* inode number of project quota file */ + __u32 s_reserved[104]; /* Padding to the end of the block */ __u32 s_checksum; /* crc32c(superblock) */ }; @@ -755,6 +757,7 @@ struct ext2_super_block { #define EXT4_FEATURE_RO_COMPAT_METADATA_CSUM 0x0400 #define EXT4_FEATURE_RO_COMPAT_REPLICA 0x0800 #define EXT4_FEATURE_RO_COMPAT_READONLY 0x1000 +#define EXT4_FEATURE_RO_COMPAT_PROJECT 0x2000 /* Project ID / Quota */ #define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001 diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h index d75dd7654c34..ca84c70fc7c1 100644 --- a/lib/ext2fs/ext2fs.h +++ b/lib/ext2fs/ext2fs.h @@ -610,7 +610,8 @@ typedef struct ext2_icount *ext2_icount_t; EXT4_FEATURE_RO_COMPAT_BIGALLOC|\ EXT4_LIB_RO_COMPAT_QUOTA|\ EXT4_FEATURE_RO_COMPAT_METADATA_CSUM|\ - EXT4_FEATURE_RO_COMPAT_READONLY) + EXT4_FEATURE_RO_COMPAT_READONLY|\ + EXT4_FEATURE_RO_COMPAT_PROJECT) /* * These features are only allowed if EXT2_FLAG_SOFTSUPP_FEATURES is passed diff --git a/lib/ext2fs/swapfs.c b/lib/ext2fs/swapfs.c index ee7a45591598..98910e6d1faf 100644 --- a/lib/ext2fs/swapfs.c +++ b/lib/ext2fs/swapfs.c @@ -82,6 +82,7 @@ void ext2fs_swap_super(struct ext2_super_block * sb) sb->s_usr_quota_inum = ext2fs_swab32(sb->s_usr_quota_inum); sb->s_grp_quota_inum = ext2fs_swab32(sb->s_grp_quota_inum); sb->s_overhead_blocks = ext2fs_swab32(sb->s_overhead_blocks); + sb->s_prj_quota_inum = ext2fs_swab32(sb->s_prj_quota_inum); sb->s_checksum = ext2fs_swab32(sb->s_checksum); for (i=0; i < 4; i++) @@ -257,7 +258,7 @@ void ext2fs_swap_inode_full(ext2_filsys fs, struct ext2_inode_large *t, t->i_block[i] = f->i_block[i]; } t->i_generation = ext2fs_swab32(f->i_generation); - t->i_faddr = ext2fs_swab32(f->i_faddr); + t->i_project = ext2fs_swab32(f->i_project); switch (fs->super->s_creator_os) { case EXT2_OS_LINUX: diff --git a/lib/ext2fs/tst_inode_size.c b/lib/ext2fs/tst_inode_size.c index e20ec981111a..384d1c2ba946 100644 --- a/lib/ext2fs/tst_inode_size.c +++ b/lib/ext2fs/tst_inode_size.c @@ -65,7 +65,7 @@ int main(int argc, char **argv) check_field(i_generation, 4); check_field(i_file_acl, 4); check_field(i_size_high, 4); - check_field(i_faddr, 4); + check_field(i_project, 4); check_field(osd2.linux2.l_i_blocks_hi, 2); check_field(osd2.linux2.l_i_file_acl_high, 2); check_field(osd2.linux2.l_i_uid_high, 2); diff --git a/lib/ext2fs/tst_super_size.c b/lib/ext2fs/tst_super_size.c index f6c74f75db34..947fb2a632cd 100644 --- a/lib/ext2fs/tst_super_size.c +++ b/lib/ext2fs/tst_super_size.c @@ -137,7 +137,8 @@ int main(int argc, char **argv) check_field(s_overhead_blocks, 4); check_field(s_backup_bgs, 8); check_field(s_encrypt_algos, 4); - check_field(s_reserved, 105 * 4); + check_field(s_prj_quota_inum, 4); + check_field(s_reserved, 104 * 4); check_field(s_checksum, 4); do_field("Superblock end", 0, 0, cur_offset, 1024); #endif diff --git a/misc/mke2fs.c b/misc/mke2fs.c index 742f81694b84..5427305b748d 100644 --- a/misc/mke2fs.c +++ b/misc/mke2fs.c @@ -1107,7 +1107,8 @@ static __u32 ok_features[3] = { #ifdef CONFIG_QUOTA EXT4_FEATURE_RO_COMPAT_QUOTA| #endif - EXT4_FEATURE_RO_COMPAT_METADATA_CSUM + EXT4_FEATURE_RO_COMPAT_METADATA_CSUM | + EXT4_FEATURE_RO_COMPAT_PROJECT }; diff --git a/misc/tune2fs.c b/misc/tune2fs.c index 550932d67949..0410d1c11539 100644 --- a/misc/tune2fs.c +++ b/misc/tune2fs.c @@ -161,7 +161,8 @@ static __u32 ok_features[3] = { EXT4_FEATURE_RO_COMPAT_QUOTA | #endif EXT4_FEATURE_RO_COMPAT_METADATA_CSUM | - EXT4_FEATURE_RO_COMPAT_READONLY + EXT4_FEATURE_RO_COMPAT_READONLY | + EXT4_FEATURE_RO_COMPAT_PROJECT }; static __u32 clear_ok_features[3] = { @@ -184,7 +185,8 @@ static __u32 clear_ok_features[3] = { EXT4_FEATURE_RO_COMPAT_QUOTA | #endif EXT4_FEATURE_RO_COMPAT_METADATA_CSUM | - EXT4_FEATURE_RO_COMPAT_READONLY + EXT4_FEATURE_RO_COMPAT_READONLY | + EXT4_FEATURE_RO_COMPAT_PROJECT }; /** @@ -1303,6 +1305,28 @@ mmp_error: grpquota = QOPT_DISABLE; } + if (FEATURE_CHANGED(E2P_FEATURE_RO_INCOMPAT, + EXT4_FEATURE_RO_COMPAT_PROJECT) && + (mount_flags & EXT2_MF_MOUNTED) && + !(mount_flags & EXT2_MF_READONLY)) { + fputs(_("The project feature may only be " + "changed when the filesystem is\n" + "unmounted or mounted read-only.\n"), stderr); + return 1; + } + + if (FEATURE_ON(E2P_FEATURE_RO_INCOMPAT, + EXT4_FEATURE_RO_COMPAT_PROJECT)) { + sb->s_feature_ro_compat |= EXT4_FEATURE_RO_COMPAT_PROJECT; + } + + if (FEATURE_OFF(E2P_FEATURE_RO_INCOMPAT, + EXT4_FEATURE_RO_COMPAT_PROJECT)) { + sb->s_feature_ro_compat &= ~EXT4_FEATURE_RO_COMPAT_PROJECT; + /* fsck will reset i_project (i_faddr) for us. */ + request_fsck_afterwards(fs); + } + if (sb->s_rev_level == EXT2_GOOD_OLD_REV && (sb->s_feature_compat || sb->s_feature_ro_compat || sb->s_feature_incompat)) -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html