diff options
author | Luis Henriques <lhenriques@suse.com> | 2018-01-05 05:47:21 -0500 |
---|---|---|
committer | Ilya Dryomov <idryomov@gmail.com> | 2018-04-02 05:17:52 -0400 |
commit | 2b83845f8bd711e66e1c367a9bd56c9df3410236 (patch) | |
tree | b2f750e237d72cc4bd2ffe80ef427ac4116d40e3 /fs | |
parent | cafe21a4fb3075fb2980caba8fdb533a1bdb52b0 (diff) |
ceph: quota: support for ceph.quota.max_bytes
Signed-off-by: Luis Henriques <lhenriques@suse.com>
Reviewed-by: "Yan, Zheng" <zyan@redhat.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ceph/file.c | 11 | ||||
-rw-r--r-- | fs/ceph/inode.c | 4 | ||||
-rw-r--r-- | fs/ceph/quota.c | 28 | ||||
-rw-r--r-- | fs/ceph/super.h | 2 |
4 files changed, 44 insertions, 1 deletions
diff --git a/fs/ceph/file.c b/fs/ceph/file.c index c3042330e0e9..0a2843fdebbd 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c | |||
@@ -1378,6 +1378,11 @@ retry_snap: | |||
1378 | 1378 | ||
1379 | pos = iocb->ki_pos; | 1379 | pos = iocb->ki_pos; |
1380 | count = iov_iter_count(from); | 1380 | count = iov_iter_count(from); |
1381 | if (ceph_quota_is_max_bytes_exceeded(inode, pos + count)) { | ||
1382 | err = -EDQUOT; | ||
1383 | goto out; | ||
1384 | } | ||
1385 | |||
1381 | err = file_remove_privs(file); | 1386 | err = file_remove_privs(file); |
1382 | if (err) | 1387 | if (err) |
1383 | goto out; | 1388 | goto out; |
@@ -1708,6 +1713,12 @@ static long ceph_fallocate(struct file *file, int mode, | |||
1708 | goto unlock; | 1713 | goto unlock; |
1709 | } | 1714 | } |
1710 | 1715 | ||
1716 | if (!(mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE)) && | ||
1717 | ceph_quota_is_max_bytes_exceeded(inode, offset + length)) { | ||
1718 | ret = -EDQUOT; | ||
1719 | goto unlock; | ||
1720 | } | ||
1721 | |||
1711 | if (ceph_osdmap_flag(osdc, CEPH_OSDMAP_FULL) && | 1722 | if (ceph_osdmap_flag(osdc, CEPH_OSDMAP_FULL) && |
1712 | !(mode & FALLOC_FL_PUNCH_HOLE)) { | 1723 | !(mode & FALLOC_FL_PUNCH_HOLE)) { |
1713 | ret = -ENOSPC; | 1724 | ret = -ENOSPC; |
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 2c6f8be4ed63..50ccae151ea0 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c | |||
@@ -2147,6 +2147,10 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr) | |||
2147 | if (err != 0) | 2147 | if (err != 0) |
2148 | return err; | 2148 | return err; |
2149 | 2149 | ||
2150 | if ((attr->ia_valid & ATTR_SIZE) && | ||
2151 | ceph_quota_is_max_bytes_exceeded(inode, attr->ia_size)) | ||
2152 | return -EDQUOT; | ||
2153 | |||
2150 | err = __ceph_setattr(inode, attr); | 2154 | err = __ceph_setattr(inode, attr); |
2151 | 2155 | ||
2152 | if (err >= 0 && (attr->ia_valid & ATTR_MODE)) | 2156 | if (err >= 0 && (attr->ia_valid & ATTR_MODE)) |
diff --git a/fs/ceph/quota.c b/fs/ceph/quota.c index 5d7dada91a57..745f9f47027b 100644 --- a/fs/ceph/quota.c +++ b/fs/ceph/quota.c | |||
@@ -134,7 +134,8 @@ bool ceph_quota_is_same_realm(struct inode *old, struct inode *new) | |||
134 | } | 134 | } |
135 | 135 | ||
136 | enum quota_check_op { | 136 | enum quota_check_op { |
137 | QUOTA_CHECK_MAX_FILES_OP /* check quota max_files limit */ | 137 | QUOTA_CHECK_MAX_FILES_OP, /* check quota max_files limit */ |
138 | QUOTA_CHECK_MAX_BYTES_OP /* check quota max_files limit */ | ||
138 | }; | 139 | }; |
139 | 140 | ||
140 | /* | 141 | /* |
@@ -171,6 +172,9 @@ static bool check_quota_exceeded(struct inode *inode, enum quota_check_op op, | |||
171 | if (op == QUOTA_CHECK_MAX_FILES_OP) { | 172 | if (op == QUOTA_CHECK_MAX_FILES_OP) { |
172 | max = ci->i_max_files; | 173 | max = ci->i_max_files; |
173 | rvalue = ci->i_rfiles + ci->i_rsubdirs; | 174 | rvalue = ci->i_rfiles + ci->i_rsubdirs; |
175 | } else { | ||
176 | max = ci->i_max_bytes; | ||
177 | rvalue = ci->i_rbytes; | ||
174 | } | 178 | } |
175 | is_root = (ci->i_vino.ino == CEPH_INO_ROOT); | 179 | is_root = (ci->i_vino.ino == CEPH_INO_ROOT); |
176 | spin_unlock(&ci->i_ceph_lock); | 180 | spin_unlock(&ci->i_ceph_lock); |
@@ -178,6 +182,9 @@ static bool check_quota_exceeded(struct inode *inode, enum quota_check_op op, | |||
178 | case QUOTA_CHECK_MAX_FILES_OP: | 182 | case QUOTA_CHECK_MAX_FILES_OP: |
179 | exceeded = (max && (rvalue >= max)); | 183 | exceeded = (max && (rvalue >= max)); |
180 | break; | 184 | break; |
185 | case QUOTA_CHECK_MAX_BYTES_OP: | ||
186 | exceeded = (max && (rvalue + delta > max)); | ||
187 | break; | ||
181 | default: | 188 | default: |
182 | /* Shouldn't happen */ | 189 | /* Shouldn't happen */ |
183 | pr_warn("Invalid quota check op (%d)\n", op); | 190 | pr_warn("Invalid quota check op (%d)\n", op); |
@@ -212,3 +219,22 @@ bool ceph_quota_is_max_files_exceeded(struct inode *inode) | |||
212 | 219 | ||
213 | return check_quota_exceeded(inode, QUOTA_CHECK_MAX_FILES_OP, 0); | 220 | return check_quota_exceeded(inode, QUOTA_CHECK_MAX_FILES_OP, 0); |
214 | } | 221 | } |
222 | |||
223 | /* | ||
224 | * ceph_quota_is_max_bytes_exceeded - check if we can write to a file | ||
225 | * @inode: inode being written | ||
226 | * @newsize: new size if write succeeds | ||
227 | * | ||
228 | * This functions returns true is max_bytes quota allows a file size to reach | ||
229 | * @newsize; it returns false otherwise. | ||
230 | */ | ||
231 | bool ceph_quota_is_max_bytes_exceeded(struct inode *inode, loff_t newsize) | ||
232 | { | ||
233 | loff_t size = i_size_read(inode); | ||
234 | |||
235 | /* return immediately if we're decreasing file size */ | ||
236 | if (newsize <= size) | ||
237 | return false; | ||
238 | |||
239 | return check_quota_exceeded(inode, QUOTA_CHECK_MAX_BYTES_OP, (newsize - size)); | ||
240 | } | ||
diff --git a/fs/ceph/super.h b/fs/ceph/super.h index eea6f70f3bf9..5870c225c2fc 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h | |||
@@ -1079,5 +1079,7 @@ extern void ceph_handle_quota(struct ceph_mds_client *mdsc, | |||
1079 | struct ceph_msg *msg); | 1079 | struct ceph_msg *msg); |
1080 | extern bool ceph_quota_is_max_files_exceeded(struct inode *inode); | 1080 | extern bool ceph_quota_is_max_files_exceeded(struct inode *inode); |
1081 | extern bool ceph_quota_is_same_realm(struct inode *old, struct inode *new); | 1081 | extern bool ceph_quota_is_same_realm(struct inode *old, struct inode *new); |
1082 | extern bool ceph_quota_is_max_bytes_exceeded(struct inode *inode, | ||
1083 | loff_t newlen); | ||
1082 | 1084 | ||
1083 | #endif /* _FS_CEPH_SUPER_H */ | 1085 | #endif /* _FS_CEPH_SUPER_H */ |