All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH v2 0/1] quota: report root dir quota usage in statfs
@ 2018-01-31 10:53 Luis Henriques
  2018-01-31 10:53 ` [RFC PATCH v2 1/1] " Luis Henriques
  0 siblings, 1 reply; 3+ messages in thread
From: Luis Henriques @ 2018-01-31 10:53 UTC (permalink / raw)
  To: ceph-devel; +Cc: Yan, Zheng, Luis Henriques

Following this email I'm sending a patch that modifies the statfs
behaviour in cephfs kernel client so that, by default, it shows the
quota statistics for the root directory instead of the overall
filesystem usage.

I'm sending this patch as an RFC because:

 * I'm not sure people really want to have this behaviour -- this is the
   default for the ceph-fuse client, so I just wanted to have a similar
   behaviour in the kernel client.
 * Showing quota usage by default may not be the correct option,
   although (again!) this is what the ceph-fuse client does.

Anyway, there's also a new mount option ('noquotadf') to revert to the
old statfs even if the root dir has max_bytes set.

Just for reference, this statfs behaviour was added to the ceph-fuse
client by commit b6d2b6d1a519 ("client: report root's quota in
statfs").

** Changes since v1 **

- Rework after review from Yan, Zheng:
  * Added '()' to expression
  * Added an extra 'quotadf' mount option

Luis Henriques (1):
  quota: report root dir quota usage in statfs

 Documentation/filesystems/ceph.txt |  4 +++
 fs/ceph/quota.c                    | 56 ++++++++++++++++++++++++++++++++++++++
 fs/ceph/super.c                    | 29 ++++++++++++++++++--
 fs/ceph/super.h                    |  3 ++
 4 files changed, 89 insertions(+), 3 deletions(-)


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [RFC PATCH v2 1/1] quota: report root dir quota usage in statfs
  2018-01-31 10:53 [RFC PATCH v2 0/1] quota: report root dir quota usage in statfs Luis Henriques
@ 2018-01-31 10:53 ` Luis Henriques
  2018-02-01  3:55   ` Yan, Zheng
  0 siblings, 1 reply; 3+ messages in thread
From: Luis Henriques @ 2018-01-31 10:53 UTC (permalink / raw)
  To: ceph-devel; +Cc: Yan, Zheng, Luis Henriques

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 <lhenriques@suse.com>
---
 Documentation/filesystems/ceph.txt |  4 +++
 fs/ceph/quota.c                    | 56 ++++++++++++++++++++++++++++++++++++++
 fs/ceph/super.c                    | 29 ++++++++++++++++++--
 fs/ceph/super.h                    |  3 ++
 4 files changed, 89 insertions(+), 3 deletions(-)

diff --git a/Documentation/filesystems/ceph.txt b/Documentation/filesystems/ceph.txt
index 094772481263..d7f011ddc150 100644
--- a/Documentation/filesystems/ceph.txt
+++ b/Documentation/filesystems/ceph.txt
@@ -149,6 +149,10 @@ Mount Options
   noasyncreaddir
 	Do not use the dcache as above for readdir.
 
+  noquotadf
+        Report overall filesystem usage in statfs instead of using the root
+        directory quota.
+
 More Information
 ================
 
diff --git a/fs/ceph/quota.c b/fs/ceph/quota.c
index 588744b4665f..242bfa5c0539 100644
--- a/fs/ceph/quota.c
+++ b/fs/ceph/quota.c
@@ -18,6 +18,8 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/statfs.h>
+
 #include "super.h"
 #include "mds_client.h"
 
@@ -303,3 +305,57 @@ bool ceph_quota_is_max_bytes_approaching(struct inode *inode, loff_t newsize)
 	return check_quota_exceeded(inode, QUOTA_CHECK_MAX_BYTES_APPROACHING_OP,
 				    (newsize - size));
 }
+
+/*
+ * ceph_quota_update_statfs - if root has quota update statfs with quota status
+ * @fsc:	filesystem client instance
+ * @buf:	statfs to update
+ *
+ * If the mounted filesystem root has max_bytes quota set, update the filesystem
+ * statistics with the quota status.
+ *
+ * This function returns true if the stats have been updated, false otherwise.
+ */
+bool ceph_quota_update_statfs(struct ceph_fs_client *fsc, struct kstatfs *buf)
+{
+	struct ceph_mds_client *mdsc = fsc->mdsc;
+	struct ceph_inode_info *ci;
+	struct ceph_snap_realm *realm;
+	struct inode *in;
+	u64 total = 0, used, free;
+	bool is_updated = false;
+
+	down_read(&mdsc->snap_rwsem);
+	realm = get_quota_realm(mdsc, d_inode(fsc->sb->s_root));
+	up_read(&mdsc->snap_rwsem);
+	if (!realm)
+		return false;
+
+	spin_lock(&realm->inodes_with_caps_lock);
+	in = realm->inode ? igrab(realm->inode) : NULL;
+	spin_unlock(&realm->inodes_with_caps_lock);
+	if (in) {
+		ci = ceph_inode(in);
+		spin_lock(&ci->i_ceph_lock);
+		if (ci->i_max_bytes) {
+			total = ci->i_max_bytes >> CEPH_BLOCK_SHIFT;
+			used = ci->i_rbytes >> CEPH_BLOCK_SHIFT;
+			/* It is possible for a quota to be exceeded.
+			 * Report 'zero' in that case
+			 */
+			free = total > used ? total - used : 0;
+		}
+		spin_unlock(&ci->i_ceph_lock);
+		if (total) {
+			buf->f_blocks = total;
+			buf->f_bfree = free;
+			buf->f_bavail = free;
+			is_updated = true;
+		}
+		iput(in);
+	}
+	ceph_put_snap_realm(mdsc, realm);
+
+	return is_updated;
+}
+
diff --git a/fs/ceph/super.c b/fs/ceph/super.c
index 9b4929420c13..5062d52f161e 100644
--- a/fs/ceph/super.c
+++ b/fs/ceph/super.c
@@ -76,9 +76,18 @@ static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf)
 	 */
 	buf->f_bsize = 1 << CEPH_BLOCK_SHIFT;
 	buf->f_frsize = 1 << CEPH_BLOCK_SHIFT;
-	buf->f_blocks = le64_to_cpu(st.kb) >> (CEPH_BLOCK_SHIFT-10);
-	buf->f_bfree = le64_to_cpu(st.kb_avail) >> (CEPH_BLOCK_SHIFT-10);
-	buf->f_bavail = le64_to_cpu(st.kb_avail) >> (CEPH_BLOCK_SHIFT-10);
+
+	/*
+	 * By default use root quota for stats; fallback to overall filesystem
+	 * usage if using 'noquotadf' mount option or if the root dir doesn't
+	 * have max_bytes quota set.
+	 */
+	if ((fsc->mount_options->flags & CEPH_MOUNT_OPT_NOQUOTADF) ||
+	    !ceph_quota_update_statfs(fsc, buf)) {
+		buf->f_blocks = le64_to_cpu(st.kb) >> (CEPH_BLOCK_SHIFT-10);
+		buf->f_bfree = le64_to_cpu(st.kb_avail) >> (CEPH_BLOCK_SHIFT-10);
+		buf->f_bavail = le64_to_cpu(st.kb_avail) >> (CEPH_BLOCK_SHIFT-10);
+	}
 
 	buf->f_files = le64_to_cpu(st.num_objects);
 	buf->f_ffree = -1;
@@ -151,6 +160,8 @@ enum {
 	Opt_acl,
 #endif
 	Opt_noacl,
+	Opt_quotadf,
+	Opt_noquotadf,
 };
 
 static match_table_t fsopt_tokens = {
@@ -187,6 +198,8 @@ static match_table_t fsopt_tokens = {
 	{Opt_acl, "acl"},
 #endif
 	{Opt_noacl, "noacl"},
+	{Opt_quotadf, "quotadf"},
+	{Opt_noquotadf, "noquotadf"},
 	{-1, NULL}
 };
 
@@ -328,6 +341,12 @@ static int parse_fsopt_token(char *c, void *private)
 	case Opt_norequire_active_mds:
 		fsopt->flags |= CEPH_MOUNT_OPT_MOUNTWAIT;
 		break;
+	case Opt_quotadf:
+		fsopt->flags &= ~CEPH_MOUNT_OPT_NOQUOTADF;
+		break;
+	case Opt_noquotadf:
+		fsopt->flags |= CEPH_MOUNT_OPT_NOQUOTADF;
+		break;
 #ifdef CONFIG_CEPH_FS_POSIX_ACL
 	case Opt_acl:
 		fsopt->sb_flags |= SB_POSIXACL;
@@ -517,6 +536,10 @@ static int ceph_show_options(struct seq_file *m, struct dentry *root)
 	}
 	if (fsopt->flags & CEPH_MOUNT_OPT_NOPOOLPERM)
 		seq_puts(m, ",nopoolperm");
+	if (fsopt->flags & CEPH_MOUNT_OPT_NOQUOTADF)
+		seq_puts(m, ",noquotadf");
+	else
+		seq_puts(m, ",quotadf");
 
 #ifdef CONFIG_CEPH_FS_POSIX_ACL
 	if (fsopt->sb_flags & SB_POSIXACL)
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index 92d189074008..60ed9399fe73 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -39,6 +39,7 @@
 #define CEPH_MOUNT_OPT_FSCACHE         (1<<10) /* use fscache */
 #define CEPH_MOUNT_OPT_NOPOOLPERM      (1<<11) /* no pool permission check */
 #define CEPH_MOUNT_OPT_MOUNTWAIT       (1<<12) /* mount waits if no mds is up */
+#define CEPH_MOUNT_OPT_NOQUOTADF       (1<<13) /* no root dir quota in statfs */
 
 #define CEPH_MOUNT_OPT_DEFAULT    CEPH_MOUNT_OPT_DCACHE
 
@@ -1111,5 +1112,7 @@ extern bool ceph_quota_is_max_bytes_exceeded(struct inode *inode,
 					     loff_t newlen);
 extern bool ceph_quota_is_max_bytes_approaching(struct inode *inode,
 						loff_t newlen);
+extern bool ceph_quota_update_statfs(struct ceph_fs_client *fsc,
+				     struct kstatfs *buf);
 
 #endif /* _FS_CEPH_SUPER_H */

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [RFC PATCH v2 1/1] quota: report root dir quota usage in statfs
  2018-01-31 10:53 ` [RFC PATCH v2 1/1] " Luis Henriques
