diff options
Diffstat (limited to 'src/messages')
171 files changed, 16616 insertions, 0 deletions
diff --git a/src/messages/MAuth.h b/src/messages/MAuth.h new file mode 100644 index 000000000..8e066a3cf --- /dev/null +++ b/src/messages/MAuth.h @@ -0,0 +1,66 @@ +// -*- 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_MAUTH_H +#define CEPH_MAUTH_H + +#include <string_view> + +#include "include/encoding.h" + +#include "msg/Message.h" +#include "msg/MessageRef.h" +#include "messages/PaxosServiceMessage.h" + +class MAuth final : public PaxosServiceMessage { +public: + __u32 protocol; + ceph::buffer::list auth_payload; + epoch_t monmap_epoch; + + /* if protocol == 0, then auth_payload is a set<__u32> listing protocols the client supports */ + + MAuth() : PaxosServiceMessage{CEPH_MSG_AUTH, 0}, protocol(0), monmap_epoch(0) { } +private: + ~MAuth() final {} + +public: + std::string_view get_type_name() const override { return "auth"; } + void print(std::ostream& out) const override { + out << "auth(proto " << protocol << " " << auth_payload.length() << " bytes" + << " epoch " << monmap_epoch << ")"; + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + paxos_decode(p); + decode(protocol, p); + decode(auth_payload, p); + if (!p.end()) + decode(monmap_epoch, p); + else + monmap_epoch = 0; + } + void encode_payload(uint64_t features) override { + using ceph::encode; + paxos_encode(); + encode(protocol, payload); + encode(auth_payload, payload); + encode(monmap_epoch, payload); + } + ceph::buffer::list& get_auth_payload() { return auth_payload; } +}; + +#endif diff --git a/src/messages/MAuthReply.h b/src/messages/MAuthReply.h new file mode 100644 index 000000000..1c7c5e506 --- /dev/null +++ b/src/messages/MAuthReply.h @@ -0,0 +1,68 @@ +// -*- 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_MAUTHREPLY_H +#define CEPH_MAUTHREPLY_H + +#include "msg/Message.h" +#include "common/errno.h" + +class MAuthReply final : public Message { +public: + __u32 protocol; + errorcode32_t result; + uint64_t global_id; // if zero, meaningless + std::string result_msg; + ceph::buffer::list result_bl; + + MAuthReply() : Message(CEPH_MSG_AUTH_REPLY), protocol(0), result(0), global_id(0) {} + MAuthReply(__u32 p, ceph::buffer::list *bl = NULL, int r = 0, uint64_t gid=0, const char *msg = "") : + Message(CEPH_MSG_AUTH_REPLY), + protocol(p), result(r), global_id(gid), + result_msg(msg) { + if (bl) + result_bl = *bl; + } +private: + ~MAuthReply() final {} + +public: + std::string_view get_type_name() const override { return "auth_reply"; } + void print(std::ostream& o) const override { + o << "auth_reply(proto " << protocol << " " << result << " " << cpp_strerror(result); + if (result_msg.length()) + o << ": " << result_msg; + o << ")"; + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(protocol, p); + decode(result, p); + decode(global_id, p); + decode(result_bl, p); + decode(result_msg, p); + } + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(protocol, payload); + encode(result, payload); + encode(global_id, payload); + encode(result_bl, payload); + encode(result_msg, payload); + } +}; + +#endif diff --git a/src/messages/MBackfillReserve.h b/src/messages/MBackfillReserve.h new file mode 100644 index 000000000..fbb262b83 --- /dev/null +++ b/src/messages/MBackfillReserve.h @@ -0,0 +1,180 @@ +// -*- 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_MBACKFILL_H +#define CEPH_MBACKFILL_H + +#include "msg/Message.h" +#include "messages/MOSDPeeringOp.h" +#include "osd/PGPeeringEvent.h" + +class MBackfillReserve : public MOSDPeeringOp { +private: + static constexpr int HEAD_VERSION = 5; + static constexpr int COMPAT_VERSION = 4; +public: + spg_t pgid; + epoch_t query_epoch; + enum { + REQUEST = 0, // primary->replica: please reserve a slot + GRANT = 1, // replica->primary: ok, i reserved it + REJECT_TOOFULL = 2, // replica->primary: too full, sorry, try again later (*) + RELEASE = 3, // primary->replcia: release the slot i reserved before + REVOKE_TOOFULL = 4, // replica->primary: too full, stop backfilling + REVOKE = 5, // replica->primary: i'm taking back the slot i gave you + // (*) NOTE: prior to luminous, REJECT was overloaded to also mean release + }; + uint32_t type; + uint32_t priority; + int64_t primary_num_bytes; + int64_t shard_num_bytes; + + spg_t get_spg() const { + return pgid; + } + epoch_t get_map_epoch() const { + return query_epoch; + } + epoch_t get_min_epoch() const { + return query_epoch; + } + + PGPeeringEvent *get_event() override { + switch (type) { + case REQUEST: + return new PGPeeringEvent( + query_epoch, + query_epoch, + RequestBackfillPrio(priority, primary_num_bytes, shard_num_bytes)); + case GRANT: + return new PGPeeringEvent( + query_epoch, + query_epoch, + RemoteBackfillReserved()); + case REJECT_TOOFULL: + // NOTE: this is replica -> primary "i reject your request" + // and also primary -> replica "cancel my previously-granted request" + // (for older peers) + // and also replica -> primary "i revoke your reservation" + // (for older peers) + return new PGPeeringEvent( + query_epoch, + query_epoch, + RemoteReservationRejectedTooFull()); + case RELEASE: + return new PGPeeringEvent( + query_epoch, + query_epoch, + RemoteReservationCanceled()); + case REVOKE_TOOFULL: + return new PGPeeringEvent( + query_epoch, + query_epoch, + RemoteReservationRevokedTooFull()); + case REVOKE: + return new PGPeeringEvent( + query_epoch, + query_epoch, + RemoteReservationRevoked()); + default: + ceph_abort(); + } + } + + MBackfillReserve() + : MOSDPeeringOp{MSG_OSD_BACKFILL_RESERVE, HEAD_VERSION, COMPAT_VERSION}, + query_epoch(0), type(-1), priority(-1), primary_num_bytes(0), + shard_num_bytes(0) {} + MBackfillReserve(int type, + spg_t pgid, + epoch_t query_epoch, unsigned prio = -1, + int64_t primary_num_bytes = 0, + int64_t shard_num_bytes = 0) + : MOSDPeeringOp{MSG_OSD_BACKFILL_RESERVE, HEAD_VERSION, COMPAT_VERSION}, + pgid(pgid), query_epoch(query_epoch), + type(type), priority(prio), primary_num_bytes(primary_num_bytes), + shard_num_bytes(shard_num_bytes) {} + + std::string_view get_type_name() const override { + return "MBackfillReserve"; + } + + void inner_print(std::ostream& out) const override { + switch (type) { + case REQUEST: + out << "REQUEST"; + break; + case GRANT: + out << "GRANT"; + break; + case REJECT_TOOFULL: + out << "REJECT_TOOFULL"; + break; + case RELEASE: + out << "RELEASE"; + break; + case REVOKE_TOOFULL: + out << "REVOKE_TOOFULL"; + break; + case REVOKE: + out << "REVOKE"; + break; + } + if (type == REQUEST) out << " prio: " << priority; + return; + } + + void decode_payload() override { + auto p = payload.cbegin(); + using ceph::decode; + decode(pgid.pgid, p); + decode(query_epoch, p); + decode(type, p); + decode(priority, p); + decode(pgid.shard, p); + if (header.version >= 5) { + decode(primary_num_bytes, p); + decode(shard_num_bytes, p); + } else { + primary_num_bytes = 0; + shard_num_bytes = 0; + } + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + if (!HAVE_FEATURE(features, RECOVERY_RESERVATION_2)) { + header.version = 3; + header.compat_version = 3; + encode(pgid.pgid, payload); + encode(query_epoch, payload); + encode((type == RELEASE || type == REVOKE_TOOFULL || type == REVOKE) ? + REJECT_TOOFULL : type, payload); + encode(priority, payload); + encode(pgid.shard, payload); + return; + } + header.version = HEAD_VERSION; + header.compat_version = COMPAT_VERSION; + encode(pgid.pgid, payload); + encode(query_epoch, payload); + encode(type, payload); + encode(priority, payload); + encode(pgid.shard, payload); + encode(primary_num_bytes, payload); + encode(shard_num_bytes, payload); + } +}; + +#endif diff --git a/src/messages/MCacheExpire.h b/src/messages/MCacheExpire.h new file mode 100644 index 000000000..1c9334ba0 --- /dev/null +++ b/src/messages/MCacheExpire.h @@ -0,0 +1,112 @@ +// -*- 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_MCACHEEXPIRE_H +#define CEPH_MCACHEEXPIRE_H + +#include <string_view> +#include "mds/mdstypes.h" +#include "messages/MMDSOp.h" + +class MCacheExpire final : public MMDSOp { +private: + __s32 from; + +public: + /* + group things by realm (auth delgation root), since that's how auth is determined. + that makes it less work to process when exports are in progress. + */ + struct realm { + std::map<vinodeno_t, uint32_t> inodes; + std::map<dirfrag_t, uint32_t> dirs; + std::map<dirfrag_t, std::map<std::pair<std::string,snapid_t>,uint32_t> > dentries; + + void merge(const realm& o) { + inodes.insert(o.inodes.begin(), o.inodes.end()); + dirs.insert(o.dirs.begin(), o.dirs.end()); + for (const auto &p : o.dentries) { + auto em = dentries.emplace(std::piecewise_construct, std::forward_as_tuple(p.first), std::forward_as_tuple(p.second)); + if (!em.second) { + em.first->second.insert(p.second.begin(), p.second.end()); + } + } + } + + void encode(ceph::buffer::list &bl) const { + using ceph::encode; + encode(inodes, bl); + encode(dirs, bl); + encode(dentries, bl); + } + void decode(ceph::buffer::list::const_iterator &bl) { + using ceph::decode; + decode(inodes, bl); + decode(dirs, bl); + decode(dentries, bl); + } + }; + WRITE_CLASS_ENCODER(realm) + + std::map<dirfrag_t, realm> realms; + + int get_from() const { return from; } + +protected: + MCacheExpire() : MMDSOp{MSG_MDS_CACHEEXPIRE}, from(-1) {} + MCacheExpire(int f) : + MMDSOp{MSG_MDS_CACHEEXPIRE}, + from(f) { } + ~MCacheExpire() final {} + +public: + std::string_view get_type_name() const override { return "cache_expire";} + + void add_inode(dirfrag_t r, vinodeno_t vino, unsigned nonce) { + realms[r].inodes[vino] = nonce; + } + void add_dir(dirfrag_t r, dirfrag_t df, unsigned nonce) { + realms[r].dirs[df] = nonce; + } + void add_dentry(dirfrag_t r, dirfrag_t df, std::string_view dn, snapid_t last, unsigned nonce) { + realms[r].dentries[df][std::pair<std::string,snapid_t>(dn,last)] = nonce; + } + + void add_realm(dirfrag_t df, const realm& r) { + auto em = realms.emplace(std::piecewise_construct, std::forward_as_tuple(df), std::forward_as_tuple(r)); + if (!em.second) { + em.first->second.merge(r); + } + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(from, p); + decode(realms, p); + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(from, payload); + encode(realms, payload); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +WRITE_CLASS_ENCODER(MCacheExpire::realm) + +#endif diff --git a/src/messages/MClientCapRelease.h b/src/messages/MClientCapRelease.h new file mode 100644 index 000000000..1524dd25c --- /dev/null +++ b/src/messages/MClientCapRelease.h @@ -0,0 +1,67 @@ +// -*- 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_MCLIENTCAPRELEASE_H +#define CEPH_MCLIENTCAPRELEASE_H + +#include "msg/Message.h" + + +class MClientCapRelease final : public SafeMessage { + public: + std::string_view get_type_name() const override { return "client_cap_release";} + void print(std::ostream& out) const override { + out << "client_cap_release(" << caps.size() << ")"; + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(head, p); + ceph::decode_nohead(head.num, caps, p); + if (header.version >= 2) { + decode(osd_epoch_barrier, p); + } + } + void encode_payload(uint64_t features) override { + using ceph::encode; + head.num = caps.size(); + encode(head, payload); + ceph::encode_nohead(caps, payload); + encode(osd_epoch_barrier, payload); + } + + struct ceph_mds_cap_release head; + std::vector<ceph_mds_cap_item> caps; + + // The message receiver must wait for this OSD epoch + // before actioning this cap release. + epoch_t osd_epoch_barrier = 0; + +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); + + static constexpr int HEAD_VERSION = 2; + static constexpr int COMPAT_VERSION = 1; + + MClientCapRelease() : + SafeMessage{CEPH_MSG_CLIENT_CAPRELEASE, HEAD_VERSION, COMPAT_VERSION} + { + memset(&head, 0, sizeof(head)); + } + ~MClientCapRelease() final {} +}; + +#endif diff --git a/src/messages/MClientCaps.h b/src/messages/MClientCaps.h new file mode 100644 index 000000000..d1a4817be --- /dev/null +++ b/src/messages/MClientCaps.h @@ -0,0 +1,349 @@ +// -*- 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_MCLIENTCAPS_H +#define CEPH_MCLIENTCAPS_H + +#include "msg/Message.h" +#include "mds/mdstypes.h" +#include "include/ceph_features.h" + +class MClientCaps final : public SafeMessage { +private: + + static constexpr int HEAD_VERSION = 11; + static constexpr int COMPAT_VERSION = 1; + + public: + static constexpr unsigned FLAG_SYNC = (1<<0); + static constexpr unsigned FLAG_NO_CAPSNAP = (1<<1); // unused + static constexpr unsigned FLAG_PENDING_CAPSNAP = (1<<2); + + struct ceph_mds_caps_head head; + + uint64_t size = 0; + uint64_t max_size = 0; + uint64_t truncate_size = 0; + uint64_t change_attr = 0; + uint32_t truncate_seq = 0; + utime_t mtime, atime, ctime, btime; + uint32_t time_warp_seq = 0; + int64_t nfiles = -1; // files in dir + int64_t nsubdirs = -1; // subdirs in dir + + struct ceph_mds_cap_peer peer; + + ceph::buffer::list snapbl; + ceph::buffer::list xattrbl; + ceph::buffer::list flockbl; + version_t inline_version = 0; + ceph::buffer::list inline_data; + + // Receivers may not use their new caps until they have this OSD map + epoch_t osd_epoch_barrier = 0; + ceph_tid_t oldest_flush_tid = 0; + uint32_t caller_uid = 0; + uint32_t caller_gid = 0; + + /* advisory CLIENT_CAPS_* flags to send to mds */ + unsigned flags = 0; + + int get_caps() const { return head.caps; } + int get_wanted() const { return head.wanted; } + int get_dirty() const { return head.dirty; } + ceph_seq_t get_seq() const { return head.seq; } + ceph_seq_t get_issue_seq() const { return head.issue_seq; } + ceph_seq_t get_mseq() const { return head.migrate_seq; } + + inodeno_t get_ino() const { return inodeno_t(head.ino); } + inodeno_t get_realm() const { return inodeno_t(head.realm); } + uint64_t get_cap_id() const { return head.cap_id; } + + uint64_t get_size() const { return size; } + uint64_t get_max_size() const { return max_size; } + __u32 get_truncate_seq() const { return truncate_seq; } + uint64_t get_truncate_size() const { return truncate_size; } + utime_t get_ctime() const { return ctime; } + utime_t get_btime() const { return btime; } + utime_t get_mtime() const { return mtime; } + utime_t get_atime() const { return atime; } + __u64 get_change_attr() const { return change_attr; } + __u32 get_time_warp_seq() const { return time_warp_seq; } + uint64_t get_nfiles() const { return nfiles; } + uint64_t get_nsubdirs() const { return nsubdirs; } + bool dirstat_is_valid() const { return nfiles != -1 || nsubdirs != -1; } + + const file_layout_t& get_layout() const { + return layout; + } + + void set_layout(const file_layout_t &l) { + layout = l; + } + + int get_migrate_seq() const { return head.migrate_seq; } + int get_op() const { return head.op; } + + uint64_t get_client_tid() const { return get_tid(); } + void set_client_tid(uint64_t s) { set_tid(s); } + + snapid_t get_snap_follows() const { return snapid_t(head.snap_follows); } + void set_snap_follows(snapid_t s) { head.snap_follows = s; } + + void set_caps(int c) { head.caps = c; } + void set_wanted(int w) { head.wanted = w; } + + void set_max_size(uint64_t ms) { max_size = ms; } + + void set_migrate_seq(unsigned m) { head.migrate_seq = m; } + void set_op(int o) { head.op = o; } + + void set_size(loff_t s) { size = s; } + void set_mtime(const utime_t &t) { mtime = t; } + void set_ctime(const utime_t &t) { ctime = t; } + void set_atime(const utime_t &t) { atime = t; } + + void set_cap_peer(uint64_t id, ceph_seq_t seq, ceph_seq_t mseq, int mds, int flags) { + peer.cap_id = id; + peer.seq = seq; + peer.mseq = mseq; + peer.mds = mds; + peer.flags = flags; + } + + void set_oldest_flush_tid(ceph_tid_t tid) { oldest_flush_tid = tid; } + ceph_tid_t get_oldest_flush_tid() const { return oldest_flush_tid; } + + void clear_dirty() { head.dirty = 0; } + +protected: + MClientCaps() + : SafeMessage{CEPH_MSG_CLIENT_CAPS, HEAD_VERSION, COMPAT_VERSION} {} + MClientCaps(int op, + inodeno_t ino, + inodeno_t realm, + uint64_t id, + long seq, + int caps, + int wanted, + int dirty, + int mseq, + epoch_t oeb) + : SafeMessage{CEPH_MSG_CLIENT_CAPS, HEAD_VERSION, COMPAT_VERSION}, + osd_epoch_barrier(oeb) { + memset(&head, 0, sizeof(head)); + head.op = op; + head.ino = ino; + head.realm = realm; + head.cap_id = id; + head.seq = seq; + head.caps = caps; + head.wanted = wanted; + head.dirty = dirty; + head.migrate_seq = mseq; + memset(&peer, 0, sizeof(peer)); + } + MClientCaps(int op, + inodeno_t ino, inodeno_t realm, + uint64_t id, int mseq, epoch_t oeb) + : SafeMessage{CEPH_MSG_CLIENT_CAPS, HEAD_VERSION, COMPAT_VERSION}, + osd_epoch_barrier(oeb) { + memset(&head, 0, sizeof(head)); + head.op = op; + head.ino = ino; + head.realm = realm; + head.cap_id = id; + head.migrate_seq = mseq; + memset(&peer, 0, sizeof(peer)); + } + ~MClientCaps() final {} + +private: + file_layout_t layout; + +public: + std::string_view get_type_name() const override { return "Cfcap";} + void print(std::ostream& out) const override { + out << "client_caps(" << ceph_cap_op_name(head.op) + << " ino " << inodeno_t(head.ino) + << " " << head.cap_id + << " seq " << head.seq; + if (get_tid()) + out << " tid " << get_tid(); + out << " caps=" << ccap_string(head.caps) + << " dirty=" << ccap_string(head.dirty) + << " wanted=" << ccap_string(head.wanted); + out << " follows " << snapid_t(head.snap_follows); + if (head.migrate_seq) + out << " mseq " << head.migrate_seq; + + out << " size " << size << "/" << max_size; + if (truncate_seq) + out << " ts " << truncate_seq << "/" << truncate_size; + out << " mtime " << mtime + << " ctime " << ctime + << " change_attr " << change_attr; + if (time_warp_seq) + out << " tws " << time_warp_seq; + + if (head.xattr_version) + out << " xattrs(v=" << head.xattr_version << " l=" << xattrbl.length() << ")"; + + out << ")"; + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(head, p); + if (head.op == CEPH_CAP_OP_EXPORT) { + ceph_mds_caps_export_body body; + decode(body, p); + peer = body.peer; + p += (sizeof(ceph_mds_caps_non_export_body) - + sizeof(ceph_mds_caps_export_body)); + } else { + ceph_mds_caps_non_export_body body; + decode(body, p); + size = body.size; + max_size = body.max_size; + truncate_size = body.truncate_size; + truncate_seq = body.truncate_seq; + mtime = utime_t(body.mtime); + atime = utime_t(body.atime); + ctime = utime_t(body.ctime); + layout.from_legacy(body.layout); + time_warp_seq = body.time_warp_seq; + } + ceph::decode_nohead(head.snap_trace_len, snapbl, p); + + ceph_assert(middle.length() == head.xattr_len); + if (head.xattr_len) + xattrbl = middle; + + // conditionally decode flock metadata + if (header.version >= 2) + decode(flockbl, p); + + if (header.version >= 3) { + if (head.op == CEPH_CAP_OP_IMPORT) + decode(peer, p); + } + + if (header.version >= 4) { + decode(inline_version, p); + decode(inline_data, p); + } else { + inline_version = CEPH_INLINE_NONE; + } + + if (header.version >= 5) { + decode(osd_epoch_barrier, p); + } + if (header.version >= 6) { + decode(oldest_flush_tid, p); + } + if (header.version >= 7) { + decode(caller_uid, p); + decode(caller_gid, p); + } + if (header.version >= 8) { + decode(layout.pool_ns, p); + } + if (header.version >= 9) { + decode(btime, p); + decode(change_attr, p); + } + if (header.version >= 10) { + decode(flags, p); + } + if (header.version >= 11) { + decode(nfiles, p); + decode(nsubdirs, p); + } + } + void encode_payload(uint64_t features) override { + using ceph::encode; + header.version = HEAD_VERSION; + head.snap_trace_len = snapbl.length(); + head.xattr_len = xattrbl.length(); + + encode(head, payload); + static_assert(sizeof(ceph_mds_caps_non_export_body) > + sizeof(ceph_mds_caps_export_body)); + if (head.op == CEPH_CAP_OP_EXPORT) { + ceph_mds_caps_export_body body; + body.peer = peer; + encode(body, payload); + payload.append_zero(sizeof(ceph_mds_caps_non_export_body) - + sizeof(ceph_mds_caps_export_body)); + } else { + ceph_mds_caps_non_export_body body; + body.size = size; + body.max_size = max_size; + body.truncate_size = truncate_size; + body.truncate_seq = truncate_seq; + mtime.encode_timeval(&body.mtime); + atime.encode_timeval(&body.atime); + ctime.encode_timeval(&body.ctime); + layout.to_legacy(&body.layout); + body.time_warp_seq = time_warp_seq; + encode(body, payload); + } + ceph::encode_nohead(snapbl, payload); + + middle = xattrbl; + + // conditionally include flock metadata + if (features & CEPH_FEATURE_FLOCK) { + encode(flockbl, payload); + } else { + header.version = 1; + return; + } + + if (features & CEPH_FEATURE_EXPORT_PEER) { + if (head.op == CEPH_CAP_OP_IMPORT) + encode(peer, payload); + } else { + header.version = 2; + return; + } + + if (features & CEPH_FEATURE_MDS_INLINE_DATA) { + encode(inline_version, payload); + encode(inline_data, payload); + } else { + encode(inline_version, payload); + encode(ceph::buffer::list(), payload); + } + + encode(osd_epoch_barrier, payload); + encode(oldest_flush_tid, payload); + encode(caller_uid, payload); + encode(caller_gid, payload); + + encode(layout.pool_ns, payload); + encode(btime, payload); + encode(change_attr, payload); + encode(flags, payload); + encode(nfiles, payload); + encode(nsubdirs, payload); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MClientLease.h b/src/messages/MClientLease.h new file mode 100644 index 000000000..cad0f3f21 --- /dev/null +++ b/src/messages/MClientLease.h @@ -0,0 +1,95 @@ +// -*- 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_MCLIENTLEASE_H +#define CEPH_MCLIENTLEASE_H + +#include <string_view> + +#include "msg/Message.h" + +class MClientLease final : public SafeMessage { +public: + struct ceph_mds_lease h; + std::string dname; + + int get_action() const { return h.action; } + ceph_seq_t get_seq() const { return h.seq; } + int get_mask() const { return h.mask; } + inodeno_t get_ino() const { return inodeno_t(h.ino); } + snapid_t get_first() const { return snapid_t(h.first); } + snapid_t get_last() const { return snapid_t(h.last); } + +protected: + MClientLease() : SafeMessage(CEPH_MSG_CLIENT_LEASE) {} + MClientLease(const MClientLease& m) : + SafeMessage(CEPH_MSG_CLIENT_LEASE), + h(m.h), + dname(m.dname) {} + MClientLease(int ac, ceph_seq_t seq, int m, uint64_t i, uint64_t sf, uint64_t sl) : + SafeMessage(CEPH_MSG_CLIENT_LEASE) { + h.action = ac; + h.seq = seq; + h.mask = m; + h.ino = i; + h.first = sf; + h.last = sl; + h.duration_ms = 0; + } + MClientLease(int ac, ceph_seq_t seq, int m, uint64_t i, uint64_t sf, uint64_t sl, std::string_view d) : + SafeMessage(CEPH_MSG_CLIENT_LEASE), + dname(d) { + h.action = ac; + h.seq = seq; + h.mask = m; + h.ino = i; + h.first = sf; + h.last = sl; + h.duration_ms = 0; + } + ~MClientLease() final {} + +public: + std::string_view get_type_name() const override { return "client_lease"; } + void print(std::ostream& out) const override { + out << "client_lease(a=" << ceph_lease_op_name(get_action()) + << " seq " << get_seq() + << " mask " << get_mask(); + out << " " << get_ino(); + if (h.last != CEPH_NOSNAP) + out << " [" << snapid_t(h.first) << "," << snapid_t(h.last) << "]"; + if (dname.length()) + out << "/" << dname; + out << ")"; + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(h, p); + decode(dname, p); + } + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(h, payload); + encode(dname, payload); + } + +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MClientMetrics.h b/src/messages/MClientMetrics.h new file mode 100644 index 000000000..5e4234c69 --- /dev/null +++ b/src/messages/MClientMetrics.h @@ -0,0 +1,54 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef CEPH_MDS_CLIENT_METRICS_H +#define CEPH_MDS_CLIENT_METRICS_H + +#include <vector> + +#include "msg/Message.h" +#include "include/cephfs/metrics/Types.h" + +class MClientMetrics final : public SafeMessage { +private: + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; +public: + std::vector<ClientMetricMessage> updates; + +protected: + MClientMetrics() : MClientMetrics(std::vector<ClientMetricMessage>{}) { } + MClientMetrics(std::vector<ClientMetricMessage> updates) + : SafeMessage(CEPH_MSG_CLIENT_METRICS, HEAD_VERSION, COMPAT_VERSION), updates(updates) { + } + ~MClientMetrics() final {} + +public: + std::string_view get_type_name() const override { + return "client_metrics"; + } + + void print(ostream &out) const override { + out << "client_metrics "; + for (auto &i : updates) { + i.print(&out); + } + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(updates, payload); + } + + void decode_payload() override { + using ceph::decode; + auto iter = payload.cbegin(); + decode(updates, iter); + } + +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif // CEPH_MDS_CLIENT_METRICS_H diff --git a/src/messages/MClientQuota.h b/src/messages/MClientQuota.h new file mode 100644 index 000000000..4dad9f1d0 --- /dev/null +++ b/src/messages/MClientQuota.h @@ -0,0 +1,54 @@ +#ifndef CEPH_MCLIENTQUOTA_H +#define CEPH_MCLIENTQUOTA_H + +#include "msg/Message.h" + +class MClientQuota final : public SafeMessage { +public: + inodeno_t ino; + nest_info_t rstat; + quota_info_t quota; + +protected: + MClientQuota() : + SafeMessage{CEPH_MSG_CLIENT_QUOTA}, + ino(0) + {} + ~MClientQuota() final {} + +public: + std::string_view get_type_name() const override { return "client_quota"; } + void print(std::ostream& out) const override { + out << "client_quota("; + out << " [" << ino << "] "; + out << rstat << " "; + out << quota; + out << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(ino, payload); + encode(rstat.rctime, payload); + encode(rstat.rbytes, payload); + encode(rstat.rfiles, payload); + encode(rstat.rsubdirs, payload); + encode(quota, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(ino, p); + decode(rstat.rctime, p); + decode(rstat.rbytes, p); + decode(rstat.rfiles, p); + decode(rstat.rsubdirs, p); + decode(quota, p); + ceph_assert(p.end()); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MClientReclaim.h b/src/messages/MClientReclaim.h new file mode 100644 index 000000000..f3f0ff09e --- /dev/null +++ b/src/messages/MClientReclaim.h @@ -0,0 +1,66 @@ +// -*- 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 final : public SafeMessage { +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; } + + std::string_view get_type_name() const override { return "client_reclaim"; } + void print(std::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: + MClientReclaim() : + SafeMessage{CEPH_MSG_CLIENT_RECLAIM, HEAD_VERSION, COMPAT_VERSION} {} + MClientReclaim(std::string_view _uuid, uint32_t _flags) : + SafeMessage{CEPH_MSG_CLIENT_RECLAIM, HEAD_VERSION, COMPAT_VERSION}, + uuid(_uuid), flags(_flags) {} +private: + ~MClientReclaim() final {} + + std::string uuid; + uint32_t flags = 0; + + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MClientReclaimReply.h b/src/messages/MClientReclaimReply.h new file mode 100644 index 000000000..354906cd4 --- /dev/null +++ b/src/messages/MClientReclaimReply.h @@ -0,0 +1,72 @@ +// -*- 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 final : public SafeMessage { +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; } + + std::string_view get_type_name() const override { return "client_reclaim_reply"; } + void print(std::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: + MClientReclaimReply() : + MClientReclaimReply{0, 0} + {} + MClientReclaimReply(int r, epoch_t e=0) : + SafeMessage{CEPH_MSG_CLIENT_RECLAIM_REPLY, HEAD_VERSION, COMPAT_VERSION}, + result(r), epoch(e) {} + +private: + ~MClientReclaimReply() final {} + + int32_t result; + epoch_t epoch; + entity_addrvec_t addrs; + + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MClientReconnect.h b/src/messages/MClientReconnect.h new file mode 100644 index 000000000..43c5a4076 --- /dev/null +++ b/src/messages/MClientReconnect.h @@ -0,0 +1,176 @@ +// -*- 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_MCLIENTRECONNECT_H +#define CEPH_MCLIENTRECONNECT_H + +#include "msg/Message.h" +#include "mds/mdstypes.h" +#include "include/ceph_features.h" + + +class MClientReconnect final : public SafeMessage { +private: + static constexpr int HEAD_VERSION = 5; + static constexpr int COMPAT_VERSION = 4; + +public: + std::map<inodeno_t, cap_reconnect_t> caps; // only head inodes + std::vector<snaprealm_reconnect_t> realms; + bool more = false; + +private: + MClientReconnect() : + SafeMessage{CEPH_MSG_CLIENT_RECONNECT, HEAD_VERSION, COMPAT_VERSION} {} + ~MClientReconnect() final {} + + size_t cap_size = 0; + size_t realm_size = 0; + size_t approx_size = sizeof(__u32) + sizeof(__u32) + 1; + + void calc_item_size() { + using ceph::encode; + { + ceph::buffer::list bl; + inodeno_t ino; + cap_reconnect_t cr; + encode(ino, bl); + encode(cr, bl); + cap_size = bl.length(); + } + { + ceph::buffer::list bl; + snaprealm_reconnect_t sr; + encode(sr, bl); + realm_size = bl.length(); + } + } + +public: + std::string_view get_type_name() const override { return "client_reconnect"; } + void print(std::ostream& out) const override { + out << "client_reconnect(" + << caps.size() << " caps " << realms.size() << " realms )"; + } + + // Force to use old encoding. + // Use connection's features to choose encoding if version is set to 0. + void set_encoding_version(int v) { + header.version = v; + if (v <= 3) + header.compat_version = 0; + } + size_t get_approx_size() { + return approx_size; + } + void mark_more() { more = true; } + bool has_more() const { return more; } + + void add_cap(inodeno_t ino, uint64_t cap_id, inodeno_t pathbase, const std::string& path, + int wanted, int issued, inodeno_t sr, snapid_t sf, ceph::buffer::list& lb) + { + caps[ino] = cap_reconnect_t(cap_id, pathbase, path, wanted, issued, sr, sf, lb); + if (!cap_size) + calc_item_size(); + approx_size += cap_size + path.length() + lb.length(); + } + void add_snaprealm(inodeno_t ino, snapid_t seq, inodeno_t parent) { + snaprealm_reconnect_t r; + r.realm.ino = ino; + r.realm.seq = seq; + r.realm.parent = parent; + realms.push_back(r); + if (!realm_size) + calc_item_size(); + approx_size += realm_size; + } + + void encode_payload(uint64_t features) override { + if (header.version == 0) { + if (features & CEPH_FEATURE_MDSENC) + header.version = 3; + else if (features & CEPH_FEATURE_FLOCK) + header.version = 2; + else + header.version = 1; + } + + using ceph::encode; + data.clear(); + + if (header.version >= 4) { + encode(caps, data); + encode(realms, data); + encode(more, data); + } else { + // compat crap + if (header.version == 3) { + encode(caps, data); + } else if (header.version == 2) { + __u32 n = caps.size(); + encode(n, data); + for (auto& p : caps) { + encode(p.first, data); + p.second.encode_old(data); + } + } else { + std::map<inodeno_t, old_cap_reconnect_t> ocaps; + for (auto& p : caps) { + ocaps[p.first] = p.second; + encode(ocaps, data); + } + for (auto& r : realms) + r.encode_old(data); + } + } + } + void decode_payload() override { + using ceph::decode; + auto p = data.cbegin(); + if (header.version >= 4) { + decode(caps, p); + decode(realms, p); + if (header.version >= 5) + decode(more, p); + } else { + // compat crap + if (header.version == 3) { + decode(caps, p); + } else if (header.version == 2) { + __u32 n; + decode(n, p); + inodeno_t ino; + while (n--) { + decode(ino, p); + caps[ino].decode_old(p); + } + } else { + std::map<inodeno_t, old_cap_reconnect_t> ocaps; + decode(ocaps, p); + for (auto &q : ocaps) + caps[q.first] = q.second; + } + while (!p.end()) { + realms.push_back(snaprealm_reconnect_t()); + realms.back().decode_old(p); + } + } + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + + +#endif diff --git a/src/messages/MClientReply.h b/src/messages/MClientReply.h new file mode 100644 index 000000000..bd58e0883 --- /dev/null +++ b/src/messages/MClientReply.h @@ -0,0 +1,405 @@ +// -*- 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_MCLIENTREPLY_H +#define CEPH_MCLIENTREPLY_H + +#include "include/types.h" +#include "include/fs_types.h" +#include "include/mempool.h" +#include "MClientRequest.h" + +#include "msg/Message.h" +#include "include/ceph_features.h" +#include "common/errno.h" +#include "common/strescape.h" + +/*** + * + * MClientReply - container message for MDS reply to a client's MClientRequest + * + * key fields: + * long tid - transaction id, so the client can match up with pending request + * int result - error code, or fh if it was open + * + * for most requests: + * trace is a vector of InodeStat's tracing from root to the file/dir/whatever + * the operation referred to, so that the client can update it's info about what + * metadata lives on what MDS. + * + * for readdir replies: + * dir_contents is a vector of InodeStat*'s. + * + * that's mostly it, i think! + * + */ + + +struct LeaseStat { + // this matches ceph_mds_reply_lease + __u16 mask = 0; + __u32 duration_ms = 0; + __u32 seq = 0; + std::string alternate_name; + + LeaseStat() = default; + LeaseStat(__u16 msk, __u32 dur, __u32 sq) : mask{msk}, duration_ms{dur}, seq{sq} {} + + void decode(ceph::buffer::list::const_iterator &bl, const uint64_t features) { + using ceph::decode; + if (features == (uint64_t)-1) { + DECODE_START(2, bl); + decode(mask, bl); + decode(duration_ms, bl); + decode(seq, bl); + if (struct_v >= 2) + decode(alternate_name, bl); + DECODE_FINISH(bl); + } + else { + decode(mask, bl); + decode(duration_ms, bl); + decode(seq, bl); + } + } +}; + +inline std::ostream& operator<<(std::ostream& out, const LeaseStat& l) { + out << "lease(mask " << l.mask << " dur " << l.duration_ms; + if (l.alternate_name.size()) { + out << " altn " << binstrprint(l.alternate_name, 128) << ")"; + } + return out << ")"; +} + +struct DirStat { + // mds distribution hints + frag_t frag; + __s32 auth; + std::set<__s32> dist; + + DirStat() : auth(CDIR_AUTH_PARENT) {} + DirStat(ceph::buffer::list::const_iterator& p, const uint64_t features) { + decode(p, features); + } + + void decode(ceph::buffer::list::const_iterator& p, const uint64_t features) { + using ceph::decode; + if (features == (uint64_t)-1) { + DECODE_START(1, p); + decode(frag, p); + decode(auth, p); + decode(dist, p); + DECODE_FINISH(p); + } + else { + decode(frag, p); + decode(auth, p); + decode(dist, p); + } + } + + // see CDir::encode_dirstat for encoder. +}; + +struct InodeStat { + vinodeno_t vino; + uint32_t rdev = 0; + version_t version = 0; + version_t xattr_version = 0; + ceph_mds_reply_cap cap; + file_layout_t layout; + utime_t ctime, btime, mtime, atime, snap_btime; + uint32_t time_warp_seq = 0; + uint64_t size = 0, max_size = 0; + uint64_t change_attr = 0; + uint64_t truncate_size = 0; + uint32_t truncate_seq = 0; + uint32_t mode = 0, uid = 0, gid = 0, nlink = 0; + frag_info_t dirstat; + nest_info_t rstat; + + fragtree_t dirfragtree; + std::string symlink; // symlink content (if symlink) + + ceph_dir_layout dir_layout; + + ceph::buffer::list xattrbl; + + ceph::buffer::list inline_data; + version_t inline_version; + + quota_info_t quota; + + mds_rank_t dir_pin; + std::map<std::string,std::string> snap_metadata; + + bool fscrypt = false; // fscrypt enabled ? + + public: + InodeStat() {} + InodeStat(ceph::buffer::list::const_iterator& p, const uint64_t features) { + decode(p, features); + } + + void decode(ceph::buffer::list::const_iterator &p, const uint64_t features) { + using ceph::decode; + if (features == (uint64_t)-1) { + DECODE_START(6, p); + decode(vino.ino, p); + decode(vino.snapid, p); + decode(rdev, p); + decode(version, p); + decode(xattr_version, p); + decode(cap, p); + { + ceph_file_layout legacy_layout; + decode(legacy_layout, p); + layout.from_legacy(legacy_layout); + } + decode(ctime, p); + decode(mtime, p); + decode(atime, p); + decode(time_warp_seq, p); + decode(size, p); + decode(max_size, p); + decode(truncate_size, p); + decode(truncate_seq, p); + decode(mode, p); + decode(uid, p); + decode(gid, p); + decode(nlink, p); + decode(dirstat.nfiles, p); + decode(dirstat.nsubdirs, p); + decode(rstat.rbytes, p); + decode(rstat.rfiles, p); + decode(rstat.rsubdirs, p); + decode(rstat.rctime, p); + decode(dirfragtree, p); + decode(symlink, p); + decode(dir_layout, p); + decode(xattrbl, p); + decode(inline_version, p); + decode(inline_data, p); + decode(quota, p); + decode(layout.pool_ns, p); + decode(btime, p); + decode(change_attr, p); + if (struct_v > 1) { + decode(dir_pin, p); + } else { + dir_pin = -ENODATA; + } + if (struct_v >= 3) { + decode(snap_btime, p); + } // else remains zero + if (struct_v >= 4) { + decode(rstat.rsnaps, p); + } // else remains zero + if (struct_v >= 5) { + decode(snap_metadata, p); + } + if (struct_v >= 6) { + decode(fscrypt, p); + } + DECODE_FINISH(p); + } + else { + decode(vino.ino, p); + decode(vino.snapid, p); + decode(rdev, p); + decode(version, p); + decode(xattr_version, p); + decode(cap, p); + { + ceph_file_layout legacy_layout; + decode(legacy_layout, p); + layout.from_legacy(legacy_layout); + } + decode(ctime, p); + decode(mtime, p); + decode(atime, p); + decode(time_warp_seq, p); + decode(size, p); + decode(max_size, p); + decode(truncate_size, p); + decode(truncate_seq, p); + decode(mode, p); + decode(uid, p); + decode(gid, p); + decode(nlink, p); + decode(dirstat.nfiles, p); + decode(dirstat.nsubdirs, p); + decode(rstat.rbytes, p); + decode(rstat.rfiles, p); + decode(rstat.rsubdirs, p); + decode(rstat.rctime, p); + decode(dirfragtree, p); + decode(symlink, p); + if (features & CEPH_FEATURE_DIRLAYOUTHASH) + decode(dir_layout, p); + else + memset(&dir_layout, 0, sizeof(dir_layout)); + + decode(xattrbl, p); + + if (features & CEPH_FEATURE_MDS_INLINE_DATA) { + decode(inline_version, p); + decode(inline_data, p); + } else { + inline_version = CEPH_INLINE_NONE; + } + + if (features & CEPH_FEATURE_MDS_QUOTA) + decode(quota, p); + else + quota = quota_info_t{}; + + if ((features & CEPH_FEATURE_FS_FILE_LAYOUT_V2)) + decode(layout.pool_ns, p); + + if ((features & CEPH_FEATURE_FS_BTIME)) { + decode(btime, p); + decode(change_attr, p); + } else { + btime = utime_t(); + change_attr = 0; + } + } + } + + // see CInode::encode_inodestat for encoder. +}; + +struct openc_response_t { + _inodeno_t created_ino; + interval_set<inodeno_t> delegated_inos; + +public: + void encode(ceph::buffer::list& bl) const { + using ceph::encode; + ENCODE_START(1, 1, bl); + encode(created_ino, bl); + encode(delegated_inos, bl); + ENCODE_FINISH(bl); + } + void decode(ceph::buffer::list::const_iterator &p) { + using ceph::decode; + DECODE_START(1, p); + decode(created_ino, p); + decode(delegated_inos, p); + DECODE_FINISH(p); + } +} __attribute__ ((__may_alias__)); +WRITE_CLASS_ENCODER(openc_response_t) + +class MClientReply final : public SafeMessage { +public: + // reply data + struct ceph_mds_reply_head head {}; + ceph::buffer::list trace_bl; + ceph::buffer::list extra_bl; + ceph::buffer::list snapbl; + + int get_op() const { return head.op; } + + void set_mdsmap_epoch(epoch_t e) { head.mdsmap_epoch = e; } + epoch_t get_mdsmap_epoch() const { return head.mdsmap_epoch; } + + int get_result() const { + return ceph_to_hostos_errno((__s32)(__u32)head.result); + } + + void set_result(int r) { head.result = r; } + + void set_unsafe() { head.safe = 0; } + + bool is_safe() const { return head.safe; } + +protected: + MClientReply() : SafeMessage{CEPH_MSG_CLIENT_REPLY} {} + MClientReply(const MClientRequest &req, int result = 0) : + SafeMessage{CEPH_MSG_CLIENT_REPLY} { + memset(&head, 0, sizeof(head)); + header.tid = req.get_tid(); + head.op = req.get_op(); + head.result = result; + head.safe = 1; + } + ~MClientReply() final {} + +public: + std::string_view get_type_name() const override { return "creply"; } + void print(std::ostream& o) const override { + o << "client_reply(???:" << get_tid(); + o << " = " << get_result(); + if (get_result() <= 0) { + o << " " << cpp_strerror(get_result()); + } + if (head.op & CEPH_MDS_OP_WRITE) { + if (head.safe) + o << " safe"; + else + o << " unsafe"; + } + o << ")"; + } + + // serialization + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(head, p); + decode(trace_bl, p); + decode(extra_bl, p); + decode(snapbl, p); + ceph_assert(p.end()); + } + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(head, payload); + encode(trace_bl, payload); + encode(extra_bl, payload); + encode(snapbl, payload); + } + + + // dir contents + void set_extra_bl(ceph::buffer::list& bl) { + extra_bl = std::move(bl); + } + ceph::buffer::list& get_extra_bl() { + return extra_bl; + } + const ceph::buffer::list& get_extra_bl() const { + return extra_bl; + } + + // trace + void set_trace(ceph::buffer::list& bl) { + trace_bl = std::move(bl); + } + ceph::buffer::list& get_trace_bl() { + return trace_bl; + } + const ceph::buffer::list& get_trace_bl() const { + return trace_bl; + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MClientRequest.h b/src/messages/MClientRequest.h new file mode 100644 index 000000000..c51f1149e --- /dev/null +++ b/src/messages/MClientRequest.h @@ -0,0 +1,329 @@ +// -*- 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_MCLIENTREQUEST_H +#define CEPH_MCLIENTREQUEST_H + +/** + * + * MClientRequest - container for a client METADATA request. created/sent by clients. + * can be forwarded around between MDS's. + * + * int client - the originating client + * long tid - transaction id, unique among requests for that client. probably just a counter! + * -> the MDS passes the Request to the Reply constructor, so this always matches. + * + * int op - the metadata op code. MDS_OP_RENAME, etc. + * int caller_uid, _gid - guess + * + * fixed size arguments are in a union. + * there's also a string argument, for e.g. symlink(). + * + */ + +#include <string_view> + +#include "include/filepath.h" +#include "mds/mdstypes.h" +#include "include/ceph_features.h" +#include "messages/MMDSOp.h" + +#include <sys/types.h> +#include <utime.h> +#include <sys/stat.h> +#include <fcntl.h> + +struct SnapPayload { + std::map<std::string, std::string> metadata; + + void encode(ceph::buffer::list &bl) const { + ENCODE_START(1, 1, bl); + encode(metadata, bl); + ENCODE_FINISH(bl); + } + + void decode(ceph::buffer::list::const_iterator &iter) { + DECODE_START(1, iter); + decode(metadata, iter); + DECODE_FINISH(iter); + } +}; + +WRITE_CLASS_ENCODER(SnapPayload) + +// metadata ops. + +class MClientRequest final : public MMDSOp { +private: + static constexpr int HEAD_VERSION = 5; + static constexpr int COMPAT_VERSION = 1; + +public: + mutable struct ceph_mds_request_head head; /* XXX HACK! */ + utime_t stamp; + + struct Release { + mutable ceph_mds_request_release item; + std::string dname; + + Release() : item(), dname() {} + Release(const ceph_mds_request_release& rel, std::string name) : + item(rel), dname(name) {} + + void encode(ceph::buffer::list& bl) const { + using ceph::encode; + item.dname_len = dname.length(); + encode(item, bl); + ceph::encode_nohead(dname, bl); + } + void decode(ceph::buffer::list::const_iterator& bl) { + using ceph::decode; + decode(item, bl); + ceph::decode_nohead(item.dname_len, dname, bl); + } + }; + mutable std::vector<Release> releases; /* XXX HACK! */ + + // path arguments + filepath path, path2; + std::string alternate_name; + std::vector<uint64_t> gid_list; + + /* XXX HACK */ + mutable bool queued_for_replay = false; + +protected: + // cons + MClientRequest() + : MMDSOp(CEPH_MSG_CLIENT_REQUEST, HEAD_VERSION, COMPAT_VERSION) {} + MClientRequest(int op) + : MMDSOp(CEPH_MSG_CLIENT_REQUEST, HEAD_VERSION, COMPAT_VERSION) { + memset(&head, 0, sizeof(head)); + head.op = op; + } + ~MClientRequest() final {} + +public: + void set_mdsmap_epoch(epoch_t e) { head.mdsmap_epoch = e; } + epoch_t get_mdsmap_epoch() const { return head.mdsmap_epoch; } + epoch_t get_osdmap_epoch() const { + ceph_assert(head.op == CEPH_MDS_OP_SETXATTR); + if (header.version >= 3) + return head.args.setxattr.osdmap_epoch; + else + return 0; + } + void set_osdmap_epoch(epoch_t e) { + ceph_assert(head.op == CEPH_MDS_OP_SETXATTR); + head.args.setxattr.osdmap_epoch = e; + } + + metareqid_t get_reqid() const { + // FIXME: for now, assume clients always have 1 incarnation + return metareqid_t(get_orig_source(), header.tid); + } + + /*bool open_file_mode_is_readonly() { + return file_mode_is_readonly(ceph_flags_to_mode(head.args.open.flags)); + }*/ + bool may_write() const { + return + (head.op & CEPH_MDS_OP_WRITE) || + (head.op == CEPH_MDS_OP_OPEN && (head.args.open.flags & (O_CREAT|O_TRUNC))); + } + + int get_flags() const { + return head.flags; + } + bool is_replay() const { + return get_flags() & CEPH_MDS_FLAG_REPLAY; + } + bool is_async() const { + return get_flags() & CEPH_MDS_FLAG_ASYNC; + } + + // normal fields + void set_stamp(utime_t t) { stamp = t; } + void set_oldest_client_tid(ceph_tid_t t) { head.oldest_client_tid = t; } + void inc_num_fwd() { head.num_fwd = head.num_fwd + 1; } + void set_retry_attempt(int a) { head.num_retry = a; } + void set_filepath(const filepath& fp) { path = fp; } + void set_filepath2(const filepath& fp) { path2 = fp; } + void set_string2(const char *s) { path2.set_path(std::string_view(s), 0); } + void set_caller_uid(unsigned u) { head.caller_uid = u; } + void set_caller_gid(unsigned g) { head.caller_gid = g; } + void set_gid_list(int count, const gid_t *gids) { + gid_list.reserve(count); + for (int i = 0; i < count; ++i) { + gid_list.push_back(gids[i]); + } + } + void set_dentry_wanted() { + head.flags = head.flags | CEPH_MDS_FLAG_WANT_DENTRY; + } + void set_replayed_op() { + head.flags = head.flags | CEPH_MDS_FLAG_REPLAY; + } + void set_async_op() { + head.flags = head.flags | CEPH_MDS_FLAG_ASYNC; + } + + void set_alternate_name(std::string _alternate_name) { + alternate_name = std::move(_alternate_name); + } + void set_alternate_name(bufferptr&& cipher) { + alternate_name = std::move(cipher.c_str()); + } + + utime_t get_stamp() const { return stamp; } + ceph_tid_t get_oldest_client_tid() const { return head.oldest_client_tid; } + int get_num_fwd() const { return head.num_fwd; } + int get_retry_attempt() const { return head.num_retry; } + int get_op() const { return head.op; } + unsigned get_caller_uid() const { return head.caller_uid; } + unsigned get_caller_gid() const { return head.caller_gid; } + const std::vector<uint64_t>& get_caller_gid_list() const { return gid_list; } + + const std::string& get_path() const { return path.get_path(); } + const filepath& get_filepath() const { return path; } + const std::string& get_path2() const { return path2.get_path(); } + const filepath& get_filepath2() const { return path2; } + std::string_view get_alternate_name() const { return std::string_view(alternate_name); } + + int get_dentry_wanted() const { return get_flags() & CEPH_MDS_FLAG_WANT_DENTRY; } + + void mark_queued_for_replay() const { queued_for_replay = true; } + bool is_queued_for_replay() const { return queued_for_replay; } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + + if (header.version >= 4) { + decode(head, p); + } else { + struct ceph_mds_request_head_legacy old_mds_head; + + decode(old_mds_head, p); + copy_from_legacy_head(&head, &old_mds_head); + head.version = 0; + + /* Can't set the btime from legacy struct */ + if (head.op == CEPH_MDS_OP_SETATTR) { + int localmask = head.args.setattr.mask; + + localmask &= ~CEPH_SETATTR_BTIME; + + head.args.setattr.btime = { init_le32(0), init_le32(0) }; + head.args.setattr.mask = localmask; + } + } + + decode(path, p); + decode(path2, p); + ceph::decode_nohead(head.num_releases, releases, p); + if (header.version >= 2) + decode(stamp, p); + if (header.version >= 4) // epoch 3 was for a ceph_mds_request_args change + decode(gid_list, p); + if (header.version >= 5) + decode(alternate_name, p); + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + head.num_releases = releases.size(); + head.version = CEPH_MDS_REQUEST_HEAD_VERSION; + + if (features & CEPH_FEATURE_FS_BTIME) { + encode(head, payload); + } else { + struct ceph_mds_request_head_legacy old_mds_head; + + copy_to_legacy_head(&old_mds_head, &head); + encode(old_mds_head, payload); + } + + encode(path, payload); + encode(path2, payload); + ceph::encode_nohead(releases, payload); + encode(stamp, payload); + encode(gid_list, payload); + encode(alternate_name, payload); + } + + std::string_view get_type_name() const override { return "creq"; } + void print(std::ostream& out) const override { + out << "client_request(" << get_orig_source() + << ":" << get_tid() + << " " << ceph_mds_op_name(get_op()); + if (head.op == CEPH_MDS_OP_GETATTR) + out << " " << ccap_string(head.args.getattr.mask); + if (head.op == CEPH_MDS_OP_SETATTR) { + if (head.args.setattr.mask & CEPH_SETATTR_MODE) + out << " mode=0" << std::oct << head.args.setattr.mode << std::dec; + if (head.args.setattr.mask & CEPH_SETATTR_UID) + out << " uid=" << head.args.setattr.uid; + if (head.args.setattr.mask & CEPH_SETATTR_GID) + out << " gid=" << head.args.setattr.gid; + if (head.args.setattr.mask & CEPH_SETATTR_SIZE) + out << " size=" << head.args.setattr.size; + if (head.args.setattr.mask & CEPH_SETATTR_MTIME) + out << " mtime=" << utime_t(head.args.setattr.mtime); + if (head.args.setattr.mask & CEPH_SETATTR_ATIME) + out << " atime=" << utime_t(head.args.setattr.atime); + } + if (head.op == CEPH_MDS_OP_SETFILELOCK || + head.op == CEPH_MDS_OP_GETFILELOCK) { + out << " rule " << (int)head.args.filelock_change.rule + << ", type " << (int)head.args.filelock_change.type + << ", owner " << head.args.filelock_change.owner + << ", pid " << head.args.filelock_change.pid + << ", start " << head.args.filelock_change.start + << ", length " << head.args.filelock_change.length + << ", wait " << (int)head.args.filelock_change.wait; + } + //if (!get_filepath().empty()) + out << " " << get_filepath(); + if (alternate_name.size()) + out << " (" << alternate_name << ") "; + if (!get_filepath2().empty()) + out << " " << get_filepath2(); + if (stamp != utime_t()) + out << " " << stamp; + if (head.num_retry) + out << " RETRY=" << (int)head.num_retry; + if (is_async()) + out << " ASYNC"; + if (is_replay()) + out << " REPLAY"; + if (queued_for_replay) + out << " QUEUED_FOR_REPLAY"; + out << " caller_uid=" << head.caller_uid + << ", caller_gid=" << head.caller_gid + << '{'; + for (auto i = gid_list.begin(); i != gid_list.end(); ++i) + out << *i << ','; + out << '}' + << ")"; + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +WRITE_CLASS_ENCODER(MClientRequest::Release) + +#endif diff --git a/src/messages/MClientRequestForward.h b/src/messages/MClientRequestForward.h new file mode 100644 index 000000000..5c1eebd4b --- /dev/null +++ b/src/messages/MClientRequestForward.h @@ -0,0 +1,72 @@ +// -*- 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_MCLIENTREQUESTFORWARD_H +#define CEPH_MCLIENTREQUESTFORWARD_H + +#include "msg/Message.h" + +class MClientRequestForward final : public SafeMessage { +private: + int32_t dest_mds; + int32_t num_fwd; + bool client_must_resend; + +protected: + MClientRequestForward() + : SafeMessage{CEPH_MSG_CLIENT_REQUEST_FORWARD}, + dest_mds(-1), num_fwd(-1), client_must_resend(false) {} + MClientRequestForward(ceph_tid_t t, int dm, int nf, bool cmr) : + SafeMessage{CEPH_MSG_CLIENT_REQUEST_FORWARD}, + dest_mds(dm), num_fwd(nf), client_must_resend(cmr) { + ceph_assert(client_must_resend); + header.tid = t; + } + ~MClientRequestForward() final {} + +public: + int get_dest_mds() const { return dest_mds; } + int get_num_fwd() const { return num_fwd; } + bool must_resend() const { return client_must_resend; } + + std::string_view get_type_name() const override { return "client_request_forward"; } + void print(std::ostream& o) const override { + o << "client_request_forward(" << get_tid() + << " to mds." << dest_mds + << " num_fwd=" << num_fwd + << (client_must_resend ? " client_must_resend":"") + << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(dest_mds, payload); + encode(num_fwd, payload); + encode(client_must_resend, payload); + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(dest_mds, p); + decode(num_fwd, p); + decode(client_must_resend, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MClientSession.h b/src/messages/MClientSession.h new file mode 100644 index 000000000..f6927a49c --- /dev/null +++ b/src/messages/MClientSession.h @@ -0,0 +1,106 @@ +// -*- 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_MCLIENTSESSION_H +#define CEPH_MCLIENTSESSION_H + +#include "msg/Message.h" +#include "mds/mdstypes.h" + +class MClientSession final : public SafeMessage { +private: + static constexpr int HEAD_VERSION = 5; + static constexpr int COMPAT_VERSION = 1; + +public: + ceph_mds_session_head head; + static constexpr unsigned SESSION_BLOCKLISTED = (1<<0); + + unsigned flags = 0; + std::map<std::string, std::string> metadata; + feature_bitset_t supported_features; + metric_spec_t metric_spec; + + int get_op() const { return head.op; } + version_t get_seq() const { return head.seq; } + utime_t get_stamp() const { return utime_t(head.stamp); } + int get_max_caps() const { return head.max_caps; } + int get_max_leases() const { return head.max_leases; } + +protected: + MClientSession() : SafeMessage{CEPH_MSG_CLIENT_SESSION, HEAD_VERSION, COMPAT_VERSION} { } + MClientSession(int o, version_t s=0, unsigned msg_flags=0) : + SafeMessage{CEPH_MSG_CLIENT_SESSION, HEAD_VERSION, COMPAT_VERSION}, + flags(msg_flags) { + memset(&head, 0, sizeof(head)); + head.op = o; + head.seq = s; + } + MClientSession(int o, utime_t st) : + SafeMessage{CEPH_MSG_CLIENT_SESSION, HEAD_VERSION, COMPAT_VERSION} { + memset(&head, 0, sizeof(head)); + head.op = o; + head.seq = 0; + st.encode_timeval(&head.stamp); + } + ~MClientSession() final {} + +public: + std::string_view get_type_name() const override { return "client_session"; } + void print(std::ostream& out) const override { + out << "client_session(" << ceph_session_op_name(get_op()); + if (get_seq()) + out << " seq " << get_seq(); + if (get_op() == CEPH_SESSION_RECALL_STATE) + out << " max_caps " << head.max_caps << " max_leases " << head.max_leases; + out << ")"; + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(head, p); + if (header.version >= 2) + decode(metadata, p); + if (header.version >= 3) + decode(supported_features, p); + if (header.version >= 4) { + decode(metric_spec, p); + } + if (header.version >= 5) { + decode(flags, p); + } + } + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(head, payload); + if (metadata.empty() && supported_features.empty()) { + // If we're not trying to send any metadata (always the case if + // we are a server) then send older-format message to avoid upsetting + // old kernel clients. + header.version = 1; + } else { + header.version = HEAD_VERSION; + encode(metadata, payload); + encode(supported_features, payload); + encode(metric_spec, payload); + encode(flags, payload); + } + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MClientSnap.h b/src/messages/MClientSnap.h new file mode 100644 index 000000000..75178bffa --- /dev/null +++ b/src/messages/MClientSnap.h @@ -0,0 +1,71 @@ +// -*- 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_MCLIENTSNAP_H +#define CEPH_MCLIENTSNAP_H + +#include "msg/Message.h" + +class MClientSnap final : public SafeMessage { +public: + ceph_mds_snap_head head; + ceph::buffer::list bl; + + // (for split only) + std::vector<inodeno_t> split_inos; + std::vector<inodeno_t> split_realms; + +protected: + MClientSnap(int o=0) : + SafeMessage{CEPH_MSG_CLIENT_SNAP} { + memset(&head, 0, sizeof(head)); + head.op = o; + } + ~MClientSnap() final {} + +public: + std::string_view get_type_name() const override { return "client_snap"; } + void print(std::ostream& out) const override { + out << "client_snap(" << ceph_snap_op_name(head.op); + if (head.split) + out << " split=" << inodeno_t(head.split); + out << " tracelen=" << bl.length(); + out << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + head.num_split_inos = split_inos.size(); + head.num_split_realms = split_realms.size(); + head.trace_len = bl.length(); + encode(head, payload); + ceph::encode_nohead(split_inos, payload); + ceph::encode_nohead(split_realms, payload); + ceph::encode_nohead(bl, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(head, p); + ceph::decode_nohead(head.num_split_inos, split_inos, p); + ceph::decode_nohead(head.num_split_realms, split_realms, p); + ceph::decode_nohead(head.trace_len, bl, p); + ceph_assert(p.end()); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MCommand.h b/src/messages/MCommand.h new file mode 100644 index 000000000..cd912cd28 --- /dev/null +++ b/src/messages/MCommand.h @@ -0,0 +1,60 @@ +// -*- 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_MCOMMAND_H +#define CEPH_MCOMMAND_H + +#include <vector> + +#include "msg/Message.h" + +class MCommand final : public Message { +public: + uuid_d fsid; + std::vector<std::string> cmd; + + MCommand() + : Message{MSG_COMMAND} {} + MCommand(const uuid_d &f) + : Message{MSG_COMMAND}, + fsid(f) { } + +private: + ~MCommand() final {} + +public: + std::string_view get_type_name() const override { return "command"; } + void print(std::ostream& o) const override { + o << "command(tid " << get_tid() << ": "; + for (unsigned i=0; i<cmd.size(); i++) { + if (i) o << ' '; + o << cmd[i]; + } + o << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(fsid, payload); + encode(cmd, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(fsid, p); + decode(cmd, p); + } +}; + +#endif diff --git a/src/messages/MCommandReply.h b/src/messages/MCommandReply.h new file mode 100644 index 000000000..ed627c85c --- /dev/null +++ b/src/messages/MCommandReply.h @@ -0,0 +1,59 @@ +// -*- 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_MCOMMANDREPLY_H +#define CEPH_MCOMMANDREPLY_H + +#include <string_view> + +#include "msg/Message.h" +#include "MCommand.h" + +class MCommandReply final : public Message { +public: + errorcode32_t r; + std::string rs; + + MCommandReply() + : Message{MSG_COMMAND_REPLY} {} + MCommandReply(MCommand *m, int _r) + : Message{MSG_COMMAND_REPLY}, r(_r) { + header.tid = m->get_tid(); + } + MCommandReply(int _r, std::string_view s) + : Message{MSG_COMMAND_REPLY}, + r(_r), rs(s) { } +private: + ~MCommandReply() final {} + +public: + std::string_view get_type_name() const override { return "command_reply"; } + void print(std::ostream& o) const override { + o << "command_reply(tid " << get_tid() << ": " << r << " " << rs << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(r, payload); + encode(rs, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(r, p); + decode(rs, p); + } +}; + +#endif diff --git a/src/messages/MConfig.h b/src/messages/MConfig.h new file mode 100644 index 000000000..c97c70640 --- /dev/null +++ b/src/messages/MConfig.h @@ -0,0 +1,42 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#pragma once + +#include "msg/Message.h" + +class MConfig : public Message { +public: + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; + + // use transparent comparator so we can lookup in it by std::string_view keys + std::map<std::string,std::string,std::less<>> config; + + MConfig() : Message{MSG_CONFIG, HEAD_VERSION, COMPAT_VERSION} { } + MConfig(const std::map<std::string,std::string,std::less<>>& c) + : Message{MSG_CONFIG, HEAD_VERSION, COMPAT_VERSION}, + config{c} {} + MConfig(std::map<std::string,std::string,std::less<>>&& c) + : Message{MSG_CONFIG, HEAD_VERSION, COMPAT_VERSION}, + config{std::move(c)} {} + + std::string_view get_type_name() const override { + return "config"; + } + void print(std::ostream& o) const override { + o << "config(" << config.size() << " keys" << ")"; + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(config, p); + } + + void encode_payload(uint64_t) override { + using ceph::encode; + encode(config, payload); + } + +}; diff --git a/src/messages/MDentryLink.h b/src/messages/MDentryLink.h new file mode 100644 index 000000000..c461105bc --- /dev/null +++ b/src/messages/MDentryLink.h @@ -0,0 +1,80 @@ +// -*- 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_MDENTRYLINK_H +#define CEPH_MDENTRYLINK_H + +#include <string_view> + +#include "messages/MMDSOp.h" + +class MDentryLink final : public MMDSOp { +private: + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; + + dirfrag_t subtree; + dirfrag_t dirfrag; + std::string dn; + bool is_primary = false; + + public: + dirfrag_t get_subtree() const { return subtree; } + dirfrag_t get_dirfrag() const { return dirfrag; } + const std::string& get_dn() const { return dn; } + bool get_is_primary() const { return is_primary; } + + ceph::buffer::list bl; + +protected: + MDentryLink() : + MMDSOp(MSG_MDS_DENTRYLINK, HEAD_VERSION, COMPAT_VERSION) { } + MDentryLink(dirfrag_t r, dirfrag_t df, std::string_view n, bool p) : + MMDSOp(MSG_MDS_DENTRYLINK, HEAD_VERSION, COMPAT_VERSION), + subtree(r), + dirfrag(df), + dn(n), + is_primary(p) {} + ~MDentryLink() final {} + +public: + std::string_view get_type_name() const override { return "dentry_link";} + void print(std::ostream& o) const override { + o << "dentry_link(" << dirfrag << " " << dn << ")"; + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(subtree, p); + decode(dirfrag, p); + decode(dn, p); + decode(is_primary, p); + decode(bl, p); + } + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(subtree, payload); + encode(dirfrag, payload); + encode(dn, payload); + encode(is_primary, payload); + encode(bl, payload); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MDentryUnlink.h b/src/messages/MDentryUnlink.h new file mode 100644 index 000000000..01240f5dc --- /dev/null +++ b/src/messages/MDentryUnlink.h @@ -0,0 +1,117 @@ +// -*- 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_MDENTRYUNLINK_H +#define CEPH_MDENTRYUNLINK_H + +#include <string_view> + +#include "messages/MMDSOp.h" + +class MDentryUnlink final : public MMDSOp { +private: + static constexpr int HEAD_VERSION = 2; + static constexpr int COMPAT_VERSION = 1; + + dirfrag_t dirfrag; + std::string dn; + bool unlinking = false; + + public: + dirfrag_t get_dirfrag() const { return dirfrag; } + const std::string& get_dn() const { return dn; } + bool is_unlinking() const { return unlinking; } + + ceph::buffer::list straybl; + ceph::buffer::list snapbl; + +protected: + MDentryUnlink() : + MMDSOp(MSG_MDS_DENTRYUNLINK, HEAD_VERSION, COMPAT_VERSION) { } + MDentryUnlink(dirfrag_t df, std::string_view n, bool u=false) : + MMDSOp(MSG_MDS_DENTRYUNLINK, HEAD_VERSION, COMPAT_VERSION), + dirfrag(df), dn(n), unlinking(u) {} + ~MDentryUnlink() final {} + +public: + std::string_view get_type_name() const override { return "dentry_unlink";} + void print(std::ostream& o) const override { + o << "dentry_unlink(" << dirfrag << " " << dn << ")"; + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(dirfrag, p); + decode(dn, p); + decode(straybl, p); + if (header.version >= 2) + decode(unlinking, p); + } + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(dirfrag, payload); + encode(dn, payload); + encode(straybl, payload); + encode(unlinking, payload); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +class MDentryUnlinkAck final : public MMDSOp { +private: + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; + + dirfrag_t dirfrag; + std::string dn; + + public: + dirfrag_t get_dirfrag() const { return dirfrag; } + const std::string& get_dn() const { return dn; } + +protected: + MDentryUnlinkAck() : + MMDSOp(MSG_MDS_DENTRYUNLINK_ACK, HEAD_VERSION, COMPAT_VERSION) { } + MDentryUnlinkAck(dirfrag_t df, std::string_view n) : + MMDSOp(MSG_MDS_DENTRYUNLINK_ACK, HEAD_VERSION, COMPAT_VERSION), + dirfrag(df), dn(n) {} + ~MDentryUnlinkAck() final {} + +public: + std::string_view get_type_name() const override { return "dentry_unlink_ack";} + void print(std::ostream& o) const override { + o << "dentry_unlink_ack(" << dirfrag << " " << dn << ")"; + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(dirfrag, p); + decode(dn, p); + } + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(dirfrag, payload); + encode(dn, payload); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MDirUpdate.h b/src/messages/MDirUpdate.h new file mode 100644 index 000000000..47ea3a7f4 --- /dev/null +++ b/src/messages/MDirUpdate.h @@ -0,0 +1,98 @@ +// -*- 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_MDIRUPDATE_H +#define CEPH_MDIRUPDATE_H + +#include "messages/MMDSOp.h" + +class MDirUpdate final : public MMDSOp { +public: + mds_rank_t get_source_mds() const { return from_mds; } + dirfrag_t get_dirfrag() const { return dirfrag; } + int get_dir_rep() const { return dir_rep; } + const std::set<int32_t>& get_dir_rep_by() const { return dir_rep_by; } + bool should_discover() const { return discover > tried_discover; } + const filepath& get_path() const { return path; } + + bool has_tried_discover() const { return tried_discover > 0; } + void inc_tried_discover() const { ++tried_discover; } + + std::string_view get_type_name() const override { return "dir_update"; } + void print(std::ostream& out) const override { + out << "dir_update(" << get_dirfrag() << ")"; + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(from_mds, p); + decode(dirfrag, p); + decode(dir_rep, p); + decode(discover, p); + decode(dir_rep_by, p); + decode(path, p); + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(from_mds, payload); + encode(dirfrag, payload); + encode(dir_rep, payload); + encode(discover, payload); + encode(dir_rep_by, payload); + encode(path, payload); + } + +protected: + ~MDirUpdate() final {} + MDirUpdate() : MMDSOp(MSG_MDS_DIRUPDATE, HEAD_VERSION, COMPAT_VERSION) {} + MDirUpdate(mds_rank_t f, + dirfrag_t dirfrag, + int dir_rep, + const std::set<int32_t>& dir_rep_by, + filepath& path, + bool discover = false) : + MMDSOp(MSG_MDS_DIRUPDATE, HEAD_VERSION, COMPAT_VERSION), from_mds(f), dirfrag(dirfrag), + dir_rep(dir_rep), dir_rep_by(dir_rep_by), path(path) { + this->discover = discover ? 5 : 0; + } + MDirUpdate(const MDirUpdate& m) + : MMDSOp{MSG_MDS_DIRUPDATE}, + from_mds(m.from_mds), + dirfrag(m.dirfrag), + dir_rep(m.dir_rep), + discover(m.discover), + dir_rep_by(m.dir_rep_by), + path(m.path), + tried_discover(m.tried_discover) + {} + + mds_rank_t from_mds = -1; + dirfrag_t dirfrag; + int32_t dir_rep = 5; + int32_t discover = 5; + std::set<int32_t> dir_rep_by; + filepath path; + mutable int tried_discover = 0; // XXX HACK + +private: + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MDiscover.h b/src/messages/MDiscover.h new file mode 100644 index 000000000..7b69981b4 --- /dev/null +++ b/src/messages/MDiscover.h @@ -0,0 +1,100 @@ +// -*- 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_MDISCOVER_H +#define CEPH_MDISCOVER_H + +#include "include/filepath.h" +#include "messages/MMDSOp.h" + +#include <string> + + +class MDiscover final : public MMDSOp { +private: + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; + + inodeno_t base_ino; // 1 -> root + frag_t base_dir_frag; + + snapid_t snapid; + filepath want; // ... [/]need/this/stuff + + bool want_base_dir = true; + bool path_locked = false; + + public: + inodeno_t get_base_ino() const { return base_ino; } + frag_t get_base_dir_frag() const { return base_dir_frag; } + snapid_t get_snapid() const { return snapid; } + + const filepath& get_want() const { return want; } + const std::string& get_dentry(int n) const { return want[n]; } + + bool wants_base_dir() const { return want_base_dir; } + bool is_path_locked() const { return path_locked; } + + void set_base_dir_frag(frag_t f) { base_dir_frag = f; } + +protected: + MDiscover() : MMDSOp(MSG_MDS_DISCOVER, HEAD_VERSION, COMPAT_VERSION) { } + MDiscover(inodeno_t base_ino_, + frag_t base_frag_, + snapid_t s, + filepath& want_path_, + bool want_base_dir_ = true, + bool path_locked_ = false) : + MMDSOp{MSG_MDS_DISCOVER}, + base_ino(base_ino_), + base_dir_frag(base_frag_), + snapid(s), + want(want_path_), + want_base_dir(want_base_dir_), + path_locked(path_locked_) { } + ~MDiscover() final {} + +public: + std::string_view get_type_name() const override { return "Dis"; } + void print(std::ostream &out) const override { + out << "discover(" << header.tid << " " << base_ino << "." << base_dir_frag + << " " << want << ")"; + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(base_ino, p); + decode(base_dir_frag, p); + decode(snapid, p); + decode(want, p); + decode(want_base_dir, p); + decode(path_locked, p); + } + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(base_ino, payload); + encode(base_dir_frag, payload); + encode(snapid, payload); + encode(want, payload); + encode(want_base_dir, payload); + encode(path_locked, payload); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MDiscoverReply.h b/src/messages/MDiscoverReply.h new file mode 100644 index 000000000..e2d11d0fb --- /dev/null +++ b/src/messages/MDiscoverReply.h @@ -0,0 +1,215 @@ +// -*- 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_MDISCOVERREPLY_H +#define CEPH_MDISCOVERREPLY_H + +#include "include/filepath.h" +#include "messages/MMDSOp.h" + +#include <string> + + + +/** + * MDiscoverReply - return new replicas (of inodes, dirs, dentries) + * + * we group returned items by (dir, dentry, inode). each + * item in each set shares an index (it's "depth"). + * + * we can start and end with any type. + * no_base_dir = true if the first group has an inode but no dir + * no_base_dentry = true if the first group has an inode but no dentry + * they are false if there is no returned data, ie the first group is empty. + * + * we also return errors: + * error_flag_dn(std::string) - the specified dentry dne + * error_flag_dir - the last item wasn't a dir, so we couldn't continue. + * + * and sometimes, + * dir_auth_hint - where we think the dir auth is + * + * depth() gives us the number of depth units/indices for which we have + * information. this INCLUDES those for which we have errors but no data. + * + * see MDCache::handle_discover, handle_discover_reply. + * + * + * so basically, we get + * + * dir den ino i + * x 0 + * x x x 1 + * or + * x x 0 + * x x x 1 + * or + * x x x 0 + * x x x 1 + * ...and trail off however we want. + * + * + */ + +class MDiscoverReply final : public MMDSOp { +private: + static constexpr int HEAD_VERSION = 2; + static constexpr int COMPAT_VERSION = 2; + + // info about original request + inodeno_t base_ino; + frag_t base_dir_frag; + bool wanted_base_dir = false; + bool path_locked = false; + snapid_t wanted_snapid; + + // and the response + bool flag_error_dn = false; + bool flag_error_dir = false; + std::string error_dentry; // dentry that was not found (to trigger waiters on asker) + bool unsolicited = false; + + mds_rank_t dir_auth_hint = 0; + + public: + __u8 starts_with = 0; + ceph::buffer::list trace; + + enum { DIR, DENTRY, INODE }; + + // accessors + inodeno_t get_base_ino() const { return base_ino; } + frag_t get_base_dir_frag() const { return base_dir_frag; } + bool get_wanted_base_dir() const { return wanted_base_dir; } + bool is_path_locked() const { return path_locked; } + snapid_t get_wanted_snapid() const { return wanted_snapid; } + + bool is_flag_error_dn() const { return flag_error_dn; } + bool is_flag_error_dir() const { return flag_error_dir; } + const std::string& get_error_dentry() const { return error_dentry; } + + int get_starts_with() const { return starts_with; } + + mds_rank_t get_dir_auth_hint() const { return dir_auth_hint; } + + bool is_unsolicited() const { return unsolicited; } + void mark_unsolicited() { unsolicited = true; } + + void set_base_dir_frag(frag_t df) { base_dir_frag = df; } + +protected: + MDiscoverReply() : MMDSOp{MSG_MDS_DISCOVERREPLY, HEAD_VERSION, COMPAT_VERSION} { } + MDiscoverReply(const MDiscover &dis) : + MMDSOp{MSG_MDS_DISCOVERREPLY, HEAD_VERSION, COMPAT_VERSION}, + base_ino(dis.get_base_ino()), + base_dir_frag(dis.get_base_dir_frag()), + wanted_base_dir(dis.wants_base_dir()), + path_locked(dis.is_path_locked()), + wanted_snapid(dis.get_snapid()), + flag_error_dn(false), + flag_error_dir(false), + unsolicited(false), + dir_auth_hint(CDIR_AUTH_UNKNOWN), + starts_with(DIR) + { + header.tid = dis.get_tid(); + } + MDiscoverReply(dirfrag_t df) : + MMDSOp{MSG_MDS_DISCOVERREPLY, HEAD_VERSION, COMPAT_VERSION}, + base_ino(df.ino), + base_dir_frag(df.frag), + wanted_base_dir(false), + path_locked(false), + wanted_snapid(CEPH_NOSNAP), + flag_error_dn(false), + flag_error_dir(false), + unsolicited(false), + dir_auth_hint(CDIR_AUTH_UNKNOWN), + starts_with(DIR) + { + header.tid = 0; + } + ~MDiscoverReply() final {} + +public: + std::string_view get_type_name() const override { return "discover_reply"; } + void print(std::ostream& out) const override { + out << "discover_reply(" << header.tid << " " << base_ino << ")"; + } + + // builders + bool is_empty() const { + return trace.length() == 0 && + !flag_error_dn && + !flag_error_dir && + dir_auth_hint == CDIR_AUTH_UNKNOWN; + } + + // void set_flag_forward() { flag_forward = true; } + void set_flag_error_dn(std::string_view dn) { + flag_error_dn = true; + error_dentry = dn; + } + void set_flag_error_dir() { + flag_error_dir = true; + } + void set_dir_auth_hint(int a) { + dir_auth_hint = a; + } + void set_error_dentry(std::string_view dn) { + error_dentry = dn; + } + + + // ... + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(base_ino, p); + decode(base_dir_frag, p); + decode(wanted_base_dir, p); + decode(path_locked, p); + decode(wanted_snapid, p); + decode(flag_error_dn, p); + decode(flag_error_dir, p); + decode(error_dentry, p); + decode(dir_auth_hint, p); + decode(unsolicited, p); + + decode(starts_with, p); + decode(trace, p); + } + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(base_ino, payload); + encode(base_dir_frag, payload); + encode(wanted_base_dir, payload); + encode(path_locked, payload); + encode(wanted_snapid, payload); + encode(flag_error_dn, payload); + encode(flag_error_dir, payload); + encode(error_dentry, payload); + encode(dir_auth_hint, payload); + encode(unsolicited, payload); + + encode(starts_with, payload); + encode(trace, payload); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MExportCaps.h b/src/messages/MExportCaps.h new file mode 100644 index 000000000..63cf927e8 --- /dev/null +++ b/src/messages/MExportCaps.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 <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_MEXPORTCAPS_H +#define CEPH_MEXPORTCAPS_H + +#include "messages/MMDSOp.h" + +class MExportCaps final : public MMDSOp { +private: + static constexpr int HEAD_VERSION = 2; + static constexpr int COMPAT_VERSION = 1; + +public: + inodeno_t ino; + ceph::buffer::list cap_bl; + std::map<client_t,entity_inst_t> client_map; + std::map<client_t,client_metadata_t> client_metadata_map; + +protected: + MExportCaps() : + MMDSOp{MSG_MDS_EXPORTCAPS, HEAD_VERSION, COMPAT_VERSION} {} + ~MExportCaps() final {} + +public: + std::string_view get_type_name() const override { return "export_caps"; } + void print(std::ostream& o) const override { + o << "export_caps(" << ino << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(ino, payload); + encode(cap_bl, payload); + encode(client_map, payload, features); + encode(client_metadata_map, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(ino, p); + decode(cap_bl, p); + decode(client_map, p); + if (header.version >= 2) + decode(client_metadata_map, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MExportCapsAck.h b/src/messages/MExportCapsAck.h new file mode 100644 index 000000000..1ac62fdd4 --- /dev/null +++ b/src/messages/MExportCapsAck.h @@ -0,0 +1,58 @@ +// -*- 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_MEXPORTCAPSACK_H +#define CEPH_MEXPORTCAPSACK_H + +#include "messages/MMDSOp.h" + +class MExportCapsAck final : public MMDSOp { + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; + +public: + inodeno_t ino; + ceph::buffer::list cap_bl; + +protected: + MExportCapsAck() : + MMDSOp{MSG_MDS_EXPORTCAPSACK, HEAD_VERSION, COMPAT_VERSION} {} + MExportCapsAck(inodeno_t i) : + MMDSOp{MSG_MDS_EXPORTCAPSACK, HEAD_VERSION, COMPAT_VERSION}, ino(i) {} + ~MExportCapsAck() final {} + +public: + std::string_view get_type_name() const override { return "export_caps_ack"; } + void print(std::ostream& o) const override { + o << "export_caps_ack(" << ino << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(ino, payload); + encode(cap_bl, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(ino, p); + decode(cap_bl, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MExportDir.h b/src/messages/MExportDir.h new file mode 100644 index 000000000..882aecfca --- /dev/null +++ b/src/messages/MExportDir.h @@ -0,0 +1,66 @@ +// -*- 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_MEXPORTDIR_H +#define CEPH_MEXPORTDIR_H + +#include "messages/MMDSOp.h" + +class MExportDir final : public MMDSOp { +public: + dirfrag_t dirfrag; + ceph::buffer::list export_data; + std::vector<dirfrag_t> bounds; + ceph::buffer::list client_map; + +protected: + MExportDir() : MMDSOp{MSG_MDS_EXPORTDIR} {} + MExportDir(dirfrag_t df, uint64_t tid) : + MMDSOp{MSG_MDS_EXPORTDIR}, dirfrag(df) { + set_tid(tid); + } + ~MExportDir() final {} + +public: + std::string_view get_type_name() const override { return "Ex"; } + void print(std::ostream& o) const override { + o << "export(" << dirfrag << ")"; + } + + void add_export(dirfrag_t df) { + bounds.push_back(df); + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(dirfrag, payload); + encode(bounds, payload); + encode(export_data, payload); + encode(client_map, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(dirfrag, p); + decode(bounds, p); + decode(export_data, p); + decode(client_map, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MExportDirAck.h b/src/messages/MExportDirAck.h new file mode 100644 index 000000000..4728cc3ab --- /dev/null +++ b/src/messages/MExportDirAck.h @@ -0,0 +1,58 @@ +// -*- 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_MEXPORTDIRACK_H +#define CEPH_MEXPORTDIRACK_H + +#include "MExportDir.h" +#include "messages/MMDSOp.h" + +class MExportDirAck final : public MMDSOp { +public: + dirfrag_t dirfrag; + ceph::buffer::list imported_caps; + + dirfrag_t get_dirfrag() const { return dirfrag; } + +protected: + MExportDirAck() : MMDSOp{MSG_MDS_EXPORTDIRACK} {} + MExportDirAck(dirfrag_t df, uint64_t tid) : + MMDSOp{MSG_MDS_EXPORTDIRACK}, dirfrag(df) { + set_tid(tid); + } + ~MExportDirAck() final {} + +public: + std::string_view get_type_name() const override { return "ExAck"; } + void print(std::ostream& o) const override { + o << "export_ack(" << dirfrag << ")"; + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(dirfrag, p); + decode(imported_caps, p); + } + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(dirfrag, payload); + encode(imported_caps, payload); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MExportDirCancel.h b/src/messages/MExportDirCancel.h new file mode 100644 index 000000000..50bba2679 --- /dev/null +++ b/src/messages/MExportDirCancel.h @@ -0,0 +1,58 @@ +// -*- 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_MEXPORTDIRCANCEL_H +#define CEPH_MEXPORTDIRCANCEL_H + +#include "include/types.h" +#include "messages/MMDSOp.h" + +class MExportDirCancel final : public MMDSOp { +private: + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; + dirfrag_t dirfrag; + + public: + dirfrag_t get_dirfrag() const { return dirfrag; } + +protected: + MExportDirCancel() : MMDSOp{MSG_MDS_EXPORTDIRCANCEL, HEAD_VERSION, COMPAT_VERSION} {} + MExportDirCancel(dirfrag_t df, uint64_t tid) : + MMDSOp{MSG_MDS_EXPORTDIRCANCEL, HEAD_VERSION, COMPAT_VERSION}, dirfrag(df) { + set_tid(tid); + } + ~MExportDirCancel() final {} + +public: + std::string_view get_type_name() const override { return "ExCancel"; } + void print(std::ostream& o) const override { + o << "export_cancel(" << dirfrag << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(dirfrag, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(dirfrag, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MExportDirDiscover.h b/src/messages/MExportDirDiscover.h new file mode 100644 index 000000000..91d62a49b --- /dev/null +++ b/src/messages/MExportDirDiscover.h @@ -0,0 +1,73 @@ +// -*- 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_MEXPORTDIRDISCOVER_H +#define CEPH_MEXPORTDIRDISCOVER_H + +#include "include/types.h" +#include "messages/MMDSOp.h" + +class MExportDirDiscover final : public MMDSOp { +private: + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; + mds_rank_t from = -1; + dirfrag_t dirfrag; + filepath path; + + public: + mds_rank_t get_source_mds() const { return from; } + inodeno_t get_ino() const { return dirfrag.ino; } + dirfrag_t get_dirfrag() const { return dirfrag; } + const filepath& get_path() const { return path; } + + bool started; + +protected: + MExportDirDiscover() : + MMDSOp{MSG_MDS_EXPORTDIRDISCOVER, HEAD_VERSION, COMPAT_VERSION}, + started(false) { } + MExportDirDiscover(dirfrag_t df, filepath& p, mds_rank_t f, uint64_t tid) : + MMDSOp{MSG_MDS_EXPORTDIRDISCOVER, HEAD_VERSION, COMPAT_VERSION}, + from(f), dirfrag(df), path(p), started(false) { + set_tid(tid); + } + ~MExportDirDiscover() final {} + +public: + std::string_view get_type_name() const override { return "ExDis"; } + void print(std::ostream& o) const override { + o << "export_discover(" << dirfrag << " " << path << ")"; + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(from, p); + decode(dirfrag, p); + decode(path, p); + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(from, payload); + encode(dirfrag, payload); + encode(path, payload); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MExportDirDiscoverAck.h b/src/messages/MExportDirDiscoverAck.h new file mode 100644 index 000000000..b33ed07a5 --- /dev/null +++ b/src/messages/MExportDirDiscoverAck.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 <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_MEXPORTDIRDISCOVERACK_H +#define CEPH_MEXPORTDIRDISCOVERACK_H + +#include "include/types.h" +#include "messages/MMDSOp.h" + +class MExportDirDiscoverAck final : public MMDSOp { +private: + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; + + dirfrag_t dirfrag; + bool success; + + public: + inodeno_t get_ino() const { return dirfrag.ino; } + dirfrag_t get_dirfrag() const { return dirfrag; } + bool is_success() const { return success; } + +protected: + MExportDirDiscoverAck() : MMDSOp{MSG_MDS_EXPORTDIRDISCOVERACK, HEAD_VERSION, COMPAT_VERSION} {} + MExportDirDiscoverAck(dirfrag_t df, uint64_t tid, bool s=true) : + MMDSOp{MSG_MDS_EXPORTDIRDISCOVERACK, HEAD_VERSION, COMPAT_VERSION}, + dirfrag(df), success(s) { + set_tid(tid); + } + ~MExportDirDiscoverAck() final {} + +public: + std::string_view get_type_name() const override { return "ExDisA"; } + void print(std::ostream& o) const override { + o << "export_discover_ack(" << dirfrag; + if (success) + o << " success)"; + else + o << " failure)"; + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(dirfrag, p); + decode(success, p); + } + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(dirfrag, payload); + encode(success, payload); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MExportDirFinish.h b/src/messages/MExportDirFinish.h new file mode 100644 index 000000000..5cbf9ae29 --- /dev/null +++ b/src/messages/MExportDirFinish.h @@ -0,0 +1,63 @@ +// -*- 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_MEXPORTDIRFINISH_H +#define CEPH_MEXPORTDIRFINISH_H + +#include "messages/MMDSOp.h" + +class MExportDirFinish final : public MMDSOp { +private: + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; + + dirfrag_t dirfrag; + bool last; + + public: + dirfrag_t get_dirfrag() const { return dirfrag; } + bool is_last() const { return last; } + +protected: + MExportDirFinish() : + MMDSOp{MSG_MDS_EXPORTDIRFINISH, HEAD_VERSION, COMPAT_VERSION}, last(false) {} + MExportDirFinish(dirfrag_t df, bool l, uint64_t tid) : + MMDSOp{MSG_MDS_EXPORTDIRFINISH, HEAD_VERSION, COMPAT_VERSION}, dirfrag(df), last(l) { + set_tid(tid); + } + ~MExportDirFinish() final {} + +public: + std::string_view get_type_name() const override { return "ExFin"; } + void print(std::ostream& o) const override { + o << "export_finish(" << dirfrag << (last ? " last" : "") << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(dirfrag, payload); + encode(last, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(dirfrag, p); + decode(last, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MExportDirNotify.h b/src/messages/MExportDirNotify.h new file mode 100644 index 000000000..bad8f82a0 --- /dev/null +++ b/src/messages/MExportDirNotify.h @@ -0,0 +1,90 @@ +// -*- 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_MEXPORTDIRNOTIFY_H +#define CEPH_MEXPORTDIRNOTIFY_H + +#include "messages/MMDSOp.h" + +class MExportDirNotify final : public MMDSOp { +private: + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; + + dirfrag_t base; + bool ack; + std::pair<__s32,__s32> old_auth, new_auth; + std::list<dirfrag_t> bounds; // bounds; these dirs are _not_ included (tho the dirfragdes are) + + public: + dirfrag_t get_dirfrag() const { return base; } + std::pair<__s32,__s32> get_old_auth() const { return old_auth; } + std::pair<__s32,__s32> get_new_auth() const { return new_auth; } + bool wants_ack() const { return ack; } + const std::list<dirfrag_t>& get_bounds() const { return bounds; } + std::list<dirfrag_t>& get_bounds() { return bounds; } + +protected: + MExportDirNotify() : + MMDSOp{MSG_MDS_EXPORTDIRNOTIFY, HEAD_VERSION, COMPAT_VERSION} {} + MExportDirNotify(dirfrag_t i, uint64_t tid, bool a, std::pair<__s32,__s32> oa, + std::pair<__s32,__s32> na) : + MMDSOp{MSG_MDS_EXPORTDIRNOTIFY, HEAD_VERSION, COMPAT_VERSION}, + base(i), ack(a), old_auth(oa), new_auth(na) { + set_tid(tid); + } + ~MExportDirNotify() final {} + +public: + std::string_view get_type_name() const override { return "ExNot"; } + void print(std::ostream& o) const override { + o << "export_notify(" << base; + o << " " << old_auth << " -> " << new_auth; + if (ack) + o << " ack)"; + else + o << " no ack)"; + } + + void copy_bounds(std::list<dirfrag_t>& ex) { + this->bounds = ex; + } + void copy_bounds(std::set<dirfrag_t>& ex) { + for (auto i = ex.begin(); i != ex.end(); ++i) + bounds.push_back(*i); + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(base, payload); + encode(ack, payload); + encode(old_auth, payload); + encode(new_auth, payload); + encode(bounds, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(base, p); + decode(ack, p); + decode(old_auth, p); + decode(new_auth, p); + decode(bounds, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MExportDirNotifyAck.h b/src/messages/MExportDirNotifyAck.h new file mode 100644 index 000000000..71ffafc14 --- /dev/null +++ b/src/messages/MExportDirNotifyAck.h @@ -0,0 +1,63 @@ +// -*- 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_MEXPORTDIRNOTIFYACK_H +#define CEPH_MEXPORTDIRNOTIFYACK_H + +#include "messages/MMDSOp.h" + +class MExportDirNotifyAck final : public MMDSOp { +private: + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; + + dirfrag_t dirfrag; + std::pair<__s32,__s32> new_auth; + + public: + dirfrag_t get_dirfrag() const { return dirfrag; } + std::pair<__s32,__s32> get_new_auth() const { return new_auth; } + +protected: + MExportDirNotifyAck() : + MMDSOp{MSG_MDS_EXPORTDIRNOTIFYACK, HEAD_VERSION, COMPAT_VERSION} {} + MExportDirNotifyAck(dirfrag_t df, uint64_t tid, std::pair<__s32,__s32> na) : + MMDSOp{MSG_MDS_EXPORTDIRNOTIFYACK, HEAD_VERSION, COMPAT_VERSION}, dirfrag(df), new_auth(na) { + set_tid(tid); + } + ~MExportDirNotifyAck() final {} + +public: + std::string_view get_type_name() const override { return "ExNotA"; } + void print(std::ostream& o) const override { + o << "export_notify_ack(" << dirfrag << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(dirfrag, payload); + encode(new_auth, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(dirfrag, p); + decode(new_auth, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MExportDirPrep.h b/src/messages/MExportDirPrep.h new file mode 100644 index 000000000..4a456d517 --- /dev/null +++ b/src/messages/MExportDirPrep.h @@ -0,0 +1,93 @@ +// -*- 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_MEXPORTDIRPREP_H +#define CEPH_MEXPORTDIRPREP_H + +#include "include/types.h" +#include "messages/MMDSOp.h" + +class MExportDirPrep final : public MMDSOp { +private: + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; + + dirfrag_t dirfrag; +public: + ceph::buffer::list basedir; + std::list<dirfrag_t> bounds; + std::list<ceph::buffer::list> traces; +private: + std::set<mds_rank_t> bystanders; + bool b_did_assim = false; + +public: + dirfrag_t get_dirfrag() const { return dirfrag; } + const std::list<dirfrag_t>& get_bounds() const { return bounds; } + const std::set<mds_rank_t> &get_bystanders() const { return bystanders; } + + bool did_assim() const { return b_did_assim; } + void mark_assim() { b_did_assim = true; } + +protected: + MExportDirPrep() = default; + MExportDirPrep(dirfrag_t df, uint64_t tid) : + MMDSOp{MSG_MDS_EXPORTDIRPREP, HEAD_VERSION, COMPAT_VERSION}, + dirfrag(df) + { + set_tid(tid); + } + ~MExportDirPrep() final {} + +public: + std::string_view get_type_name() const override { return "ExP"; } + void print(std::ostream& o) const override { + o << "export_prep(" << dirfrag << ")"; + } + + void add_bound(dirfrag_t df) { + bounds.push_back( df ); + } + void add_trace(ceph::buffer::list& bl) { + traces.push_back(bl); + } + void add_bystander(mds_rank_t who) { + bystanders.insert(who); + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(dirfrag, p); + decode(basedir, p); + decode(bounds, p); + decode(traces, p); + decode(bystanders, p); + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(dirfrag, payload); + encode(basedir, payload); + encode(bounds, payload); + encode(traces, payload); + encode(bystanders, payload); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MExportDirPrepAck.h b/src/messages/MExportDirPrepAck.h new file mode 100644 index 000000000..1d5456ac8 --- /dev/null +++ b/src/messages/MExportDirPrepAck.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 <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_MEXPORTDIRPREPACK_H +#define CEPH_MEXPORTDIRPREPACK_H + +#include "include/types.h" +#include "messages/MMDSOp.h" + +class MExportDirPrepAck final : public MMDSOp { +private: + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; + + dirfrag_t dirfrag; + bool success = false; + + public: + dirfrag_t get_dirfrag() const { return dirfrag; } + +protected: + MExportDirPrepAck() : + MMDSOp{MSG_MDS_EXPORTDIRPREPACK, HEAD_VERSION, COMPAT_VERSION} {} + MExportDirPrepAck(dirfrag_t df, bool s, uint64_t tid) : + MMDSOp{MSG_MDS_EXPORTDIRPREPACK, HEAD_VERSION, COMPAT_VERSION}, dirfrag(df), success(s) { + set_tid(tid); + } + ~MExportDirPrepAck() final {} + +public: + bool is_success() const { return success; } + std::string_view get_type_name() const override { return "ExPAck"; } + void print(std::ostream& o) const override { + o << "export_prep_ack(" << dirfrag << (success ? " success)" : " fail)"); + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(dirfrag, p); + decode(success, p); + } + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(dirfrag, payload); + encode(success, payload); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MFSMap.h b/src/messages/MFSMap.h new file mode 100644 index 000000000..fff7529d3 --- /dev/null +++ b/src/messages/MFSMap.h @@ -0,0 +1,62 @@ +// -*- 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_MFSMAP_H +#define CEPH_MFSMAP_H + +#include "msg/Message.h" +#include "mds/FSMap.h" +#include "include/ceph_features.h" + +class MFSMap final : public Message { +public: + epoch_t epoch; + + version_t get_epoch() const { return epoch; } + const FSMap& get_fsmap() const {return fsmap;} + + MFSMap() : + Message{CEPH_MSG_FS_MAP}, epoch(0) {} + MFSMap(const uuid_d &f, const FSMap &fsmap_) : + Message{CEPH_MSG_FS_MAP}, + epoch(fsmap_.get_epoch()), + fsmap{fsmap_} + {} +private: + FSMap fsmap; + + ~MFSMap() final {} + +public: + std::string_view get_type_name() const override { return "fsmap"; } + void print(std::ostream& out) const override { + out << "fsmap(e " << epoch << ")"; + } + + // marshalling + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(epoch, p); + decode(fsmap, p); + } + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(epoch, payload); + encode(fsmap, payload, features); + } +}; + +#endif diff --git a/src/messages/MFSMapUser.h b/src/messages/MFSMapUser.h new file mode 100644 index 000000000..2d4192841 --- /dev/null +++ b/src/messages/MFSMapUser.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 <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_MFSMAPCOMPACT_H +#define CEPH_MFSMAPCOMPACT_H + +#include "msg/Message.h" +#include "mds/FSMapUser.h" +#include "include/ceph_features.h" + +class MFSMapUser final : public Message { +public: + epoch_t epoch; + + version_t get_epoch() const { return epoch; } + const FSMapUser& get_fsmap() const { return fsmap; } + + MFSMapUser() : + Message{CEPH_MSG_FS_MAP_USER}, epoch(0) {} + MFSMapUser(const uuid_d &f, const FSMapUser &fsmap_) : + Message{CEPH_MSG_FS_MAP_USER}, + epoch(fsmap_.epoch), + fsmap{fsmap_} + {} +private: + FSMapUser fsmap; + + ~MFSMapUser() final {} + +public: + std::string_view get_type_name() const override { return "fsmap.user"; } + void print(std::ostream& out) const override { + out << "fsmap.user(e " << epoch << ")"; + } + + // marshalling + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(epoch, p); + decode(fsmap, p); + } + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(epoch, payload); + encode(fsmap, payload, features); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MForward.h b/src/messages/MForward.h new file mode 100644 index 000000000..f47de8fc2 --- /dev/null +++ b/src/messages/MForward.h @@ -0,0 +1,158 @@ +// -*- 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-2010 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. + * + * Client requests often need to get forwarded from some monitor + * to the leader. This class encapsulates the original message + * along with the client's caps so the leader can do proper permissions + * checking. + */ + +#ifndef CEPH_MFORWARD_H +#define CEPH_MFORWARD_H + +#include "msg/Message.h" +#include "mon/MonCap.h" +#include "include/encoding.h" +#include "include/stringify.h" + +class MForward final : public Message { +public: + uint64_t tid; + uint8_t client_type; + entity_addrvec_t client_addrs; + entity_addr_t client_socket_addr; + MonCap client_caps; + uint64_t con_features; + EntityName entity_name; + PaxosServiceMessage *msg; // incoming or outgoing message + + std::string msg_desc; // for operator<< only + + static constexpr int HEAD_VERSION = 4; + static constexpr int COMPAT_VERSION = 4; + + MForward() : Message{MSG_FORWARD, HEAD_VERSION, COMPAT_VERSION}, + tid(0), con_features(0), msg(NULL) {} + MForward(uint64_t t, PaxosServiceMessage *m, uint64_t feat, + const MonCap& caps) : + Message{MSG_FORWARD, HEAD_VERSION, COMPAT_VERSION}, + tid(t), client_caps(caps), msg(NULL) { + client_type = m->get_source().type(); + client_addrs = m->get_source_addrs(); + if (auto con = m->get_connection()) { + client_socket_addr = con->get_peer_socket_addr(); + } + con_features = feat; + msg = (PaxosServiceMessage*)m->get(); + } +private: + ~MForward() final { + if (msg) { + // message was unclaimed + msg->put(); + msg = NULL; + } + } + +public: + void encode_payload(uint64_t features) override { + using ceph::encode; + if (!HAVE_FEATURE(features, SERVER_NAUTILUS)) { + header.version = 3; + header.compat_version = 3; + encode(tid, payload); + entity_inst_t client; + client.name = entity_name_t(client_type, -1); + client.addr = client_addrs.legacy_addr(); + encode(client, payload, features); + encode(client_caps, payload, features); + // Encode client message with intersection of target and source + // features. This could matter if the semantics of the encoded + // message are changed when reencoding with more features than the + // client had originally. That should never happen, but we may as + // well be defensive here. + if (con_features != features) { + msg->clear_payload(); + } + encode_message(msg, features & con_features, payload); + encode(con_features, payload); + encode(entity_name, payload); + return; + } + header.version = HEAD_VERSION; + header.compat_version = COMPAT_VERSION; + encode(tid, payload); + encode(client_type, payload, features); + encode(client_addrs, payload, features); + encode(client_socket_addr, payload, features); + encode(client_caps, payload, features); + // Encode client message with intersection of target and source + // features. This could matter if the semantics of the encoded + // message are changed when reencoding with more features than the + // client had originally. That should never happen, but we may as + // well be defensive here. + if (con_features != features) { + msg->clear_payload(); + } + encode_message(msg, features & con_features, payload); + encode(con_features, payload); + encode(entity_name, payload); + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(tid, p); + if (header.version < 4) { + entity_inst_t client; + decode(client, p); + client_type = client.name.type(); + client_addrs = entity_addrvec_t(client.addr); + client_socket_addr = client.addr; + } else { + decode(client_type, p); + decode(client_addrs, p); + decode(client_socket_addr, p); + } + decode(client_caps, p); + msg = (PaxosServiceMessage *)decode_message(NULL, 0, p); + decode(con_features, p); + decode(entity_name, p); + } + + PaxosServiceMessage *claim_message() { + // let whoever is claiming the message deal with putting it. + ceph_assert(msg); + msg_desc = stringify(*msg); + PaxosServiceMessage *m = msg; + msg = NULL; + return m; + } + + std::string_view get_type_name() const override { return "forward"; } + void print(std::ostream& o) const override { + o << "forward("; + if (msg) { + o << *msg; + } else { + o << msg_desc; + } + o << " caps " << client_caps + << " tid " << tid + << " con_features " << con_features << ")"; + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MGatherCaps.h b/src/messages/MGatherCaps.h new file mode 100644 index 000000000..f3f05b94e --- /dev/null +++ b/src/messages/MGatherCaps.h @@ -0,0 +1,39 @@ +#ifndef CEPH_MGATHERCAPS_H +#define CEPH_MGATHERCAPS_H + +#include "messages/MMDSOp.h" + + +class MGatherCaps final : public MMDSOp { + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; + +public: + inodeno_t ino; + +protected: + MGatherCaps() : + MMDSOp{MSG_MDS_GATHERCAPS, HEAD_VERSION, COMPAT_VERSION} {} + ~MGatherCaps() final {} + +public: + std::string_view get_type_name() const override { return "gather_caps"; } + void print(std::ostream& o) const override { + o << "gather_caps(" << ino << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(ino, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(ino, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MGenericMessage.h b/src/messages/MGenericMessage.h new file mode 100644 index 000000000..32699728a --- /dev/null +++ b/src/messages/MGenericMessage.h @@ -0,0 +1,40 @@ +// -*- 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_MGENERICMESSAGE_H +#define CEPH_MGENERICMESSAGE_H + +#include "msg/Message.h" + +class MGenericMessage : public Message { +private: + char tname[20]; + //long pcid; + + public: + MGenericMessage(int t=0) : Message{t} { + snprintf(tname, sizeof(tname), "generic%d", get_type()); + } + + //void set_pcid(long pcid) { this->pcid = pcid; } + //long get_pcid() { return pcid; } + + std::string_view get_type_name() const override { return tname; } + + void decode_payload() override { } + void encode_payload(uint64_t features) override { } +}; + +#endif diff --git a/src/messages/MGetConfig.h b/src/messages/MGetConfig.h new file mode 100644 index 000000000..2575aa4bc --- /dev/null +++ b/src/messages/MGetConfig.h @@ -0,0 +1,48 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#pragma once + +#include "msg/Message.h" + +class MGetConfig : public Message { +public: + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; + + EntityName name; ///< e.g., mon.a, client.foo + std::string host; ///< our hostname + std::string device_class; + + MGetConfig() : Message{MSG_GET_CONFIG, HEAD_VERSION, COMPAT_VERSION} { } + MGetConfig(const EntityName& n, const std::string& h) + : Message{MSG_GET_CONFIG, HEAD_VERSION, COMPAT_VERSION}, + name(n), + host(h) {} + + std::string_view get_type_name() const override { + return "get_config"; + } + void print(std::ostream& o) const override { + o << "get_config(" << name << "@" << host; + if (device_class.size()) { + o << " device_class " << device_class; + } + o << ")"; + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(name, p); + decode(host, p); + decode(device_class, p); + } + + void encode_payload(uint64_t) override { + using ceph::encode; + encode(name, payload); + encode(host, payload); + encode(device_class, payload); + } +}; diff --git a/src/messages/MGetPoolStats.h b/src/messages/MGetPoolStats.h new file mode 100644 index 000000000..82d1fcd2d --- /dev/null +++ b/src/messages/MGetPoolStats.h @@ -0,0 +1,57 @@ +// -*- 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_MGETPOOLSTATS_H +#define CEPH_MGETPOOLSTATS_H + +#include "messages/PaxosServiceMessage.h" + +class MGetPoolStats final : public PaxosServiceMessage { +public: + uuid_d fsid; + std::vector<std::string> pools; + + MGetPoolStats() : PaxosServiceMessage{MSG_GETPOOLSTATS, 0} {} + MGetPoolStats(const uuid_d& f, ceph_tid_t t, std::vector<std::string>& ls, version_t l) : + PaxosServiceMessage{MSG_GETPOOLSTATS, l}, + fsid(f), pools(ls) { + set_tid(t); + } + +private: + ~MGetPoolStats() final {} + +public: + std::string_view get_type_name() const override { return "getpoolstats"; } + void print(std::ostream& out) const override { + out << "getpoolstats(" << get_tid() << " " << pools << " v" << version << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + paxos_encode(); + encode(fsid, payload); + encode(pools, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + paxos_decode(p); + decode(fsid, p); + decode(pools, p); + } +}; + +#endif diff --git a/src/messages/MGetPoolStatsReply.h b/src/messages/MGetPoolStatsReply.h new file mode 100644 index 000000000..eaf95d4a0 --- /dev/null +++ b/src/messages/MGetPoolStatsReply.h @@ -0,0 +1,73 @@ +// -*- 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_MGETPOOLSTATSREPLY_H +#define CEPH_MGETPOOLSTATSREPLY_H + +class MGetPoolStatsReply final : public PaxosServiceMessage { + static constexpr int HEAD_VERSION = 2; + static constexpr int COMPAT_VERSION = 1; + +public: + uuid_d fsid; + boost::container::flat_map<std::string, pool_stat_t> pool_stats; + bool per_pool = false; + + MGetPoolStatsReply() : PaxosServiceMessage{MSG_GETPOOLSTATSREPLY, 0, + HEAD_VERSION, COMPAT_VERSION} {} + MGetPoolStatsReply(uuid_d& f, ceph_tid_t t, version_t v) : + PaxosServiceMessage{MSG_GETPOOLSTATSREPLY, v, + HEAD_VERSION, COMPAT_VERSION}, + fsid(f) { + set_tid(t); + } + +private: + ~MGetPoolStatsReply() final {} + +public: + std::string_view get_type_name() const override { return "getpoolstats"; } + void print(std::ostream& out) const override { + out << "getpoolstatsreply(" << get_tid(); + if (per_pool) + out << " per_pool"; + out << " v" << version << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + paxos_encode(); + encode(fsid, payload); + encode(pool_stats, payload, features); + encode(per_pool, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + paxos_decode(p); + decode(fsid, p); + decode(pool_stats, p); + if (header.version >= 2) { + decode(per_pool, p); + } else { + per_pool = false; + } + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MHeartbeat.h b/src/messages/MHeartbeat.h new file mode 100644 index 000000000..40c1042b6 --- /dev/null +++ b/src/messages/MHeartbeat.h @@ -0,0 +1,66 @@ +// -*- 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_MHEARTBEAT_H +#define CEPH_MHEARTBEAT_H + +#include "include/types.h" +#include "common/DecayCounter.h" +#include "messages/MMDSOp.h" + +class MHeartbeat final : public MMDSOp { +private: + mds_load_t load; + __s32 beat = 0; + std::map<mds_rank_t, float> import_map; + + public: + const mds_load_t& get_load() const { return load; } + int get_beat() const { return beat; } + + const std::map<mds_rank_t, float>& get_import_map() const { return import_map; } + std::map<mds_rank_t, float>& get_import_map() { return import_map; } + +protected: + MHeartbeat() : MMDSOp(MSG_MDS_HEARTBEAT), load(DecayRate()) {} + MHeartbeat(mds_load_t& load, int beat) + : MMDSOp(MSG_MDS_HEARTBEAT), + load(load), + beat(beat) + {} + ~MHeartbeat() final {} + +public: + std::string_view get_type_name() const override { return "HB"; } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(load, payload); + encode(beat, payload); + encode(import_map, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(load, p); + decode(beat, p); + decode(import_map, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MInodeFileCaps.h b/src/messages/MInodeFileCaps.h new file mode 100644 index 000000000..e2a189ec4 --- /dev/null +++ b/src/messages/MInodeFileCaps.h @@ -0,0 +1,63 @@ +// -*- 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_MINODEFILECAPS_H +#define CEPH_MINODEFILECAPS_H + +#include "messages/MMDSOp.h" + +class MInodeFileCaps final : public MMDSOp { +private: + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; + inodeno_t ino; + __u32 caps = 0; + +public: + inodeno_t get_ino() const { return ino; } + int get_caps() const { return caps; } + +protected: + MInodeFileCaps() : MMDSOp(MSG_MDS_INODEFILECAPS, HEAD_VERSION, COMPAT_VERSION) {} + MInodeFileCaps(inodeno_t ino, int caps) : + MMDSOp(MSG_MDS_INODEFILECAPS, HEAD_VERSION, COMPAT_VERSION) { + this->ino = ino; + this->caps = caps; + } + ~MInodeFileCaps() final {} + +public: + std::string_view get_type_name() const override { return "inode_file_caps";} + void print(std::ostream& out) const override { + out << "inode_file_caps(" << ino << " " << ccap_string(caps) << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(ino, payload); + encode(caps, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(ino, p); + decode(caps, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MKVData.h b/src/messages/MKVData.h new file mode 100644 index 000000000..f735f79d7 --- /dev/null +++ b/src/messages/MKVData.h @@ -0,0 +1,48 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#pragma once + +#include "msg/Message.h" + +class MKVData : public Message { +public: + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; + + version_t version; + std::string prefix; + bool incremental = false; + + // use transparent comparator so we can lookup in it by std::string_view keys + std::map<std::string,boost::optional<bufferlist>,std::less<>> data; + + MKVData() : Message{MSG_KV_DATA, HEAD_VERSION, COMPAT_VERSION} { } + + std::string_view get_type_name() const override { + return "kv_data"; + } + void print(std::ostream& o) const override { + o << "kv_data(v" << version + << " prefix " << prefix << ", " + << (incremental ? "incremental, " : "full, ") + << data.size() << " keys" << ")"; + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(version, p); + decode(prefix, p); + decode(incremental, p); + decode(data, p); + } + + void encode_payload(uint64_t) override { + using ceph::encode; + encode(version, payload); + encode(prefix, payload); + encode(incremental, payload); + encode(data, payload); + } +}; diff --git a/src/messages/MLock.h b/src/messages/MLock.h new file mode 100644 index 000000000..25dd718f8 --- /dev/null +++ b/src/messages/MLock.h @@ -0,0 +1,106 @@ +// -*- 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_MLOCK_H +#define CEPH_MLOCK_H + +#include "mds/locks.h" +#include "mds/SimpleLock.h" +#include "messages/MMDSOp.h" + +class MLock final : public MMDSOp { +private: + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; + + int32_t action = 0; // action type + mds_rank_t asker = 0; // who is initiating this request + metareqid_t reqid; // for remote lock requests + + __u16 lock_type = 0; // lock object type + MDSCacheObjectInfo object_info; + + ceph::buffer::list lockdata; // and possibly some data + +public: + ceph::buffer::list& get_data() { return lockdata; } + const ceph::buffer::list& get_data() const { return lockdata; } + int get_asker() const { return asker; } + int get_action() const { return action; } + metareqid_t get_reqid() const { return reqid; } + + int get_lock_type() const { return lock_type; } + const MDSCacheObjectInfo &get_object_info() const { return object_info; } + MDSCacheObjectInfo &get_object_info() { return object_info; } + +protected: + MLock() : MMDSOp{MSG_MDS_LOCK, HEAD_VERSION, COMPAT_VERSION} {} + MLock(int ac, mds_rank_t as) : + MMDSOp{MSG_MDS_LOCK, HEAD_VERSION, COMPAT_VERSION}, + action(ac), asker(as), + lock_type(0) { } + MLock(SimpleLock *lock, int ac, mds_rank_t as) : + MMDSOp{MSG_MDS_LOCK, HEAD_VERSION, COMPAT_VERSION}, + action(ac), asker(as), + lock_type(lock->get_type()) { + lock->get_parent()->set_object_info(object_info); + } + MLock(SimpleLock *lock, int ac, mds_rank_t as, ceph::buffer::list& bl) : + MMDSOp{MSG_MDS_LOCK, HEAD_VERSION, COMPAT_VERSION}, + action(ac), asker(as), lock_type(lock->get_type()) { + lock->get_parent()->set_object_info(object_info); + lockdata = std::move(bl); + } + ~MLock() final {} + +public: + std::string_view get_type_name() const override { return "ILock"; } + void print(std::ostream& out) const override { + out << "lock(a=" << SimpleLock::get_lock_action_name(action) + << " " << SimpleLock::get_lock_type_name(lock_type) + << " " << object_info + << ")"; + } + + void set_reqid(metareqid_t ri) { reqid = ri; } + void set_data(const ceph::buffer::list& lockdata) { + this->lockdata = lockdata; + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(asker, p); + decode(action, p); + decode(reqid, p); + decode(lock_type, p); + decode(object_info, p); + decode(lockdata, p); + } + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(asker, payload); + encode(action, payload); + encode(reqid, payload); + encode(lock_type, payload); + encode(object_info, payload); + encode(lockdata, payload); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MLog.h b/src/messages/MLog.h new file mode 100644 index 000000000..e38aab904 --- /dev/null +++ b/src/messages/MLog.h @@ -0,0 +1,60 @@ +// -*- 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_MLOG_H +#define CEPH_MLOG_H + +#include "common/LogEntry.h" +#include "messages/PaxosServiceMessage.h" + +#include <deque> + +class MLog final : public PaxosServiceMessage { +public: + uuid_d fsid; + std::deque<LogEntry> entries; + + MLog() : PaxosServiceMessage{MSG_LOG, 0} {} + MLog(const uuid_d& f, std::deque<LogEntry>&& e) + : PaxosServiceMessage{MSG_LOG, 0}, fsid(f), entries{std::move(e)} { } + MLog(const uuid_d& f) : PaxosServiceMessage(MSG_LOG, 0), fsid(f) { } +private: + ~MLog() final {} + +public: + std::string_view get_type_name() const override { return "log"; } + void print(std::ostream& out) const override { + out << "log("; + if (entries.size()) + out << entries.size() << " entries from seq " << entries.front().seq + << " at " << entries.front().stamp; + out << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + paxos_encode(); + encode(fsid, payload); + encode(entries, payload, features); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + paxos_decode(p); + decode(fsid, p); + decode(entries, p); + } +}; + +#endif diff --git a/src/messages/MLogAck.h b/src/messages/MLogAck.h new file mode 100644 index 000000000..5949157e2 --- /dev/null +++ b/src/messages/MLogAck.h @@ -0,0 +1,62 @@ +// -*- 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_MLOGACK_H +#define CEPH_MLOGACK_H + +#include <iostream> +#include <string> +#include <string_view> + +#include "include/uuid.h" + +#include "msg/Message.h" + +class MLogAck final : public Message { +public: + uuid_d fsid; + version_t last = 0; + std::string channel; + + MLogAck() : Message{MSG_LOGACK} {} + MLogAck(uuid_d& f, version_t l) : Message{MSG_LOGACK}, fsid(f), last(l) {} +private: + ~MLogAck() final {} + +public: + std::string_view get_type_name() const override { return "log_ack"; } + void print(std::ostream& out) const override { + out << "log(last " << last << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(fsid, payload); + encode(last, payload); + encode(channel, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(fsid, p); + decode(last, p); + if (!p.end()) + decode(channel, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MMDSBeacon.h b/src/messages/MMDSBeacon.h new file mode 100644 index 000000000..bd46926e4 --- /dev/null +++ b/src/messages/MMDSBeacon.h @@ -0,0 +1,324 @@ +// -*- 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_MMDSBEACON_H +#define CEPH_MMDSBEACON_H + +#include <string_view> + +#include "msg/Message.h" +#include "messages/PaxosServiceMessage.h" + +#include "include/types.h" + +#include "mds/MDSMap.h" + + + +/** + * Unique ID for each type of metric we can send to the mon, so that if the mon + * knows about the IDs then it can implement special behaviour for certain + * messages. + */ +enum mds_metric_t { + MDS_HEALTH_NULL = 0, + MDS_HEALTH_TRIM, + MDS_HEALTH_CLIENT_RECALL, + MDS_HEALTH_CLIENT_LATE_RELEASE, + MDS_HEALTH_CLIENT_RECALL_MANY, + MDS_HEALTH_CLIENT_LATE_RELEASE_MANY, + MDS_HEALTH_CLIENT_OLDEST_TID, + MDS_HEALTH_CLIENT_OLDEST_TID_MANY, + MDS_HEALTH_DAMAGE, + MDS_HEALTH_READ_ONLY, + MDS_HEALTH_SLOW_REQUEST, + MDS_HEALTH_CACHE_OVERSIZED, + MDS_HEALTH_SLOW_METADATA_IO, + MDS_HEALTH_DUMMY, // not a real health warning, for testing +}; + +inline const char *mds_metric_name(mds_metric_t m) +{ + switch (m) { + case MDS_HEALTH_TRIM: return "MDS_TRIM"; + case MDS_HEALTH_CLIENT_RECALL: return "MDS_CLIENT_RECALL"; + case MDS_HEALTH_CLIENT_LATE_RELEASE: return "MDS_CLIENT_LATE_RELEASE"; + case MDS_HEALTH_CLIENT_RECALL_MANY: return "MDS_CLIENT_RECALL_MANY"; + case MDS_HEALTH_CLIENT_LATE_RELEASE_MANY: return "MDS_CLIENT_LATE_RELEASE_MANY"; + case MDS_HEALTH_CLIENT_OLDEST_TID: return "MDS_CLIENT_OLDEST_TID"; + case MDS_HEALTH_CLIENT_OLDEST_TID_MANY: return "MDS_CLIENT_OLDEST_TID_MANY"; + case MDS_HEALTH_DAMAGE: return "MDS_DAMAGE"; + case MDS_HEALTH_READ_ONLY: return "MDS_READ_ONLY"; + case MDS_HEALTH_SLOW_REQUEST: return "MDS_SLOW_REQUEST"; + case MDS_HEALTH_CACHE_OVERSIZED: return "MDS_CACHE_OVERSIZED"; + case MDS_HEALTH_SLOW_METADATA_IO: return "MDS_SLOW_METADATA_IO"; + case MDS_HEALTH_DUMMY: return "MDS_DUMMY"; + default: + return "???"; + } +} + +inline const char *mds_metric_summary(mds_metric_t m) +{ + switch (m) { + case MDS_HEALTH_TRIM: + return "%num% MDSs behind on trimming"; + case MDS_HEALTH_CLIENT_RECALL: + return "%num% clients failing to respond to cache pressure"; + case MDS_HEALTH_CLIENT_LATE_RELEASE: + return "%num% clients failing to respond to capability release"; + case MDS_HEALTH_CLIENT_RECALL_MANY: + return "%num% MDSs have many clients failing to respond to cache pressure"; + case MDS_HEALTH_CLIENT_LATE_RELEASE_MANY: + return "%num% MDSs have many clients failing to respond to capability " + "release"; + case MDS_HEALTH_CLIENT_OLDEST_TID: + return "%num% clients failing to advance oldest client/flush tid"; + case MDS_HEALTH_CLIENT_OLDEST_TID_MANY: + return "%num% MDSs have clients failing to advance oldest client/flush tid"; + case MDS_HEALTH_DAMAGE: + return "%num% MDSs report damaged metadata"; + case MDS_HEALTH_READ_ONLY: + return "%num% MDSs are read only"; + case MDS_HEALTH_SLOW_REQUEST: + return "%num% MDSs report slow requests"; + case MDS_HEALTH_CACHE_OVERSIZED: + return "%num% MDSs report oversized cache"; + case MDS_HEALTH_SLOW_METADATA_IO: + return "%num% MDSs report slow metadata IOs"; + default: + return "???"; + } +} + +/** + * This structure is designed to allow some flexibility in how we emit health + * complaints, such that: + * - The mon doesn't have to have foreknowledge of all possible metrics: we can + * implement new messages in the MDS and have the mon pass them through to the user + * (enables us to do complex checks inside the MDS, and allows mon to be older version + * than MDS) + * - The mon has enough information to perform reductions on some types of metric, for + * example complaints about the same client from multiple MDSs where we might want + * to reduce three "client X is stale on MDS y" metrics into one "client X is stale + * on 3 MDSs" message. + */ +struct MDSHealthMetric +{ + mds_metric_t type; + health_status_t sev; + std::string message; + std::map<std::string, std::string> metadata; + + void encode(ceph::buffer::list& bl) const { + ENCODE_START(1, 1, bl); + ceph_assert(type != MDS_HEALTH_NULL); + encode((uint16_t)type, bl); + encode((uint8_t)sev, bl); + encode(message, bl); + encode(metadata, bl); + ENCODE_FINISH(bl); + } + + void decode(ceph::buffer::list::const_iterator& bl) { + DECODE_START(1, bl); + uint16_t raw_type; + decode(raw_type, bl); + type = (mds_metric_t)raw_type; + ceph_assert(type != MDS_HEALTH_NULL); + uint8_t raw_sev; + decode(raw_sev, bl); + sev = (health_status_t)raw_sev; + decode(message, bl); + decode(metadata, bl); + DECODE_FINISH(bl); + } + + bool operator==(MDSHealthMetric const &other) const + { + return (type == other.type && sev == other.sev && message == other.message); + } + + MDSHealthMetric() : type(MDS_HEALTH_NULL), sev(HEALTH_OK) {} + MDSHealthMetric(mds_metric_t type_, health_status_t sev_, std::string_view message_) + : type(type_), sev(sev_), message(message_) {} +}; +WRITE_CLASS_ENCODER(MDSHealthMetric) + + +/** + * Health metrics send by the MDS to the mon, so that the mon can generate + * user friendly warnings about undesirable states. + */ +struct MDSHealth +{ + std::vector<MDSHealthMetric> metrics; + + void encode(ceph::buffer::list& bl) const { + ENCODE_START(1, 1, bl); + encode(metrics, bl); + ENCODE_FINISH(bl); + } + + void decode(ceph::buffer::list::const_iterator& bl) { + DECODE_START(1, bl); + decode(metrics, bl); + DECODE_FINISH(bl); + } + + bool operator==(MDSHealth const &other) const + { + return metrics == other.metrics; + } +}; +WRITE_CLASS_ENCODER(MDSHealth) + + +class MMDSBeacon final : public PaxosServiceMessage { +private: + + static constexpr int HEAD_VERSION = 8; + static constexpr int COMPAT_VERSION = 6; + + uuid_d fsid; + mds_gid_t global_id = MDS_GID_NONE; + std::string name; + + MDSMap::DaemonState state = MDSMap::STATE_NULL; + version_t seq = 0; + + CompatSet compat; + + MDSHealth health; + + std::map<std::string, std::string> sys_info; + + uint64_t mds_features = 0; + + std::string fs; + +protected: + MMDSBeacon() : PaxosServiceMessage(MSG_MDS_BEACON, 0, HEAD_VERSION, COMPAT_VERSION) + { + set_priority(CEPH_MSG_PRIO_HIGH); + } + MMDSBeacon(const uuid_d &f, mds_gid_t g, const std::string& n, epoch_t les, + MDSMap::DaemonState st, version_t se, uint64_t feat) : + PaxosServiceMessage(MSG_MDS_BEACON, les, HEAD_VERSION, COMPAT_VERSION), + fsid(f), global_id(g), name(n), state(st), seq(se), + mds_features(feat) { + set_priority(CEPH_MSG_PRIO_HIGH); + } + ~MMDSBeacon() final {} + +public: + const uuid_d& get_fsid() const { return fsid; } + mds_gid_t get_global_id() const { return global_id; } + const std::string& get_name() const { return name; } + epoch_t get_last_epoch_seen() const { return version; } + MDSMap::DaemonState get_state() const { return state; } + version_t get_seq() const { return seq; } + std::string_view get_type_name() const override { return "mdsbeacon"; } + uint64_t get_mds_features() const { return mds_features; } + + CompatSet const& get_compat() const { return compat; } + void set_compat(const CompatSet& c) { compat = c; } + + MDSHealth const& get_health() const { return health; } + void set_health(const MDSHealth &h) { health = h; } + + const std::string& get_fs() const { return fs; } + void set_fs(std::string_view s) { fs = s; } + + const std::map<std::string, std::string>& get_sys_info() const { return sys_info; } + void set_sys_info(const std::map<std::string, std::string>& i) { sys_info = i; } + + void print(std::ostream& out) const override { + out << "mdsbeacon(" << global_id << "/" << name + << " " << ceph_mds_state_name(state); + if (fs.size()) { + out << " fs=" << fs; + } + out << " seq=" << seq << " v" << version << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + paxos_encode(); + encode(fsid, payload); + encode(global_id, payload); + encode((__u32)state, payload); + encode(seq, payload); + encode(name, payload); + encode(MDS_RANK_NONE, payload); + encode(std::string(), payload); + encode(compat, payload); + encode(health, payload); + if (state == MDSMap::STATE_BOOT) { + encode(sys_info, payload); + } + encode(mds_features, payload); + encode(FS_CLUSTER_ID_NONE, payload); + encode(false, payload); + encode(fs, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + paxos_decode(p); + decode(fsid, p); + decode(global_id, p); + __u32 raw_state; + decode(raw_state, p); + state = (MDSMap::DaemonState)raw_state; + decode(seq, p); + decode(name, p); + { + mds_rank_t standby_for_rank; + decode(standby_for_rank, p); + } + { + std::string standby_for_name; + decode(standby_for_name, p); + } + decode(compat, p); + decode(health, p); + if (state == MDSMap::STATE_BOOT) { + decode(sys_info, p); + } + decode(mds_features, p); + { + fs_cluster_id_t standby_for_fscid; + decode(standby_for_fscid, p); + } + if (header.version >= 7) { + bool standby_replay; + decode(standby_replay, p); + } + + if (header.version < 7 && state == MDSMap::STATE_STANDBY_REPLAY) { + // Old MDS daemons request the state, instead of explicitly + // advertising that they are configured as a replay daemon. + state = MDSMap::STATE_STANDBY; + } + if (header.version >= 8) { + decode(fs, p); + } + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MMDSCacheRejoin.h b/src/messages/MMDSCacheRejoin.h new file mode 100644 index 000000000..6f13ccd10 --- /dev/null +++ b/src/messages/MMDSCacheRejoin.h @@ -0,0 +1,366 @@ +// -*- 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_MMDSCACHEREJOIN_H +#define CEPH_MMDSCACHEREJOIN_H + +#include <string_view> +#include "include/types.h" +#include "mds/CInode.h" +#include "mds/CDir.h" +#include "mds/mdstypes.h" +#include "messages/MMDSOp.h" + +// sent from replica to auth + +class MMDSCacheRejoin final : public MMDSOp { +public: + static constexpr int OP_WEAK = 1; // replica -> auth, i exist, + maybe open files. + static constexpr int OP_STRONG = 2; // replica -> auth, i exist, + open files and lock state. + static constexpr int OP_ACK = 3; // auth -> replica, here is your lock state. + static const char *get_opname(int op) { + switch (op) { + case OP_WEAK: return "weak"; + case OP_STRONG: return "strong"; + case OP_ACK: return "ack"; + default: ceph_abort(); return 0; + } + } + + // -- types -- + struct inode_strong { + uint32_t nonce = 0; + int32_t caps_wanted = 0; + int32_t filelock = 0, nestlock = 0, dftlock = 0; + inode_strong() {} + inode_strong(int n, int cw, int dl, int nl, int dftl) : + nonce(n), caps_wanted(cw), + filelock(dl), nestlock(nl), dftlock(dftl) { } + void encode(ceph::buffer::list &bl) const { + using ceph::encode; + encode(nonce, bl); + encode(caps_wanted, bl); + encode(filelock, bl); + encode(nestlock, bl); + encode(dftlock, bl); + } + void decode(ceph::buffer::list::const_iterator &bl) { + using ceph::decode; + decode(nonce, bl); + decode(caps_wanted, bl); + decode(filelock, bl); + decode(nestlock, bl); + decode(dftlock, bl); + } + }; + WRITE_CLASS_ENCODER(inode_strong) + + struct dirfrag_strong { + uint32_t nonce = 0; + int8_t dir_rep = 0; + dirfrag_strong() {} + dirfrag_strong(int n, int dr) : nonce(n), dir_rep(dr) {} + void encode(ceph::buffer::list &bl) const { + using ceph::encode; + encode(nonce, bl); + encode(dir_rep, bl); + } + void decode(ceph::buffer::list::const_iterator &bl) { + using ceph::decode; + decode(nonce, bl); + decode(dir_rep, bl); + } + }; + WRITE_CLASS_ENCODER(dirfrag_strong) + + struct dn_strong { + snapid_t first; + std::string alternate_name; + inodeno_t ino = 0; + inodeno_t remote_ino = 0; + unsigned char remote_d_type = 0; + uint32_t nonce = 0; + int32_t lock = 0; + dn_strong() = default; + dn_strong(snapid_t f, std::string_view altn, inodeno_t pi, inodeno_t ri, unsigned char rdt, int n, int l) : + first(f), alternate_name(altn), ino(pi), remote_ino(ri), remote_d_type(rdt), nonce(n), lock(l) {} + bool is_primary() const { return ino > 0; } + bool is_remote() const { return remote_ino > 0; } + bool is_null() const { return ino == 0 && remote_ino == 0; } + void encode(ceph::buffer::list &bl) const { + using ceph::encode; + encode(first, bl); + encode(ino, bl); + encode(remote_ino, bl); + encode(remote_d_type, bl); + encode(nonce, bl); + encode(lock, bl); + encode(alternate_name, bl); + } + void decode(ceph::buffer::list::const_iterator &bl) { + using ceph::decode; + decode(first, bl); + decode(ino, bl); + decode(remote_ino, bl); + decode(remote_d_type, bl); + decode(nonce, bl); + decode(lock, bl); + decode(alternate_name, bl); + } + }; + WRITE_CLASS_ENCODER(dn_strong) + + struct dn_weak { + snapid_t first; + inodeno_t ino = 0; + dn_weak() = default; + dn_weak(snapid_t f, inodeno_t pi) : first(f), ino(pi) {} + void encode(ceph::buffer::list &bl) const { + using ceph::encode; + encode(first, bl); + encode(ino, bl); + } + void decode(ceph::buffer::list::const_iterator &bl) { + using ceph::decode; + decode(first, bl); + decode(ino, bl); + } + }; + WRITE_CLASS_ENCODER(dn_weak) + + struct lock_bls { + ceph::buffer::list file, nest, dft; + void encode(ceph::buffer::list& bl) const { + using ceph::encode; + encode(file, bl); + encode(nest, bl); + encode(dft, bl); + } + void decode(ceph::buffer::list::const_iterator& bl) { + using ceph::decode; + decode(file, bl); + decode(nest, bl); + decode(dft, bl); + } + }; + WRITE_CLASS_ENCODER(lock_bls) + + // authpins, xlocks + struct peer_reqid { + metareqid_t reqid; + __u32 attempt; + peer_reqid() : attempt(0) {} + peer_reqid(const metareqid_t& r, __u32 a) + : reqid(r), attempt(a) {} + void encode(ceph::buffer::list& bl) const { + using ceph::encode; + encode(reqid, bl); + encode(attempt, bl); + } + void decode(ceph::buffer::list::const_iterator& bl) { + using ceph::decode; + decode(reqid, bl); + decode(attempt, bl); + } + }; + + std::string_view get_type_name() const override { return "cache_rejoin"; } + void print(std::ostream& out) const override { + out << "cache_rejoin " << get_opname(op); + } + + // -- builders -- + // inodes + void add_weak_inode(vinodeno_t i) { + weak_inodes.insert(i); + } + void add_strong_inode(vinodeno_t i, int n, int cw, int dl, int nl, int dftl) { + strong_inodes[i] = inode_strong(n, cw, dl, nl, dftl); + } + void add_inode_locks(CInode *in, __u32 nonce, ceph::buffer::list& bl) { + using ceph::encode; + encode(in->ino(), inode_locks); + encode(in->last, inode_locks); + encode(nonce, inode_locks); + encode(bl, inode_locks); + } + void add_inode_base(CInode *in, uint64_t features) { + using ceph::encode; + encode(in->ino(), inode_base); + encode(in->last, inode_base); + ceph::buffer::list bl; + in->_encode_base(bl, features); + encode(bl, inode_base); + } + void add_inode_authpin(vinodeno_t ino, const metareqid_t& ri, __u32 attempt) { + authpinned_inodes[ino].push_back(peer_reqid(ri, attempt)); + } + void add_inode_frozen_authpin(vinodeno_t ino, const metareqid_t& ri, __u32 attempt) { + frozen_authpin_inodes[ino] = peer_reqid(ri, attempt); + } + void add_inode_xlock(vinodeno_t ino, int lt, const metareqid_t& ri, __u32 attempt) { + xlocked_inodes[ino][lt] = peer_reqid(ri, attempt); + } + void add_inode_wrlock(vinodeno_t ino, int lt, const metareqid_t& ri, __u32 attempt) { + wrlocked_inodes[ino][lt].push_back(peer_reqid(ri, attempt)); + } + + void add_scatterlock_state(CInode *in) { + if (inode_scatterlocks.count(in->ino())) + return; // already added this one + in->encode_lock_state(CEPH_LOCK_IFILE, inode_scatterlocks[in->ino()].file); + in->encode_lock_state(CEPH_LOCK_INEST, inode_scatterlocks[in->ino()].nest); + in->encode_lock_state(CEPH_LOCK_IDFT, inode_scatterlocks[in->ino()].dft); + } + + // dirfrags + void add_strong_dirfrag(dirfrag_t df, int n, int dr) { + strong_dirfrags[df] = dirfrag_strong(n, dr); + } + void add_dirfrag_base(CDir *dir) { + ceph::buffer::list& bl = dirfrag_bases[dir->dirfrag()]; + dir->_encode_base(bl); + } + + // dentries + void add_weak_dirfrag(dirfrag_t df) { + weak_dirfrags.insert(df); + } + void add_weak_dentry(inodeno_t dirino, std::string_view dname, snapid_t last, dn_weak& dnw) { + weak[dirino][string_snap_t(dname, last)] = dnw; + } + void add_weak_primary_dentry(inodeno_t dirino, std::string_view dname, snapid_t first, snapid_t last, inodeno_t ino) { + weak[dirino][string_snap_t(dname, last)] = dn_weak(first, ino); + } + void add_strong_dentry(dirfrag_t df, std::string_view dname, std::string_view altn, snapid_t first, snapid_t last, inodeno_t pi, inodeno_t ri, unsigned char rdt, int n, int ls) { + auto& m = strong_dentries[df]; + m.insert_or_assign(string_snap_t(dname, last), dn_strong(first, altn, pi, ri, rdt, n, ls)); + } + void add_dentry_authpin(dirfrag_t df, std::string_view dname, snapid_t last, + const metareqid_t& ri, __u32 attempt) { + authpinned_dentries[df][string_snap_t(dname, last)].push_back(peer_reqid(ri, attempt)); + } + void add_dentry_xlock(dirfrag_t df, std::string_view dname, snapid_t last, + const metareqid_t& ri, __u32 attempt) { + xlocked_dentries[df][string_snap_t(dname, last)] = peer_reqid(ri, attempt); + } + + // -- encoding -- + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(op, payload); + encode(strong_inodes, payload); + encode(inode_base, payload); + encode(inode_locks, payload); + encode(inode_scatterlocks, payload); + encode(authpinned_inodes, payload); + encode(frozen_authpin_inodes, payload); + encode(xlocked_inodes, payload); + encode(wrlocked_inodes, payload); + encode(cap_exports, payload); + encode(client_map, payload, features); + encode(imported_caps, payload); + encode(strong_dirfrags, payload); + encode(dirfrag_bases, payload); + encode(weak, payload); + encode(weak_dirfrags, payload); + encode(weak_inodes, payload); + encode(strong_dentries, payload); + encode(authpinned_dentries, payload); + encode(xlocked_dentries, payload); + encode(client_metadata_map, payload); + } + void decode_payload() override { + auto p = payload.cbegin(); + using ceph::decode; + decode(op, p); + decode(strong_inodes, p); + decode(inode_base, p); + decode(inode_locks, p); + decode(inode_scatterlocks, p); + decode(authpinned_inodes, p); + decode(frozen_authpin_inodes, p); + decode(xlocked_inodes, p); + decode(wrlocked_inodes, p); + decode(cap_exports, p); + decode(client_map, p); + decode(imported_caps, p); + decode(strong_dirfrags, p); + decode(dirfrag_bases, p); + decode(weak, p); + decode(weak_dirfrags, p); + decode(weak_inodes, p); + decode(strong_dentries, p); + decode(authpinned_dentries, p); + decode(xlocked_dentries, p); + if (header.version >= 2) + decode(client_metadata_map, p); + } + + // -- data -- + int32_t op = 0; + + // weak + std::map<inodeno_t, std::map<string_snap_t, dn_weak> > weak; + std::set<dirfrag_t> weak_dirfrags; + std::set<vinodeno_t> weak_inodes; + std::map<inodeno_t, lock_bls> inode_scatterlocks; + + // strong + std::map<dirfrag_t, dirfrag_strong> strong_dirfrags; + std::map<dirfrag_t, std::map<string_snap_t, dn_strong> > strong_dentries; + std::map<vinodeno_t, inode_strong> strong_inodes; + + // open + std::map<inodeno_t,std::map<client_t, cap_reconnect_t> > cap_exports; + std::map<client_t, entity_inst_t> client_map; + std::map<client_t,client_metadata_t> client_metadata_map; + ceph::buffer::list imported_caps; + + // full + ceph::buffer::list inode_base; + ceph::buffer::list inode_locks; + std::map<dirfrag_t, ceph::buffer::list> dirfrag_bases; + + std::map<vinodeno_t, std::list<peer_reqid> > authpinned_inodes; + std::map<vinodeno_t, peer_reqid> frozen_authpin_inodes; + std::map<vinodeno_t, std::map<__s32, peer_reqid> > xlocked_inodes; + std::map<vinodeno_t, std::map<__s32, std::list<peer_reqid> > > wrlocked_inodes; + std::map<dirfrag_t, std::map<string_snap_t, std::list<peer_reqid> > > authpinned_dentries; + std::map<dirfrag_t, std::map<string_snap_t, peer_reqid> > xlocked_dentries; + +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); + + static constexpr int HEAD_VERSION = 2; + static constexpr int COMPAT_VERSION = 1; + + MMDSCacheRejoin(int o) : MMDSCacheRejoin() { op = o; } + MMDSCacheRejoin() : MMDSOp{MSG_MDS_CACHEREJOIN, HEAD_VERSION, COMPAT_VERSION} {} + ~MMDSCacheRejoin() final {} +}; + +WRITE_CLASS_ENCODER(MMDSCacheRejoin::inode_strong) +WRITE_CLASS_ENCODER(MMDSCacheRejoin::dirfrag_strong) +WRITE_CLASS_ENCODER(MMDSCacheRejoin::dn_strong) +WRITE_CLASS_ENCODER(MMDSCacheRejoin::dn_weak) +WRITE_CLASS_ENCODER(MMDSCacheRejoin::lock_bls) +WRITE_CLASS_ENCODER(MMDSCacheRejoin::peer_reqid) + +inline std::ostream& operator<<(std::ostream& out, const MMDSCacheRejoin::peer_reqid& r) { + return out << r.reqid << '.' << r.attempt; +} + +#endif diff --git a/src/messages/MMDSFindIno.h b/src/messages/MMDSFindIno.h new file mode 100644 index 000000000..09f8e72ff --- /dev/null +++ b/src/messages/MMDSFindIno.h @@ -0,0 +1,55 @@ +// -*- 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) 2011 New Dream Network + * + * 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_MDSFINDINO_H +#define CEPH_MDSFINDINO_H + +#include "include/filepath.h" +#include "messages/MMDSOp.h" + +class MMDSFindIno final : public MMDSOp { + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; +public: + ceph_tid_t tid {0}; + inodeno_t ino; + +protected: + MMDSFindIno() : MMDSOp{MSG_MDS_FINDINO, HEAD_VERSION, COMPAT_VERSION} {} + MMDSFindIno(ceph_tid_t t, inodeno_t i) : MMDSOp{MSG_MDS_FINDINO, HEAD_VERSION, COMPAT_VERSION}, tid(t), ino(i) {} + ~MMDSFindIno() final {} + +public: + std::string_view get_type_name() const override { return "findino"; } + void print(std::ostream &out) const override { + out << "findino(" << tid << " " << ino << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(tid, payload); + encode(ino, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(tid, p); + decode(ino, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MMDSFindInoReply.h b/src/messages/MMDSFindInoReply.h new file mode 100644 index 000000000..eef8e6926 --- /dev/null +++ b/src/messages/MMDSFindInoReply.h @@ -0,0 +1,55 @@ +// -*- 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) 2011 New Dream Network + * + * 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_MDSFINDINOREPLY_H +#define CEPH_MDSFINDINOREPLY_H + +#include "include/filepath.h" +#include "messages/MMDSOp.h" + +class MMDSFindInoReply final : public MMDSOp { + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; +public: + ceph_tid_t tid = 0; + filepath path; + +protected: + MMDSFindInoReply() : MMDSOp{MSG_MDS_FINDINOREPLY, HEAD_VERSION, COMPAT_VERSION} {} + MMDSFindInoReply(ceph_tid_t t) : MMDSOp{MSG_MDS_FINDINOREPLY, HEAD_VERSION, COMPAT_VERSION}, tid(t) {} + ~MMDSFindInoReply() final {} + +public: + std::string_view get_type_name() const override { return "findinoreply"; } + void print(std::ostream &out) const override { + out << "findinoreply(" << tid << " " << path << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(tid, payload); + encode(path, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(tid, p); + decode(path, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MMDSFragmentNotify.h b/src/messages/MMDSFragmentNotify.h new file mode 100644 index 000000000..7ae5829f9 --- /dev/null +++ b/src/messages/MMDSFragmentNotify.h @@ -0,0 +1,76 @@ +// -*- 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_MMDSFRAGMENTNOTIFY_H +#define CEPH_MMDSFRAGMENTNOTIFY_H + +#include "messages/MMDSOp.h" + +class MMDSFragmentNotify final : public MMDSOp { +private: + static constexpr int HEAD_VERSION = 2; + static constexpr int COMPAT_VERSION = 1; + + dirfrag_t base_dirfrag; + int8_t bits = 0; + bool ack_wanted = false; + + public: + inodeno_t get_ino() const { return base_dirfrag.ino; } + frag_t get_basefrag() const { return base_dirfrag.frag; } + dirfrag_t get_base_dirfrag() const { return base_dirfrag; } + int get_bits() const { return bits; } + bool is_ack_wanted() const { return ack_wanted; } + void mark_ack_wanted() { ack_wanted = true; } + + ceph::buffer::list basebl; + +protected: + MMDSFragmentNotify() : + MMDSOp{MSG_MDS_FRAGMENTNOTIFY, HEAD_VERSION, COMPAT_VERSION} {} + MMDSFragmentNotify(dirfrag_t df, int b, uint64_t tid) : + MMDSOp{MSG_MDS_FRAGMENTNOTIFY, HEAD_VERSION, COMPAT_VERSION}, + base_dirfrag(df), bits(b) { + set_tid(tid); + } + ~MMDSFragmentNotify() final {} + +public: + std::string_view get_type_name() const override { return "fragment_notify"; } + void print(std::ostream& o) const override { + o << "fragment_notify(" << base_dirfrag << " " << (int)bits << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(base_dirfrag, payload); + encode(bits, payload); + encode(basebl, payload); + encode(ack_wanted, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(base_dirfrag, p); + decode(bits, p); + decode(basebl, p); + if (header.version >= 2) + decode(ack_wanted, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MMDSFragmentNotifyAck.h b/src/messages/MMDSFragmentNotifyAck.h new file mode 100644 index 000000000..4d60a732e --- /dev/null +++ b/src/messages/MMDSFragmentNotifyAck.h @@ -0,0 +1,62 @@ +// -*- 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_MMDSFRAGMENTNOTIFYAck_H +#define CEPH_MMDSFRAGMENTNOTIFYAck_H + +#include "messages/MMDSOp.h" + +class MMDSFragmentNotifyAck final : public MMDSOp { +private: + dirfrag_t base_dirfrag; + int8_t bits = 0; + + public: + dirfrag_t get_base_dirfrag() const { return base_dirfrag; } + int get_bits() const { return bits; } + + ceph::buffer::list basebl; + +protected: + MMDSFragmentNotifyAck() : MMDSOp{MSG_MDS_FRAGMENTNOTIFYACK} {} + MMDSFragmentNotifyAck(dirfrag_t df, int b, uint64_t tid) : + MMDSOp{MSG_MDS_FRAGMENTNOTIFYACK}, + base_dirfrag(df), bits(b) { + set_tid(tid); + } + ~MMDSFragmentNotifyAck() final {} + +public: + std::string_view get_type_name() const override { return "fragment_notify_ack"; } + void print(std::ostream& o) const override { + o << "fragment_notify_ack(" << base_dirfrag << " " << (int)bits << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(base_dirfrag, payload); + encode(bits, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(base_dirfrag, p); + decode(bits, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MMDSLoadTargets.h b/src/messages/MMDSLoadTargets.h new file mode 100644 index 000000000..bab923db0 --- /dev/null +++ b/src/messages/MMDSLoadTargets.h @@ -0,0 +1,63 @@ +// -*- 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) 2009 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_MMDSLoadTargets_H +#define CEPH_MMDSLoadTargets_H + +#include "msg/Message.h" +#include "mds/mdstypes.h" +#include "messages/PaxosServiceMessage.h" +#include "include/types.h" + +#include <map> +using std::map; + +class MMDSLoadTargets final : public PaxosServiceMessage { +public: + mds_gid_t global_id; + std::set<mds_rank_t> targets; + +protected: + MMDSLoadTargets() : PaxosServiceMessage(MSG_MDS_OFFLOAD_TARGETS, 0) {} + MMDSLoadTargets(mds_gid_t g, std::set<mds_rank_t>& mds_targets) : + PaxosServiceMessage(MSG_MDS_OFFLOAD_TARGETS, 0), + global_id(g), targets(mds_targets) {} + ~MMDSLoadTargets() final {} + +public: + std::string_view get_type_name() const override { return "mds_load_targets"; } + void print(std::ostream& o) const override { + o << "mds_load_targets(" << global_id << " " << targets << ")"; + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + paxos_decode(p); + decode(global_id, p); + decode(targets, p); + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + paxos_encode(); + encode(global_id, payload); + encode(targets, payload); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MMDSMap.h b/src/messages/MMDSMap.h new file mode 100644 index 000000000..c3bf2bc5a --- /dev/null +++ b/src/messages/MMDSMap.h @@ -0,0 +1,89 @@ +// -*- 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_MMDSMAP_H +#define CEPH_MMDSMAP_H + +#include "msg/Message.h" +#include "mds/MDSMap.h" +#include "include/ceph_features.h" + +class MMDSMap final : public SafeMessage { +private: + static constexpr int HEAD_VERSION = 2; + static constexpr int COMPAT_VERSION = 1; +public: + uuid_d fsid; + epoch_t epoch = 0; + ceph::buffer::list encoded; + std::string map_fs_name; + + version_t get_epoch() const { return epoch; } + const ceph::buffer::list& get_encoded() const { return encoded; } + +protected: + MMDSMap() : + SafeMessage{CEPH_MSG_MDS_MAP, HEAD_VERSION, COMPAT_VERSION} {} + + MMDSMap(const uuid_d &f, const MDSMap &mm, + const std::string mf = std::string()) : + SafeMessage{CEPH_MSG_MDS_MAP, HEAD_VERSION, COMPAT_VERSION}, + fsid(f), map_fs_name(mf) { + epoch = mm.get_epoch(); + mm.encode(encoded, -1); // we will reencode with fewer features as necessary + } + + ~MMDSMap() final {} + +public: + std::string_view get_type_name() const override { return "mdsmap"; } + void print(std::ostream& out) const override { + out << "mdsmap(e " << epoch << ")"; + } + + // marshalling + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(fsid, p); + decode(epoch, p); + decode(encoded, p); + if (header.version >= 2) { + decode(map_fs_name, p); + } + } + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(fsid, payload); + encode(epoch, payload); + if ((features & CEPH_FEATURE_PGID64) == 0 || + (features & CEPH_FEATURE_MDSENC) == 0 || + (features & CEPH_FEATURE_MSG_ADDR2) == 0 || + !HAVE_FEATURE(features, SERVER_NAUTILUS)) { + // reencode for old clients. + MDSMap m; + m.decode(encoded); + encoded.clear(); + m.encode(encoded, features); + } + encode(encoded, payload); + encode(map_fs_name, payload); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MMDSMetrics.h b/src/messages/MMDSMetrics.h new file mode 100644 index 000000000..1cb741880 --- /dev/null +++ b/src/messages/MMDSMetrics.h @@ -0,0 +1,53 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef CEPH_MDS_METRICS_H +#define CEPH_MDS_METRICS_H + +#include "messages/MMDSOp.h" +#include "mds/MDSPerfMetricTypes.h" + +class MMDSMetrics final : public MMDSOp { +private: + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; +public: + // metrics messsage (client -> metrics map, rank, etc..) + metrics_message_t metrics_message; + +protected: + MMDSMetrics() : MMDSOp(MSG_MDS_METRICS, HEAD_VERSION, COMPAT_VERSION) { + } + MMDSMetrics(metrics_message_t metrics_message) + : MMDSOp(MSG_MDS_METRICS, HEAD_VERSION, COMPAT_VERSION), + metrics_message(metrics_message) { + } + ~MMDSMetrics() final {} + +public: + std::string_view get_type_name() const override { + return "mds_metrics"; + } + + void print(ostream &out) const override { + out << "mds_metrics from rank=" << metrics_message.rank << " carrying " + << metrics_message.client_metrics_map.size() << " metric updates"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(metrics_message, payload, features); + } + + void decode_payload() override { + using ceph::decode; + auto iter = payload.cbegin(); + decode(metrics_message, iter); + } + +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif // CEPH_MDS_METRICS_H diff --git a/src/messages/MMDSOp.h b/src/messages/MMDSOp.h new file mode 100644 index 000000000..53a67ea85 --- /dev/null +++ b/src/messages/MMDSOp.h @@ -0,0 +1,15 @@ +#pragma once + +#include "msg/Message.h" + +/* + * MMDSOp is used to ensure that all incoming MDS-MDS + * messages in MDSRankDispatcher are versioned. Therefore + * all MDS-MDS messages must be of type MMDSOp. + */ +class MMDSOp : public SafeMessage { +public: + template<typename... Types> + MMDSOp(Types&&... args) + : SafeMessage(std::forward<Types>(args)...) {} +}; diff --git a/src/messages/MMDSOpenIno.h b/src/messages/MMDSOpenIno.h new file mode 100644 index 000000000..b51795338 --- /dev/null +++ b/src/messages/MMDSOpenIno.h @@ -0,0 +1,59 @@ +// -*- 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) 2011 New Dream Network + * + * 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_MDSOPENINO_H +#define CEPH_MDSOPENINO_H + +#include "messages/MMDSOp.h" + +class MMDSOpenIno final : public MMDSOp { + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; +public: + inodeno_t ino; + std::vector<inode_backpointer_t> ancestors; + +protected: + MMDSOpenIno() : MMDSOp{MSG_MDS_OPENINO, HEAD_VERSION, COMPAT_VERSION} {} + MMDSOpenIno(ceph_tid_t t, inodeno_t i, std::vector<inode_backpointer_t>* pa) : + MMDSOp{MSG_MDS_OPENINO, HEAD_VERSION, COMPAT_VERSION}, ino(i) { + header.tid = t; + if (pa) + ancestors = *pa; + } + ~MMDSOpenIno() final {} + +public: + std::string_view get_type_name() const override { return "openino"; } + void print(std::ostream &out) const override { + out << "openino(" << header.tid << " " << ino << " " << ancestors << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(ino, payload); + encode(ancestors, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(ino, p); + decode(ancestors, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MMDSOpenInoReply.h b/src/messages/MMDSOpenInoReply.h new file mode 100644 index 000000000..a331b5f8b --- /dev/null +++ b/src/messages/MMDSOpenInoReply.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) 2011 New Dream Network + * + * 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_MDSOPENINOREPLY_H +#define CEPH_MDSOPENINOREPLY_H + +#include "messages/MMDSOp.h" + +class MMDSOpenInoReply final : public MMDSOp { +public: + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; + inodeno_t ino; + std::vector<inode_backpointer_t> ancestors; + mds_rank_t hint; + int32_t error; + +protected: + MMDSOpenInoReply() : MMDSOp{MSG_MDS_OPENINOREPLY, HEAD_VERSION, COMPAT_VERSION}, error(0) {} + MMDSOpenInoReply(ceph_tid_t t, inodeno_t i, mds_rank_t h=MDS_RANK_NONE, int e=0) : + MMDSOp{MSG_MDS_OPENINOREPLY, HEAD_VERSION, COMPAT_VERSION}, ino(i), hint(h), error(e) { + header.tid = t; + } + + +public: + std::string_view get_type_name() const override { return "openinoreply"; } + void print(std::ostream &out) const override { + out << "openinoreply(" << header.tid << " " + << ino << " " << hint << " " << ancestors << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(ino, payload); + encode(ancestors, payload); + encode(hint, payload); + encode(error, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(ino, p); + decode(ancestors, p); + decode(hint, p); + decode(error, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MMDSPeerRequest.h b/src/messages/MMDSPeerRequest.h new file mode 100644 index 000000000..389f8b96b --- /dev/null +++ b/src/messages/MMDSPeerRequest.h @@ -0,0 +1,233 @@ +// -*- 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_MMDSPEERREQUEST_H +#define CEPH_MMDSPEERREQUEST_H + +#include "mds/mdstypes.h" +#include "messages/MMDSOp.h" + +class MMDSPeerRequest final : public MMDSOp { + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; +public: + static constexpr int OP_XLOCK = 1; + static constexpr int OP_XLOCKACK = -1; + static constexpr int OP_UNXLOCK = 2; + static constexpr int OP_AUTHPIN = 3; + static constexpr int OP_AUTHPINACK = -3; + + static constexpr int OP_LINKPREP = 4; + static constexpr int OP_UNLINKPREP = 5; + static constexpr int OP_LINKPREPACK = -4; + + static constexpr int OP_RENAMEPREP = 7; + static constexpr int OP_RENAMEPREPACK = -7; + + static constexpr int OP_WRLOCK = 8; + static constexpr int OP_WRLOCKACK = -8; + static constexpr int OP_UNWRLOCK = 9; + + static constexpr int OP_RMDIRPREP = 10; + static constexpr int OP_RMDIRPREPACK = -10; + + static constexpr int OP_DROPLOCKS = 11; + + static constexpr int OP_RENAMENOTIFY = 12; + static constexpr int OP_RENAMENOTIFYACK = -12; + + static constexpr int OP_FINISH = 17; + static constexpr int OP_COMMITTED = -18; + + static constexpr int OP_ABORT = 20; // used for recovery only + //static constexpr int OP_COMMIT = 21; // used for recovery only + + + static const char *get_opname(int o) { + switch (o) { + case OP_XLOCK: return "xlock"; + case OP_XLOCKACK: return "xlock_ack"; + case OP_UNXLOCK: return "unxlock"; + case OP_AUTHPIN: return "authpin"; + case OP_AUTHPINACK: return "authpin_ack"; + + case OP_LINKPREP: return "link_prep"; + case OP_LINKPREPACK: return "link_prep_ack"; + case OP_UNLINKPREP: return "unlink_prep"; + + case OP_RENAMEPREP: return "rename_prep"; + case OP_RENAMEPREPACK: return "rename_prep_ack"; + + case OP_FINISH: return "finish"; // commit + case OP_COMMITTED: return "committed"; + + case OP_WRLOCK: return "wrlock"; + case OP_WRLOCKACK: return "wrlock_ack"; + case OP_UNWRLOCK: return "unwrlock"; + + case OP_RMDIRPREP: return "rmdir_prep"; + case OP_RMDIRPREPACK: return "rmdir_prep_ack"; + + case OP_DROPLOCKS: return "drop_locks"; + + case OP_RENAMENOTIFY: return "rename_notify"; + case OP_RENAMENOTIFYACK: return "rename_notify_ack"; + + case OP_ABORT: return "abort"; + //case OP_COMMIT: return "commit"; + + default: ceph_abort(); return 0; + } + } + + private: + metareqid_t reqid; + __u32 attempt; + __s16 op; + mutable __u16 flags; /* XXX HACK for mark_interrupted */ + + static constexpr unsigned FLAG_NONBLOCKING = 1<<0; + static constexpr unsigned FLAG_WOULDBLOCK = 1<<1; + static constexpr unsigned FLAG_NOTJOURNALED = 1<<2; + static constexpr unsigned FLAG_EROFS = 1<<3; + static constexpr unsigned FLAG_ABORT = 1<<4; + static constexpr unsigned FLAG_INTERRUPTED = 1<<5; + static constexpr unsigned FLAG_NOTIFYBLOCKING = 1<<6; + static constexpr unsigned FLAG_REQBLOCKED = 1<<7; + + // for locking + __u16 lock_type; // lock object type + MDSCacheObjectInfo object_info; + + // for authpins + std::vector<MDSCacheObjectInfo> authpins; + + public: + // for rename prep + filepath srcdnpath; + filepath destdnpath; + std::string alternate_name; + std::set<mds_rank_t> witnesses; + ceph::buffer::list inode_export; + version_t inode_export_v; + mds_rank_t srcdn_auth; + utime_t op_stamp; + + mutable ceph::buffer::list straybl; // stray dir + dentry + ceph::buffer::list srci_snapbl; + ceph::buffer::list desti_snapbl; + +public: + metareqid_t get_reqid() const { return reqid; } + __u32 get_attempt() const { return attempt; } + int get_op() const { return op; } + bool is_reply() const { return op < 0; } + + int get_lock_type() const { return lock_type; } + const MDSCacheObjectInfo &get_object_info() const { return object_info; } + MDSCacheObjectInfo &get_object_info() { return object_info; } + const MDSCacheObjectInfo &get_authpin_freeze() const { return object_info; } + MDSCacheObjectInfo &get_authpin_freeze() { return object_info; } + + const std::vector<MDSCacheObjectInfo>& get_authpins() const { return authpins; } + std::vector<MDSCacheObjectInfo>& get_authpins() { return authpins; } + void mark_nonblocking() { flags |= FLAG_NONBLOCKING; } + bool is_nonblocking() const { return (flags & FLAG_NONBLOCKING); } + void mark_error_wouldblock() { flags |= FLAG_WOULDBLOCK; } + bool is_error_wouldblock() const { return (flags & FLAG_WOULDBLOCK); } + void mark_not_journaled() { flags |= FLAG_NOTJOURNALED; } + bool is_not_journaled() const { return (flags & FLAG_NOTJOURNALED); } + void mark_error_rofs() { flags |= FLAG_EROFS; } + bool is_error_rofs() const { return (flags & FLAG_EROFS); } + bool is_abort() const { return (flags & FLAG_ABORT); } + void mark_abort() { flags |= FLAG_ABORT; } + bool is_interrupted() const { return (flags & FLAG_INTERRUPTED); } + void mark_interrupted() const { flags |= FLAG_INTERRUPTED; } + bool should_notify_blocking() const { return (flags & FLAG_NOTIFYBLOCKING); } + void mark_notify_blocking() { flags |= FLAG_NOTIFYBLOCKING; } + void clear_notify_blocking() const { flags &= ~FLAG_NOTIFYBLOCKING; } + bool is_req_blocked() const { return (flags & FLAG_REQBLOCKED); } + void mark_req_blocked() { flags |= FLAG_REQBLOCKED; } + + void set_lock_type(int t) { lock_type = t; } + const ceph::buffer::list& get_lock_data() const { return inode_export; } + ceph::buffer::list& get_lock_data() { return inode_export; } + +protected: + MMDSPeerRequest() : MMDSOp{MSG_MDS_PEER_REQUEST, HEAD_VERSION, COMPAT_VERSION} { } + MMDSPeerRequest(metareqid_t ri, __u32 att, int o) : + MMDSOp{MSG_MDS_PEER_REQUEST, HEAD_VERSION, COMPAT_VERSION}, + reqid(ri), attempt(att), op(o), flags(0), lock_type(0), + inode_export_v(0), srcdn_auth(MDS_RANK_NONE) { } + ~MMDSPeerRequest() final {} + +public: + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(reqid, payload); + encode(attempt, payload); + encode(op, payload); + encode(flags, payload); + encode(lock_type, payload); + encode(object_info, payload); + encode(authpins, payload); + encode(srcdnpath, payload); + encode(destdnpath, payload); + encode(witnesses, payload); + encode(op_stamp, payload); + encode(inode_export, payload); + encode(inode_export_v, payload); + encode(srcdn_auth, payload); + encode(straybl, payload); + encode(srci_snapbl, payload); + encode(desti_snapbl, payload); + encode(alternate_name, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(reqid, p); + decode(attempt, p); + decode(op, p); + decode(flags, p); + decode(lock_type, p); + decode(object_info, p); + decode(authpins, p); + decode(srcdnpath, p); + decode(destdnpath, p); + decode(witnesses, p); + decode(op_stamp, p); + decode(inode_export, p); + decode(inode_export_v, p); + decode(srcdn_auth, p); + decode(straybl, p); + decode(srci_snapbl, p); + decode(desti_snapbl, p); + decode(alternate_name, p); + } + + std::string_view get_type_name() const override { return "peer_request"; } + void print(std::ostream& out) const override { + out << "peer_request(" << reqid + << "." << attempt + << " " << get_opname(op) + << ")"; + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MMDSPing.h b/src/messages/MMDSPing.h new file mode 100644 index 000000000..6c1f2f20e --- /dev/null +++ b/src/messages/MMDSPing.h @@ -0,0 +1,50 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef CEPH_MESSAGES_MMDSPING_H +#define CEPH_MESSAGES_MMDSPING_H + +#include "include/types.h" +#include "messages/MMDSOp.h" + +class MMDSPing final : public MMDSOp { +private: + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; +public: + version_t seq; + +protected: + MMDSPing() : MMDSOp(MSG_MDS_PING, HEAD_VERSION, COMPAT_VERSION) { + } + MMDSPing(version_t seq) + : MMDSOp(MSG_MDS_PING, HEAD_VERSION, COMPAT_VERSION), seq(seq) { + } + ~MMDSPing() final {} + +public: + std::string_view get_type_name() const override { + return "mdsping"; + } + + void print(ostream &out) const override { + out << "mdsping"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(seq, payload); + } + + void decode_payload() override { + using ceph::decode; + auto iter = payload.cbegin(); + decode(seq, iter); + } + +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif // CEPH_MESSAGES_MMDSPING_H diff --git a/src/messages/MMDSResolve.h b/src/messages/MMDSResolve.h new file mode 100644 index 000000000..d636bdcd5 --- /dev/null +++ b/src/messages/MMDSResolve.h @@ -0,0 +1,160 @@ +// -*- 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_MMDSRESOLVE_H +#define CEPH_MMDSRESOLVE_H + +#include "include/types.h" +#include "mds/Capability.h" +#include "messages/MMDSOp.h" + +class MMDSResolve final : public MMDSOp { + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; + +public: + std::map<dirfrag_t, std::vector<dirfrag_t>> subtrees; + std::map<dirfrag_t, std::vector<dirfrag_t>> ambiguous_imports; + + class peer_inode_cap { + public: + inodeno_t ino; + std::map<client_t,Capability::Export> cap_exports; + peer_inode_cap() {} + peer_inode_cap(inodeno_t a, map<client_t, Capability::Export> b) : ino(a), cap_exports(b) {} + void encode(ceph::buffer::list &bl) const + { + ENCODE_START(1, 1, bl); + encode(ino, bl); + encode(cap_exports, bl); + ENCODE_FINISH(bl); + } + void decode(ceph::buffer::list::const_iterator &blp) + { + DECODE_START(1, blp); + decode(ino, blp); + decode(cap_exports, blp); + DECODE_FINISH(blp); + } + }; + WRITE_CLASS_ENCODER(peer_inode_cap) + + struct peer_request { + ceph::buffer::list inode_caps; + bool committing; + peer_request() : committing(false) {} + void encode(ceph::buffer::list &bl) const { + ENCODE_START(1, 1, bl); + encode(inode_caps, bl); + encode(committing, bl); + ENCODE_FINISH(bl); + } + void decode(ceph::buffer::list::const_iterator &blp) { + DECODE_START(1, blp); + decode(inode_caps, blp); + decode(committing, blp); + DECODE_FINISH(blp); + } + }; + + std::map<metareqid_t, peer_request> peer_requests; + + // table client information + struct table_client { + __u8 type; + std::set<version_t> pending_commits; + + table_client() : type(0) {} + table_client(int _type, const std::set<version_t>& commits) + : type(_type), pending_commits(commits) {} + + void encode(ceph::buffer::list& bl) const { + using ceph::encode; + encode(type, bl); + encode(pending_commits, bl); + } + void decode(ceph::buffer::list::const_iterator& bl) { + using ceph::decode; + decode(type, bl); + decode(pending_commits, bl); + } + }; + + std::list<table_client> table_clients; + +protected: + MMDSResolve() : MMDSOp{MSG_MDS_RESOLVE, HEAD_VERSION, COMPAT_VERSION} + {} + ~MMDSResolve() final {} + +public: + std::string_view get_type_name() const override { return "mds_resolve"; } + + void print(std::ostream& out) const override { + out << "mds_resolve(" << subtrees.size() + << "+" << ambiguous_imports.size() + << " subtrees +" << peer_requests.size() << " peer requests)"; + } + + void add_subtree(dirfrag_t im) { + subtrees[im].clear(); + } + void add_subtree_bound(dirfrag_t im, dirfrag_t ex) { + subtrees[im].push_back(ex); + } + + void add_ambiguous_import(dirfrag_t im, const std::vector<dirfrag_t>& m) { + ambiguous_imports[im] = m; + } + + void add_peer_request(metareqid_t reqid, bool committing) { + peer_requests[reqid].committing = committing; + } + + void add_peer_request(metareqid_t reqid, ceph::buffer::list& bl) { + peer_requests[reqid].inode_caps = std::move(bl); + } + + void add_table_commits(int table, const std::set<version_t>& pending_commits) { + table_clients.push_back(table_client(table, pending_commits)); + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(subtrees, payload); + encode(ambiguous_imports, payload); + encode(peer_requests, payload); + encode(table_clients, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(subtrees, p); + decode(ambiguous_imports, p); + decode(peer_requests, p); + decode(table_clients, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +inline std::ostream& operator<<(std::ostream& out, const MMDSResolve::peer_request&) { + return out; +} + +WRITE_CLASS_ENCODER(MMDSResolve::peer_request) +WRITE_CLASS_ENCODER(MMDSResolve::table_client) +WRITE_CLASS_ENCODER(MMDSResolve::peer_inode_cap) +#endif diff --git a/src/messages/MMDSResolveAck.h b/src/messages/MMDSResolveAck.h new file mode 100644 index 000000000..727f83f45 --- /dev/null +++ b/src/messages/MMDSResolveAck.h @@ -0,0 +1,65 @@ +// -*- 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_MMDSRESOLVEACK_H +#define CEPH_MMDSRESOLVEACK_H + +#include "include/types.h" +#include "messages/MMDSOp.h" + + +class MMDSResolveAck final : public MMDSOp { + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; +public: + std::map<metareqid_t, ceph::buffer::list> commit; + std::vector<metareqid_t> abort; + +protected: + MMDSResolveAck() : MMDSOp{MSG_MDS_RESOLVEACK, HEAD_VERSION, COMPAT_VERSION} {} + ~MMDSResolveAck() final {} + +public: + std::string_view get_type_name() const override { return "resolve_ack"; } + /*void print(ostream& out) const { + out << "resolve_ack.size() + << "+" << ambiguous_imap.size() + << " imports +" << peer_requests.size() << " peer requests)"; + } + */ + + void add_commit(metareqid_t r) { + commit[r].clear(); + } + void add_abort(metareqid_t r) { + abort.push_back(r); + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(commit, payload); + encode(abort, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(commit, p); + decode(abort, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MMDSScrub.h b/src/messages/MMDSScrub.h new file mode 100644 index 000000000..b4f4ce55b --- /dev/null +++ b/src/messages/MMDSScrub.h @@ -0,0 +1,138 @@ +// -*- 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_MMDSSCRUB_H +#define CEPH_MMDSSCRUB_H + +#include "messages/MMDSOp.h" + +#include "include/types.h" +#include "include/frag.h" + +class MMDSScrub : public MMDSOp { +public: + static constexpr int OP_QUEUEDIR = 1; + static constexpr int OP_QUEUEDIR_ACK = -1; + static constexpr int OP_QUEUEINO = 2; + static constexpr int OP_QUEUEINO_ACK = -2; + static constexpr int OP_ABORT = 3; + static constexpr int OP_PAUSE = 4; + static constexpr int OP_RESUME = 5; + + static const char *get_opname(int o) { + switch (o) { + case OP_QUEUEDIR: return "queue_dir"; + case OP_QUEUEDIR_ACK: return "queue_dir_ack"; + case OP_QUEUEINO: return "queue_ino"; + case OP_QUEUEINO_ACK: return "queue_ino_ack"; + case OP_ABORT: return "abort"; + case OP_PAUSE: return "pause"; + case OP_RESUME: return "resume"; + default: ceph_abort(); return nullptr; + } + } + + std::string_view get_type_name() const override { return "mds_scrub"; } + + void print(std::ostream& out) const override { + out << "mds_scrub(" << get_opname(op) << " " + << ino << " " << frags << " " << tag; + if (is_force()) out << " force"; + if (is_recursive()) out << " recursive"; + if (is_repair()) out << " repair"; + out << ")"; + } + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(op, payload); + encode(ino, payload); + encode(frags, payload); + encode(tag, payload); + encode(origin, payload); + encode(flags, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(op, p); + decode(ino, p); + decode(frags, p); + decode(tag, p); + decode(origin, p); + decode(flags, p); + } + inodeno_t get_ino() const { + return ino; + } + const fragset_t& get_frags() const { + return frags; + } + const std::string& get_tag() const { + return tag; + } + inodeno_t get_origin() const { + return origin; + } + int get_op() const { + return op; + } + bool is_internal_tag() const { + return flags & FLAG_INTERNAL_TAG; + } + bool is_force() const { + return flags & FLAG_FORCE; + } + bool is_recursive() const { + return flags & FLAG_RECURSIVE; + } + bool is_repair() const { + return flags & FLAG_REPAIR; + } + +protected: + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; + + MMDSScrub() : MMDSOp(MSG_MDS_SCRUB, HEAD_VERSION, COMPAT_VERSION) {} + MMDSScrub(int o) + : MMDSOp(MSG_MDS_SCRUB, HEAD_VERSION, COMPAT_VERSION), op(o) {} + MMDSScrub(int o, inodeno_t i, fragset_t&& _frags, std::string_view _tag, + inodeno_t _origin=inodeno_t(), bool internal_tag=false, + bool force=false, bool recursive=false, bool repair=false) + : MMDSOp(MSG_MDS_SCRUB, HEAD_VERSION, COMPAT_VERSION), + op(o), ino(i), frags(std::move(_frags)), tag(_tag), origin(_origin) { + if (internal_tag) flags |= FLAG_INTERNAL_TAG; + if (force) flags |= FLAG_FORCE; + if (recursive) flags |= FLAG_RECURSIVE; + if (repair) flags |= FLAG_REPAIR; + } + + ~MMDSScrub() override {} +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); + + static constexpr unsigned FLAG_INTERNAL_TAG = 1<<0; + static constexpr unsigned FLAG_FORCE = 1<<1; + static constexpr unsigned FLAG_RECURSIVE = 1<<2; + static constexpr unsigned FLAG_REPAIR = 1<<3; + + int op; + inodeno_t ino; + fragset_t frags; + std::string tag; + inodeno_t origin; + unsigned flags = 0; +}; +#endif // CEPH_MMDSSCRUB_H diff --git a/src/messages/MMDSScrubStats.h b/src/messages/MMDSScrubStats.h new file mode 100644 index 000000000..41c403ade --- /dev/null +++ b/src/messages/MMDSScrubStats.h @@ -0,0 +1,80 @@ +// -*- 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_MMDSSCRUBSTATS_H +#define CEPH_MMDSSCRUBSTATS_H + +#include "messages/MMDSOp.h" + +class MMDSScrubStats : public MMDSOp { + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; + +public: + std::string_view get_type_name() const override { return "mds_scrub_stats"; } + void print(ostream& o) const override { + o << "mds_scrub_stats(e" << epoch; + if (update_scrubbing) + o << " [" << scrubbing_tags << "]"; + if (aborting) + o << " aborting"; + o << ")"; + } + + unsigned get_epoch() const { return epoch; } + const auto& get_scrubbing_tags() const { return scrubbing_tags; } + bool is_aborting() const { return aborting; } + bool is_finished(const std::string& tag) const { + return update_scrubbing && !scrubbing_tags.count(tag); + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(epoch, payload); + encode(scrubbing_tags, payload); + encode(update_scrubbing, payload); + encode(aborting, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(epoch, p); + decode(scrubbing_tags, p); + decode(update_scrubbing, p); + decode(aborting, p); + } + +protected: + MMDSScrubStats(unsigned e=0) : + MMDSOp(MSG_MDS_SCRUB_STATS, HEAD_VERSION, COMPAT_VERSION), + epoch(e) {} + MMDSScrubStats(unsigned e, std::set<std::string>&& tags, bool abrt=false) : + MMDSOp(MSG_MDS_SCRUB_STATS, HEAD_VERSION, COMPAT_VERSION), + epoch(e), scrubbing_tags(std::move(tags)), update_scrubbing(true), aborting(abrt) {} + MMDSScrubStats(unsigned e, const std::set<std::string>& tags, bool abrt=false) : + MMDSOp(MSG_MDS_SCRUB_STATS, HEAD_VERSION, COMPAT_VERSION), + epoch(e), scrubbing_tags(tags), update_scrubbing(true), aborting(abrt) {} + ~MMDSScrubStats() override {} + +private: + unsigned epoch; + std::set<std::string> scrubbing_tags; + bool update_scrubbing = false; + bool aborting = false; + + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MMDSSnapUpdate.h b/src/messages/MMDSSnapUpdate.h new file mode 100644 index 000000000..51b976024 --- /dev/null +++ b/src/messages/MMDSSnapUpdate.h @@ -0,0 +1,63 @@ +// -*- 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_MMDSSNAPUPDATE_H +#define CEPH_MMDSSNAPUPDATE_H + +#include "messages/MMDSOp.h" + +class MMDSSnapUpdate final : public MMDSOp { +private: + inodeno_t ino; + __s16 snap_op; + +public: + inodeno_t get_ino() const { return ino; } + int get_snap_op() const { return snap_op; } + + ceph::buffer::list snap_blob; + +protected: + MMDSSnapUpdate() : MMDSOp{MSG_MDS_SNAPUPDATE} {} + MMDSSnapUpdate(inodeno_t i, version_t tid, int op) : + MMDSOp{MSG_MDS_SNAPUPDATE}, ino(i), snap_op(op) { + set_tid(tid); + } + ~MMDSSnapUpdate() final {} + +public: + std::string_view get_type_name() const override { return "snap_update"; } + void print(std::ostream& o) const override { + o << "snap_update(" << ino << " table_tid " << get_tid() << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(ino, payload); + encode(snap_op, payload); + encode(snap_blob, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(ino, p); + decode(snap_op, p); + decode(snap_blob, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MMDSTableRequest.h b/src/messages/MMDSTableRequest.h new file mode 100644 index 000000000..365d5fb59 --- /dev/null +++ b/src/messages/MMDSTableRequest.h @@ -0,0 +1,70 @@ +// -*- 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_MMDSTABLEREQUEST_H +#define CEPH_MMDSTABLEREQUEST_H + +#include "mds/mds_table_types.h" +#include "messages/MMDSOp.h" + +class MMDSTableRequest final : public MMDSOp { +public: + __u16 table = 0; + __s16 op = 0; + uint64_t reqid = 0; + ceph::buffer::list bl; + +protected: + MMDSTableRequest() : MMDSOp{MSG_MDS_TABLE_REQUEST} {} + MMDSTableRequest(int tab, int o, uint64_t r, version_t v=0) : + MMDSOp{MSG_MDS_TABLE_REQUEST}, + table(tab), op(o), reqid(r) { + set_tid(v); + } + ~MMDSTableRequest() final {} + +public: + std::string_view get_type_name() const override { return "mds_table_request"; } + void print(std::ostream& o) const override { + o << "mds_table_request(" << get_mdstable_name(table) + << " " << get_mdstableserver_opname(op); + if (reqid) o << " " << reqid; + if (get_tid()) o << " tid " << get_tid(); + if (bl.length()) o << " " << bl.length() << " bytes"; + o << ")"; + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(table, p); + decode(op, p); + decode(reqid, p); + decode(bl, p); + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(table, payload); + encode(op, payload); + encode(reqid, payload); + encode(bl, payload); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MMgrBeacon.h b/src/messages/MMgrBeacon.h new file mode 100644 index 000000000..5b6ca3b60 --- /dev/null +++ b/src/messages/MMgrBeacon.h @@ -0,0 +1,206 @@ +// -*- 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_MMGRBEACON_H +#define CEPH_MMGRBEACON_H + +#include "messages/PaxosServiceMessage.h" +#include "mon/MonCommand.h" +#include "mon/MgrMap.h" + +#include "include/types.h" + + +class MMgrBeacon final : public PaxosServiceMessage { +private: + static constexpr int HEAD_VERSION = 10; + static constexpr int COMPAT_VERSION = 8; + +protected: + uint64_t gid; + entity_addrvec_t server_addrs; + bool available; + std::string name; + uuid_d fsid; + + // From active daemon to populate MgrMap::services + std::map<std::string, std::string> services; + + // Only populated during activation + std::vector<MonCommand> command_descs; + + // Information about the modules found locally on this daemon + std::vector<MgrMap::ModuleInfo> modules; + + std::map<std::string,std::string> metadata; ///< misc metadata about this osd + + std::vector<entity_addrvec_t> clients; + + uint64_t mgr_features = 0; ///< reporting mgr's features + +public: + MMgrBeacon() + : PaxosServiceMessage{MSG_MGR_BEACON, 0, HEAD_VERSION, COMPAT_VERSION}, + gid(0), available(false) + {} + + MMgrBeacon(const uuid_d& fsid_, uint64_t gid_, const std::string &name_, + entity_addrvec_t server_addrs_, bool available_, + std::vector<MgrMap::ModuleInfo>&& modules_, + std::map<std::string,std::string>&& metadata_, + std::vector<entity_addrvec_t> clients, + uint64_t feat) + : PaxosServiceMessage{MSG_MGR_BEACON, 0, HEAD_VERSION, COMPAT_VERSION}, + gid(gid_), server_addrs(server_addrs_), available(available_), name(name_), + fsid(fsid_), modules(std::move(modules_)), metadata(std::move(metadata_)), + clients(std::move(clients)), + mgr_features(feat) + { + } + + uint64_t get_gid() const { return gid; } + entity_addrvec_t get_server_addrs() const { return server_addrs; } + bool get_available() const { return available; } + const std::string& get_name() const { return name; } + const uuid_d& get_fsid() const { return fsid; } + const std::map<std::string,std::string>& get_metadata() const { + return metadata; + } + const std::map<std::string,std::string>& get_services() const { + return services; + } + uint64_t get_mgr_features() const { return mgr_features; } + + void set_services(const std::map<std::string, std::string> &svcs) + { + services = svcs; + } + + void set_command_descs(const std::vector<MonCommand> &cmds) + { + command_descs = cmds; + } + + const std::vector<MonCommand> &get_command_descs() + { + return command_descs; + } + + const std::vector<MgrMap::ModuleInfo> &get_available_modules() const + { + return modules; + } + + const auto& get_clients() const + { + return clients; + } + +private: + ~MMgrBeacon() final {} + +public: + + std::string_view get_type_name() const override { return "mgrbeacon"; } + + void print(std::ostream& out) const override { + out << get_type_name() << " mgr." << name << "(" << fsid << "," + << gid << ", " << server_addrs << ", " << available + << ")"; + } + + void encode_payload(uint64_t features) override { + header.version = HEAD_VERSION; + header.compat_version = COMPAT_VERSION; + using ceph::encode; + paxos_encode(); + + if (!HAVE_FEATURE(features, SERVER_NAUTILUS)) { + header.version = 7; + header.compat_version = 1; + encode(server_addrs.legacy_addr(), payload, features); + } else { + encode(server_addrs, payload, features); + } + encode(gid, payload); + encode(available, payload); + encode(name, payload); + encode(fsid, payload); + + // Fill out old-style list of module names (deprecated by + // later field of full ModuleInfos) + std::set<std::string> module_names; + for (const auto &info : modules) { + module_names.insert(info.name); + } + encode(module_names, payload); + + encode(command_descs, payload); + encode(metadata, payload); + encode(services, payload); + + encode(modules, payload); + encode(mgr_features, payload); + encode(clients, payload, features); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + paxos_decode(p); + decode(server_addrs, p); // entity_addr_t for version < 8 + decode(gid, p); + decode(available, p); + decode(name, p); + if (header.version >= 2) { + decode(fsid, p); + } + if (header.version >= 3) { + std::set<std::string> module_name_list; + decode(module_name_list, p); + // Only need to unpack this field if we won't have the full + // ModuleInfo structures added in v7 + if (header.version < 7) { + for (const auto &i : module_name_list) { + MgrMap::ModuleInfo info; + info.name = i; + modules.push_back(std::move(info)); + } + } + } + if (header.version >= 4) { + decode(command_descs, p); + } + if (header.version >= 5) { + decode(metadata, p); + } + if (header.version >= 6) { + decode(services, p); + } + if (header.version >= 7) { + decode(modules, p); + } + if (header.version >= 9) { + decode(mgr_features, p); + } + if (header.version >= 10) { + decode(clients, p); + } + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + + +#endif diff --git a/src/messages/MMgrClose.h b/src/messages/MMgrClose.h new file mode 100644 index 000000000..680ce273c --- /dev/null +++ b/src/messages/MMgrClose.h @@ -0,0 +1,51 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#pragma once + +#include "msg/Message.h" + +class MMgrClose : public Message { +private: + + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; + +public: + std::string daemon_name; + std::string service_name; // optional; otherwise infer from entity type + + void decode_payload() override + { + using ceph::decode; + auto p = payload.cbegin(); + decode(daemon_name, p); + decode(service_name, p); + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(daemon_name, payload); + encode(service_name, payload); + } + + std::string_view get_type_name() const override { return "mgrclose"; } + void print(std::ostream& out) const override { + out << get_type_name() << "("; + if (service_name.length()) { + out << service_name; + } else { + out << ceph_entity_type_name(get_source().type()); + } + out << "." << daemon_name; + out << ")"; + } + + MMgrClose() + : Message{MSG_MGR_CLOSE, HEAD_VERSION, COMPAT_VERSION} + {} + +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; diff --git a/src/messages/MMgrCommand.h b/src/messages/MMgrCommand.h new file mode 100644 index 000000000..83ee618c5 --- /dev/null +++ b/src/messages/MMgrCommand.h @@ -0,0 +1,46 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#pragma once + +#include <vector> + +#include "msg/Message.h" + +class MMgrCommand final : public Message { +public: + uuid_d fsid; + std::vector<std::string> cmd; + + MMgrCommand() + : Message{MSG_MGR_COMMAND} {} + MMgrCommand(const uuid_d &f) + : Message{MSG_MGR_COMMAND}, + fsid(f) { } + +private: + ~MMgrCommand() final {} + +public: + std::string_view get_type_name() const override { return "mgr_command"; } + void print(std::ostream& o) const override { + o << "mgr_command(tid " << get_tid() << ": "; + for (unsigned i=0; i<cmd.size(); i++) { + if (i) o << ' '; + o << cmd[i]; + } + o << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(fsid, payload); + encode(cmd, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(fsid, p); + decode(cmd, p); + } +}; diff --git a/src/messages/MMgrCommandReply.h b/src/messages/MMgrCommandReply.h new file mode 100644 index 000000000..40b8fd34d --- /dev/null +++ b/src/messages/MMgrCommandReply.h @@ -0,0 +1,45 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#pragma once + +#include <string_view> + +#include "msg/Message.h" +#include "MMgrCommand.h" + +class MMgrCommandReply final : public Message { +public: + errorcode32_t r; + std::string rs; + + MMgrCommandReply() + : Message{MSG_MGR_COMMAND_REPLY} {} + MMgrCommandReply(MMgrCommand *m, int _r) + : Message{MSG_MGR_COMMAND_REPLY}, r(_r) { + header.tid = m->get_tid(); + } + MMgrCommandReply(int _r, std::string_view s) + : Message{MSG_MGR_COMMAND_REPLY}, + r(_r), rs(s) { } +private: + ~MMgrCommandReply() final {} + +public: + std::string_view get_type_name() const override { return "mgr_command_reply"; } + void print(std::ostream& o) const override { + o << "mgr_command_reply(tid " << get_tid() << ": " << r << " " << rs << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(r, payload); + encode(rs, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(r, p); + decode(rs, p); + } +}; diff --git a/src/messages/MMgrConfigure.h b/src/messages/MMgrConfigure.h new file mode 100644 index 000000000..7b27c9064 --- /dev/null +++ b/src/messages/MMgrConfigure.h @@ -0,0 +1,87 @@ +// -*- 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) 2016 John Spray <john.spray@redhat.com> + * + * 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_MMGRCONFIGURE_H_ +#define CEPH_MMGRCONFIGURE_H_ + +#include "msg/Message.h" +#include "mgr/MetricTypes.h" +#include "mgr/OSDPerfMetricTypes.h" + +/** + * This message is sent from ceph-mgr to MgrClient, instructing it + * it about what data to send back to ceph-mgr at what frequency. + */ +class MMgrConfigure : public Message { +private: + static constexpr int HEAD_VERSION = 4; + static constexpr int COMPAT_VERSION = 1; + +public: + uint32_t stats_period = 0; + + // Default 0 means if unspecified will include all stats + uint32_t stats_threshold = 0; + + std::map<OSDPerfMetricQuery, OSDPerfMetricLimits> osd_perf_metric_queries; + + boost::optional<MetricConfigMessage> metric_config_message; + + void decode_payload() override + { + using ceph::decode; + auto p = payload.cbegin(); + decode(stats_period, p); + if (header.version >= 2) { + decode(stats_threshold, p); + } + if (header.version >= 3) { + decode(osd_perf_metric_queries, p); + } + if (header.version >= 4) { + decode(metric_config_message, p); + } + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(stats_period, payload); + encode(stats_threshold, payload); + encode(osd_perf_metric_queries, payload); + if (metric_config_message && metric_config_message->should_encode(features)) { + encode(metric_config_message, payload); + } else { + boost::optional<MetricConfigMessage> empty; + encode(empty, payload); + } + } + + std::string_view get_type_name() const override { return "mgrconfigure"; } + void print(std::ostream& out) const override { + out << get_type_name() << "(period=" << stats_period + << ", threshold=" << stats_threshold << ")"; + } + +private: + MMgrConfigure() + : Message{MSG_MGR_CONFIGURE, HEAD_VERSION, COMPAT_VERSION} + {} + using RefCountedObject::put; + using RefCountedObject::get; + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif + diff --git a/src/messages/MMgrDigest.h b/src/messages/MMgrDigest.h new file mode 100644 index 000000000..69f336868 --- /dev/null +++ b/src/messages/MMgrDigest.h @@ -0,0 +1,58 @@ +// -*- 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_MMGRDIGEST_H +#define CEPH_MMGRDIGEST_H + +#include "msg/Message.h" + +/** + * The mgr digest is a way for the mgr to subscribe to things + * other than the cluster maps, which are needed by + */ +class MMgrDigest final : public Message { +public: + ceph::buffer::list mon_status_json; + ceph::buffer::list health_json; + + std::string_view get_type_name() const override { return "mgrdigest"; } + void print(std::ostream& out) const override { + out << get_type_name(); + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(mon_status_json, p); + decode(health_json, p); + } + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(mon_status_json, payload); + encode(health_json, payload); + } + +private: + MMgrDigest() : + Message{MSG_MGR_DIGEST} {} + ~MMgrDigest() final {} + + using RefCountedObject::put; + using RefCountedObject::get; + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MMgrMap.h b/src/messages/MMgrMap.h new file mode 100644 index 000000000..9f16130be --- /dev/null +++ b/src/messages/MMgrMap.h @@ -0,0 +1,58 @@ +// -*- 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_MMGRMAP_H +#define CEPH_MMGRMAP_H + +#include "msg/Message.h" +#include "mon/MgrMap.h" + +class MMgrMap final : public Message { +protected: + MgrMap map; + +public: + const MgrMap & get_map() {return map;} + +private: + MMgrMap() : + Message{MSG_MGR_MAP} {} + MMgrMap(const MgrMap &map_) : + Message{MSG_MGR_MAP}, map(map_) + {} + ~MMgrMap() final {} + +public: + std::string_view get_type_name() const override { return "mgrmap"; } + void print(std::ostream& out) const override { + out << get_type_name() << "(e " << map.epoch << ")"; + } + + void decode_payload() override { + auto p = payload.cbegin(); + decode(map, p); + } + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(map, payload, features); + } +private: + using RefCountedObject::put; + using RefCountedObject::get; + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MMgrOpen.h b/src/messages/MMgrOpen.h new file mode 100644 index 000000000..c5061a281 --- /dev/null +++ b/src/messages/MMgrOpen.h @@ -0,0 +1,98 @@ +// -*- 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) 2016 John Spray <john.spray@redhat.com> + * + * 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_MMGROPEN_H_ +#define CEPH_MMGROPEN_H_ + +#include "msg/Message.h" + +class MMgrOpen : public Message { +private: + static constexpr int HEAD_VERSION = 3; + static constexpr int COMPAT_VERSION = 1; + +public: + + std::string daemon_name; + std::string service_name; // optional; otherwise infer from entity type + + bool service_daemon = false; + std::map<std::string,std::string> daemon_metadata; + std::map<std::string,std::string> daemon_status; + + // encode map<string,map<int32_t,string>> of current config + ceph::buffer::list config_bl; + + // encode map<string,string> of compiled-in defaults + ceph::buffer::list config_defaults_bl; + + void decode_payload() override + { + using ceph::decode; + auto p = payload.cbegin(); + decode(daemon_name, p); + if (header.version >= 2) { + decode(service_name, p); + decode(service_daemon, p); + if (service_daemon) { + decode(daemon_metadata, p); + decode(daemon_status, p); + } + } + if (header.version >= 3) { + decode(config_bl, p); + decode(config_defaults_bl, p); + } + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(daemon_name, payload); + encode(service_name, payload); + encode(service_daemon, payload); + if (service_daemon) { + encode(daemon_metadata, payload); + encode(daemon_status, payload); + } + encode(config_bl, payload); + encode(config_defaults_bl, payload); + } + + std::string_view get_type_name() const override { return "mgropen"; } + void print(std::ostream& out) const override { + out << get_type_name() << "("; + if (service_name.length()) { + out << service_name; + } else { + out << ceph_entity_type_name(get_source().type()); + } + out << "." << daemon_name; + if (service_daemon) { + out << " daemon"; + } + out << ")"; + } + +private: + MMgrOpen() + : Message{MSG_MGR_OPEN, HEAD_VERSION, COMPAT_VERSION} + {} + using RefCountedObject::put; + using RefCountedObject::get; + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif + diff --git a/src/messages/MMgrReport.h b/src/messages/MMgrReport.h new file mode 100644 index 000000000..5cd5f3d54 --- /dev/null +++ b/src/messages/MMgrReport.h @@ -0,0 +1,202 @@ +// -*- 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) 2016 John Spray <john.spray@redhat.com> + * + * 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_MMGRREPORT_H_ +#define CEPH_MMGRREPORT_H_ + +#include <boost/optional.hpp> + +#include "msg/Message.h" +#include "mgr/MetricTypes.h" +#include "mgr/OSDPerfMetricTypes.h" + +#include "common/perf_counters.h" +#include "include/common_fwd.h" +#include "mgr/DaemonHealthMetric.h" + +class PerfCounterType +{ +public: + std::string path; + std::string description; + std::string nick; + enum perfcounter_type_d type; + + // For older clients that did not send priority, pretend everything + // is "useful" so that mgr plugins filtering on prio will get some + // data (albeit probably more than they wanted) + uint8_t priority = PerfCountersBuilder::PRIO_USEFUL; + enum unit_t unit; + + void encode(ceph::buffer::list &bl) const + { + // TODO: decide whether to drop the per-type + // encoding here, we could rely on the MgrReport + // verisoning instead. + ENCODE_START(3, 1, bl); + encode(path, bl); + encode(description, bl); + encode(nick, bl); + static_assert(sizeof(type) == 1, "perfcounter_type_d must be one byte"); + encode((uint8_t)type, bl); + encode(priority, bl); + encode((uint8_t)unit, bl); + ENCODE_FINISH(bl); + } + + void decode(ceph::buffer::list::const_iterator &p) + { + DECODE_START(3, p); + decode(path, p); + decode(description, p); + decode(nick, p); + uint8_t raw_type; + decode(raw_type, p); + type = (enum perfcounter_type_d)raw_type; + if (struct_v >= 2) { + decode(priority, p); + } + if (struct_v >= 3) { + uint8_t raw_unit; + decode(raw_unit, p); + unit = (enum unit_t)raw_unit; + } + DECODE_FINISH(p); + } +}; +WRITE_CLASS_ENCODER(PerfCounterType) + +class MMgrReport : public Message { +private: + static constexpr int HEAD_VERSION = 9; + static constexpr int COMPAT_VERSION = 1; + +public: + /** + * Client is responsible for remembering whether it has introduced + * each perf counter to the server. When first sending a particular + * counter, it must inline the counter's schema here. + */ + std::vector<PerfCounterType> declare_types; + std::vector<std::string> undeclare_types; + + // For all counters present, sorted by idx, output + // as many bytes as are needed to represent them + + // Decode: iterate over the types we know about, sorted by idx, + // and use the current type's type to decide how to decode + // the next bytes from the ceph::buffer::list. + ceph::buffer::list packed; + + std::string daemon_name; + std::string service_name; // optional; otherwise infer from entity type + + // for service registration + boost::optional<std::map<std::string,std::string>> daemon_status; + boost::optional<std::map<std::string,std::string>> task_status; + + std::vector<DaemonHealthMetric> daemon_health_metrics; + + // encode map<string,map<int32_t,string>> of current config + ceph::buffer::list config_bl; + + std::map<OSDPerfMetricQuery, OSDPerfMetricReport> osd_perf_metric_reports; + + boost::optional<MetricReportMessage> metric_report_message; + + void decode_payload() override + { + using ceph::decode; + auto p = payload.cbegin(); + decode(daemon_name, p); + decode(declare_types, p); + decode(packed, p); + if (header.version >= 2) + decode(undeclare_types, p); + if (header.version >= 3) { + decode(service_name, p); + decode(daemon_status, p); + } + if (header.version >= 5) { + decode(daemon_health_metrics, p); + } + if (header.version >= 6) { + decode(config_bl, p); + } + if (header.version >= 7) { + decode(osd_perf_metric_reports, p); + } + if (header.version >= 8) { + decode(task_status, p); + } + if (header.version >= 9) { + decode(metric_report_message, p); + } + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(daemon_name, payload); + encode(declare_types, payload); + encode(packed, payload); + encode(undeclare_types, payload); + encode(service_name, payload); + encode(daemon_status, payload); + encode(daemon_health_metrics, payload); + encode(config_bl, payload); + encode(osd_perf_metric_reports, payload); + encode(task_status, payload); + if (metric_report_message && metric_report_message->should_encode(features)) { + encode(metric_report_message, payload); + } else { + boost::optional<MetricReportMessage> empty; + encode(empty, payload); + } + } + + std::string_view get_type_name() const override { return "mgrreport"; } + void print(std::ostream& out) const override { + out << get_type_name() << "("; + if (service_name.length()) { + out << service_name; + } else { + out << ceph_entity_type_name(get_source().type()); + } + out << "." << daemon_name + << " +" << declare_types.size() + << "-" << undeclare_types.size() + << " packed " << packed.length(); + if (daemon_status) { + out << " status=" << daemon_status->size(); + } + if (!daemon_health_metrics.empty()) { + out << " daemon_metrics=" << daemon_health_metrics.size(); + } + if (task_status) { + out << " task_status=" << task_status->size(); + } + out << ")"; + } + +private: + MMgrReport() + : Message{MSG_MGR_REPORT, HEAD_VERSION, COMPAT_VERSION} + {} + using RefCountedObject::put; + using RefCountedObject::get; + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MMgrUpdate.h b/src/messages/MMgrUpdate.h new file mode 100644 index 000000000..5e1f27b5f --- /dev/null +++ b/src/messages/MMgrUpdate.h @@ -0,0 +1,84 @@ +// -*- 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) 2022 Prashant D <pdhange@redhat.com> + * + * 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_MMGRUPDATE_H_ +#define CEPH_MMGRUPDATE_H_ + +#include "msg/Message.h" + +class MMgrUpdate : public Message { +private: + static constexpr int HEAD_VERSION = 2; + static constexpr int COMPAT_VERSION = 1; + +public: + + std::string daemon_name; + std::string service_name; // optional; otherwise infer from entity type + + std::map<std::string,std::string> daemon_metadata; + std::map<std::string,std::string> daemon_status; + + bool need_metadata_update = false; + + void decode_payload() override + { + using ceph::decode; + auto p = payload.cbegin(); + decode(daemon_name, p); + if (header.version >= 2) { + decode(service_name, p); + decode(need_metadata_update, p); + if (need_metadata_update) { + decode(daemon_metadata, p); + decode(daemon_status, p); + } + } + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(daemon_name, payload); + encode(service_name, payload); + encode(need_metadata_update, payload); + if (need_metadata_update) { + encode(daemon_metadata, payload); + encode(daemon_status, payload); + } + } + + std::string_view get_type_name() const override { return "mgrupdate"; } + void print(std::ostream& out) const override { + out << get_type_name() << "("; + if (service_name.length()) { + out << service_name; + } else { + out << ceph_entity_type_name(get_source().type()); + } + out << "." << daemon_name; + out << ")"; + } + +private: + MMgrUpdate() + : Message{MSG_MGR_UPDATE, HEAD_VERSION, COMPAT_VERSION} + {} + using RefCountedObject::put; + using RefCountedObject::get; + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif + diff --git a/src/messages/MMonCommand.h b/src/messages/MMonCommand.h new file mode 100644 index 000000000..494d5cf56 --- /dev/null +++ b/src/messages/MMonCommand.h @@ -0,0 +1,89 @@ +// -*- 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_MMONCOMMAND_H +#define CEPH_MMONCOMMAND_H + +#include "messages/PaxosServiceMessage.h" + +#include <vector> +#include <string> + +using TOPNSPC::common::cmdmap_from_json; +using TOPNSPC::common::cmd_getval; + +class MMonCommand final : public PaxosServiceMessage { +public: + // weird note: prior to octopus, MgrClient would leave fsid blank when + // sending commands to the mgr. Starting with octopus, this is either + // populated with a valid fsid (tell command) or an MMgrCommand is sent + // instead. + uuid_d fsid; + std::vector<std::string> cmd; + + MMonCommand() : PaxosServiceMessage{MSG_MON_COMMAND, 0} {} + MMonCommand(const uuid_d &f) + : PaxosServiceMessage{MSG_MON_COMMAND, 0}, + fsid(f) + { } + +private: + ~MMonCommand() final {} + +public: + std::string_view get_type_name() const override { return "mon_command"; } + void print(std::ostream& o) const override { + cmdmap_t cmdmap; + std::ostringstream ss; + string prefix; + cmdmap_from_json(cmd, &cmdmap, ss); + cmd_getval(cmdmap, "prefix", prefix); + // Some config values contain sensitive data, so don't log them + o << "mon_command("; + if (prefix == "config set") { + string name; + cmd_getval(cmdmap, "name", name); + o << "[{prefix=" << prefix << ", name=" << name << "}]"; + } else if (prefix == "config-key set") { + string key; + cmd_getval(cmdmap, "key", key); + o << "[{prefix=" << prefix << ", key=" << key << "}]"; + } else { + for (unsigned i=0; i<cmd.size(); i++) { + if (i) o << ' '; + o << cmd[i]; + } + } + o << " v " << version << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + paxos_encode(); + encode(fsid, payload); + encode(cmd, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + paxos_decode(p); + decode(fsid, p); + decode(cmd, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MMonCommandAck.h b/src/messages/MMonCommandAck.h new file mode 100644 index 000000000..b49e8bcff --- /dev/null +++ b/src/messages/MMonCommandAck.h @@ -0,0 +1,83 @@ +// -*- 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_MMONCOMMANDACK_H +#define CEPH_MMONCOMMANDACK_H + +#include "messages/PaxosServiceMessage.h" + +using TOPNSPC::common::cmdmap_from_json; +using TOPNSPC::common::cmd_getval; + +class MMonCommandAck final : public PaxosServiceMessage { +public: + std::vector<std::string> cmd; + errorcode32_t r; + std::string rs; + + MMonCommandAck() : PaxosServiceMessage{MSG_MON_COMMAND_ACK, 0} {} + MMonCommandAck(const std::vector<std::string>& c, int _r, std::string s, version_t v) : + PaxosServiceMessage{MSG_MON_COMMAND_ACK, v}, + cmd(c), r(_r), rs(s) { } +private: + ~MMonCommandAck() final {} + +public: + std::string_view get_type_name() const override { return "mon_command"; } + void print(std::ostream& o) const override { + cmdmap_t cmdmap; + std::ostringstream ss; + string prefix; + cmdmap_from_json(cmd, &cmdmap, ss); + cmd_getval(cmdmap, "prefix", prefix); + // Some config values contain sensitive data, so don't log them + o << "mon_command_ack("; + if (prefix == "config set") { + string name; + cmd_getval(cmdmap, "name", name); + o << "[{prefix=" << prefix + << ", name=" << name << "}]" + << "=" << r << " " << rs << " v" << version << ")"; + } else if (prefix == "config-key set") { + string key; + cmd_getval(cmdmap, "key", key); + o << "[{prefix=" << prefix << ", key=" << key << "}]" + << "=" << r << " " << rs << " v" << version << ")"; + } else { + o << cmd; + } + o << "=" << r << " " << rs << " v" << version << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + paxos_encode(); + encode(r, payload); + encode(rs, payload); + encode(cmd, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + paxos_decode(p); + decode(r, p); + decode(rs, p); + decode(cmd, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MMonElection.h b/src/messages/MMonElection.h new file mode 100644 index 000000000..d50a5c0ff --- /dev/null +++ b/src/messages/MMonElection.h @@ -0,0 +1,144 @@ +// -*- 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_MMONELECTION_H +#define CEPH_MMONELECTION_H + +#include "common/ceph_releases.h" +#include "msg/Message.h" +#include "mon/MonMap.h" +#include "mon/mon_types.h" + +class MMonElection final : public Message { +private: + static constexpr int HEAD_VERSION = 9; + static constexpr int COMPAT_VERSION = 5; + +public: + static constexpr int OP_PROPOSE = 1; + static constexpr int OP_ACK = 2; + static constexpr int OP_NAK = 3; + static constexpr int OP_VICTORY = 4; + static const char *get_opname(int o) { + switch (o) { + case OP_PROPOSE: return "propose"; + case OP_ACK: return "ack"; + case OP_NAK: return "nak"; + case OP_VICTORY: return "victory"; + default: ceph_abort(); return 0; + } + } + + uuid_d fsid; + int32_t op; + epoch_t epoch; + ceph::buffer::list monmap_bl; + std::set<int32_t> quorum; + uint64_t quorum_features; + mon_feature_t mon_features; + ceph_release_t mon_release{ceph_release_t::unknown}; + ceph::buffer::list sharing_bl; + ceph::buffer::list scoring_bl; + uint8_t strategy; + std::map<std::string,std::string> metadata; + + MMonElection() : Message{MSG_MON_ELECTION, HEAD_VERSION, COMPAT_VERSION}, + op(0), epoch(0), + quorum_features(0), + mon_features(0), + strategy(0) + { } + + MMonElection(int o, epoch_t e, const bufferlist& bl, uint8_t s, MonMap *m) + : Message{MSG_MON_ELECTION, HEAD_VERSION, COMPAT_VERSION}, + fsid(m->fsid), op(o), epoch(e), + quorum_features(0), + mon_features(0), scoring_bl(bl), strategy(s) + { + // encode using full feature set; we will reencode for dest later, + // if necessary + m->encode(monmap_bl, CEPH_FEATURES_ALL); + } +private: + ~MMonElection() final {} + +public: + std::string_view get_type_name() const override { return "election"; } + void print(std::ostream& out) const override { + out << "election(" << fsid << " " << get_opname(op) + << " rel " << (int)mon_release << " e" << epoch << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + if (monmap_bl.length() && (features != CEPH_FEATURES_ALL)) { + // reencode old-format monmap + MonMap t; + t.decode(monmap_bl); + monmap_bl.clear(); + t.encode(monmap_bl, features); + } + + encode(fsid, payload); + encode(op, payload); + encode(epoch, payload); + encode(monmap_bl, payload); + encode(quorum, payload); + encode(quorum_features, payload); + encode((version_t)0, payload); // defunct + encode((version_t)0, payload); // defunct + encode(sharing_bl, payload); + encode(mon_features, payload); + encode(metadata, payload); + encode(mon_release, payload); + encode(scoring_bl, payload); + encode(strategy, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(fsid, p); + decode(op, p); + decode(epoch, p); + decode(monmap_bl, p); + decode(quorum, p); + decode(quorum_features, p); + { + version_t v; // defunct fields from old encoding + decode(v, p); + decode(v, p); + } + decode(sharing_bl, p); + if (header.version >= 6) + decode(mon_features, p); + if (header.version >= 7) + decode(metadata, p); + if (header.version >= 8) + decode(mon_release, p); + else + mon_release = infer_ceph_release_from_mon_features(mon_features); + if (header.version >= 9) { + decode(scoring_bl, p); + decode(strategy, p); + } else { + strategy = MonMap::election_strategy::CLASSIC; + } + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MMonGetMap.h b/src/messages/MMonGetMap.h new file mode 100644 index 000000000..9192da077 --- /dev/null +++ b/src/messages/MMonGetMap.h @@ -0,0 +1,39 @@ +// -*- 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_MMONGETMAP_H +#define CEPH_MMONGETMAP_H + +#include "msg/Message.h" + +#include "include/types.h" + +class MMonGetMap final : public Message { +public: + MMonGetMap() : Message{CEPH_MSG_MON_GET_MAP} { } +private: + ~MMonGetMap() final {} + +public: + std::string_view get_type_name() const override { return "mon_getmap"; } + + void encode_payload(uint64_t features) override { } + void decode_payload() override { } + +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MMonGetOSDMap.h b/src/messages/MMonGetOSDMap.h new file mode 100644 index 000000000..c70938b7e --- /dev/null +++ b/src/messages/MMonGetOSDMap.h @@ -0,0 +1,97 @@ +// -*- 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) 2014 Red Hat + * + * 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_MMONGETOSDMAP_H +#define CEPH_MMONGETOSDMAP_H + +#include <iostream> +#include <string> +#include <string_view> + +#include "msg/Message.h" + +#include "include/types.h" + +class MMonGetOSDMap final : public PaxosServiceMessage { +private: + epoch_t full_first, full_last; + epoch_t inc_first, inc_last; + +public: + MMonGetOSDMap() + : PaxosServiceMessage{CEPH_MSG_MON_GET_OSDMAP, 0}, + full_first(0), + full_last(0), + inc_first(0), + inc_last(0) { } +private: + ~MMonGetOSDMap() final {} + +public: + void request_full(epoch_t first, epoch_t last) { + ceph_assert(last >= first); + full_first = first; + full_last = last; + } + void request_inc(epoch_t first, epoch_t last) { + ceph_assert(last >= first); + inc_first = first; + inc_last = last; + } + epoch_t get_full_first() const { + return full_first; + } + epoch_t get_full_last() const { + return full_last; + } + epoch_t get_inc_first() const { + return inc_first; + } + epoch_t get_inc_last() const { + return inc_last; + } + + std::string_view get_type_name() const override { return "mon_get_osdmap"; } + void print(std::ostream& out) const override { + out << "mon_get_osdmap("; + if (full_first && full_last) + out << "full " << full_first << "-" << full_last; + if (inc_first && inc_last) + out << " inc" << inc_first << "-" << inc_last; + out << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + paxos_encode(); + encode(full_first, payload); + encode(full_last, payload); + encode(inc_first, payload); + encode(inc_last, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + paxos_decode(p); + decode(full_first, p); + decode(full_last, p); + decode(inc_first, p); + decode(inc_last, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MMonGetPurgedSnaps.h b/src/messages/MMonGetPurgedSnaps.h new file mode 100644 index 000000000..9b1977e37 --- /dev/null +++ b/src/messages/MMonGetPurgedSnaps.h @@ -0,0 +1,45 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#pragma once + +#include "PaxosServiceMessage.h" +#include "include/types.h" + +class MMonGetPurgedSnaps final : public PaxosServiceMessage { +public: + epoch_t start, last; + + MMonGetPurgedSnaps(epoch_t s=0, epoch_t l=0) + : PaxosServiceMessage{MSG_MON_GET_PURGED_SNAPS, 0}, + start(s), + last(l) {} +private: + ~MMonGetPurgedSnaps() final {} + +public: + std::string_view get_type_name() const override { + return "mon_get_purged_snaps"; + } + void print(std::ostream& out) const override { + out << "mon_get_purged_snaps([" << start << "," << last << "])"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + paxos_encode(); + encode(start, payload); + encode(last, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + paxos_decode(p); + decode(start, p); + decode(last, p); + } + +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; diff --git a/src/messages/MMonGetPurgedSnapsReply.h b/src/messages/MMonGetPurgedSnapsReply.h new file mode 100644 index 000000000..7810ab6d7 --- /dev/null +++ b/src/messages/MMonGetPurgedSnapsReply.h @@ -0,0 +1,49 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#pragma once + +#include "PaxosServiceMessage.h" +#include "osd/osd_types.h" +#include "include/types.h" + +class MMonGetPurgedSnapsReply final : public PaxosServiceMessage { +public: + epoch_t start, last; + std::map<epoch_t,mempool::osdmap::map<int64_t,snap_interval_set_t>> purged_snaps; + + MMonGetPurgedSnapsReply(epoch_t s=0, epoch_t l=0) + : PaxosServiceMessage{MSG_MON_GET_PURGED_SNAPS_REPLY, 0}, + start(s), + last(l) {} +private: + ~MMonGetPurgedSnapsReply() final {} + +public: + std::string_view get_type_name() const override { + return "mon_get_purged_snaps_reply"; + } + void print(std::ostream& out) const override { + out << "mon_get_purged_snaps_reply([" << start << "," << last << "])"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + paxos_encode(); + encode(start, payload); + encode(last, payload); + encode(purged_snaps, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + paxos_decode(p); + decode(start, p); + decode(last, p); + decode(purged_snaps, p); + } + +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; diff --git a/src/messages/MMonGetVersion.h b/src/messages/MMonGetVersion.h new file mode 100644 index 000000000..ad91cd155 --- /dev/null +++ b/src/messages/MMonGetVersion.h @@ -0,0 +1,60 @@ +// -*- 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) 2011 New Dream Network + * + * 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_MMONGETVERSION_H +#define CEPH_MMONGETVERSION_H + +#include "msg/Message.h" + +#include "include/types.h" + +/* + * This message is sent to the monitors to verify that the client's + * version of the map(s) is the latest available. For example, this + * can be used to determine whether a pool actually does not exist, or + * if it may have been created but the map was not received yet. + */ +class MMonGetVersion final : public Message { +public: + MMonGetVersion() : Message{CEPH_MSG_MON_GET_VERSION} {} + + std::string_view get_type_name() const override { + return "mon_get_version"; + } + + void print(std::ostream& o) const override { + o << "mon_get_version(what=" << what << " handle=" << handle << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(handle, payload); + encode(what, payload); + } + + void decode_payload() override { + auto p = payload.cbegin(); + using ceph::decode; + decode(handle, p); + decode(what, p); + } + + ceph_tid_t handle = 0; + std::string what; + +private: + ~MMonGetVersion() final {} +}; + +#endif diff --git a/src/messages/MMonGetVersionReply.h b/src/messages/MMonGetVersionReply.h new file mode 100644 index 000000000..407b449a0 --- /dev/null +++ b/src/messages/MMonGetVersionReply.h @@ -0,0 +1,66 @@ +// -*- 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) 2011 New Dream Network + * + * 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_MMONGETVERSIONREPLY_H +#define CEPH_MMONGETVERSIONREPLY_H + +#include "msg/Message.h" + +#include "include/types.h" + +/* + * This message is sent from the monitors to clients in response to a + * MMonGetVersion. The latest version of the requested thing is sent + * back. + */ +class MMonGetVersionReply final : public Message { +private: + static constexpr int HEAD_VERSION = 2; + +public: + MMonGetVersionReply() : Message{CEPH_MSG_MON_GET_VERSION_REPLY, HEAD_VERSION} { } + + std::string_view get_type_name() const override { + return "mon_get_version_reply"; + } + + void print(std::ostream& o) const override { + o << "mon_get_version_reply(handle=" << handle << " version=" << version << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(handle, payload); + encode(version, payload); + encode(oldest_version, payload); + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(handle, p); + decode(version, p); + if (header.version >= 2) + decode(oldest_version, p); + } + + ceph_tid_t handle = 0; + version_t version = 0; + version_t oldest_version = 0; + +private: + ~MMonGetVersionReply() final {} +}; + +#endif diff --git a/src/messages/MMonGlobalID.h b/src/messages/MMonGlobalID.h new file mode 100644 index 000000000..4330974e0 --- /dev/null +++ b/src/messages/MMonGlobalID.h @@ -0,0 +1,50 @@ +// -*- 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_MMONGLOBALID_H +#define CEPH_MMONGLOBALID_H + +#include "messages/PaxosServiceMessage.h" + +class MMonGlobalID final : public PaxosServiceMessage { +public: + uint64_t old_max_id = 0; + MMonGlobalID() : PaxosServiceMessage{MSG_MON_GLOBAL_ID, 0} + {} +private: + ~MMonGlobalID() final {} + +public: + std::string_view get_type_name() const override { return "global_id"; } + void print(std::ostream& out) const override { + out << "global_id (" << old_max_id << ")"; + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + paxos_decode(p); + decode(old_max_id, p); + } + void encode_payload(uint64_t features) override { + using ceph::encode; + paxos_encode(); + encode(old_max_id, payload); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MMonHealth.h b/src/messages/MMonHealth.h new file mode 100644 index 000000000..9f5d4084c --- /dev/null +++ b/src/messages/MMonHealth.h @@ -0,0 +1,63 @@ +// -*- 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) 2012 Inktank, Inc. + * + * 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_MMON_HEALTH_H +#define CEPH_MMON_HEALTH_H + +#include "msg/Message.h" +#include "messages/MMonQuorumService.h" +#include "mon/mon_types.h" + +class MMonHealth final : public MMonQuorumService { +public: + static constexpr int HEAD_VERSION = 1; + + int service_type = 0; + int service_op = 0; + + // service specific data + DataStats data_stats; + + MMonHealth() : MMonQuorumService{MSG_MON_HEALTH, HEAD_VERSION} { } + +private: + ~MMonHealth() final { } + +public: + std::string_view get_type_name() const override { return "mon_health"; } + void print(std::ostream &o) const override { + o << "mon_health(" + << " e " << get_epoch() + << " r " << get_round() + << " )"; + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + service_decode(p); + decode(service_type, p); + decode(service_op, p); + decode(data_stats, p); + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + service_encode(); + encode(service_type, payload); + encode(service_op, payload); + encode(data_stats, payload); + } +}; + +#endif /* CEPH_MMON_HEALTH_H */ diff --git a/src/messages/MMonHealthChecks.h b/src/messages/MMonHealthChecks.h new file mode 100644 index 000000000..9dd726fd4 --- /dev/null +++ b/src/messages/MMonHealthChecks.h @@ -0,0 +1,51 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef CEPH_MMON_HEALTH_CHECKS_H +#define CEPH_MMON_HEALTH_CHECKS_H + +#include "messages/PaxosServiceMessage.h" +#include "mon/health_check.h" + +class MMonHealthChecks final : public PaxosServiceMessage { +public: + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; + + health_check_map_t health_checks; + + MMonHealthChecks() + : PaxosServiceMessage{MSG_MON_HEALTH_CHECKS, HEAD_VERSION, COMPAT_VERSION} { + } + MMonHealthChecks(health_check_map_t& m) + : PaxosServiceMessage{MSG_MON_HEALTH_CHECKS, HEAD_VERSION, COMPAT_VERSION}, + health_checks(m) + {} + +private: + ~MMonHealthChecks() final { } + +public: + std::string_view get_type_name() const override { return "mon_health_checks"; } + void print(std::ostream &o) const override { + o << "mon_health_checks(" << health_checks.checks.size() << " checks)"; + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + paxos_decode(p); + decode(health_checks, p); + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + paxos_encode(); + encode(health_checks, payload); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MMonJoin.h b/src/messages/MMonJoin.h new file mode 100644 index 000000000..cf662f514 --- /dev/null +++ b/src/messages/MMonJoin.h @@ -0,0 +1,93 @@ +// -*- 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_MMONJOIN_H +#define CEPH_MMONJOIN_H + +#include "messages/PaxosServiceMessage.h" + +class MMonJoin final : public PaxosServiceMessage { +public: + static constexpr int HEAD_VERSION = 3; + static constexpr int COMPAT_VERSION = 2; + + uuid_d fsid; + std::string name; + entity_addrvec_t addrs; + /* The location members are for stretch mode. crush_loc is the location + * (generally just a "datacenter=<foo>" statement) of the monitor. The + * force_loc is whether the mon cluster should replace a previously-known + * location. Generally the monitor will force an update if it's given a + * location from the CLI on boot-up, and then never force again (so that it + * can be moved/updated via the ceph tool from elsewhere). */ + map<string,string> crush_loc; + bool force_loc{false}; + + MMonJoin() : PaxosServiceMessage{MSG_MON_JOIN, 0, HEAD_VERSION, COMPAT_VERSION} {} + MMonJoin(uuid_d &f, std::string n, const entity_addrvec_t& av) + : PaxosServiceMessage{MSG_MON_JOIN, 0, HEAD_VERSION, COMPAT_VERSION}, + fsid(f), name(n), addrs(av) + { } + MMonJoin(uuid_d &f, std::string n, const entity_addrvec_t& av, const map<string,string>& cloc, bool force) + : PaxosServiceMessage{MSG_MON_JOIN, 0, HEAD_VERSION, COMPAT_VERSION}, + fsid(f), name(n), addrs(av), crush_loc(cloc), force_loc(force) + { } + +private: + ~MMonJoin() final {} + +public: + std::string_view get_type_name() const override { return "mon_join"; } + void print(std::ostream& o) const override { + o << "mon_join(" << name << " " << addrs << " " << crush_loc << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + paxos_encode(); + encode(fsid, payload); + encode(name, payload); + if (HAVE_FEATURE(features, SERVER_NAUTILUS)) { + header.version = HEAD_VERSION; + header.compat_version = COMPAT_VERSION; + encode(addrs, payload, features); + encode(crush_loc, payload); + encode(force_loc, payload); + } else { + header.version = 1; + header.compat_version = 1; + encode(addrs.legacy_addr(), payload, features); + } + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + paxos_decode(p); + decode(fsid, p); + decode(name, p); + if (header.version == 1) { + entity_addr_t addr; + decode(addr, p); + addrs = entity_addrvec_t(addr); + } else { + decode(addrs, p); + if (header.version >= 3) { + decode(crush_loc, p); + decode(force_loc, p); + } + } + } +}; + +#endif diff --git a/src/messages/MMonMap.h b/src/messages/MMonMap.h new file mode 100644 index 000000000..e72c115f6 --- /dev/null +++ b/src/messages/MMonMap.h @@ -0,0 +1,62 @@ +// -*- 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_MMONMAP_H +#define CEPH_MMONMAP_H + +#include "include/encoding.h" +#include "include/ceph_features.h" +#include "msg/Message.h" +#include "msg/MessageRef.h" +#include "mon/MonMap.h" + +class MMonMap final : public Message { +public: + ceph::buffer::list monmapbl; + + MMonMap() : Message{CEPH_MSG_MON_MAP} { } + explicit MMonMap(ceph::buffer::list &bl) : Message{CEPH_MSG_MON_MAP} { + monmapbl = std::move(bl); + } +private: + ~MMonMap() final {} + +public: + std::string_view get_type_name() const override { return "mon_map"; } + + void encode_payload(uint64_t features) override { + if (monmapbl.length() && + ((features & CEPH_FEATURE_MONENC) == 0 || + (features & CEPH_FEATURE_MSG_ADDR2) == 0)) { + // reencode old-format monmap + MonMap t; + t.decode(monmapbl); + monmapbl.clear(); + t.encode(monmapbl, features); + } + + using ceph::encode; + encode(monmapbl, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(monmapbl, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MMonMgrReport.h b/src/messages/MMonMgrReport.h new file mode 100644 index 000000000..f5a68c7d3 --- /dev/null +++ b/src/messages/MMonMgrReport.h @@ -0,0 +1,94 @@ +// -*- 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) 2017 Greg Farnum/Red Hat <gfarnum@redhat.com> + * + * 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_MMONMGRREPORT_H +#define CEPH_MMONMGRREPORT_H + +#include "messages/PaxosServiceMessage.h" +#include "include/types.h" +#include "include/health.h" +#include "mon/health_check.h" +#include "mon/PGMap.h" + +class MMonMgrReport final : public PaxosServiceMessage { +private: + static constexpr int HEAD_VERSION = 3; + static constexpr int COMPAT_VERSION = 1; + +public: + // PGMapDigest is in data payload + health_check_map_t health_checks; + ceph::buffer::list service_map_bl; // encoded ServiceMap + std::map<std::string,ProgressEvent> progress_events; + uint64_t gid = 0; + + MMonMgrReport() + : PaxosServiceMessage{MSG_MON_MGR_REPORT, 0, HEAD_VERSION, COMPAT_VERSION} + {} +private: + ~MMonMgrReport() final {} + +public: + std::string_view get_type_name() const override { return "monmgrreport"; } + + void print(std::ostream& out) const override { + out << get_type_name() << "(gid " << gid + << ", " << health_checks.checks.size() << " checks, " + << progress_events.size() << " progress events)"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + paxos_encode(); + encode(health_checks, payload); + encode(service_map_bl, payload); + encode(progress_events, payload); + encode(gid, payload); + + if (!HAVE_FEATURE(features, SERVER_NAUTILUS) || + !HAVE_FEATURE(features, SERVER_MIMIC)) { + // PGMapDigest had a backwards-incompatible change between + // luminous and mimic, and conditionally encodes based on + // provided features, so reencode the one in our data payload. + // The mgr isn't able to do this at the time the encoded + // PGMapDigest is constructed because we don't know which mon we + // will target. Note that this only triggers if the user + // upgrades ceph-mgr before ceph-mon (tsk tsk). + PGMapDigest digest; + auto p = data.cbegin(); + decode(digest, p); + ceph::buffer::list bl; + encode(digest, bl, features); + set_data(bl); + } + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + paxos_decode(p); + decode(health_checks, p); + decode(service_map_bl, p); + if (header.version >= 2) { + decode(progress_events, p); + } + if (header.version >= 3) { + decode(gid, p); + } + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MMonPaxos.h b/src/messages/MMonPaxos.h new file mode 100644 index 000000000..e1aabc64c --- /dev/null +++ b/src/messages/MMonPaxos.h @@ -0,0 +1,135 @@ +// -*- 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_MMONPAXOS_H +#define CEPH_MMONPAXOS_H + +#include "messages/PaxosServiceMessage.h" +#include "mon/mon_types.h" +#include "include/ceph_features.h" + +class MMonPaxos final : public Message { +private: + static constexpr int HEAD_VERSION = 4; + static constexpr int COMPAT_VERSION = 3; + + public: + // op types + static constexpr int OP_COLLECT = 1; // proposer: propose round + static constexpr int OP_LAST = 2; // voter: accept proposed round + static constexpr int OP_BEGIN = 3; // proposer: value proposed for this round + static constexpr int OP_ACCEPT = 4; // voter: accept propsed value + static constexpr int OP_COMMIT = 5; // proposer: notify learners of agreed value + static constexpr int OP_LEASE = 6; // leader: extend peon lease + static constexpr int OP_LEASE_ACK = 7; // peon: lease ack + static const char *get_opname(int op) { + switch (op) { + case OP_COLLECT: return "collect"; + case OP_LAST: return "last"; + case OP_BEGIN: return "begin"; + case OP_ACCEPT: return "accept"; + case OP_COMMIT: return "commit"; + case OP_LEASE: return "lease"; + case OP_LEASE_ACK: return "lease_ack"; + default: ceph_abort(); return 0; + } + } + + epoch_t epoch = 0; // monitor epoch + __s32 op = 0; // paxos op + + version_t first_committed = 0; // i've committed to + version_t last_committed = 0; // i've committed to + version_t pn_from = 0; // i promise to accept after + version_t pn = 0; // with with proposal + version_t uncommitted_pn = 0; // previous pn, if we are a LAST with an uncommitted value + utime_t lease_timestamp; + utime_t sent_timestamp; + + version_t latest_version = 0; + ceph::buffer::list latest_value; + + std::map<version_t,ceph::buffer::list> values; + + ceph::buffer::list feature_map; + + MMonPaxos() : Message{MSG_MON_PAXOS, HEAD_VERSION, COMPAT_VERSION} { } + MMonPaxos(epoch_t e, int o, utime_t now) : + Message{MSG_MON_PAXOS, HEAD_VERSION, COMPAT_VERSION}, + epoch(e), + op(o), + first_committed(0), last_committed(0), pn_from(0), pn(0), uncommitted_pn(0), + sent_timestamp(now), + latest_version(0) { + } + +private: + ~MMonPaxos() final {} + +public: + std::string_view get_type_name() const override { return "paxos"; } + + void print(std::ostream& out) const override { + out << "paxos(" << get_opname(op) + << " lc " << last_committed + << " fc " << first_committed + << " pn " << pn << " opn " << uncommitted_pn; + if (latest_version) + out << " latest " << latest_version << " (" << latest_value.length() << " bytes)"; + out << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + header.version = HEAD_VERSION; + encode(epoch, payload); + encode(op, payload); + encode(first_committed, payload); + encode(last_committed, payload); + encode(pn_from, payload); + encode(pn, payload); + encode(uncommitted_pn, payload); + encode(lease_timestamp, payload); + encode(sent_timestamp, payload); + encode(latest_version, payload); + encode(latest_value, payload); + encode(values, payload); + encode(feature_map, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(epoch, p); + decode(op, p); + decode(first_committed, p); + decode(last_committed, p); + decode(pn_from, p); + decode(pn, p); + decode(uncommitted_pn, p); + decode(lease_timestamp, p); + decode(sent_timestamp, p); + decode(latest_version, p); + decode(latest_value, p); + decode(values, p); + if (header.version >= 4) { + decode(feature_map, p); + } + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MMonPing.h b/src/messages/MMonPing.h new file mode 100644 index 000000000..682094958 --- /dev/null +++ b/src/messages/MMonPing.h @@ -0,0 +1,109 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/** + * This is used to send pings between monitors for + * heartbeat purposes. We include a timestamp and distinguish between + * outgoing pings and responses to those. If you set the + * min_message in the constructor, the message will inflate itself + * to the specified size -- this is good for dealing with network + * issues with jumbo frames. See http://tracker.ceph.com/issues/20087 + * + */ + +#ifndef CEPH_MMONPING_H +#define CEPH_MMONPING_H + +#include "common/Clock.h" + +#include "msg/Message.h" +#include "mon/ConnectionTracker.h" + +class MMonPing final : public Message { +private: + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; + + public: + enum { + PING = 1, + PING_REPLY = 2, + }; + const char *get_op_name(int op) const { + switch (op) { + case PING: return "ping"; + case PING_REPLY: return "ping_reply"; + default: return "???"; + } + } + + __u8 op = 0; + utime_t stamp; + bufferlist tracker_bl; + uint32_t min_message_size = 0; + + MMonPing(__u8 o, utime_t s, const bufferlist& tbl, + uint32_t min_message) + : Message{MSG_MON_PING, HEAD_VERSION, COMPAT_VERSION}, + op(o), stamp(s), tracker_bl(tbl), min_message_size(min_message) + {} + MMonPing(__u8 o, utime_t s, const bufferlist& tbl) + : Message{MSG_MON_PING, HEAD_VERSION, COMPAT_VERSION}, + op(o), stamp(s), tracker_bl(tbl) {} + MMonPing() + : Message{MSG_MON_PING, HEAD_VERSION, COMPAT_VERSION} + {} +private: + ~MMonPing() final {} + +public: + void decode_payload() override { + auto p = payload.cbegin(); + decode(op, p); + decode(stamp, p); + decode(tracker_bl, p); + + int payload_mid_length = p.get_off(); + uint32_t size; + decode(size, p); + p += size; + min_message_size = size + payload_mid_length; + } + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(op, payload); + encode(stamp, payload); + encode(tracker_bl, payload); + + size_t s = 0; + if (min_message_size > payload.length()) { + s = min_message_size - payload.length(); + } + encode((uint32_t)s, payload); + if (s) { + // this should be big enough for normal min_message padding sizes. since + // we are targeting jumbo ethernet frames around 9000 bytes, 16k should + // be more than sufficient! the compiler will statically zero this so + // that at runtime we are only adding a bufferptr reference to it. + static char zeros[16384] = {}; + while (s > sizeof(zeros)) { + payload.append(buffer::create_static(sizeof(zeros), zeros)); + s -= sizeof(zeros); + } + if (s) { + payload.append(buffer::create_static(s, zeros)); + } + } + } + + std::string_view get_type_name() const override { return "mon_ping"; } + void print(ostream& out) const override { + out << "mon_ping(" << get_op_name(op) + << " stamp " << stamp + << ")"; + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MMonProbe.h b/src/messages/MMonProbe.h new file mode 100644 index 000000000..ae5fc3028 --- /dev/null +++ b/src/messages/MMonProbe.h @@ -0,0 +1,153 @@ +// -*- 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_MMONPROBE_H +#define CEPH_MMONPROBE_H + +#include "include/ceph_features.h" +#include "common/ceph_releases.h" +#include "msg/Message.h" +#include "mon/MonMap.h" + +class MMonProbe final : public Message { +public: + static constexpr int HEAD_VERSION = 8; + static constexpr int COMPAT_VERSION = 5; + + enum { + OP_PROBE = 1, + OP_REPLY = 2, + OP_SLURP = 3, + OP_SLURP_LATEST = 4, + OP_DATA = 5, + OP_MISSING_FEATURES = 6, + }; + + static const char *get_opname(int o) { + switch (o) { + case OP_PROBE: return "probe"; + case OP_REPLY: return "reply"; + case OP_SLURP: return "slurp"; + case OP_SLURP_LATEST: return "slurp_latest"; + case OP_DATA: return "data"; + case OP_MISSING_FEATURES: return "missing_features"; + default: ceph_abort(); return 0; + } + } + + uuid_d fsid; + int32_t op = 0; + std::string name; + std::set<int32_t> quorum; + int leader = -1; + ceph::buffer::list monmap_bl; + version_t paxos_first_version = 0; + version_t paxos_last_version = 0; + bool has_ever_joined = 0; + uint64_t required_features = 0; + ceph_release_t mon_release{ceph_release_t::unknown}; + + MMonProbe() + : Message{MSG_MON_PROBE, HEAD_VERSION, COMPAT_VERSION} {} + MMonProbe(const uuid_d& f, int o, const std::string& n, bool hej, ceph_release_t mr) + : Message{MSG_MON_PROBE, HEAD_VERSION, COMPAT_VERSION}, + fsid(f), + op(o), + name(n), + paxos_first_version(0), + paxos_last_version(0), + has_ever_joined(hej), + required_features(0), + mon_release{mr} {} +private: + ~MMonProbe() final {} + +public: + std::string_view get_type_name() const override { return "mon_probe"; } + void print(std::ostream& out) const override { + out << "mon_probe(" << get_opname(op) << " " << fsid << " name " << name; + if (quorum.size()) + out << " quorum " << quorum; + out << " leader " << leader; + if (op == OP_REPLY) { + out << " paxos(" + << " fc " << paxos_first_version + << " lc " << paxos_last_version + << " )"; + } + if (!has_ever_joined) + out << " new"; + if (required_features) + out << " required_features " << required_features; + if (mon_release != ceph_release_t::unknown) + out << " mon_release " << mon_release; + out << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + if (monmap_bl.length() && + ((features & CEPH_FEATURE_MONENC) == 0 || + (features & CEPH_FEATURE_MSG_ADDR2) == 0)) { + // reencode old-format monmap + MonMap t; + t.decode(monmap_bl); + monmap_bl.clear(); + t.encode(monmap_bl, features); + } + + encode(fsid, payload); + encode(op, payload); + encode(name, payload); + encode(quorum, payload); + encode(monmap_bl, payload); + encode(has_ever_joined, payload); + encode(paxos_first_version, payload); + encode(paxos_last_version, payload); + encode(required_features, payload); + encode(mon_release, payload); + encode(leader, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(fsid, p); + decode(op, p); + decode(name, p); + decode(quorum, p); + decode(monmap_bl, p); + decode(has_ever_joined, p); + decode(paxos_first_version, p); + decode(paxos_last_version, p); + if (header.version >= 6) + decode(required_features, p); + else + required_features = 0; + if (header.version >= 7) + decode(mon_release, p); + else + mon_release = ceph_release_t::unknown; + if (header.version >= 8) { + decode(leader, p); + } else if (quorum.size()) { + leader = *quorum.begin(); + } + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MMonQuorumService.h b/src/messages/MMonQuorumService.h new file mode 100644 index 000000000..23de9af51 --- /dev/null +++ b/src/messages/MMonQuorumService.h @@ -0,0 +1,70 @@ +// -*- 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) 2012 Inktank, Inc. + * + * 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_MMON_QUORUM_SERVICE_H +#define CEPH_MMON_QUORUM_SERVICE_H + +#include "msg/Message.h" + +class MMonQuorumService : public Message { +public: + epoch_t epoch = 0; + version_t round = 0; + +protected: + MMonQuorumService(int type, int head) + : Message{type, head, 1} + {} + ~MMonQuorumService() override {} + +public: + void set_epoch(epoch_t e) { + epoch = e; + } + + void set_round(version_t r) { + round = r; + } + + epoch_t get_epoch() const { + return epoch; + } + + version_t get_round() const { + return round; + } + + void service_encode() { + using ceph::encode; + encode(epoch, payload); + encode(round, payload); + } + + void service_decode(ceph::buffer::list::const_iterator &p) { + using ceph::decode; + decode(epoch, p); + decode(round, p); + } + + void encode_payload(uint64_t features) override { + ceph_abort_msg("MMonQuorumService message must always be a base class"); + } + + void decode_payload() override { + ceph_abort_msg("MMonQuorumService message must always be a base class"); + } + + std::string_view get_type_name() const override { return "quorum_service"; } +}; + +#endif /* CEPH_MMON_QUORUM_SERVICE_H */ diff --git a/src/messages/MMonScrub.h b/src/messages/MMonScrub.h new file mode 100644 index 000000000..b3b99b43f --- /dev/null +++ b/src/messages/MMonScrub.h @@ -0,0 +1,92 @@ +// -*- 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) 2013 Inktank, Inc. +* +* 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_MMONSCRUB_H +#define CEPH_MMONSCRUB_H + +#include "msg/Message.h" +#include "mon/mon_types.h" + +class MMonScrub : public Message { +private: + static constexpr int HEAD_VERSION = 2; + static constexpr int COMPAT_VERSION = 2; + +public: + typedef enum { + OP_SCRUB = 1, // leader->peon: scrub (a range of) keys + OP_RESULT = 2, // peon->leader: result of a scrub + } op_type_t; + + static const char *get_opname(op_type_t op) { + switch (op) { + case OP_SCRUB: return "scrub"; + case OP_RESULT: return "result"; + default: ceph_abort_msg("unknown op type"); return NULL; + } + } + + op_type_t op = OP_SCRUB; + version_t version = 0; + ScrubResult result; + int32_t num_keys; + std::pair<std::string,std::string> key; + + MMonScrub() + : Message{MSG_MON_SCRUB, HEAD_VERSION, COMPAT_VERSION}, + num_keys(-1) + { } + + MMonScrub(op_type_t op, version_t v, int32_t num_keys) + : Message{MSG_MON_SCRUB, HEAD_VERSION, COMPAT_VERSION}, + op(op), version(v), num_keys(num_keys) + { } + + std::string_view get_type_name() const override { return "mon_scrub"; } + + void print(std::ostream& out) const override { + out << "mon_scrub(" << get_opname((op_type_t)op); + out << " v " << version; + if (op == OP_RESULT) + out << " " << result; + out << " num_keys " << num_keys; + out << " key (" << key << ")"; + out << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + uint8_t o = op; + encode(o, payload); + encode(version, payload); + encode(result, payload); + encode(num_keys, payload); + encode(key, payload); + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + uint8_t o; + decode(o, p); + op = (op_type_t)o; + decode(version, p); + decode(result, p); + decode(num_keys, p); + decode(key, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif /* CEPH_MMONSCRUB_H */ diff --git a/src/messages/MMonSubscribe.h b/src/messages/MMonSubscribe.h new file mode 100644 index 000000000..55220b0ce --- /dev/null +++ b/src/messages/MMonSubscribe.h @@ -0,0 +1,103 @@ +// -*- 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_MMONSUBSCRIBE_H +#define CEPH_MMONSUBSCRIBE_H + +#include "msg/Message.h" +#include "include/ceph_features.h" + +/* + * compatibility with old crap + */ +struct ceph_mon_subscribe_item_old { + ceph_le64 unused; + ceph_le64 have; + __u8 onetime; +} __attribute__ ((packed)); +WRITE_RAW_ENCODER(ceph_mon_subscribe_item_old) + + +class MMonSubscribe final : public Message { +public: + static constexpr int HEAD_VERSION = 3; + static constexpr int COMPAT_VERSION = 1; + + std::string hostname; + std::map<std::string, ceph_mon_subscribe_item> what; + + MMonSubscribe() : Message{CEPH_MSG_MON_SUBSCRIBE, HEAD_VERSION, COMPAT_VERSION} { } +private: + ~MMonSubscribe() final {} + +public: + void sub_want(const char *w, version_t start, unsigned flags) { + what[w].start = start; + what[w].flags = flags; + } + + std::string_view get_type_name() const override { return "mon_subscribe"; } + void print(std::ostream& o) const override { + o << "mon_subscribe(" << what << ")"; + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + if (header.version < 2) { + std::map<std::string, ceph_mon_subscribe_item_old> oldwhat; + decode(oldwhat, p); + what.clear(); + for (auto q = oldwhat.begin(); q != oldwhat.end(); q++) { + if (q->second.have) + what[q->first].start = q->second.have + 1; + else + what[q->first].start = 0; + what[q->first].flags = 0; + if (q->second.onetime) + what[q->first].flags |= CEPH_SUBSCRIBE_ONETIME; + } + return; + } + decode(what, p); + if (header.version >= 3) { + decode(hostname, p); + } + } + void encode_payload(uint64_t features) override { + using ceph::encode; + if ((features & CEPH_FEATURE_SUBSCRIBE2) == 0) { + header.version = 0; + std::map<std::string, ceph_mon_subscribe_item_old> oldwhat; + for (auto q = what.begin(); q != what.end(); q++) { + if (q->second.start) + // warning: start=1 -> have=0, which was ambiguous + oldwhat[q->first].have = q->second.start - 1; + else + oldwhat[q->first].have = 0; + oldwhat[q->first].onetime = q->second.flags & CEPH_SUBSCRIBE_ONETIME; + } + encode(oldwhat, payload); + return; + } + header.version = HEAD_VERSION; + encode(what, payload); + encode(hostname, payload); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MMonSubscribeAck.h b/src/messages/MMonSubscribeAck.h new file mode 100644 index 000000000..2f6e2eddb --- /dev/null +++ b/src/messages/MMonSubscribeAck.h @@ -0,0 +1,55 @@ +// -*- 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_MMONSUBSCRIBEACK_H +#define CEPH_MMONSUBSCRIBEACK_H + +#include "msg/Message.h" + +class MMonSubscribeAck final : public Message { +public: + __u32 interval; + uuid_d fsid; + + MMonSubscribeAck() : Message{CEPH_MSG_MON_SUBSCRIBE_ACK}, + interval(0) { + } + MMonSubscribeAck(uuid_d& f, int i) : Message{CEPH_MSG_MON_SUBSCRIBE_ACK}, + interval(i), fsid(f) { } +private: + ~MMonSubscribeAck() final {} + +public: + std::string_view get_type_name() const override { return "mon_subscribe_ack"; } + void print(std::ostream& o) const override { + o << "mon_subscribe_ack(" << interval << "s)"; + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(interval, p); + decode(fsid, p); + } + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(interval, payload); + encode(fsid, payload); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MMonSync.h b/src/messages/MMonSync.h new file mode 100644 index 000000000..a9e6184be --- /dev/null +++ b/src/messages/MMonSync.h @@ -0,0 +1,116 @@ +// -*- 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) 2012 Inktank, Inc. +* +* 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_MMONSYNC_H +#define CEPH_MMONSYNC_H + +#include "msg/Message.h" + +class MMonSync : public Message { +private: + static constexpr int HEAD_VERSION = 2; + static constexpr int COMPAT_VERSION = 2; + +public: + /** + * Operation types + */ + enum { + OP_GET_COOKIE_FULL = 1, // -> start a session (full scan) + OP_GET_COOKIE_RECENT = 2, // -> start a session (only recent paxos events) + OP_COOKIE = 3, // <- pass the iterator cookie, or + OP_GET_CHUNK = 4, // -> get some keys + OP_CHUNK = 5, // <- return some keys + OP_LAST_CHUNK = 6, // <- return the last set of keys + OP_NO_COOKIE = 8, // <- sorry, no cookie + }; + + /** + * Obtain a string corresponding to the operation type @p op + * + * @param op Operation type + * @returns A string + */ + static const char *get_opname(int op) { + switch (op) { + case OP_GET_COOKIE_FULL: return "get_cookie_full"; + case OP_GET_COOKIE_RECENT: return "get_cookie_recent"; + case OP_COOKIE: return "cookie"; + case OP_GET_CHUNK: return "get_chunk"; + case OP_CHUNK: return "chunk"; + case OP_LAST_CHUNK: return "last_chunk"; + case OP_NO_COOKIE: return "no_cookie"; + default: ceph_abort_msg("unknown op type"); return NULL; + } + } + + uint32_t op = 0; + uint64_t cookie = 0; + version_t last_committed = 0; + std::pair<std::string,std::string> last_key; + ceph::buffer::list chunk_bl; + entity_inst_t reply_to; + + MMonSync() + : Message{MSG_MON_SYNC, HEAD_VERSION, COMPAT_VERSION} + { } + + MMonSync(uint32_t op, uint64_t c = 0) + : Message{MSG_MON_SYNC, HEAD_VERSION, COMPAT_VERSION}, + op(op), + cookie(c), + last_committed(0) + { } + + std::string_view get_type_name() const override { return "mon_sync"; } + + void print(std::ostream& out) const override { + out << "mon_sync(" << get_opname(op); + if (cookie) + out << " cookie " << cookie; + if (last_committed > 0) + out << " lc " << last_committed; + if (chunk_bl.length()) + out << " bl " << chunk_bl.length() << " bytes"; + if (!last_key.first.empty() || !last_key.second.empty()) + out << " last_key " << last_key.first << "," << last_key.second; + out << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(op, payload); + encode(cookie, payload); + encode(last_committed, payload); + encode(last_key.first, payload); + encode(last_key.second, payload); + encode(chunk_bl, payload); + encode(reply_to, payload, features); + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(op, p); + decode(cookie, p); + decode(last_committed, p); + decode(last_key.first, p); + decode(last_key.second, p); + decode(chunk_bl, p); + decode(reply_to, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif /* CEPH_MMONSYNC_H */ diff --git a/src/messages/MOSDAlive.h b/src/messages/MOSDAlive.h new file mode 100644 index 000000000..f43e9e266 --- /dev/null +++ b/src/messages/MOSDAlive.h @@ -0,0 +1,53 @@ +// -*- 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_MOSDALIVE_H +#define CEPH_MOSDALIVE_H + +#include "messages/PaxosServiceMessage.h" + +class MOSDAlive final : public PaxosServiceMessage { +public: + epoch_t want = 0; + + MOSDAlive(epoch_t h, epoch_t w) : PaxosServiceMessage{MSG_OSD_ALIVE, h}, want(w) {} + MOSDAlive() : MOSDAlive{0, 0} {} +private: + ~MOSDAlive() final {} + +public: + void encode_payload(uint64_t features) override { + paxos_encode(); + using ceph::encode; + encode(want, payload); + } + void decode_payload() override { + auto p = payload.cbegin(); + paxos_decode(p); + using ceph::decode; + decode(want, p); + } + + std::string_view get_type_name() const override { return "osd_alive"; } + void print(std::ostream &out) const override { + out << "osd_alive(want up_thru " << want << " have " << version << ")"; + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MOSDBackoff.h b/src/messages/MOSDBackoff.h new file mode 100644 index 000000000..82218d2fa --- /dev/null +++ b/src/messages/MOSDBackoff.h @@ -0,0 +1,86 @@ +// -*- 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) 2017 Red Hat + * + * 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_MOSDBACKOFF_H +#define CEPH_MOSDBACKOFF_H + +#include "MOSDFastDispatchOp.h" +#include "osd/osd_types.h" + +class MOSDBackoff : public MOSDFastDispatchOp { +public: + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; + + spg_t pgid; + epoch_t map_epoch = 0; + uint8_t op = 0; ///< CEPH_OSD_BACKOFF_OP_* + uint64_t id = 0; ///< unique id within this session + hobject_t begin, end; ///< [) range to block, unless ==, block single obj + + spg_t get_spg() const override { + return pgid; + } + epoch_t get_map_epoch() const override { + return map_epoch; + } + + MOSDBackoff() + : MOSDFastDispatchOp{CEPH_MSG_OSD_BACKOFF, HEAD_VERSION, COMPAT_VERSION} {} + MOSDBackoff(spg_t pgid_, epoch_t ep, uint8_t op_, uint64_t id_, + hobject_t begin_, hobject_t end_) + : MOSDFastDispatchOp{CEPH_MSG_OSD_BACKOFF, HEAD_VERSION, COMPAT_VERSION}, + pgid(pgid_), + map_epoch(ep), + op(op_), + id(id_), + begin(begin_), + end(end_) { } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(pgid, payload); + encode(map_epoch, payload); + encode(op, payload); + encode(id, payload); + encode(begin, payload); + encode(end, payload); + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(pgid, p); + decode(map_epoch, p); + decode(op, p); + decode(id, p); + decode(begin, p); + decode(end, p); + } + + std::string_view get_type_name() const override { return "osd_backoff"; } + + void print(std::ostream& out) const override { + out << "osd_backoff(" << pgid << " " << ceph_osd_backoff_op_name(op) + << " id " << id + << " [" << begin << "," << end << ")" + << " e" << map_epoch << ")"; + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MOSDBeacon.h b/src/messages/MOSDBeacon.h new file mode 100644 index 000000000..998d6e638 --- /dev/null +++ b/src/messages/MOSDBeacon.h @@ -0,0 +1,64 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#pragma once + +#include "PaxosServiceMessage.h" + +class MOSDBeacon : public PaxosServiceMessage { +private: + static constexpr int HEAD_VERSION = 3; + static constexpr int COMPAT_VERSION = 1; +public: + std::vector<pg_t> pgs; + epoch_t min_last_epoch_clean = 0; + utime_t last_purged_snaps_scrub; + int osd_beacon_report_interval = 0; + + MOSDBeacon() + : PaxosServiceMessage{MSG_OSD_BEACON, 0, + HEAD_VERSION, COMPAT_VERSION} + {} + MOSDBeacon(epoch_t e, epoch_t min_lec, utime_t ls, int interval) + : PaxosServiceMessage{MSG_OSD_BEACON, e, + HEAD_VERSION, COMPAT_VERSION}, + min_last_epoch_clean(min_lec), + last_purged_snaps_scrub(ls), + osd_beacon_report_interval(interval) + {} + void encode_payload(uint64_t features) override { + using ceph::encode; + paxos_encode(); + encode(pgs, payload); + encode(min_last_epoch_clean, payload); + encode(last_purged_snaps_scrub, payload); + encode(osd_beacon_report_interval, payload); + } + void decode_payload() override { + auto p = payload.cbegin(); + using ceph::decode; + paxos_decode(p); + decode(pgs, p); + decode(min_last_epoch_clean, p); + if (header.version >= 2) { + decode(last_purged_snaps_scrub, p); + } + if (header.version >= 3) { + decode(osd_beacon_report_interval, p); + } else { + osd_beacon_report_interval = 0; + } + } + std::string_view get_type_name() const override { return "osd_beacon"; } + void print(std::ostream &out) const { + out << get_type_name() + << "(pgs " << pgs + << " lec " << min_last_epoch_clean + << " last_purged_snaps_scrub " << last_purged_snaps_scrub + << " osd_beacon_report_interval " << osd_beacon_report_interval + << " v" << version << ")"; + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; diff --git a/src/messages/MOSDBoot.h b/src/messages/MOSDBoot.h new file mode 100644 index 000000000..d40324f4a --- /dev/null +++ b/src/messages/MOSDBoot.h @@ -0,0 +1,122 @@ +// -*- 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_MOSDBOOT_H +#define CEPH_MOSDBOOT_H + +#include "messages/PaxosServiceMessage.h" + +#include "include/ceph_features.h" +#include "include/types.h" +#include "osd/osd_types.h" + +class MOSDBoot final : public PaxosServiceMessage { +private: + static constexpr int HEAD_VERSION = 7; + static constexpr int COMPAT_VERSION = 7; + + public: + OSDSuperblock sb; + entity_addrvec_t hb_back_addrs, hb_front_addrs; + entity_addrvec_t cluster_addrs; + epoch_t boot_epoch; // last epoch this daemon was added to the map (if any) + std::map<std::string,std::string> metadata; ///< misc metadata about this osd + uint64_t osd_features; + + MOSDBoot() + : PaxosServiceMessage{MSG_OSD_BOOT, 0, HEAD_VERSION, COMPAT_VERSION}, + boot_epoch(0), osd_features(0) + { } + MOSDBoot(const OSDSuperblock& s, epoch_t e, epoch_t be, + const entity_addrvec_t& hb_back_addr_ref, + const entity_addrvec_t& hb_front_addr_ref, + const entity_addrvec_t& cluster_addr_ref, + uint64_t feat) + : PaxosServiceMessage{MSG_OSD_BOOT, e, HEAD_VERSION, COMPAT_VERSION}, + sb(s), + hb_back_addrs(hb_back_addr_ref), + hb_front_addrs(hb_front_addr_ref), + cluster_addrs(cluster_addr_ref), + boot_epoch(be), + osd_features(feat) + { } + +private: + ~MOSDBoot() final { } + +public: + std::string_view get_type_name() const override { return "osd_boot"; } + void print(std::ostream& out) const override { + out << "osd_boot(osd." << sb.whoami << " booted " << boot_epoch + << " features " << osd_features + << " v" << version << ")"; + } + + void encode_payload(uint64_t features) override { + header.version = HEAD_VERSION; + header.compat_version = COMPAT_VERSION; + using ceph::encode; + paxos_encode(); + if (!HAVE_FEATURE(features, SERVER_NAUTILUS)) { + header.version = 6; + header.compat_version = 6; + encode(sb, payload); + hb_back_addrs.legacy_addr().encode(payload, features); + cluster_addrs.legacy_addr().encode(payload, features); + encode(boot_epoch, payload); + hb_front_addrs.legacy_addr().encode(payload, features); + encode(metadata, payload); + encode(osd_features, payload); + return; + } + encode(sb, payload); + encode(hb_back_addrs, payload, features); + encode(cluster_addrs, payload, features); + encode(boot_epoch, payload); + encode(hb_front_addrs, payload, features); + encode(metadata, payload); + encode(osd_features, payload); + } + void decode_payload() override { + auto p = payload.cbegin(); + using ceph::decode; + paxos_decode(p); + if (header.version < 7) { + entity_addr_t a; + decode(sb, p); + decode(a, p); + hb_back_addrs = entity_addrvec_t(a); + decode(a, p); + cluster_addrs = entity_addrvec_t(a); + decode(boot_epoch, p); + decode(a, p); + hb_front_addrs = entity_addrvec_t(a); + decode(metadata, p); + decode(osd_features, p); + return; + } + decode(sb, p); + decode(hb_back_addrs, p); + decode(cluster_addrs, p); + decode(boot_epoch, p); + decode(hb_front_addrs, p); + decode(metadata, p); + decode(osd_features, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MOSDECSubOpRead.h b/src/messages/MOSDECSubOpRead.h new file mode 100644 index 000000000..254357f13 --- /dev/null +++ b/src/messages/MOSDECSubOpRead.h @@ -0,0 +1,84 @@ +// -*- 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) 2013 Inktank Storage, Inc. + * + * 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 MOSDECSUBOPREAD_H +#define MOSDECSUBOPREAD_H + +#include "MOSDFastDispatchOp.h" +#include "osd/ECMsgTypes.h" + +class MOSDECSubOpRead : public MOSDFastDispatchOp { +private: + static constexpr int HEAD_VERSION = 3; + static constexpr int COMPAT_VERSION = 1; + +public: + spg_t pgid; + epoch_t map_epoch = 0, min_epoch = 0; + ECSubRead op; + + int get_cost() const override { + return 0; + } + epoch_t get_map_epoch() const override { + return map_epoch; + } + epoch_t get_min_epoch() const override { + return min_epoch; + } + spg_t get_spg() const override { + return pgid; + } + + MOSDECSubOpRead() + : MOSDFastDispatchOp{MSG_OSD_EC_READ, HEAD_VERSION, COMPAT_VERSION} + {} + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(pgid, p); + decode(map_epoch, p); + decode(op, p); + if (header.version >= 3) { + decode(min_epoch, p); + decode_trace(p); + } else { + min_epoch = map_epoch; + } + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(pgid, payload); + encode(map_epoch, payload); + encode(op, payload, features); + encode(min_epoch, payload); + encode_trace(payload, features); + } + + std::string_view get_type_name() const override { return "MOSDECSubOpRead"; } + + void print(std::ostream& out) const override { + out << "MOSDECSubOpRead(" << pgid + << " " << map_epoch << "/" << min_epoch + << " " << op; + out << ")"; + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MOSDECSubOpReadReply.h b/src/messages/MOSDECSubOpReadReply.h new file mode 100644 index 000000000..b71c22db4 --- /dev/null +++ b/src/messages/MOSDECSubOpReadReply.h @@ -0,0 +1,84 @@ +// -*- 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) 2013 Inktank Storage, Inc. + * + * 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 MOSDECSUBOPREADREPLY_H +#define MOSDECSUBOPREADREPLY_H + +#include "MOSDFastDispatchOp.h" +#include "osd/ECMsgTypes.h" + +class MOSDECSubOpReadReply : public MOSDFastDispatchOp { +private: + static constexpr int HEAD_VERSION = 2; + static constexpr int COMPAT_VERSION = 1; + +public: + spg_t pgid; + epoch_t map_epoch = 0, min_epoch = 0; + ECSubReadReply op; + + int get_cost() const override { + return 0; + } + epoch_t get_map_epoch() const override { + return map_epoch; + } + epoch_t get_min_epoch() const override { + return min_epoch; + } + spg_t get_spg() const override { + return pgid; + } + + MOSDECSubOpReadReply() + : MOSDFastDispatchOp{MSG_OSD_EC_READ_REPLY, HEAD_VERSION, COMPAT_VERSION} + {} + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(pgid, p); + decode(map_epoch, p); + decode(op, p); + if (header.version >= 2) { + decode(min_epoch, p); + decode_trace(p); + } else { + min_epoch = map_epoch; + } + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(pgid, payload); + encode(map_epoch, payload); + encode(op, payload); + encode(min_epoch, payload); + encode_trace(payload, features); + } + + std::string_view get_type_name() const override { return "MOSDECSubOpReadReply"; } + + void print(std::ostream& out) const override { + out << "MOSDECSubOpReadReply(" << pgid + << " " << map_epoch << "/" << min_epoch + << " " << op; + out << ")"; + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MOSDECSubOpWrite.h b/src/messages/MOSDECSubOpWrite.h new file mode 100644 index 000000000..e1e37d096 --- /dev/null +++ b/src/messages/MOSDECSubOpWrite.h @@ -0,0 +1,93 @@ +// -*- 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) 2013 Inktank Storage, Inc. + * + * 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 MOSDECSUBOPWRITE_H +#define MOSDECSUBOPWRITE_H + +#include "MOSDFastDispatchOp.h" +#include "osd/ECMsgTypes.h" + +class MOSDECSubOpWrite : public MOSDFastDispatchOp { +private: + static constexpr int HEAD_VERSION = 2; + static constexpr int COMPAT_VERSION = 1; + +public: + spg_t pgid; + epoch_t map_epoch = 0, min_epoch = 0; + ECSubWrite op; + + int get_cost() const override { + return 0; + } + epoch_t get_map_epoch() const override { + return map_epoch; + } + epoch_t get_min_epoch() const override { + return min_epoch; + } + spg_t get_spg() const override { + return pgid; + } + + MOSDECSubOpWrite() + : MOSDFastDispatchOp{MSG_OSD_EC_WRITE, HEAD_VERSION, COMPAT_VERSION} + {} + MOSDECSubOpWrite(ECSubWrite &in_op) + : MOSDFastDispatchOp{MSG_OSD_EC_WRITE, HEAD_VERSION, COMPAT_VERSION} { + op.claim(in_op); + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(pgid, p); + decode(map_epoch, p); + decode(op, p); + if (header.version >= 2) { + decode(min_epoch, p); + decode_trace(p); + } else { + min_epoch = map_epoch; + } + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(pgid, payload); + encode(map_epoch, payload); + encode(op, payload); + encode(min_epoch, payload); + encode_trace(payload, features); + } + + std::string_view get_type_name() const override { return "MOSDECSubOpWrite"; } + + void print(std::ostream& out) const override { + out << "MOSDECSubOpWrite(" << pgid + << " " << map_epoch << "/" << min_epoch + << " " << op; + out << ")"; + } + + void clear_buffers() override { + op.t = ObjectStore::Transaction(); + op.log_entries.clear(); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MOSDECSubOpWriteReply.h b/src/messages/MOSDECSubOpWriteReply.h new file mode 100644 index 000000000..7a813d283 --- /dev/null +++ b/src/messages/MOSDECSubOpWriteReply.h @@ -0,0 +1,84 @@ +// -*- 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) 2013 Inktank Storage, Inc. + * + * 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 MOSDECSUBOPWRITEREPLY_H +#define MOSDECSUBOPWRITEREPLY_H + +#include "MOSDFastDispatchOp.h" +#include "osd/ECMsgTypes.h" + +class MOSDECSubOpWriteReply : public MOSDFastDispatchOp { +private: + static constexpr int HEAD_VERSION = 2; + static constexpr int COMPAT_VERSION = 1; + +public: + spg_t pgid; + epoch_t map_epoch = 0, min_epoch = 0; + ECSubWriteReply op; + + int get_cost() const override { + return 0; + } + epoch_t get_map_epoch() const override { + return map_epoch; + } + epoch_t get_min_epoch() const override { + return min_epoch; + } + spg_t get_spg() const override { + return pgid; + } + + MOSDECSubOpWriteReply() + : MOSDFastDispatchOp{MSG_OSD_EC_WRITE_REPLY, HEAD_VERSION, COMPAT_VERSION} + {} + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(pgid, p); + decode(map_epoch, p); + decode(op, p); + if (header.version >= 2) { + decode(min_epoch, p); + decode_trace(p); + } else { + min_epoch = map_epoch; + } + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(pgid, payload); + encode(map_epoch, payload); + encode(op, payload); + encode(min_epoch, payload); + encode_trace(payload, features); + } + + std::string_view get_type_name() const override { return "MOSDECSubOpWriteReply"; } + + void print(std::ostream& out) const override { + out << "MOSDECSubOpWriteReply(" << pgid + << " " << map_epoch << "/" << min_epoch + << " " << op; + out << ")"; + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MOSDFailure.h b/src/messages/MOSDFailure.h new file mode 100644 index 000000000..72aa644ed --- /dev/null +++ b/src/messages/MOSDFailure.h @@ -0,0 +1,130 @@ +// -*- 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_MOSDFAILURE_H +#define CEPH_MOSDFAILURE_H + +#include "messages/PaxosServiceMessage.h" + + +class MOSDFailure final : public PaxosServiceMessage { +private: + static constexpr int HEAD_VERSION = 4; + static constexpr int COMPAT_VERSION = 4; + + public: + enum { + FLAG_ALIVE = 0, // use this on its own to mark as "I'm still alive" + FLAG_FAILED = 1, // if set, failure; if not, recovery + FLAG_IMMEDIATE = 2, // known failure, not a timeout + }; + + uuid_d fsid; + int32_t target_osd; + entity_addrvec_t target_addrs; + __u8 flags = 0; + epoch_t epoch = 0; + int32_t failed_for = 0; // known to be failed since at least this long + + MOSDFailure() : PaxosServiceMessage(MSG_OSD_FAILURE, 0, HEAD_VERSION) { } + MOSDFailure(const uuid_d &fs, int osd, const entity_addrvec_t& av, + int duration, epoch_t e) + : PaxosServiceMessage(MSG_OSD_FAILURE, e, HEAD_VERSION, COMPAT_VERSION), + fsid(fs), + target_osd(osd), + target_addrs(av), + flags(FLAG_FAILED), + epoch(e), failed_for(duration) { } + MOSDFailure(const uuid_d &fs, int osd, const entity_addrvec_t& av, + int duration, + epoch_t e, __u8 extra_flags) + : PaxosServiceMessage(MSG_OSD_FAILURE, e, HEAD_VERSION, COMPAT_VERSION), + fsid(fs), + target_osd(osd), + target_addrs(av), + flags(extra_flags), + epoch(e), failed_for(duration) { } +private: + ~MOSDFailure() final {} + +public: + int get_target_osd() { return target_osd; } + const entity_addrvec_t& get_target_addrs() { return target_addrs; } + bool if_osd_failed() const { + return flags & FLAG_FAILED; + } + bool is_immediate() const { + return flags & FLAG_IMMEDIATE; + } + epoch_t get_epoch() const { return epoch; } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + paxos_decode(p); + decode(fsid, p); + if (header.version < 4) { + entity_inst_t i; + decode(i, p); + target_osd = i.name.num(); + target_addrs.v.push_back(i.addr); + } else { + decode(target_osd, p); + decode(target_addrs, p); + } + decode(epoch, p); + decode(flags, p); + decode(failed_for, p); + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + paxos_encode(); + if (!HAVE_FEATURE(features, SERVER_NAUTILUS)) { + header.version = 3; + header.compat_version = 3; + encode(fsid, payload); + encode(entity_inst_t(entity_name_t::OSD(target_osd), + target_addrs.legacy_addr()), payload, features); + encode(epoch, payload); + encode(flags, payload); + encode(failed_for, payload); + return; + } + header.version = HEAD_VERSION; + header.compat_version = COMPAT_VERSION; + encode(fsid, payload); + encode(target_osd, payload, features); + encode(target_addrs, payload, features); + encode(epoch, payload); + encode(flags, payload); + encode(failed_for, payload); + } + + std::string_view get_type_name() const override { return "osd_failure"; } + void print(std::ostream& out) const override { + out << "osd_failure(" + << (if_osd_failed() ? "failed " : "recovered ") + << (is_immediate() ? "immediate " : "timeout ") + << "osd." << target_osd << " " << target_addrs + << " for " << failed_for << "sec e" << epoch + << " v" << version << ")"; + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MOSDFastDispatchOp.h b/src/messages/MOSDFastDispatchOp.h new file mode 100644 index 000000000..d1103fb88 --- /dev/null +++ b/src/messages/MOSDFastDispatchOp.h @@ -0,0 +1,22 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef CEPH_MOSDFASTDISPATCHOP_H +#define CEPH_MOSDFASTDISPATCHOP_H + +#include "msg/Message.h" +#include "osd/osd_types.h" + +class MOSDFastDispatchOp : public Message { +public: + MOSDFastDispatchOp(int t, int version, int compat_version) + : Message{t, version, compat_version} + {} + virtual epoch_t get_map_epoch() const = 0; + virtual epoch_t get_min_epoch() const { + return get_map_epoch(); + } + virtual spg_t get_spg() const = 0; +}; + +#endif diff --git a/src/messages/MOSDForceRecovery.h b/src/messages/MOSDForceRecovery.h new file mode 100644 index 000000000..2d9ccc0e0 --- /dev/null +++ b/src/messages/MOSDForceRecovery.h @@ -0,0 +1,114 @@ +// -*- 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) 2017 OVH + * + * 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_MOSDFORCERECOVERY_H +#define CEPH_MOSDFORCERECOVERY_H + +#include "msg/Message.h" + +/* + * instruct an OSD to boost/unboost recovery/backfill priority of some or all pg(s) + */ + +// boost priority of recovery +static const int OFR_RECOVERY = 1; + +// boost priority of backfill +static const int OFR_BACKFILL = 2; + +// cancel priority boost, requeue if necessary +static const int OFR_CANCEL = 4; + +class MOSDForceRecovery final : public Message { +public: + static constexpr int HEAD_VERSION = 2; + static constexpr int COMPAT_VERSION = 2; + + uuid_d fsid; + std::vector<spg_t> forced_pgs; + uint8_t options = 0; + + MOSDForceRecovery() : Message{MSG_OSD_FORCE_RECOVERY, HEAD_VERSION, COMPAT_VERSION} {} + MOSDForceRecovery(const uuid_d& f, char opts) : + Message{MSG_OSD_FORCE_RECOVERY, HEAD_VERSION, COMPAT_VERSION}, + fsid(f), options(opts) {} + MOSDForceRecovery(const uuid_d& f, std::vector<spg_t>& pgs, char opts) : + Message{MSG_OSD_FORCE_RECOVERY, HEAD_VERSION, COMPAT_VERSION}, + fsid(f), forced_pgs(pgs), options(opts) {} +private: + ~MOSDForceRecovery() final {} + +public: + std::string_view get_type_name() const { return "force_recovery"; } + void print(std::ostream& out) const { + out << "force_recovery("; + if (forced_pgs.empty()) + out << "osd"; + else + out << forced_pgs; + if (options & OFR_RECOVERY) + out << " recovery"; + if (options & OFR_BACKFILL) + out << " backfill"; + if (options & OFR_CANCEL) + out << " cancel"; + out << ")"; + } + + void encode_payload(uint64_t features) { + using ceph::encode; + if (!HAVE_FEATURE(features, SERVER_MIMIC)) { + header.version = 1; + header.compat_version = 1; + std::vector<pg_t> pgs; + for (auto pgid : forced_pgs) { + pgs.push_back(pgid.pgid); + } + encode(fsid, payload); + encode(pgs, payload); + encode(options, payload); + return; + } + header.version = HEAD_VERSION; + header.compat_version = COMPAT_VERSION; + encode(fsid, payload); + encode(forced_pgs, payload); + encode(options, payload); + } + void decode_payload() { + using ceph::decode; + auto p = payload.cbegin(); + if (header.version == 1) { + std::vector<pg_t> pgs; + decode(fsid, p); + decode(pgs, p); + decode(options, p); + for (auto pg : pgs) { + // note: this only works with replicated pools. if a pre-mimic mon + // tries to force a mimic+ osd on an ec pool it will not work. + forced_pgs.push_back(spg_t(pg)); + } + return; + } + decode(fsid, p); + decode(forced_pgs, p); + decode(options, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif /* CEPH_MOSDFORCERECOVERY_H_ */ diff --git a/src/messages/MOSDFull.h b/src/messages/MOSDFull.h new file mode 100644 index 000000000..89f5b8402 --- /dev/null +++ b/src/messages/MOSDFull.h @@ -0,0 +1,54 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef CEPH_MOSDFULL_H +#define CEPH_MOSDFULL_H + +#include "messages/PaxosServiceMessage.h" +#include "osd/OSDMap.h" + +// tell the mon to update the full/nearfull bits. note that in the +// future this message could be generalized to other state bits, but +// for now name it for its sole application. + +class MOSDFull final : public PaxosServiceMessage { +public: + epoch_t map_epoch = 0; + uint32_t state = 0; + +private: + ~MOSDFull() final {} + +public: + MOSDFull(epoch_t e, unsigned s) + : PaxosServiceMessage{MSG_OSD_FULL, e}, map_epoch(e), state(s) { } + MOSDFull() + : PaxosServiceMessage{MSG_OSD_FULL, 0} {} + +public: + void encode_payload(uint64_t features) { + using ceph::encode; + paxos_encode(); + encode(map_epoch, payload); + encode(state, payload); + } + void decode_payload() { + using ceph::decode; + auto p = payload.cbegin(); + paxos_decode(p); + decode(map_epoch, p); + decode(state, p); + } + + std::string_view get_type_name() const { return "osd_full"; } + void print(std::ostream &out) const { + std::set<std::string> states; + OSDMap::calc_state_set(state, states); + out << "osd_full(e" << map_epoch << " " << states << " v" << version << ")"; + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MOSDMap.h b/src/messages/MOSDMap.h new file mode 100644 index 000000000..4a57011c4 --- /dev/null +++ b/src/messages/MOSDMap.h @@ -0,0 +1,166 @@ +// -*- 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_MOSDMAP_H +#define CEPH_MOSDMAP_H + +#include "msg/Message.h" +#include "osd/OSDMap.h" +#include "include/ceph_features.h" + +class MOSDMap final : public Message { +private: + static constexpr int HEAD_VERSION = 4; + static constexpr int COMPAT_VERSION = 3; + +public: + uuid_d fsid; + uint64_t encode_features = 0; + std::map<epoch_t, ceph::buffer::list> maps; + std::map<epoch_t, ceph::buffer::list> incremental_maps; + epoch_t oldest_map =0, newest_map = 0; + + epoch_t get_first() const { + epoch_t e = 0; + auto i = maps.cbegin(); + if (i != maps.cend()) e = i->first; + i = incremental_maps.begin(); + if (i != incremental_maps.end() && + (e == 0 || i->first < e)) e = i->first; + return e; + } + epoch_t get_last() const { + epoch_t e = 0; + auto i = maps.crbegin(); + if (i != maps.crend()) e = i->first; + i = incremental_maps.rbegin(); + if (i != incremental_maps.rend() && + (e == 0 || i->first > e)) e = i->first; + return e; + } + epoch_t get_oldest() { + return oldest_map; + } + epoch_t get_newest() { + return newest_map; + } + + + MOSDMap() : Message{CEPH_MSG_OSD_MAP, HEAD_VERSION, COMPAT_VERSION} { } + MOSDMap(const uuid_d &f, const uint64_t features) + : Message{CEPH_MSG_OSD_MAP, HEAD_VERSION, COMPAT_VERSION}, + fsid(f), encode_features(features), + oldest_map(0), newest_map(0) { } +private: + ~MOSDMap() final {} +public: + // marshalling + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(fsid, p); + decode(incremental_maps, p); + decode(maps, p); + if (header.version >= 2) { + decode(oldest_map, p); + decode(newest_map, p); + } else { + oldest_map = 0; + newest_map = 0; + } + if (header.version >= 4) { + // removed in octopus + mempool::osdmap::map<int64_t,snap_interval_set_t> gap_removed_snaps; + decode(gap_removed_snaps, p); + } + } + void encode_payload(uint64_t features) override { + using ceph::encode; + header.version = HEAD_VERSION; + header.compat_version = COMPAT_VERSION; + encode(fsid, payload); + if (OSDMap::get_significant_features(encode_features) != + OSDMap::get_significant_features(features)) { + if ((features & CEPH_FEATURE_PGID64) == 0 || + (features & CEPH_FEATURE_PGPOOL3) == 0) { + header.version = 1; // old old_client version + header.compat_version = 1; + } else if ((features & CEPH_FEATURE_OSDENC) == 0) { + header.version = 2; // old pg_pool_t + header.compat_version = 2; + } + + // reencode maps using old format + // + // FIXME: this can probably be done more efficiently higher up + // the stack, or maybe replaced with something that only + // includes the pools the client cares about. + for (auto p = incremental_maps.begin(); p != incremental_maps.end(); ++p) { + OSDMap::Incremental inc; + auto q = p->second.cbegin(); + inc.decode(q); + // always encode with subset of osdmaps canonical features + uint64_t f = inc.encode_features & features; + p->second.clear(); + if (inc.fullmap.length()) { + // embedded full std::map? + OSDMap m; + m.decode(inc.fullmap); + inc.fullmap.clear(); + m.encode(inc.fullmap, f | CEPH_FEATURE_RESERVED); + } + if (inc.crush.length()) { + // embedded crush std::map + CrushWrapper c; + auto p = inc.crush.cbegin(); + c.decode(p); + inc.crush.clear(); + c.encode(inc.crush, f); + } + inc.encode(p->second, f | CEPH_FEATURE_RESERVED); + } + for (auto p = maps.begin(); p != maps.end(); ++p) { + OSDMap m; + m.decode(p->second); + // always encode with subset of osdmaps canonical features + uint64_t f = m.get_encoding_features() & features; + p->second.clear(); + m.encode(p->second, f | CEPH_FEATURE_RESERVED); + } + } + encode(incremental_maps, payload); + encode(maps, payload); + if (header.version >= 2) { + encode(oldest_map, payload); + encode(newest_map, payload); + } + if (header.version >= 4) { + encode((uint32_t)0, payload); + } + } + + std::string_view get_type_name() const override { return "osdmap"; } + void print(std::ostream& out) const override { + out << "osd_map(" << get_first() << ".." << get_last(); + if (oldest_map || newest_map) + out << " src has " << oldest_map << ".." << newest_map; + out << ")"; + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MOSDMarkMeDead.h b/src/messages/MOSDMarkMeDead.h new file mode 100644 index 000000000..35f988055 --- /dev/null +++ b/src/messages/MOSDMarkMeDead.h @@ -0,0 +1,63 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#pragma once + +#include "messages/PaxosServiceMessage.h" + +class MOSDMarkMeDead final : public PaxosServiceMessage { +private: + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; + + public: + uuid_d fsid; + int32_t target_osd; + epoch_t epoch = 0; + + MOSDMarkMeDead() + : PaxosServiceMessage{MSG_OSD_MARK_ME_DEAD, 0, + HEAD_VERSION, COMPAT_VERSION} { } + MOSDMarkMeDead(const uuid_d &fs, int osd, + epoch_t e) + : PaxosServiceMessage{MSG_OSD_MARK_ME_DEAD, e, + HEAD_VERSION, COMPAT_VERSION}, + fsid(fs), target_osd(osd), + epoch(e) {} + private: + ~MOSDMarkMeDead() final {} + +public: + epoch_t get_epoch() const { return epoch; } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + paxos_decode(p); + decode(fsid, p); + decode(target_osd, p); + decode(epoch, p); + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + paxos_encode(); + header.version = HEAD_VERSION; + header.compat_version = COMPAT_VERSION; + encode(fsid, payload); + encode(target_osd, payload, features); + encode(epoch, payload); + } + + std::string_view get_type_name() const override { return "MOSDMarkMeDead"; } + void print(std::ostream& out) const override { + out << "MOSDMarkMeDead(" + << "osd." << target_osd + << ", epoch " << epoch + << ", fsid=" << fsid + << ")"; + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; diff --git a/src/messages/MOSDMarkMeDown.h b/src/messages/MOSDMarkMeDown.h new file mode 100644 index 000000000..44d57395f --- /dev/null +++ b/src/messages/MOSDMarkMeDown.h @@ -0,0 +1,116 @@ +// -*- 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) 2013 Inktank Storage, Inc. + * + * 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_MOSDMARKMEDOWN_H +#define CEPH_MOSDMARKMEDOWN_H + +#include "messages/PaxosServiceMessage.h" + +class MOSDMarkMeDown final : public PaxosServiceMessage { +private: + static constexpr int HEAD_VERSION = 4; + static constexpr int COMPAT_VERSION = 3; + + public: + uuid_d fsid; + int32_t target_osd; + entity_addrvec_t target_addrs; + epoch_t epoch = 0; + bool request_ack = false; // ack requested + bool down_and_dead = false; // mark down and dead + + MOSDMarkMeDown() + : PaxosServiceMessage{MSG_OSD_MARK_ME_DOWN, 0, + HEAD_VERSION, COMPAT_VERSION} { } + MOSDMarkMeDown(const uuid_d &fs, int osd, const entity_addrvec_t& av, + epoch_t e, bool request_ack) + : PaxosServiceMessage{MSG_OSD_MARK_ME_DOWN, e, + HEAD_VERSION, COMPAT_VERSION}, + fsid(fs), target_osd(osd), target_addrs(av), + epoch(e), request_ack(request_ack) {} + MOSDMarkMeDown(const uuid_d &fs, int osd, const entity_addrvec_t& av, + epoch_t e, bool request_ack, bool down_and_dead) + : PaxosServiceMessage{MSG_OSD_MARK_ME_DOWN, e, + HEAD_VERSION, COMPAT_VERSION}, + fsid(fs), target_osd(osd), target_addrs(av), + epoch(e), request_ack(request_ack), down_and_dead(down_and_dead) {} + private: + ~MOSDMarkMeDown() final {} + +public: + epoch_t get_epoch() const { return epoch; } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + paxos_decode(p); + if (header.version <= 2) { + decode(fsid, p); + entity_inst_t i; + decode(i, p); + target_osd = i.name.num(); + target_addrs = entity_addrvec_t(i.addr); + decode(epoch, p); + decode(request_ack, p); + return; + } + decode(fsid, p); + decode(target_osd, p); + decode(target_addrs, p); + decode(epoch, p); + decode(request_ack, p); + if(header.version >= 4) + decode(down_and_dead, p); + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + paxos_encode(); + if (!HAVE_FEATURE(features, SERVER_NAUTILUS)) { + header.version = 2; + header.compat_version = 2; + encode(fsid, payload); + encode(entity_inst_t(entity_name_t::OSD(target_osd), + target_addrs.legacy_addr()), + payload, features); + encode(epoch, payload); + encode(request_ack, payload); + return; + } + header.version = HEAD_VERSION; + header.compat_version = COMPAT_VERSION; + encode(fsid, payload); + encode(target_osd, payload, features); + encode(target_addrs, payload, features); + encode(epoch, payload); + encode(request_ack, payload); + encode(down_and_dead, payload); + } + + std::string_view get_type_name() const override { return "MOSDMarkMeDown"; } + void print(std::ostream& out) const override { + out << "MOSDMarkMeDown(" + << "request_ack=" << request_ack + << ", down_and_dead=" << down_and_dead + << ", osd." << target_osd + << ", " << target_addrs + << ", fsid=" << fsid + << ")"; + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MOSDOp.h b/src/messages/MOSDOp.h new file mode 100644 index 000000000..2275c4588 --- /dev/null +++ b/src/messages/MOSDOp.h @@ -0,0 +1,608 @@ +// -*- 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_MOSDOP_H +#define CEPH_MOSDOP_H + +#include <atomic> + +#include "MOSDFastDispatchOp.h" +#include "include/ceph_features.h" +#include "common/hobject.h" + +/* + * OSD op + * + * oid - object id + * op - OSD_OP_DELETE, etc. + * + */ + +class MOSDOpReply; + +namespace _mosdop { +template<typename V> +class MOSDOp final : public MOSDFastDispatchOp { +private: + static constexpr int HEAD_VERSION = 8; + static constexpr int COMPAT_VERSION = 3; + +private: + uint32_t client_inc = 0; + __u32 osdmap_epoch = 0; + __u32 flags = 0; + utime_t mtime; + int32_t retry_attempt = -1; // 0 is first attempt. -1 if we don't know. + + hobject_t hobj; + spg_t pgid; + ceph::buffer::list::const_iterator p; + // Decoding flags. Decoding is only needed for messages caught by pipe reader. + // Transition from true -> false without locks being held + // Can never see final_decode_needed == false and partial_decode_needed == true + std::atomic<bool> partial_decode_needed; + std::atomic<bool> final_decode_needed; + // +public: + V ops; +private: + snapid_t snap_seq; + std::vector<snapid_t> snaps; + + uint64_t features; + bool bdata_encode; + osd_reqid_t reqid; // reqid explicitly set by sender + +public: + friend MOSDOpReply; + + ceph_tid_t get_client_tid() { return header.tid; } + void set_snapid(const snapid_t& s) { + hobj.snap = s; + } + void set_snaps(const std::vector<snapid_t>& i) { + snaps = i; + } + void set_snap_seq(const snapid_t& s) { snap_seq = s; } + void set_reqid(const osd_reqid_t rid) { + reqid = rid; + } + void set_spg(spg_t p) { + pgid = p; + } + + // Fields decoded in partial decoding + pg_t get_pg() const { + ceph_assert(!partial_decode_needed); + return pgid.pgid; + } + spg_t get_spg() const override { + ceph_assert(!partial_decode_needed); + return pgid; + } + pg_t get_raw_pg() const { + ceph_assert(!partial_decode_needed); + return pg_t(hobj.get_hash(), pgid.pgid.pool()); + } + epoch_t get_map_epoch() const override { + ceph_assert(!partial_decode_needed); + return osdmap_epoch; + } + int get_flags() const { + ceph_assert(!partial_decode_needed); + return flags; + } + osd_reqid_t get_reqid() const { + ceph_assert(!partial_decode_needed); + if (reqid.name != entity_name_t() || reqid.tid != 0) { + return reqid; + } else { + if (!final_decode_needed) + ceph_assert(reqid.inc == (int32_t)client_inc); // decode() should have done this + return osd_reqid_t(get_orig_source(), + reqid.inc, + header.tid); + } + } + + // Fields decoded in final decoding + int get_client_inc() const { + ceph_assert(!final_decode_needed); + return client_inc; + } + utime_t get_mtime() const { + ceph_assert(!final_decode_needed); + return mtime; + } + object_locator_t get_object_locator() const { + ceph_assert(!final_decode_needed); + if (hobj.oid.name.empty()) + return object_locator_t(hobj.pool, hobj.nspace, hobj.get_hash()); + else + return object_locator_t(hobj); + } + const object_t& get_oid() const { + ceph_assert(!final_decode_needed); + return hobj.oid; + } + const hobject_t &get_hobj() const { + return hobj; + } + snapid_t get_snapid() const { + ceph_assert(!final_decode_needed); + return hobj.snap; + } + const snapid_t& get_snap_seq() const { + ceph_assert(!final_decode_needed); + return snap_seq; + } + const std::vector<snapid_t> &get_snaps() const { + ceph_assert(!final_decode_needed); + return snaps; + } + + /** + * get retry attempt + * + * 0 is the first attempt. + * + * @return retry attempt, or -1 if we don't know + */ + int get_retry_attempt() const { + return retry_attempt; + } + uint64_t get_features() const { + if (features) + return features; + return get_connection()->get_features(); + } + + MOSDOp() + : MOSDFastDispatchOp(CEPH_MSG_OSD_OP, HEAD_VERSION, COMPAT_VERSION), + partial_decode_needed(true), + final_decode_needed(true), + bdata_encode(false) { } + MOSDOp(int inc, long tid, const hobject_t& ho, spg_t& _pgid, + epoch_t _osdmap_epoch, + int _flags, uint64_t feat) + : MOSDFastDispatchOp(CEPH_MSG_OSD_OP, HEAD_VERSION, COMPAT_VERSION), + client_inc(inc), + osdmap_epoch(_osdmap_epoch), flags(_flags), retry_attempt(-1), + hobj(ho), + pgid(_pgid), + partial_decode_needed(false), + final_decode_needed(false), + features(feat), + bdata_encode(false) { + set_tid(tid); + + // also put the client_inc in reqid.inc, so that get_reqid() can + // be used before the full message is decoded. + reqid.inc = inc; + } +private: + ~MOSDOp() final {} + +public: + void set_mtime(utime_t mt) { mtime = mt; } + void set_mtime(ceph::real_time mt) { + mtime = ceph::real_clock::to_timespec(mt); + } + + // ops + void add_simple_op(int o, uint64_t off, uint64_t len) { + OSDOp osd_op; + osd_op.op.op = o; + osd_op.op.extent.offset = off; + osd_op.op.extent.length = len; + ops.push_back(osd_op); + } + void write(uint64_t off, uint64_t len, ceph::buffer::list& bl) { + add_simple_op(CEPH_OSD_OP_WRITE, off, len); + data = std::move(bl); + header.data_off = off; + } + void writefull(ceph::buffer::list& bl) { + add_simple_op(CEPH_OSD_OP_WRITEFULL, 0, bl.length()); + data = std::move(bl); + header.data_off = 0; + } + void zero(uint64_t off, uint64_t len) { + add_simple_op(CEPH_OSD_OP_ZERO, off, len); + } + void truncate(uint64_t off) { + add_simple_op(CEPH_OSD_OP_TRUNCATE, off, 0); + } + void remove() { + add_simple_op(CEPH_OSD_OP_DELETE, 0, 0); + } + + void read(uint64_t off, uint64_t len) { + add_simple_op(CEPH_OSD_OP_READ, off, len); + } + void stat() { + add_simple_op(CEPH_OSD_OP_STAT, 0, 0); + } + + bool has_flag(__u32 flag) const { return flags & flag; }; + + bool is_retry_attempt() const { return flags & CEPH_OSD_FLAG_RETRY; } + void set_retry_attempt(unsigned a) { + if (a) + flags |= CEPH_OSD_FLAG_RETRY; + else + flags &= ~CEPH_OSD_FLAG_RETRY; + retry_attempt = a; + } + + // marshalling + void encode_payload(uint64_t features) override { + using ceph::encode; + if( false == bdata_encode ) { + OSDOp::merge_osd_op_vector_in_data(ops, data); + bdata_encode = true; + } + + if ((features & CEPH_FEATURE_OBJECTLOCATOR) == 0) { + // here is the old structure we are encoding to: // +#if 0 +struct ceph_osd_request_head { + ceph_le32 client_inc; /* client incarnation */ + struct ceph_object_layout layout; /* pgid */ + ceph_le32 osdmap_epoch; /* client's osdmap epoch */ + + ceph_le32 flags; + + struct ceph_timespec mtime; /* for mutations only */ + struct ceph_eversion reassert_version; /* if we are replaying op */ + + ceph_le32 object_len; /* length of object name */ + + ceph_le64 snapid; /* snapid to read */ + ceph_le64 snap_seq; /* writer's snap context */ + ceph_le32 num_snaps; + + ceph_le16 num_ops; + struct ceph_osd_op ops[]; /* followed by ops[], obj, ticket, snaps */ +} __attribute__ ((packed)); +#endif + header.version = 1; + + encode(client_inc, payload); + + __u32 su = 0; + encode(get_raw_pg(), payload); + encode(su, payload); + + encode(osdmap_epoch, payload); + encode(flags, payload); + encode(mtime, payload); + encode(eversion_t(), payload); // reassert_version + + __u32 oid_len = hobj.oid.name.length(); + encode(oid_len, payload); + encode(hobj.snap, payload); + encode(snap_seq, payload); + __u32 num_snaps = snaps.size(); + encode(num_snaps, payload); + + //::encode(ops, payload); + __u16 num_ops = ops.size(); + encode(num_ops, payload); + for (unsigned i = 0; i < ops.size(); i++) + encode(ops[i].op, payload); + + ceph::encode_nohead(hobj.oid.name, payload); + ceph::encode_nohead(snaps, payload); + } else if ((features & CEPH_FEATURE_NEW_OSDOP_ENCODING) == 0) { + header.version = 6; + encode(client_inc, payload); + encode(osdmap_epoch, payload); + encode(flags, payload); + encode(mtime, payload); + encode(eversion_t(), payload); // reassert_version + encode(get_object_locator(), payload); + encode(get_raw_pg(), payload); + + encode(hobj.oid, payload); + + __u16 num_ops = ops.size(); + encode(num_ops, payload); + for (unsigned i = 0; i < ops.size(); i++) + encode(ops[i].op, payload); + + encode(hobj.snap, payload); + encode(snap_seq, payload); + encode(snaps, payload); + + encode(retry_attempt, payload); + encode(features, payload); + if (reqid.name != entity_name_t() || reqid.tid != 0) { + encode(reqid, payload); + } else { + // don't include client_inc in the reqid for the legacy v6 + // encoding or else we'll confuse older peers. + encode(osd_reqid_t(), payload); + } + } else if (!HAVE_FEATURE(features, RESEND_ON_SPLIT)) { + // reordered, v7 message encoding + header.version = 7; + encode(get_raw_pg(), payload); + encode(osdmap_epoch, payload); + encode(flags, payload); + encode(eversion_t(), payload); // reassert_version + encode(reqid, payload); + encode(client_inc, payload); + encode(mtime, payload); + encode(get_object_locator(), payload); + encode(hobj.oid, payload); + + __u16 num_ops = ops.size(); + encode(num_ops, payload); + for (unsigned i = 0; i < ops.size(); i++) + encode(ops[i].op, payload); + + encode(hobj.snap, payload); + encode(snap_seq, payload); + encode(snaps, payload); + + encode(retry_attempt, payload); + encode(features, payload); + } else { + // latest v8 encoding with hobject_t hash separate from pgid, no + // reassert version + header.version = HEAD_VERSION; + + encode(pgid, payload); + encode(hobj.get_hash(), payload); + encode(osdmap_epoch, payload); + encode(flags, payload); + encode(reqid, payload); + encode_trace(payload, features); + + // -- above decoded up front; below decoded post-dispatch thread -- + + encode(client_inc, payload); + encode(mtime, payload); + encode(get_object_locator(), payload); + encode(hobj.oid, payload); + + __u16 num_ops = ops.size(); + encode(num_ops, payload); + for (unsigned i = 0; i < ops.size(); i++) + encode(ops[i].op, payload); + + encode(hobj.snap, payload); + encode(snap_seq, payload); + encode(snaps, payload); + + encode(retry_attempt, payload); + encode(features, payload); + } + } + + void decode_payload() override { + using ceph::decode; + ceph_assert(partial_decode_needed && final_decode_needed); + p = std::cbegin(payload); + + // Always keep here the newest version of decoding order/rule + if (header.version == HEAD_VERSION) { + decode(pgid, p); // actual pgid + uint32_t hash; + decode(hash, p); // raw hash value + hobj.set_hash(hash); + decode(osdmap_epoch, p); + decode(flags, p); + decode(reqid, p); + decode_trace(p); + } else if (header.version == 7) { + decode(pgid.pgid, p); // raw pgid + hobj.set_hash(pgid.pgid.ps()); + decode(osdmap_epoch, p); + decode(flags, p); + eversion_t reassert_version; + decode(reassert_version, p); + decode(reqid, p); + } else if (header.version < 2) { + // old decode + decode(client_inc, p); + + old_pg_t opgid; + ceph::decode_raw(opgid, p); + pgid.pgid = opgid; + + __u32 su; + decode(su, p); + + decode(osdmap_epoch, p); + decode(flags, p); + decode(mtime, p); + eversion_t reassert_version; + decode(reassert_version, p); + + __u32 oid_len; + decode(oid_len, p); + decode(hobj.snap, p); + decode(snap_seq, p); + __u32 num_snaps; + decode(num_snaps, p); + + //::decode(ops, p); + __u16 num_ops; + decode(num_ops, p); + ops.resize(num_ops); + for (unsigned i = 0; i < num_ops; i++) + decode(ops[i].op, p); + + ceph::decode_nohead(oid_len, hobj.oid.name, p); + ceph::decode_nohead(num_snaps, snaps, p); + + // recalculate pgid hash value + pgid.pgid.set_ps(ceph_str_hash(CEPH_STR_HASH_RJENKINS, + hobj.oid.name.c_str(), + hobj.oid.name.length())); + hobj.pool = pgid.pgid.pool(); + hobj.set_hash(pgid.pgid.ps()); + + retry_attempt = -1; + features = 0; + OSDOp::split_osd_op_vector_in_data(ops, data); + + // we did the full decode + final_decode_needed = false; + + // put client_inc in reqid.inc for get_reqid()'s benefit + reqid = osd_reqid_t(); + reqid.inc = client_inc; + } else if (header.version < 7) { + decode(client_inc, p); + decode(osdmap_epoch, p); + decode(flags, p); + decode(mtime, p); + eversion_t reassert_version; + decode(reassert_version, p); + + object_locator_t oloc; + decode(oloc, p); + + if (header.version < 3) { + old_pg_t opgid; + ceph::decode_raw(opgid, p); + pgid.pgid = opgid; + } else { + decode(pgid.pgid, p); + } + + decode(hobj.oid, p); + + //::decode(ops, p); + __u16 num_ops; + decode(num_ops, p); + ops.resize(num_ops); + for (unsigned i = 0; i < num_ops; i++) + decode(ops[i].op, p); + + decode(hobj.snap, p); + decode(snap_seq, p); + decode(snaps, p); + + if (header.version >= 4) + decode(retry_attempt, p); + else + retry_attempt = -1; + + if (header.version >= 5) + decode(features, p); + else + features = 0; + + if (header.version >= 6) + decode(reqid, p); + else + reqid = osd_reqid_t(); + + hobj.pool = pgid.pgid.pool(); + hobj.set_key(oloc.key); + hobj.nspace = oloc.nspace; + hobj.set_hash(pgid.pgid.ps()); + + OSDOp::split_osd_op_vector_in_data(ops, data); + + // we did the full decode + final_decode_needed = false; + + // put client_inc in reqid.inc for get_reqid()'s benefit + if (reqid.name == entity_name_t() && reqid.tid == 0) + reqid.inc = client_inc; + } + + partial_decode_needed = false; + } + + bool finish_decode() { + using ceph::decode; + ceph_assert(!partial_decode_needed); // partial decoding required + if (!final_decode_needed) + return false; // Message is already final decoded + ceph_assert(header.version >= 7); + + decode(client_inc, p); + decode(mtime, p); + object_locator_t oloc; + decode(oloc, p); + decode(hobj.oid, p); + + __u16 num_ops; + decode(num_ops, p); + ops.resize(num_ops); + for (unsigned i = 0; i < num_ops; i++) + decode(ops[i].op, p); + + decode(hobj.snap, p); + decode(snap_seq, p); + decode(snaps, p); + + decode(retry_attempt, p); + + decode(features, p); + + hobj.pool = pgid.pgid.pool(); + hobj.set_key(oloc.key); + hobj.nspace = oloc.nspace; + + OSDOp::split_osd_op_vector_in_data(ops, data); + + final_decode_needed = false; + return true; + } + + void clear_buffers() override { + OSDOp::clear_data(ops); + bdata_encode = false; + } + + std::string_view get_type_name() const override { return "osd_op"; } + void print(std::ostream& out) const override { + out << "osd_op("; + if (!partial_decode_needed) { + out << get_reqid() << ' '; + out << pgid; + if (!final_decode_needed) { + out << ' '; + out << hobj + << " " << ops + << " snapc " << get_snap_seq() << "=" << snaps; + if (is_retry_attempt()) + out << " RETRY=" << get_retry_attempt(); + } else { + out << " " << get_raw_pg() << " (undecoded)"; + } + out << " " << ceph_osd_flag_string(get_flags()); + out << " e" << osdmap_epoch; + } + out << ")"; + } + +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; +} + +using MOSDOp = _mosdop::MOSDOp<std::vector<OSDOp>>; + + +#endif diff --git a/src/messages/MOSDOpReply.h b/src/messages/MOSDOpReply.h new file mode 100644 index 000000000..54c5157c2 --- /dev/null +++ b/src/messages/MOSDOpReply.h @@ -0,0 +1,353 @@ +// -*- 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_MOSDOPREPLY_H +#define CEPH_MOSDOPREPLY_H + +#include "msg/Message.h" + +#include "MOSDOp.h" +#include "common/errno.h" + +/* + * OSD op reply + * + * oid - object id + * op - OSD_OP_DELETE, etc. + * + */ + +class MOSDOpReply final : public Message { +private: + static constexpr int HEAD_VERSION = 8; + static constexpr int COMPAT_VERSION = 2; + + object_t oid; + pg_t pgid; + std::vector<OSDOp> ops; + bool bdata_encode; + int64_t flags = 0; + errorcode32_t result; + eversion_t bad_replay_version; + eversion_t replay_version; + version_t user_version = 0; + epoch_t osdmap_epoch = 0; + int32_t retry_attempt = -1; + bool do_redirect; + request_redirect_t redirect; + +public: + const object_t& get_oid() const { return oid; } + const pg_t& get_pg() const { return pgid; } + int get_flags() const { return flags; } + + bool is_ondisk() const { return get_flags() & CEPH_OSD_FLAG_ONDISK; } + bool is_onnvram() const { return get_flags() & CEPH_OSD_FLAG_ONNVRAM; } + + int get_result() const { return result; } + const eversion_t& get_replay_version() const { return replay_version; } + const version_t& get_user_version() const { return user_version; } + + void set_result(int r) { result = r; } + + void set_reply_versions(eversion_t v, version_t uv) { + replay_version = v; + user_version = uv; + /* We go through some shenanigans here for backwards compatibility + * with old clients, who do not look at our replay_version and + * user_version but instead see what we now call the + * bad_replay_version. On pools without caching + * the user_version infrastructure is a slightly-laggy copy of + * the regular pg version/at_version infrastructure; the difference + * being it is not updated on watch ops like that is -- but on updates + * it is set equal to at_version. This means that for non-watch write ops + * on classic pools, all three of replay_version, user_version, and + * bad_replay_version are identical. But for watch ops the replay_version + * has been updated, while the user_at_version has not, and the semantics + * we promised old clients are that the version they see is not an update. + * So set the bad_replay_version to be the same as the user_at_version. */ + bad_replay_version = v; + if (uv) { + bad_replay_version.version = uv; + } + } + + /* Don't fill in replay_version for non-write ops */ + void set_enoent_reply_versions(const eversion_t& v, const version_t& uv) { + user_version = uv; + bad_replay_version = v; + } + + void set_redirect(const request_redirect_t& redir) { redirect = redir; } + const request_redirect_t& get_redirect() const { return redirect; } + bool is_redirect_reply() const { return do_redirect; } + + void add_flags(int f) { flags |= f; } + + void claim_op_out_data(std::vector<OSDOp>& o) { + ceph_assert(ops.size() == o.size()); + for (unsigned i = 0; i < o.size(); i++) { + ops[i].outdata = std::move(o[i].outdata); + } + } + void claim_ops(std::vector<OSDOp>& o) { + o.swap(ops); + bdata_encode = false; + } + void set_op_returns(const std::vector<pg_log_op_return_item_t>& op_returns) { + if (op_returns.size()) { + ceph_assert(ops.empty() || ops.size() == op_returns.size()); + ops.resize(op_returns.size()); + for (unsigned i = 0; i < op_returns.size(); ++i) { + ops[i].rval = op_returns[i].rval; + ops[i].outdata = op_returns[i].bl; + } + } + } + + /** + * get retry attempt + * + * If we don't know the attempt (because the server is old), return -1. + */ + int get_retry_attempt() const { + return retry_attempt; + } + + // osdmap + epoch_t get_map_epoch() const { return osdmap_epoch; } + + /*osd_reqid_t get_reqid() { return osd_reqid_t(get_dest(), + head.client_inc, + head.tid); } + */ + +public: + MOSDOpReply() + : Message{CEPH_MSG_OSD_OPREPLY, HEAD_VERSION, COMPAT_VERSION}, + bdata_encode(false) { + do_redirect = false; + } + MOSDOpReply(const MOSDOp *req, int r, epoch_t e, int acktype, + bool ignore_out_data) + : Message{CEPH_MSG_OSD_OPREPLY, HEAD_VERSION, COMPAT_VERSION}, + oid(req->hobj.oid), pgid(req->pgid.pgid), ops(req->ops), + bdata_encode(false) { + + set_tid(req->get_tid()); + result = r; + flags = + (req->flags & ~(CEPH_OSD_FLAG_ONDISK|CEPH_OSD_FLAG_ONNVRAM|CEPH_OSD_FLAG_ACK)) | acktype; + osdmap_epoch = e; + user_version = 0; + retry_attempt = req->get_retry_attempt(); + do_redirect = false; + + for (unsigned i = 0; i < ops.size(); i++) { + // zero out input data + ops[i].indata.clear(); + if (ignore_out_data) { + // original request didn't set the RETURNVEC flag + ops[i].outdata.clear(); + } + } + } +private: + ~MOSDOpReply() final {} + +public: + void encode_payload(uint64_t features) override { + using ceph::encode; + if(false == bdata_encode) { + OSDOp::merge_osd_op_vector_out_data(ops, data); + bdata_encode = true; + } + + if ((features & CEPH_FEATURE_PGID64) == 0) { + header.version = 1; + ceph_osd_reply_head head; + memset(&head, 0, sizeof(head)); + head.layout.ol_pgid = pgid.get_old_pg().v; + head.flags = flags; + head.osdmap_epoch = osdmap_epoch; + head.reassert_version = bad_replay_version; + head.result = result; + head.num_ops = ops.size(); + head.object_len = oid.name.length(); + encode(head, payload); + for (unsigned i = 0; i < head.num_ops; i++) { + encode(ops[i].op, payload); + } + ceph::encode_nohead(oid.name, payload); + } else { + header.version = HEAD_VERSION; + encode(oid, payload); + encode(pgid, payload); + encode(flags, payload); + encode(result, payload); + encode(bad_replay_version, payload); + encode(osdmap_epoch, payload); + + __u32 num_ops = ops.size(); + encode(num_ops, payload); + for (unsigned i = 0; i < num_ops; i++) + encode(ops[i].op, payload); + + encode(retry_attempt, payload); + + for (unsigned i = 0; i < num_ops; i++) + encode(ops[i].rval, payload); + + encode(replay_version, payload); + encode(user_version, payload); + if ((features & CEPH_FEATURE_NEW_OSDOPREPLY_ENCODING) == 0) { + header.version = 6; + encode(redirect, payload); + } else { + do_redirect = !redirect.empty(); + encode(do_redirect, payload); + if (do_redirect) { + encode(redirect, payload); + } + } + encode_trace(payload, features); + } + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + + // Always keep here the newest version of decoding order/rule + if (header.version == HEAD_VERSION) { + decode(oid, p); + decode(pgid, p); + decode(flags, p); + decode(result, p); + decode(bad_replay_version, p); + decode(osdmap_epoch, p); + + __u32 num_ops = ops.size(); + decode(num_ops, p); + ops.resize(num_ops); + for (unsigned i = 0; i < num_ops; i++) + decode(ops[i].op, p); + decode(retry_attempt, p); + + for (unsigned i = 0; i < num_ops; ++i) + decode(ops[i].rval, p); + + OSDOp::split_osd_op_vector_out_data(ops, data); + + decode(replay_version, p); + decode(user_version, p); + decode(do_redirect, p); + if (do_redirect) + decode(redirect, p); + decode_trace(p); + } else if (header.version < 2) { + ceph_osd_reply_head head; + decode(head, p); + ops.resize(head.num_ops); + for (unsigned i = 0; i < head.num_ops; i++) { + decode(ops[i].op, p); + } + ceph::decode_nohead(head.object_len, oid.name, p); + pgid = pg_t(head.layout.ol_pgid); + result = (int32_t)head.result; + flags = head.flags; + replay_version = head.reassert_version; + user_version = replay_version.version; + osdmap_epoch = head.osdmap_epoch; + retry_attempt = -1; + } else { + decode(oid, p); + decode(pgid, p); + decode(flags, p); + decode(result, p); + decode(bad_replay_version, p); + decode(osdmap_epoch, p); + + __u32 num_ops = ops.size(); + decode(num_ops, p); + ops.resize(num_ops); + for (unsigned i = 0; i < num_ops; i++) + decode(ops[i].op, p); + + if (header.version >= 3) + decode(retry_attempt, p); + else + retry_attempt = -1; + + if (header.version >= 4) { + for (unsigned i = 0; i < num_ops; ++i) + decode(ops[i].rval, p); + + OSDOp::split_osd_op_vector_out_data(ops, data); + } + + if (header.version >= 5) { + decode(replay_version, p); + decode(user_version, p); + } else { + replay_version = bad_replay_version; + user_version = replay_version.version; + } + + if (header.version == 6) { + decode(redirect, p); + do_redirect = !redirect.empty(); + } + if (header.version >= 7) { + decode(do_redirect, p); + if (do_redirect) { + decode(redirect, p); + } + } + if (header.version >= 8) { + decode_trace(p); + } + } + } + + std::string_view get_type_name() const override { return "osd_op_reply"; } + + void print(std::ostream& out) const override { + out << "osd_op_reply(" << get_tid() + << " " << oid << " " << ops + << " v" << get_replay_version() + << " uv" << get_user_version(); + if (is_ondisk()) + out << " ondisk"; + else if (is_onnvram()) + out << " onnvram"; + else + out << " ack"; + out << " = " << get_result(); + if (get_result() < 0) { + out << " (" << cpp_strerror(get_result()) << ")"; + } + if (is_redirect_reply()) { + out << " redirect: { " << redirect << " }"; + } + out << ")"; + } + +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + + +#endif diff --git a/src/messages/MOSDPGBackfill.h b/src/messages/MOSDPGBackfill.h new file mode 100644 index 000000000..eccb4e696 --- /dev/null +++ b/src/messages/MOSDPGBackfill.h @@ -0,0 +1,117 @@ +// -*- 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_MOSDPGBACKFILL_H +#define CEPH_MOSDPGBACKFILL_H + +#include "MOSDFastDispatchOp.h" + +class MOSDPGBackfill final : public MOSDFastDispatchOp { +private: + static constexpr int HEAD_VERSION = 3; + static constexpr int COMPAT_VERSION = 3; +public: + enum { + OP_BACKFILL_PROGRESS = 2, + OP_BACKFILL_FINISH = 3, + OP_BACKFILL_FINISH_ACK = 4, + }; + const char *get_op_name(int o) const { + switch (o) { + case OP_BACKFILL_PROGRESS: return "progress"; + case OP_BACKFILL_FINISH: return "finish"; + case OP_BACKFILL_FINISH_ACK: return "finish_ack"; + default: return "???"; + } + } + + __u32 op = 0; + epoch_t map_epoch = 0, query_epoch = 0; + spg_t pgid; + hobject_t last_backfill; + pg_stat_t stats; + + epoch_t get_map_epoch() const override { + return map_epoch; + } + epoch_t get_min_epoch() const override { + return query_epoch; + } + spg_t get_spg() const override { + return pgid; + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(op, p); + decode(map_epoch, p); + decode(query_epoch, p); + decode(pgid.pgid, p); + decode(last_backfill, p); + + // For compatibility with version 1 + decode(stats.stats, p); + + decode(stats, p); + + // Handle hobject_t format change + if (!last_backfill.is_max() && + last_backfill.pool == -1) + last_backfill.pool = pgid.pool(); + decode(pgid.shard, p); + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(op, payload); + encode(map_epoch, payload); + encode(query_epoch, payload); + encode(pgid.pgid, payload); + encode(last_backfill, payload); + + // For compatibility with version 1 + encode(stats.stats, payload); + + encode(stats, payload); + + encode(pgid.shard, payload); + } + + MOSDPGBackfill() + : MOSDFastDispatchOp{MSG_OSD_PG_BACKFILL, HEAD_VERSION, COMPAT_VERSION} {} + MOSDPGBackfill(__u32 o, epoch_t e, epoch_t qe, spg_t p) + : MOSDFastDispatchOp{MSG_OSD_PG_BACKFILL, HEAD_VERSION, COMPAT_VERSION}, + op(o), + map_epoch(e), query_epoch(e), + pgid(p) {} +private: + ~MOSDPGBackfill() final {} + +public: + std::string_view get_type_name() const override { return "pg_backfill"; } + void print(std::ostream& out) const override { + out << "pg_backfill(" << get_op_name(op) + << " " << pgid + << " e " << map_epoch << "/" << query_epoch + << " lb " << last_backfill + << ")"; + } + +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MOSDPGBackfillRemove.h b/src/messages/MOSDPGBackfillRemove.h new file mode 100644 index 000000000..6029024ee --- /dev/null +++ b/src/messages/MOSDPGBackfillRemove.h @@ -0,0 +1,80 @@ +// -*- 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) 2017 Sage Weil <sage@redhat.com> + * + * 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_MOSDPGBACKFILLREMOVE_H +#define CEPH_MOSDPGBACKFILLREMOVE_H + +#include "MOSDFastDispatchOp.h" + +/* + * instruct non-primary to remove some objects during backfill + */ + +class MOSDPGBackfillRemove final : public MOSDFastDispatchOp { +public: + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; + + spg_t pgid; ///< target spg_t + epoch_t map_epoch = 0; + std::list<std::pair<hobject_t,eversion_t>> ls; ///< objects to remove + + epoch_t get_map_epoch() const override { + return map_epoch; + } + spg_t get_spg() const override { + return pgid; + } + + MOSDPGBackfillRemove() + : MOSDFastDispatchOp{MSG_OSD_PG_BACKFILL_REMOVE, HEAD_VERSION, + COMPAT_VERSION} + {} + + MOSDPGBackfillRemove(spg_t pgid, epoch_t map_epoch) + : MOSDFastDispatchOp{MSG_OSD_PG_BACKFILL_REMOVE, HEAD_VERSION, + COMPAT_VERSION}, + pgid(pgid), + map_epoch(map_epoch) {} + +private: + ~MOSDPGBackfillRemove() final {} + +public: + std::string_view get_type_name() const override { return "backfill_remove"; } + void print(std::ostream& out) const override { + out << "backfill_remove(" << pgid << " e" << map_epoch + << " " << ls << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(pgid, payload); + encode(map_epoch, payload); + encode(ls, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(pgid, p); + decode(map_epoch, p); + decode(ls, p); + } + +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MOSDPGCreate.h b/src/messages/MOSDPGCreate.h new file mode 100644 index 000000000..405135ed8 --- /dev/null +++ b/src/messages/MOSDPGCreate.h @@ -0,0 +1,73 @@ +// -*- 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_MOSDPGCREATE_H +#define CEPH_MOSDPGCREATE_H + +#include "msg/Message.h" +#include "osd/osd_types.h" + +/* + * PGCreate - instruct an OSD to create a pg, if it doesn't already exist + */ + +class MOSDPGCreate final : public Message { +public: + static constexpr int HEAD_VERSION = 3; + static constexpr int COMPAT_VERSION = 3; + + version_t epoch = 0; + std::map<pg_t,pg_create_t> mkpg; + std::map<pg_t,utime_t> ctimes; + + MOSDPGCreate() + : MOSDPGCreate{0} + {} + MOSDPGCreate(epoch_t e) + : Message{MSG_OSD_PG_CREATE, HEAD_VERSION, COMPAT_VERSION}, + epoch(e) + {} +private: + ~MOSDPGCreate() final {} + +public: + std::string_view get_type_name() const override { return "pg_create"; } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(epoch, payload); + encode(mkpg, payload); + encode(ctimes, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(epoch, p); + decode(mkpg, p); + decode(ctimes, p); + } + void print(std::ostream& out) const override { + out << "osd_pg_create(e" << epoch; + for (auto i = mkpg.begin(); i != mkpg.end(); ++i) { + out << " " << i->first << ":" << i->second.created; + } + out << ")"; + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MOSDPGCreate2.h b/src/messages/MOSDPGCreate2.h new file mode 100644 index 000000000..d05387c7b --- /dev/null +++ b/src/messages/MOSDPGCreate2.h @@ -0,0 +1,56 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#pragma once + +#include "msg/Message.h" +#include "osd/osd_types.h" + +/* + * PGCreate2 - instruct an OSD to create some pgs + */ + +class MOSDPGCreate2 final : public Message { +public: + static constexpr int HEAD_VERSION = 2; + static constexpr int COMPAT_VERSION = 1; + + epoch_t epoch = 0; + std::map<spg_t,std::pair<epoch_t,utime_t>> pgs; + std::map<spg_t,std::pair<pg_history_t,PastIntervals>> pg_extra; + + MOSDPGCreate2() + : Message{MSG_OSD_PG_CREATE2, HEAD_VERSION, COMPAT_VERSION} {} + MOSDPGCreate2(epoch_t e) + : Message{MSG_OSD_PG_CREATE2, HEAD_VERSION, COMPAT_VERSION}, + epoch(e) { } +private: + ~MOSDPGCreate2() final {} + +public: + std::string_view get_type_name() const override { + return "pg_create2"; + } + void print(std::ostream& out) const override { + out << "pg_create2(e" << epoch << " " << pgs << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(epoch, payload); + encode(pgs, payload); + encode(pg_extra, payload); + } + void decode_payload() override { + auto p = payload.cbegin(); + using ceph::decode; + decode(epoch, p); + decode(pgs, p); + if (header.version >= 2) { + decode(pg_extra, p); + } + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; diff --git a/src/messages/MOSDPGCreated.h b/src/messages/MOSDPGCreated.h new file mode 100644 index 000000000..9be8e2ddc --- /dev/null +++ b/src/messages/MOSDPGCreated.h @@ -0,0 +1,37 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#pragma once + +#include "osd/osd_types.h" +#include "messages/PaxosServiceMessage.h" + +class MOSDPGCreated : public PaxosServiceMessage { +public: + pg_t pgid; + MOSDPGCreated() + : PaxosServiceMessage{MSG_OSD_PG_CREATED, 0} + {} + MOSDPGCreated(pg_t pgid) + : PaxosServiceMessage{MSG_OSD_PG_CREATED, 0}, + pgid(pgid) + {} + std::string_view get_type_name() const override { return "pg_created"; } + void print(std::ostream& out) const override { + out << "osd_pg_created(" << pgid << ")"; + } + void encode_payload(uint64_t features) override { + using ceph::encode; + paxos_encode(); + encode(pgid, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + paxos_decode(p); + decode(pgid, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; diff --git a/src/messages/MOSDPGInfo.h b/src/messages/MOSDPGInfo.h new file mode 100644 index 000000000..b742cd014 --- /dev/null +++ b/src/messages/MOSDPGInfo.h @@ -0,0 +1,104 @@ +// -*- 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_MOSDPGINFO_H +#define CEPH_MOSDPGINFO_H + +#include "msg/Message.h" +#include "osd/osd_types.h" + +class MOSDPGInfo final : public Message { +private: + static constexpr int HEAD_VERSION = 6; + static constexpr int COMPAT_VERSION = 5; + + epoch_t epoch = 0; + +public: + using pg_list_t = std::vector<pg_notify_t>; + pg_list_t pg_list; + + epoch_t get_epoch() const { return epoch; } + + MOSDPGInfo() + : MOSDPGInfo{0, {}} + {} + MOSDPGInfo(epoch_t mv) + : MOSDPGInfo(mv, {}) + {} + MOSDPGInfo(epoch_t mv, pg_list_t&& l) + : Message{MSG_OSD_PG_INFO, HEAD_VERSION, COMPAT_VERSION}, + epoch{mv}, + pg_list{std::move(l)} + { + set_priority(CEPH_MSG_PRIO_HIGH); + } +private: + ~MOSDPGInfo() final {} + +public: + std::string_view get_type_name() const override { return "pg_info"; } + void print(std::ostream& out) const override { + out << "pg_info("; + for (auto i = pg_list.begin(); + i != pg_list.end(); + ++i) { + if (i != pg_list.begin()) + out << " "; + out << *i; + } + out << " epoch " << epoch + << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + header.version = HEAD_VERSION; + encode(epoch, payload); + if (!HAVE_FEATURE(features, SERVER_OCTOPUS)) { + // pretend to be vector<pair<pg_notify_t,PastIntervals>> + header.version = 5; + encode((uint32_t)pg_list.size(), payload); + for (auto& i : pg_list) { + encode(i, payload); // this embeds a dup (ignored) PastIntervals + encode(i.past_intervals, payload); + } + return; + } + encode(pg_list, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(epoch, p); + if (header.version == 5) { + // decode legacy vector<pair<pg_notify_t,PastIntervals>> + uint32_t num; + decode(num, p); + pg_list.resize(num); + for (unsigned i = 0; i < num; ++i) { + decode(pg_list[i], p); + decode(pg_list[i].past_intervals, p); + } + return; + } + decode(pg_list, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MOSDPGInfo2.h b/src/messages/MOSDPGInfo2.h new file mode 100644 index 000000000..8e7f4bc58 --- /dev/null +++ b/src/messages/MOSDPGInfo2.h @@ -0,0 +1,98 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#pragma once + +#include "messages/MOSDPeeringOp.h" +#include "osd/PGPeeringEvent.h" + +class MOSDPGInfo2 final : public MOSDPeeringOp { +private: + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; + +public: + spg_t spgid; + epoch_t epoch_sent; + epoch_t min_epoch; + pg_info_t info; + std::optional<pg_lease_t> lease; + std::optional<pg_lease_ack_t> lease_ack; + + spg_t get_spg() const override { + return spgid; + } + epoch_t get_map_epoch() const override { + return epoch_sent; + } + epoch_t get_min_epoch() const override { + return min_epoch; + } + + PGPeeringEvent *get_event() override { + return new PGPeeringEvent( + epoch_sent, + min_epoch, + MInfoRec( + pg_shard_t(get_source().num(), info.pgid.shard), + info, + epoch_sent, + lease, + lease_ack)); + } + + MOSDPGInfo2() : MOSDPeeringOp{MSG_OSD_PG_INFO2, + HEAD_VERSION, COMPAT_VERSION} { + set_priority(CEPH_MSG_PRIO_HIGH); + } + MOSDPGInfo2( + spg_t s, + pg_info_t q, + epoch_t sent, + epoch_t min, + std::optional<pg_lease_t> l, + std::optional<pg_lease_ack_t> la) + : MOSDPeeringOp{MSG_OSD_PG_INFO2, HEAD_VERSION, COMPAT_VERSION}, + spgid(s), + epoch_sent(sent), + min_epoch(min), + info(q), + lease(l), + lease_ack(la) { + set_priority(CEPH_MSG_PRIO_HIGH); + } + +private: + ~MOSDPGInfo2() final {} + +public: + std::string_view get_type_name() const override { + return "pg_info2"; + } + void inner_print(std::ostream& out) const override { + out << spgid << " " << info; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(spgid, payload); + encode(epoch_sent, payload); + encode(min_epoch, payload); + encode(info, payload); + encode(lease, payload); + encode(lease_ack, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(spgid, p); + decode(epoch_sent, p); + decode(min_epoch, p); + decode(info, p); + decode(lease, p); + decode(lease_ack, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; diff --git a/src/messages/MOSDPGLease.h b/src/messages/MOSDPGLease.h new file mode 100644 index 000000000..20b197e1d --- /dev/null +++ b/src/messages/MOSDPGLease.h @@ -0,0 +1,68 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#pragma once + +#include "msg/Message.h" +#include "osd/osd_types.h" + +class MOSDPGLease final : public MOSDPeeringOp { +private: + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; + + epoch_t epoch = 0; + spg_t spgid; + pg_lease_t lease; + +public: + spg_t get_spg() const { + return spgid; + } + epoch_t get_map_epoch() const { + return epoch; + } + epoch_t get_min_epoch() const { + return epoch; + } + PGPeeringEvent *get_event() override { + return new PGPeeringEvent( + epoch, + epoch, + MLease(epoch, get_source().num(), lease)); + } + + MOSDPGLease() : MOSDPeeringOp{MSG_OSD_PG_LEASE, + HEAD_VERSION, COMPAT_VERSION} {} + MOSDPGLease(version_t mv, spg_t p, pg_lease_t lease) : + MOSDPeeringOp{MSG_OSD_PG_LEASE, + HEAD_VERSION, COMPAT_VERSION}, + epoch(mv), + spgid(p), + lease(lease) { } +private: + ~MOSDPGLease() final {} + +public: + std::string_view get_type_name() const override { return "pg_lease"; } + void inner_print(std::ostream& out) const override { + out << lease; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(epoch, payload); + encode(spgid, payload); + encode(lease, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(epoch, p); + decode(spgid, p); + decode(lease, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; diff --git a/src/messages/MOSDPGLeaseAck.h b/src/messages/MOSDPGLeaseAck.h new file mode 100644 index 000000000..5c6c1188a --- /dev/null +++ b/src/messages/MOSDPGLeaseAck.h @@ -0,0 +1,68 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#pragma once + +#include "msg/Message.h" +#include "osd/osd_types.h" + +class MOSDPGLeaseAck final : public MOSDPeeringOp { +private: + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; + + epoch_t epoch = 0; + spg_t spgid; + pg_lease_ack_t lease_ack; + +public: + spg_t get_spg() const { + return spgid; + } + epoch_t get_map_epoch() const { + return epoch; + } + epoch_t get_min_epoch() const { + return epoch; + } + PGPeeringEvent *get_event() override { + return new PGPeeringEvent( + epoch, + epoch, + MLeaseAck(epoch, get_source().num(), lease_ack)); + } + + MOSDPGLeaseAck() : MOSDPeeringOp{MSG_OSD_PG_LEASE_ACK, + HEAD_VERSION, COMPAT_VERSION} {} + MOSDPGLeaseAck(version_t mv, spg_t p, pg_lease_ack_t lease_ack) : + MOSDPeeringOp{MSG_OSD_PG_LEASE_ACK, + HEAD_VERSION, COMPAT_VERSION}, + epoch(mv), + spgid(p), + lease_ack(lease_ack) { } +private: + ~MOSDPGLeaseAck() final {} + +public: + std::string_view get_type_name() const override { return "pg_lease_ack"; } + void inner_print(std::ostream& out) const override { + out << lease_ack; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(epoch, payload); + encode(spgid, payload); + encode(lease_ack, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(epoch, p); + decode(spgid, p); + decode(lease_ack, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; diff --git a/src/messages/MOSDPGLog.h b/src/messages/MOSDPGLog.h new file mode 100644 index 000000000..fc3b9174d --- /dev/null +++ b/src/messages/MOSDPGLog.h @@ -0,0 +1,135 @@ +// -*- 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_MOSDPGLOG_H +#define CEPH_MOSDPGLOG_H + +#include "messages/MOSDPeeringOp.h" +#include "osd/PGPeeringEvent.h" + +class MOSDPGLog final : public MOSDPeeringOp { +private: + static constexpr int HEAD_VERSION = 6; + static constexpr int COMPAT_VERSION = 5; + + epoch_t epoch = 0; + /// query_epoch is the epoch of the query being responded to, or + /// the current epoch if this is not being sent in response to a + /// query. This allows the recipient to disregard responses to old + /// queries. + epoch_t query_epoch = 0; + +public: + shard_id_t to; + shard_id_t from; + pg_info_t info; + pg_log_t log; + pg_missing_t missing; + PastIntervals past_intervals; + std::optional<pg_lease_t> lease; + + epoch_t get_epoch() const { return epoch; } + spg_t get_pgid() const { return spg_t(info.pgid.pgid, to); } + epoch_t get_query_epoch() const { return query_epoch; } + + spg_t get_spg() const override { + return spg_t(info.pgid.pgid, to); + } + epoch_t get_map_epoch() const override { + return epoch; + } + epoch_t get_min_epoch() const override { + return query_epoch; + } + + PGPeeringEvent *get_event() override { + return new PGPeeringEvent( + epoch, query_epoch, + MLogRec(pg_shard_t(get_source().num(), from), + this), + true, + new PGCreateInfo( + get_spg(), + query_epoch, + info.history, + past_intervals, + false)); + } + + MOSDPGLog() : MOSDPeeringOp{MSG_OSD_PG_LOG, HEAD_VERSION, COMPAT_VERSION} { + set_priority(CEPH_MSG_PRIO_HIGH); + } + MOSDPGLog(shard_id_t to, shard_id_t from, + version_t mv, const pg_info_t& i, epoch_t query_epoch) + : MOSDPeeringOp{MSG_OSD_PG_LOG, HEAD_VERSION, COMPAT_VERSION}, + epoch(mv), query_epoch(query_epoch), + to(to), from(from), + info(i) { + set_priority(CEPH_MSG_PRIO_HIGH); + } + +private: + ~MOSDPGLog() final {} + +public: + std::string_view get_type_name() const override { return "PGlog"; } + void inner_print(std::ostream& out) const override { + // NOTE: log is not const, but operator<< doesn't touch fields + // swapped out by OSD code. + out << "log " << log + << " pi " << past_intervals; + if (lease) { + out << " " << *lease; + } + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(epoch, payload); + encode(info, payload); + encode(log, payload); + encode(missing, payload, features); + if (!HAVE_FEATURE(features, SERVER_NAUTILUS)) { + // pre-nautilus OSDs do not set last_peering_reset properly + encode(epoch, payload); + } else { + encode(query_epoch, payload); + } + encode(past_intervals, payload); + encode(to, payload); + encode(from, payload); + encode(lease, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(epoch, p); + decode(info, p); + log.decode(p, info.pgid.pool()); + missing.decode(p, info.pgid.pool()); + decode(query_epoch, p); + decode(past_intervals, p); + decode(to, p); + decode(from, p); + if (header.version >= 6) { + decode(lease, p); + } + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MOSDPGNotify.h b/src/messages/MOSDPGNotify.h new file mode 100644 index 000000000..a3b237c1a --- /dev/null +++ b/src/messages/MOSDPGNotify.h @@ -0,0 +1,111 @@ +// -*- 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_MOSDPGPEERNOTIFY_H +#define CEPH_MOSDPGPEERNOTIFY_H + +#include "msg/Message.h" + +#include "osd/osd_types.h" + +/* + * PGNotify - notify primary of my PGs and versions. + */ + +class MOSDPGNotify final : public Message { +private: + static constexpr int HEAD_VERSION = 7; + static constexpr int COMPAT_VERSION = 6; + + epoch_t epoch = 0; + /// query_epoch is the epoch of the query being responded to, or + /// the current epoch if this is not being sent in response to a + /// query. This allows the recipient to disregard responses to old + /// queries. + using pg_list_t = std::vector<pg_notify_t>; + pg_list_t pg_list; + + public: + version_t get_epoch() const { return epoch; } + const pg_list_t& get_pg_list() const { + return pg_list; + } + + MOSDPGNotify() + : MOSDPGNotify(0, {}) + {} + MOSDPGNotify(epoch_t e, pg_list_t&& l) + : Message{MSG_OSD_PG_NOTIFY, HEAD_VERSION, COMPAT_VERSION}, + epoch(e), + pg_list(std::move(l)) { + set_priority(CEPH_MSG_PRIO_HIGH); + } +private: + ~MOSDPGNotify() final {} + +public: + std::string_view get_type_name() const override { return "PGnot"; } + + void encode_payload(uint64_t features) override { + using ceph::encode; + header.version = HEAD_VERSION; + encode(epoch, payload); + if (!HAVE_FEATURE(features, SERVER_OCTOPUS)) { + // pretend to be vector<pair<pg_notify_t,PastIntervals>> + header.version = 6; + encode((uint32_t)pg_list.size(), payload); + for (auto& i : pg_list) { + encode(i, payload); // this embeds a dup (ignored) PastIntervals + encode(i.past_intervals, payload); + } + return; + } + encode(pg_list, payload); + } + + void decode_payload() override { + auto p = payload.cbegin(); + using ceph::decode; + decode(epoch, p); + if (header.version == 6) { + // decode legacy vector<pair<pg_notify_t,PastIntervals>> + uint32_t num; + decode(num, p); + pg_list.resize(num); + for (unsigned i = 0; i < num; ++i) { + decode(pg_list[i], p); + decode(pg_list[i].past_intervals, p); + } + return; + } + decode(pg_list, p); + } + void print(std::ostream& out) const override { + out << "pg_notify("; + for (auto i = pg_list.begin(); + i != pg_list.end(); + ++i) { + if (i != pg_list.begin()) + out << " "; + out << *i; + } + out << " epoch " << epoch + << ")"; + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MOSDPGNotify2.h b/src/messages/MOSDPGNotify2.h new file mode 100644 index 000000000..127037398 --- /dev/null +++ b/src/messages/MOSDPGNotify2.h @@ -0,0 +1,84 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#pragma once + +#include "messages/MOSDPeeringOp.h" +#include "osd/PGPeeringEvent.h" + +class MOSDPGNotify2 final : public MOSDPeeringOp { +private: + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; + +public: + spg_t spgid; + pg_notify_t notify; + + spg_t get_spg() const override { + return spgid; + } + epoch_t get_map_epoch() const override { + return notify.epoch_sent; + } + epoch_t get_min_epoch() const override { + return notify.query_epoch; + } + + PGPeeringEvent *get_event() override { + return new PGPeeringEvent( + notify.epoch_sent, + notify.query_epoch, + MNotifyRec( + spgid, + pg_shard_t(get_source().num(), notify.from), + notify, + get_connection()->get_features()), + true, + new PGCreateInfo( + spgid, + notify.epoch_sent, + notify.info.history, + notify.past_intervals, + false)); + } + + MOSDPGNotify2() : MOSDPeeringOp{MSG_OSD_PG_NOTIFY2, + HEAD_VERSION, COMPAT_VERSION} { + set_priority(CEPH_MSG_PRIO_HIGH); + } + MOSDPGNotify2( + spg_t s, + pg_notify_t n) + : MOSDPeeringOp{MSG_OSD_PG_NOTIFY2, HEAD_VERSION, COMPAT_VERSION}, + spgid(s), + notify(n) { + set_priority(CEPH_MSG_PRIO_HIGH); + } + +private: + ~MOSDPGNotify2() final {} + +public: + std::string_view get_type_name() const override { + return "pg_notify2"; + } + void inner_print(std::ostream& out) const override { + out << spgid << " " << notify; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(spgid, payload); + encode(notify, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(spgid, p); + decode(notify, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; diff --git a/src/messages/MOSDPGPull.h b/src/messages/MOSDPGPull.h new file mode 100644 index 000000000..eb5c94516 --- /dev/null +++ b/src/messages/MOSDPGPull.h @@ -0,0 +1,106 @@ +// -*- 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) 2013 Inktank Storage, Inc. + * + * 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 MOSDPGPULL_H +#define MOSDPGPULL_H + +#include "MOSDFastDispatchOp.h" + +class MOSDPGPull : public MOSDFastDispatchOp { +private: + static constexpr int HEAD_VERSION = 3; + static constexpr int COMPAT_VERSION = 2; + + std::vector<PullOp> pulls; + +public: + pg_shard_t from; + spg_t pgid; + epoch_t map_epoch = 0, min_epoch = 0; + uint64_t cost = 0; + + epoch_t get_map_epoch() const override { + return map_epoch; + } + epoch_t get_min_epoch() const override { + return min_epoch; + } + spg_t get_spg() const override { + return pgid; + } + + std::vector<PullOp> take_pulls() { + return std::move(pulls); + } + void set_pulls(std::vector<PullOp>&& pull_ops) { + pulls = std::move(pull_ops); + } + + MOSDPGPull() + : MOSDFastDispatchOp{MSG_OSD_PG_PULL, HEAD_VERSION, COMPAT_VERSION} + {} + + void compute_cost(CephContext *cct) { + cost = 0; + for (auto i = pulls.begin(); i != pulls.end(); ++i) { + cost += i->cost(cct); + } + } + + int get_cost() const override { + return cost; + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(pgid.pgid, p); + decode(map_epoch, p); + decode(pulls, p); + decode(cost, p); + decode(pgid.shard, p); + decode(from, p); + if (header.version >= 3) { + decode(min_epoch, p); + } else { + min_epoch = map_epoch; + } + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(pgid.pgid, payload); + encode(map_epoch, payload); + encode(pulls, payload, features); + encode(cost, payload); + encode(pgid.shard, payload); + encode(from, payload); + encode(min_epoch, payload); + } + + std::string_view get_type_name() const override { return "MOSDPGPull"; } + + void print(std::ostream& out) const override { + out << "MOSDPGPull(" << pgid + << " e" << map_epoch << "/" << min_epoch + << " cost " << cost + << ")"; + } + +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MOSDPGPush.h b/src/messages/MOSDPGPush.h new file mode 100644 index 000000000..df9dbae5b --- /dev/null +++ b/src/messages/MOSDPGPush.h @@ -0,0 +1,112 @@ +// -*- 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) 2013 Inktank Storage, Inc. + * + * 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 MOSDPGPUSH_H +#define MOSDPGPUSH_H + +#include "MOSDFastDispatchOp.h" + +class MOSDPGPush : public MOSDFastDispatchOp { +private: + static constexpr int HEAD_VERSION = 4; + static constexpr int COMPAT_VERSION = 2; + +public: + pg_shard_t from; + spg_t pgid; + epoch_t map_epoch = 0, min_epoch = 0; + std::vector<PushOp> pushes; + bool is_repair = false; + +private: + uint64_t cost = 0; + +public: + void compute_cost(CephContext *cct) { + cost = 0; + for (auto i = pushes.begin(); i != pushes.end(); ++i) { + cost += i->cost(cct); + } + } + + int get_cost() const override { + return cost; + } + + epoch_t get_map_epoch() const override { + return map_epoch; + } + epoch_t get_min_epoch() const override { + return min_epoch; + } + spg_t get_spg() const override { + return pgid; + } + + void set_cost(uint64_t c) { + cost = c; + } + + MOSDPGPush() + : MOSDFastDispatchOp{MSG_OSD_PG_PUSH, HEAD_VERSION, COMPAT_VERSION} + {} + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(pgid.pgid, p); + decode(map_epoch, p); + decode(pushes, p); + decode(cost, p); + decode(pgid.shard, p); + decode(from, p); + if (header.version >= 3) { + decode(min_epoch, p); + } else { + min_epoch = map_epoch; + } + if (header.version >= 4) { + decode(is_repair, p); + } else { + is_repair = false; + } + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(pgid.pgid, payload); + encode(map_epoch, payload); + encode(pushes, payload, features); + encode(cost, payload); + encode(pgid.shard, payload); + encode(from, payload); + encode(min_epoch, payload); + encode(is_repair, payload); + } + + std::string_view get_type_name() const override { return "MOSDPGPush"; } + + void print(std::ostream& out) const override { + out << "MOSDPGPush(" << pgid + << " " << map_epoch << "/" << min_epoch + << " " << pushes; + out << ")"; + } + +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MOSDPGPushReply.h b/src/messages/MOSDPGPushReply.h new file mode 100644 index 000000000..1fdfd9b69 --- /dev/null +++ b/src/messages/MOSDPGPushReply.h @@ -0,0 +1,94 @@ +// -*- 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) 2013 Inktank Storage, Inc. + * + * 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 MOSDPGPUSHREPLY_H +#define MOSDPGPUSHREPLY_H + +#include "MOSDFastDispatchOp.h" + +class MOSDPGPushReply : public MOSDFastDispatchOp { +private: + static constexpr int HEAD_VERSION = 3; + static constexpr int COMPAT_VERSION = 2; + +public: + pg_shard_t from; + spg_t pgid; + epoch_t map_epoch = 0, min_epoch = 0; + std::vector<PushReplyOp> replies; + uint64_t cost = 0; + + epoch_t get_map_epoch() const override { + return map_epoch; + } + epoch_t get_min_epoch() const override { + return min_epoch; + } + spg_t get_spg() const override { + return pgid; + } + + MOSDPGPushReply() + : MOSDFastDispatchOp{MSG_OSD_PG_PUSH_REPLY, HEAD_VERSION, COMPAT_VERSION} + {} + + void compute_cost(CephContext *cct) { + cost = 0; + for (auto i = replies.begin(); i != replies.end(); ++i) { + cost += i->cost(cct); + } + } + + int get_cost() const override { + return cost; + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(pgid.pgid, p); + decode(map_epoch, p); + decode(replies, p); + decode(cost, p); + decode(pgid.shard, p); + decode(from, p); + if (header.version >= 3) { + decode(min_epoch, p); + } else { + min_epoch = map_epoch; + } + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(pgid.pgid, payload); + encode(map_epoch, payload); + encode(replies, payload); + encode(cost, payload); + encode(pgid.shard, payload); + encode(from, payload); + encode(min_epoch, payload); + } + + void print(std::ostream& out) const override { + out << "MOSDPGPushReply(" << pgid + << " " << map_epoch << "/" << min_epoch + << " " << replies; + out << ")"; + } + + std::string_view get_type_name() const override { return "MOSDPGPushReply"; } +}; + +#endif diff --git a/src/messages/MOSDPGQuery.h b/src/messages/MOSDPGQuery.h new file mode 100644 index 000000000..b9a48b989 --- /dev/null +++ b/src/messages/MOSDPGQuery.h @@ -0,0 +1,82 @@ +// -*- 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_MOSDPGQUERY_H +#define CEPH_MOSDPGQUERY_H + +#include "common/hobject.h" +#include "msg/Message.h" + +/* + * PGQuery - query another OSD as to the contents of their PGs + */ + +class MOSDPGQuery final : public Message { +private: + static constexpr int HEAD_VERSION = 4; + static constexpr int COMPAT_VERSION = 4; + + version_t epoch = 0; + + public: + version_t get_epoch() const { return epoch; } + using pg_list_t = std::map<spg_t, pg_query_t>; + pg_list_t pg_list; + + MOSDPGQuery() : Message{MSG_OSD_PG_QUERY, + HEAD_VERSION, + COMPAT_VERSION} { + set_priority(CEPH_MSG_PRIO_HIGH); + } + MOSDPGQuery(epoch_t e, pg_list_t&& ls) : + Message{MSG_OSD_PG_QUERY, + HEAD_VERSION, + COMPAT_VERSION}, + epoch(e), + pg_list(std::move(ls)) { + set_priority(CEPH_MSG_PRIO_HIGH); + } +private: + ~MOSDPGQuery() final {} + +public: + std::string_view get_type_name() const override { return "pg_query"; } + void print(std::ostream& out) const override { + out << "pg_query("; + for (auto p = pg_list.begin(); p != pg_list.end(); ++p) { + if (p != pg_list.begin()) + out << ","; + out << p->first; + } + out << " epoch " << epoch << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(epoch, payload); + encode(pg_list, payload, features); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(epoch, p); + decode(pg_list, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MOSDPGQuery2.h b/src/messages/MOSDPGQuery2.h new file mode 100644 index 000000000..d2257ee53 --- /dev/null +++ b/src/messages/MOSDPGQuery2.h @@ -0,0 +1,78 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#pragma once + +#include "messages/MOSDPeeringOp.h" +#include "osd/PGPeeringEvent.h" + +class MOSDPGQuery2 final : public MOSDPeeringOp { +private: + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; + +public: + spg_t spgid; + pg_query_t query; + + spg_t get_spg() const override { + return spgid; + } + epoch_t get_map_epoch() const override { + return query.epoch_sent; + } + epoch_t get_min_epoch() const override { + return query.epoch_sent; + } + + PGPeeringEvent *get_event() override { + return new PGPeeringEvent( + query.epoch_sent, + query.epoch_sent, + MQuery( + spgid, + pg_shard_t(get_source().num(), query.from), + query, + query.epoch_sent), + false); + } + + MOSDPGQuery2() : MOSDPeeringOp{MSG_OSD_PG_QUERY2, + HEAD_VERSION, COMPAT_VERSION} { + set_priority(CEPH_MSG_PRIO_HIGH); + } + MOSDPGQuery2( + spg_t s, + pg_query_t q) + : MOSDPeeringOp{MSG_OSD_PG_QUERY2, HEAD_VERSION, COMPAT_VERSION}, + spgid(s), + query(q) { + set_priority(CEPH_MSG_PRIO_HIGH); + } + +private: + ~MOSDPGQuery2() final {} + +public: + std::string_view get_type_name() const override { + return "pg_query2"; + } + void inner_print(std::ostream& out) const override { + out << spgid << " " << query; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(spgid, payload); + encode(query, payload, features); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(spgid, p); + decode(query, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; diff --git a/src/messages/MOSDPGReadyToMerge.h b/src/messages/MOSDPGReadyToMerge.h new file mode 100644 index 000000000..e75212638 --- /dev/null +++ b/src/messages/MOSDPGReadyToMerge.h @@ -0,0 +1,61 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#pragma once + +class MOSDPGReadyToMerge : public PaxosServiceMessage { +public: + pg_t pgid; + eversion_t source_version, target_version; + epoch_t last_epoch_started = 0; + epoch_t last_epoch_clean = 0; + bool ready = true; + + MOSDPGReadyToMerge() + : PaxosServiceMessage{MSG_OSD_PG_READY_TO_MERGE, 0} + {} + MOSDPGReadyToMerge(pg_t p, eversion_t sv, eversion_t tv, + epoch_t les, epoch_t lec, bool r, epoch_t v) + : PaxosServiceMessage{MSG_OSD_PG_READY_TO_MERGE, v}, + pgid(p), + source_version(sv), + target_version(tv), + last_epoch_started(les), + last_epoch_clean(lec), + ready(r) + {} + void encode_payload(uint64_t features) override { + using ceph::encode; + paxos_encode(); + encode(pgid, payload); + encode(source_version, payload); + encode(target_version, payload); + encode(last_epoch_started, payload); + encode(last_epoch_clean, payload); + encode(ready, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + paxos_decode(p); + decode(pgid, p); + decode(source_version, p); + decode(target_version, p); + decode(last_epoch_started, p); + decode(last_epoch_clean, p); + decode(ready, p); + } + std::string_view get_type_name() const override { return "osd_pg_ready_to_merge"; } + void print(std::ostream &out) const { + out << get_type_name() + << "(" << pgid + << " sv " << source_version + << " tv " << target_version + << " les/c " << last_epoch_started << "/" << last_epoch_clean + << (ready ? " ready" : " NOT READY") + << " v" << version << ")"; + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; diff --git a/src/messages/MOSDPGRecoveryDelete.h b/src/messages/MOSDPGRecoveryDelete.h new file mode 100644 index 000000000..555a1c733 --- /dev/null +++ b/src/messages/MOSDPGRecoveryDelete.h @@ -0,0 +1,94 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef CEPH_MOSDPGRECOVERYDELETE_H +#define CEPH_MOSDPGRECOVERYDELETE_H + +#include "MOSDFastDispatchOp.h" + +/* + * instruct non-primary to remove some objects during recovery + */ + +class MOSDPGRecoveryDelete final : public MOSDFastDispatchOp { +public: + static constexpr int HEAD_VERSION = 2; + static constexpr int COMPAT_VERSION = 1; + + pg_shard_t from; + spg_t pgid; ///< target spg_t + epoch_t map_epoch, min_epoch; + std::list<std::pair<hobject_t, eversion_t>> objects; ///< objects to remove + +private: + uint64_t cost = 0; + +public: + int get_cost() const override { + return cost; + } + + epoch_t get_map_epoch() const override { + return map_epoch; + } + epoch_t get_min_epoch() const override { + return min_epoch; + } + spg_t get_spg() const override { + return pgid; + } + + void set_cost(uint64_t c) { + cost = c; + } + + MOSDPGRecoveryDelete() + : MOSDFastDispatchOp{MSG_OSD_PG_RECOVERY_DELETE, HEAD_VERSION, + COMPAT_VERSION} + {} + + MOSDPGRecoveryDelete(pg_shard_t from, spg_t pgid, epoch_t map_epoch, + epoch_t min_epoch) + : MOSDFastDispatchOp{MSG_OSD_PG_RECOVERY_DELETE, HEAD_VERSION, + COMPAT_VERSION}, + from(from), + pgid(pgid), + map_epoch(map_epoch), + min_epoch(min_epoch) + {} + +private: + ~MOSDPGRecoveryDelete() final {} + +public: + std::string_view get_type_name() const { return "recovery_delete"; } + void print(std::ostream& out) const { + out << "MOSDPGRecoveryDelete(" << pgid << " e" << map_epoch << "," + << min_epoch << " " << objects << ")"; + } + + void encode_payload(uint64_t features) { + using ceph::encode; + encode(from, payload); + encode(pgid, payload); + encode(map_epoch, payload); + encode(min_epoch, payload); + encode(cost, payload); + encode(objects, payload); + } + void decode_payload() { + using ceph::decode; + auto p = payload.cbegin(); + decode(from, p); + decode(pgid, p); + decode(map_epoch, p); + decode(min_epoch, p); + decode(cost, p); + decode(objects, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MOSDPGRecoveryDeleteReply.h b/src/messages/MOSDPGRecoveryDeleteReply.h new file mode 100644 index 000000000..60f494b62 --- /dev/null +++ b/src/messages/MOSDPGRecoveryDeleteReply.h @@ -0,0 +1,67 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef MOSDRECOVERYDELETEREPLY_H +#define MOSDRECOVERYDELETEREPLY_H + +#include "MOSDFastDispatchOp.h" + +class MOSDPGRecoveryDeleteReply : public MOSDFastDispatchOp { +public: + static constexpr int HEAD_VERSION = 2; + static constexpr int COMPAT_VERSION = 1; + + pg_shard_t from; + spg_t pgid; + epoch_t map_epoch = 0; + epoch_t min_epoch = 0; + std::list<std::pair<hobject_t, eversion_t> > objects; + + epoch_t get_map_epoch() const override { + return map_epoch; + } + epoch_t get_min_epoch() const override { + return min_epoch; + } + spg_t get_spg() const override { + return pgid; + } + + MOSDPGRecoveryDeleteReply() + : MOSDFastDispatchOp{MSG_OSD_PG_RECOVERY_DELETE_REPLY, HEAD_VERSION, COMPAT_VERSION} + {} + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(pgid.pgid, p); + decode(map_epoch, p); + decode(min_epoch, p); + decode(objects, p); + decode(pgid.shard, p); + decode(from, p); + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(pgid.pgid, payload); + encode(map_epoch, payload); + encode(min_epoch, payload); + encode(objects, payload); + encode(pgid.shard, payload); + encode(from, payload); + } + + void print(std::ostream& out) const override { + out << "MOSDPGRecoveryDeleteReply(" << pgid + << " e" << map_epoch << "," << min_epoch << " " << objects << ")"; + } + + std::string_view get_type_name() const override { return "recovery_delete_reply"; } + +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MOSDPGRemove.h b/src/messages/MOSDPGRemove.h new file mode 100644 index 000000000..3ac651ba7 --- /dev/null +++ b/src/messages/MOSDPGRemove.h @@ -0,0 +1,71 @@ +// -*- 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_MOSDPGREMOVE_H +#define CEPH_MOSDPGREMOVE_H + +#include "common/hobject.h" +#include "msg/Message.h" + + +class MOSDPGRemove final : public Message { +private: + static constexpr int HEAD_VERSION = 3; + static constexpr int COMPAT_VERSION = 3; + + epoch_t epoch = 0; + + public: + std::vector<spg_t> pg_list; + + epoch_t get_epoch() const { return epoch; } + + MOSDPGRemove() : + Message{MSG_OSD_PG_REMOVE, HEAD_VERSION, COMPAT_VERSION} {} + MOSDPGRemove(epoch_t e, std::vector<spg_t>& l) : + Message{MSG_OSD_PG_REMOVE, HEAD_VERSION, COMPAT_VERSION} { + this->epoch = e; + pg_list.swap(l); + } +private: + ~MOSDPGRemove() final {} + +public: + std::string_view get_type_name() const override { return "PGrm"; } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(epoch, payload); + encode(pg_list, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(epoch, p); + decode(pg_list, p); + } + void print(std::ostream& out) const override { + out << "osd pg remove(" << "epoch " << epoch << "; "; + for (auto i = pg_list.begin(); i != pg_list.end(); ++i) { + out << "pg" << *i << "; "; + } + out << ")"; + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MOSDPGScan.h b/src/messages/MOSDPGScan.h new file mode 100644 index 000000000..c80bb6efc --- /dev/null +++ b/src/messages/MOSDPGScan.h @@ -0,0 +1,119 @@ +// -*- 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_MOSDPGSCAN_H +#define CEPH_MOSDPGSCAN_H + +#include "MOSDFastDispatchOp.h" + +class MOSDPGScan final : public MOSDFastDispatchOp { +private: + static constexpr int HEAD_VERSION = 2; + static constexpr int COMPAT_VERSION = 2; + +public: + enum { + OP_SCAN_GET_DIGEST = 1, // just objects and versions + OP_SCAN_DIGEST = 2, // result + }; + const char *get_op_name(int o) const { + switch (o) { + case OP_SCAN_GET_DIGEST: return "get_digest"; + case OP_SCAN_DIGEST: return "digest"; + default: return "???"; + } + } + + __u32 op = 0; + epoch_t map_epoch = 0, query_epoch = 0; + pg_shard_t from; + spg_t pgid; + hobject_t begin, end; + + epoch_t get_map_epoch() const override { + return map_epoch; + } + epoch_t get_min_epoch() const override { + return query_epoch; + } + spg_t get_spg() const override { + return pgid; + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(op, p); + decode(map_epoch, p); + decode(query_epoch, p); + decode(pgid.pgid, p); + decode(begin, p); + decode(end, p); + + // handle hobject_t format upgrade + if (!begin.is_max() && begin.pool == -1) + begin.pool = pgid.pool(); + if (!end.is_max() && end.pool == -1) + end.pool = pgid.pool(); + + decode(from, p); + decode(pgid.shard, p); + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(op, payload); + encode(map_epoch, payload); + if (!HAVE_FEATURE(features, SERVER_NAUTILUS)) { + // pre-nautilus OSDs do not set last_peering_reset properly + encode(map_epoch, payload); + } else { + encode(query_epoch, payload); + } + encode(pgid.pgid, payload); + encode(begin, payload); + encode(end, payload); + encode(from, payload); + encode(pgid.shard, payload); + } + + MOSDPGScan() + : MOSDFastDispatchOp{MSG_OSD_PG_SCAN, HEAD_VERSION, COMPAT_VERSION} {} + MOSDPGScan(__u32 o, pg_shard_t from, + epoch_t e, epoch_t qe, spg_t p, hobject_t be, hobject_t en) + : MOSDFastDispatchOp{MSG_OSD_PG_SCAN, HEAD_VERSION, COMPAT_VERSION}, + op(o), + map_epoch(e), query_epoch(qe), + from(from), + pgid(p), + begin(be), end(en) { + } +private: + ~MOSDPGScan() final {} + +public: + std::string_view get_type_name() const override { return "pg_scan"; } + void print(std::ostream& out) const override { + out << "pg_scan(" << get_op_name(op) + << " " << pgid + << " " << begin << "-" << end + << " e " << map_epoch << "/" << query_epoch + << ")"; + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MOSDPGTemp.h b/src/messages/MOSDPGTemp.h new file mode 100644 index 000000000..d73a767b7 --- /dev/null +++ b/src/messages/MOSDPGTemp.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 <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_MOSDPGTEMP_H +#define CEPH_MOSDPGTEMP_H + +#include "messages/PaxosServiceMessage.h" + +class MOSDPGTemp final : public PaxosServiceMessage { +public: + epoch_t map_epoch = 0; + std::map<pg_t, std::vector<int32_t> > pg_temp; + bool forced = false; + + MOSDPGTemp(epoch_t e) + : PaxosServiceMessage{MSG_OSD_PGTEMP, e, HEAD_VERSION, COMPAT_VERSION}, + map_epoch(e) + {} + MOSDPGTemp() + : MOSDPGTemp(0) + {} +private: + ~MOSDPGTemp() final {} + +public: + void encode_payload(uint64_t features) override { + using ceph::encode; + paxos_encode(); + encode(map_epoch, payload); + encode(pg_temp, payload); + encode(forced, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + paxos_decode(p); + decode(map_epoch, p); + decode(pg_temp, p); + if (header.version >= 2) { + decode(forced, p); + } + } + + std::string_view get_type_name() const override { return "osd_pgtemp"; } + void print(std::ostream &out) const override { + out << "osd_pgtemp(e" << map_epoch << " " << pg_temp << " v" << version << ")"; + } +private: + static constexpr int HEAD_VERSION = 2; + static constexpr int COMPAT_VERSION = 1; + + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MOSDPGTrim.h b/src/messages/MOSDPGTrim.h new file mode 100644 index 000000000..91ba1c786 --- /dev/null +++ b/src/messages/MOSDPGTrim.h @@ -0,0 +1,82 @@ +// -*- 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_MOSDPGTRIM_H +#define CEPH_MOSDPGTRIM_H + +#include "msg/Message.h" +#include "messages/MOSDPeeringOp.h" +#include "osd/PGPeeringEvent.h" + +class MOSDPGTrim final : public MOSDPeeringOp { +private: + static constexpr int HEAD_VERSION = 2; + static constexpr int COMPAT_VERSION = 2; + +public: + epoch_t epoch = 0; + spg_t pgid; + eversion_t trim_to; + + epoch_t get_epoch() const { return epoch; } + spg_t get_spg() const { + return pgid; + } + epoch_t get_map_epoch() const { + return epoch; + } + epoch_t get_min_epoch() const { + return epoch; + } + PGPeeringEvent *get_event() override { + return new PGPeeringEvent( + epoch, + epoch, + MTrim(epoch, get_source().num(), pgid.shard, trim_to)); + } + + MOSDPGTrim() : MOSDPeeringOp{MSG_OSD_PG_TRIM, HEAD_VERSION, COMPAT_VERSION} {} + MOSDPGTrim(version_t mv, spg_t p, eversion_t tt) : + MOSDPeeringOp{MSG_OSD_PG_TRIM, HEAD_VERSION, COMPAT_VERSION}, + epoch(mv), pgid(p), trim_to(tt) { } +private: + ~MOSDPGTrim() final {} + +public: + std::string_view get_type_name() const override { return "pg_trim"; } + void inner_print(std::ostream& out) const override { + out << trim_to; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(epoch, payload); + encode(pgid.pgid, payload); + encode(trim_to, payload); + encode(pgid.shard, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(epoch, p); + decode(pgid.pgid, p); + decode(trim_to, p); + decode(pgid.shard, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MOSDPGUpdateLogMissing.h b/src/messages/MOSDPGUpdateLogMissing.h new file mode 100644 index 000000000..2a0011e8f --- /dev/null +++ b/src/messages/MOSDPGUpdateLogMissing.h @@ -0,0 +1,124 @@ +// -*- 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_MOSDPGUPDATELOGMISSING_H +#define CEPH_MOSDPGUPDATELOGMISSING_H + +#include "MOSDFastDispatchOp.h" + +class MOSDPGUpdateLogMissing final : public MOSDFastDispatchOp { +private: + static constexpr int HEAD_VERSION = 3; + static constexpr int COMPAT_VERSION = 1; + +public: + epoch_t map_epoch = 0, min_epoch = 0; + spg_t pgid; + shard_id_t from; + ceph_tid_t rep_tid = 0; + mempool::osd_pglog::list<pg_log_entry_t> entries; + // piggybacked osd/pg state + eversion_t pg_trim_to; // primary->replica: trim to here + eversion_t pg_roll_forward_to; // primary->replica: trim rollback info to here + + epoch_t get_epoch() const { return map_epoch; } + spg_t get_pgid() const { return pgid; } + epoch_t get_query_epoch() const { return map_epoch; } + ceph_tid_t get_tid() const { return rep_tid; } + + epoch_t get_map_epoch() const override { + return map_epoch; + } + epoch_t get_min_epoch() const override { + return min_epoch; + } + spg_t get_spg() const override { + return pgid; + } + + MOSDPGUpdateLogMissing() + : MOSDFastDispatchOp{MSG_OSD_PG_UPDATE_LOG_MISSING, HEAD_VERSION, + COMPAT_VERSION} {} + MOSDPGUpdateLogMissing( + const mempool::osd_pglog::list<pg_log_entry_t> &entries, + spg_t pgid, + shard_id_t from, + epoch_t epoch, + epoch_t min_epoch, + ceph_tid_t rep_tid, + eversion_t pg_trim_to, + eversion_t pg_roll_forward_to) + : MOSDFastDispatchOp{MSG_OSD_PG_UPDATE_LOG_MISSING, HEAD_VERSION, + COMPAT_VERSION}, + map_epoch(epoch), + min_epoch(min_epoch), + pgid(pgid), + from(from), + rep_tid(rep_tid), + entries(entries), + pg_trim_to(pg_trim_to), + pg_roll_forward_to(pg_roll_forward_to) + {} + +private: + ~MOSDPGUpdateLogMissing() final {} + +public: + std::string_view get_type_name() const override { return "PGUpdateLogMissing"; } + void print(std::ostream& out) const override { + out << "pg_update_log_missing(" << pgid << " epoch " << map_epoch + << "/" << min_epoch + << " rep_tid " << rep_tid + << " entries " << entries + << " trim_to " << pg_trim_to + << " roll_forward_to " << pg_roll_forward_to + << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(map_epoch, payload); + encode(pgid, payload); + encode(from, payload); + encode(rep_tid, payload); + encode(entries, payload); + encode(min_epoch, payload); + encode(pg_trim_to, payload); + encode(pg_roll_forward_to, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(map_epoch, p); + decode(pgid, p); + decode(from, p); + decode(rep_tid, p); + decode(entries, p); + if (header.version >= 2) { + decode(min_epoch, p); + } else { + min_epoch = map_epoch; + } + if (header.version >= 3) { + decode(pg_trim_to, p); + decode(pg_roll_forward_to, p); + } + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MOSDPGUpdateLogMissingReply.h b/src/messages/MOSDPGUpdateLogMissingReply.h new file mode 100644 index 000000000..559c14353 --- /dev/null +++ b/src/messages/MOSDPGUpdateLogMissingReply.h @@ -0,0 +1,115 @@ +// -*- 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_MOSDPGUPDATELOGMISSINGREPLY_H +#define CEPH_MOSDPGUPDATELOGMISSINGREPLY_H + +#include "MOSDFastDispatchOp.h" + +class MOSDPGUpdateLogMissingReply final : public MOSDFastDispatchOp { +private: + static constexpr int HEAD_VERSION = 3; + static constexpr int COMPAT_VERSION = 1; + + +public: + epoch_t map_epoch = 0, min_epoch = 0; + spg_t pgid; + shard_id_t from; + ceph_tid_t rep_tid = 0; + // piggybacked osd state + eversion_t last_complete_ondisk; + + epoch_t get_epoch() const { return map_epoch; } + spg_t get_pgid() const { return pgid; } + epoch_t get_query_epoch() const { return map_epoch; } + ceph_tid_t get_tid() const { return rep_tid; } + pg_shard_t get_from() const { + return pg_shard_t(get_source().num(), from); + } + epoch_t get_map_epoch() const override { + return map_epoch; + } + epoch_t get_min_epoch() const override { + return min_epoch; + } + spg_t get_spg() const override { + return pgid; + } + + MOSDPGUpdateLogMissingReply() + : MOSDFastDispatchOp{MSG_OSD_PG_UPDATE_LOG_MISSING_REPLY, HEAD_VERSION, + COMPAT_VERSION} + {} + MOSDPGUpdateLogMissingReply( + spg_t pgid, + shard_id_t from, + epoch_t epoch, + epoch_t min_epoch, + ceph_tid_t rep_tid, + eversion_t last_complete_ondisk) + : MOSDFastDispatchOp{MSG_OSD_PG_UPDATE_LOG_MISSING_REPLY, HEAD_VERSION, + COMPAT_VERSION}, + map_epoch(epoch), + min_epoch(min_epoch), + pgid(pgid), + from(from), + rep_tid(rep_tid), + last_complete_ondisk(last_complete_ondisk) + {} + +private: + ~MOSDPGUpdateLogMissingReply() final {} + +public: + std::string_view get_type_name() const override { return "PGUpdateLogMissingReply"; } + void print(std::ostream& out) const override { + out << "pg_update_log_missing_reply(" << pgid << " epoch " << map_epoch + << "/" << min_epoch + << " rep_tid " << rep_tid + << " lcod " << last_complete_ondisk << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(map_epoch, payload); + encode(pgid, payload); + encode(from, payload); + encode(rep_tid, payload); + encode(min_epoch, payload); + encode(last_complete_ondisk, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(map_epoch, p); + decode(pgid, p); + decode(from, p); + decode(rep_tid, p); + if (header.version >= 2) { + decode(min_epoch, p); + } else { + min_epoch = map_epoch; + } + if (header.version >= 3) { + decode(last_complete_ondisk, p); + } + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MOSDPeeringOp.h b/src/messages/MOSDPeeringOp.h new file mode 100644 index 000000000..56d10cff1 --- /dev/null +++ b/src/messages/MOSDPeeringOp.h @@ -0,0 +1,28 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#pragma once + +#include "msg/Message.h" +#include "osd/osd_types.h" + +class PGPeeringEvent; + +class MOSDPeeringOp : public Message { +public: + MOSDPeeringOp(int t, int version, int compat_version) + : Message{t, version, compat_version} {} + + void print(std::ostream& out) const override final { + out << get_type_name() << "(" + << get_spg() << " "; + inner_print(out); + out << " e" << get_map_epoch() << "/" << get_min_epoch() << ")"; + } + + virtual spg_t get_spg() const = 0; + virtual epoch_t get_map_epoch() const = 0; + virtual epoch_t get_min_epoch() const = 0; + virtual PGPeeringEvent *get_event() = 0; + virtual void inner_print(std::ostream& out) const = 0; +}; diff --git a/src/messages/MOSDPing.h b/src/messages/MOSDPing.h new file mode 100644 index 000000000..8f512a7d7 --- /dev/null +++ b/src/messages/MOSDPing.h @@ -0,0 +1,168 @@ +// -*- 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. + * + */ + + +/** + * This is used to send pings between daemons (so far, the OSDs) for + * heartbeat purposes. We include a timestamp and distinguish between + * outgoing pings and responses to those. If you set the + * min_message in the constructor, the message will inflate itself + * to the specified size -- this is good for dealing with network + * issues with jumbo frames. See http://tracker.ceph.com/issues/20087 + * + */ + +#ifndef CEPH_MOSDPING_H +#define CEPH_MOSDPING_H + +#include "common/Clock.h" + +#include "msg/Message.h" +#include "osd/osd_types.h" + + +class MOSDPing final : public Message { +private: + static constexpr int HEAD_VERSION = 5; + static constexpr int COMPAT_VERSION = 4; + + public: + enum { + HEARTBEAT = 0, + START_HEARTBEAT = 1, + YOU_DIED = 2, + STOP_HEARTBEAT = 3, + PING = 4, + PING_REPLY = 5, + }; + const char *get_op_name(int op) const { + switch (op) { + case HEARTBEAT: return "heartbeat"; + case START_HEARTBEAT: return "start_heartbeat"; + case STOP_HEARTBEAT: return "stop_heartbeat"; + case YOU_DIED: return "you_died"; + case PING: return "ping"; + case PING_REPLY: return "ping_reply"; + default: return "???"; + } + } + + uuid_d fsid; + epoch_t map_epoch = 0; + __u8 op = 0; + utime_t ping_stamp; ///< when the PING was sent + ceph::signedspan mono_ping_stamp; ///< relative to sender's clock + ceph::signedspan mono_send_stamp; ///< replier's send stamp + std::optional<ceph::signedspan> delta_ub; ///< ping sender + epoch_t up_from = 0; + + uint32_t min_message_size = 0; + + MOSDPing(const uuid_d& f, epoch_t e, __u8 o, + utime_t s, + ceph::signedspan ms, + ceph::signedspan mss, + epoch_t upf, + uint32_t min_message, + std::optional<ceph::signedspan> delta_ub = {}) + : Message{MSG_OSD_PING, HEAD_VERSION, COMPAT_VERSION}, + fsid(f), map_epoch(e), op(o), + ping_stamp(s), + mono_ping_stamp(ms), + mono_send_stamp(mss), + delta_ub(delta_ub), + up_from(upf), + min_message_size(min_message) + { } + MOSDPing() + : Message{MSG_OSD_PING, HEAD_VERSION, COMPAT_VERSION} + {} +private: + ~MOSDPing() final {} + +public: + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(fsid, p); + decode(map_epoch, p); + decode(op, p); + decode(ping_stamp, p); + + int payload_mid_length = p.get_off(); + uint32_t size; + decode(size, p); + + if (header.version >= 5) { + decode(up_from, p); + decode(mono_ping_stamp, p); + decode(mono_send_stamp, p); + decode(delta_ub, p); + } + + p += size; + min_message_size = size + payload_mid_length; + } + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(fsid, payload); + encode(map_epoch, payload); + encode(op, payload); + encode(ping_stamp, payload); + + size_t s = 0; + if (min_message_size > payload.length()) { + s = min_message_size - payload.length(); + } + encode((uint32_t)s, payload); + + encode(up_from, payload); + encode(mono_ping_stamp, payload); + encode(mono_send_stamp, payload); + encode(delta_ub, payload); + + if (s) { + // this should be big enough for normal min_message padding sizes. since + // we are targeting jumbo ethernet frames around 9000 bytes, 16k should + // be more than sufficient! the compiler will statically zero this so + // that at runtime we are only adding a bufferptr reference to it. + static char zeros[16384] = {}; + while (s > sizeof(zeros)) { + payload.append(ceph::buffer::create_static(sizeof(zeros), zeros)); + s -= sizeof(zeros); + } + if (s) { + payload.append(ceph::buffer::create_static(s, zeros)); + } + } + } + + std::string_view get_type_name() const override { return "osd_ping"; } + void print(std::ostream& out) const override { + out << "osd_ping(" << get_op_name(op) + << " e" << map_epoch + << " up_from " << up_from + << " ping_stamp " << ping_stamp << "/" << mono_ping_stamp + << " send_stamp " << mono_send_stamp; + if (delta_ub) { + out << " delta_ub " << *delta_ub; + } + out << ")"; + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MOSDRepOp.h b/src/messages/MOSDRepOp.h new file mode 100644 index 000000000..5ecec0007 --- /dev/null +++ b/src/messages/MOSDRepOp.h @@ -0,0 +1,199 @@ +// -*- 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_MOSDREPOP_H +#define CEPH_MOSDREPOP_H + +#include "MOSDFastDispatchOp.h" + +/* + * OSD sub op - for internal ops on pobjects between primary and replicas(/stripes/whatever) + */ + +class MOSDRepOp final : public MOSDFastDispatchOp { +private: + static constexpr int HEAD_VERSION = 3; + static constexpr int COMPAT_VERSION = 1; + +public: + epoch_t map_epoch, min_epoch; + + // metadata from original request + osd_reqid_t reqid; + + spg_t pgid; + + ceph::buffer::list::const_iterator p; + // Decoding flags. Decoding is only needed for messages caught by pipe reader. + bool final_decode_needed; + + // subop + pg_shard_t from; + hobject_t poid; + + __u8 acks_wanted; + + // transaction to exec + ceph::buffer::list logbl; + pg_stat_t pg_stats; + + // subop metadata + eversion_t version; + + // piggybacked osd/og state + eversion_t pg_trim_to; // primary->replica: trim to here + eversion_t min_last_complete_ondisk; // lower bound on committed version + + hobject_t new_temp_oid; ///< new temp object that we must now start tracking + hobject_t discard_temp_oid; ///< previously used temp object that we can now stop tracking + + /// non-empty if this transaction involves a hit_set history update + std::optional<pg_hit_set_history_t> updated_hit_set_history; + + epoch_t get_map_epoch() const override { + return map_epoch; + } + epoch_t get_min_epoch() const override { + return min_epoch; + } + spg_t get_spg() const override { + return pgid; + } + + int get_cost() const override { + return data.length(); + } + + void decode_payload() override { + using ceph::decode; + p = payload.cbegin(); + // split to partial and final + decode(map_epoch, p); + if (header.version >= 2) { + decode(min_epoch, p); + decode_trace(p); + } else { + min_epoch = map_epoch; + } + decode(reqid, p); + decode(pgid, p); + } + + void finish_decode() { + using ceph::decode; + if (!final_decode_needed) + return; // Message is already final decoded + decode(poid, p); + + decode(acks_wanted, p); + decode(version, p); + decode(logbl, p); + decode(pg_stats, p); + decode(pg_trim_to, p); + + + decode(new_temp_oid, p); + decode(discard_temp_oid, p); + + decode(from, p); + decode(updated_hit_set_history, p); + + if (header.version >= 3) { + decode(min_last_complete_ondisk, p); + } else { + /* This field used to mean pg_roll_foward_to, but ReplicatedBackend + * simply assumes that we're rolling foward to version. */ + eversion_t pg_roll_forward_to; + decode(pg_roll_forward_to, p); + } + final_decode_needed = false; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(map_epoch, payload); + if (HAVE_FEATURE(features, SERVER_LUMINOUS)) { + header.version = HEAD_VERSION; + encode(min_epoch, payload); + encode_trace(payload, features); + } else { + header.version = 1; + } + encode(reqid, payload); + encode(pgid, payload); + encode(poid, payload); + + encode(acks_wanted, payload); + encode(version, payload); + encode(logbl, payload); + encode(pg_stats, payload); + encode(pg_trim_to, payload); + encode(new_temp_oid, payload); + encode(discard_temp_oid, payload); + encode(from, payload); + encode(updated_hit_set_history, payload); + encode(min_last_complete_ondisk, payload); + } + + MOSDRepOp() + : MOSDFastDispatchOp{MSG_OSD_REPOP, HEAD_VERSION, COMPAT_VERSION}, + map_epoch(0), + final_decode_needed(true), acks_wanted (0) {} + MOSDRepOp(osd_reqid_t r, pg_shard_t from, + spg_t p, const hobject_t& po, int aw, + epoch_t mape, epoch_t min_epoch, ceph_tid_t rtid, eversion_t v) + : MOSDFastDispatchOp{MSG_OSD_REPOP, HEAD_VERSION, COMPAT_VERSION}, + map_epoch(mape), + min_epoch(min_epoch), + reqid(r), + pgid(p), + final_decode_needed(false), + from(from), + poid(po), + acks_wanted(aw), + version(v) { + set_tid(rtid); + } + + void set_rollback_to(const eversion_t &rollback_to) { + header.version = 2; + min_last_complete_ondisk = rollback_to; + } +private: + ~MOSDRepOp() final {} + +public: + std::string_view get_type_name() const override { return "osd_repop"; } + void print(std::ostream& out) const override { + out << "osd_repop(" << reqid + << " " << pgid << " e" << map_epoch << "/" << min_epoch; + if (!final_decode_needed) { + out << " " << poid << " v " << version; + if (updated_hit_set_history) + out << ", has_updated_hit_set_history"; + if (header.version < 3) { + out << ", rollback_to(legacy)=" << min_last_complete_ondisk; + } else { + out << ", mlcod=" << min_last_complete_ondisk; + } + } + out << ")"; + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MOSDRepOpReply.h b/src/messages/MOSDRepOpReply.h new file mode 100644 index 000000000..8974b4b0f --- /dev/null +++ b/src/messages/MOSDRepOpReply.h @@ -0,0 +1,164 @@ +// -*- 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_MOSDREPOPREPLY_H +#define CEPH_MOSDREPOPREPLY_H + +#include "MOSDFastDispatchOp.h" +#include "MOSDRepOp.h" + +/* + * OSD Client Subop reply + * + * oid - object id + * op - OSD_OP_DELETE, etc. + * + */ + +class MOSDRepOpReply final : public MOSDFastDispatchOp { +private: + static constexpr int HEAD_VERSION = 2; + static constexpr int COMPAT_VERSION = 1; +public: + epoch_t map_epoch, min_epoch; + + // subop metadata + osd_reqid_t reqid; + pg_shard_t from; + spg_t pgid; + + // result + __u8 ack_type; + int32_t result; + + // piggybacked osd state + eversion_t last_complete_ondisk; + + ceph::buffer::list::const_iterator p; + // Decoding flags. Decoding is only needed for messages caught by pipe reader. + bool final_decode_needed; + + epoch_t get_map_epoch() const override { + return map_epoch; + } + epoch_t get_min_epoch() const override { + return min_epoch; + } + spg_t get_spg() const override { + return pgid; + } + + void decode_payload() override { + using ceph::decode; + p = payload.cbegin(); + decode(map_epoch, p); + if (header.version >= 2) { + decode(min_epoch, p); + decode_trace(p); + } else { + min_epoch = map_epoch; + } + decode(reqid, p); + decode(pgid, p); + } + + void finish_decode() { + using ceph::decode; + if (!final_decode_needed) + return; // Message is already final decoded + decode(ack_type, p); + decode(result, p); + decode(last_complete_ondisk, p); + + decode(from, p); + final_decode_needed = false; + } + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(map_epoch, payload); + if (HAVE_FEATURE(features, SERVER_LUMINOUS)) { + header.version = HEAD_VERSION; + encode(min_epoch, payload); + encode_trace(payload, features); + } else { + header.version = 1; + } + encode(reqid, payload); + encode(pgid, payload); + encode(ack_type, payload); + encode(result, payload); + encode(last_complete_ondisk, payload); + encode(from, payload); + } + + spg_t get_pg() { return pgid; } + + int get_ack_type() { return ack_type; } + bool is_ondisk() { return ack_type & CEPH_OSD_FLAG_ONDISK; } + bool is_onnvram() { return ack_type & CEPH_OSD_FLAG_ONNVRAM; } + + int get_result() { return result; } + + void set_last_complete_ondisk(eversion_t v) { last_complete_ondisk = v; } + eversion_t get_last_complete_ondisk() const { return last_complete_ondisk; } + +public: + MOSDRepOpReply( + const MOSDRepOp *req, pg_shard_t from, int result_, epoch_t e, epoch_t mine, + int at) : + MOSDFastDispatchOp{MSG_OSD_REPOPREPLY, HEAD_VERSION, COMPAT_VERSION}, + map_epoch(e), + min_epoch(mine), + reqid(req->reqid), + from(from), + pgid(req->pgid.pgid, req->from.shard), + ack_type(at), + result(result_), + final_decode_needed(false) { + set_tid(req->get_tid()); + } + MOSDRepOpReply() + : MOSDFastDispatchOp{MSG_OSD_REPOPREPLY, HEAD_VERSION, COMPAT_VERSION}, + map_epoch(0), + min_epoch(0), + ack_type(0), result(0), + final_decode_needed(true) {} +private: + ~MOSDRepOpReply() final {} + +public: + std::string_view get_type_name() const override { return "osd_repop_reply"; } + + void print(std::ostream& out) const override { + out << "osd_repop_reply(" << reqid + << " " << pgid << " e" << map_epoch << "/" << min_epoch; + if (!final_decode_needed) { + if (ack_type & CEPH_OSD_FLAG_ONDISK) + out << " ondisk"; + if (ack_type & CEPH_OSD_FLAG_ONNVRAM) + out << " onnvram"; + if (ack_type & CEPH_OSD_FLAG_ACK) + out << " ack"; + out << ", result = " << result; + } + out << ")"; + } + +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MOSDRepScrub.h b/src/messages/MOSDRepScrub.h new file mode 100644 index 000000000..ededcdca8 --- /dev/null +++ b/src/messages/MOSDRepScrub.h @@ -0,0 +1,142 @@ +// -*- 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_MOSDREPSCRUB_H +#define CEPH_MOSDREPSCRUB_H + +#include "MOSDFastDispatchOp.h" + +/* + * instruct an OSD initiate a replica scrub on a specific PG + */ + +class MOSDRepScrub final : public MOSDFastDispatchOp { +public: + static constexpr int HEAD_VERSION = 9; + static constexpr int COMPAT_VERSION = 6; + + spg_t pgid; // PG to scrub + eversion_t scrub_from; // only scrub log entries after scrub_from + eversion_t scrub_to; // last_update_applied when message sent (not used) + epoch_t map_epoch = 0, min_epoch = 0; + bool chunky; // true for chunky scrubs + hobject_t start; // lower bound of scrub, inclusive + hobject_t end; // upper bound of scrub, exclusive + bool deep; // true if scrub should be deep + bool allow_preemption = false; + int32_t priority = 0; + bool high_priority = false; + + epoch_t get_map_epoch() const override { + return map_epoch; + } + epoch_t get_min_epoch() const override { + return min_epoch; + } + spg_t get_spg() const override { + return pgid; + } + + MOSDRepScrub() + : MOSDFastDispatchOp{MSG_OSD_REP_SCRUB, HEAD_VERSION, COMPAT_VERSION}, + chunky(false), + deep(false) { } + + MOSDRepScrub(spg_t pgid, eversion_t scrub_to, epoch_t map_epoch, epoch_t min_epoch, + hobject_t start, hobject_t end, bool deep, + bool preemption, int prio, bool highprio) + : MOSDFastDispatchOp{MSG_OSD_REP_SCRUB, HEAD_VERSION, COMPAT_VERSION}, + pgid(pgid), + scrub_to(scrub_to), + map_epoch(map_epoch), + min_epoch(min_epoch), + chunky(true), + start(start), + end(end), + deep(deep), + allow_preemption(preemption), + priority(prio), + high_priority(highprio) { } + + +private: + ~MOSDRepScrub() final {} + +public: + std::string_view get_type_name() const override { return "replica scrub"; } + void print(std::ostream& out) const override { + out << "replica_scrub(pg: " << pgid + << ",from:" << scrub_from + << ",to:" << scrub_to + << ",epoch:" << map_epoch << "/" << min_epoch + << ",start:" << start << ",end:" << end + << ",chunky:" << chunky + << ",deep:" << deep + << ",version:" << header.version + << ",allow_preemption:" << (int)allow_preemption + << ",priority=" << priority + << (high_priority ? " (high)":"") + << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(pgid.pgid, payload); + encode(scrub_from, payload); + encode(scrub_to, payload); + encode(map_epoch, payload); + encode(chunky, payload); + encode(start, payload); + encode(end, payload); + encode(deep, payload); + encode(pgid.shard, payload); + encode((uint32_t)-1, payload); // seed + encode(min_epoch, payload); + encode(allow_preemption, payload); + encode(priority, payload); + encode(high_priority, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(pgid.pgid, p); + decode(scrub_from, p); + decode(scrub_to, p); + decode(map_epoch, p); + decode(chunky, p); + decode(start, p); + decode(end, p); + decode(deep, p); + decode(pgid.shard, p); + { + uint32_t seed; + decode(seed, p); + } + if (header.version >= 7) { + decode(min_epoch, p); + } else { + min_epoch = map_epoch; + } + if (header.version >= 8) { + decode(allow_preemption, p); + } + if (header.version >= 9) { + decode(priority, p); + decode(high_priority, p); + } + } +}; + +#endif diff --git a/src/messages/MOSDRepScrubMap.h b/src/messages/MOSDRepScrubMap.h new file mode 100644 index 000000000..51e8b02ee --- /dev/null +++ b/src/messages/MOSDRepScrubMap.h @@ -0,0 +1,84 @@ +// -*- 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) 2017 Sage Weil <sage@redhat.com> + * + * 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_MOSDREPSCRUBMAP_H +#define CEPH_MOSDREPSCRUBMAP_H + +#include "MOSDFastDispatchOp.h" + +/* + * pass a ScrubMap from a shard back to the primary + */ + +class MOSDRepScrubMap final : public MOSDFastDispatchOp { +public: + static constexpr int HEAD_VERSION = 2; + static constexpr int COMPAT_VERSION = 1; + + spg_t pgid; // primary spg_t + epoch_t map_epoch = 0; + pg_shard_t from; // whose scrubmap this is + ceph::buffer::list scrub_map_bl; + bool preempted = false; + + epoch_t get_map_epoch() const override { + return map_epoch; + } + spg_t get_spg() const override { + return pgid; + } + + MOSDRepScrubMap() + : MOSDFastDispatchOp{MSG_OSD_REP_SCRUBMAP, HEAD_VERSION, COMPAT_VERSION} {} + + MOSDRepScrubMap(spg_t pgid, epoch_t map_epoch, pg_shard_t from) + : MOSDFastDispatchOp{MSG_OSD_REP_SCRUBMAP, HEAD_VERSION, COMPAT_VERSION}, + pgid(pgid), + map_epoch(map_epoch), + from(from) {} + +private: + ~MOSDRepScrubMap() final {} + +public: + std::string_view get_type_name() const override { return "rep_scrubmap"; } + void print(std::ostream& out) const override { + out << "rep_scrubmap(" << pgid << " e" << map_epoch + << " from shard " << from + << (preempted ? " PREEMPTED":"") << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(pgid, payload); + encode(map_epoch, payload); + encode(from, payload); + encode(preempted, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(pgid, p); + decode(map_epoch, p); + decode(from, p); + if (header.version >= 2) { + decode(preempted, p); + } + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MOSDScrub.h b/src/messages/MOSDScrub.h new file mode 100644 index 000000000..4f850fad7 --- /dev/null +++ b/src/messages/MOSDScrub.h @@ -0,0 +1,80 @@ +// -*- 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_MOSDSCRUB_H +#define CEPH_MOSDSCRUB_H + +#include "msg/Message.h" + +/* + * instruct an OSD to scrub some or all pg(s) + */ + +class MOSDScrub final : public Message { +public: + static constexpr int HEAD_VERSION = 2; + static constexpr int COMPAT_VERSION = 2; + + uuid_d fsid; + std::vector<pg_t> scrub_pgs; + bool repair = false; + bool deep = false; + + MOSDScrub() : Message{MSG_OSD_SCRUB, HEAD_VERSION, COMPAT_VERSION} {} + MOSDScrub(const uuid_d& f, bool r, bool d) : + Message{MSG_OSD_SCRUB, HEAD_VERSION, COMPAT_VERSION}, + fsid(f), repair(r), deep(d) {} + MOSDScrub(const uuid_d& f, std::vector<pg_t>& pgs, bool r, bool d) : + Message{MSG_OSD_SCRUB, HEAD_VERSION, COMPAT_VERSION}, + fsid(f), scrub_pgs(pgs), repair(r), deep(d) {} +private: + ~MOSDScrub() final {} + +public: + std::string_view get_type_name() const override { return "scrub"; } + void print(std::ostream& out) const override { + out << "scrub("; + if (scrub_pgs.empty()) + out << "osd"; + else + out << scrub_pgs; + if (repair) + out << " repair"; + if (deep) + out << " deep"; + out << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(fsid, payload); + encode(scrub_pgs, payload); + encode(repair, payload); + encode(deep, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(fsid, p); + decode(scrub_pgs, p); + decode(repair, p); + decode(deep, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MOSDScrub2.h b/src/messages/MOSDScrub2.h new file mode 100644 index 000000000..61bafba24 --- /dev/null +++ b/src/messages/MOSDScrub2.h @@ -0,0 +1,61 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#pragma once + +#include "msg/Message.h" + +/* + * instruct an OSD to scrub some or all pg(s) + */ + +class MOSDScrub2 final : public Message { +public: + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; + + uuid_d fsid; + epoch_t epoch; + std::vector<spg_t> scrub_pgs; + bool repair = false; + bool deep = false; + + MOSDScrub2() : Message{MSG_OSD_SCRUB2, HEAD_VERSION, COMPAT_VERSION} {} + MOSDScrub2(const uuid_d& f, epoch_t e, std::vector<spg_t>& pgs, bool r, bool d) : + Message{MSG_OSD_SCRUB2, HEAD_VERSION, COMPAT_VERSION}, + fsid(f), epoch(e), scrub_pgs(pgs), repair(r), deep(d) {} +private: + ~MOSDScrub2() final {} + +public: + std::string_view get_type_name() const override { return "scrub2"; } + void print(std::ostream& out) const override { + out << "scrub2(" << scrub_pgs; + if (repair) + out << " repair"; + if (deep) + out << " deep"; + out << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(fsid, payload); + encode(epoch, payload); + encode(scrub_pgs, payload); + encode(repair, payload); + encode(deep, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(fsid, p); + decode(epoch, p); + decode(scrub_pgs, p); + decode(repair, p); + decode(deep, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; diff --git a/src/messages/MOSDScrubReserve.h b/src/messages/MOSDScrubReserve.h new file mode 100644 index 000000000..f1f76b3e6 --- /dev/null +++ b/src/messages/MOSDScrubReserve.h @@ -0,0 +1,99 @@ +// -*- 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_MOSDSCRUBRESERVE_H +#define CEPH_MOSDSCRUBRESERVE_H + +#include "MOSDFastDispatchOp.h" + +class MOSDScrubReserve : public MOSDFastDispatchOp { +private: + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; +public: + spg_t pgid; + epoch_t map_epoch; + enum { + REQUEST = 0, + GRANT = 1, + RELEASE = 2, + REJECT = 3, + }; + int32_t type; + pg_shard_t from; + + epoch_t get_map_epoch() const override { + return map_epoch; + } + spg_t get_spg() const override { + return pgid; + } + + MOSDScrubReserve() + : MOSDFastDispatchOp{MSG_OSD_SCRUB_RESERVE, HEAD_VERSION, COMPAT_VERSION}, + map_epoch(0), type(-1) {} + MOSDScrubReserve(spg_t pgid, + epoch_t map_epoch, + int type, + pg_shard_t from) + : MOSDFastDispatchOp{MSG_OSD_SCRUB_RESERVE, HEAD_VERSION, COMPAT_VERSION}, + pgid(pgid), map_epoch(map_epoch), + type(type), from(from) {} + + std::string_view get_type_name() const { + return "MOSDScrubReserve"; + } + + void print(std::ostream& out) const { + out << "MOSDScrubReserve(" << pgid << " "; + switch (type) { + case REQUEST: + out << "REQUEST "; + break; + case GRANT: + out << "GRANT "; + break; + case REJECT: + out << "REJECT "; + break; + case RELEASE: + out << "RELEASE "; + break; + } + out << "e" << map_epoch << ")"; + return; + } + + void decode_payload() { + using ceph::decode; + auto p = payload.cbegin(); + decode(pgid, p); + decode(map_epoch, p); + decode(type, p); + decode(from, p); + } + + void encode_payload(uint64_t features) { + using ceph::encode; + encode(pgid, payload); + encode(map_epoch, payload); + encode(type, payload); + encode(from, payload); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MPGStats.h b/src/messages/MPGStats.h new file mode 100644 index 000000000..65cec5244 --- /dev/null +++ b/src/messages/MPGStats.h @@ -0,0 +1,77 @@ +// -*- 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_MPGSTATS_H +#define CEPH_MPGSTATS_H + +#include "osd/osd_types.h" +#include "messages/PaxosServiceMessage.h" + +class MPGStats final : public PaxosServiceMessage { + static constexpr int HEAD_VERSION = 2; + static constexpr int COMPAT_VERSION = 1; + +public: + uuid_d fsid; + std::map<pg_t, pg_stat_t> pg_stat; + osd_stat_t osd_stat; + std::map<int64_t, store_statfs_t> pool_stat; + epoch_t epoch = 0; + + MPGStats() : PaxosServiceMessage{MSG_PGSTATS, 0, HEAD_VERSION, COMPAT_VERSION} {} + MPGStats(const uuid_d& f, epoch_t e) + : PaxosServiceMessage{MSG_PGSTATS, 0, HEAD_VERSION, COMPAT_VERSION}, + fsid(f), + epoch(e) + {} + +private: + ~MPGStats() final {} + +public: + std::string_view get_type_name() const override { return "pg_stats"; } + void print(std::ostream& out) const override { + out << "pg_stats(" << pg_stat.size() << " pgs seq " << osd_stat.seq << " v " << version << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + paxos_encode(); + encode(fsid, payload); + encode(osd_stat, payload, features); + encode(pg_stat, payload); + encode(epoch, payload); + encode(utime_t{}, payload); + encode(pool_stat, payload, features); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + paxos_decode(p); + decode(fsid, p); + decode(osd_stat, p); + if (osd_stat.num_osds == 0) { + // for the benefit of legacy OSDs who don't set this field + osd_stat.num_osds = 1; + } + decode(pg_stat, p); + decode(epoch, p); + utime_t dummy; + decode(dummy, p); + if (header.version >= 2) + decode(pool_stat, p); + } +}; + +#endif diff --git a/src/messages/MPGStatsAck.h b/src/messages/MPGStatsAck.h new file mode 100644 index 000000000..03bade32b --- /dev/null +++ b/src/messages/MPGStatsAck.h @@ -0,0 +1,49 @@ +// -*- 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_MPGSTATSACK_H +#define CEPH_MPGSTATSACK_H + +#include "osd/osd_types.h" + +class MPGStatsAck final : public Message { +public: + std::map<pg_t,std::pair<version_t,epoch_t> > pg_stat; + + MPGStatsAck() : Message{MSG_PGSTATSACK} {} + +private: + ~MPGStatsAck() final {} + +public: + std::string_view get_type_name() const override { return "pg_stats_ack"; } + void print(std::ostream& out) const override { + out << "pg_stats_ack(" << pg_stat.size() << " pgs tid " << get_tid() << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(pg_stat, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(pg_stat, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MPing.h b/src/messages/MPing.h new file mode 100644 index 000000000..bff4326ee --- /dev/null +++ b/src/messages/MPing.h @@ -0,0 +1,33 @@ +// -*- 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_MPING_H +#define CEPH_MPING_H + +#include "msg/Message.h" + +class MPing final : public Message { +public: + MPing() : Message{CEPH_MSG_PING} {} +private: + ~MPing() final {} + +public: + void decode_payload() override { } + void encode_payload(uint64_t features) override { } + std::string_view get_type_name() const override { return "ping"; } +}; + +#endif diff --git a/src/messages/MPoolOp.h b/src/messages/MPoolOp.h new file mode 100644 index 000000000..0e53c56b9 --- /dev/null +++ b/src/messages/MPoolOp.h @@ -0,0 +1,98 @@ +// -*- 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_MPOOLOP_H +#define CEPH_MPOOLOP_H + +#include "messages/PaxosServiceMessage.h" + + +class MPoolOp final : public PaxosServiceMessage { +private: + static constexpr int HEAD_VERSION = 4; + static constexpr int COMPAT_VERSION = 2; + +public: + uuid_d fsid; + __u32 pool = 0; + std::string name; + __u32 op = 0; + snapid_t snapid; + __s16 crush_rule = 0; + + MPoolOp() + : PaxosServiceMessage{CEPH_MSG_POOLOP, 0, HEAD_VERSION, COMPAT_VERSION} {} + MPoolOp(const uuid_d& f, ceph_tid_t t, int p, std::string& n, int o, version_t v) + : PaxosServiceMessage{CEPH_MSG_POOLOP, v, HEAD_VERSION, COMPAT_VERSION}, + fsid(f), pool(p), name(n), op(o), + snapid(0), crush_rule(0) { + set_tid(t); + } + +private: + ~MPoolOp() final {} + +public: + std::string_view get_type_name() const override { return "poolop"; } + void print(std::ostream& out) const override { + out << "pool_op(" << ceph_pool_op_name(op) << " pool " << pool + << " tid " << get_tid() + << " name " << name + << " v" << version << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + paxos_encode(); + encode(fsid, payload); + encode(pool, payload); + encode(op, payload); + encode((uint64_t)0, payload); + encode(snapid, payload); + encode(name, payload); + __u8 pad = 0; + encode(pad, payload); /* for v3->v4 encoding change */ + encode(crush_rule, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + paxos_decode(p); + decode(fsid, p); + decode(pool, p); + if (header.version < 2) + decode(name, p); + decode(op, p); + uint64_t old_auid; + decode(old_auid, p); + decode(snapid, p); + if (header.version >= 2) + decode(name, p); + + if (header.version >= 3) { + __u8 pad; + decode(pad, p); + if (header.version >= 4) + decode(crush_rule, p); + else + crush_rule = pad; + } else + crush_rule = -1; + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MPoolOpReply.h b/src/messages/MPoolOpReply.h new file mode 100644 index 000000000..59ec764af --- /dev/null +++ b/src/messages/MPoolOpReply.h @@ -0,0 +1,85 @@ +// -*- 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_MPOOLOPREPLY_H +#define CEPH_MPOOLOPREPLY_H + +#include "common/errno.h" + +class MPoolOpReply : public PaxosServiceMessage { +public: + uuid_d fsid; + __u32 replyCode = 0; + epoch_t epoch = 0; + ceph::buffer::list response_data; + + MPoolOpReply() : PaxosServiceMessage{CEPH_MSG_POOLOP_REPLY, 0} + {} + MPoolOpReply( uuid_d& f, ceph_tid_t t, int rc, int e, version_t v) : + PaxosServiceMessage{CEPH_MSG_POOLOP_REPLY, v}, + fsid(f), + replyCode(rc), + epoch(e) { + set_tid(t); + } + MPoolOpReply(uuid_d& f, ceph_tid_t t, int rc, int e, version_t v, + ceph::buffer::list *blp) : + PaxosServiceMessage{CEPH_MSG_POOLOP_REPLY, v}, + fsid(f), + replyCode(rc), + epoch(e) { + set_tid(t); + if (blp) + response_data = std::move(*blp); + } + + std::string_view get_type_name() const override { return "poolopreply"; } + + void print(std::ostream& out) const override { + out << "pool_op_reply(tid " << get_tid() + << " " << cpp_strerror(-replyCode) + << " v" << version << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + paxos_encode(); + encode(fsid, payload); + encode(replyCode, payload); + encode(epoch, payload); + if (response_data.length()) { + encode(true, payload); + encode(response_data, payload); + } else + encode(false, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + paxos_decode(p); + decode(fsid, p); + decode(replyCode, p); + decode(epoch, p); + bool has_response_data; + decode(has_response_data, p); + if (has_response_data) { + decode(response_data, p); + } + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MRecoveryReserve.h b/src/messages/MRecoveryReserve.h new file mode 100644 index 000000000..55fb2d81b --- /dev/null +++ b/src/messages/MRecoveryReserve.h @@ -0,0 +1,133 @@ +// -*- 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_MRECOVERY_H +#define CEPH_MRECOVERY_H + +#include "msg/Message.h" +#include "messages/MOSDPeeringOp.h" +#include "osd/PGPeeringEvent.h" + +class MRecoveryReserve : public MOSDPeeringOp { +private: + static constexpr int HEAD_VERSION = 3; + static constexpr int COMPAT_VERSION = 2; +public: + spg_t pgid; + epoch_t query_epoch; + enum { + REQUEST = 0, // primary->replica: please reserve slot + GRANT = 1, // replica->primary: ok, i reserved it + RELEASE = 2, // primary->replica: release the slot i reserved before + REVOKE = 3, // replica->primary: i'm taking back the slot i gave you + }; + uint32_t type; + uint32_t priority = 0; + + spg_t get_spg() const { + return pgid; + } + epoch_t get_map_epoch() const { + return query_epoch; + } + epoch_t get_min_epoch() const { + return query_epoch; + } + + PGPeeringEvent *get_event() override { + switch (type) { + case REQUEST: + return new PGPeeringEvent( + query_epoch, + query_epoch, + RequestRecoveryPrio(priority)); + case GRANT: + return new PGPeeringEvent( + query_epoch, + query_epoch, + RemoteRecoveryReserved()); + case RELEASE: + return new PGPeeringEvent( + query_epoch, + query_epoch, + RecoveryDone()); + case REVOKE: + return new PGPeeringEvent( + query_epoch, + query_epoch, + DeferRecovery(0.0)); + default: + ceph_abort(); + } + } + + MRecoveryReserve() + : MOSDPeeringOp{MSG_OSD_RECOVERY_RESERVE, HEAD_VERSION, COMPAT_VERSION}, + query_epoch(0), type(-1) {} + MRecoveryReserve(int type, + spg_t pgid, + epoch_t query_epoch, + unsigned prio = 0) + : MOSDPeeringOp{MSG_OSD_RECOVERY_RESERVE, HEAD_VERSION, COMPAT_VERSION}, + pgid(pgid), query_epoch(query_epoch), + type(type), priority(prio) {} + + std::string_view get_type_name() const override { + return "MRecoveryReserve"; + } + + void inner_print(std::ostream& out) const override { + switch (type) { + case REQUEST: + out << "REQUEST"; + break; + case GRANT: + out << "GRANT"; + break; + case RELEASE: + out << "RELEASE"; + break; + case REVOKE: + out << "REVOKE"; + break; + } + if (type == REQUEST) out << " prio: " << priority; + } + + void decode_payload() override { + auto p = payload.cbegin(); + using ceph::decode; + decode(pgid.pgid, p); + decode(query_epoch, p); + decode(type, p); + decode(pgid.shard, p); + if (header.version >= 3) { + decode(priority, p); + } + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(pgid.pgid, payload); + encode(query_epoch, payload); + encode(type, payload); + encode(pgid.shard, payload); + encode(priority, payload); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MRemoveSnaps.h b/src/messages/MRemoveSnaps.h new file mode 100644 index 000000000..c0217f832 --- /dev/null +++ b/src/messages/MRemoveSnaps.h @@ -0,0 +1,56 @@ +// -*- 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_MREMOVESNAPS_H +#define CEPH_MREMOVESNAPS_H + +#include "messages/PaxosServiceMessage.h" + +class MRemoveSnaps final : public PaxosServiceMessage { +public: + std::map<int32_t, std::vector<snapid_t>> snaps; + +protected: + MRemoveSnaps() : + PaxosServiceMessage{MSG_REMOVE_SNAPS, 0} { } + MRemoveSnaps(std::map<int, std::vector<snapid_t>>& s) : + PaxosServiceMessage{MSG_REMOVE_SNAPS, 0} { + snaps.swap(s); + } + ~MRemoveSnaps() final {} + +public: + std::string_view get_type_name() const override { return "remove_snaps"; } + void print(std::ostream& out) const override { + out << "remove_snaps(" << snaps << " v" << version << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + paxos_encode(); + encode(snaps, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + paxos_decode(p); + decode(snaps, p); + ceph_assert(p.end()); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MRoute.h b/src/messages/MRoute.h new file mode 100644 index 000000000..4154434af --- /dev/null +++ b/src/messages/MRoute.h @@ -0,0 +1,90 @@ +// -*- 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_MROUTE_H +#define CEPH_MROUTE_H + +#include "msg/Message.h" +#include "include/encoding.h" + +class MRoute final : public Message { +public: + static constexpr int HEAD_VERSION = 3; + static constexpr int COMPAT_VERSION = 3; + + uint64_t session_mon_tid; + Message *msg; + epoch_t send_osdmap_first; + + MRoute() : Message{MSG_ROUTE, HEAD_VERSION, COMPAT_VERSION}, + session_mon_tid(0), + msg(NULL), + send_osdmap_first(0) {} + MRoute(uint64_t t, Message *m) + : Message{MSG_ROUTE, HEAD_VERSION, COMPAT_VERSION}, + session_mon_tid(t), + msg(m), + send_osdmap_first(0) {} +private: + ~MRoute() final { + if (msg) + msg->put(); + } + +public: + void decode_payload() override { + auto p = payload.cbegin(); + using ceph::decode; + decode(session_mon_tid, p); + entity_inst_t dest_unused; + decode(dest_unused, p); + bool m; + decode(m, p); + if (m) + msg = decode_message(NULL, 0, p); + decode(send_osdmap_first, p); + } + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(session_mon_tid, payload); + entity_inst_t dest_unused; + encode(dest_unused, payload, features); + bool m = msg ? true : false; + encode(m, payload); + if (msg) + encode_message(msg, features, payload); + encode(send_osdmap_first, payload); + } + + std::string_view get_type_name() const override { return "route"; } + void print(std::ostream& o) const override { + if (msg) + o << "route(" << *msg; + else + o << "route(no-reply"; + if (send_osdmap_first) + o << " send_osdmap_first " << send_osdmap_first; + if (session_mon_tid) + o << " tid " << session_mon_tid << ")"; + else + o << " tid (none)"; + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MServiceMap.h b/src/messages/MServiceMap.h new file mode 100644 index 000000000..05954354a --- /dev/null +++ b/src/messages/MServiceMap.h @@ -0,0 +1,39 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#pragma once + +#include "msg/Message.h" +#include "mgr/ServiceMap.h" + +class MServiceMap final : public Message { +public: + ServiceMap service_map; + + MServiceMap() : Message{MSG_SERVICE_MAP} { } + explicit MServiceMap(const ServiceMap& sm) + : Message{MSG_SERVICE_MAP}, + service_map(sm) { + } +private: + ~MServiceMap() final {} + +public: + std::string_view get_type_name() const override { return "service_map"; } + void print(std::ostream& out) const override { + out << "service_map(e" << service_map.epoch << " " + << service_map.services.size() << " svc)"; + } + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(service_map, payload, features); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(service_map, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; diff --git a/src/messages/MStatfs.h b/src/messages/MStatfs.h new file mode 100644 index 000000000..41b236a9e --- /dev/null +++ b/src/messages/MStatfs.h @@ -0,0 +1,71 @@ +// -*- 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_MSTATFS_H +#define CEPH_MSTATFS_H + +#include <sys/statvfs.h> /* or <sys/statfs.h> */ +#include "messages/PaxosServiceMessage.h" + +class MStatfs final : public PaxosServiceMessage { +private: + static constexpr int HEAD_VERSION = 2; + static constexpr int COMPAT_VERSION = 1; + +public: + uuid_d fsid; + boost::optional<int64_t> data_pool; + + MStatfs() : PaxosServiceMessage{CEPH_MSG_STATFS, 0, HEAD_VERSION, COMPAT_VERSION} {} + MStatfs(const uuid_d& f, ceph_tid_t t, boost::optional<int64_t> _data_pool, + version_t v) + : PaxosServiceMessage{CEPH_MSG_STATFS, v, HEAD_VERSION, COMPAT_VERSION}, + fsid(f), data_pool(_data_pool) { + set_tid(t); + } + +private: + ~MStatfs() final {} + +public: + std::string_view get_type_name() const override { return "statfs"; } + void print(std::ostream& out) const override { + out << "statfs(" << get_tid() << " pool " + << (data_pool ? *data_pool : -1) << " v" << version << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + paxos_encode(); + encode(fsid, payload); + encode(data_pool, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + paxos_decode(p); + decode(fsid, p); + if (header.version >= 2) { + decode(data_pool, p); + } else { + data_pool = boost::optional<int64_t> (); + } + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MStatfsReply.h b/src/messages/MStatfsReply.h new file mode 100644 index 000000000..3bdcfe0a7 --- /dev/null +++ b/src/messages/MStatfsReply.h @@ -0,0 +1,49 @@ +// -*- 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_MSTATFSREPLY_H +#define CEPH_MSTATFSREPLY_H + +class MStatfsReply : public Message { +public: + struct ceph_mon_statfs_reply h{}; + + MStatfsReply() : Message{CEPH_MSG_STATFS_REPLY} {} + MStatfsReply(uuid_d &f, ceph_tid_t t, epoch_t epoch) + : Message{CEPH_MSG_STATFS_REPLY} { + memcpy(&h.fsid, f.bytes(), sizeof(h.fsid)); + header.tid = t; + h.version = epoch; + } + + std::string_view get_type_name() const override { return "statfs_reply"; } + void print(std::ostream& out) const override { + out << "statfs_reply(" << header.tid << ")"; + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(h, payload); + } + void decode_payload() override { + auto p = payload.cbegin(); + decode(h, p); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/MTimeCheck.h b/src/messages/MTimeCheck.h new file mode 100644 index 000000000..03cd157f2 --- /dev/null +++ b/src/messages/MTimeCheck.h @@ -0,0 +1,92 @@ +// -*- 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) 2012 Inktank, Inc. + * + * 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_MTIMECHECK_H +#define CEPH_MTIMECHECK_H + +class MTimeCheck final : public Message { +public: + static constexpr int HEAD_VERSION = 1; + + enum { + OP_PING = 1, + OP_PONG = 2, + OP_REPORT = 3, + }; + + int op = 0; + version_t epoch = 0; + version_t round = 0; + + utime_t timestamp; + map<entity_inst_t, double> skews; + map<entity_inst_t, double> latencies; + + MTimeCheck() : Message{MSG_TIMECHECK, HEAD_VERSION} {} + MTimeCheck(int op) : + Message{MSG_TIMECHECK, HEAD_VERSION}, + op(op) + {} + +private: + ~MTimeCheck() final {} + +public: + std::string_view get_type_name() const override { return "time_check"; } + const char *get_op_name() const { + switch (op) { + case OP_PING: return "ping"; + case OP_PONG: return "pong"; + case OP_REPORT: return "report"; + } + return "???"; + } + void print(std::ostream &o) const override { + o << "time_check( " << get_op_name() + << " e " << epoch << " r " << round; + if (op == OP_PONG) { + o << " ts " << timestamp; + } else if (op == OP_REPORT) { + o << " #skews " << skews.size() + << " #latencies " << latencies.size(); + } + o << " )"; + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(op, p); + decode(epoch, p); + decode(round, p); + decode(timestamp, p); + decode(skews, p); + decode(latencies, p); + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(op, payload); + encode(epoch, payload); + encode(round, payload); + encode(timestamp, payload); + encode(skews, payload, features); + encode(latencies, payload, features); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif /* CEPH_MTIMECHECK_H */ diff --git a/src/messages/MTimeCheck2.h b/src/messages/MTimeCheck2.h new file mode 100644 index 000000000..8d9c4215f --- /dev/null +++ b/src/messages/MTimeCheck2.h @@ -0,0 +1,90 @@ +// -*- 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) 2012 Inktank, Inc. + * + * 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. + * + */ + +#pragma once + +class MTimeCheck2 final : public Message { +public: + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; + + enum { + OP_PING = 1, + OP_PONG = 2, + OP_REPORT = 3, + }; + + int op = 0; + version_t epoch = 0; + version_t round = 0; + + utime_t timestamp; + std::map<int, double> skews; + std::map<int, double> latencies; + + MTimeCheck2() : Message{MSG_TIMECHECK2, HEAD_VERSION, COMPAT_VERSION} { } + MTimeCheck2(int op) : + Message{MSG_TIMECHECK2, HEAD_VERSION, COMPAT_VERSION}, + op(op) + { } + +private: + ~MTimeCheck2() final { } + +public: + std::string_view get_type_name() const override { return "time_check2"; } + const char *get_op_name() const { + switch (op) { + case OP_PING: return "ping"; + case OP_PONG: return "pong"; + case OP_REPORT: return "report"; + } + return "???"; + } + void print(std::ostream &o) const override { + o << "time_check( " << get_op_name() + << " e " << epoch << " r " << round; + if (op == OP_PONG) { + o << " ts " << timestamp; + } else if (op == OP_REPORT) { + o << " #skews " << skews.size() + << " #latencies " << latencies.size(); + } + o << " )"; + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(op, p); + decode(epoch, p); + decode(round, p); + decode(timestamp, p); + decode(skews, p); + decode(latencies, p); + } + + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(op, payload); + encode(epoch, payload); + encode(round, payload); + encode(timestamp, payload); + encode(skews, payload, features); + encode(latencies, payload, features); + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; diff --git a/src/messages/MWatchNotify.h b/src/messages/MWatchNotify.h new file mode 100644 index 000000000..971c860c7 --- /dev/null +++ b/src/messages/MWatchNotify.h @@ -0,0 +1,98 @@ +// -*- 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_MWATCHNOTIFY_H +#define CEPH_MWATCHNOTIFY_H + +#include "msg/Message.h" + + +class MWatchNotify final : public Message { +private: + static constexpr int HEAD_VERSION = 3; + static constexpr int COMPAT_VERSION = 1; + + public: + uint64_t cookie; ///< client unique id for this watch or notify + uint64_t ver; ///< unused + uint64_t notify_id; ///< osd unique id for a notify notification + uint8_t opcode; ///< CEPH_WATCH_EVENT_* + ceph::buffer::list bl; ///< notify payload (osd->client) + errorcode32_t return_code; ///< notify result (osd->client) + uint64_t notifier_gid; ///< who sent the notify + + MWatchNotify() + : Message{CEPH_MSG_WATCH_NOTIFY, HEAD_VERSION, COMPAT_VERSION} { } + MWatchNotify(uint64_t c, uint64_t v, uint64_t i, uint8_t o, ceph::buffer::list b, uint64_t n=0) + : Message{CEPH_MSG_WATCH_NOTIFY, HEAD_VERSION, COMPAT_VERSION}, + cookie(c), + ver(v), + notify_id(i), + opcode(o), + bl(b), + return_code(0), + notifier_gid(n) { } +private: + ~MWatchNotify() final {} + +public: + void decode_payload() override { + using ceph::decode; + uint8_t msg_ver; + auto p = payload.cbegin(); + decode(msg_ver, p); + decode(opcode, p); + decode(cookie, p); + decode(ver, p); + decode(notify_id, p); + if (msg_ver >= 1) + decode(bl, p); + if (header.version >= 2) + decode(return_code, p); + else + return_code = 0; + if (header.version >= 3) + decode(notifier_gid, p); + else + notifier_gid = 0; + } + void encode_payload(uint64_t features) override { + using ceph::encode; + uint8_t msg_ver = 1; + encode(msg_ver, payload); + encode(opcode, payload); + encode(cookie, payload); + encode(ver, payload); + encode(notify_id, payload); + encode(bl, payload); + encode(return_code, payload); + encode(notifier_gid, payload); + } + + std::string_view get_type_name() const override { return "watch-notify"; } + void print(std::ostream& out) const override { + out << "watch-notify(" + << ceph_watch_event_name(opcode) << " (" << (int)opcode << ")" + << " cookie " << cookie + << " notify " << notify_id + << " ret " << return_code + << ")"; + } +private: + template<class T, typename... Args> + friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args); +}; + +#endif diff --git a/src/messages/PaxosServiceMessage.h b/src/messages/PaxosServiceMessage.h new file mode 100644 index 000000000..a2b1ddf4e --- /dev/null +++ b/src/messages/PaxosServiceMessage.h @@ -0,0 +1,59 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- + +#ifndef CEPH_PAXOSSERVICEMESSAGE_H +#define CEPH_PAXOSSERVICEMESSAGE_H + +#include "msg/Message.h" +#include "mon/Session.h" + +class PaxosServiceMessage : public Message { +public: + version_t version; + __s16 deprecated_session_mon; + uint64_t deprecated_session_mon_tid; + + // track which epoch the leader received a forwarded request in, so we can + // discard forwarded requests appropriately on election boundaries. + epoch_t rx_election_epoch; + + PaxosServiceMessage() + : Message{MSG_PAXOS}, + version(0), deprecated_session_mon(-1), deprecated_session_mon_tid(0), + rx_election_epoch(0) { } + PaxosServiceMessage(int type, version_t v, int enc_version=1, int compat_enc_version=0) + : Message{type, enc_version, compat_enc_version}, + version(v), deprecated_session_mon(-1), deprecated_session_mon_tid(0), + rx_election_epoch(0) { } + protected: + ~PaxosServiceMessage() override {} + + public: + void paxos_encode() { + using ceph::encode; + encode(version, payload); + encode(deprecated_session_mon, payload); + encode(deprecated_session_mon_tid, payload); + } + + void paxos_decode(ceph::buffer::list::const_iterator& p ) { + using ceph::decode; + decode(version, p); + decode(deprecated_session_mon, p); + decode(deprecated_session_mon_tid, p); + } + + void encode_payload(uint64_t features) override { + ceph_abort(); + paxos_encode(); + } + + void decode_payload() override { + ceph_abort(); + auto p = payload.cbegin(); + paxos_decode(p); + } + + std::string_view get_type_name() const override { return "PaxosServiceMessage"; } +}; + +#endif |