Skip to content

Commit 9122eed

Browse files
Luis Henriquesidryomov
authored andcommitted
ceph: quota: report root dir quota usage in statfs
This commit changes statfs default behaviour when reporting usage statistics. Instead of using the overall filesystem usage, statfs now reports the quota for the filesystem root, if ceph.quota.max_bytes has been set for this inode. If quota hasn't been set, it falls back to the old statfs behaviour. A new mount option is also added ('noquotadf') to disable this behaviour. Signed-off-by: Luis Henriques <[email protected]> Reviewed-by: "Yan, Zheng" <[email protected]> Signed-off-by: Ilya Dryomov <[email protected]>
1 parent d557c48 commit 9122eed

File tree

4 files changed

+87
-3
lines changed

4 files changed

+87
-3
lines changed

Documentation/filesystems/ceph.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,10 @@ Mount Options
149149
noasyncreaddir
150150
Do not use the dcache as above for readdir.
151151

152+
noquotadf
153+
Report overall filesystem usage in statfs instead of using the root
154+
directory quota.
155+
152156
More Information
153157
================
154158

fs/ceph/quota.c

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
* along with this program; if not, see <http://www.gnu.org/licenses/>.
1919
*/
2020

21+
#include <linux/statfs.h>
22+
2123
#include "super.h"
2224
#include "mds_client.h"
2325

@@ -303,3 +305,57 @@ bool ceph_quota_is_max_bytes_approaching(struct inode *inode, loff_t newsize)
303305
return check_quota_exceeded(inode, QUOTA_CHECK_MAX_BYTES_APPROACHING_OP,
304306
(newsize - size));
305307
}
308+
309+
/*
310+
* ceph_quota_update_statfs - if root has quota update statfs with quota status
311+
* @fsc: filesystem client instance
312+
* @buf: statfs to update
313+
*
314+
* If the mounted filesystem root has max_bytes quota set, update the filesystem
315+
* statistics with the quota status.
316+
*
317+
* This function returns true if the stats have been updated, false otherwise.
318+
*/
319+
bool ceph_quota_update_statfs(struct ceph_fs_client *fsc, struct kstatfs *buf)
320+
{
321+
struct ceph_mds_client *mdsc = fsc->mdsc;
322+
struct ceph_inode_info *ci;
323+
struct ceph_snap_realm *realm;
324+
struct inode *in;
325+
u64 total = 0, used, free;
326+
bool is_updated = false;
327+
328+
down_read(&mdsc->snap_rwsem);
329+
realm = get_quota_realm(mdsc, d_inode(fsc->sb->s_root));
330+
up_read(&mdsc->snap_rwsem);
331+
if (!realm)
332+
return false;
333+
334+
spin_lock(&realm->inodes_with_caps_lock);
335+
in = realm->inode ? igrab(realm->inode) : NULL;
336+
spin_unlock(&realm->inodes_with_caps_lock);
337+
if (in) {
338+
ci = ceph_inode(in);
339+
spin_lock(&ci->i_ceph_lock);
340+
if (ci->i_max_bytes) {
341+
total = ci->i_max_bytes >> CEPH_BLOCK_SHIFT;
342+
used = ci->i_rbytes >> CEPH_BLOCK_SHIFT;
343+
/* It is possible for a quota to be exceeded.
344+
* Report 'zero' in that case
345+
*/
346+
free = total > used ? total - used : 0;
347+
}
348+
spin_unlock(&ci->i_ceph_lock);
349+
if (total) {
350+
buf->f_blocks = total;
351+
buf->f_bfree = free;
352+
buf->f_bavail = free;
353+
is_updated = true;
354+
}
355+
iput(in);
356+
}
357+
ceph_put_snap_realm(mdsc, realm);
358+
359+
return is_updated;
360+
}
361+

