Skip to content

Commit f63d76a

Browse files
cyx1231stMatan-B
authored andcommitted
crimson/common/tri_mutex: make lock() atomic if doesn't need wait
Otherwise, promotion cannot be atomic with the 1st locker. Identified by: Matan Breizman <[email protected]> Signed-off-by: Yingxin Cheng <[email protected]>
1 parent 251b9d4 commit f63d76a

File tree

3 files changed

+38
-19
lines changed

3 files changed

+38
-19
lines changed

src/crimson/common/tri_mutex.cc

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
SET_SUBSYS(osd);
99
//TODO: SET_SUBSYS(crimson_tri_mutex);
1010

11-
seastar::future<> read_lock::lock()
11+
std::optional<seastar::future<>>
12+
read_lock::lock()
1213
{
1314
return static_cast<tri_mutex*>(this)->lock_for_read();
1415
}
@@ -18,7 +19,8 @@ void read_lock::unlock()
1819
static_cast<tri_mutex*>(this)->unlock_for_read();
1920
}
2021

21-
seastar::future<> write_lock::lock()
22+
std::optional<seastar::future<>>
23+
write_lock::lock()
2224
{
2325
return static_cast<tri_mutex*>(this)->lock_for_write();
2426
}
@@ -28,7 +30,8 @@ void write_lock::unlock()
2830
static_cast<tri_mutex*>(this)->unlock_for_write();
2931
}
3032

31-
seastar::future<> excl_lock::lock()
33+
std::optional<seastar::future<>>
34+
excl_lock::lock()
3235
{
3336
return static_cast<tri_mutex*>(this)->lock_for_excl();
3437
}
@@ -65,13 +68,14 @@ tri_mutex::~tri_mutex()
6568
assert(!is_acquired());
6669
}
6770

68-
seastar::future<> tri_mutex::lock_for_read()
71+
std::optional<seastar::future<>>
72+
tri_mutex::lock_for_read()
6973
{
7074
LOG_PREFIX(tri_mutex::lock_for_read());
7175
DEBUGDPP("", *this);
7276
if (try_lock_for_read()) {
7377
DEBUGDPP("lock_for_read successfully", *this);
74-
return seastar::now();
78+
return std::nullopt;
7579
}
7680
DEBUGDPP("can't lock_for_read, adding to waiters", *this);
7781
waiters.emplace_back(seastar::promise<>(), type_t::read, name);
@@ -117,13 +121,14 @@ void tri_mutex::demote_to_read()
117121
++readers;
118122
}
119123

120-
seastar::future<> tri_mutex::lock_for_write()
124+
std::optional<seastar::future<>>
125+
tri_mutex::lock_for_write()
121126
{
122127
LOG_PREFIX(tri_mutex::lock_for_write());
123128
DEBUGDPP("", *this);
124129
if (try_lock_for_write()) {
125130
DEBUGDPP("lock_for_write successfully", *this);
126-
return seastar::now();
131+
return std::nullopt;
127132
}
128133
DEBUGDPP("can't lock_for_write, adding to waiters", *this);
129134
waiters.emplace_back(seastar::promise<>(), type_t::write, name);
@@ -170,13 +175,14 @@ void tri_mutex::demote_to_write()
170175
}
171176

172177
// for exclusive users
173-
seastar::future<> tri_mutex::lock_for_excl()
178+
std::optional<seastar::future<>>
179+
tri_mutex::lock_for_excl()
174180
{
175181
LOG_PREFIX(tri_mutex::lock_for_excl());
176182
DEBUGDPP("", *this);
177183
if (try_lock_for_excl()) {
178184
DEBUGDPP("lock_for_excl, successfully", *this);
179-
return seastar::now();
185+
return std::nullopt;
180186
}
181187
DEBUGDPP("can't lock_for_excl, adding to waiters", *this);
182188
waiters.emplace_back(seastar::promise<>(), type_t::exclusive, name);

src/crimson/common/tri_mutex.h

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,27 @@
33

44
#pragma once
55

6+
#include <optional>
7+
68
#include <seastar/core/future.hh>
79
#include <seastar/core/circular_buffer.hh>
810
#include "crimson/common/log.h"
911

1012
class read_lock {
1113
public:
12-
seastar::future<> lock();
14+
std::optional<seastar::future<>> lock();
1315
void unlock();
1416
};
1517

1618
class write_lock {
1719
public:
18-
seastar::future<> lock();
20+
std::optional<seastar::future<>> lock();
1921
void unlock();
2022
};
2123

2224
class excl_lock {
2325
public:
24-
seastar::future<> lock();
26+
std::optional<seastar::future<>> lock();
2527
void unlock();
2628
};
2729

@@ -87,7 +89,7 @@ class tri_mutex : private read_lock,
8789
}
8890

8991
// for shared readers
90-
seastar::future<> lock_for_read();
92+
std::optional<seastar::future<>> lock_for_read();
9193
bool try_lock_for_read() noexcept;
9294
void unlock_for_read();
9395
void promote_from_read();
@@ -97,7 +99,7 @@ class tri_mutex : private read_lock,
9799
}
98100

99101
// for shared writers
100-
seastar::future<> lock_for_write();
102+
std::optional<seastar::future<>> lock_for_write();
101103
bool try_lock_for_write() noexcept;
102104
void unlock_for_write();
103105
void promote_from_write();
@@ -107,7 +109,7 @@ class tri_mutex : private read_lock,
107109
}
108110

109111
// for exclusive users
110-
seastar::future<> lock_for_excl();
112+
std::optional<seastar::future<>> lock_for_excl();
111113
bool try_lock_for_excl() noexcept;
112114
void unlock_for_excl();
113115
bool is_excl_acquired() const {

src/crimson/osd/object_context.h

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -138,10 +138,21 @@ class ObjectContext : public ceph::common::intrusive_lru_base<
138138
template <typename Lock, typename Func>
139139
auto _with_lock(Lock& lock, Func&& func) {
140140
Ref obc = this;
141-
return lock.lock().then([&lock, func = std::forward<Func>(func), obc]() mutable {
142-
return seastar::futurize_invoke(func).finally([&lock, obc] {
143-
lock.unlock();
144-
});
141+
auto maybe_fut = lock.lock();
142+
return seastar::futurize_invoke([
143+
maybe_fut=std::move(maybe_fut),
144+
func=std::forward<Func>(func)]() mutable {
145+
if (maybe_fut) {
146+
return std::move(*maybe_fut
147+
).then([func=std::forward<Func>(func)]() mutable {
148+
return seastar::futurize_invoke(func);
149+
});
150+
} else {
151+
// atomically calling func upon locking
152+
return seastar::futurize_invoke(func);
153+
}
154+
}).finally([&lock, obc] {
155+
lock.unlock();
145156
});
146157
}
147158

0 commit comments

Comments
 (0)