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>
This commit is contained in:
parent
2b83845f8b
commit
1ab302a0cb
@ -1464,6 +1464,7 @@ retry_snap:
|
|||||||
|
|
||||||
if (written >= 0) {
|
if (written >= 0) {
|
||||||
int dirty;
|
int dirty;
|
||||||
|
|
||||||
spin_lock(&ci->i_ceph_lock);
|
spin_lock(&ci->i_ceph_lock);
|
||||||
ci->i_inline_version = CEPH_INLINE_NONE;
|
ci->i_inline_version = CEPH_INLINE_NONE;
|
||||||
dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_FILE_WR,
|
dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_FILE_WR,
|
||||||
@ -1471,6 +1472,8 @@ retry_snap:
|
|||||||
spin_unlock(&ci->i_ceph_lock);
|
spin_unlock(&ci->i_ceph_lock);
|
||||||
if (dirty)
|
if (dirty)
|
||||||
__mark_inode_dirty(inode, dirty);
|
__mark_inode_dirty(inode, dirty);
|
||||||
|
if (ceph_quota_is_max_bytes_approaching(inode, iocb->ki_pos))
|
||||||
|
ceph_check_caps(ci, CHECK_CAPS_NODELAY, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
dout("aio_write %p %llx.%llx %llu~%u dropping cap refs on %s\n",
|
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,
|
|||||||
spin_unlock(&ci->i_ceph_lock);
|
spin_unlock(&ci->i_ceph_lock);
|
||||||
if (dirty)
|
if (dirty)
|
||||||
__mark_inode_dirty(inode, dirty);
|
__mark_inode_dirty(inode, dirty);
|
||||||
|
if ((endoff > size) &&
|
||||||
|
ceph_quota_is_max_bytes_approaching(inode, endoff))
|
||||||
|
ceph_check_caps(ci, CHECK_CAPS_NODELAY, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
ceph_put_cap_refs(ci, got);
|
ceph_put_cap_refs(ci, got);
|
||||||
|
@ -135,7 +135,9 @@ bool ceph_quota_is_same_realm(struct inode *old, struct inode *new)
|
|||||||
|
|
||||||
enum quota_check_op {
|
enum quota_check_op {
|
||||||
QUOTA_CHECK_MAX_FILES_OP, /* check quota max_files limit */
|
QUOTA_CHECK_MAX_FILES_OP, /* check quota max_files limit */
|
||||||
QUOTA_CHECK_MAX_BYTES_OP /* check quota max_files limit */
|
QUOTA_CHECK_MAX_BYTES_OP, /* check quota max_files limit */
|
||||||
|
QUOTA_CHECK_MAX_BYTES_APPROACHING_OP /* check if quota max_files
|
||||||
|
limit is approaching */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -185,6 +187,20 @@ static bool check_quota_exceeded(struct inode *inode, enum quota_check_op op,
|
|||||||
case QUOTA_CHECK_MAX_BYTES_OP:
|
case QUOTA_CHECK_MAX_BYTES_OP:
|
||||||
exceeded = (max && (rvalue + delta > max));
|
exceeded = (max && (rvalue + delta > max));
|
||||||
break;
|
break;
|
||||||
|
case QUOTA_CHECK_MAX_BYTES_APPROACHING_OP:
|
||||||
|
if (max) {
|
||||||
|
if (rvalue >= max)
|
||||||
|
exceeded = true;
|
||||||
|
else {
|
||||||
|
/*
|
||||||
|
* when we're writing more that 1/16th
|
||||||
|
* of the available space
|
||||||
|
*/
|
||||||
|
exceeded =
|
||||||
|
(((max - rvalue) >> 4) < delta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
/* Shouldn't happen */
|
/* Shouldn't happen */
|
||||||
pr_warn("Invalid quota check op (%d)\n", op);
|
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)
|
|||||||
|
|
||||||
return check_quota_exceeded(inode, QUOTA_CHECK_MAX_BYTES_OP, (newsize - size));
|
return check_quota_exceeded(inode, QUOTA_CHECK_MAX_BYTES_OP, (newsize - size));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ceph_quota_is_max_bytes_approaching - check if we're reaching max_bytes
|
||||||
|
* @inode: inode being written
|
||||||
|
* @newsize: new size if write succeeds
|
||||||
|
*
|
||||||
|
* This function returns true if the new file size @newsize will be consuming
|
||||||
|
* more than 1/16th of the available quota space; it returns false otherwise.
|
||||||
|
*/
|
||||||
|
bool ceph_quota_is_max_bytes_approaching(struct inode *inode, loff_t newsize)
|
||||||
|
{
|
||||||
|
loff_t size = ceph_inode(inode)->i_reported_size;
|
||||||
|
|
||||||
|
/* return immediately if we're decreasing file size */
|
||||||
|
if (newsize <= size)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return check_quota_exceeded(inode, QUOTA_CHECK_MAX_BYTES_APPROACHING_OP,
|
||||||
|
(newsize - size));
|
||||||
|
}
|
||||||
|
@ -1081,5 +1081,7 @@ extern bool ceph_quota_is_max_files_exceeded(struct inode *inode);
|
|||||||
extern bool ceph_quota_is_same_realm(struct inode *old, struct inode *new);
|
extern bool ceph_quota_is_same_realm(struct inode *old, struct inode *new);
|
||||||
extern bool ceph_quota_is_max_bytes_exceeded(struct inode *inode,
|
extern bool ceph_quota_is_max_bytes_exceeded(struct inode *inode,
|
||||||
loff_t newlen);
|
loff_t newlen);
|
||||||
|
extern bool ceph_quota_is_max_bytes_approaching(struct inode *inode,
|
||||||
|
loff_t newlen);
|
||||||
|
|
||||||
#endif /* _FS_CEPH_SUPER_H */
|
#endif /* _FS_CEPH_SUPER_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user