#include "librbd/ImageCtx.h"
#include "librbd/Utils.h"
#include "librbd/asio/ContextWQ.h"
+#include "librbd/asio/Utils.h"
#include "librbd/managed_lock/GetLockerRequest.h"
#define dout_subsys ceph_subsys_rbd
using util::create_context_callback;
using util::create_rados_callback;
-namespace {
-
-struct C_BlacklistClient : public Context {
- librados::IoCtx &ioctx;
- std::string locker_address;
- uint32_t expire_seconds;
- Context *on_finish;
-
- C_BlacklistClient(librados::IoCtx &ioctx, const std::string &locker_address,
- uint32_t expire_seconds, Context *on_finish)
- : ioctx(ioctx), locker_address(locker_address),
- expire_seconds(expire_seconds), on_finish(on_finish) {
- }
-
- void finish(int r) override {
- librados::Rados rados(ioctx);
- r = rados.blacklist_add(locker_address, expire_seconds);
- on_finish->complete(r);
- }
-};
-
-} // anonymous namespace
-
template <typename I>
BreakRequest<I>::BreakRequest(librados::IoCtx& ioctx,
AsioEngine& asio_engine,
return;
}
- // TODO: need async version of RadosClient::blacklist_add
- using klass = BreakRequest<I>;
- Context *ctx = create_context_callback<klass, &klass::handle_blacklist>(
- this);
- m_asio_engine.get_work_queue()->queue(
- new C_BlacklistClient(m_ioctx, m_locker.address,
- m_blacklist_expire_seconds, ctx), 0);
+ entity_addr_t locker_addr;
+ if (!locker_addr.parse(m_locker.address.c_str(), 0)) {
+ lderr(m_cct) << "unable to parse locker address: " << m_locker.address
+ << dendl;
+ finish(-EINVAL);
+ return;
+ }
+
+ std::stringstream cmd;
+ cmd << "{"
+ << "\"prefix\": \"osd blacklist\", "
+ << "\"blacklistop\": \"add\", "
+ << "\"addr\": \"" << locker_addr << "\"";
+ if (m_blacklist_expire_seconds != 0) {
+ cmd << ", \"expire\": " << m_blacklist_expire_seconds << ".0";
+ }
+ cmd << "}";
+
+ bufferlist in_bl;
+ m_asio_engine.get_rados_api().mon_command(
+ {cmd.str()}, in_bl, nullptr, nullptr,
+ librbd::asio::util::get_callback_adapter(
+ [this](int r) { handle_blacklist(r); }));
}
template <typename I>
finish(r);
return;
}
+
+ wait_for_osd_map();
+}
+
+template <typename I>
+void BreakRequest<I>::wait_for_osd_map() {
+ ldout(m_cct, 10) << dendl;
+
+ m_asio_engine.get_rados_api().wait_for_latest_osd_map(
+ librbd::asio::util::get_callback_adapter(
+ [this](int r) { handle_wait_for_osd_map(r); }));
+}
+
+template <typename I>
+void BreakRequest<I>::handle_wait_for_osd_map(int r) {
+ ldout(m_cct, 10) << "r=" << r << dendl;
+
+ if (r < 0) {
+ lderr(m_cct) << "failed to wait for updated OSD map: " << cpp_strerror(r)
+ << dendl;
+ finish(r);
+ return;
+ }
+
send_break_lock();
}
// template definitions
#include "librbd/managed_lock/BreakRequest.cc"
+MATCHER(IsBlacklistCommand, "") {
+ return (arg.size() == 1 &&
+ arg[0].find("\"blacklistop\": \"add\"") != std::string::npos);
+}
+
namespace librbd {
namespace managed_lock {
void expect_blacklist_add(MockTestImageCtx &mock_image_ctx, int r) {
- EXPECT_CALL(*get_mock_io_ctx(mock_image_ctx.md_ctx).get_mock_rados_client(),
- blacklist_add(_, _))
- .WillOnce(Return(r));
+ auto& mock_rados_client = librados::get_mock_rados_client(
+ mock_image_ctx.rados_api);
+ EXPECT_CALL(mock_rados_client, mon_command(IsBlacklistCommand(), _, _, _))
+ .WillOnce(Return(r));
+ }
+
+ void expect_wait_for_latest_osd_map(MockTestImageCtx &mock_image_ctx, int r) {
+ auto& mock_rados_client = librados::get_mock_rados_client(
+ mock_image_ctx.rados_api);
+ EXPECT_CALL(mock_rados_client, wait_for_latest_osd_map())
+ .WillOnce(Return(r));
}
void expect_break_lock(MockTestImageCtx &mock_image_ctx, int r) {
0);
expect_blacklist_add(mock_image_ctx, 0);
+ expect_wait_for_latest_osd_map(mock_image_ctx, 0);
expect_break_lock(mock_image_ctx, 0);
C_SaferCond ctx;
0);
expect_blacklist_add(mock_image_ctx, 0);
+ expect_wait_for_latest_osd_map(mock_image_ctx, 0);
expect_break_lock(mock_image_ctx, 0);
C_SaferCond ctx;
0);
expect_blacklist_add(mock_image_ctx, 0);
+ expect_wait_for_latest_osd_map(mock_image_ctx, 0);
expect_break_lock(mock_image_ctx, -ENOENT);
C_SaferCond ctx;
0);
expect_blacklist_add(mock_image_ctx, 0);
+ expect_wait_for_latest_osd_map(mock_image_ctx, 0);
expect_break_lock(mock_image_ctx, -EINVAL);
C_SaferCond ctx;