Re: [RFC PATCH v2 1/1] quota: report root dir quota usage in statfs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




> On 31 Jan 2018, at 18:53, Luis Henriques <lhenriques@xxxxxxxx> 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@xxxxxxxx>
> ---
> 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

--
To unsubscribe from this list: send the line "unsubscribe ceph-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [CEPH Users]     [Ceph Large]     [Information on CEPH]     [Linux BTRFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux