diff options
author | Michael Cahill <michael.cahill@mongodb.com> | 2016-02-23 10:25:03 +1100 |
---|---|---|
committer | Michael Cahill <michael.cahill@mongodb.com> | 2016-02-23 10:25:03 +1100 |
commit | 62b3ca8a7a07287205fca35bc49c24db121c0855 (patch) | |
tree | 90ecac2f3fcc1f51ae91d7d6fa26d8ea58cc19d0 | |
parent | cae5fcf57a7b13d742f687f3f064574a004d0537 (diff) | |
parent | 39adc781ce9de9f4e562015cc9cccc70eb5e9e3e (diff) | |
download | mongo-62b3ca8a7a07287205fca35bc49c24db121c0855.tar.gz |
Merge pull request #2514 from wiredtiger/server-22554-backport
SERVER-22554 Fix a reference counting bug in dhandles.
-rw-r--r-- | src/session/session_dhandle.c | 40 |
1 files changed, 33 insertions, 7 deletions
diff --git a/src/session/session_dhandle.c b/src/session/session_dhandle.c index 63635b54032..5c9d5688c14 100644 --- a/src/session/session_dhandle.c +++ b/src/session/session_dhandle.c @@ -360,10 +360,32 @@ __session_dhandle_sweep(WT_SESSION_IMPL *session) */ static int __session_find_shared_dhandle(WT_SESSION_IMPL *session, - const char *uri, const char *checkpoint, uint32_t flags) + WT_DATA_HANDLE_CACHE **dhandle_cachep, const char *uri, + const char *checkpoint, uint32_t flags) { WT_RET(__wt_conn_dhandle_find(session, uri, checkpoint, flags)); - (void)__wt_atomic_add32(&session->dhandle->session_ref, 1); + WT_RET(__session_add_dhandle(session, dhandle_cachep)); + return (0); +} + +/* + * __session_get_shared_dhandle -- + * Open a data handle and add it to the connection cache. Bump the + * reference + * cache. Since the data handle isn't locked, this must be called holding + * the handle list lock, and we must increment the handle's reference + * count before releasing it. + */ +static int +__session_get_shared_dhandle(WT_SESSION_IMPL *session, + WT_DATA_HANDLE_CACHE **dhandle_cachep, const char *uri, + const char *checkpoint, const char *cfg[], uint32_t flags) +{ + + WT_RET(__wt_conn_btree_get(session, uri, checkpoint, cfg, flags)); + /* Bump the reference count when opening the file for the first time */ + if (!LF_ISSET(WT_DHANDLE_HAVE_REF)) + WT_RET(__session_add_dhandle(session, dhandle_cachep)); return (0); } @@ -394,7 +416,7 @@ __wt_session_get_btree(WT_SESSION_IMPL *session, */ WT_WITH_HANDLE_LIST_LOCK(session, ret = __session_find_shared_dhandle( - session, uri, checkpoint, flags)); + session, &dhandle_cache, uri, checkpoint, flags)); dhandle = (ret == 0) ? session->dhandle : NULL; WT_RET_NOTFOUND_OK(ret); } @@ -420,6 +442,12 @@ __wt_session_get_btree(WT_SESSION_IMPL *session, WT_SESSION_LOCKED_HANDLE_LIST | WT_SESSION_LOCKED_TABLE))) return (ret); + /* + * If we retrieved a dhandle it needs to have been added to + * our session cache already. + */ + WT_ASSERT(session, dhandle_cache != NULL); + /* If we found the handle and it isn't dead, reopen it. */ if (is_dead) { __session_discard_dhandle(session, dhandle_cache); @@ -445,7 +473,8 @@ retry: is_dead = 0; WT_WITH_HANDLE_LIST_LOCK(session, ret = (is_dead = (dhandle != NULL && F_ISSET(dhandle, WT_DHANDLE_DEAD))) ? - 0 : __wt_conn_btree_get(session, uri, checkpoint, cfg, flags))); + 0 : __session_get_shared_dhandle( + session, &dhandle_cache, uri, checkpoint, cfg, flags))); if (is_dead) { if (dhandle_cache != NULL) @@ -457,9 +486,6 @@ retry: is_dead = 0; } WT_RET(ret); - if (!LF_ISSET(WT_DHANDLE_HAVE_REF)) - WT_RET(__session_add_dhandle(session, NULL)); - WT_ASSERT(session, LF_ISSET(WT_DHANDLE_LOCK_ONLY) || (F_ISSET(session->dhandle, WT_DHANDLE_OPEN) && !F_ISSET(session->dhandle, WT_DHANDLE_DEAD))); |