]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: fix lock scope in ObjectCache::get() 44747/head
authorCasey Bodley <cbodley@redhat.com>
Mon, 18 Oct 2021 15:23:49 +0000 (11:23 -0400)
committerYuma Ogami <yuma-ogami@cybozu.co.jp>
Mon, 24 Jan 2022 05:06:42 +0000 (05:06 +0000)
in the touch_lru() case, we promote the shared_lock to a unique_lock.
but because the unique_lock is in a nested scope, the lock drops with
its scope and we continue accessing the map without any protection

this moves the unique_lock up to function scope, where it's
constructed as unlocked with std::defer_lock. after promotion, this
lock will be held until the function returns

Fixes: https://tracker.ceph.com/issues/52800
Signed-off-by: Casey Bodley <cbodley@redhat.com>
(cherry picked from commit 1aee987ec8f817541aab9cd21480b5351df38f69)

src/rgw/rgw_cache.cc

index e82c142eb024042ba06e742a3a408582910fe6a8..346b86193c99a6dc597d9802f5702e572fff9541 100644 (file)
@@ -13,6 +13,7 @@ int ObjectCache::get(const DoutPrefixProvider *dpp, const string& name, ObjectCa
 {
 
   std::shared_lock rl{lock};
+  std::unique_lock wl{lock, std::defer_lock}; // may be promoted to write lock
   if (!enabled) {
     return -ENOENT;
   }
@@ -29,7 +30,7 @@ int ObjectCache::get(const DoutPrefixProvider *dpp, const string& name, ObjectCa
        (ceph::coarse_mono_clock::now() - iter->second.info.time_added) > expiry) {
     ldpp_dout(dpp, 10) << "cache get: name=" << name << " : expiry miss" << dendl;
     rl.unlock();
-    std::unique_lock wl{lock};  // write lock for insertion
+    wl.lock(); // write lock for expiration
     // check that wasn't already removed by other thread
     iter = cache_map.find(name);
     if (iter != cache_map.end()) {
@@ -50,7 +51,7 @@ int ObjectCache::get(const DoutPrefixProvider *dpp, const string& name, ObjectCa
     ldpp_dout(dpp, 20) << "cache get: touching lru, lru_counter=" << lru_counter
                    << " promotion_ts=" << entry->lru_promotion_ts << dendl;
     rl.unlock();
-    std::unique_lock wl{lock};  // write lock for insertion
+    wl.lock(); // write lock for touch_lru()
     /* need to redo this because entry might have dropped off the cache */
     iter = cache_map.find(name);
     if (iter == cache_map.end()) {