5555#include < thread>
5656#include < unordered_map>
5757#include < unordered_set>
58+ #include < shared_mutex>
5859
5960using std::set;
6061using 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+
263298class Client : public Dispatcher , public md_config_obs_t {
264299public:
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;
0 commit comments