ceph: quota: cache inode pointer in ceph_snap_realm
authorLuis Henriques <lhenriques@suse.com>
Fri, 12 Jan 2018 17:19:28 +0000 (17:19 +0000)
committerIlya Dryomov <idryomov@gmail.com>
Mon, 2 Apr 2018 09:17:53 +0000 (11:17 +0200)
Keep a pointer to the inode in struct ceph_snap_realm.  This allows to
optimize functions that walk the realms hierarchy (e.g. in quotas).

Signed-off-by: Luis Henriques <lhenriques@suse.com>
Reviewed-by: "Yan, Zheng" <zyan@redhat.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
fs/ceph/caps.c
fs/ceph/inode.c
fs/ceph/quota.c
fs/ceph/snap.c
fs/ceph/super.h

index 25141b6683e95db3437b4949a9dc1a1640ebec98..23dbfae1615685dde002b8fa4e77ed54f6a01c0e 100644 (file)
@@ -703,9 +703,11 @@ void ceph_add_cap(struct inode *inode,
                        }
 
                        spin_lock(&realm->inodes_with_caps_lock);
-                       ci->i_snap_realm = realm;
                        list_add(&ci->i_snap_realm_item,
                                 &realm->inodes_with_caps);
+                       ci->i_snap_realm = realm;
+                       if (realm->ino == ci->i_vino.ino)
+                               realm->inode = inode;
                        spin_unlock(&realm->inodes_with_caps_lock);
 
                        if (oldrealm)
index 50ccae151ea08ace51c4d3869d3920b0b2be8a6d..8ea11b1a2e23334dc2caaa6b428a032b1f6fd645 100644 (file)
@@ -551,6 +551,9 @@ void ceph_destroy_inode(struct inode *inode)
                dout(" dropping residual ref to snap realm %p\n", realm);
                spin_lock(&realm->inodes_with_caps_lock);
                list_del_init(&ci->i_snap_realm_item);
+               ci->i_snap_realm = NULL;
+               if (realm->ino == ci->i_vino.ino)
+                       realm->inode = NULL;
                spin_unlock(&realm->inodes_with_caps_lock);
                ceph_put_snap_realm(mdsc, realm);
        }
index 121819baeb58fa630cbd116f5f982c65d5d80505..c561a85ea8b1c2bec1bc4ac087b3e633d15d9b91 100644 (file)
@@ -83,7 +83,6 @@ static struct ceph_snap_realm *get_quota_realm(struct ceph_mds_client *mdsc,
 {
        struct ceph_inode_info *ci = NULL;
        struct ceph_snap_realm *realm, *next;
-       struct ceph_vino vino;
        struct inode *in;
        bool has_quota;
 
@@ -97,13 +96,12 @@ static struct ceph_snap_realm *get_quota_realm(struct ceph_mds_client *mdsc,
                pr_err_ratelimited("get_quota_realm: ino (%llx.%llx) "
                                   "null i_snap_realm\n", ceph_vinop(inode));
        while (realm) {
-               vino.ino = realm->ino;
-               vino.snap = CEPH_NOSNAP;
-               in = ceph_find_inode(inode->i_sb, vino);
-               if (!in) {
-                       pr_warn("Failed to find inode for %llu\n", vino.ino);
+               spin_lock(&realm->inodes_with_caps_lock);
+               in = realm->inode ? igrab(realm->inode) : NULL;
+               spin_unlock(&realm->inodes_with_caps_lock);
+               if (!in)
                        break;
-               }
+
                ci = ceph_inode(in);
                has_quota = ceph_has_quota(ci);
                iput(in);
@@ -161,7 +159,6 @@ static bool check_quota_exceeded(struct inode *inode, enum quota_check_op op,
        struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc;
        struct ceph_inode_info *ci;
        struct ceph_snap_realm *realm, *next;
-       struct ceph_vino vino;
        struct inode *in;
        u64 max, rvalue;
        bool exceeded = false;
@@ -177,13 +174,12 @@ static bool check_quota_exceeded(struct inode *inode, enum quota_check_op op,
                pr_err_ratelimited("check_quota_exceeded: ino (%llx.%llx) "
                                   "null i_snap_realm\n", ceph_vinop(inode));
        while (realm) {
-               vino.ino = realm->ino;
-               vino.snap = CEPH_NOSNAP;
-               in = ceph_find_inode(inode->i_sb, vino);
-               if (!in) {
-                       pr_warn("Failed to find inode for %llu\n", vino.ino);
+               spin_lock(&realm->inodes_with_caps_lock);
+               in = realm->inode ? igrab(realm->inode) : NULL;
+               spin_unlock(&realm->inodes_with_caps_lock);
+               if (!in)
                        break;
-               }
+
                ci = ceph_inode(in);
                spin_lock(&ci->i_ceph_lock);
                if (op == QUOTA_CHECK_MAX_FILES_OP) {
index 07cf95e6413d775d01c383f3d3d7e0e8e4879910..041c27ea8de155a0002bdb5af25eb2fc5f8e6efa 100644 (file)
@@ -931,6 +931,8 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc,
                        list_add(&ci->i_snap_realm_item,
                                 &realm->inodes_with_caps);
                        ci->i_snap_realm = realm;
+                       if (realm->ino == ci->i_vino.ino)
+                                realm->inode = inode;
                        spin_unlock(&realm->inodes_with_caps_lock);
 
                        spin_unlock(&ci->i_ceph_lock);
index e4ff485d24c711713095e5e645360e9e0494f573..8217abf461821d338bd2dcc3dac2cb4c2f5dae6c 100644 (file)
@@ -755,6 +755,7 @@ struct ceph_readdir_cache_control {
  */
 struct ceph_snap_realm {
        u64 ino;
+       struct inode *inode;
        atomic_t nref;
        struct rb_node node;