From: Jason Dillaman Date: Tue, 6 Mar 2018 19:23:47 +0000 (-0500) Subject: librbd: switch to lock-free queue for event poll IO interface X-Git-Tag: v15.1.0~2767^2~6 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=ef9d74720f2e8ba3146774e75f60fed815a3c9de;p=ceph.git librbd: switch to lock-free queue for event poll IO interface 'perf' shows several percent of CPU being wasted on lock contention in the event poll interface. The 'fio' RBD engine uses this poll IO interface by default when available. Signed-off-by: Jason Dillaman --- diff --git a/src/librbd/ImageCtx.cc b/src/librbd/ImageCtx.cc index b39ef9302a5..a20069c6e16 100644 --- a/src/librbd/ImageCtx.cc +++ b/src/librbd/ImageCtx.cc @@ -110,7 +110,6 @@ public: timestamp_lock(util::unique_lock_name("librbd::ImageCtx::timestamp_lock", this)), async_ops_lock(util::unique_lock_name("librbd::ImageCtx::async_ops_lock", this)), copyup_list_lock(util::unique_lock_name("librbd::ImageCtx::copyup_list_lock", this)), - completed_reqs_lock(util::unique_lock_name("librbd::ImageCtx::completed_reqs_lock", this)), extra_read_flags(0), old_format(false), order(0), size(0), features(0), @@ -123,6 +122,7 @@ public: operations(new Operations<>(*this)), exclusive_lock(nullptr), object_map(nullptr), io_work_queue(nullptr), op_work_queue(nullptr), + completed_reqs(32), asok_hook(nullptr), trace_endpoint("librbd") { @@ -712,13 +712,6 @@ public: on_finish->complete(0); } - void ImageCtx::clear_pending_completions() { - Mutex::Locker l(completed_reqs_lock); - ldout(cct, 10) << "clear pending AioCompletion: count=" - << completed_reqs.size() << dendl; - completed_reqs.clear(); - } - void ImageCtx::apply_metadata(const std::map &meta, bool thread_safe) { ldout(cct, 20) << __func__ << dendl; diff --git a/src/librbd/ImageCtx.h b/src/librbd/ImageCtx.h index 25a1300ce8e..1b7cf5a8d5e 100644 --- a/src/librbd/ImageCtx.h +++ b/src/librbd/ImageCtx.h @@ -31,6 +31,8 @@ #include "librbd/AsyncRequest.h" #include "librbd/Types.h" +#include + class CephContext; class ContextWQ; class Finisher; @@ -118,7 +120,6 @@ namespace librbd { RWLock timestamp_lock; // protects (create/access/modify)_timestamp Mutex async_ops_lock; // protects async_ops and async_requests Mutex copyup_list_lock; // protects copyup_waiting_list - Mutex completed_reqs_lock; // protects completed_reqs unsigned extra_read_flags; @@ -167,11 +168,11 @@ namespace librbd { io::ImageRequestWQ *io_work_queue; io::ObjectDispatcher *io_object_dispatcher = nullptr; - xlist completed_reqs; - EventSocket event_socket; - ContextWQ *op_work_queue; + boost::lockfree::queue completed_reqs; + EventSocket event_socket; + bool ignore_migrating = false; /// Cached latency-sensitive configuration settings @@ -301,8 +302,6 @@ namespace librbd { ObjectMap *create_object_map(uint64_t snap_id); Journal *create_journal(); - void clear_pending_completions(); - void set_image_name(const std::string &name); void notify_update(); diff --git a/src/librbd/internal.cc b/src/librbd/internal.cc index a40649ae4c1..dadf699c29d 100644 --- a/src/librbd/internal.cc +++ b/src/librbd/internal.cc @@ -1839,12 +1839,10 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) { ldout(cct, 20) << __func__ << " " << ictx << " numcomp = " << numcomp << dendl; int i = 0; - Mutex::Locker l(ictx->completed_reqs_lock); - numcomp = std::min(numcomp, (int)ictx->completed_reqs.size()); - while (i < numcomp) { - comps[i++] = ictx->completed_reqs.front(); - ictx->completed_reqs.pop_front(); + while (i < numcomp && ictx->completed_reqs.pop(comps[i])) { + ++i; } + return i; } diff --git a/src/librbd/io/AioCompletion.cc b/src/librbd/io/AioCompletion.cc index fce9529d5f6..e151d622433 100644 --- a/src/librbd/io/AioCompletion.cc +++ b/src/librbd/io/AioCompletion.cc @@ -103,9 +103,7 @@ void AioCompletion::complete() { } if (ictx != nullptr && event_notify && ictx->event_socket.is_valid()) { - ictx->completed_reqs_lock.Lock(); - ictx->completed_reqs.push_back(&m_xlist_item); - ictx->completed_reqs_lock.Unlock(); + ictx->completed_reqs.push(this); ictx->event_socket.notify(); } state = AIO_STATE_COMPLETE; diff --git a/src/librbd/io/AioCompletion.h b/src/librbd/io/AioCompletion.h index 0e6874126e2..46f2bd0b021 100644 --- a/src/librbd/io/AioCompletion.h +++ b/src/librbd/io/AioCompletion.h @@ -68,7 +68,6 @@ struct AioCompletion { AsyncOperation async_op; - xlist::item m_xlist_item; bool event_notify = false; template @@ -104,7 +103,7 @@ struct AioCompletion { return comp; } - AioCompletion() : m_xlist_item(this) { + AioCompletion() { } ~AioCompletion() { @@ -159,11 +158,6 @@ struct AioCompletion { ceph_assert(previous_ref > 0); if (previous_ref == 1) { - if (ictx != nullptr && event_notify) { - ictx->completed_reqs_lock.Lock(); - m_xlist_item.remove_myself(); - ictx->completed_reqs_lock.Unlock(); - } delete this; } }