@ 2018-02-01  3:55   ` Yan, Zheng
  0 siblings, 0 replies; 3+ messages in thread
From: Yan, Zheng @ 2018-02-01  3:55 UTC (permalink / raw)
  To: Luis Henriques; +Cc: ceph-devel



> On 31 Jan 2018, at 18:53, Luis Henriques <lhenriques@suse.com> wrote:
> 
> 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 <lhenriques@suse.com>
> ---
> Documentation/filesystems/ceph.txt |  4 +++
> fs/ceph/quota.c                    | 56 ++++++++++++++++++++++++++++++++++++++
> fs/ceph/super.c                    | 29 ++++++++++++++++++--
> fs/ceph/super.h                    |  3 ++
> 4 files changed, 89 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/filesystems/ceph.txt b/Documentation/filesystems/ceph.txt
> index 094772481263..d7f011ddc150 100644
> --- a/Documentation/filesystems/ceph.txt
> +++ b/Documentation/filesystems/ceph.txt
> @@ -149,6 +149,10 @@ Mount Options
>   noasyncreaddir
> 	Do not use the dcache as above for readdir.
> 
> +  noquotadf
> +        Report overall filesystem usage in statfs instead of using the root
> +        directory quota.
> +
> More Information
> ================
> 
> diff --git a/fs/ceph/quota.c b/fs/ceph/quota.c
> index 588744b4665f..242bfa5c0539 100644
> --- a/fs/ceph/quota.c
> +++ b/fs/ceph/quota.c
> @@ -18,6 +18,8 @@
>  * along with this program; if not, see <http://www.gnu.org/licenses/>.
>  */
> 
> +#include <linux/statfs.h>
> +
> #include "super.h"
> #include "mds_client.h"
> 
> @@ -303,3 +305,57 @@ bool ceph_quota_is_max_bytes_approaching(struct inode *inode, loff_t newsize)
> 	return check_quota_exceeded(inode, QUOTA_CHECK_MAX_BYTES_APPROACHING_OP,
> 				    (newsize - size));
> }
> +
> +/*
> + * ceph_quota_update_statfs - if root has quota update statfs with quota status
> + * @fsc:	filesystem client instance
> + * @buf:	statfs to update
> + *
> + * If the mounted filesystem root has max_bytes quota set, update the filesystem
> + * statistics with the quota status.
> + *
> + * This function returns true if the stats have been updated, false otherwise.
> + */
> +bool ceph_quota_update_statfs(struct ceph_fs_client *fsc, struct kstatfs *buf)
> +{
> +	struct ceph_mds_client *mdsc = fsc->mdsc;
> +	struct ceph_inode_info *ci;
> +	struct ceph_snap_realm *realm;
> +	struct inode *in;
> +	u64 total = 0, used, free;
> +	bool is_updated = false;
> +
> +	down_read(&mdsc->snap_rwsem);
> +	realm = get_quota_realm(mdsc, d_inode(fsc->sb->s_root));
> +	up_read(&mdsc->snap_rwsem);
> +	if (!realm)
> +		return false;
> +
> +	spin_lock(&realm->inodes_with_caps_lock);
> +	in = realm->inode ? igrab(realm->inode) : NULL;
> +	spin_unlock(&realm->inodes_with_caps_lock);
> +	if (in) {
> +		ci = ceph_inode(in);
> +		spin_lock(&ci->i_ceph_lock);
> +		if (ci->i_max_bytes) {
> +			total = ci->i_max_bytes >> CEPH_BLOCK_SHIFT;
> +			used = ci->i_rbytes >> CEPH_BLOCK_SHIFT;
> +			/* It is possible for a quota to be exceeded.
> +			 * Report 'zero' in that case
> +			 */
> +			free = total > used ? total - used : 0;
> +		}
> +		spin_unlock(&ci->i_ceph_lock);
> +		if (total) {
> +			buf->f_blocks = total;
> +			buf->f_bfree = free;
> +			buf->f_bavail = free;
> +			is_updated = true;
> +		}
> +		iput(in);
> +	}
> +	ceph_put_snap_realm(mdsc, realm);
> +
> +	return is_updated;
> +}
> +
> diff --git a/fs/ceph/super.c b/fs/ceph/super.c
> index 9b4929420c13..5062d52f161e 100644
> --- a/fs/ceph/super.c
> +++ b/fs/ceph/super.c
> @@ -76,9 +76,18 @@ static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf)
> 	 */
> 	buf->f_bsize = 1 << CEPH_BLOCK_SHIFT;
> 	buf->f_frsize = 1 << CEPH_BLOCK_SHIFT;
> -	buf->f_blocks = le64_to_cpu(st.kb) >> (CEPH_BLOCK_SHIFT-10);
> -	buf->f_bfree = le64_to_cpu(st.kb_avail) >> (CEPH_BLOCK_SHIFT-10);
> -	buf->f_bavail = le64_to_cpu(st.kb_avail) >> (CEPH_BLOCK_SHIFT-10);
> +
> +	/*
> +	 * By default use root quota for stats; fallback to overall filesystem
> +	 * usage if using 'noquotadf' mount option or if the root dir doesn't
> +	 * have max_bytes quota set.
> +	 */
> +	if ((fsc->mount_options->flags & CEPH_MOUNT_OPT_NOQUOTADF) ||
> +	    !ceph_quota_update_statfs(fsc, buf)) {
> +		buf->f_blocks = le64_to_cpu(st.kb) >> (CEPH_BLOCK_SHIFT-10);
> +		buf->f_bfree = le64_to_cpu(st.kb_avail) >> (CEPH_BLOCK_SHIFT-10);
> +		buf->f_bavail = le64_to_cpu(st.kb_avail) >> (CEPH_BLOCK_SHIFT-10);
> +	}
> 
> 	buf->f_files = le64_to_cpu(st.num_objects);
> 	buf->f_ffree = -1;
> @@ -151,6 +160,8 @@ enum {
> 	Opt_acl,
> #endif
> 	Opt_noacl,
> +	Opt_quotadf,
> +	Opt_noquotadf,
> };
> 
> static match_table_t fsopt_tokens = {
> @@ -187,6 +198,8 @@ static match_table_t fsopt_tokens = {
> 	{Opt_acl, "acl"},
> #endif
> 	{Opt_noacl, "noacl"},
> +	{Opt_quotadf, "quotadf"},
> +	{Opt_noquotadf, "noquotadf"},
> 	{-1, NULL}
> };
> 
> @@ -328,6 +341,12 @@ static int parse_fsopt_token(char *c, void *private)
> 	case Opt_norequire_active_mds:
> 		fsopt->flags |= CEPH_MOUNT_OPT_MOUNTWAIT;
> 		break;
> +	case Opt_quotadf:
> +		fsopt->flags &= ~CEPH_MOUNT_OPT_NOQUOTADF;
> +		break;
> +	case Opt_noquotadf:
> +		fsopt->flags |= CEPH_MOUNT_OPT_NOQUOTADF;
> +		break;
> #ifdef CONFIG_CEPH_FS_POSIX_ACL
> 	case Opt_acl:
> 		fsopt->sb_flags |= SB_POSIXACL;
> @@ -517,6 +536,10 @@ static int ceph_show_options(struct seq_file *m, struct dentry *root)
> 	}
> 	if (fsopt->flags & CEPH_MOUNT_OPT_NOPOOLPERM)
> 		seq_puts(m, ",nopoolperm");
> +	if (fsopt->flags & CEPH_MOUNT_OPT_NOQUOTADF)
> +		seq_puts(m, ",noquotadf");
> +	else
> +		seq_puts(m, ",quotadf");
> 
> #ifdef CONFIG_CEPH_FS_POSIX_ACL
> 	if (fsopt->sb_flags & SB_POSIXACL)
> diff --git a/fs/ceph/super.h b/fs/ceph/super.h
> index 92d189074008..60ed9399fe73 100644
> --- a/fs/ceph/super.h
> +++ b/fs/ceph/super.h
> @@ -39,6 +39,7 @@
> #define CEPH_MOUNT_OPT_FSCACHE         (1<<10) /* use fscache */
> #define CEPH_MOUNT_OPT_NOPOOLPERM      (1<<11) /* no pool permission check */
> #define CEPH_MOUNT_OPT_MOUNTWAIT       (1<<12) /* mount waits if no mds is up */
> +#define CEPH_MOUNT_OPT_NOQUOTADF       (1<<13) /* no root dir quota in statfs */
> 
> #define CEPH_MOUNT_OPT_DEFAULT    CEPH_MOUNT_OPT_DCACHE
> 
> @@ -1111,5 +1112,7 @@ extern bool ceph_quota_is_max_bytes_exceeded(struct inode *inode,
> 					     loff_t newlen);
> extern bool ceph_quota_is_max_bytes_approaching(struct inode *inode,
> 						loff_t newlen);
> +extern bool ceph_quota_update_statfs(struct ceph_fs_client *fsc,
> +				     struct kstatfs *buf);
> 
> #endif /* _FS_CEPH_SUPER_H */

Applied, thanks

Yan, Zheng


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2018-02-01  3:56 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-31 10:53 [RFC PATCH v2 0/1] quota: report root dir quota usage in statfs Luis Henriques
2018-01-31 10:53 ` [RFC PATCH v2 1/1] " Luis Henriques
2018-02-01  3:55   ` Yan, Zheng

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.