Action active_action = get_active_action();
ceph_assert(active_action == ACTION_TRY_LOCK ||
active_action == ACTION_ACQUIRE_LOCK);
- complete_active_action(STATE_UNLOCKED, -ESHUTDOWN);
+ complete_active_action(STATE_UNLOCKED, -ERESTART);
}
execute_action(ACTION_SHUT_DOWN, on_shut_down);
{
std::lock_guard locker{m_lock};
if (is_state_shutdown()) {
- r = -ESHUTDOWN;
+ r = -ERESTART;
} else if (m_state != STATE_LOCKED || !m_actions_contexts.empty()) {
ldout(m_cct, 10) << dendl;
execute_action(ACTION_ACQUIRE_LOCK, on_acquired);
{
std::lock_guard locker{m_lock};
if (is_state_shutdown()) {
- r = -ESHUTDOWN;
+ r = -ERESTART;
} else if (m_state != STATE_LOCKED || !m_actions_contexts.empty()) {
ldout(m_cct, 10) << dendl;
execute_action(ACTION_TRY_LOCK, on_acquired);
{
std::lock_guard locker{m_lock};
if (is_state_shutdown()) {
- r = -ESHUTDOWN;
+ r = -ERESTART;
} else if (m_state != STATE_UNLOCKED || !m_actions_contexts.empty()) {
ldout(m_cct, 10) << dendl;
execute_action(ACTION_RELEASE_LOCK, on_released);
{
std::lock_guard l{m_lock};
if (is_state_shutdown()) {
- r = -ESHUTDOWN;
+ r = -ERESTART;
} else {
on_finish = new C_Tracked(m_async_op_tracker, on_finish);
auto req = managed_lock::GetLockerRequest<I>::create(
{
std::lock_guard l{m_lock};
if (is_state_shutdown()) {
- r = -ESHUTDOWN;
+ r = -ERESTART;
} else if (is_lock_owner(m_lock)) {
r = -EBUSY;
} else {
// shut down might race w/ release/re-acquire of the lock
if (is_state_shutdown()) {
- complete_active_action(STATE_UNLOCKED, -ESHUTDOWN);
+ complete_active_action(STATE_UNLOCKED, -ERESTART);
}
}
return;
#include "cls/journal/cls_journal_client.h"
#include "cls/rbd/cls_rbd_client.h"
#include "cls/rbd/cls_rbd_types.h"
+#include "test/librados/test_cxx.h"
#include "test/librbd/test_fixture.h"
#include "test/librbd/test_support.h"
#include "include/rbd/librbd.h"
ASSERT_EQ(-EROFS, ictx2->operations->flatten(no_op));
}
+TEST_F(TestInternal, WriteFailsToLockImageBlocklisted) {
+ REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
+
+ librados::Rados blocklist_rados;
+ ASSERT_EQ("", connect_cluster_pp(blocklist_rados));
+
+ librados::IoCtx blocklist_ioctx;
+ ASSERT_EQ(0, blocklist_rados.ioctx_create(_pool_name.c_str(),
+ blocklist_ioctx));
+
+ auto ictx = new librbd::ImageCtx(m_image_name, "", nullptr, blocklist_ioctx,
+ false);
+ ASSERT_EQ(0, ictx->state->open(0));
+
+ std::list<librbd::image_watcher_t> watchers;
+ ASSERT_EQ(0, librbd::list_watchers(ictx, watchers));
+ ASSERT_EQ(1U, watchers.size());
+
+ bool lock_owner;
+ ASSERT_EQ(0, librbd::is_exclusive_lock_owner(ictx, &lock_owner));
+ ASSERT_FALSE(lock_owner);
+
+ ASSERT_EQ(0, blocklist_rados.blocklist_add(watchers.front().addr, 0));
+
+ ceph::bufferlist bl;
+ bl.append(std::string(256, '1'));
+ ASSERT_EQ(-EBLOCKLISTED, api::Io<>::write(*ictx, 0, bl.length(),
+ std::move(bl), 0));
+ ASSERT_EQ(-EBLOCKLISTED, librbd::is_exclusive_lock_owner(ictx, &lock_owner));
+
+ close_image(ictx);
+}
+
+TEST_F(TestInternal, WriteFailsToLockImageBlocklistedWatch) {
+ REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
+
+ librados::Rados blocklist_rados;
+ ASSERT_EQ("", connect_cluster_pp(blocklist_rados));
+
+ librados::IoCtx blocklist_ioctx;
+ ASSERT_EQ(0, blocklist_rados.ioctx_create(_pool_name.c_str(),
+ blocklist_ioctx));
+
+ auto ictx = new librbd::ImageCtx(m_image_name, "", nullptr, blocklist_ioctx,
+ false);
+ ASSERT_EQ(0, ictx->state->open(0));
+
+ std::list<librbd::image_watcher_t> watchers;
+ ASSERT_EQ(0, librbd::list_watchers(ictx, watchers));
+ ASSERT_EQ(1U, watchers.size());
+
+ bool lock_owner;
+ ASSERT_EQ(0, librbd::is_exclusive_lock_owner(ictx, &lock_owner));
+ ASSERT_FALSE(lock_owner);
+
+ ASSERT_EQ(0, blocklist_rados.blocklist_add(watchers.front().addr, 0));
+ // let ImageWatcher discover that the watch can't be re-registered to
+ // eliminate the (intended) race in WriteFailsToLockImageBlocklisted
+ while (!ictx->image_watcher->is_blocklisted()) {
+ sleep(1);
+ }
+
+ ceph::bufferlist bl;
+ bl.append(std::string(256, '1'));
+ ASSERT_EQ(-EBLOCKLISTED, api::Io<>::write(*ictx, 0, bl.length(),
+ std::move(bl), 0));
+ ASSERT_EQ(-EBLOCKLISTED, librbd::is_exclusive_lock_owner(ictx, &lock_owner));
+
+ close_image(ictx);
+}
+
TEST_F(TestInternal, AioWriteRequestsLock) {
REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);