From 69d8dac132e3142f7d1ee0b000bd3894e29c90c9 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Tue, 25 Sep 2018 12:50:08 -0400 Subject: [PATCH] mds: initial code for client states reclaim this patch only implements function that cancels out old session [ jlayton: adapt to new fs_name field in cmount ] Signed-off-by: "Yan, Zheng" Signed-off-by: Jeff Layton --- src/client/Client.cc | 199 +++++++++++++++++++++++++++-- src/client/Client.h | 19 ++- src/client/MetaSession.h | 10 +- src/common/ceph_strings.cc | 2 +- src/include/ceph_fs.h | 5 + src/include/cephfs/libcephfs.h | 31 +++++ src/libcephfs.cc | 27 ++++ src/mds/MDSRank.cc | 1 + src/mds/Server.cc | 156 +++++++++++++++++++++- src/mds/Server.h | 10 +- src/mds/SessionMap.h | 1 + src/mds/cephfs_features.h | 2 + src/messages/MClientReclaim.h | 64 ++++++++++ src/messages/MClientReclaimReply.h | 69 ++++++++++ src/msg/Message.cc | 8 ++ 15 files changed, 583 insertions(+), 21 deletions(-) create mode 100644 src/messages/MClientReclaim.h create mode 100644 src/messages/MClientReclaimReply.h diff --git a/src/client/Client.cc b/src/client/Client.cc index 82577eff64f..a8534663ad2 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -54,6 +54,8 @@ #include "messages/MClientCaps.h" #include "messages/MClientLease.h" #include "messages/MClientSnap.h" +#include "messages/MClientReclaim.h" +#include "messages/MClientReclaimReply.h" #include "messages/MCommandReply.h" #include "messages/MOSDMap.h" #include "messages/MClientQuota.h" @@ -2550,6 +2552,11 @@ bool Client::ms_dispatch(Message *m) handle_client_reply(static_cast(m)); break; + // reclaim reply + case CEPH_MSG_CLIENT_RECLAIM_REPLY: + handle_client_reclaim_reply(static_cast(m)); + break; + case CEPH_MSG_CLIENT_SNAP: handle_snap(static_cast(m)); break; @@ -2775,6 +2782,9 @@ void Client::send_reconnect(MetaSession *session) session->con->send_message(m); mount_cond.Signal(); + + if (session->reclaim_state == MetaSession::RECLAIMING) + signal_cond_list(waiting_for_reclaim); } @@ -5709,18 +5719,8 @@ void Client::handle_command_reply(MCommandReply *m) // ------------------- // MOUNT -int Client::mount(const std::string &mount_root, const UserPerm& perms, - bool require_mds, const std::string &fs_name) +int Client::subscribe_mdsmap(const std::string &fs_name) { - Mutex::Locker lock(client_lock); - - if (mounted) { - ldout(cct, 5) << "already mounted" << dendl; - return 0; - } - - unmounting = false; - int r = authenticate(); if (r < 0) { lderr(cct) << "authentication failed: " << cpp_strerror(r) << dendl; @@ -5753,6 +5753,27 @@ int Client::mount(const std::string &mount_root, const UserPerm& perms, monclient->sub_want(want, 0, 0); monclient->renew_subs(); + return 0; +} + +int Client::mount(const std::string &mount_root, const UserPerm& perms, + bool require_mds, const std::string &fs_name) +{ + Mutex::Locker lock(client_lock); + + if (mounted) { + ldout(cct, 5) << "already mounted" << dendl; + return 0; + } + + unmounting = false; + + int r = subscribe_mdsmap(fs_name); + if (r < 0) { + lderr(cct) << "mdsmap subscription failed: " << cpp_strerror(r) << dendl; + return r; + } + tick(); // start tick if (require_mds) { @@ -14174,6 +14195,162 @@ void Client::clear_filer_flags(int flags) objecter->clear_global_op_flag(flags); } +// called before mount +void Client::set_uuid(const std::string& uuid) +{ + Mutex::Locker l(client_lock); + assert(initialized); + assert(!uuid.empty()); + + metadata["uuid"] = uuid; + _close_sessions(); +} + +// called before mount +int Client::start_reclaim(const std::string& uuid, unsigned flags, + const std::string& fs_name) +{ + Mutex::Locker l(client_lock); + if (!initialized) + return -ENOTCONN; + + if (uuid.empty()) + return -EINVAL; + + { + auto it = metadata.find("uuid"); + if (it != metadata.end() && it->second == uuid) + return -EINVAL; + } + + int r = subscribe_mdsmap(fs_name); + if (r < 0) { + lderr(cct) << "mdsmap subscription failed: " << cpp_strerror(r) << dendl; + return r; + } + + if (metadata.empty()) + populate_metadata(""); + + while (mdsmap->get_epoch() == 0) + wait_on_list(waiting_for_mdsmap); + + reclaim_errno = 0; + for (unsigned mds = 0; mds < mdsmap->get_num_in_mds(); ) { + if (!mdsmap->is_up(mds)) { + ldout(cct, 10) << "mds." << mds << " not active, waiting for new mdsmap" << dendl; + wait_on_list(waiting_for_mdsmap); + continue; + } + + MetaSession *session; + if (!have_open_session(mds)) { + session = _get_or_open_mds_session(mds); + if (session->state != MetaSession::STATE_OPENING) { + // umounting? + return -EINVAL; + } + ldout(cct, 10) << "waiting for session to mds." << mds << " to open" << dendl; + wait_on_context_list(session->waiting_for_open); + if (rejected_by_mds.count(mds)) + return -EPERM; + continue; + } + + session = &mds_sessions.at(mds); + if (!session->mds_features.test(CEPHFS_FEATURE_RECLAIM_CLIENT)) + return -EOPNOTSUPP; + + if (session->reclaim_state == MetaSession::RECLAIM_NULL || + session->reclaim_state == MetaSession::RECLAIMING) { + session->reclaim_state = MetaSession::RECLAIMING; + auto m = MClientReclaim::create(uuid, flags); + session->con->send_message2(m); + wait_on_list(waiting_for_reclaim); + } else if (session->reclaim_state == MetaSession::RECLAIM_FAIL) { + return reclaim_errno ? : -ENOTRECOVERABLE; + } else { + mds++; + } + } + + // didn't find target session in any mds + if (reclaim_target_addrs.empty()) { + if (flags & CEPH_RECLAIM_RESET) + return -ENOENT; + return -ENOTRECOVERABLE; + } + + if (flags & CEPH_RECLAIM_RESET) + return 0; + + // use blacklist to check if target session was killed + // (config option mds_session_blacklist_on_evict needs to be true) + C_SaferCond cond; + if (!objecter->wait_for_map(reclaim_osd_epoch, &cond)) { + ldout(cct, 10) << __func__ << ": waiting for OSD epoch " << reclaim_osd_epoch << dendl; + client_lock.Unlock(); + cond.wait(); + client_lock.Lock(); + } + + bool blacklisted = objecter->with_osdmap( + [this](const OSDMap &osd_map) -> bool { + return osd_map.is_blacklisted(reclaim_target_addrs); + }); + if (blacklisted) + return -ENOTRECOVERABLE; + + metadata["reclaiming_uuid"] = uuid; + return 0; +} + +void Client::finish_reclaim() +{ + auto it = metadata.find("reclaiming_uuid"); + if (it == metadata.end()) { + for (auto &it : mds_sessions) + it.second.reclaim_state = MetaSession::RECLAIM_NULL; + return; + } + + for (auto &it : mds_sessions) { + it.second.reclaim_state = MetaSession::RECLAIM_NULL; + auto m = MClientReclaim::create("", MClientReclaim::FLAG_FINISH); + it.second.con->send_message2(m); + } + + metadata["uuid"] = it->second; + metadata.erase(it); +} + +void Client::handle_client_reclaim_reply(MClientReclaimReply *reply) +{ + mds_rank_t from = mds_rank_t(reply->get_source().num()); + ldout(cct, 10) << __func__ << " " << *reply << " from mds." << from << dendl; + + MetaSession *session = _get_mds_session(from, reply->get_connection().get()); + if (!session) { + ldout(cct, 10) << " discarding reclaim reply from sessionless mds." << from << dendl; + reply->put(); + return; + } + + if (reply->get_result() >= 0) { + session->reclaim_state = MetaSession::RECLAIM_OK; + if (reply->get_epoch() > reclaim_osd_epoch) + reclaim_osd_epoch = reply->get_epoch(); + if (!reply->get_addrs().empty()) + reclaim_target_addrs = reply->get_addrs(); + } else { + session->reclaim_state = MetaSession::RECLAIM_FAIL; + reclaim_errno = reply->get_result(); + } + + signal_cond_list(waiting_for_reclaim); + reply->put(); +} + /** * This is included in cap release messages, to cause * the MDS to wait until this OSD map epoch. It is necessary diff --git a/src/client/Client.h b/src/client/Client.h index 8aacf6d07ed..b8c4d7cc044 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -58,8 +58,9 @@ class MClientRequest; class MClientSession; class MClientRequest; class MClientRequestForward; -struct MClientLease; +class MClientLease; class MClientCaps; +class MClientReclaimReply; struct DirStat; struct LeaseStat; @@ -296,6 +297,11 @@ public: void unmount(); void abort_conn(); + void set_uuid(const std::string& uuid); + int start_reclaim(const std::string& uuid, unsigned flags, + const std::string& fs_name); + void finish_reclaim(); + int mds_command( const std::string &mds_spec, const std::vector& cmd, @@ -862,7 +868,10 @@ protected: void put_inode(Inode *in, int n=1); void close_dir(Dir *dir); + int subscribe_mdsmap(const std::string &fs_name=""); + void _abort_mds_sessions(int err); + // same as unmount() but for when the client_lock is already held void _unmount(bool abort); @@ -928,6 +937,8 @@ protected: int check_pool_perm(Inode *in, int need); + void handle_client_reclaim_reply(MClientReclaimReply *reply); + /** * Call this when an OSDMap is seen with a full flag (global or per pool) * set. @@ -1276,6 +1287,12 @@ private: list waiting_for_pool_perm; uint64_t retries_on_invalidate = 0; + + // state reclaim + list waiting_for_reclaim; + int reclaim_errno = 0; + epoch_t reclaim_osd_epoch = 0; + entity_addrvec_t reclaim_target_addrs; }; /** diff --git a/src/client/MetaSession.h b/src/client/MetaSession.h index b00abad27e6..af2d7acd764 100644 --- a/src/client/MetaSession.h +++ b/src/client/MetaSession.h @@ -35,6 +35,13 @@ struct MetaSession { STATE_STALE, } state; + enum { + RECLAIM_NULL, + RECLAIMING, + RECLAIM_OK, + RECLAIM_FAIL, + } reclaim_state; + int mds_state; bool readonly; @@ -53,7 +60,8 @@ struct MetaSession { const entity_addrvec_t& addrs) : mds_num(mds_num), con(con), seq(0), cap_gen(0), cap_renew_seq(0), addrs(addrs), - state(STATE_OPENING), mds_state(MDSMap::STATE_NULL), readonly(false) + state(STATE_OPENING), reclaim_state(RECLAIM_NULL), + mds_state(MDSMap::STATE_NULL), readonly(false) {} const char *get_state_name() const; diff --git a/src/common/ceph_strings.cc b/src/common/ceph_strings.cc index 3709d597764..3e453a2663a 100644 --- a/src/common/ceph_strings.cc +++ b/src/common/ceph_strings.cc @@ -294,7 +294,7 @@ const char *ceph_session_op_name(int op) case CEPH_SESSION_FLUSHMSG_ACK: return "flushmsg_ack"; case CEPH_SESSION_FORCE_RO: return "force_ro"; case CEPH_SESSION_REJECT: return "reject"; - case CEPH_SESSION_REQUEST_FLUSH_MDLOG: return "request_flush_mdlog"; + case CEPH_SESSION_REQUEST_FLUSH_MDLOG: return "request_flushmdlog"; } return "???"; } diff --git a/src/include/ceph_fs.h b/src/include/ceph_fs.h index 68305939cdb..b4f4cbea6e7 100644 --- a/src/include/ceph_fs.h +++ b/src/include/ceph_fs.h @@ -111,6 +111,8 @@ struct ceph_dir_layout { #define CEPH_MSG_CLIENT_REQUEST 24 #define CEPH_MSG_CLIENT_REQUEST_FORWARD 25 #define CEPH_MSG_CLIENT_REPLY 26 +#define CEPH_MSG_CLIENT_RECLAIM 27 +#define CEPH_MSG_CLIENT_RECLAIM_REPLY 28 #define CEPH_MSG_CLIENT_CAPS 0x310 #define CEPH_MSG_CLIENT_LEASE 0x311 #define CEPH_MSG_CLIENT_SNAP 0x312 @@ -310,6 +312,9 @@ enum { CEPH_SESSION_REQUEST_FLUSH_MDLOG }; +// flags for state reclaim +#define CEPH_RECLAIM_RESET 1 + extern const char *ceph_session_op_name(int op); struct ceph_mds_session_head { diff --git a/src/include/cephfs/libcephfs.h b/src/include/cephfs/libcephfs.h index be367e45b8b..4573fa5ce84 100644 --- a/src/include/cephfs/libcephfs.h +++ b/src/include/cephfs/libcephfs.h @@ -1772,6 +1772,37 @@ int ceph_ll_delegation(struct ceph_mount_info *cmount, Fh *fh, mode_t ceph_umask(struct ceph_mount_info *cmount, mode_t mode); +/* state reclaim */ +#define CEPH_RECLAIM_RESET 1 + +/** + * Set ceph client uuid + * @param cmount the ceph mount handle to use. + * @param uuid the uuid to set + * + * Must be called before mount. + */ +void ceph_set_uuid(struct ceph_mount_info *cmount, const char *uuid); + +/** + * Start to reclaim states of other client + * @param cmount the ceph mount handle to use. + * @param uuid uuid of client whose states need to be reclaimed + * @param flags flags that control how states get reclaimed + * + * Returns 0 success, -EOPNOTSUPP if mds does not support the operation, + * -ENOENT if CEPH_RECLAIM_RESET is specified and there is no client + * with the given uuid, -ENOTRECOVERABLE in all other error cases. + */ +int ceph_start_reclaim(struct ceph_mount_info *cmount, + const char *uuid, unsigned flags); + +/** + * finish reclaiming states of other client ( + * @param cmount the ceph mount handle to use. + */ +void ceph_finish_reclaim(struct ceph_mount_info *cmount); + #ifdef __cplusplus } #endif diff --git a/src/libcephfs.cc b/src/libcephfs.cc index eff9cc70a73..9d27e23984a 100644 --- a/src/libcephfs.cc +++ b/src/libcephfs.cc @@ -137,6 +137,11 @@ public: return 0; } + const std::string& get_filesystem(void) + { + return fs_name; + } + int mount(const std::string &mount_root, const UserPerm& perms) { int ret; @@ -1912,3 +1917,25 @@ extern "C" int ceph_set_deleg_timeout(class ceph_mount_info *cmount, uint32_t ti return -ENOTCONN; return cmount->get_client()->set_deleg_timeout(timeout); } + +extern "C" void ceph_set_uuid(class ceph_mount_info *cmount, const char *uuid) +{ + cmount->get_client()->set_uuid(std::string(uuid)); +} + +extern "C" int ceph_start_reclaim(class ceph_mount_info *cmount, + const char *uuid, unsigned flags) +{ + if (!cmount->is_initialized()) { + int ret = cmount->init(); + if (ret != 0) + return ret; + } + return cmount->get_client()->start_reclaim(std::string(uuid), flags, + cmount->get_filesystem()); +} + +extern "C" void ceph_finish_reclaim(class ceph_mount_info *cmount) +{ + cmount->get_client()->finish_reclaim(); +} diff --git a/src/mds/MDSRank.cc b/src/mds/MDSRank.cc index a365ed8223a..58ed76055b3 100644 --- a/src/mds/MDSRank.cc +++ b/src/mds/MDSRank.cc @@ -754,6 +754,7 @@ bool MDSRank::handle_deferrable_message(const Message::const_ref &m) // SERVER case CEPH_MSG_CLIENT_SESSION: case CEPH_MSG_CLIENT_RECONNECT: + case CEPH_MSG_CLIENT_RECLAIM: ALLOW_MESSAGES_FROM(CEPH_ENTITY_TYPE_CLIENT); // fall-thru case CEPH_MSG_CLIENT_REQUEST: diff --git a/src/mds/Server.cc b/src/mds/Server.cc index 3d8f3c9a2bc..8ba4d7fa6f9 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -40,6 +40,7 @@ #include "events/EOpen.h" #include "events/ECommitted.h" +#include "include/stringify.h" #include "include/filepath.h" #include "common/errno.h" #include "common/Timer.h" @@ -259,6 +260,9 @@ void Server::dispatch(const Message::const_ref &m) case CEPH_MSG_CLIENT_REQUEST: handle_client_request(MClientRequest::msgref_cast(m)); return; + case CEPH_MSG_CLIENT_RECLAIM: + handle_client_reclaim(MClientReclaim::msgref_cast(m)); + return; case MSG_MDS_SLAVE_REQUEST: handle_slave_request(MMDSSlaveRequest::msgref_cast(m)); return; @@ -295,6 +299,132 @@ public: } }; +Session* Server::find_session_by_uuid(std::string_view uuid) +{ + Session* session = nullptr; + for (auto& it : mds->sessionmap.get_sessions()) { + auto& metadata = it.second->info.client_metadata; + + auto p = metadata.find("uuid"); + if (p == metadata.end() || p->second != uuid) + continue; + + if (!session) { + session = it.second; + } else if (!session->reclaiming_from) { + assert(it.second->reclaiming_from == session); + session = it.second; + } else { + assert(session->reclaiming_from == it.second); + } + } + return session; +} + +void Server::reclaim_session(Session *session, const MClientReclaim::const_ref &m) +{ + if (!session->is_open() && !session->is_stale()) { + dout(10) << "session not open, dropping this req" << dendl; + return; + } + + auto reply = MClientReclaimReply::create(0); + if (m->get_uuid().empty()) { + dout(10) << __func__ << " invalid message (no uuid)" << dendl; + reply->set_result(-EINVAL); + mds->send_message_client(reply, session); + return; + } + + unsigned flags = m->get_flags(); + if (flags != CEPH_RECLAIM_RESET) { // currently only support reset + dout(10) << __func__ << " unsupported flags" << dendl; + reply->set_result(-EOPNOTSUPP); + mds->send_message_client(reply, session); + return; + } + + Session* target = find_session_by_uuid(m->get_uuid()); + if (target) { + assert(!target->reclaiming_from); + assert(!session->reclaiming_from); + session->reclaiming_from = target; + reply->set_addrs(entity_addrvec_t(target->info.inst.addr)); + } + + if (flags & CEPH_RECLAIM_RESET) { + finish_reclaim_session(session, reply); + return; + } + + ceph_abort(); +} + +void Server::finish_reclaim_session(Session *session, const MClientReclaimReply::ref &reply) +{ + Session *target = session->reclaiming_from; + if (target) { + session->reclaiming_from = nullptr; + + Context *send_reply; + if (reply) { + int64_t session_id = session->get_client().v; + send_reply = new FunctionContext([this, session_id, reply](int r) { + assert(mds->mds_lock.is_locked_by_me()); + Session *session = mds->sessionmap.get_session(entity_name_t::CLIENT(session_id)); + if (!session) { + reply->put(); + return; + } + auto epoch = mds->objecter->with_osdmap([](const OSDMap &map){ return map.get_epoch(); }); + reply->set_epoch(epoch); + mds->send_message_client(reply, session); + }); + } else { + send_reply = nullptr; + } + + bool blacklisted = mds->objecter->with_osdmap([target](const OSDMap &map) { + return map.is_blacklisted(target->info.inst.addr); + }); + + if (blacklisted || !g_conf()->mds_session_blacklist_on_evict) { + kill_session(target, send_reply); + } else { + std::stringstream ss; + mds->evict_client(target->get_client().v, false, true, ss, send_reply); + } + } else if (reply) { + mds->send_message_client(reply, session); + } +} + +void Server::handle_client_reclaim(const MClientReclaim::const_ref &m) +{ + Session *session = mds->get_session(m); + dout(3) << __func__ << " " << *m << " from " << m->get_source() << dendl; + assert(m->get_source().is_client()); // should _not_ come from an mds! + + if (!session) { + dout(0) << " ignoring sessionless msg " << *m << dendl; + m->put(); + return; + } + + if (mds->get_state() < MDSMap::STATE_CLIENTREPLAY) { + mds->wait_for_replay(new C_MDS_RetryMessage(mds, m)); + return; + } + + if (m->get_flags() & MClientReclaim::FLAG_FINISH) { + finish_reclaim_session(session); + } else { + reclaim_session(session, m); + } + m->put(); +} + +/* This function DOES put the passed message before returning*/ void Server::handle_client_session(const MClientSession::const_ref &m) { version_t pv; @@ -415,6 +545,17 @@ void Server::handle_client_session(const MClientSession::const_ref &m) } } + it = client_metadata.find("uuid"); + if (it != client_metadata.end()) { + if (find_session_by_uuid(it->second)) { + send_reject_message("duplicated session uuid"); + mds->clog->warn() << "client session with duplicated session uuid '" + << it->second << "' denied (" << session->info.inst << ")"; + session->clear(); + break; + } + } + session->set_client_metadata(client_metadata); if (session->is_closed()) @@ -871,12 +1012,15 @@ void Server::kill_session(Session *session, Context *on_safe) journal_close_session(session, Session::STATE_KILLING, on_safe); } else { dout(10) << "kill_session importing or already closing/killing " << session << dendl; - ceph_assert(session->is_closing() || - session->is_closed() || - session->is_killing() || - session->is_importing()); - if (on_safe) { - on_safe->complete(0); + if (session->is_closing() || + session->is_killing()) { + if (on_safe) + mdlog->wait_for_safe(new MDSInternalContextWrapper(mds, on_safe)); + } else { + ceph_assert(session->is_closed() || + session->is_importing()); + if (on_safe) + on_safe->complete(0); } } } diff --git a/src/mds/Server.h b/src/mds/Server.h index c53f7271d18..40b1077d200 100644 --- a/src/mds/Server.h +++ b/src/mds/Server.h @@ -22,6 +22,8 @@ #include "messages/MClientRequest.h" #include "messages/MClientSession.h" #include "messages/MClientSnap.h" +#include "messages/MClientReclaim.h" +#include "messages/MClientReclaimReply.h" #include "messages/MLock.h" #include "MDSRank.h" @@ -33,8 +35,8 @@ class PerfCounters; class LogEvent; class EMetaBlob; class EUpdate; -struct SnapInfo; class MDLog; +struct SnapInfo; enum { l_mdss_first = 1000, @@ -142,6 +144,12 @@ public: void kill_session(Session *session, Context *on_safe); size_t apply_blacklist(const std::set &blacklist); void journal_close_session(Session *session, int state, Context *on_safe); + + Session *find_session_by_uuid(std::string_view uuid); + void reclaim_session(Session *session, const MClientReclaim::const_ref &m); + void finish_reclaim_session(Session *session, const MClientReclaimReply::ref &reply=nullptr); + void handle_client_reclaim(const MClientReclaim::const_ref &m); + void reconnect_clients(MDSInternalContext *reconnect_done_); void handle_client_reconnect(const MClientReconnect::const_ref &m); void infer_supported_features(Session *session, client_metadata_t& client_metadata); diff --git a/src/mds/SessionMap.h b/src/mds/SessionMap.h index 1c1d9f818a1..8e9bebea442 100644 --- a/src/mds/SessionMap.h +++ b/src/mds/SessionMap.h @@ -120,6 +120,7 @@ private: time birth_time; public: + Session *reclaiming_from = nullptr; void push_pv(version_t pv) { diff --git a/src/mds/cephfs_features.h b/src/mds/cephfs_features.h index 4788d4ba571..8ad16cc2f8c 100644 --- a/src/mds/cephfs_features.h +++ b/src/mds/cephfs_features.h @@ -24,6 +24,7 @@ #define CEPHFS_FEATURE_LUMINOUS 7 #define CEPHFS_FEATURE_MIMIC 8 #define CEPHFS_FEATURE_REPLY_ENCODING 9 +#define CEPHFS_FEATURE_RECLAIM_CLIENT 10 #define CEPHFS_FEATURES_ALL { \ 0, 1, 2, 3, 4, \ @@ -32,6 +33,7 @@ CEPHFS_FEATURE_LUMINOUS, \ CEPHFS_FEATURE_MIMIC, \ CEPHFS_FEATURE_REPLY_ENCODING, \ + CEPHFS_FEATURE_RECLAIM_CLIENT, \ } #define CEPHFS_FEATURES_MDS_SUPPORTED CEPHFS_FEATURES_ALL diff --git a/src/messages/MClientReclaim.h b/src/messages/MClientReclaim.h new file mode 100644 index 00000000000..75206f90743 --- /dev/null +++ b/src/messages/MClientReclaim.h @@ -0,0 +1,64 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2004-2006 Sage Weil + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + + +#ifndef CEPH_MCLIENTRECLAIM_H +#define CEPH_MCLIENTRECLAIM_H + +#include "msg/Message.h" + +class MClientReclaim: public MessageInstance { +public: + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; + static constexpr uint32_t FLAG_FINISH = 1U << 31; + + uint32_t get_flags() const { return flags; } + std::string_view get_uuid() const { return uuid; } + + const char *get_type_name() const override { return "client_reclaim"; } + void print(ostream& o) const override { + std::ios_base::fmtflags f(o.flags()); + o << "client_reclaim(" << get_uuid() << " flags 0x" << std::hex << get_flags() << ")"; + o.flags(f); + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(uuid, payload); + encode(flags, payload); + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(uuid, p); + decode(flags, p); + } + +protected: + friend factory; + MClientReclaim() : + MessageInstance(CEPH_MSG_CLIENT_RECLAIM, HEAD_VERSION, COMPAT_VERSION) {} + MClientReclaim(std::string_view _uuid, uint32_t _flags) : + MessageInstance(CEPH_MSG_CLIENT_RECLAIM, HEAD_VERSION, COMPAT_VERSION), + uuid(_uuid), flags(_flags) {} +private: + ~MClientReclaim() override {} + + std::string uuid; + uint32_t flags = 0; +}; + +#endif diff --git a/src/messages/MClientReclaimReply.h b/src/messages/MClientReclaimReply.h new file mode 100644 index 00000000000..7f88c3d1d89 --- /dev/null +++ b/src/messages/MClientReclaimReply.h @@ -0,0 +1,69 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2004-2006 Sage Weil + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + + +#ifndef CEPH_MCLIENTRECLAIMREPLY_H +#define CEPH_MCLIENTRECLAIMREPLY_H + +#include "msg/Message.h" + +class MClientReclaimReply: public MessageInstance { +public: + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; + + int32_t get_result() const { return result; } + void set_result(int r) { result = r; } + epoch_t get_epoch() const { return epoch; } + void set_epoch(epoch_t e) { epoch = e; } + const entity_addrvec_t& get_addrs() const { return addrs; } + void set_addrs(const entity_addrvec_t& _addrs) { addrs = _addrs; } + + const char *get_type_name() const override { return "client_reclaim_reply"; } + void print(ostream& o) const override { + o << "client_reclaim_reply(" << result << " e " << epoch << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(result, payload); + encode(epoch, payload); + encode(addrs, payload, features); + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(result, p); + decode(epoch, p); + decode(addrs, p); + } + +protected: + friend factory; + MClientReclaimReply() : + MessageInstance(CEPH_MSG_CLIENT_RECLAIM_REPLY, HEAD_VERSION, COMPAT_VERSION) {} + MClientReclaimReply(int r, epoch_t e=0) : + MessageInstance(CEPH_MSG_CLIENT_RECLAIM_REPLY, HEAD_VERSION, COMPAT_VERSION), + result(r), epoch(e) {} + +private: + ~MClientReclaimReply() override {} + + int32_t result; + epoch_t epoch; + entity_addrvec_t addrs; +}; + +#endif diff --git a/src/msg/Message.cc b/src/msg/Message.cc index 92defd17d43..693ecc94cd2 100644 --- a/src/msg/Message.cc +++ b/src/msg/Message.cc @@ -114,6 +114,8 @@ #include "messages/MClientRequest.h" #include "messages/MClientRequestForward.h" #include "messages/MClientReply.h" +#include "messages/MClientReclaim.h" +#include "messages/MClientReclaimReply.h" #include "messages/MClientCaps.h" #include "messages/MClientCapRelease.h" #include "messages/MClientLease.h" @@ -617,6 +619,12 @@ Message *decode_message(CephContext *cct, int crcflags, case CEPH_MSG_CLIENT_REPLY: m = MClientReply::create(); break; + case CEPH_MSG_CLIENT_RECLAIM: + m = MClientReclaim::create(); + break; + case CEPH_MSG_CLIENT_RECLAIM_REPLY: + m = MClientReclaimReply::create(); + break; case CEPH_MSG_CLIENT_CAPS: m = MClientCaps::create(); break; -- 2.39.5