@@ -1079,7 +1079,7 @@ static int check_owner(int type, int id)
return 0;
}
-static int quotactl_ioctl(struct ll_sb_info *sbi, struct if_quotactl *qctl)
+int quotactl_ioctl(struct ll_sb_info *sbi, struct if_quotactl *qctl)
{
int cmd = qctl->qc_cmd;
int type = qctl->qc_type;
@@ -996,6 +996,7 @@ int ll_dir_read(struct inode *inode, u64 *ppos, struct md_op_data *op_data,
struct page *ll_get_dir_page(struct inode *dir, struct md_op_data *op_data,
u64 offset);
void ll_release_page(struct inode *inode, struct page *page, bool remove);
+int quotactl_ioctl(struct ll_sb_info *sbi, struct if_quotactl *qctl);
enum get_default_layout_type {
GET_DEFAULT_LAYOUT_ROOT = 1,
@@ -2137,6 +2137,53 @@ int ll_statfs_internal(struct ll_sb_info *sbi, struct obd_statfs *osfs,
return rc;
}
+static int ll_statfs_project(struct inode *inode, struct kstatfs *sfs)
+{
+ struct if_quotactl qctl = {
+ .qc_cmd = LUSTRE_Q_GETQUOTA,
+ .qc_type = PRJQUOTA,
+ .qc_valid = QC_GENERAL,
+ };
+ u64 limit, curblock;
+ int ret;
+
+ qctl.qc_id = ll_i2info(inode)->lli_projid;
+ ret = quotactl_ioctl(ll_i2sbi(inode), &qctl);
+ if (ret) {
+ /* ignore errors if project ID does not have
+ * a quota limit or feature unsupported.
+ */
+ if (ret == -ESRCH || ret == -EOPNOTSUPP)
+ ret = 0;
+ return ret;
+ }
+
+ limit = ((qctl.qc_dqblk.dqb_bsoftlimit ?
+ qctl.qc_dqblk.dqb_bsoftlimit :
+ qctl.qc_dqblk.dqb_bhardlimit) * 1024) / sfs->f_bsize;
+ if (limit && sfs->f_blocks > limit) {
+ curblock = (qctl.qc_dqblk.dqb_curspace +
+ sfs->f_bsize - 1) / sfs->f_bsize;
+ sfs->f_blocks = limit;
+ sfs->f_bavail =
+ (sfs->f_blocks > curblock) ?
+ (sfs->f_blocks - curblock) : 0;
+ sfs->f_bfree = sfs->f_bavail;
+ }
+
+ limit = qctl.qc_dqblk.dqb_isoftlimit ?
+ qctl.qc_dqblk.dqb_isoftlimit :
+ qctl.qc_dqblk.dqb_ihardlimit;
+ if (limit && sfs->f_files > limit) {
+ sfs->f_files = limit;
+ sfs->f_ffree = (sfs->f_files >
+ qctl.qc_dqblk.dqb_curinodes) ?
+ (sfs->f_files - qctl.qc_dqblk.dqb_curinodes) : 0;
+ }
+
+ return 0;
+}
+
int ll_statfs(struct dentry *de, struct kstatfs *sfs)
{
struct super_block *sb = de->d_sb;
@@ -2174,6 +2221,8 @@ int ll_statfs(struct dentry *de, struct kstatfs *sfs)
sfs->f_bavail = osfs.os_bavail;
sfs->f_fsid.val[0] = (u32)fsid;
sfs->f_fsid.val[1] = (u32)(fsid >> 32);
+ if (ll_i2info(de->d_inode)->lli_projid)
+ return ll_statfs_project(de->d_inode, sfs);
ll_stats_ops_tally(ll_s2sbi(sb), LPROC_LL_STATFS,
ktime_us_delta(ktime_get(), kstart));
@@ -1043,9 +1043,9 @@ struct obd_dqinfo {
/* XXX: same as if_dqblk struct in kernel, plus one padding */
struct obd_dqblk {
- __u64 dqb_bhardlimit;
- __u64 dqb_bsoftlimit;
- __u64 dqb_curspace;
+ __u64 dqb_bhardlimit; /* kbytes unit */
+ __u64 dqb_bsoftlimit; /* kbytes unit */
+ __u64 dqb_curspace; /* bytes unit */
__u64 dqb_ihardlimit;
__u64 dqb_isoftlimit;
__u64 dqb_curinodes;