}
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
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
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) {
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;
}
};
+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)) { }
OpenedInodesPayload,
ReadIoSizesPayload,
WriteIoSizesPayload,
+ CopyIoSizesPayload,
UnknownPayload> ClientMetricPayload;
// metric update message sent by clients
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;
}
};
+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)
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 {
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);
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);
}
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) {
<< ", 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;
}
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
};
"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]);
}
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,
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;
}
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;
}
struct OpenedInodesPayload;
struct ReadIoSizesPayload;
struct WriteIoSizesPayload;
+struct CopyIoSizesPayload;
struct UnknownPayload;
class MClientMetrics;
class MDSMap;
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);
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