Skip to content

Commit c376635

Browse files
salieri11vshankar
authored andcommitted
client,mds: add support for subvolume level metrics
Add support for client side metrics collection using SimpleIOMetric struct and aggregation using AggregatedIOMetrics struct, Client holds SimpleIOMetrics vector per each subvolume it recognized (via caps/metadata messages), aggregates them into the AggregatedIOMetric struct, and sends periodically to the MDS, along with regulat client metrics. MDS holds map of subvolume_path -> vector<AggregatedIOMetrics> and sends it periodically to rank0, for further aggregation and exposure. Fixes: https://tracker.ceph.com/issues/68929, https://tracker.ceph.com/issues/68930 Signed-off-by: Igor Golikov <[email protected]>
1 parent 23e12c7 commit c376635

File tree

17 files changed

+726
-49
lines changed

17 files changed

+726
-49
lines changed

src/client/Client.cc

Lines changed: 175 additions & 18 deletions
Large diffs are not rendered by default.

src/client/Client.h

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
#include <thread>
5656
#include <unordered_map>
5757
#include <unordered_set>
58+
#include <shared_mutex>
5859

5960
using std::set;
6061
using std::map;
@@ -260,6 +261,40 @@ struct dir_result_t {
260261
int fd; // fd attached using fdopendir (-1 if none)
261262
};
262263

