]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
kclient: fix snap_realm leak
authorSage Weil <sage@newdream.net>
Mon, 20 Oct 2008 21:26:14 +0000 (14:26 -0700)
committerSage Weil <sage@newdream.net>
Mon, 20 Oct 2008 21:26:14 +0000 (14:26 -0700)
The snap tree carries no reference.  Instead, when the refcount hits 0, we remove
the realm from the tree.

Alternatively, we could attach the realm to it's parent inode and avoid the snap
tree entirely... hmm.

src/kernel/caps.c
src/kernel/snap.c
src/kernel/super.h

index 922a85253fe63b5e1e89b1b0c62b2f59396dcb04..cda047dc05d58bb201655f4b681f166b68381723 100644 (file)
@@ -134,7 +134,7 @@ retry:
                        spin_unlock(&inode->i_lock);
                        new_cap = kmalloc(sizeof(*cap), GFP_NOFS);
                        if (new_cap == NULL) {
-                               ceph_put_snap_realm(realm);
+                               ceph_put_snap_realm(mdsc, realm);
                                return -ENOMEM;
                        }
                        goto retry;
@@ -163,7 +163,7 @@ retry:
                ci->i_snap_realm = realm;
                list_add(&ci->i_snap_realm_item, &realm->inodes_with_caps);
        } else {
-               ceph_put_snap_realm(realm);
+               ceph_put_snap_realm(mdsc, realm);
        }
 
        dout(10, "add_cap inode %p (%llx.%llx) cap %xh now %xh seq %d mds%d\n",
@@ -227,6 +227,7 @@ static int __ceph_remove_cap(struct ceph_cap *cap)
 {
        struct ceph_mds_session *session = cap->session;
        struct ceph_inode_info *ci = cap->ci;
+       struct ceph_mds_client *mdsc = &ceph_client(ci->vfs_inode.i_sb)->mdsc;
 
        dout(20, "__ceph_remove_cap %p from %p\n", cap, &ci->vfs_inode);
 
@@ -242,7 +243,7 @@ static int __ceph_remove_cap(struct ceph_cap *cap)
 
        if (RB_EMPTY_ROOT(&ci->i_caps)) {
                list_del_init(&ci->i_snap_realm_item);
-               ceph_put_snap_realm(ci->i_snap_realm);
+               ceph_put_snap_realm(mdsc, ci->i_snap_realm);
                ci->i_snap_realm = NULL;
                return 1;
        }
index bf90bdc41c619b36de9f6bac29c7b7edb028dd65..45ef8830f3e886fd894629ec676cac7a03d71e91 100644 (file)
@@ -75,7 +75,7 @@ struct ceph_snap_realm *ceph_get_snap_realm(struct ceph_mds_client *mdsc,
                if (!realm)
                        return ERR_PTR(-ENOMEM);
                radix_tree_insert(&mdsc->snap_realms, ino, realm);
-               realm->nref = 1;    /* in tree */
+               realm->nref = 0;    /* tree does not take a ref */
                realm->ino = ino;
                INIT_LIST_HEAD(&realm->children);
                INIT_LIST_HEAD(&realm->child_item);
@@ -91,12 +91,14 @@ struct ceph_snap_realm *ceph_get_snap_realm(struct ceph_mds_client *mdsc,
 /*
  * caller must hold snap_rwsem for write
  */
-void ceph_put_snap_realm(struct ceph_snap_realm *realm)
+void ceph_put_snap_realm(struct ceph_mds_client *mdsc,
+                        struct ceph_snap_realm *realm)
 {
        dout(20, "put_snap_realm %llx %p %d -> %d\n", realm->ino, realm,
             realm->nref, realm->nref-1);
        realm->nref--;
        if (realm->nref == 0) {
+               radix_tree_delete(&mdsc->snap_realms, realm->ino);
                kfree(realm->prior_parent_snaps);
                kfree(realm->snaps);
                ceph_put_snap_context(realm->cached_context);
@@ -129,7 +131,7 @@ static int adjust_snap_realm_parent(struct ceph_mds_client *mdsc,
             parentino, parent);
        if (realm->parent) {
                list_del_init(&realm->child_item);
-               ceph_put_snap_realm(realm->parent);
+               ceph_put_snap_realm(mdsc, realm->parent);
        }
        realm->parent_ino = parentino;
        realm->parent = parent;
@@ -484,7 +486,7 @@ more:
        if (p == e && invalidate)
                rebuild_snap_realms(realm);
 
-       ceph_put_snap_realm(realm);
+       ceph_put_snap_realm(mdsc, realm);
        if (p < e)
                goto more;
 
@@ -645,10 +647,10 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc,
                        if (IS_ERR(child))
                                continue;
                        adjust_snap_realm_parent(mdsc, child, realm->ino);
-                       ceph_put_snap_realm(child);
+                       ceph_put_snap_realm(mdsc, child);
                }
 
-               ceph_put_snap_realm(realm);
+               ceph_put_snap_realm(mdsc, realm);
        }
 
        /*
@@ -676,7 +678,7 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc,
                                continue;
                        ci = ceph_inode(inode);
                        spin_lock(&inode->i_lock);
-                       ceph_put_snap_realm(ci->i_snap_realm);
+                       ceph_put_snap_realm(mdsc, ci->i_snap_realm);
                        list_add(&ci->i_snap_realm_item,
                                 &realm->inodes_with_caps);
                        ci->i_snap_realm = realm;
@@ -686,7 +688,7 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc,
                }
        }
 
-       ceph_put_snap_realm(realm);
+       ceph_put_snap_realm(mdsc, realm);
        up_write(&mdsc->snap_rwsem);
        return;
 
index f75e91ebff994c14ebb5f4e52950f4b06e8d2bb5..23b1d313f8a6cafc20a26a2d84c40e1e211b8bd4 100644 (file)
@@ -532,7 +532,8 @@ static inline int calc_pages_for(u64 off, u64 len)
 
 
 /* snap.c */
-extern void ceph_put_snap_realm(struct ceph_snap_realm *realm);
+extern void ceph_put_snap_realm(struct ceph_mds_client *mdsc,
+                               struct ceph_snap_realm *realm);
 extern struct ceph_snap_realm *ceph_update_snap_trace(struct ceph_mds_client *m,
                                                      void *p, void *e,
                                                      bool deletion);