lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Fri, 13 Mar 2015 19:00:07 +0300
From:	Konstantin Khlebnikov <khlebnikov@...dex-team.ru>
To:	Andreas Dilger <adilger@...ger.ca>, linux-ext4@...r.kernel.org,
	Theodore Ts'o <tytso@....edu>,
	"Darrick J. Wong" <darrick.wong@...cle.com>
Cc:	Li Xi <pkuelelixi@...il.com>
Subject: [PATCH RFC v1 1/4] e2fsprogs: introduce project id feature

* 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@...dex-team.ru>
---
 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@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists