]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
ceph: quota: support for ceph.quota.max_bytes
authorLuis Henriques <lhenriques@suse.com>
Fri, 5 Jan 2018 10:47:21 +0000 (10:47 +0000)
committerKleber Sacilotto de Souza <kleber.souza@canonical.com>
Tue, 2 Jul 2019 16:30:46 +0000 (18:30 +0200)
BugLink: https://bugs.launchpad.net/bugs/1834235
Signed-off-by: Luis Henriques <lhenriques@suse.com>
Reviewed-by: "Yan, Zheng" <zyan@redhat.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
(cherry picked from commit 2b83845f8bd711e66e1c367a9bd56c9df3410236)
Signed-off-by: Connor Kuehl <connor.kuehl@canonical.com>
Acked-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
Acked-by: Stefan Bader <stefan.bader@canonical.com>
Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
fs/ceph/file.c
fs/ceph/inode.c
fs/ceph/quota.c
fs/ceph/super.h

index 4ef0d60b4ebeb2343b763f734caf95ef5827381f..a51098c0fc877eed3c0e6b4e373db5908788ed02 100644 (file)
@@ -1340,6 +1340,11 @@ retry_snap:
 
        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;
@@ -1670,6 +1675,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;
index ae6723e80c7158c79f89f8aa43de239e2f596c36..80aad584e2a0a462501ba8161fd00d77c9b5ff77 100644 (file)
@@ -2150,6 +2150,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))
index fd27e7113731c81f39bcab956e5b5001802386a0..e324593a97714136d25e127cad58665e5c2463b3 100644 (file)
@@ -136,7 +136,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 */
 };
 
 /*
@@ -172,12 +173,18 @@ 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;
                }
                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);
@@ -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));
+}
index 54e7f2ed89635ebd1582c9b64905aea5d7dd4a3c..fb1119147a688d16548849be8f3aeb65de00a229 100644 (file)
@@ -1080,5 +1080,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 */