[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-Id: <1426045077-1264-3-git-send-email-lixi@ddn.com>
Date: Wed, 11 Mar 2015 12:37:57 +0900
From: Li Xi <pkuelelixi@...il.com>
To: linux-ext4@...r.kernel.org, tytso@....edu, adilger@...ger.ca,
jack@...e.cz, viro@...iv.linux.org.uk, hch@...radead.org,
dmonakhov@...nvz.org
Subject: [PATCH 2/2] quota: add project quota support
This patch adds project quota support so that a file system can
be formated with project quota feature enabled.
Signed-off-by: Li Xi <lixi@....com>
---
debugfs/set_fields.c | 1 +
lib/e2p/feature.c | 2 ++
lib/e2p/ls.c | 1 +
lib/e2p/pf.c | 1 +
lib/ext2fs/ext2_fs.h | 12 ++++++++----
lib/ext2fs/ext2fs.h | 3 ++-
lib/ext2fs/swapfs.c | 2 ++
lib/quota/mkquota.c | 11 +++++++++++
lib/quota/quotaio.c | 9 ++++++++-
lib/quota/quotaio.h | 11 ++++++++---
misc/chattr.c | 3 ++-
misc/ext4.5.in | 5 +++++
misc/mke2fs.c | 5 ++++-
misc/tune2fs.c | 7 ++++++-
14 files changed, 61 insertions(+), 12 deletions(-)
diff --git a/debugfs/set_fields.c b/debugfs/set_fields.c
index 9325ab9..221649a 100644
--- a/debugfs/set_fields.c
+++ b/debugfs/set_fields.c
@@ -150,6 +150,7 @@ static struct field_set_info super_fields[] = {
{ "mount_opts", &set_sb.s_mount_opts, NULL, 64, parse_string },
{ "usr_quota_inum", &set_sb.s_usr_quota_inum, NULL, 4, parse_uint },
{ "grp_quota_inum", &set_sb.s_grp_quota_inum, NULL, 4, parse_uint },
+ { "prj_quota_inum", &set_sb.s_prj_quota_inum, NULL, 4, parse_uint },
{ "overhead_blocks", &set_sb.s_overhead_blocks, NULL, 4, parse_uint },
{ "backup_bgs", &set_sb.s_backup_bgs[0], NULL, 4, parse_uint,
FLAG_ARRAY, 2 },
diff --git a/lib/e2p/feature.c b/lib/e2p/feature.c
index 30d2db1..3d482af 100644
--- a/lib/e2p/feature.c
+++ b/lib/e2p/feature.c
@@ -68,6 +68,8 @@ static struct feature feature_list[] = {
"metadata_csum"},
{ E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_REPLICA,
"replica" },
+ { 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 93e202d..bddf0c9 100644
--- a/lib/e2p/ls.c
+++ b/lib/e2p/ls.c
@@ -210,6 +210,7 @@ static const char *checksum_type(__u8 type)
static const char const *quota_prefix[MAXQUOTAS] = {
[USRQUOTA] = "User quota inode:",
[GRPQUOTA] = "Group quota inode:",
+ [PRJQUOTA] = "Project quota inode:",
};
/**
diff --git a/lib/e2p/pf.c b/lib/e2p/pf.c
index 788c445..feaa171 100644
--- a/lib/e2p/pf.c
+++ b/lib/e2p/pf.c
@@ -51,6 +51,7 @@ static struct flags_name flags_array[] = {
{ EXT4_HUGE_FILE_FL, "h", "Huge_file" },
{ FS_NOCOW_FL, "C", "No_COW" },
{ EXT4_INLINE_DATA_FL, "N", "Inline_Data" },
+ { EXT4_PROJINHERIT_FL, "P", "Project_Iherit" },
{ 0, NULL, NULL }
};
diff --git a/lib/ext2fs/ext2_fs.h b/lib/ext2fs/ext2_fs.h
index 10cb650..6b9f243 100644
--- a/lib/ext2fs/ext2_fs.h
+++ b/lib/ext2fs/ext2_fs.h
@@ -50,7 +50,7 @@
#define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */
#define EXT2_RESIZE_INO 7 /* Reserved group descriptors inode */
#define EXT2_JOURNAL_INO 8 /* Journal inode */
-#define EXT2_EXCLUDE_INO 9 /* The "exclude" inode, for snapshots */
+#define EXT4_PRJ_QUOTA_INO 9 /* Project quota inode */
#define EXT4_REPLICA_INO 10 /* Used by non-upstream feature */
/* First non-reserved inode for old ext2 filesystems */
@@ -326,10 +326,11 @@ struct ext2_dx_tail {
#define EXT4_SNAPFILE_DELETED_FL 0x04000000 /* Snapshot is being deleted */
#define EXT4_SNAPFILE_SHRUNK_FL 0x08000000 /* Snapshot shrink has completed */
#define EXT4_INLINE_DATA_FL 0x10000000 /* Inode has inline data */
+#define EXT4_PROJINHERIT_FL 0x20000000 /* Create with parents projid */
#define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */
-#define EXT2_FL_USER_VISIBLE 0x004BDFFF /* User visible flags */
-#define EXT2_FL_USER_MODIFIABLE 0x004B80FF /* User modifiable flags */
+#define EXT2_FL_USER_VISIBLE 0x204BDFFF /* User visible flags */
+#define EXT2_FL_USER_MODIFIABLE 0x204B80FF /* User modifiable flags */
/*
* ioctl commands
@@ -473,6 +474,7 @@ struct ext2_inode_large {
__u32 i_crtime; /* File creation time */
__u32 i_crtime_extra; /* extra File creation time (nsec << 2 | epoch)*/
__u32 i_version_hi; /* high 32 bits for 64-bit version */
+ __u32 i_projid; /* Project ID */
};
#define EXT4_INODE_CSUM_HI_EXTRA_END \
@@ -683,7 +685,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) */
};
@@ -754,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_PROJECT 0x2000 /* Project quota */
#define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001
#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index f090df1..719416a 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -608,7 +608,8 @@ typedef struct ext2_icount *ext2_icount_t;
EXT4_FEATURE_RO_COMPAT_GDT_CSUM|\
EXT4_FEATURE_RO_COMPAT_BIGALLOC|\
EXT4_LIB_RO_COMPAT_QUOTA|\
- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)
+ EXT4_FEATURE_RO_COMPAT_METADATA_CSUM|\
+ 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 ee7a455..bc50fd4 100644
--- a/lib/ext2fs/swapfs.c
+++ b/lib/ext2fs/swapfs.c
@@ -320,6 +320,8 @@ void ext2fs_swap_inode_full(ext2_filsys fs, struct ext2_inode_large *t,
t->i_crtime_extra = ext2fs_swab32(f->i_crtime_extra);
if (extra_isize >= 28)
t->i_version_hi = ext2fs_swab32(f->i_version_hi);
+ if (extra_isize >= 32)
+ t->i_projid = ext2fs_swab32(f->i_projid);
i = sizeof(struct ext2_inode) + extra_isize + sizeof(__u32);
if (bufsize < (int) i)
diff --git a/lib/quota/mkquota.c b/lib/quota/mkquota.c
index 825457b..7ce3bb3 100644
--- a/lib/quota/mkquota.c
+++ b/lib/quota/mkquota.c
@@ -231,6 +231,12 @@ static int dict_uint_cmp(const void *a, const void *b)
static inline qid_t get_qid(struct ext2_inode *inode, enum quota_type qtype)
{
+ struct ext2_inode_large *large_inode;
+ //int is_large_inode = 0;
+
+ //if (EXT2_INODE_SIZE(current_fs->super) > EXT2_GOOD_OLD_INODE_SIZE)
+ // is_large_inode = 1;
+
assert(qtype >= 0);
assert(qtype < MAXQUOTAS);
switch (qtype) {
@@ -238,6 +244,11 @@ static inline qid_t get_qid(struct ext2_inode *inode, enum quota_type qtype)
return inode_uid(*inode);
case GRPQUOTA:
return inode_gid(*inode);
+ case PRJQUOTA:
+ large_inode = (struct ext2_inode_large *) inode;
+ assert(//is_large_inode &&
+ large_inode->i_extra_isize >= 32);
+ return inode_gid(*inode); //XXX
default:
return 0;
}
diff --git a/lib/quota/quotaio.c b/lib/quota/quotaio.c
index b1f4a4f..53fad1c 100644
--- a/lib/quota/quotaio.c
+++ b/lib/quota/quotaio.c
@@ -20,7 +20,11 @@
#include "common.h"
#include "quotaio.h"
-static const char * const extensions[MAXQUOTAS] = {"user", "group"};
+static const char * const extensions[MAXQUOTAS] = {
+ [USRQUOTA] = "user",
+ [GRPQUOTA] = "group",
+ [PRJQUOTA] = "project",
+};
static const char * const basenames[] = {
"", /* undefined */
"quota", /* QFMT_VFS_OLD */
@@ -56,6 +60,9 @@ ext2_ino_t quota_type2inum(enum quota_type qtype)
case GRPQUOTA:
return EXT4_GRP_QUOTA_INO;
break;
+ case PRJQUOTA:
+ return EXT4_PRJ_QUOTA_INO;
+ break;
default:
return 0;
break;
diff --git a/lib/quota/quotaio.h b/lib/quota/quotaio.h
index 8b8a945..b7d6195 100644
--- a/lib/quota/quotaio.h
+++ b/lib/quota/quotaio.h
@@ -47,9 +47,10 @@ typedef int64_t qsize_t; /* Type in which we store size limitations */
enum quota_type {
USRQUOTA = 0,
GRPQUOTA = 1,
+ PRJQUOTA = 2,
};
-#define MAXQUOTAS 2
+#define MAXQUOTAS 3
#if MAXQUOTAS > 32
#error "cannot have more than 32 quota types to fit in qtype_bits"
@@ -57,7 +58,8 @@ enum quota_type {
#define QUOTA_USR_BIT (1 << USRQUOTA)
#define QUOTA_GRP_BIT (1 << GRPQUOTA)
-#define QUOTA_ALL_BIT (QUOTA_USR_BIT | QUOTA_GRP_BIT)
+#define QUOTA_PRJ_BIT (1 << PRJQUOTA)
+#define QUOTA_ALL_BIT (QUOTA_USR_BIT | QUOTA_GRP_BIT | QUOTA_PRJ_BIT)
typedef struct quota_ctx *quota_ctx_t;
@@ -72,7 +74,8 @@ struct quota_ctx {
*/
#define INITQMAGICS {\
0xd9c01f11, /* USRQUOTA */\
- 0xd9c01927 /* GRPQUOTA */\
+ 0xd9c01927, /* GRPQUOTA */\
+ 0xd9c03f14 /* PRJQUOTA */\
}
/* Size of blocks in which are counted size limits in generic utility parts */
@@ -246,6 +249,8 @@ static inline ext2_ino_t *quota_sb_inump(struct ext2_super_block *sb, enum quota
return &sb->s_usr_quota_inum;
case GRPQUOTA:
return &sb->s_grp_quota_inum;
+ case PRJQUOTA:
+ return &sb->s_prj_quota_inum;
default:
return NULL;
}
diff --git a/misc/chattr.c b/misc/chattr.c
index f130108..f5fa397 100644
--- a/misc/chattr.c
+++ b/misc/chattr.c
@@ -83,7 +83,7 @@ static unsigned long sf;
static void usage(void)
{
fprintf(stderr,
- _("Usage: %s [-RVf] [-+=aAcCdDeijsStTu] [-v version] files...\n"),
+ _("Usage: %s [-RVf] [-+=aAcCdDeijPsStTu] [-v version] files...\n"),
program_name);
exit(1);
}
@@ -103,6 +103,7 @@ static const struct flags_char flags_array[] = {
{ EXT4_EXTENTS_FL, 'e'},
{ EXT2_IMMUTABLE_FL, 'i' },
{ EXT3_JOURNAL_DATA_FL, 'j' },
+ { EXT4_PROJINHERIT_FL, 'P' },
{ EXT2_SECRM_FL, 's' },
{ EXT2_UNRM_FL, 'u' },
{ EXT2_NOTAIL_FL, 't' },
diff --git a/misc/ext4.5.in b/misc/ext4.5.in
index 19302a7..a69104a 100644
--- a/misc/ext4.5.in
+++ b/misc/ext4.5.in
@@ -214,6 +214,11 @@ shared storage environments.
@QUOTA_MAN_COMMENT@...up.quota which existed
@QUOTA_MAN_COMMENT@in the older quota design) to be hidden inodes.
.TP
+.B project
+.br
+This ext4 feature provides project quota support. With this feature,
+the project ID of inode will be managed when the filesystem is mounted.
+.TP
.B resize_inode
.br
This file system feature indicates that space has been reserved so
diff --git a/misc/mke2fs.c b/misc/mke2fs.c
index 18da59d..906425a 100644
--- a/misc/mke2fs.c
+++ b/misc/mke2fs.c
@@ -1015,6 +1015,8 @@ static void parse_extended_opts(struct ext2_super_block *param,
quotatype_bits = QUOTA_USR_BIT;
} else if (!strncmp(arg, "grp", 3)) {
quotatype_bits = QUOTA_GRP_BIT;
+ } else if (!strncmp(arg, "prj", 4)) {
+ quotatype_bits = QUOTA_PRJ_BIT;
} else {
fprintf(stderr,
_("Invalid quotatype parameter: %s\n"),
@@ -1088,7 +1090,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 eb85e26..b3ce8d2 100644
--- a/misc/tune2fs.c
+++ b/misc/tune2fs.c
@@ -160,7 +160,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
};
static __u32 clear_ok_features[3] = {
@@ -1495,6 +1496,10 @@ static void parse_quota_opts(const char *opts)
quota_enable[GRPQUOTA] = QOPT_ENABLE;
} else if (strcmp(token, "^grpquota") == 0) {
quota_enable[GRPQUOTA] = QOPT_DISABLE;
+ } else if (strcmp(token, "prjquota") == 0) {
+ quota_enable[PRJQUOTA] = QOPT_ENABLE;
+ } else if (strcmp(token, "^prjquota") == 0) {
+ quota_enable[PRJQUOTA] = QOPT_DISABLE;
} else {
fputs(_("\nBad quota options specified.\n\n"
"Following valid quota options are available "
--
1.7.1
--
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