Skip to content

Commit

Permalink
ceph: quota: support for ceph.quota.max_bytes
Browse files Browse the repository at this point in the history
Signed-off-by: Luis Henriques <lhenriques@suse.com>
Reviewed-by: "Yan, Zheng" <zyan@redhat.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
  • Loading branch information
Luis Henriques authored and Ilya Dryomov committed Apr 2, 2018
1 parent cafe21a commit 2b83845
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 1 deletion.
11 changes: 11 additions & 0 deletions fs/ceph/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -1378,6 +1378,11 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)

pos = iocb->ki_pos;
count = iov_iter_count(from);
if (ceph_quota_is_max_bytes_exceeded(inode, pos + count)) {
err = -EDQUOT;
goto out;
}

err = file_remove_privs(file);
if (err)
goto out;
Expand Down Expand Up @@ -1708,6 +1713,12 @@ static long ceph_fallocate(struct file *file, int mode,
goto unlock;
}

if (!(mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE)) &&
ceph_quota_is_max_bytes_exceeded(inode, offset + length)) {
ret = -EDQUOT;
goto unlock;
}

if (ceph_osdmap_flag(osdc, CEPH_OSDMAP_FULL) &&
!(mode & FALLOC_FL_PUNCH_HOLE)) {
ret = -ENOSPC;
Expand Down
4 changes: 4 additions & 0 deletions fs/ceph/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -2147,6 +2147,10 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr)
if (err != 0)
return err;

if ((attr->ia_valid & ATTR_SIZE) &&
ceph_quota_is_max_bytes_exceeded(inode, attr->ia_size))
return -EDQUOT;

err = __ceph_setattr(inode, attr);

if (err >= 0 && (attr->ia_valid & ATTR_MODE))
Expand Down
28 changes: 27 additions & 1 deletion fs/ceph/quota.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,8 @@ bool ceph_quota_is_same_realm(struct inode *old, struct inode *new)
}

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 */
};

/*
Expand Down Expand Up @@ -171,13 +172,19 @@ static bool check_quota_exceeded(struct inode *inode, enum quota_check_op op,
if (op == QUOTA_CHECK_MAX_FILES_OP) {
max = ci->i_max_files;
rvalue = ci->i_rfiles + ci->i_rsubdirs;
} else {
max = ci->i_max_bytes;
rvalue = ci->i_rbytes;
}
is_root = (ci->i_vino.ino == CEPH_INO_ROOT);
spin_unlock(&ci->i_ceph_lock);
switch (op) {
case QUOTA_CHECK_MAX_FILES_OP:
exceeded = (max && (rvalue >= max));
break;
case QUOTA_CHECK_MAX_BYTES_OP:
exceeded = (max && (rvalue + delta > max));
break;
default:
/* Shouldn't happen */
pr_warn("Invalid quota check op (%d)\n", op);
Expand Down Expand Up @@ -212,3 +219,22 @@ bool ceph_quota_is_max_files_exceeded(struct inode *inode)

return check_quota_exceeded(inode, QUOTA_CHECK_MAX_FILES_OP, 0);
}

/*
* ceph_quota_is_max_bytes_exceeded - check if we can write to a file
* @inode: inode being written
* @newsize: new size if write succeeds
*
* This functions returns true is max_bytes quota allows a file size to reach
* @newsize; it returns false otherwise.
*/
bool ceph_quota_is_max_bytes_exceeded(struct inode *inode, loff_t newsize)
{
loff_t size = i_size_read(inode);

/* return immediately if we're decreasing file size */
if (newsize <= size)
return false;

return check_quota_exceeded(inode, QUOTA_CHECK_MAX_BYTES_OP, (newsize - size));
}
2 changes: 2 additions & 0 deletions fs/ceph/super.h
Original file line number Diff line number Diff line change
Expand Up @@ -1079,5 +1079,7 @@ extern void ceph_handle_quota(struct ceph_mds_client *mdsc,
struct ceph_msg *msg);
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_max_bytes_exceeded(struct inode *inode,
loff_t newlen);

#endif /* _FS_CEPH_SUPER_H */

0 comments on commit 2b83845

Please sign in to comment.