Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fb18a575 authored by Luis Henriques's avatar Luis Henriques Committed by Ilya Dryomov
Browse files

ceph: quota: add initial infrastructure to support cephfs quotas

This patch adds the infrastructure required to support cephfs quotas as it
is currently implemented in the ceph fuse client.  Cephfs quotas can be
set on any directory, and can restrict the number of bytes or the number
of files stored beneath that point in the directory hierarchy.

Quotas are set using the extended attributes 'ceph.quota.max_files' and
'ceph.quota.max_bytes', and can be removed by setting these attributes to
'0'.

Link: http://tracker.ceph.com/issues/22372


Signed-off-by: default avatarLuis Henriques <lhenriques@suse.com>
Reviewed-by: default avatar"Yan, Zheng" <zyan@redhat.com>
Signed-off-by: default avatarIlya Dryomov <idryomov@gmail.com>
parent 08a79102
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -62,6 +62,18 @@ subdirectories, and a summation of all nested file sizes. This makes
the identification of large disk space consumers relatively quick, as
no 'du' or similar recursive scan of the file system is required.

Finally, Ceph also allows quotas to be set on any directory in the system.
The quota can restrict the number of bytes or the number of files stored
beneath that point in the directory hierarchy.  Quotas can be set using
extended attributes 'ceph.quota.max_files' and 'ceph.quota.max_bytes', eg:

 setfattr -n ceph.quota.max_bytes -v 100000000 /some/dir
 getfattr -n ceph.quota.max_bytes /some/dir

A limitation of the current quotas implementation is that it relies on the
cooperation of the client mounting the file system to stop writers when a
limit is reached.  A modified or adversarial client cannot be prevented
from writing as much data as it needs.

Mount Syntax
============
+1 −1
Original line number Diff line number Diff line
@@ -6,7 +6,7 @@
obj-$(CONFIG_CEPH_FS) += ceph.o

ceph-y := super.o inode.o dir.o file.o locks.o addr.o ioctl.o \
	export.o caps.o snap.o xattr.o \
	export.o caps.o snap.o xattr.o quota.o \
	mds_client.o mdsmap.o strings.o ceph_frag.o \
	debugfs.o

+6 −0
Original line number Diff line number Diff line
@@ -441,6 +441,9 @@ struct inode *ceph_alloc_inode(struct super_block *sb)
	atomic64_set(&ci->i_complete_seq[1], 0);
	ci->i_symlink = NULL;

	ci->i_max_bytes = 0;
	ci->i_max_files = 0;

	memset(&ci->i_dir_layout, 0, sizeof(ci->i_dir_layout));
	RCU_INIT_POINTER(ci->i_layout.pool_ns, NULL);

@@ -790,6 +793,9 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
	inode->i_rdev = le32_to_cpu(info->rdev);
	inode->i_blkbits = fls(le32_to_cpu(info->layout.fl_stripe_unit)) - 1;

	ci->i_max_bytes = iinfo->max_bytes;
	ci->i_max_files = iinfo->max_files;

	if ((new_version || (new_issued & CEPH_CAP_AUTH_SHARED)) &&
	    (issued & CEPH_CAP_AUTH_EXCL) == 0) {
		inode->i_mode = le32_to_cpu(info->mode);
+23 −0
Original line number Diff line number Diff line
@@ -100,6 +100,26 @@ static int parse_reply_info_in(void **p, void *end,
	} else
		info->inline_version = CEPH_INLINE_NONE;

	if (features & CEPH_FEATURE_MDS_QUOTA) {
		u8 struct_v, struct_compat;
		u32 struct_len;

		/*
		 * both struct_v and struct_compat are expected to be >= 1
		 */
		ceph_decode_8_safe(p, end, struct_v, bad);
		ceph_decode_8_safe(p, end, struct_compat, bad);
		if (!struct_v || !struct_compat)
			goto bad;
		ceph_decode_32_safe(p, end, struct_len, bad);
		ceph_decode_need(p, end, struct_len, bad);
		ceph_decode_64_safe(p, end, info->max_bytes, bad);
		ceph_decode_64_safe(p, end, info->max_files, bad);
	} else {
		info->max_bytes = 0;
		info->max_files = 0;
	}

	info->pool_ns_len = 0;
	info->pool_ns_data = NULL;
	if (features & CEPH_FEATURE_FS_FILE_LAYOUT_V2) {
@@ -4082,6 +4102,9 @@ static void dispatch(struct ceph_connection *con, struct ceph_msg *msg)
	case CEPH_MSG_CLIENT_LEASE:
		handle_lease(mdsc, s, msg);
		break;
	case CEPH_MSG_CLIENT_QUOTA:
		ceph_handle_quota(mdsc, s, msg);
		break;

	default:
		pr_err("received unknown message type %d %s\n", type,
+2 −0
Original line number Diff line number Diff line
@@ -49,6 +49,8 @@ struct ceph_mds_reply_info_in {
	char *inline_data;
	u32 pool_ns_len;
	char *pool_ns_data;
	u64 max_bytes;
	u64 max_files;
};

struct ceph_mds_reply_dir_entry {
Loading