Skip to content

Commit

Permalink
librbd: helper methods to query and break lock
Browse files Browse the repository at this point in the history
Signed-off-by: Mykola Golub <mgolub@mirantis.com>
  • Loading branch information
Mykola Golub committed Jan 13, 2017
1 parent 352a98c commit 2fba46f
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 12 deletions.
39 changes: 39 additions & 0 deletions src/librbd/ManagedLock.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

#include "librbd/ManagedLock.h"
#include "librbd/managed_lock/AcquireRequest.h"
#include "librbd/managed_lock/BreakRequest.h"
#include "librbd/managed_lock/GetLockerRequest.h"
#include "librbd/managed_lock/ReleaseRequest.h"
#include "librbd/managed_lock/ReacquireRequest.h"
#include "librbd/Watcher.h"
Expand Down Expand Up @@ -63,6 +65,14 @@ template <typename I>
bool ManagedLock<I>::is_lock_owner() const {
Mutex::Locker locker(m_lock);

return is_lock_owner(m_lock);
}

template <typename I>
bool ManagedLock<I>::is_lock_owner(Mutex &lock) const {

assert(m_lock.is_locked());

bool lock_owner;

switch (m_state) {
Expand Down Expand Up @@ -178,6 +188,35 @@ void ManagedLock<I>::reacquire_lock(Context *on_reacquired) {
}
}

template <typename I>
void ManagedLock<I>::get_locker(managed_lock::Locker *locker,
Context *on_finish) {
ldout(m_cct, 10) << dendl;

auto req = managed_lock::GetLockerRequest<I>::create(
m_ioctx, m_oid, locker, on_finish);
req->send();
}

template <typename I>
void ManagedLock<I>::break_lock(const managed_lock::Locker &locker,
bool blacklist_locker,
uint32_t blacklist_expire_seconds,
bool force_break_lock, Context *on_finish) {
{
Mutex::Locker l(m_lock);
if (!is_lock_owner(m_lock)) {
auto req = managed_lock::BreakRequest<I>::create(
m_ioctx, m_work_queue, m_oid, locker, blacklist_locker,
blacklist_expire_seconds, force_break_lock, on_finish);
req->send();
return;
}
}

on_finish->complete(-EBUSY);
}

template <typename I>
void ManagedLock<I>::shutdown_handler(int r, Context *on_finish) {
on_finish->complete(r);
Expand Down
6 changes: 6 additions & 0 deletions src/librbd/ManagedLock.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "include/Context.h"
#include "include/rados/librados.hpp"
#include "cls/lock/cls_lock_types.h"
#include "librbd/managed_lock/Types.h"
#include "librbd/watcher/Types.h"
#include "common/Mutex.h"
#include <list>
Expand Down Expand Up @@ -45,6 +46,10 @@ class ManagedLock {
void try_acquire_lock(Context *on_acquired);
void release_lock(Context *on_released);
void reacquire_lock(Context *on_reacquired = nullptr);
void get_locker(managed_lock::Locker *locker, Context *on_finish);
void break_lock(const managed_lock::Locker &locker, bool blacklist_locker,
uint32_t blacklist_expire_seconds, bool force_break_lock,
Context *on_finish);

bool is_shutdown() const {
Mutex::Locker l(m_lock);
Expand Down Expand Up @@ -161,6 +166,7 @@ class ManagedLock {

static std::string encode_lock_cookie(uint64_t watch_handle);

bool is_lock_owner(Mutex &lock) const;
bool is_transition_state() const;

void append_context(Action action, Context *ctx);
Expand Down
41 changes: 30 additions & 11 deletions src/librbd/internal.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1570,9 +1570,16 @@ void filter_out_mirror_watchers(ImageCtx *ictx,

managed_lock::Locker locker;
C_SaferCond get_owner_ctx;
auto get_owner_req = managed_lock::GetLockerRequest<>::create(
ictx->md_ctx, ictx->header_oid, &locker, &get_owner_ctx);
get_owner_req->send();
{
RWLock::RLocker l(ictx->owner_lock);

if (ictx->exclusive_lock == nullptr) {
lderr(cct) << "exclusive-lock feature is not enabled" << dendl;
return -EINVAL;
}

ictx->exclusive_lock->get_locker(&locker, &get_owner_ctx);
}

int r = get_owner_ctx.wait();
if (r == -ENOENT) {
Expand Down Expand Up @@ -1603,10 +1610,16 @@ void filter_out_mirror_watchers(ImageCtx *ictx,

managed_lock::Locker locker;
C_SaferCond get_owner_ctx;
auto get_owner_req = managed_lock::GetLockerRequest<>::create(
ictx->md_ctx, ictx->header_oid, &locker, &get_owner_ctx);
get_owner_req->send();
{
RWLock::RLocker l(ictx->owner_lock);

if (ictx->exclusive_lock == nullptr) {
lderr(cct) << "exclusive-lock feature is not enabled" << dendl;
return -EINVAL;
}

ictx->exclusive_lock->get_locker(&locker, &get_owner_ctx);
}
int r = get_owner_ctx.wait();
if (r == -ENOENT) {
return r;
Expand All @@ -1621,12 +1634,18 @@ void filter_out_mirror_watchers(ImageCtx *ictx,
}

C_SaferCond break_ctx;
auto break_req = managed_lock::BreakRequest<>::create(
ictx->md_ctx, ictx->op_work_queue, ictx->header_oid, locker,
ictx->blacklist_on_break_lock, ictx->blacklist_expire_seconds, true,
&break_ctx);
break_req->send();
{
RWLock::RLocker l(ictx->owner_lock);

if (ictx->exclusive_lock == nullptr) {
lderr(cct) << "exclusive-lock feature is not enabled" << dendl;
return -EINVAL;
}

ictx->exclusive_lock->break_lock(locker, ictx->blacklist_on_break_lock,
ictx->blacklist_expire_seconds, true,
&break_ctx);
}
r = break_ctx.wait();
if (r == -ENOENT) {
return r;
Expand Down
32 changes: 31 additions & 1 deletion src/test/librbd/test_mock_ManagedLock.cc
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
// -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab

#include "test/librbd/test_mock_fixture.h"
#include "test/librbd/test_support.h"
#include "librbd/ManagedLock.h"
#include "librbd/managed_lock/AcquireRequest.h"
#include "librbd/managed_lock/BreakRequest.h"
#include "librbd/managed_lock/GetLockerRequest.h"
#include "librbd/managed_lock/ReacquireRequest.h"
#include "librbd/managed_lock/ReleaseRequest.h"
#include "gmock/gmock.h"
Expand Down Expand Up @@ -70,6 +72,34 @@ struct ReleaseRequest<MockManagedLockImageCtx> : public BaseRequest<ReleaseReque
MOCK_METHOD0(send, void());
};

template <>
struct GetLockerRequest<MockManagedLockImageCtx> {
static GetLockerRequest* create(librados::IoCtx& ioctx,
const std::string& oid,
Locker *locker, Context *on_finish) {
assert(0 == "unexpected call");
}

void send() {
assert(0 == "unexpected call");
}
};

template <>
struct BreakRequest<MockManagedLockImageCtx> {
static BreakRequest* create(librados::IoCtx& ioctx, ContextWQ *work_queue,
const std::string& oid, const Locker &locker,
bool blacklist_locker,
uint32_t blacklist_expire_seconds,
bool force_break_lock, Context *on_finish) {
assert(0 == "unexpected call");
}

void send() {
assert(0 == "unexpected call");
}
};

} // namespace managed_lock
} // namespace librbd

Expand Down

0 comments on commit 2fba46f

Please sign in to comment.