From: Sage Weil Date: Thu, 5 Mar 2009 22:03:31 +0000 (-0800) Subject: kclient: fix snap_realm leak X-Git-Tag: v0.7~25^2~3 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=ff52f0a10b8f76cd4c3b0dd6b74a1fe1a1727017;p=ceph.git kclient: fix snap_realm leak Separate lookup/create from get (this is safe because we always hold span_rwsem during these operations). --- diff --git a/src/kernel/caps.c b/src/kernel/caps.c index a89f2c9abba..7b796df14ad 100644 --- a/src/kernel/caps.c +++ b/src/kernel/caps.c @@ -273,9 +273,10 @@ retry: __adjust_cap_rdcaps_listing(ci, cap, __ceph_caps_wanted(ci) | wanted); if (!ci->i_snap_realm) { - struct ceph_snap_realm *realm = ceph_get_snap_realm(mdsc, - realmino); + struct ceph_snap_realm *realm = ceph_lookup_snap_realm(mdsc, + realmino); if (realm) { + ceph_get_snap_realm(mdsc, realm); ci->i_snap_realm = realm; list_add(&ci->i_snap_realm_item, &realm->inodes_with_caps); } else { diff --git a/src/kernel/snap.c b/src/kernel/snap.c index 0137ecc1671..f034b1ff722 100644 --- a/src/kernel/snap.c +++ b/src/kernel/snap.c @@ -62,9 +62,11 @@ int ceph_debug_snap __read_mostly = -1; * * caller must hold snap_rwsem for write. */ -static void get_realm(struct ceph_mds_client *mdsc, - struct ceph_snap_realm *realm) +void ceph_get_snap_realm(struct ceph_mds_client *mdsc, + struct ceph_snap_realm *realm) { + dout(20, "get_realm %p %d -> %d\n", realm, + atomic_read(&realm->nref), atomic_read(&realm->nref)+1); /* * since we _only_ increment realm refs or empty the empty * list with snap_rwsem held, adjusting the empty list here is @@ -111,17 +113,14 @@ static struct ceph_snap_realm *ceph_create_snap_realm(struct ceph_mds_client *md * * caller must hold snap_rwsem for write. */ -struct ceph_snap_realm *ceph_get_snap_realm(struct ceph_mds_client *mdsc, - u64 ino) +struct ceph_snap_realm *ceph_lookup_snap_realm(struct ceph_mds_client *mdsc, + u64 ino) { struct ceph_snap_realm *realm; realm = radix_tree_lookup(&mdsc->snap_realms, ino); - if (realm) { - dout(20, "get_snap_realm %llx %p %d -> %d\n", realm->ino, realm, - atomic_read(&realm->nref), atomic_read(&realm->nref)+1); - get_realm(mdsc, realm); - } + if (realm) + dout(20, "lookup_snap_realm %llx %p\n", realm->ino, realm); return realm; } @@ -229,7 +228,7 @@ static int adjust_snap_realm_parent(struct ceph_mds_client *mdsc, if (realm->parent_ino == parentino) return 0; - parent = ceph_get_snap_realm(mdsc, parentino); + parent = ceph_lookup_snap_realm(mdsc, parentino); if (IS_ERR(parent)) return PTR_ERR(parent); if (!parent) { @@ -246,7 +245,7 @@ static int adjust_snap_realm_parent(struct ceph_mds_client *mdsc, } realm->parent_ino = parentino; realm->parent = parent; - get_realm(mdsc, parent); + ceph_get_snap_realm(mdsc, parent); list_add(&realm->child_item, &parent->children); return 1; } @@ -540,7 +539,7 @@ more: prior_parent_snaps = p; p += sizeof(u64) * le32_to_cpu(ri->num_prior_parent_snaps); - realm = ceph_get_snap_realm(mdsc, le64_to_cpu(ri->ino)); + realm = ceph_lookup_snap_realm(mdsc, le64_to_cpu(ri->ino)); if (IS_ERR(realm)) { err = PTR_ERR(realm); goto fail; @@ -613,15 +612,14 @@ more: dout(10, "done with %llx %p, invalidated=%d, %p %p\n", realm->ino, realm, invalidate, p, e); - /* invalidate when we reach the _end_ (root) of the trace */ - if (p == e && invalidate) - rebuild_snap_realms(realm); - if (p < e) goto more; - __cleanup_empty_realms(mdsc); + /* invalidate when we reach the _end_ (root) of the trace */ + if (invalidate) + rebuild_snap_realms(realm); + __cleanup_empty_realms(mdsc); return 0; bad: @@ -751,15 +749,15 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc, * ceph_update_snap_trace. */ ri = p; - realm = ceph_get_snap_realm(mdsc, split); + realm = ceph_lookup_snap_realm(mdsc, split); if (IS_ERR(realm)) goto out; if (!realm) { realm = ceph_create_snap_realm(mdsc, split); if (IS_ERR(realm)) goto out; - get_realm(mdsc, realm); } + ceph_get_snap_realm(mdsc, realm); dout(10, "splitting snap_realm %llx %p\n", realm->ino, realm); for (i = 0; i < num_split_inos; i++) { @@ -817,14 +815,13 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc, /* we may have taken some of the old realm's children. */ for (i = 0; i < num_split_realms; i++) { struct ceph_snap_realm *child = - ceph_get_snap_realm(mdsc, + ceph_lookup_snap_realm(mdsc, le64_to_cpu(split_realms[i])); if (IS_ERR(child)) continue; if (!child) continue; adjust_snap_realm_parent(mdsc, child, realm->ino); - ceph_put_snap_realm(mdsc, child); } } @@ -857,7 +854,7 @@ 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; - get_realm(mdsc, realm); + ceph_get_snap_realm(mdsc, realm); split_skip_inode: spin_unlock(&inode->i_lock); iput(inode); diff --git a/src/kernel/super.h b/src/kernel/super.h index b8b36dde286..f0a554dca6a 100644 --- a/src/kernel/super.h +++ b/src/kernel/super.h @@ -620,8 +620,10 @@ static inline int calc_pages_for(u64 off, u64 len) /* snap.c */ -struct ceph_snap_realm *ceph_get_snap_realm(struct ceph_mds_client *mdsc, - u64 ino); +struct ceph_snap_realm *ceph_lookup_snap_realm(struct ceph_mds_client *mdsc, + u64 ino); +extern void ceph_get_snap_realm(struct ceph_mds_client *mdsc, + struct ceph_snap_realm *realm); extern void ceph_put_snap_realm(struct ceph_mds_client *mdsc, struct ceph_snap_realm *realm); extern int ceph_update_snap_trace(struct ceph_mds_client *m,