]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
cephfs client: add RW copy metrics
authorIgor Golikov <igolikov@ibm.com>
Tue, 18 Mar 2025 12:53:45 +0000 (12:53 +0000)
committerIgor Golikov <igolikov@ibm.com>
Tue, 18 Mar 2025 13:01:12 +0000 (13:01 +0000)
add metrics for counting copy ops and copy sizes
these metrics are used by zerocopy tests

Signed-off-by: Igor Golikov <igolikov@ibm.com>
Fixes: https://tracker.ceph.com/issues/69919
src/include/buffer.h
src/include/cephfs/metrics/Types.h
src/mds/MDSPerfMetricTypes.h
src/mds/MetricAggregator.cc
src/mds/MetricsHandler.cc
src/mds/MetricsHandler.h
src/mds/cephfs_features.h

index d8f4f306cc38df14a5cfc2e37887170dd0c3cd6b..48f84d1623dc94a153ae43f3de6721fac5e7eac0 100644 (file)
@@ -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<unsigned>(resid, iov[j].iov_len);
          iter.copy(round_size, reinterpret_cast<char*>(iov[j].iov_base));
          resid -= round_size;
+         total_size += round_size;
          /* iter is self-updating */
   }
+  return total_size;
 }
 
 } // namespace buffer
index af377db606e2b54545d6ba8220c28006a92af310..ee9bc4849481886c2492d5588a62753556300b66 100644 (file)
@@ -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<std::underlying_type<ClientMetricType>::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<ClientMetricType>(-1)) { }
@@ -562,6 +603,7 @@ typedef boost::variant<CapInfoPayload,
                        OpenedInodesPayload,
                        ReadIoSizesPayload,
                        WriteIoSizesPayload,
+                       CopyIoSizesPayload,
                        UnknownPayload> 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<ClientMetricType>(metric_type));
       break;
index 78b838c892d92f4166528cf73fe6149b374782c5..eb18b91bc737af9bf74b74a0c8c4ce813935f43f 100644 (file)
@@ -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;
   }
index c916c92d56b7d635fc8c5905371a6fc544a3e587..75554efc66e613032ed7557c27cccde203503c49 100644 (file)
@@ -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,
index 2977a5947bcbcd442cf3b767b7922c890110a05d..dfe2557fb847e35c912928d17cf32d418d32dd25 100644 (file)
@@ -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;
 }
index 0d03fe8b209874dca55728dfa233650fbc0a2bd8..b84d48e583e321b2dcad2532764a109101f4cee4 100644 (file)
@@ -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);
index f05ce672beab540b515b28ea8f4b73535965fca8..877adf2ec674b81faaac9a886105dd044d661c04 100644 (file)
@@ -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