Skip to content

Commit 689c958

Browse files
mtfstytso
authored andcommitted
ext4: add project quota support
This patch adds mount options for enabling/disabling project quota accounting and enforcement. A new specific inode is also used for project quota accounting. [ Includes fix from Dan Carpenter to crrect error checking from dqget(). ] Signed-off-by: Li Xi <lixi@ddn.com> Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org> Signed-off-by: Theodore Ts'o <tytso@mit.edu> Reviewed-by: Andreas Dilger <adilger@dilger.ca> Reviewed-by: Jan Kara <jack@suse.cz>
1 parent 040cb37 commit 689c958

File tree

2 files changed

+61
-6
lines changed

2 files changed

+61
-6
lines changed

fs/ext4/ext4.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1261,7 +1261,7 @@ struct ext4_super_block {
12611261
#endif
12621262

12631263
/* Number of quota types we support */
1264-
#define EXT4_MAXQUOTAS 2
1264+
#define EXT4_MAXQUOTAS 3
12651265

12661266
/*
12671267
* fourth extended-fs super-block data in memory

fs/ext4/super.c

Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1097,8 +1097,8 @@ static int bdev_try_to_free_page(struct super_block *sb, struct page *page,
10971097
}
10981098

10991099
#ifdef CONFIG_QUOTA
1100-
#define QTYPE2NAME(t) ((t) == USRQUOTA ? "user" : "group")
1101-
#define QTYPE2MOPT(on, t) ((t) == USRQUOTA?((on)##USRJQUOTA):((on)##GRPJQUOTA))
1100+
static char *quotatypes[] = INITQFNAMES;
1101+
#define QTYPE2NAME(t) (quotatypes[t])
11021102

11031103
static int ext4_write_dquot(struct dquot *dquot);
11041104
static int ext4_acquire_dquot(struct dquot *dquot);
@@ -2558,6 +2558,12 @@ static int ext4_feature_set_ok(struct super_block *sb, int readonly)
25582558
"without CONFIG_QUOTA");
25592559
return 0;
25602560
}
2561+
if (ext4_has_feature_project(sb) && !readonly) {
2562+
ext4_msg(sb, KERN_ERR,
2563+
"Filesystem with project quota feature cannot be mounted RDWR "
2564+
"without CONFIG_QUOTA");
2565+
return 0;
2566+
}
25612567
#endif /* CONFIG_QUOTA */
25622568
return 1;
25632569
}
@@ -3686,7 +3692,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
36863692
sb->s_qcop = &dquot_quotactl_sysfile_ops;
36873693
else
36883694
sb->s_qcop = &ext4_qctl_operations;
3689-
sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP;
3695+
sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP | QTYPE_MASK_PRJ;
36903696
#endif
36913697
memcpy(sb->s_uuid, es->s_uuid, sizeof(es->s_uuid));
36923698

@@ -4822,6 +4828,48 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
48224828
return err;
48234829
}
48244830

4831+
#ifdef CONFIG_QUOTA
4832+
static int ext4_statfs_project(struct super_block *sb,
4833+
kprojid_t projid, struct kstatfs *buf)
4834+
{
4835+
struct kqid qid;
4836+
struct dquot *dquot;
4837+
u64 limit;
4838+
u64 curblock;
4839+
4840+
qid = make_kqid_projid(projid);
4841+
dquot = dqget(sb, qid);
4842+
if (IS_ERR(dquot))
4843+
return PTR_ERR(dquot);
4844+
spin_lock(&dq_data_lock);
4845+
4846+
limit = (dquot->dq_dqb.dqb_bsoftlimit ?
4847+
dquot->dq_dqb.dqb_bsoftlimit :
4848+
dquot->dq_dqb.dqb_bhardlimit) >> sb->s_blocksize_bits;
4849+
if (limit && buf->f_blocks > limit) {
4850+
curblock = dquot->dq_dqb.dqb_curspace >> sb->s_blocksize_bits;
4851+
buf->f_blocks = limit;
4852+
buf->f_bfree = buf->f_bavail =
4853+
(buf->f_blocks > curblock) ?
4854+
(buf->f_blocks - curblock) : 0;
4855+
}
4856+
4857+
limit = dquot->dq_dqb.dqb_isoftlimit ?
4858+
dquot->dq_dqb.dqb_isoftlimit :
4859+
dquot->dq_dqb.dqb_ihardlimit;
4860+
if (limit && buf->f_files > limit) {
4861+
buf->f_files = limit;
4862+
buf->f_ffree =
4863+
(buf->f_files > dquot->dq_dqb.dqb_curinodes) ?
4864+
(buf->f_files - dquot->dq_dqb.dqb_curinodes) : 0;
4865+
}
4866+
4867+
spin_unlock(&dq_data_lock);
4868+
dqput(dquot);
4869+
return 0;
4870+
}
4871+
#endif
4872+
48254873
static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf)
48264874
{
48274875
struct super_block *sb = dentry->d_sb;
@@ -4854,6 +4902,11 @@ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf)
48544902
buf->f_fsid.val[0] = fsid & 0xFFFFFFFFUL;
48554903
buf->f_fsid.val[1] = (fsid >> 32) & 0xFFFFFFFFUL;
48564904

4905+
#ifdef CONFIG_QUOTA
4906+
if (ext4_test_inode_flag(dentry->d_inode, EXT4_INODE_PROJINHERIT) &&
4907+
sb_has_quota_limits_enabled(sb, PRJQUOTA))
4908+
ext4_statfs_project(sb, EXT4_I(dentry->d_inode)->i_projid, buf);
4909+
#endif
48574910
return 0;
48584911
}
48594912

@@ -5018,7 +5071,8 @@ static int ext4_quota_enable(struct super_block *sb, int type, int format_id,
50185071
struct inode *qf_inode;
50195072
unsigned long qf_inums[EXT4_MAXQUOTAS] = {
50205073
le32_to_cpu(EXT4_SB(sb)->s_es->s_usr_quota_inum),
5021-
le32_to_cpu(EXT4_SB(sb)->s_es->s_grp_quota_inum)
5074+
le32_to_cpu(EXT4_SB(sb)->s_es->s_grp_quota_inum),
5075+
le32_to_cpu(EXT4_SB(sb)->s_es->s_prj_quota_inum)
50225076
};
50235077

50245078
BUG_ON(!ext4_has_feature_quota(sb));
@@ -5046,7 +5100,8 @@ static int ext4_enable_quotas(struct super_block *sb)
50465100
int type, err = 0;
50475101
unsigned long qf_inums[EXT4_MAXQUOTAS] = {
50485102
le32_to_cpu(EXT4_SB(sb)->s_es->s_usr_quota_inum),
5049-
le32_to_cpu(EXT4_SB(sb)->s_es->s_grp_quota_inum)
5103+
le32_to_cpu(EXT4_SB(sb)->s_es->s_grp_quota_inum),
5104+
le32_to_cpu(EXT4_SB(sb)->s_es->s_prj_quota_inum)
50505105
};
50515106

50525107
sb_dqopt(sb)->flags |= DQUOT_QUOTA_SYS_FILE;

0 commit comments

Comments
 (0)