]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
crimson: fix ObjectContext::_with_lock to only unlock if lock is taken 58824/head
authorSamuel Just <sjust@redhat.com>
Thu, 13 Jun 2024 00:41:55 +0000 (00:41 +0000)
committerMatan Breizman <mbreizma@redhat.com>
Thu, 25 Jul 2024 07:32:11 +0000 (10:32 +0300)
Fixes: https://tracker.ceph.com/issues/66461
Signed-off-by: Samuel Just <sjust@redhat.com>
(cherry picked from commit 9e0c518d37ce1ba17139629e75d780cc0f0f064f)

src/crimson/osd/object_context.h

index 466f22b8372f37138f80a878d3c0ec4e5ac91670..b1a1e893827678ed82700d0dffc520be33e52849 100644 (file)
@@ -137,22 +137,34 @@ public:
 private:
   template <typename Lock, typename Func>
   auto _with_lock(Lock& lock, Func&& func) {
-    Ref obc = this;
     auto maybe_fut = lock.lock();
     return seastar::futurize_invoke([
         maybe_fut=std::move(maybe_fut),
-        func=std::forward<Func>(func)]() mutable {
+        func=std::forward<Func>(func),
+       obc=Ref(this),
+       &lock]() mutable {
       if (maybe_fut) {
         return std::move(*maybe_fut
-        ).then([func=std::forward<Func>(func)]() mutable {
-          return seastar::futurize_invoke(func);
+        ).then([func=std::forward<Func>(func), obc, &lock]() mutable {
+          return seastar::futurize_invoke(
+           func
+         ).finally([&lock, obc] {
+           /* We chain the finally block here because it's possible for
+            * *maybe_fut from lock.lock() above to fail due to a call to
+            * ObjectContext::interrupt, which calls tri_mutex::abort.
+            * In the event of such an error, the lock isn't actually taken
+            * and calling unlock() would be incorrect. */
+           lock.unlock();
+         });
         });
       } else {
         // atomically calling func upon locking
-        return seastar::futurize_invoke(func);
+        return seastar::futurize_invoke(
+         func
+       ).finally([&lock, obc] {
+         lock.unlock();
+       });
       }
-    }).finally([&lock, obc] {
-      lock.unlock();
     });
   }