From: Igor Golikov Date: Tue, 18 Mar 2025 12:53:45 +0000 (+0000) Subject: cephfs client: add RW copy metrics X-Git-Tag: testing/wip-vshankar-testing-20250325.080107-debug^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=15a6b030f4cec3ffa7a3b3e4f170c605107fff82;p=ceph-ci.git cephfs client: add RW copy metrics add metrics for counting copy ops and copy sizes these metrics are used by zerocopy tests Signed-off-by: Igor Golikov Fixes: https://tracker.ceph.com/issues/69919 --- diff --git a/src/include/buffer.h b/src/include/buffer.h index d8f4f306cc3..48f84d1623d 100644 --- a/src/include/buffer.h +++ b/src/include/buffer.h @@ -1296,10 +1296,11 @@ inline bufferhash& operator<<(bufferhash& l, const bufferlist &r) { } static inline -void copy_bufferlist_to_iovec(const struct iovec *iov, unsigned iovcnt, +uint64_t copy_bufferlist_to_iovec(const struct iovec *iov, unsigned iovcnt, bufferlist *bl, int64_t r) { auto iter = bl->cbegin(); + uint64_t total_size = 0; for (unsigned j = 0, resid = r; j < iovcnt && resid > 0; j++) { /* * This piece of code aims to handle the case that bufferlist @@ -1308,8 +1309,10 @@ void copy_bufferlist_to_iovec(const struct iovec *iov, unsigned iovcnt, const auto round_size = std::min(resid, iov[j].iov_len); iter.copy(round_size, reinterpret_cast(iov[j].iov_base)); resid -= round_size; + total_size += round_size; /* iter is self-updating */ } + return total_size; } } // namespace buffer diff --git a/src/include/cephfs/metrics/Types.h b/src/include/cephfs/metrics/Types.h index af377db606e..ee9bc484948 100644 --- a/src/include/cephfs/metrics/Types.h +++ b/src/include/cephfs/metrics/Types.h @@ -33,6 +33,7 @@ enum ClientMetricType { CLIENT_METRIC_TYPE_STDEV_WRITE_LATENCY, CLIENT_METRIC_TYPE_AVG_METADATA_LATENCY, CLIENT_METRIC_TYPE_STDEV_METADATA_LATENCY, + CLIENT_METRIC_TYPE_COPY_IO_SIZES, }; inline std::ostream &operator<<(std::ostream &os, const ClientMetricType &type) { switch(type) { @@ -84,6 +85,9 @@ inline std::ostream &operator<<(std::ostream &os, const ClientMetricType &type) case ClientMetricType::CLIENT_METRIC_TYPE_STDEV_METADATA_LATENCY: os << "STDEV_METADATA_LATENCY"; break; + case ClientMetricType::CLIENT_METRIC_TYPE_COPY_IO_SIZES: + os << "COPY_IO_SIZES"; + break; default: os << "(UNKNOWN:" << static_cast::type>(type) << ")"; break; @@ -529,6 +533,43 @@ struct WriteIoSizesPayload : public ClientMetricPayloadBase { } }; +struct CopyIoSizesPayload : public ClientMetricPayloadBase { + uint64_t total_ops = 0; + uint64_t total_size = 0; + + CopyIoSizesPayload() + : ClientMetricPayloadBase(ClientMetricType::CLIENT_METRIC_TYPE_COPY_IO_SIZES) { } + CopyIoSizesPayload(uint64_t total_ops, uint64_t total_size) + : ClientMetricPayloadBase(ClientMetricType::CLIENT_METRIC_TYPE_COPY_IO_SIZES), + total_ops(total_ops), total_size(total_size) { + } + + void encode(bufferlist &bl) const { + using ceph::encode; + ENCODE_START(1, 1, bl); + encode(total_ops, bl); + encode(total_size, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::const_iterator &iter) { + using ceph::decode; + DECODE_START(1, iter); + decode(total_ops, iter); + decode(total_size, iter); + DECODE_FINISH(iter); + } + + void dump(Formatter *f) const { + f->dump_int("total_ops", total_ops); + f->dump_int("total_size", total_size); + } + + void print(std::ostream *out) const { + *out << "total_ops: " << total_ops << " total_size: " << total_size; + } +}; + struct UnknownPayload : public ClientMetricPayloadBase { UnknownPayload() : ClientMetricPayloadBase(static_cast(-1)) { } @@ -562,6 +603,7 @@ typedef boost::variant ClientMetricPayload; // metric update message sent by clients @@ -676,6 +718,9 @@ public: case ClientMetricType::CLIENT_METRIC_TYPE_WRITE_IO_SIZES: payload = WriteIoSizesPayload(); break; + case ClientMetricType::CLIENT_METRIC_TYPE_COPY_IO_SIZES: + payload = CopyIoSizesPayload(); + break; default: payload = UnknownPayload(static_cast(metric_type)); break; diff --git a/src/mds/MDSPerfMetricTypes.h b/src/mds/MDSPerfMetricTypes.h index 78b838c892d..eb18b91bc73 100644 --- a/src/mds/MDSPerfMetricTypes.h +++ b/src/mds/MDSPerfMetricTypes.h @@ -286,6 +286,30 @@ struct WriteIoSizesMetric { } }; +struct CopyIoSizesMetric { + uint64_t total_ops = 0; + uint64_t total_size = 0; + bool updated = false; + + DENC(CopyIoSizesMetric, v, p) { + DENC_START(1, 1, p); + denc(v.total_ops, p); + denc(v.total_size, p); + denc(v.updated, p); + DENC_FINISH(p); + } + + void dump(Formatter *f) const { + f->dump_unsigned("total_ops", total_ops); + f->dump_unsigned("total_size", total_size); + } + + friend std::ostream& operator<<(std::ostream& os, const CopyIoSizesMetric &metric) { + os << "{total_ops=" << metric.total_ops << ", total_size=" << metric.total_size <<"}"; + return os; + } +}; + WRITE_CLASS_DENC(CapHitMetric) WRITE_CLASS_DENC(ReadLatencyMetric) WRITE_CLASS_DENC(WriteLatencyMetric) @@ -296,6 +320,7 @@ WRITE_CLASS_DENC(PinnedIcapsMetric) WRITE_CLASS_DENC(OpenedInodesMetric) WRITE_CLASS_DENC(ReadIoSizesMetric) WRITE_CLASS_DENC(WriteIoSizesMetric) +WRITE_CLASS_DENC(CopyIoSizesMetric) // metrics that are forwarded to the MDS by client(s). struct Metrics { @@ -310,12 +335,13 @@ struct Metrics { OpenedInodesMetric opened_inodes_metric; ReadIoSizesMetric read_io_sizes_metric; WriteIoSizesMetric write_io_sizes_metric; + CopyIoSizesMetric copy_io_sizes_metric; // metric update type uint32_t update_type = UpdateType::UPDATE_TYPE_REFRESH; DENC(Metrics, v, p) { - DENC_START(4, 1, p); + DENC_START(5, 1, p); denc(v.update_type, p); denc(v.cap_hit_metric, p); denc(v.read_latency_metric, p); @@ -333,6 +359,9 @@ struct Metrics { denc(v.read_io_sizes_metric, p); denc(v.write_io_sizes_metric, p); } + if (struct_v >= 5) { + denc(v.copy_io_sizes_metric, p); + } DENC_FINISH(p); } @@ -348,6 +377,7 @@ struct Metrics { f->dump_object("opened_inodes_metric", opened_inodes_metric); f->dump_object("read_io_sizes_metric", read_io_sizes_metric); f->dump_object("write_io_sizes_metric", write_io_sizes_metric); + f->dump_object("copy_io_sizes_metric", copy_io_sizes_metric); } friend std::ostream& operator<<(std::ostream& os, const Metrics& metrics) { @@ -362,6 +392,7 @@ struct Metrics { << ", opened_inodes_metric=" << metrics.opened_inodes_metric << ", read_io_sizes_metric=" << metrics.read_io_sizes_metric << ", write_io_sizes_metric=" << metrics.write_io_sizes_metric + << ", copy_io_sizes_metric=" << metrics.copy_io_sizes_metric << "}]"; return os; } diff --git a/src/mds/MetricAggregator.cc b/src/mds/MetricAggregator.cc index c916c92d56b..75554efc66e 100644 --- a/src/mds/MetricAggregator.cc +++ b/src/mds/MetricAggregator.cc @@ -44,6 +44,8 @@ enum { l_mds_per_client_metrics_total_read_size, l_mds_per_client_metrics_total_write_ops, l_mds_per_client_metrics_total_write_size, + l_mds_per_client_metrics_total_copy_ops, + l_mds_per_client_metrics_total_copy_size, l_mds_per_client_metrics_last }; @@ -195,6 +197,10 @@ void MetricAggregator::refresh_metrics_for_rank(const entity_inst_t &client, "total_write_ops", "Total Write Operations", "wops", PerfCountersBuilder::PRIO_CRITICAL); plb.add_u64(l_mds_per_client_metrics_total_write_size, "total_write_size", "Total Write Size", "wsiz", PerfCountersBuilder::PRIO_CRITICAL); + plb.add_u64(l_mds_per_client_metrics_total_copy_ops, + "total_copy_ops", "Total Copy Ops", "wops", PerfCountersBuilder::PRIO_CRITICAL); + plb.add_u64(l_mds_per_client_metrics_total_copy_size, + "total_copy_size", "Total Copy Size", "csiz", PerfCountersBuilder::PRIO_CRITICAL); client_perf_counters[crpair] = plb.create_perf_counters(); m_cct->get_perfcounters_collection()->add(client_perf_counters[crpair]); } @@ -256,6 +262,12 @@ void MetricAggregator::refresh_metrics_for_rank(const entity_inst_t &client, perf_counter_ptr->set(l_mds_per_client_metrics_total_write_ops, metrics.write_io_sizes_metric.total_ops); perf_counter_ptr->set(l_mds_per_client_metrics_total_write_size, metrics.write_io_sizes_metric.total_size); } + + // copy io metrics + if (metrics.copy_io_sizes_metric.updated) { + perf_counter_ptr->set(l_mds_per_client_metrics_total_copy_ops, metrics.copy_io_sizes_metric.total_ops); + perf_counter_ptr->set(l_mds_per_client_metrics_total_copy_size, metrics.copy_io_sizes_metric.total_size); + } } auto update_counter_func = [&metrics](const MDSPerformanceCounterDescriptor &d, diff --git a/src/mds/MetricsHandler.cc b/src/mds/MetricsHandler.cc index 2977a5947bc..dfe2557fb84 100644 --- a/src/mds/MetricsHandler.cc +++ b/src/mds/MetricsHandler.cc @@ -125,6 +125,7 @@ void MetricsHandler::remove_session(Session *session) { metrics.opened_inodes_metric = { }; metrics.read_io_sizes_metric = { }; metrics.write_io_sizes_metric = { }; + metrics.copy_io_sizes_metric = { }; metrics.update_type = UPDATE_TYPE_REMOVE; } @@ -322,6 +323,24 @@ void MetricsHandler::handle_payload(Session *session, const WriteIoSizesPayload metrics.write_io_sizes_metric.updated = true; } +void MetricsHandler::handle_payload(Session *session, const CopyIoSizesPayload &payload) { + dout(20) << ": type=" << payload.get_type() + << ", session=" << session << ", total_ops=" << payload.total_ops + << ", total_size=" << payload.total_size << dendl; + + auto it = client_metrics_map.find(session->info.inst); + if (it == client_metrics_map.end()) { + return; + } + + auto &metrics = it->second.second; + metrics.update_type = UPDATE_TYPE_REFRESH; + metrics.copy_io_sizes_metric.total_ops = payload.total_ops; + metrics.copy_io_sizes_metric.total_size = payload.total_size; + metrics.copy_io_sizes_metric.updated = true; +} + + void MetricsHandler::handle_payload(Session *session, const UnknownPayload &payload) { dout(5) << ": type=Unknown, session=" << session << ", ignoring unknown payload" << dendl; } diff --git a/src/mds/MetricsHandler.h b/src/mds/MetricsHandler.h index 0d03fe8b209..b84d48e583e 100644 --- a/src/mds/MetricsHandler.h +++ b/src/mds/MetricsHandler.h @@ -26,6 +26,7 @@ struct PinnedIcapsPayload; struct OpenedInodesPayload; struct ReadIoSizesPayload; struct WriteIoSizesPayload; +struct CopyIoSizesPayload; struct UnknownPayload; class MClientMetrics; class MDSMap; @@ -107,6 +108,7 @@ private: void handle_payload(Session *session, const OpenedInodesPayload &payload); void handle_payload(Session *session, const ReadIoSizesPayload &payload); void handle_payload(Session *session, const WriteIoSizesPayload &payload); + void handle_payload(Session *session, const CopyIoSizesPayload &payload); void handle_payload(Session *session, const UnknownPayload &payload); void set_next_seq(version_t seq); diff --git a/src/mds/cephfs_features.h b/src/mds/cephfs_features.h index f05ce672bea..877adf2ec67 100644 --- a/src/mds/cephfs_features.h +++ b/src/mds/cephfs_features.h @@ -95,6 +95,7 @@ namespace ceph { CLIENT_METRIC_TYPE_STDEV_WRITE_LATENCY, \ CLIENT_METRIC_TYPE_AVG_METADATA_LATENCY, \ CLIENT_METRIC_TYPE_STDEV_METADATA_LATENCY, \ + CLIENT_METRIC_TYPE_COPY_IO_SIZES, \ } #define CEPHFS_FEATURES_MDS_SUPPORTED CEPHFS_FEATURES_ALL