}
dn->link(in);
+ inc_dentry_nr();
ldout(cct, 20) << "link inode " << in << " parents now " << in->dentries << dendl;
}
// unlink from inode
if (dn->inode) {
dn->unlink();
+ dec_dentry_nr();
ldout(cct, 20) << "unlink inode " << in << " parents now " << in->dentries << dendl;
}
metric = ClientMetricMessage(CapInfoPayload(cap_hits, cap_misses, 0));
message.push_back(metric);
+ // dentry lease hit ratio
+ auto [dlease_hits, dlease_misses, nr] = get_dlease_hit_rates();
+ metric = ClientMetricMessage(DentryLeasePayload(dlease_hits, dlease_misses, nr));
+ message.push_back(metric);
+
session->con->send_message2(make_message<MClientMetrics>(std::move(message)));
}
if (dn->lease_mds >= 0 && dn->lease_ttl > now &&
mds_sessions.count(dn->lease_mds)) {
MetaSession &s = mds_sessions.at(dn->lease_mds);
- if (s.cap_ttl > now && s.cap_gen == dn->lease_gen)
+ if (s.cap_ttl > now && s.cap_gen == dn->lease_gen) {
+ dlease_hit();
return true;
+ }
ldout(cct, 20) << " bad lease, cap_ttl " << s.cap_ttl << ", cap_gen " << s.cap_gen
<< " vs lease_gen " << dn->lease_gen << dendl;
}
+ dlease_miss();
return false;
}
void flush_cap_releases();
void tick();
+ void inc_dentry_nr() {
+ ++dentry_nr;
+ }
+ void dec_dentry_nr() {
+ --dentry_nr;
+ }
+ void dlease_hit() {
+ ++dlease_hits;
+ }
+ void dlease_miss() {
+ ++dlease_misses;
+ }
+ std::tuple<uint64_t, uint64_t, uint64_t> get_dlease_hit_rates() {
+ return std::make_tuple(dlease_hits, dlease_misses, dentry_nr);
+ }
+
void cap_hit() {
++cap_hits;
}
epoch_t reclaim_osd_epoch = 0;
entity_addrvec_t reclaim_target_addrs;
+ // dentry lease metrics
+ uint64_t dentry_nr = 0;
+ uint64_t dlease_hits = 0;
+ uint64_t dlease_misses = 0;
+
uint64_t cap_hits = 0;
uint64_t cap_misses = 0;
CLIENT_METRIC_TYPE_READ_LATENCY,
CLIENT_METRIC_TYPE_WRITE_LATENCY,
CLIENT_METRIC_TYPE_METADATA_LATENCY,
+ CLIENT_METRIC_TYPE_DENTRY_LEASE,
};
inline std::ostream &operator<<(std::ostream &os, const ClientMetricType &type) {
switch(type) {
case ClientMetricType::CLIENT_METRIC_TYPE_METADATA_LATENCY:
os << "METADATA_LATENCY";
break;
+ case ClientMetricType::CLIENT_METRIC_TYPE_DENTRY_LEASE:
+ os << "DENTRY_LEASE";
+ break;
default:
ceph_abort();
}
}
};
+struct DentryLeasePayload {
+ static const ClientMetricType METRIC_TYPE = ClientMetricType::CLIENT_METRIC_TYPE_DENTRY_LEASE;
+
+ uint64_t dlease_hits = 0;
+ uint64_t dlease_misses = 0;
+ uint64_t nr_dentries = 0;
+
+ DentryLeasePayload() { }
+ DentryLeasePayload(uint64_t dlease_hits, uint64_t dlease_misses, uint64_t nr_dentries)
+ : dlease_hits(dlease_hits), dlease_misses(dlease_misses), nr_dentries(nr_dentries) {
+ }
+
+ void encode(bufferlist &bl) const {
+ using ceph::encode;
+ ENCODE_START(1, 1, bl);
+ encode(dlease_hits, bl);
+ encode(dlease_misses, bl);
+ encode(nr_dentries, bl);
+ ENCODE_FINISH(bl);
+ }
+
+ void decode(bufferlist::const_iterator &iter) {
+ using ceph::decode;
+ DECODE_START(1, iter);
+ decode(dlease_hits, iter);
+ decode(dlease_misses, iter);
+ decode(nr_dentries, iter);
+ DECODE_FINISH(iter);
+ }
+
+ void dump(Formatter *f) const {
+ f->dump_int("dlease_hits", dlease_hits);
+ f->dump_int("dlease_misses", dlease_misses);
+ f->dump_int("num_dentries", nr_dentries);
+ }
+
+ void print(ostream *out) const {
+ *out << "dlease_hits: " << dlease_hits << " "
+ << "dlease_misses: " << dlease_misses << " "
+ << "num_dentries: " << nr_dentries;
+ }
+};
+
struct UnknownPayload {
static const ClientMetricType METRIC_TYPE = static_cast<ClientMetricType>(-1);
ReadLatencyPayload,
WriteLatencyPayload,
MetadataLatencyPayload,
+ DentryLeasePayload,
UnknownPayload> ClientMetricPayload;
// metric update message sent by clients
case ClientMetricType::CLIENT_METRIC_TYPE_METADATA_LATENCY:
payload = MetadataLatencyPayload();
break;
+ case ClientMetricType::CLIENT_METRIC_TYPE_DENTRY_LEASE:
+ payload = DentryLeasePayload();
+ break;
default:
payload = UnknownPayload();
break;
}
};
+struct DentryLeaseHitMetric {
+ uint64_t hits = 0;
+ uint64_t misses = 0;
+ bool updated = false;
+
+ DENC(DentryLeaseHitMetric, v, p) {
+ DENC_START(1, 1, p);
+ denc(v.hits, p);
+ denc(v.misses, p);
+ denc(v.updated, p);
+ DENC_FINISH(p);
+ }
+
+ void dump(Formatter *f) const {
+ f->dump_unsigned("hits", hits);
+ f->dump_unsigned("misses", misses);
+ }
+
+ friend std::ostream& operator<<(std::ostream& os, const DentryLeaseHitMetric &metric) {
+ os << "{hits=" << metric.hits << ", misses=" << metric.misses << "}";
+ return os;
+ }
+};
+
WRITE_CLASS_DENC(CapHitMetric)
WRITE_CLASS_DENC(ReadLatencyMetric)
WRITE_CLASS_DENC(WriteLatencyMetric)
WRITE_CLASS_DENC(MetadataLatencyMetric)
+WRITE_CLASS_DENC(DentryLeaseHitMetric)
// metrics that are forwarded to the MDS by client(s).
struct Metrics {
ReadLatencyMetric read_latency_metric;
WriteLatencyMetric write_latency_metric;
MetadataLatencyMetric metadata_latency_metric;
+ DentryLeaseHitMetric dentry_lease_metric;
// metric update type
uint32_t update_type = UpdateType::UPDATE_TYPE_REFRESH;
DENC(Metrics, v, p) {
- DENC_START(1, 1, p);
+ DENC_START(2, 1, p);
denc(v.update_type, p);
denc(v.cap_hit_metric, p);
denc(v.read_latency_metric, p);
denc(v.write_latency_metric, p);
denc(v.metadata_latency_metric, p);
+ if (struct_v >= 2) {
+ denc(v.dentry_lease_metric, p);
+ }
DENC_FINISH(p);
}
f->dump_object("read_latency_metric", read_latency_metric);
f->dump_object("write_latency_metric", write_latency_metric);
f->dump_object("metadata_latency_metric", metadata_latency_metric);
+ f->dump_object("dentry_lease_metric", dentry_lease_metric);
}
friend std::ostream& operator<<(std::ostream& os, const Metrics& metrics) {
<< ", read_latency=" << metrics.read_latency_metric
<< ", write_latency=" << metrics.write_latency_metric
<< ", metadata_latency=" << metrics.metadata_latency_metric
+ << ", dentry_lease =" << metrics.dentry_lease_metric
<< "}]";
return os;
}
c->first = metrics.metadata_latency_metric.lat.tv.tv_sec;
c->second = metrics.metadata_latency_metric.lat.tv.tv_nsec;
break;
+ case MDSPerformanceCounterType::DENTRY_LEASE_METRIC:
+ if (metrics.dentry_lease_metric.updated) {
+ c->first = metrics.dentry_lease_metric.hits;
+ c->second = metrics.dentry_lease_metric.misses;
+ }
+ break;
default:
ceph_abort_msg("unknown counter type");
}
metrics.read_latency_metric = { };
metrics.write_latency_metric = { };
metrics.metadata_latency_metric = { };
+ metrics.dentry_lease_metric = { };
metrics.update_type = UPDATE_TYPE_REMOVE;
}
metrics.metadata_latency_metric.lat = payload.lat;
}
+void MetricsHandler::handle_payload(Session *session, const DentryLeasePayload &payload) {
+ dout(20) << ": type=" << static_cast<ClientMetricType>(DentryLeasePayload::METRIC_TYPE)
+ << ", session=" << session << ", hits=" << payload.dlease_hits << ", misses="
+ << payload.dlease_misses << 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.dentry_lease_metric.hits = payload.dlease_hits;
+ metrics.dentry_lease_metric.misses = payload.dlease_misses;
+ metrics.dentry_lease_metric.updated = true;
+}
+
void MetricsHandler::handle_payload(Session *session, const UnknownPayload &payload) {
dout(5) << ": session=" << session << ", ignoring unknown payload" << dendl;
}
void handle_payload(Session *session, const ReadLatencyPayload &payload);
void handle_payload(Session *session, const WriteLatencyPayload &payload);
void handle_payload(Session *session, const MetadataLatencyPayload &payload);
+ void handle_payload(Session *session, const DentryLeasePayload &payload);
void handle_payload(Session *session, const UnknownPayload &payload);
void set_next_seq(version_t seq);
CLIENT_METRIC_TYPE_READ_LATENCY, \
CLIENT_METRIC_TYPE_WRITE_LATENCY, \
CLIENT_METRIC_TYPE_METADATA_LATENCY, \
+ CLIENT_METRIC_TYPE_DENTRY_LEASE, \
}
#define CEPHFS_FEATURES_MDS_SUPPORTED CEPHFS_FEATURES_ALL
{"read_latency", MDSPerformanceCounterType::READ_LATENCY_METRIC},
{"write_latency", MDSPerformanceCounterType::WRITE_LATENCY_METRIC},
{"metadata_latency", MDSPerformanceCounterType::METADATA_LATENCY_METRIC},
+ {"dentry_lease", MDSPerformanceCounterType::DENTRY_LEASE_METRIC},
};
PyObject *py_query = nullptr;
case MDSPerformanceCounterType::READ_LATENCY_METRIC:
case MDSPerformanceCounterType::WRITE_LATENCY_METRIC:
case MDSPerformanceCounterType::METADATA_LATENCY_METRIC:
+ case MDSPerformanceCounterType::DENTRY_LEASE_METRIC:
break;
default:
ceph_abort_msg("unknown counter type");
case MDSPerformanceCounterType::READ_LATENCY_METRIC:
case MDSPerformanceCounterType::WRITE_LATENCY_METRIC:
case MDSPerformanceCounterType::METADATA_LATENCY_METRIC:
+ case MDSPerformanceCounterType::DENTRY_LEASE_METRIC:
break;
default:
ceph_abort_msg("unknown counter type");
case MDSPerformanceCounterType::METADATA_LATENCY_METRIC:
os << "metadata_latency_metric";
break;
+ case MDSPerformanceCounterType::DENTRY_LEASE_METRIC:
+ os << "dentry_lease_metric";
+ break;
}
return os;
READ_LATENCY_METRIC = 1,
WRITE_LATENCY_METRIC = 2,
METADATA_LATENCY_METRIC = 3,
+ DENTRY_LEASE_METRIC = 4,
};
struct MDSPerformanceCounterDescriptor {
case MDSPerformanceCounterType::READ_LATENCY_METRIC:
case MDSPerformanceCounterType::WRITE_LATENCY_METRIC:
case MDSPerformanceCounterType::METADATA_LATENCY_METRIC:
+ case MDSPerformanceCounterType::DENTRY_LEASE_METRIC:
return true;
default:
return false;
MDS_PERF_QUERY_COUNTERS_MAP = OrderedDict({'cap_hit': 0,
'read_latency': 1,
'write_latency': 2,
- 'metadata_latency': 3})
+ 'metadata_latency': 3,
+ 'dentry_lease': 4})
MDS_PERF_QUERY_COUNTERS = [] # type: List[str]
-MDS_GLOBAL_PERF_QUERY_COUNTERS = ['cap_hit', 'read_latency', 'write_latency', 'metadata_latency'] # type: List[str]
+MDS_GLOBAL_PERF_QUERY_COUNTERS = ['cap_hit', 'read_latency', 'write_latency', 'metadata_latency', 'dentry_lease'] # type: List[str]
QUERY_EXPIRE_INTERVAL = timedelta(minutes=1)