From: Sage Weil Date: Mon, 23 Sep 2019 22:20:03 +0000 (-0500) Subject: osd/osd_types: add per-op return fields to log [dup] records X-Git-Tag: v15.1.0~1384^2~10 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=7985d9593d5dd86df75edbcc7a70de0db5e803bd;p=ceph-ci.git osd/osd_types: add per-op return fields to log [dup] records Allow an overall positive return value, and also per-op return value and outdata for each op in a request. Signed-off-by: Sage Weil --- diff --git a/src/osd/osd_types.cc b/src/osd/osd_types.cc index f44676254d3..d83991fc20a 100644 --- a/src/osd/osd_types.cc +++ b/src/osd/osd_types.cc @@ -4555,7 +4555,7 @@ void pg_log_entry_t::decode_with_checksum(ceph::buffer::list::const_iterator& p) void pg_log_entry_t::encode(ceph::buffer::list &bl) const { - ENCODE_START(13, 4, bl); + ENCODE_START(14, 4, bl); encode(op, bl); encode(soid, bl); encode(version, bl); @@ -4585,12 +4585,15 @@ void pg_log_entry_t::encode(ceph::buffer::list &bl) const if (!extra_reqids.empty()) encode(extra_reqid_return_codes, bl); encode(clean_regions, bl); + if (op != ERROR) + encode(return_code, bl); + encode(op_returns, bl); ENCODE_FINISH(bl); } void pg_log_entry_t::decode(ceph::buffer::list::const_iterator &bl) { - DECODE_START_LEGACY_COMPAT_LEN(13, 4, 4, bl); + DECODE_START_LEGACY_COMPAT_LEN(14, 4, 4, bl); decode(op, bl); if (struct_v < 2) { sobject_t old_soid; @@ -4650,6 +4653,12 @@ void pg_log_entry_t::decode(ceph::buffer::list::const_iterator &bl) decode(clean_regions, bl); else clean_regions.mark_fully_dirty(); + if (struct_v >= 14) { + if (op != ERROR) { + decode(return_code, bl); + } + decode(op_returns, bl); + } DECODE_FINISH(bl); } @@ -4677,6 +4686,13 @@ void pg_log_entry_t::dump(Formatter *f) const f->close_section(); f->dump_stream("mtime") << mtime; f->dump_int("return_code", return_code); + if (!op_returns.empty()) { + f->open_array_section("op_returns"); + for (auto& i : op_returns) { + f->dump_object("op", i); + } + f->close_section(); + } if (snaps.length() > 0) { vector v; ceph::buffer::list c = snaps; @@ -4722,6 +4738,9 @@ ostream& operator<<(ostream& out, const pg_log_entry_t& e) << std::left << std::setw(8) << e.get_op_name() << ' ' << e.soid << " by " << e.reqid << " " << e.mtime << " " << e.return_code; + if (!e.op_returns.empty()) { + out << " " << e.op_returns; + } if (e.snaps.length()) { vector snaps; ceph::buffer::list c = e.snaps; @@ -4751,21 +4770,25 @@ std::string pg_log_dup_t::get_key_name() const void pg_log_dup_t::encode(ceph::buffer::list &bl) const { - ENCODE_START(1, 1, bl); + ENCODE_START(2, 1, bl); encode(reqid, bl); encode(version, bl); encode(user_version, bl); encode(return_code, bl); + encode(op_returns, bl); ENCODE_FINISH(bl); } void pg_log_dup_t::decode(ceph::buffer::list::const_iterator &bl) { - DECODE_START(1, bl); + DECODE_START(2, bl); decode(reqid, bl); decode(version, bl); decode(user_version, bl); decode(return_code, bl); + if (struct_v >= 2) { + decode(op_returns, bl); + } DECODE_FINISH(bl); } @@ -4775,6 +4798,13 @@ void pg_log_dup_t::dump(Formatter *f) const f->dump_stream("version") << version; f->dump_stream("user_version") << user_version; f->dump_stream("return_code") << return_code; + if (!op_returns.empty()) { + f->open_array_section("op_returns"); + for (auto& i : op_returns) { + f->dump_object("op", i); + } + f->close_section(); + } } void pg_log_dup_t::generate_test_instances(list& o) @@ -4792,9 +4822,13 @@ void pg_log_dup_t::generate_test_instances(list& o) std::ostream& operator<<(std::ostream& out, const pg_log_dup_t& e) { - return out << "log_dup(reqid=" << e.reqid << + out << "log_dup(reqid=" << e.reqid << " v=" << e.version << " uv=" << e.user_version << - " rc=" << e.return_code << ")"; + " rc=" << e.return_code; + if (!e.op_returns.empty()) { + out << " " << e.op_returns; + } + return out << ")"; } diff --git a/src/osd/osd_types.h b/src/osd/osd_types.h index dc37e96d62c..cc4546f441b 100644 --- a/src/osd/osd_types.h +++ b/src/osd/osd_types.h @@ -3823,6 +3823,100 @@ public: WRITE_CLASS_ENCODER(ObjectCleanRegions) ostream& operator<<(ostream& out, const ObjectCleanRegions& ocr); + +struct OSDOp { + ceph_osd_op op; + sobject_t soid; + + ceph::buffer::list indata, outdata; + errorcode32_t rval = 0; + + OSDOp() { + memset(&op, 0, sizeof(ceph_osd_op)); + } + + OSDOp(const int op_code) { + memset(&op, 0, sizeof(ceph_osd_op)); + op.op = op_code; + } + + /** + * split a ceph::buffer::list into constituent indata members of a vector of OSDOps + * + * @param ops [out] vector of OSDOps + * @param in [in] combined data buffer + */ + static void split_osd_op_vector_in_data(std::vector& ops, ceph::buffer::list& in); + + /** + * merge indata members of a vector of OSDOp into a single ceph::buffer::list + * + * Notably this also encodes certain other OSDOp data into the data + * buffer, including the sobject_t soid. + * + * @param ops [in] vector of OSDOps + * @param out [out] combined data buffer + */ + static void merge_osd_op_vector_in_data(std::vector& ops, ceph::buffer::list& out); + + /** + * split a ceph::buffer::list into constituent outdata members of a vector of OSDOps + * + * @param ops [out] vector of OSDOps + * @param in [in] combined data buffer + */ + static void split_osd_op_vector_out_data(std::vector& ops, ceph::buffer::list& in); + + /** + * merge outdata members of a vector of OSDOps into a single ceph::buffer::list + * + * @param ops [in] vector of OSDOps + * @param out [out] combined data buffer + */ + static void merge_osd_op_vector_out_data(std::vector& ops, ceph::buffer::list& out); + + /** + * Clear data as much as possible, leave minimal data for historical op dump + * + * @param ops [in] vector of OSDOps + */ + static void clear_data(std::vector& ops); +}; +std::ostream& operator<<(std::ostream& out, const OSDOp& op); + + +struct pg_log_op_return_item_t { + int32_t rval; + bufferlist bl; + void encode(bufferlist& p) const { + using ceph::encode; + encode(rval, p); + encode(bl, p); + } + void decode(bufferlist::const_iterator& p) { + using ceph::decode; + decode(rval, p); + decode(bl, p); + } + void dump(Formatter *f) const { + f->dump_int("rval", rval); + f->dump_unsigned("bl_length", bl.length()); + } + friend bool operator==(const pg_log_op_return_item_t& lhs, + const pg_log_op_return_item_t& rhs) { + return lhs.rval == rhs.rval && + lhs.bl.contents_equal(rhs.bl); + } + friend bool operator!=(const pg_log_op_return_item_t& lhs, + const pg_log_op_return_item_t& rhs) { + return !(lhs == rhs); + } + friend ostream& operator<<(ostream& out, const pg_log_op_return_item_t& i) { + return out << "r=" << i.rval << "+" << i.bl.length() << "b"; + } +}; +WRITE_CLASS_ENCODER(pg_log_op_return_item_t) + /** * pg_log_entry_t - single entry/event in pg log * @@ -3883,6 +3977,8 @@ struct pg_log_entry_t { utime_t mtime; // this is the _user_ mtime, mind you int32_t return_code; // only stored for ERRORs for dup detection + vector op_returns; + __s32 op; bool invalid_hash; // only when decoding sobject_t based entries bool invalid_pool; // only when decoding pool-less hobject based entries @@ -3947,6 +4043,14 @@ struct pg_log_entry_t { (op == MODIFY || op == DELETE || op == ERROR); } + void set_op_returns(std::vector& ops) { + op_returns.resize(ops.size()); + for (unsigned i = 0; i < ops.size(); ++i) { + op_returns[i].rval = ops[i].rval; + op_returns[i].bl = ops[i].outdata; + } + } + std::string get_key_name() const; void encode_with_checksum(ceph::buffer::list& bl) const; void decode_with_checksum(ceph::buffer::list::const_iterator& p); @@ -3967,12 +4071,16 @@ struct pg_log_dup_t { version_t user_version; // the user version for this entry int32_t return_code; // only stored for ERRORs for dup detection + vector op_returns; + pg_log_dup_t() : user_version(0), return_code(0) {} explicit pg_log_dup_t(const pg_log_entry_t& entry) : reqid(entry.reqid), version(entry.version), - user_version(entry.user_version), return_code(entry.return_code) + user_version(entry.user_version), + return_code(entry.return_code), + op_returns(entry.op_returns) {} pg_log_dup_t(const eversion_t& v, version_t uv, const osd_reqid_t& rid, int return_code) @@ -3990,7 +4098,8 @@ struct pg_log_dup_t { return reqid == rhs.reqid && version == rhs.version && user_version == rhs.user_version && - return_code == rhs.return_code; + return_code == rhs.return_code && + op_returns == rhs.op_returns; } bool operator!=(const pg_log_dup_t &rhs) const { return !(*this == rhs); @@ -5664,67 +5773,6 @@ struct ScrubMapBuilder { } }; -struct OSDOp { - ceph_osd_op op; - sobject_t soid; - - ceph::buffer::list indata, outdata; - errorcode32_t rval = 0; - - OSDOp() { - memset(&op, 0, sizeof(ceph_osd_op)); - } - - OSDOp(const int op_code) { - memset(&op, 0, sizeof(ceph_osd_op)); - op.op = op_code; - } - - /** - * split a ceph::buffer::list into constituent indata members of a vector of OSDOps - * - * @param ops [out] vector of OSDOps - * @param in [in] combined data buffer - */ - static void split_osd_op_vector_in_data(std::vector& ops, ceph::buffer::list& in); - - /** - * merge indata members of a vector of OSDOp into a single ceph::buffer::list - * - * Notably this also encodes certain other OSDOp data into the data - * buffer, including the sobject_t soid. - * - * @param ops [in] vector of OSDOps - * @param out [out] combined data buffer - */ - static void merge_osd_op_vector_in_data(std::vector& ops, ceph::buffer::list& out); - - /** - * split a ceph::buffer::list into constituent outdata members of a vector of OSDOps - * - * @param ops [out] vector of OSDOps - * @param in [in] combined data buffer - */ - static void split_osd_op_vector_out_data(std::vector& ops, ceph::buffer::list& in); - - /** - * merge outdata members of a vector of OSDOps into a single ceph::buffer::list - * - * @param ops [in] vector of OSDOps - * @param out [out] combined data buffer - */ - static void merge_osd_op_vector_out_data(std::vector& ops, ceph::buffer::list& out); - - /** - * Clear data as much as possible, leave minimal data for historical op dump - * - * @param ops [in] vector of OSDOps - */ - static void clear_data(std::vector& ops); -}; - -std::ostream& operator<<(std::ostream& out, const OSDOp& op); - struct watch_item_t { entity_name_t name; uint64_t cookie;