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>
This commit is contained in:
parent
cafe21a4fb
commit
2b83845f8b
|
@ -1378,6 +1378,11 @@ retry_snap:
|
||||||
|
|
||||||
pos = iocb->ki_pos;
|
pos = iocb->ki_pos;
|
||||||
count = iov_iter_count(from);
|
count = iov_iter_count(from);
|
||||||
|
if (ceph_quota_is_max_bytes_exceeded(inode, pos + count)) {
|
||||||
|
err = -EDQUOT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
err = file_remove_privs(file);
|
err = file_remove_privs(file);
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -1708,6 +1713,12 @@ static long ceph_fallocate(struct file *file, int mode,
|
||||||
goto unlock;
|
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) &&
|
if (ceph_osdmap_flag(osdc, CEPH_OSDMAP_FULL) &&
|
||||||
!(mode & FALLOC_FL_PUNCH_HOLE)) {
|
!(mode & FALLOC_FL_PUNCH_HOLE)) {
|
||||||
ret = -ENOSPC;
|
ret = -ENOSPC;
|
||||||
|
|
|
@ -2147,6 +2147,10 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr)
|
||||||
if (err != 0)
|
if (err != 0)
|
||||||
return err;
|
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);
|
err = __ceph_setattr(inode, attr);
|
||||||
|
|
||||||
if (err >= 0 && (attr->ia_valid & ATTR_MODE))
|
if (err >= 0 && (attr->ia_valid & ATTR_MODE))
|
||||||
|
|
|
@ -134,7 +134,8 @@ 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 */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -171,6 +172,9 @@ static bool check_quota_exceeded(struct inode *inode, enum quota_check_op op,
|
||||||
if (op == QUOTA_CHECK_MAX_FILES_OP) {
|
if (op == QUOTA_CHECK_MAX_FILES_OP) {
|
||||||
max = ci->i_max_files;
|
max = ci->i_max_files;
|
||||||
rvalue = ci->i_rfiles + ci->i_rsubdirs;
|
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);
|
is_root = (ci->i_vino.ino == CEPH_INO_ROOT);
|
||||||
spin_unlock(&ci->i_ceph_lock);
|
spin_unlock(&ci->i_ceph_lock);
|
||||||
|
@ -178,6 +182,9 @@ static bool check_quota_exceeded(struct inode *inode, enum quota_check_op op,
|
||||||
case QUOTA_CHECK_MAX_FILES_OP:
|
case QUOTA_CHECK_MAX_FILES_OP:
|
||||||
exceeded = (max && (rvalue >= max));
|
exceeded = (max && (rvalue >= max));
|
||||||
break;
|
break;
|
||||||
|
case QUOTA_CHECK_MAX_BYTES_OP:
|
||||||
|
exceeded = (max && (rvalue + delta > max));
|
||||||
|
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);
|
||||||
|
@ -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);
|
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));
|
||||||
|
}
|
||||||
|
|
|
@ -1079,5 +1079,7 @@ extern void ceph_handle_quota(struct ceph_mds_client *mdsc,
|
||||||
struct ceph_msg *msg);
|
struct ceph_msg *msg);
|
||||||
extern bool ceph_quota_is_max_files_exceeded(struct inode *inode);
|
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,
|
||||||
|
loff_t newlen);
|
||||||
|
|
||||||
#endif /* _FS_CEPH_SUPER_H */
|
#endif /* _FS_CEPH_SUPER_H */
|
||||||
|
|
Loading…
Reference in New Issue