fs/ceph/super.c

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,18 @@ static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf)
7676
*/
7777
buf->f_bsize = 1 << CEPH_BLOCK_SHIFT;
7878
buf->f_frsize = 1 << CEPH_BLOCK_SHIFT;
79-
buf->f_blocks = le64_to_cpu(st.kb) >> (CEPH_BLOCK_SHIFT-10);
80-
buf->f_bfree = le64_to_cpu(st.kb_avail) >> (CEPH_BLOCK_SHIFT-10);
81-
buf->f_bavail = le64_to_cpu(st.kb_avail) >> (CEPH_BLOCK_SHIFT-10);
79+
80+
/*
81+
* By default use root quota for stats; fallback to overall filesystem
82+
* usage if using 'noquotadf' mount option or if the root dir doesn't
83+
* have max_bytes quota set.
84+
*/
85+
if (ceph_test_mount_opt(fsc, NOQUOTADF) ||
86+
!ceph_quota_update_statfs(fsc, buf)) {
87+
buf->f_blocks = le64_to_cpu(st.kb) >> (CEPH_BLOCK_SHIFT-10);
88+
buf->f_bfree = le64_to_cpu(st.kb_avail) >> (CEPH_BLOCK_SHIFT-10);
89+
buf->f_bavail = le64_to_cpu(st.kb_avail) >> (CEPH_BLOCK_SHIFT-10);
90+
}
8291

8392
buf->f_files = le64_to_cpu(st.num_objects);
8493
buf->f_ffree = -1;
@@ -151,6 +160,8 @@ enum {
151160
Opt_acl,
152161
#endif
153162
Opt_noacl,
163+
Opt_quotadf,
164+
Opt_noquotadf,
154165
};
155166

156167
static match_table_t fsopt_tokens = {
@@ -187,6 +198,8 @@ static match_table_t fsopt_tokens = {
187198
{Opt_acl, "acl"},
188199
#endif
189200
{Opt_noacl, "noacl"},
201+
{Opt_quotadf, "quotadf"},
202+
{Opt_noquotadf, "noquotadf"},
190203
{-1, NULL}
191204
};
192205

@@ -334,6 +347,12 @@ static int parse_fsopt_token(char *c, void *private)
334347
case Opt_norequire_active_mds:
335348
fsopt->flags |= CEPH_MOUNT_OPT_MOUNTWAIT;
336349
break;
350+
case Opt_quotadf:
351+
fsopt->flags &= ~CEPH_MOUNT_OPT_NOQUOTADF;
352+
break;
353+
case Opt_noquotadf:
354+
fsopt->flags |= CEPH_MOUNT_OPT_NOQUOTADF;
355+
break;
337356
#ifdef CONFIG_CEPH_FS_POSIX_ACL
338357
case Opt_acl:
339358
fsopt->sb_flags |= SB_POSIXACL;
@@ -520,6 +539,8 @@ static int ceph_show_options(struct seq_file *m, struct dentry *root)
520539
}
521540
if (fsopt->flags & CEPH_MOUNT_OPT_NOPOOLPERM)
522541
seq_puts(m, ",nopoolperm");
542+
if (fsopt->flags & CEPH_MOUNT_OPT_NOQUOTADF)
543+
seq_puts(m, ",noquotadf");
523544

524545
#ifdef CONFIG_CEPH_FS_POSIX_ACL
525546
if (fsopt->sb_flags & SB_POSIXACL)

fs/ceph/super.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#define CEPH_MOUNT_OPT_FSCACHE (1<<10) /* use fscache */
4040
#define CEPH_MOUNT_OPT_NOPOOLPERM (1<<11) /* no pool permission check */
4141
#define CEPH_MOUNT_OPT_MOUNTWAIT (1<<12) /* mount waits if no mds is up */
42+
#define CEPH_MOUNT_OPT_NOQUOTADF (1<<13) /* no root dir quota in statfs */
4243

4344
#define CEPH_MOUNT_OPT_DEFAULT CEPH_MOUNT_OPT_DCACHE
4445

@@ -1104,5 +1105,7 @@ extern bool ceph_quota_is_max_bytes_exceeded(struct inode *inode,
11041105
loff_t newlen);
11051106
extern bool ceph_quota_is_max_bytes_approaching(struct inode *inode,
11061107
loff_t newlen);
1108+
extern bool ceph_quota_update_statfs(struct ceph_fs_client *fsc,
1109+
struct kstatfs *buf);
11071110

11081111
#endif /* _FS_CEPH_SUPER_H */

0 commit comments

Comments
 (0)