提交 689c958c 编写于 作者: L Li Xi 提交者: Theodore Ts'o

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: NLi Xi <lixi@ddn.com>
Signed-off-by: NDmitry Monakhov <dmonakhov@openvz.org>
Signed-off-by: NTheodore Ts'o <tytso@mit.edu>
Reviewed-by: NAndreas Dilger <adilger@dilger.ca>
Reviewed-by: NJan Kara <jack@suse.cz>
上级 040cb378
...@@ -1261,7 +1261,7 @@ struct ext4_super_block { ...@@ -1261,7 +1261,7 @@ struct ext4_super_block {
#endif #endif
/* Number of quota types we support */ /* Number of quota types we support */
#define EXT4_MAXQUOTAS 2 #define EXT4_MAXQUOTAS 3
/* /*
* fourth extended-fs super-block data in memory * fourth extended-fs super-block data in memory
......
...@@ -1097,8 +1097,8 @@ static int bdev_try_to_free_page(struct super_block *sb, struct page *page, ...@@ -1097,8 +1097,8 @@ static int bdev_try_to_free_page(struct super_block *sb, struct page *page,
} }
#ifdef CONFIG_QUOTA #ifdef CONFIG_QUOTA
#define QTYPE2NAME(t) ((t) == USRQUOTA ? "user" : "group") static char *quotatypes[] = INITQFNAMES;
#define QTYPE2MOPT(on, t) ((t) == USRQUOTA?((on)##USRJQUOTA):((on)##GRPJQUOTA)) #define QTYPE2NAME(t) (quotatypes[t])
static int ext4_write_dquot(struct dquot *dquot); static int ext4_write_dquot(struct dquot *dquot);
static int ext4_acquire_dquot(struct dquot *dquot); static int ext4_acquire_dquot(struct dquot *dquot);
...@@ -2558,6 +2558,12 @@ static int ext4_feature_set_ok(struct super_block *sb, int readonly) ...@@ -2558,6 +2558,12 @@ static int ext4_feature_set_ok(struct super_block *sb, int readonly)
"without CONFIG_QUOTA"); "without CONFIG_QUOTA");
return 0; return 0;
} }
if (ext4_has_feature_project(sb) && !readonly) {
ext4_msg(sb, KERN_ERR,
"Filesystem with project quota feature cannot be mounted RDWR "
"without CONFIG_QUOTA");
return 0;
}
#endif /* CONFIG_QUOTA */ #endif /* CONFIG_QUOTA */
return 1; return 1;
} }
...@@ -3686,7 +3692,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) ...@@ -3686,7 +3692,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
sb->s_qcop = &dquot_quotactl_sysfile_ops; sb->s_qcop = &dquot_quotactl_sysfile_ops;
else else
sb->s_qcop = &ext4_qctl_operations; sb->s_qcop = &ext4_qctl_operations;
sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP; sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP | QTYPE_MASK_PRJ;
#endif #endif
memcpy(sb->s_uuid, es->s_uuid, sizeof(es->s_uuid)); memcpy(sb->s_uuid, es->s_uuid, sizeof(es->s_uuid));
...@@ -4822,6 +4828,48 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data) ...@@ -4822,6 +4828,48 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
return err; return err;
} }
#ifdef CONFIG_QUOTA
static int ext4_statfs_project(struct super_block *sb,
kprojid_t projid, struct kstatfs *buf)
{
struct kqid qid;
struct dquot *dquot;
u64 limit;
u64 curblock;
qid = make_kqid_projid(projid);
dquot = dqget(sb, qid);
if (IS_ERR(dquot))
return PTR_ERR(dquot);
spin_lock(&dq_data_lock);
limit = (dquot->dq_dqb.dqb_bsoftlimit ?
dquot->dq_dqb.dqb_bsoftlimit :
dquot->dq_dqb.dqb_bhardlimit) >> sb->s_blocksize_bits;
if (limit && buf->f_blocks > limit) {
curblock = dquot->dq_dqb.dqb_curspace >> sb->s_blocksize_bits;
buf->f_blocks = limit;
buf->f_bfree = buf->f_bavail =
(buf->f_blocks > curblock) ?
(buf->f_blocks - curblock) : 0;
}
limit = dquot->dq_dqb.dqb_isoftlimit ?
dquot->dq_dqb.dqb_isoftlimit :
dquot->dq_dqb.dqb_ihardlimit;
if (limit && buf->f_files > limit) {
buf->f_files = limit;
buf->f_ffree =
(buf->f_files > dquot->dq_dqb.dqb_curinodes) ?
(buf->f_files - dquot->dq_dqb.dqb_curinodes) : 0;
}
spin_unlock(&dq_data_lock);
dqput(dquot);
return 0;
}
#endif
static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf) static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf)
{ {
struct super_block *sb = dentry->d_sb; struct super_block *sb = dentry->d_sb;
...@@ -4854,6 +4902,11 @@ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf) ...@@ -4854,6 +4902,11 @@ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf)
buf->f_fsid.val[0] = fsid & 0xFFFFFFFFUL; buf->f_fsid.val[0] = fsid & 0xFFFFFFFFUL;
buf->f_fsid.val[1] = (fsid >> 32) & 0xFFFFFFFFUL; buf->f_fsid.val[1] = (fsid >> 32) & 0xFFFFFFFFUL;
#ifdef CONFIG_QUOTA
if (ext4_test_inode_flag(dentry->d_inode, EXT4_INODE_PROJINHERIT) &&
sb_has_quota_limits_enabled(sb, PRJQUOTA))
ext4_statfs_project(sb, EXT4_I(dentry->d_inode)->i_projid, buf);
#endif
return 0; return 0;
} }
...@@ -5018,7 +5071,8 @@ static int ext4_quota_enable(struct super_block *sb, int type, int format_id, ...@@ -5018,7 +5071,8 @@ static int ext4_quota_enable(struct super_block *sb, int type, int format_id,
struct inode *qf_inode; struct inode *qf_inode;
unsigned long qf_inums[EXT4_MAXQUOTAS] = { unsigned long qf_inums[EXT4_MAXQUOTAS] = {
le32_to_cpu(EXT4_SB(sb)->s_es->s_usr_quota_inum), le32_to_cpu(EXT4_SB(sb)->s_es->s_usr_quota_inum),
le32_to_cpu(EXT4_SB(sb)->s_es->s_grp_quota_inum) le32_to_cpu(EXT4_SB(sb)->s_es->s_grp_quota_inum),
le32_to_cpu(EXT4_SB(sb)->s_es->s_prj_quota_inum)
}; };
BUG_ON(!ext4_has_feature_quota(sb)); BUG_ON(!ext4_has_feature_quota(sb));
...@@ -5046,7 +5100,8 @@ static int ext4_enable_quotas(struct super_block *sb) ...@@ -5046,7 +5100,8 @@ static int ext4_enable_quotas(struct super_block *sb)
int type, err = 0; int type, err = 0;
unsigned long qf_inums[EXT4_MAXQUOTAS] = { unsigned long qf_inums[EXT4_MAXQUOTAS] = {
le32_to_cpu(EXT4_SB(sb)->s_es->s_usr_quota_inum), le32_to_cpu(EXT4_SB(sb)->s_es->s_usr_quota_inum),
le32_to_cpu(EXT4_SB(sb)->s_es->s_grp_quota_inum) le32_to_cpu(EXT4_SB(sb)->s_es->s_grp_quota_inum),
le32_to_cpu(EXT4_SB(sb)->s_es->s_prj_quota_inum)
}; };
sb_dqopt(sb)->flags |= DQUOT_QUOTA_SYS_FILE; sb_dqopt(sb)->flags |= DQUOT_QUOTA_SYS_FILE;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册