]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
ceph: quota: add counter for snaprealms with quota
authorLuis Henriques <lhenriques@suse.com>
Fri, 12 Jan 2018 17:19:29 +0000 (17:19 +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
By keeping a counter with the number of snaprealms that have quota set
allows to optimize the functions that need to walk throught the realms
hierarchy looking for quotas.  Thus, if this counter is zero it's safe to
assume that there are no realms with quota.

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 d557c48db730eaab6b75d4af332c135309b7a6a4)
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/inode.c
fs/ceph/mds_client.c
fs/ceph/mds_client.h
fs/ceph/quota.c
fs/ceph/super.h

index 80aad584e2a0a462501ba8161fd00d77c9b5ff77..fb198365cb1a3f0d01c3911b9576d4f5ba40d1d4 100644 (file)
@@ -535,6 +535,9 @@ void ceph_destroy_inode(struct inode *inode)
 
        __ceph_remove_caps(inode);
 
+       if (__ceph_has_any_quota(ci))
+               ceph_adjust_quota_realms_count(inode, false);
+
        /*
         * we may still have a snap_realm reference if there are stray
         * caps in i_snap_caps.
@@ -790,8 +793,7 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
        inode->i_rdev = le32_to_cpu(info->rdev);
        inode->i_blkbits = fls(le32_to_cpu(info->layout.fl_stripe_unit)) - 1;
 
-       ci->i_max_bytes = iinfo->max_bytes;
-       ci->i_max_files = iinfo->max_files;
+       __ceph_update_quota(ci, iinfo->max_bytes, iinfo->max_files);
 
        if ((new_version || (new_issued & CEPH_CAP_AUTH_SHARED)) &&
            (issued & CEPH_CAP_AUTH_EXCL) == 0) {
index c28e8b3f68a001098e4d8f8530930144167b03d0..1eb99893f722c257e9ad2ccee9fe934080b64d97 100644 (file)
@@ -3637,6 +3637,7 @@ int ceph_mdsc_init(struct ceph_fs_client *fsc)
        atomic_set(&mdsc->num_sessions, 0);
        mdsc->max_sessions = 0;
        mdsc->stopping = 0;
+       atomic64_set(&mdsc->quotarealms_count, 0);
        mdsc->last_snap_seq = 0;
        init_rwsem(&mdsc->snap_rwsem);
        mdsc->snap_realms = RB_ROOT;
index 7cfb18c061bae24acffe6938116009a90432a88a..2e41170354c40d19140aead90d489b7fffdc4ed5 100644 (file)
@@ -315,6 +315,8 @@ struct ceph_mds_client {
        int                     max_sessions;  /* len of s_mds_sessions */
        int                     stopping;      /* true if shutting down */
 
+       atomic64_t              quotarealms_count; /* # realms with quota */
+
        /*
         * snap_rwsem will cover cap linkage into snaprealms, and
         * realm snap contexts.  (later, we can do per-realm snap
index 656c9fbba1aef8021c63f60a64d93c5292dccad0..2d3d619131622e876e1e2fcf7b0b663d11a66d53 100644 (file)
 #include "super.h"
 #include "mds_client.h"
 
-static inline bool ceph_has_quota(struct ceph_inode_info *ci)
+void ceph_adjust_quota_realms_count(struct inode *inode, bool inc)
 {
-       return (ci && (ci->i_max_files || ci->i_max_bytes));
+       struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc;
+       if (inc)
+               atomic64_inc(&mdsc->quotarealms_count);
+       else
+               atomic64_dec(&mdsc->quotarealms_count);
+}
+
+static inline bool ceph_has_realms_with_quotas(struct inode *inode)
+{
+       struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc;
+       return atomic64_read(&mdsc->quotarealms_count) > 0;
 }
 
 void ceph_handle_quota(struct ceph_mds_client *mdsc,
@@ -62,8 +72,8 @@ void ceph_handle_quota(struct ceph_mds_client *mdsc,
        ci->i_rbytes = le64_to_cpu(h->rbytes);
        ci->i_rfiles = le64_to_cpu(h->rfiles);
        ci->i_rsubdirs = le64_to_cpu(h->rsubdirs);
-       ci->i_max_bytes = le64_to_cpu(h->max_bytes);
-       ci->i_max_files = le64_to_cpu(h->max_files);
+       __ceph_update_quota(ci, le64_to_cpu(h->max_bytes),
+                           le64_to_cpu(h->max_files));
        spin_unlock(&ci->i_ceph_lock);
 
        iput(inode);
@@ -98,7 +108,7 @@ static struct ceph_snap_realm *get_quota_realm(struct ceph_mds_client *mdsc,
                        break;
                }
                ci = ceph_inode(in);
-               has_quota = ceph_has_quota(ci);
+               has_quota = __ceph_has_any_quota(ci);
                iput(in);
 
                next = realm->parent;
@@ -231,6 +241,9 @@ static bool check_quota_exceeded(struct inode *inode, enum quota_check_op op,
  */
 bool ceph_quota_is_max_files_exceeded(struct inode *inode)
 {
+       if (!ceph_has_realms_with_quotas(inode))
+               return false;
+
        WARN_ON(!S_ISDIR(inode->i_mode));
 
        return check_quota_exceeded(inode, QUOTA_CHECK_MAX_FILES_OP, 0);
@@ -248,6 +261,9 @@ bool ceph_quota_is_max_bytes_exceeded(struct inode *inode, loff_t newsize)
 {
        loff_t size = i_size_read(inode);
 
+       if (!ceph_has_realms_with_quotas(inode))
+               return false;
+
        /* return immediately if we're decreasing file size */
        if (newsize <= size)
                return false;
@@ -267,6 +283,9 @@ bool ceph_quota_is_max_bytes_approaching(struct inode *inode, loff_t newsize)
 {
        loff_t size = ceph_inode(inode)->i_reported_size;
 
+       if (!ceph_has_realms_with_quotas(inode))
+               return false;
+
        /* return immediately if we're decreasing file size */
        if (newsize <= size)
                return false;
index 35c2195e3e3db6e7e03897880fbd5b0609ed4ec4..8a4429d05e3c802cc2fe9da02d307dc0d7dbfe5b 100644 (file)
@@ -1075,6 +1075,26 @@ extern int ceph_fs_debugfs_init(struct ceph_fs_client *client);
 extern void ceph_fs_debugfs_cleanup(struct ceph_fs_client *client);
 
 /* quota.c */
+static inline bool __ceph_has_any_quota(struct ceph_inode_info *ci)
+{
+       return ci->i_max_files || ci->i_max_bytes;
+}
+
+extern void ceph_adjust_quota_realms_count(struct inode *inode, bool inc);
+
+static inline void __ceph_update_quota(struct ceph_inode_info *ci,
+                                      u64 max_bytes, u64 max_files)
+{
+       bool had_quota, has_quota;
+       had_quota = __ceph_has_any_quota(ci);
+       ci->i_max_bytes = max_bytes;
+       ci->i_max_files = max_files;
+       has_quota = __ceph_has_any_quota(ci);
+
+       if (had_quota != has_quota)
+               ceph_adjust_quota_realms_count(&ci->vfs_inode, has_quota);
+}
+
 extern void ceph_handle_quota(struct ceph_mds_client *mdsc,
                              struct ceph_mds_session *session,
                              struct ceph_msg *msg);