|
@@ -1097,8 +1097,8 @@ static int bdev_try_to_free_page(struct super_block *sb, struct page *page,
|
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_QUOTA
|
|
|
-#define QTYPE2NAME(t) ((t) == USRQUOTA ? "user" : "group")
|
|
|
-#define QTYPE2MOPT(on, t) ((t) == USRQUOTA?((on)##USRJQUOTA):((on)##GRPJQUOTA))
|
|
|
+static char *quotatypes[] = INITQFNAMES;
|
|
|
+#define QTYPE2NAME(t) (quotatypes[t])
|
|
|
|
|
|
static int ext4_write_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)
|
|
|
"without CONFIG_QUOTA");
|
|
|
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 */
|
|
|
return 1;
|
|
|
}
|
|
@@ -3686,7 +3692,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|
|
sb->s_qcop = &dquot_quotactl_sysfile_ops;
|
|
|
else
|
|
|
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
|
|
|
memcpy(sb->s_uuid, es->s_uuid, sizeof(es->s_uuid));
|
|
|
|
|
@@ -4822,6 +4828,48 @@ restore_opts:
|
|
|
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)
|
|
|
{
|
|
|
struct super_block *sb = dentry->d_sb;
|
|
@@ -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[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;
|
|
|
}
|
|
|
|
|
@@ -5018,7 +5071,8 @@ static int ext4_quota_enable(struct super_block *sb, int type, int format_id,
|
|
|
struct inode *qf_inode;
|
|
|
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_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));
|
|
@@ -5046,7 +5100,8 @@ static int ext4_enable_quotas(struct super_block *sb)
|
|
|
int type, err = 0;
|
|
|
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_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;
|