aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuis Henriques <lhenriques@suse.com>2018-01-05 05:47:22 -0500
committerIlya Dryomov <idryomov@gmail.com>2018-04-02 05:17:52 -0400
commit1ab302a0cb1455631646aa66b7fc02afd617ea4f (patch)
tree73686da6a5aef8ef0190bd8498d3591fc766ddee
parent2b83845f8bd711e66e1c367a9bd56c9df3410236 (diff)
ceph: quota: update MDS when max_bytes is approaching
When we're reaching the ceph.quota.max_bytes limit, i.e., when writing more than 1/16th of the space left in a quota realm, update the MDS with the new file size. This mirrors the fuse-client approach with commit 122c50315ed1 ("client: Inform mds file size when approaching quota limit"), in the ceph git tree. Signed-off-by: Luis Henriques <lhenriques@suse.com> Reviewed-by: "Yan, Zheng" <zyan@redhat.com> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
-rw-r--r--fs/ceph/file.c6
-rw-r--r--fs/ceph/quota.c38
-rw-r--r--fs/ceph/super.h2
3 files changed, 45 insertions, 1 deletions
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index 0a2843fdebbd..f85040d73e3d 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -1464,6 +1464,7 @@ retry_snap:
1464 1464
1465 if (written >= 0) { 1465 if (written >= 0) {
1466 int dirty; 1466 int dirty;
1467
1467 spin_lock(&ci->i_ceph_lock); 1468 spin_lock(&ci->i_ceph_lock);
1468 ci->i_inline_version = CEPH_INLINE_NONE; 1469 ci->i_inline_version = CEPH_INLINE_NONE;
1469 dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_FILE_WR, 1470 dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_FILE_WR,
@@ -1471,6 +1472,8 @@ retry_snap:
1471 spin_unlock(&ci->i_ceph_lock); 1472 spin_unlock(&ci->i_ceph_lock);
1472 if (dirty) 1473 if (dirty)
1473 __mark_inode_dirty(inode, dirty); 1474 __mark_inode_dirty(inode, dirty);
1475 if (ceph_quota_is_max_bytes_approaching(inode, iocb->ki_pos))
1476 ceph_check_caps(ci, CHECK_CAPS_NODELAY, NULL);
1474 } 1477 }
1475 1478
1476 dout("aio_write %p %llx.%llx %llu~%u dropping cap refs on %s\n", 1479 dout("aio_write %p %llx.%llx %llu~%u dropping cap refs on %s\n",
@@ -1767,6 +1770,9 @@ static long ceph_fallocate(struct file *file, int mode,
1767 spin_unlock(&ci->i_ceph_lock); 1770 spin_unlock(&ci->i_ceph_lock);
1768 if (dirty) 1771 if (dirty)
1769 __mark_inode_dirty(inode, dirty); 1772 __mark_inode_dirty(inode, dirty);
1773 if ((endoff > size) &&
1774 ceph_quota_is_max_bytes_approaching(inode, endoff))
1775 ceph_check_caps(ci, CHECK_CAPS_NODELAY, NULL);
1770 } 1776 }
1771 1777
1772 ceph_put_cap_refs(ci, got); 1778 ceph_put_cap_refs(ci, got);
diff --git a/fs/ceph/quota.c b/fs/ceph/quota.c
index 745f9f47027b..7d1e18e2249f 100644
--- a/fs/ceph/quota.c
+++ b/fs/ceph/quota.c
@@ -135,7 +135,9 @@ bool ceph_quota_is_same_realm(struct inode *old, struct inode *new)
135 135
136enum quota_check_op { 136enum 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 QUOTA_CHECK_MAX_BYTES_OP, /* check quota max_files limit */
139 QUOTA_CHECK_MAX_BYTES_APPROACHING_OP /* check if quota max_files
140 limit is approaching */
139}; 141};
140 142
141/* 143/*
@@ -185,6 +187,20 @@ static bool check_quota_exceeded(struct inode *inode, enum quota_check_op op,
185 case QUOTA_CHECK_MAX_BYTES_OP: 187 case QUOTA_CHECK_MAX_BYTES_OP:
186 exceeded = (max && (rvalue + delta > max)); 188 exceeded = (max && (rvalue + delta > max));
187 break; 189 break;
190 case QUOTA_CHECK_MAX_BYTES_APPROACHING_OP:
191 if (max) {
192 if (rvalue >= max)
193 exceeded = true;
194 else {
195 /*
196 * when we're writing more that 1/16th
197 * of the available space
198 */
199 exceeded =
200 (((max - rvalue) >> 4) < delta);
201 }
202 }
203 break;
188 default: 204 default:
189 /* Shouldn't happen */ 205 /* Shouldn't happen */
190 pr_warn("Invalid quota check op (%d)\n", op); 206 pr_warn("Invalid quota check op (%d)\n", op);
@@ -238,3 +254,23 @@ bool ceph_quota_is_max_bytes_exceeded(struct inode *inode, loff_t newsize)
238 254
239 return check_quota_exceeded(inode, QUOTA_CHECK_MAX_BYTES_OP, (newsize - size)); 255 return check_quota_exceeded(inode, QUOTA_CHECK_MAX_BYTES_OP, (newsize - size));
240} 256}
257
258/*
259 * ceph_quota_is_max_bytes_approaching - check if we're reaching max_bytes
260 * @inode: inode being written
261 * @newsize: new size if write succeeds
262 *
263 * This function returns true if the new file size @newsize will be consuming
264 * more than 1/16th of the available quota space; it returns false otherwise.
265 */
266bool ceph_quota_is_max_bytes_approaching(struct inode *inode, loff_t newsize)
267{
268 loff_t size = ceph_inode(inode)->i_reported_size;
269
270 /* return immediately if we're decreasing file size */
271 if (newsize <= size)
272 return false;
273
274 return check_quota_exceeded(inode, QUOTA_CHECK_MAX_BYTES_APPROACHING_OP,
275 (newsize - size));
276}
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index 5870c225c2fc..e4ff485d24c7 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -1081,5 +1081,7 @@ extern bool ceph_quota_is_max_files_exceeded(struct inode *inode);
1081extern bool ceph_quota_is_same_realm(struct inode *old, struct inode *new); 1081extern bool ceph_quota_is_same_realm(struct inode *old, struct inode *new);
1082extern bool ceph_quota_is_max_bytes_exceeded(struct inode *inode, 1082extern bool ceph_quota_is_max_bytes_exceeded(struct inode *inode,
1083 loff_t newlen); 1083 loff_t newlen);
1084extern bool ceph_quota_is_max_bytes_approaching(struct inode *inode,
1085 loff_t newlen);
1084 1086
1085#endif /* _FS_CEPH_SUPER_H */ 1087#endif /* _FS_CEPH_SUPER_H */