From 1de14a5e30c4d5a4e0fc17037c93b24a3cc9cf42 Mon Sep 17 00:00:00 2001 From: Patrick Donnelly Date: Mon, 12 Aug 2024 11:31:46 -0400 Subject: [PATCH] client: use vectors for context lists To avoid an allocation for each Context and improved cache locality. Signed-off-by: Patrick Donnelly --- src/client/Client.cc | 32 ++++++++------------------------ src/client/Client.h | 7 +++---- src/client/Inode.h | 6 +++--- src/client/MetaRequest.h | 2 +- src/client/MetaSession.h | 2 +- 5 files changed, 16 insertions(+), 33 deletions(-) diff --git a/src/client/Client.cc b/src/client/Client.cc index 5f78e73f92224..e60b9345e24ae 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -4265,7 +4265,7 @@ void Client::signal_cond_list(list& ls) } } -void Client::wait_on_context_list(list& ls) +void Client::wait_on_context_list(std::vector& ls) { ceph::condition_variable cond; bool done = false; @@ -4276,30 +4276,14 @@ void Client::wait_on_context_list(list& ls) l.release(); } -void Client::signal_context_list(list& ls) -{ - while (!ls.empty()) { - ls.front()->complete(0); - ls.pop_front(); - } -} - void Client::signal_caps_inode(Inode *in) { // Process the waitfor_caps list - while (!in->waitfor_caps.empty()) { - in->waitfor_caps.front()->complete(0); - in->waitfor_caps.pop_front(); - } + signal_context_list(in->waitfor_caps); // New items may have been added to the pending list, move them onto the // waitfor_caps list - while (!in->waitfor_caps_pending.empty()) { - Context *ctx = in->waitfor_caps_pending.front(); - - in->waitfor_caps_pending.pop_front(); - in->waitfor_caps.push_back(ctx); - } + std::swap(in->waitfor_caps, in->waitfor_caps_pending); } void Client::wake_up_session_caps(MetaSession *s, bool reconnect) @@ -11904,7 +11888,7 @@ void Client::C_nonblocking_fsync_state::advance() ldout(clnt->cct, 15) << "waiting on unsafe requests, last tid " << req->get_tid() << dendl; req->get(); - clnt->add_nonblocking_onfinish_to_context_list(req->waitfor_safe, advancer); + req->waitfor_safe.push_back(advancer); // ------------ here is a state machine break point return; } @@ -11930,7 +11914,7 @@ void Client::C_nonblocking_fsync_state::advance() ldout(clnt->cct, 10) << "ino " << in->ino << " has " << in->cap_refs[CEPH_CAP_FILE_BUFFER] << " uncommitted, waiting" << dendl; advancer = new C_nonblocking_fsync_state_advancer(clnt, this); - clnt->add_nonblocking_onfinish_to_context_list(in->waitfor_commit, advancer); + in->waitfor_commit.push_back(advancer); // ------------ here is a state machine break point but we have to // return to this case because this might loop. progress = 1; @@ -11988,9 +11972,9 @@ void Client::C_nonblocking_fsync_state::advance() << " for C_nonblocking_fsync_state " << this << dendl; if (progress == 3) - clnt->add_nonblocking_onfinish_to_context_list(in->waitfor_caps, advancer); + in->waitfor_caps.push_back(advancer); else - clnt->add_nonblocking_onfinish_to_context_list(in->waitfor_caps_pending, advancer); + in->waitfor_caps_pending.push_back(advancer); // ------------ here is a state machine break point // the advancer completion will resume with case 3 progress = 4; @@ -16796,7 +16780,7 @@ void Client::ms_handle_remote_reset(Connection *con) case MetaSession::STATE_OPENING: { ldout(cct, 1) << "reset from mds we were opening; retrying" << dendl; - list waiters; + std::vector waiters; waiters.swap(s->waiting_for_open); _closed_mds_session(s.get()); auto news = _get_or_open_mds_session(mds); diff --git a/src/client/Client.h b/src/client/Client.h index 658ecd4726fb6..5a1e69394d02a 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -1057,11 +1057,10 @@ protected: // helpers void wake_up_session_caps(MetaSession *s, bool reconnect); - void add_nonblocking_onfinish_to_context_list(std::list& ls, Context *onfinish) { - ls.push_back(onfinish); + void wait_on_context_list(std::vector& ls); + void signal_context_list(std::vector& ls) { + finish_contexts(cct, ls, 0); } - void wait_on_context_list(std::list& ls); - void signal_context_list(std::list& ls); void signal_caps_inode(Inode *in); // -- metadata cache stuff diff --git a/src/client/Inode.h b/src/client/Inode.h index 6392619335ceb..61188bd2f4479 100644 --- a/src/client/Inode.h +++ b/src/client/Inode.h @@ -238,9 +238,9 @@ struct Inode : RefCountedObject { std::map fragmap; // known frag -> mds mappings std::map> frag_repmap; // non-auth mds mappings - std::list waitfor_caps; - std::list waitfor_caps_pending; - std::list waitfor_commit; + std::vector waitfor_caps; + std::vector waitfor_caps_pending; + std::vector waitfor_commit; std::list waitfor_deleg; Dentry *get_first_parent() { diff --git a/src/client/MetaRequest.h b/src/client/MetaRequest.h index 240c0cd02a395..1b447050800ce 100644 --- a/src/client/MetaRequest.h +++ b/src/client/MetaRequest.h @@ -70,7 +70,7 @@ public: ceph::condition_variable *caller_cond = NULL; // who to take up ceph::condition_variable *dispatch_cond = NULL; // who to kick back - std::list waitfor_safe; + std::vector waitfor_safe; InodeRef target; UserPerm perms; diff --git a/src/client/MetaSession.h b/src/client/MetaSession.h index 301306263e66e..058272de053ee 100644 --- a/src/client/MetaSession.h +++ b/src/client/MetaSession.h @@ -47,7 +47,7 @@ struct MetaSession { int mds_state = MDSMap::STATE_NULL; bool readonly = false; - std::list waiting_for_open; + std::vector waiting_for_open; xlist caps; // dirty_list keeps all the dirty inodes before flushing in current session. -- 2.39.5