#include "librbd/ExclusiveLock.h"
#include "librbd/ImageCtx.h"
#include "librbd/ImageState.h"
+#include "librbd/Journal.h"
#include "librbd/Utils.h"
#include "librbd/exclusive_lock/Policy.h"
#include "librbd/journal/Policy.h"
+#include <type_traits>
#define dout_subsys ceph_subsys_rbd_mirror
#undef dout_prefix
#define dout_prefix *_dout << "rbd::mirror::image_replayer::OpenLocalImageRequest: " \
- << this << " " << __func__
+ << this << " " << __func__ << " "
namespace rbd {
namespace mirror {
*m_local_image_ctx = I::create(m_local_image_name, m_local_image_id, nullptr,
m_local_io_ctx, false);
- (*m_local_image_ctx)->set_exclusive_lock_policy(
- new MirrorExclusiveLockPolicy());
- (*m_local_image_ctx)->set_journal_policy(
- new MirrorJournalPolicy(m_work_queue));
+ {
+ RWLock::WLocker owner_locker((*m_local_image_ctx)->owner_lock);
+ RWLock::WLocker snap_locker((*m_local_image_ctx)->snap_lock);
+ (*m_local_image_ctx)->set_exclusive_lock_policy(
+ new MirrorExclusiveLockPolicy());
+ (*m_local_image_ctx)->set_journal_policy(
+ new MirrorJournalPolicy(m_work_queue));
+ }
Context *ctx = create_context_callback<
OpenLocalImageRequest<I>, &OpenLocalImageRequest<I>::handle_open_image>(
<< cpp_strerror(r) << dendl;
send_close_image(true, r);
return;
- } else if ((*m_local_image_ctx)->exclusive_lock == nullptr) {
- derr << "image does not support exclusive lock" << dendl;
- send_close_image(false, -EINVAL);
- return;
}
send_lock_image();
template <typename I>
void OpenLocalImageRequest<I>::send_lock_image() {
+ // deduce the class type for the journal to support unit tests
+ typedef typename std::decay<decltype(*I::journal)>::type Journal;
+
dout(20) << dendl;
+ RWLock::RLocker owner_locker((*m_local_image_ctx)->owner_lock);
+ if ((*m_local_image_ctx)->exclusive_lock == nullptr) {
+ derr << "image does not support exclusive lock" << dendl;
+ send_close_image(false, -EINVAL);
+ return;
+ }
+
+ // TODO: make an async version
+ bool tag_owner;
+ int r = Journal::is_tag_owner(*m_local_image_ctx, &tag_owner);
+ if (r < 0) {
+ derr << "failed to query journal: " << cpp_strerror(r) << dendl;
+ send_close_image(false, r);
+ return;
+ }
+
+ // if the local image owns the tag -- don't steal the lock since
+ // we aren't going to mirror peer data into this image anyway
+ if (tag_owner) {
+ dout(10) << "local image is primary -- skipping image replay" << dendl;
+ send_close_image(false, -EREMOTEIO);
+ return;
+ }
+
Context *ctx = create_context_callback<
OpenLocalImageRequest<I>, &OpenLocalImageRequest<I>::handle_lock_image>(
this);
- RWLock::RLocker owner_locker((*m_local_image_ctx)->owner_lock);
(*m_local_image_ctx)->exclusive_lock->request_lock(ctx);
}