template <typename I>
void ExclusiveLock<I>::try_lock(Context *on_tried_lock) {
+ int r = 0;
{
Mutex::Locker locker(m_lock);
assert(m_image_ctx.owner_lock.is_locked());
- assert(!is_shutdown());
-
- if (m_state != STATE_LOCKED || !m_actions_contexts.empty()) {
+ if (is_shutdown()) {
+ r = -ESHUTDOWN;
+ } else if (m_state != STATE_LOCKED || !m_actions_contexts.empty()) {
ldout(m_image_ctx.cct, 10) << this << " " << __func__ << dendl;
execute_action(ACTION_TRY_LOCK, on_tried_lock);
return;
}
}
- on_tried_lock->complete(0);
+ on_tried_lock->complete(r);
}
template <typename I>
void ExclusiveLock<I>::request_lock(Context *on_locked) {
+ int r = 0;
{
Mutex::Locker locker(m_lock);
assert(m_image_ctx.owner_lock.is_locked());
- assert(!is_shutdown());
- if (m_state != STATE_LOCKED || !m_actions_contexts.empty()) {
+ if (is_shutdown()) {
+ r = -ESHUTDOWN;
+ } else if (m_state != STATE_LOCKED || !m_actions_contexts.empty()) {
ldout(m_image_ctx.cct, 10) << this << " " << __func__ << dendl;
execute_action(ACTION_REQUEST_LOCK, on_locked);
return;
}
if (on_locked != nullptr) {
- on_locked->complete(0);
+ on_locked->complete(r);
}
}
template <typename I>
void ExclusiveLock<I>::release_lock(Context *on_released) {
+ int r = 0;
{
Mutex::Locker locker(m_lock);
assert(m_image_ctx.owner_lock.is_locked());
- assert(!is_shutdown());
-
- if (m_state != STATE_UNLOCKED || !m_actions_contexts.empty()) {
+ if (is_shutdown()) {
+ r = -ESHUTDOWN;
+ } else if (m_state != STATE_UNLOCKED || !m_actions_contexts.empty()) {
ldout(m_image_ctx.cct, 10) << this << " " << __func__ << dendl;
execute_action(ACTION_RELEASE_LOCK, on_released);
return;
}
}
- on_released->complete(0);
+ on_released->complete(r);
}
template <typename I>
assert(m_lock.is_locked());
if (m_state == STATE_UNLOCKED) {
m_state = STATE_SHUTTING_DOWN;
- m_image_ctx.aio_work_queue->clear_require_lock_on_read();
- m_image_ctx.aio_work_queue->unblock_writes();
- m_image_ctx.image_watcher->flush(util::create_context_callback<
- ExclusiveLock<I>, &ExclusiveLock<I>::complete_shutdown>(this));
+ m_image_ctx.op_work_queue->queue(util::create_context_callback<
+ ExclusiveLock<I>, &ExclusiveLock<I>::handle_unlocked_shutdown>(this), 0);
return;
}
using el = ExclusiveLock<I>;
ReleaseRequest<I>* req = ReleaseRequest<I>::create(
m_image_ctx, cookie, nullptr,
- util::create_context_callback<el, &el::handle_shutdown>(this));
+ util::create_context_callback<el, &el::handle_locked_shutdown>(this));
req->send();
}
template <typename I>
-void ExclusiveLock<I>::handle_shutdown(int r) {
+void ExclusiveLock<I>::handle_locked_shutdown(int r) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 10) << this << " " << __func__ << ": r=" << r << dendl;
+ {
+ RWLock::WLocker owner_locker(m_image_ctx.owner_lock);
+ m_image_ctx.exclusive_lock = nullptr;
+ }
+
if (r < 0) {
lderr(cct) << "failed to shut down exclusive lock: " << cpp_strerror(r)
<< dendl;
complete_shutdown(r);
}
+template <typename I>
+void ExclusiveLock<I>::handle_unlocked_shutdown(int r) {
+ CephContext *cct = m_image_ctx.cct;
+ ldout(cct, 10) << this << " " << __func__ << ": r=" << r << dendl;
+
+ {
+ RWLock::WLocker owner_locker(m_image_ctx.owner_lock);
+ m_image_ctx.exclusive_lock = nullptr;
+ }
+
+ m_image_ctx.aio_work_queue->clear_require_lock_on_read();
+ m_image_ctx.aio_work_queue->unblock_writes();
+ m_image_ctx.image_watcher->flush(util::create_context_callback<
+ ExclusiveLock<I>, &ExclusiveLock<I>::complete_shutdown>(this));
+}
+
template <typename I>
void ExclusiveLock<I>::complete_shutdown(int r) {
ActionContexts action_contexts;
void CloseRequest<I>::send_shut_down_exclusive_lock() {
{
RWLock::WLocker owner_locker(m_image_ctx->owner_lock);
- RWLock::WLocker snap_locker(m_image_ctx->snap_lock);
- std::swap(m_exclusive_lock, m_image_ctx->exclusive_lock);
+ m_exclusive_lock = m_image_ctx->exclusive_lock;
+ // if reading a snapshot -- possible object map is open
+ RWLock::WLocker snap_locker(m_image_ctx->snap_lock);
if (m_exclusive_lock == nullptr) {
delete m_image_ctx->object_map;
m_image_ctx->object_map = nullptr;
CephContext *cct = m_image_ctx->cct;
ldout(cct, 10) << this << " " << __func__ << dendl;
+ // in-flight IO will be flushed and in-flight requests will be canceled
+ // before releasing lock
m_exclusive_lock->shut_down(create_context_callback<
CloseRequest<I>, &CloseRequest<I>::handle_shut_down_exclusive_lock>(this));
}
CephContext *cct = m_image_ctx->cct;
ldout(cct, 10) << this << " " << __func__ << ": r=" << r << dendl;
- // object map and journal closed during exclusive lock shutdown
- assert(m_image_ctx->journal == nullptr);
- assert(m_image_ctx->object_map == nullptr);
+ {
+ RWLock::RLocker owner_locker(m_image_ctx->owner_lock);
+ assert(m_image_ctx->exclusive_lock == nullptr);
+
+ // object map and journal closed during exclusive lock shutdown
+ RWLock::RLocker snap_locker(m_image_ctx->snap_lock);
+ assert(m_image_ctx->journal == nullptr);
+ assert(m_image_ctx->object_map == nullptr);
+ }
+
delete m_exclusive_lock;
+ m_exclusive_lock = nullptr;
save_result(r);
if (r < 0) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 10) << this << " " << __func__ << dendl;
- // exclusive lock feature was dynamically disabled
+ // exclusive lock feature was dynamically disabled. in-flight IO will be
+ // flushed and in-flight requests will be canceled before releasing lock
using klass = RefreshRequest<I>;
Context *ctx = create_context_callback<
klass, &klass::handle_v2_shut_down_exclusive_lock>(this);
save_result(result);
}
+ {
+ RWLock::WLocker owner_locker(m_image_ctx.owner_lock);
+ assert(m_image_ctx.exclusive_lock == nullptr);
+ }
+
assert(m_exclusive_lock != nullptr);
delete m_exclusive_lock;
m_exclusive_lock = nullptr;
m_image_ctx.snap_lock)) {
// disabling exclusive lock will automatically handle closing
// object map and journaling
- std::swap(m_exclusive_lock, m_image_ctx.exclusive_lock);
+ assert(m_exclusive_lock == nullptr);
+ m_exclusive_lock = m_image_ctx.exclusive_lock;
} else {
if (m_exclusive_lock != nullptr) {
+ assert(m_image_ctx.exclusive_lock == nullptr);
std::swap(m_exclusive_lock, m_image_ctx.exclusive_lock);
}
if (!m_image_ctx.test_features(RBD_FEATURE_JOURNALING,