X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fceph%2Fsrc%2Flibrbd%2FImageWatcher.cc;fp=src%2Fceph%2Fsrc%2Flibrbd%2FImageWatcher.cc;h=0000000000000000000000000000000000000000;hb=7da45d65be36d36b880cc55c5036e96c24b53f00;hp=487eabaa69c18f5c7b374362982ce071b40de1b2;hpb=691462d09d0987b47e112d6ee8740375df3c51b2;p=stor4nfv.git diff --git a/src/ceph/src/librbd/ImageWatcher.cc b/src/ceph/src/librbd/ImageWatcher.cc deleted file mode 100644 index 487eaba..0000000 --- a/src/ceph/src/librbd/ImageWatcher.cc +++ /dev/null @@ -1,1013 +0,0 @@ -// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- -// vim: ts=8 sw=2 smarttab - -#include "librbd/ImageWatcher.h" -#include "librbd/ExclusiveLock.h" -#include "librbd/ImageCtx.h" -#include "librbd/ImageState.h" -#include "librbd/internal.h" -#include "librbd/Operations.h" -#include "librbd/TaskFinisher.h" -#include "librbd/Utils.h" -#include "librbd/exclusive_lock/Policy.h" -#include "librbd/image_watcher/NotifyLockOwner.h" -#include "librbd/io/AioCompletion.h" -#include "librbd/watcher/Utils.h" -#include "include/encoding.h" -#include "common/errno.h" -#include "common/WorkQueue.h" -#include - -#define dout_subsys ceph_subsys_rbd -#undef dout_prefix -#define dout_prefix *_dout << "librbd::ImageWatcher: " - -namespace librbd { - -using namespace image_watcher; -using namespace watch_notify; -using util::create_async_context_callback; -using util::create_context_callback; -using util::create_rados_callback; -using librbd::watcher::util::HandlePayloadVisitor; - -static const double RETRY_DELAY_SECONDS = 1.0; - -template -struct ImageWatcher::C_ProcessPayload : public Context { - ImageWatcher *image_watcher; - uint64_t notify_id; - uint64_t handle; - watch_notify::Payload payload; - - C_ProcessPayload(ImageWatcher *image_watcher_, uint64_t notify_id_, - uint64_t handle_, const watch_notify::Payload &payload) - : image_watcher(image_watcher_), notify_id(notify_id_), handle(handle_), - payload(payload) { - } - - void finish(int r) override { - image_watcher->m_async_op_tracker.start_op(); - if (image_watcher->notifications_blocked()) { - // requests are blocked -- just ack the notification - bufferlist bl; - image_watcher->acknowledge_notify(notify_id, handle, bl); - } else { - image_watcher->process_payload(notify_id, handle, payload); - } - image_watcher->m_async_op_tracker.finish_op(); - } -}; - -template -ImageWatcher::ImageWatcher(I &image_ctx) - : Watcher(image_ctx.md_ctx, image_ctx.op_work_queue, image_ctx.header_oid), - m_image_ctx(image_ctx), - m_task_finisher(new TaskFinisher(*m_image_ctx.cct)), - m_async_request_lock(util::unique_lock_name("librbd::ImageWatcher::m_async_request_lock", this)), - m_owner_client_id_lock(util::unique_lock_name("librbd::ImageWatcher::m_owner_client_id_lock", this)) -{ -} - -template -ImageWatcher::~ImageWatcher() -{ - delete m_task_finisher; -} - -template -void ImageWatcher::unregister_watch(Context *on_finish) { - CephContext *cct = m_image_ctx.cct; - ldout(cct, 10) << this << " unregistering image watcher" << dendl; - - cancel_async_requests(); - - FunctionContext *ctx = new FunctionContext([this, on_finish](int r) { - m_task_finisher->cancel_all(on_finish); - }); - Watcher::unregister_watch(ctx); -} - -template -void ImageWatcher::block_notifies(Context *on_finish) { - CephContext *cct = m_image_ctx.cct; - ldout(cct, 10) << this << " " << __func__ << dendl; - - on_finish = new FunctionContext([this, on_finish](int r) { - cancel_async_requests(); - on_finish->complete(r); - }); - Watcher::block_notifies(on_finish); -} - -template -void ImageWatcher::schedule_async_progress(const AsyncRequestId &request, - uint64_t offset, uint64_t total) { - FunctionContext *ctx = new FunctionContext( - boost::bind(&ImageWatcher::notify_async_progress, this, request, offset, - total)); - m_task_finisher->queue(Task(TASK_CODE_ASYNC_PROGRESS, request), ctx); -} - -template -int ImageWatcher::notify_async_progress(const AsyncRequestId &request, - uint64_t offset, uint64_t total) { - ldout(m_image_ctx.cct, 20) << this << " remote async request progress: " - << request << " @ " << offset - << "/" << total << dendl; - - send_notify(AsyncProgressPayload(request, offset, total)); - return 0; -} - -template -void ImageWatcher::schedule_async_complete(const AsyncRequestId &request, - int r) { - FunctionContext *ctx = new FunctionContext( - boost::bind(&ImageWatcher::notify_async_complete, this, request, r)); - m_task_finisher->queue(ctx); -} - -template -void ImageWatcher::notify_async_complete(const AsyncRequestId &request, - int r) { - ldout(m_image_ctx.cct, 20) << this << " remote async request finished: " - << request << " = " << r << dendl; - - send_notify(AsyncCompletePayload(request, r), - new FunctionContext(boost::bind(&ImageWatcher::handle_async_complete, - this, request, r, _1))); -} - -template -void ImageWatcher::handle_async_complete(const AsyncRequestId &request, - int r, int ret_val) { - ldout(m_image_ctx.cct, 20) << this << " " << __func__ << ": " - << "request=" << request << ", r=" << ret_val - << dendl; - if (ret_val < 0) { - lderr(m_image_ctx.cct) << this << " failed to notify async complete: " - << cpp_strerror(ret_val) << dendl; - if (ret_val == -ETIMEDOUT) { - schedule_async_complete(request, r); - } - } else { - RWLock::WLocker async_request_locker(m_async_request_lock); - m_async_pending.erase(request); - } -} - -template -void ImageWatcher::notify_flatten(uint64_t request_id, - ProgressContext &prog_ctx, - Context *on_finish) { - assert(m_image_ctx.owner_lock.is_locked()); - assert(m_image_ctx.exclusive_lock && - !m_image_ctx.exclusive_lock->is_lock_owner()); - - AsyncRequestId async_request_id(get_client_id(), request_id); - - notify_async_request(async_request_id, FlattenPayload(async_request_id), - prog_ctx, on_finish); -} - -template -void ImageWatcher::notify_resize(uint64_t request_id, uint64_t size, - bool allow_shrink, - ProgressContext &prog_ctx, - Context *on_finish) { - assert(m_image_ctx.owner_lock.is_locked()); - assert(m_image_ctx.exclusive_lock && - !m_image_ctx.exclusive_lock->is_lock_owner()); - - AsyncRequestId async_request_id(get_client_id(), request_id); - - notify_async_request(async_request_id, - ResizePayload(size, allow_shrink, async_request_id), - prog_ctx, on_finish); -} - -template -void ImageWatcher::notify_snap_create(const cls::rbd::SnapshotNamespace &snap_namespace, - const std::string &snap_name, - Context *on_finish) { - assert(m_image_ctx.owner_lock.is_locked()); - assert(m_image_ctx.exclusive_lock && - !m_image_ctx.exclusive_lock->is_lock_owner()); - - notify_lock_owner(SnapCreatePayload(snap_namespace, snap_name), on_finish); -} - -template -void ImageWatcher::notify_snap_rename(const snapid_t &src_snap_id, - const std::string &dst_snap_name, - Context *on_finish) { - assert(m_image_ctx.owner_lock.is_locked()); - assert(m_image_ctx.exclusive_lock && - !m_image_ctx.exclusive_lock->is_lock_owner()); - - notify_lock_owner(SnapRenamePayload(src_snap_id, dst_snap_name), on_finish); -} - -template -void ImageWatcher::notify_snap_remove(const cls::rbd::SnapshotNamespace &snap_namespace, - const std::string &snap_name, - Context *on_finish) { - assert(m_image_ctx.owner_lock.is_locked()); - assert(m_image_ctx.exclusive_lock && - !m_image_ctx.exclusive_lock->is_lock_owner()); - - notify_lock_owner(SnapRemovePayload(snap_namespace, snap_name), on_finish); -} - -template -void ImageWatcher::notify_snap_protect(const cls::rbd::SnapshotNamespace &snap_namespace, - const std::string &snap_name, - Context *on_finish) { - assert(m_image_ctx.owner_lock.is_locked()); - assert(m_image_ctx.exclusive_lock && - !m_image_ctx.exclusive_lock->is_lock_owner()); - - notify_lock_owner(SnapProtectPayload(snap_namespace, snap_name), on_finish); -} - -template -void ImageWatcher::notify_snap_unprotect(const cls::rbd::SnapshotNamespace &snap_namespace, - const std::string &snap_name, - Context *on_finish) { - assert(m_image_ctx.owner_lock.is_locked()); - assert(m_image_ctx.exclusive_lock && - !m_image_ctx.exclusive_lock->is_lock_owner()); - - notify_lock_owner(SnapUnprotectPayload(snap_namespace, snap_name), on_finish); -} - -template -void ImageWatcher::notify_rebuild_object_map(uint64_t request_id, - ProgressContext &prog_ctx, - Context *on_finish) { - assert(m_image_ctx.owner_lock.is_locked()); - assert(m_image_ctx.exclusive_lock && - !m_image_ctx.exclusive_lock->is_lock_owner()); - - AsyncRequestId async_request_id(get_client_id(), request_id); - - notify_async_request(async_request_id, - RebuildObjectMapPayload(async_request_id), - prog_ctx, on_finish); -} - -template -void ImageWatcher::notify_rename(const std::string &image_name, - Context *on_finish) { - assert(m_image_ctx.owner_lock.is_locked()); - assert(m_image_ctx.exclusive_lock && - !m_image_ctx.exclusive_lock->is_lock_owner()); - - notify_lock_owner(RenamePayload(image_name), on_finish); -} - -template -void ImageWatcher::notify_update_features(uint64_t features, bool enabled, - Context *on_finish) { - assert(m_image_ctx.owner_lock.is_locked()); - assert(m_image_ctx.exclusive_lock && - !m_image_ctx.exclusive_lock->is_lock_owner()); - - notify_lock_owner(UpdateFeaturesPayload(features, enabled), on_finish); -} - -template -void ImageWatcher::notify_header_update(Context *on_finish) { - ldout(m_image_ctx.cct, 10) << this << ": " << __func__ << dendl; - - // supports legacy (empty buffer) clients - send_notify(HeaderUpdatePayload(), on_finish); -} - -template -void ImageWatcher::notify_header_update(librados::IoCtx &io_ctx, - const std::string &oid) { - // supports legacy (empty buffer) clients - bufferlist bl; - ::encode(NotifyMessage(HeaderUpdatePayload()), bl); - io_ctx.notify2(oid, bl, watcher::Notifier::NOTIFY_TIMEOUT, nullptr); -} - -template -void ImageWatcher::schedule_cancel_async_requests() { - FunctionContext *ctx = new FunctionContext( - boost::bind(&ImageWatcher::cancel_async_requests, this)); - m_task_finisher->queue(TASK_CODE_CANCEL_ASYNC_REQUESTS, ctx); -} - -template -void ImageWatcher::cancel_async_requests() { - RWLock::WLocker l(m_async_request_lock); - for (std::map::iterator iter = - m_async_requests.begin(); - iter != m_async_requests.end(); ++iter) { - iter->second.first->complete(-ERESTART); - } - m_async_requests.clear(); -} - -template -void ImageWatcher::set_owner_client_id(const ClientId& client_id) { - assert(m_owner_client_id_lock.is_locked()); - m_owner_client_id = client_id; - ldout(m_image_ctx.cct, 10) << this << " current lock owner: " - << m_owner_client_id << dendl; -} - -template -ClientId ImageWatcher::get_client_id() { - RWLock::RLocker l(this->m_watch_lock); - return ClientId(m_image_ctx.md_ctx.get_instance_id(), this->m_watch_handle); -} - -template -void ImageWatcher::notify_acquired_lock() { - ldout(m_image_ctx.cct, 10) << this << " notify acquired lock" << dendl; - - ClientId client_id = get_client_id(); - { - Mutex::Locker owner_client_id_locker(m_owner_client_id_lock); - set_owner_client_id(client_id); - } - - send_notify(AcquiredLockPayload(client_id)); -} - -template -void ImageWatcher::notify_released_lock() { - ldout(m_image_ctx.cct, 10) << this << " notify released lock" << dendl; - - { - Mutex::Locker owner_client_id_locker(m_owner_client_id_lock); - set_owner_client_id(ClientId()); - } - - send_notify(ReleasedLockPayload(get_client_id())); -} - -template -void ImageWatcher::schedule_request_lock(bool use_timer, int timer_delay) { - assert(m_image_ctx.owner_lock.is_locked()); - - if (m_image_ctx.exclusive_lock == nullptr) { - // exclusive lock dynamically disabled via image refresh - return; - } - assert(m_image_ctx.exclusive_lock && - !m_image_ctx.exclusive_lock->is_lock_owner()); - - RWLock::RLocker watch_locker(this->m_watch_lock); - if (this->m_watch_state == Watcher::WATCH_STATE_REGISTERED) { - ldout(m_image_ctx.cct, 15) << this << " requesting exclusive lock" << dendl; - - FunctionContext *ctx = new FunctionContext( - boost::bind(&ImageWatcher::notify_request_lock, this)); - if (use_timer) { - if (timer_delay < 0) { - timer_delay = RETRY_DELAY_SECONDS; - } - m_task_finisher->add_event_after(TASK_CODE_REQUEST_LOCK, - timer_delay, ctx); - } else { - m_task_finisher->queue(TASK_CODE_REQUEST_LOCK, ctx); - } - } -} - -template -void ImageWatcher::notify_request_lock() { - RWLock::RLocker owner_locker(m_image_ctx.owner_lock); - RWLock::RLocker snap_locker(m_image_ctx.snap_lock); - - // ExclusiveLock state machine can be dynamically disabled or - // race with task cancel - if (m_image_ctx.exclusive_lock == nullptr || - m_image_ctx.exclusive_lock->is_lock_owner()) { - return; - } - - ldout(m_image_ctx.cct, 10) << this << " notify request lock" << dendl; - - notify_lock_owner(RequestLockPayload(get_client_id(), false), - create_context_callback< - ImageWatcher, &ImageWatcher::handle_request_lock>(this)); -} - -template -void ImageWatcher::handle_request_lock(int r) { - RWLock::RLocker owner_locker(m_image_ctx.owner_lock); - RWLock::RLocker snap_locker(m_image_ctx.snap_lock); - - // ExclusiveLock state machine cannot transition -- but can be - // dynamically disabled - if (m_image_ctx.exclusive_lock == nullptr) { - return; - } - - if (r == -ETIMEDOUT) { - ldout(m_image_ctx.cct, 5) << this << " timed out requesting lock: retrying" - << dendl; - - // treat this is a dead client -- so retest acquiring the lock - m_image_ctx.exclusive_lock->handle_peer_notification(0); - } else if (r == -EROFS) { - ldout(m_image_ctx.cct, 5) << this << " peer will not release lock" << dendl; - m_image_ctx.exclusive_lock->handle_peer_notification(r); - } else if (r < 0) { - lderr(m_image_ctx.cct) << this << " error requesting lock: " - << cpp_strerror(r) << dendl; - schedule_request_lock(true); - } else { - // lock owner acked -- but resend if we don't see them release the lock - int retry_timeout = m_image_ctx.cct->_conf->template get_val( - "client_notify_timeout"); - ldout(m_image_ctx.cct, 15) << this << " will retry in " << retry_timeout - << " seconds" << dendl; - schedule_request_lock(true, retry_timeout); - } -} - -template -void ImageWatcher::notify_lock_owner(const Payload& payload, - Context *on_finish) { - assert(on_finish != nullptr); - assert(m_image_ctx.owner_lock.is_locked()); - - bufferlist bl; - ::encode(NotifyMessage(payload), bl); - - NotifyLockOwner *notify_lock_owner = NotifyLockOwner::create( - m_image_ctx, this->m_notifier, std::move(bl), on_finish); - notify_lock_owner->send(); -} - -template -Context *ImageWatcher::remove_async_request(const AsyncRequestId &id) { - RWLock::WLocker async_request_locker(m_async_request_lock); - auto it = m_async_requests.find(id); - if (it != m_async_requests.end()) { - Context *on_complete = it->second.first; - m_async_requests.erase(it); - return on_complete; - } - return nullptr; -} - -template -void ImageWatcher::schedule_async_request_timed_out(const AsyncRequestId &id) { - ldout(m_image_ctx.cct, 20) << "scheduling async request time out: " << id - << dendl; - - Context *ctx = new FunctionContext(boost::bind( - &ImageWatcher::async_request_timed_out, this, id)); - - Task task(TASK_CODE_ASYNC_REQUEST, id); - m_task_finisher->cancel(task); - - m_task_finisher->add_event_after(task, m_image_ctx.request_timed_out_seconds, - ctx); -} - -template -void ImageWatcher::async_request_timed_out(const AsyncRequestId &id) { - Context *on_complete = remove_async_request(id); - if (on_complete != nullptr) { - ldout(m_image_ctx.cct, 5) << "async request timed out: " << id << dendl; - m_image_ctx.op_work_queue->queue(on_complete, -ETIMEDOUT); - } -} - -template -void ImageWatcher::notify_async_request(const AsyncRequestId &async_request_id, - const Payload& payload, - ProgressContext& prog_ctx, - Context *on_finish) { - assert(on_finish != nullptr); - assert(m_image_ctx.owner_lock.is_locked()); - - ldout(m_image_ctx.cct, 10) << this << " async request: " << async_request_id - << dendl; - - Context *on_notify = new FunctionContext([this, async_request_id](int r) { - if (r < 0) { - // notification failed -- don't expect updates - Context *on_complete = remove_async_request(async_request_id); - if (on_complete != nullptr) { - on_complete->complete(r); - } - } - }); - - Context *on_complete = new FunctionContext( - [this, async_request_id, on_finish](int r) { - m_task_finisher->cancel(Task(TASK_CODE_ASYNC_REQUEST, async_request_id)); - on_finish->complete(r); - }); - - { - RWLock::WLocker async_request_locker(m_async_request_lock); - m_async_requests[async_request_id] = AsyncRequest(on_complete, &prog_ctx); - } - - schedule_async_request_timed_out(async_request_id); - notify_lock_owner(payload, on_notify); -} - -template -int ImageWatcher::prepare_async_request(const AsyncRequestId& async_request_id, - bool* new_request, Context** ctx, - ProgressContext** prog_ctx) { - if (async_request_id.client_id == get_client_id()) { - return -ERESTART; - } else { - RWLock::WLocker l(m_async_request_lock); - if (m_async_pending.count(async_request_id) == 0) { - m_async_pending.insert(async_request_id); - *new_request = true; - *prog_ctx = new RemoteProgressContext(*this, async_request_id); - *ctx = new RemoteContext(*this, async_request_id, *prog_ctx); - } else { - *new_request = false; - } - } - return 0; -} - -template -bool ImageWatcher::handle_payload(const HeaderUpdatePayload &payload, - C_NotifyAck *ack_ctx) { - ldout(m_image_ctx.cct, 10) << this << " image header updated" << dendl; - - m_image_ctx.state->handle_update_notification(); - m_image_ctx.perfcounter->inc(l_librbd_notify); - if (ack_ctx != nullptr) { - m_image_ctx.state->flush_update_watchers(new C_ResponseMessage(ack_ctx)); - return false; - } - return true; -} - -template -bool ImageWatcher::handle_payload(const AcquiredLockPayload &payload, - C_NotifyAck *ack_ctx) { - ldout(m_image_ctx.cct, 10) << this << " image exclusively locked announcement" - << dendl; - - bool cancel_async_requests = true; - if (payload.client_id.is_valid()) { - Mutex::Locker owner_client_id_locker(m_owner_client_id_lock); - if (payload.client_id == m_owner_client_id) { - cancel_async_requests = false; - } - set_owner_client_id(payload.client_id); - } - - RWLock::RLocker owner_locker(m_image_ctx.owner_lock); - if (m_image_ctx.exclusive_lock != nullptr) { - // potentially wake up the exclusive lock state machine now that - // a lock owner has advertised itself - m_image_ctx.exclusive_lock->handle_peer_notification(0); - } - if (cancel_async_requests && - (m_image_ctx.exclusive_lock == nullptr || - !m_image_ctx.exclusive_lock->is_lock_owner())) { - schedule_cancel_async_requests(); - } - return true; -} - -template -bool ImageWatcher::handle_payload(const ReleasedLockPayload &payload, - C_NotifyAck *ack_ctx) { - ldout(m_image_ctx.cct, 10) << this << " exclusive lock released" << dendl; - - bool cancel_async_requests = true; - if (payload.client_id.is_valid()) { - Mutex::Locker l(m_owner_client_id_lock); - if (payload.client_id != m_owner_client_id) { - ldout(m_image_ctx.cct, 10) << this << " unexpected owner: " - << payload.client_id << " != " - << m_owner_client_id << dendl; - cancel_async_requests = false; - } else { - set_owner_client_id(ClientId()); - } - } - - RWLock::RLocker owner_locker(m_image_ctx.owner_lock); - if (cancel_async_requests && - (m_image_ctx.exclusive_lock == nullptr || - !m_image_ctx.exclusive_lock->is_lock_owner())) { - schedule_cancel_async_requests(); - } - - // alert the exclusive lock state machine that the lock is available - if (m_image_ctx.exclusive_lock != nullptr && - !m_image_ctx.exclusive_lock->is_lock_owner()) { - m_task_finisher->cancel(TASK_CODE_REQUEST_LOCK); - m_image_ctx.exclusive_lock->handle_peer_notification(0); - } - return true; -} - -template -bool ImageWatcher::handle_payload(const RequestLockPayload &payload, - C_NotifyAck *ack_ctx) { - ldout(m_image_ctx.cct, 10) << this << " exclusive lock requested" << dendl; - if (payload.client_id == get_client_id()) { - return true; - } - - RWLock::RLocker l(m_image_ctx.owner_lock); - if (m_image_ctx.exclusive_lock != nullptr && - m_image_ctx.exclusive_lock->is_lock_owner()) { - int r = 0; - bool accept_request = m_image_ctx.exclusive_lock->accept_requests(&r); - - if (accept_request) { - assert(r == 0); - Mutex::Locker owner_client_id_locker(m_owner_client_id_lock); - if (!m_owner_client_id.is_valid()) { - return true; - } - - ldout(m_image_ctx.cct, 10) << this << " queuing release of exclusive lock" - << dendl; - r = m_image_ctx.get_exclusive_lock_policy()->lock_requested( - payload.force); - } - ::encode(ResponseMessage(r), ack_ctx->out); - } - return true; -} - -template -bool ImageWatcher::handle_payload(const AsyncProgressPayload &payload, - C_NotifyAck *ack_ctx) { - RWLock::RLocker l(m_async_request_lock); - std::map::iterator req_it = - m_async_requests.find(payload.async_request_id); - if (req_it != m_async_requests.end()) { - ldout(m_image_ctx.cct, 20) << this << " request progress: " - << payload.async_request_id << " @ " - << payload.offset << "/" << payload.total - << dendl; - schedule_async_request_timed_out(payload.async_request_id); - req_it->second.second->update_progress(payload.offset, payload.total); - } - return true; -} - -template -bool ImageWatcher::handle_payload(const AsyncCompletePayload &payload, - C_NotifyAck *ack_ctx) { - Context *on_complete = remove_async_request(payload.async_request_id); - if (on_complete != nullptr) { - ldout(m_image_ctx.cct, 10) << this << " request finished: " - << payload.async_request_id << "=" - << payload.result << dendl; - on_complete->complete(payload.result); - } - return true; -} - -template -bool ImageWatcher::handle_payload(const FlattenPayload &payload, - C_NotifyAck *ack_ctx) { - - RWLock::RLocker l(m_image_ctx.owner_lock); - if (m_image_ctx.exclusive_lock != nullptr) { - int r; - if (m_image_ctx.exclusive_lock->accept_requests(&r)) { - bool new_request; - Context *ctx; - ProgressContext *prog_ctx; - r = prepare_async_request(payload.async_request_id, &new_request, - &ctx, &prog_ctx); - if (r == 0 && new_request) { - ldout(m_image_ctx.cct, 10) << this << " remote flatten request: " - << payload.async_request_id << dendl; - m_image_ctx.operations->execute_flatten(*prog_ctx, ctx); - } - - ::encode(ResponseMessage(r), ack_ctx->out); - } else if (r < 0) { - ::encode(ResponseMessage(r), ack_ctx->out); - } - } - return true; -} - -template -bool ImageWatcher::handle_payload(const ResizePayload &payload, - C_NotifyAck *ack_ctx) { - RWLock::RLocker l(m_image_ctx.owner_lock); - if (m_image_ctx.exclusive_lock != nullptr) { - int r; - if (m_image_ctx.exclusive_lock->accept_requests(&r)) { - bool new_request; - Context *ctx; - ProgressContext *prog_ctx; - r = prepare_async_request(payload.async_request_id, &new_request, - &ctx, &prog_ctx); - if (r == 0 && new_request) { - ldout(m_image_ctx.cct, 10) << this << " remote resize request: " - << payload.async_request_id << " " - << payload.size << " " - << payload.allow_shrink << dendl; - m_image_ctx.operations->execute_resize(payload.size, payload.allow_shrink, *prog_ctx, ctx, 0); - } - - ::encode(ResponseMessage(r), ack_ctx->out); - } else if (r < 0) { - ::encode(ResponseMessage(r), ack_ctx->out); - } - } - return true; -} - -template -bool ImageWatcher::handle_payload(const SnapCreatePayload &payload, - C_NotifyAck *ack_ctx) { - RWLock::RLocker l(m_image_ctx.owner_lock); - if (m_image_ctx.exclusive_lock != nullptr) { - int r; - if (m_image_ctx.exclusive_lock->accept_requests(&r)) { - ldout(m_image_ctx.cct, 10) << this << " remote snap_create request: " - << payload.snap_name << dendl; - - m_image_ctx.operations->execute_snap_create(payload.snap_namespace, - payload.snap_name, - new C_ResponseMessage(ack_ctx), - 0, false); - return false; - } else if (r < 0) { - ::encode(ResponseMessage(r), ack_ctx->out); - } - } - return true; -} - -template -bool ImageWatcher::handle_payload(const SnapRenamePayload &payload, - C_NotifyAck *ack_ctx) { - RWLock::RLocker l(m_image_ctx.owner_lock); - if (m_image_ctx.exclusive_lock != nullptr) { - int r; - if (m_image_ctx.exclusive_lock->accept_requests(&r)) { - ldout(m_image_ctx.cct, 10) << this << " remote snap_rename request: " - << payload.snap_id << " to " - << payload.snap_name << dendl; - - m_image_ctx.operations->execute_snap_rename(payload.snap_id, - payload.snap_name, - new C_ResponseMessage(ack_ctx)); - return false; - } else if (r < 0) { - ::encode(ResponseMessage(r), ack_ctx->out); - } - } - return true; -} - -template -bool ImageWatcher::handle_payload(const SnapRemovePayload &payload, - C_NotifyAck *ack_ctx) { - RWLock::RLocker l(m_image_ctx.owner_lock); - if (m_image_ctx.exclusive_lock != nullptr) { - int r; - if (m_image_ctx.exclusive_lock->accept_requests(&r)) { - ldout(m_image_ctx.cct, 10) << this << " remote snap_remove request: " - << payload.snap_name << dendl; - - m_image_ctx.operations->execute_snap_remove(payload.snap_namespace, - payload.snap_name, - new C_ResponseMessage(ack_ctx)); - return false; - } else if (r < 0) { - ::encode(ResponseMessage(r), ack_ctx->out); - } - } - return true; -} - -template -bool ImageWatcher::handle_payload(const SnapProtectPayload& payload, - C_NotifyAck *ack_ctx) { - RWLock::RLocker owner_locker(m_image_ctx.owner_lock); - if (m_image_ctx.exclusive_lock != nullptr) { - int r; - if (m_image_ctx.exclusive_lock->accept_requests(&r)) { - ldout(m_image_ctx.cct, 10) << this << " remote snap_protect request: " - << payload.snap_name << dendl; - - m_image_ctx.operations->execute_snap_protect(payload.snap_namespace, - payload.snap_name, - new C_ResponseMessage(ack_ctx)); - return false; - } else if (r < 0) { - ::encode(ResponseMessage(r), ack_ctx->out); - } - } - return true; -} - -template -bool ImageWatcher::handle_payload(const SnapUnprotectPayload& payload, - C_NotifyAck *ack_ctx) { - RWLock::RLocker owner_locker(m_image_ctx.owner_lock); - if (m_image_ctx.exclusive_lock != nullptr) { - int r; - if (m_image_ctx.exclusive_lock->accept_requests(&r)) { - ldout(m_image_ctx.cct, 10) << this << " remote snap_unprotect request: " - << payload.snap_name << dendl; - - m_image_ctx.operations->execute_snap_unprotect(payload.snap_namespace, - payload.snap_name, - new C_ResponseMessage(ack_ctx)); - return false; - } else if (r < 0) { - ::encode(ResponseMessage(r), ack_ctx->out); - } - } - return true; -} - -template -bool ImageWatcher::handle_payload(const RebuildObjectMapPayload& payload, - C_NotifyAck *ack_ctx) { - RWLock::RLocker l(m_image_ctx.owner_lock); - if (m_image_ctx.exclusive_lock != nullptr) { - int r; - if (m_image_ctx.exclusive_lock->accept_requests(&r)) { - bool new_request; - Context *ctx; - ProgressContext *prog_ctx; - r = prepare_async_request(payload.async_request_id, &new_request, - &ctx, &prog_ctx); - if (r == 0 && new_request) { - ldout(m_image_ctx.cct, 10) << this - << " remote rebuild object map request: " - << payload.async_request_id << dendl; - m_image_ctx.operations->execute_rebuild_object_map(*prog_ctx, ctx); - } - - ::encode(ResponseMessage(r), ack_ctx->out); - } else if (r < 0) { - ::encode(ResponseMessage(r), ack_ctx->out); - } - } - return true; -} - -template -bool ImageWatcher::handle_payload(const RenamePayload& payload, - C_NotifyAck *ack_ctx) { - RWLock::RLocker owner_locker(m_image_ctx.owner_lock); - if (m_image_ctx.exclusive_lock != nullptr) { - int r; - if (m_image_ctx.exclusive_lock->accept_requests(&r)) { - ldout(m_image_ctx.cct, 10) << this << " remote rename request: " - << payload.image_name << dendl; - - m_image_ctx.operations->execute_rename(payload.image_name, - new C_ResponseMessage(ack_ctx)); - return false; - } else if (r < 0) { - ::encode(ResponseMessage(r), ack_ctx->out); - } - } - return true; -} - -template -bool ImageWatcher::handle_payload(const UpdateFeaturesPayload& payload, - C_NotifyAck *ack_ctx) { - RWLock::RLocker owner_locker(m_image_ctx.owner_lock); - if (m_image_ctx.exclusive_lock != nullptr) { - int r; - if (m_image_ctx.exclusive_lock->accept_requests(&r)) { - ldout(m_image_ctx.cct, 10) << this << " remote update_features request: " - << payload.features << " " - << (payload.enabled ? "enabled" : "disabled") - << dendl; - - m_image_ctx.operations->execute_update_features( - payload.features, payload.enabled, new C_ResponseMessage(ack_ctx), 0); - return false; - } else if (r < 0) { - ::encode(ResponseMessage(r), ack_ctx->out); - } - } - return true; -} - -template -bool ImageWatcher::handle_payload(const UnknownPayload &payload, - C_NotifyAck *ack_ctx) { - RWLock::RLocker l(m_image_ctx.owner_lock); - if (m_image_ctx.exclusive_lock != nullptr) { - int r; - if (m_image_ctx.exclusive_lock->accept_requests(&r) || r < 0) { - ::encode(ResponseMessage(-EOPNOTSUPP), ack_ctx->out); - } - } - return true; -} - -template -void ImageWatcher::process_payload(uint64_t notify_id, uint64_t handle, - const Payload &payload) { - apply_visitor(HandlePayloadVisitor>(this, notify_id, handle), - payload); -} - -template -void ImageWatcher::handle_notify(uint64_t notify_id, uint64_t handle, - uint64_t notifier_id, bufferlist &bl) { - NotifyMessage notify_message; - if (bl.length() == 0) { - // legacy notification for header updates - notify_message = NotifyMessage(HeaderUpdatePayload()); - } else { - try { - bufferlist::iterator iter = bl.begin(); - ::decode(notify_message, iter); - } catch (const buffer::error &err) { - lderr(m_image_ctx.cct) << this << " error decoding image notification: " - << err.what() << dendl; - return; - } - } - - // if an image refresh is required, refresh before processing the request - if (notify_message.check_for_refresh() && - m_image_ctx.state->is_refresh_required()) { - m_image_ctx.state->refresh(new C_ProcessPayload(this, notify_id, handle, - notify_message.payload)); - } else { - process_payload(notify_id, handle, notify_message.payload); - } -} - -template -void ImageWatcher::handle_error(uint64_t handle, int err) { - lderr(m_image_ctx.cct) << this << " image watch failed: " << handle << ", " - << cpp_strerror(err) << dendl; - - { - Mutex::Locker l(m_owner_client_id_lock); - set_owner_client_id(ClientId()); - } - - Watcher::handle_error(handle, err); -} - -template -void ImageWatcher::handle_rewatch_complete(int r) { - CephContext *cct = m_image_ctx.cct; - ldout(cct, 10) << this << " " << __func__ << ": r=" << r << dendl; - - { - RWLock::RLocker owner_locker(m_image_ctx.owner_lock); - if (m_image_ctx.exclusive_lock != nullptr) { - // update the lock cookie with the new watch handle - m_image_ctx.exclusive_lock->reacquire_lock(); - } - } - - // image might have been updated while we didn't have active watch - handle_payload(HeaderUpdatePayload(), nullptr); -} - -template -void ImageWatcher::send_notify(const Payload &payload, Context *ctx) { - bufferlist bl; - - ::encode(NotifyMessage(payload), bl); - Watcher::send_notify(bl, nullptr, ctx); -} - -template -void ImageWatcher::RemoteContext::finish(int r) { - m_image_watcher.schedule_async_complete(m_async_request_id, r); -} - -template -void ImageWatcher::C_ResponseMessage::finish(int r) { - CephContext *cct = notify_ack->cct; - ldout(cct, 10) << this << " C_ResponseMessage: r=" << r << dendl; - - ::encode(ResponseMessage(r), notify_ack->out); - notify_ack->complete(0); -} - -} // namespace librbd - -template class librbd::ImageWatcher;