#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"
handle_client_reply(static_cast<MClientReply*>(m));
break;
+ // reclaim reply
+ case CEPH_MSG_CLIENT_RECLAIM_REPLY:
+ handle_client_reclaim_reply(static_cast<MClientReclaimReply*>(m));
+ break;
+
case CEPH_MSG_CLIENT_SNAP:
handle_snap(static_cast<MClientSnap*>(m));
break;
session->con->send_message(m);
mount_cond.Signal();
+
+ if (session->reclaim_state == MetaSession::RECLAIMING)
+ signal_cond_list(waiting_for_reclaim);
}
// -------------------
// 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;
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) {
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
class MClientSession;
class MClientRequest;
class MClientRequestForward;
-struct MClientLease;
+class MClientLease;
class MClientCaps;
+class MClientReclaimReply;
struct DirStat;
struct LeaseStat;
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<std::string>& cmd,
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);
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.
list<Cond*> waiting_for_pool_perm;
uint64_t retries_on_invalidate = 0;
+
+ // state reclaim
+ list<Cond*> waiting_for_reclaim;
+ int reclaim_errno = 0;
+ epoch_t reclaim_osd_epoch = 0;
+ entity_addrvec_t reclaim_target_addrs;
};
/**
STATE_STALE,
} state;
+ enum {
+ RECLAIM_NULL,
+ RECLAIMING,
+ RECLAIM_OK,
+ RECLAIM_FAIL,
+ } reclaim_state;
+
int mds_state;
bool readonly;
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;
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 "???";
}
#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
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 {
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
return 0;
}
+ const std::string& get_filesystem(void)
+ {
+ return fs_name;
+ }
+
int mount(const std::string &mount_root, const UserPerm& perms)
{
int ret;
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();
+}
// 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:
#include "events/EOpen.h"
#include "events/ECommitted.h"
+#include "include/stringify.h"
#include "include/filepath.h"
#include "common/errno.h"
#include "common/Timer.h"
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;
}
};
+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;
}
}
+ 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())
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);
}
}
}
#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"
class LogEvent;
class EMetaBlob;
class EUpdate;
-struct SnapInfo;
class MDLog;
+struct SnapInfo;
enum {
l_mdss_first = 1000,
void kill_session(Session *session, Context *on_safe);
size_t apply_blacklist(const std::set<entity_addr_t> &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);
time birth_time;
public:
+ Session *reclaiming_from = nullptr;
void push_pv(version_t pv)
{
#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, \
CEPHFS_FEATURE_LUMINOUS, \
CEPHFS_FEATURE_MIMIC, \
CEPHFS_FEATURE_REPLY_ENCODING, \
+ CEPHFS_FEATURE_RECLAIM_CLIENT, \
}
#define CEPHFS_FEATURES_MDS_SUPPORTED CEPHFS_FEATURES_ALL
--- /dev/null
+// -*- 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 <sage@newdream.net>
+ *
+ * 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<MClientReclaim> {
+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
--- /dev/null
+// -*- 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 <sage@newdream.net>
+ *
+ * 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<MClientReclaimReply> {
+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
#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"
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;