Skip to content

Commit 676947e

Browse files
committed
crimson/common/tri_mutex: make promotion atomic with func
Specifically, make promotion atomic with load-obc to fix assert(readers/writers == 1) failures. Fixes: https://tracker.ceph.com/issues/65451 Signed-off-by: Yingxin Cheng <[email protected]>
1 parent 26b96f9 commit 676947e

File tree

3 files changed

+24
-34
lines changed

3 files changed

+24
-34
lines changed

src/crimson/common/tri_mutex.cc

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,37 +35,26 @@ void excl_lock::unlock()
3535
static_cast<tri_mutex*>(this)->unlock_for_excl();
3636
}
3737

38-
seastar::future<> excl_lock_from_read::lock()
38+
void excl_lock_from_read::lock()
3939
{
4040
static_cast<tri_mutex*>(this)->promote_from_read();
41-
return seastar::now();
4241
}
4342

4443
void excl_lock_from_read::unlock()
4544
{
4645
static_cast<tri_mutex*>(this)->demote_to_read();
4746
}
4847

49-
seastar::future<> excl_lock_from_write::lock()
48+
void excl_lock_from_write::lock()
5049
{
5150
static_cast<tri_mutex*>(this)->promote_from_write();
52-
return seastar::now();
5351
}
5452

5553
void excl_lock_from_write::unlock()
5654
{
5755
static_cast<tri_mutex*>(this)->demote_to_write();
5856
}
5957

60-
seastar::future<> excl_lock_from_excl::lock()
61-
{
62-
return seastar::now();
63-
}
64-
65-
void excl_lock_from_excl::unlock()
66-
{
67-
}
68-
6958
tri_mutex::~tri_mutex()
7059
{
7160
assert(!is_acquired());

src/crimson/common/tri_mutex.h

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,21 +27,14 @@ class excl_lock {
2727
// promote from read to excl
2828
class excl_lock_from_read {
2929
public:
30-
seastar::future<> lock();
30+
void lock();
3131
void unlock();
3232
};
3333

3434
// promote from write to excl
3535
class excl_lock_from_write {
3636
public:
37-
seastar::future<> lock();
38-
void unlock();
39-
};
40-
41-
// promote from excl to excl
42-
class excl_lock_from_excl {
43-
public:
44-
seastar::future<> lock();
37+
void lock();
4538
void unlock();
4639
};
4740

@@ -58,12 +51,14 @@ class excl_lock_from_excl {
5851
/// - readers
5952
/// - writers
6053
/// - exclusive users
54+
///
55+
/// For lock promotion, a read or a write lock is only allowed to be promoted
56+
/// atomically upon the first locking.
6157
class tri_mutex : private read_lock,
6258
write_lock,
6359
excl_lock,
6460
excl_lock_from_read,
65-
excl_lock_from_write,
66-
excl_lock_from_excl
61+
excl_lock_from_write
6762
{
6863
public:
6964
tri_mutex() = default;
@@ -84,9 +79,6 @@ class tri_mutex : private read_lock,
8479
excl_lock_from_write& excl_from_write() {
8580
return *this;
8681
}
87-
excl_lock_from_excl& excl_from_excl() {
88-
return *this;
89-
}
9082

9183
// for shared readers
9284
seastar::future<> lock_for_read();

src/crimson/osd/object_context.h

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ class ObjectContext : public ceph::common::intrusive_lru_base<
121121
bool recovery_read_marker = false;
122122

123123
template <typename Lock, typename Func>
124-
auto _with_lock(Lock&& lock, Func&& func) {
124+
auto _with_lock(Lock& lock, Func&& func) {
125125
Ref obc = this;
126126
return lock.lock().then([&lock, func = std::forward<Func>(func), obc]() mutable {
127127
return seastar::futurize_invoke(func).finally([&lock, obc] {
@@ -130,6 +130,15 @@ class ObjectContext : public ceph::common::intrusive_lru_base<
130130
});
131131
}
132132

133+
template <typename Lock, typename Func>
134+
auto _with_promoted_lock(Lock& lock, Func&& func) {
135+
Ref obc = this;
136+
lock.lock();
137+
return seastar::futurize_invoke(func).finally([&lock, obc] {
138+
lock.unlock();
139+
});
140+
}
141+
133142
boost::intrusive::list_member_hook<> obc_accessing_hook;
134143
uint64_t list_link_cnt = 0;
135144
bool fully_loaded = false;
@@ -196,11 +205,11 @@ class ObjectContext : public ceph::common::intrusive_lru_base<
196205
auto wrapper = ::crimson::interruptible::interruptor<InterruptCond>::wrap_function(std::forward<Func>(func));
197206
switch (Type) {
198207
case RWState::RWWRITE:
199-
return _with_lock(lock.excl_from_write(), std::move(wrapper));
208+
return _with_promoted_lock(lock.excl_from_write(), std::move(wrapper));
200209
case RWState::RWREAD:
201-
return _with_lock(lock.excl_from_read(), std::move(wrapper));
210+
return _with_promoted_lock(lock.excl_from_read(), std::move(wrapper));
202211
case RWState::RWEXCL:
203-
return _with_lock(lock.excl_from_excl(), std::move(wrapper));
212+
return seastar::futurize_invoke(std::move(wrapper));
204213
case RWState::RWNONE:
205214
return _with_lock(lock.for_excl(), std::move(wrapper));
206215
default:
@@ -209,11 +218,11 @@ class ObjectContext : public ceph::common::intrusive_lru_base<
209218
} else {
210219
switch (Type) {
211220
case RWState::RWWRITE:
212-
return _with_lock(lock.excl_from_write(), std::forward<Func>(func));
221+
return _with_promoted_lock(lock.excl_from_write(), std::forward<Func>(func));
213222
case RWState::RWREAD:
214-
return _with_lock(lock.excl_from_read(), std::forward<Func>(func));
223+
return _with_promoted_lock(lock.excl_from_read(), std::forward<Func>(func));
215224
case RWState::RWEXCL:
216-
return _with_lock(lock.excl_from_excl(), std::forward<Func>(func));
225+
return seastar::futurize_invoke(std::forward<Func>(func));
217226
case RWState::RWNONE:
218227
return _with_lock(lock.for_excl(), std::forward<Func>(func));
219228
default:

0 commit comments

Comments
 (0)