264+
/**
265+
* @brief The subvolume metric tracker.
266+
*
267+
* Maps subvolume_id(which is in fact inode id) to the vector of SimpleIOMetric instances.
268+
* Each simple metric records the single IO operation on the client.
269+
* On clients metric message to the MDS, client will aggregate all simple metrics for each subvolume
270+
* into the AggregatedIOMetric struct and clear the current metrics list.
271+
* TODO: limit the cap for each subvolume? in the case client sends metrics to the MDS not so often?
272+
*/
273+
class SubvolumeMetricTracker {
274+
public:
275+
struct SubvolumeEntry {
276+
AggregatedIOMetrics metrics;
277+
278+
void dump(Formatter *f) const {
279+
f->dump_object("", metrics);
280+
}
281+
};
282+
283+
SubvolumeMetricTracker(CephContext *ct, client_t id);
284+
void dump(Formatter *f);
285+
void add_inode(inodeno_t inode, inodeno_t subvol);
286+
void remove_inode(inodeno_t inode);
287+
void add_metric(inodeno_t inode, SimpleIOMetric&& metric);
288+
std::vector<AggregatedIOMetrics> aggregate(bool clean);
289+
protected:
290+
std::vector<AggregatedIOMetrics> last_subvolume_metrics;
291+
std::unordered_map<inodeno_t, SubvolumeEntry> subvolume_metrics;
292+
std::unordered_map<inodeno_t, inodeno_t> inode_subvolume;
293+
CephContext *cct = nullptr;
294+
client_t whoami;
295+
std::shared_mutex metrics_lock;
296+
};
297+
263298
class Client : public Dispatcher, public md_config_obs_t {
264299
public:
265300
friend class C_Block_Sync; // Calls block map and protected helpers
@@ -1180,6 +1215,7 @@ class Client : public Dispatcher, public md_config_obs_t {
11801215
void force_session_readonly(MetaSession *s);
11811216

11821217
void dump_status(Formatter *f); // debug
1218+
void dump_subvolume_metrics(Formatter* f);
11831219

11841220
Dispatcher::dispatch_result_t ms_dispatch2(const MessageRef& m) override;
11851221

@@ -1362,11 +1398,11 @@ class Client : public Dispatcher, public md_config_obs_t {
13621398

13631399
C_Read_Finisher(Client *clnt, Context *onfinish, Context *iofinish,
13641400
bool is_read_async, int have_caps, bool movepos,
1365-
utime_t start, Fh *f, Inode *in, uint64_t fpos,
1401+
Fh *f, Inode *in, uint64_t fpos,
13661402
int64_t offset, uint64_t size)
13671403
: clnt(clnt), onfinish(onfinish), iofinish(iofinish),
13681404
is_read_async(is_read_async), have_caps(have_caps), f(f), in(in),
1369-
start(start), fpos(fpos), offset(offset), size(size), movepos(movepos) {
1405+
start(mono_clock_now()), fpos(fpos), offset(offset), size(size), movepos(movepos) {
13701406
iofinished = false;
13711407
}
13721408

@@ -1415,7 +1451,7 @@ class Client : public Dispatcher, public md_config_obs_t {
14151451
uint64_t fpos, uint64_t off, uint64_t len,
14161452
bufferlist *bl, Filer *filer, int have_caps)
14171453
: clnt(clnt), onfinish(onfinish), f(f), in(in), off(off), len(len), bl(bl),
1418-
filer(filer), have_caps(have_caps)
1454+
filer(filer), have_caps(have_caps), start_time(mono_clock_now())
14191455
{
14201456
left = len;
14211457
wanted = len;
@@ -1439,6 +1475,7 @@ class Client : public Dispatcher, public md_config_obs_t {
14391475
bufferlist tbl;
14401476
Filer *filer;
14411477
int have_caps;
1478+
utime_t start_time;
14421479
int read;
14431480
uint64_t pos;
14441481
bool fini;
@@ -1457,7 +1494,7 @@ class Client : public Dispatcher, public md_config_obs_t {
14571494
public:
14581495
C_Read_Async_Finisher(Client *clnt, Context *onfinish, Fh *f, Inode *in,
14591496
uint64_t fpos, uint64_t off, uint64_t len)
1460-
: clnt(clnt), onfinish(onfinish), f(f), in(in), off(off), len(len) {}
1497+
: clnt(clnt), onfinish(onfinish), f(f), in(in), off(off), len(len), start_time(mono_clock_now()) {}
14611498

14621499
private:
14631500
Client *clnt;
@@ -1466,6 +1503,7 @@ class Client : public Dispatcher, public md_config_obs_t {
14661503
Inode *in;
14671504
uint64_t off;
14681505
uint64_t len;
1506+
utime_t start_time;
14691507

14701508
void finish(int r) override;
14711509
};
@@ -1492,11 +1530,11 @@ class Client : public Dispatcher, public md_config_obs_t {
14921530
void finish_fsync(int r);
14931531

14941532
C_Write_Finisher(Client *clnt, Context *onfinish, bool dont_need_uninline,
1495-
bool is_file_write, utime_t start, Fh *f, Inode *in,
1533+
bool is_file_write, Fh *f, Inode *in,
14961534
uint64_t fpos, int64_t offset, uint64_t size,
14971535
bool do_fsync, bool syncdataonly)
14981536
: clnt(clnt), onfinish(onfinish),
1499-
is_file_write(is_file_write), start(start), f(f), in(in), fpos(fpos),
1537+
is_file_write(is_file_write), start(mono_clock_now()), f(f), in(in), fpos(fpos),
15001538
offset(offset), size(size), syncdataonly(syncdataonly) {
15011539
iofinished_r = 0;
15021540
onuninlinefinished_r = 0;
@@ -1576,7 +1614,7 @@ class Client : public Dispatcher, public md_config_obs_t {
15761614
C_nonblocking_fsync_state(Client *clnt, Inode *in, bool syncdataonly, Context *onfinish)
15771615
: clnt(clnt), in(in), syncdataonly(syncdataonly), onfinish(onfinish) {
15781616
flush_tid = 0;
1579-
start = ceph_clock_now();
1617+
start = mono_clock_now();
15801618
progress = 0;
15811619
flush_wait = false;
15821620
flush_completed = false;
@@ -1621,6 +1659,7 @@ class Client : public Dispatcher, public md_config_obs_t {
16211659

16221660
Client *client;
16231661
Fh *f;
1662+
utime_t start_time = 0;
16241663
};
16251664

16261665
/*
@@ -1932,6 +1971,9 @@ class Client : public Dispatcher, public md_config_obs_t {
19321971
// Cluster fsid
19331972
fs_cluster_id_t fscid;
19341973

1974+
// subvolume metrics tracker
1975+
std::unique_ptr<SubvolumeMetricTracker> subvolume_tracker = nullptr;
1976+
19351977
// file handles, etc.
19361978
interval_set<int> free_fd_set; // unused fds
19371979
std::unordered_map<int, Fh*> fd_map;

src/common/Clock.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,18 @@ static inline utime_t ceph_clock_now()
3333
return n;
3434
}
3535

36+
static inline utime_t mono_clock_now()
37+
{
38+
#if defined(__linux__)
39+
struct timespec tp;
40+
clock_gettime(CLOCK_MONOTONIC, &tp);
41+
utime_t n(tp);
42+
#else
43+
struct timeval tv;
44+
gettimeofday(&tv, nullptr);
45+
utime_t n(&tv);
46+
#endif
47+
return n;
48+
}
49+
3650
#endif

0 commit comments

Comments
 (0)