@@ -209,6 +209,7 @@ struct lprocfs_stats {
/* 1 + the biggest cpu # whose ls_percpu slot has been allocated */
unsigned short ls_biggest_alloc_num;
enum lprocfs_stats_flags ls_flags;
+ ktime_t ls_init;
/* Lock used when there are no percpu stats areas; For percpu stats,
* it is used to protect ls_biggest_alloc_num change
*/
@@ -444,9 +445,11 @@ void ldebugfs_add_vars(struct dentry *parent, struct ldebugfs_vars *var,
int lprocfs_obd_setup(struct obd_device *obd, bool uuid_only);
int lprocfs_obd_cleanup(struct obd_device *obd);
+void lprocfs_stats_header(struct seq_file *seq, ktime_t now,
+ ktime_t ts_init, int width, const char *colon,
+ bool show_units);
/* Generic callbacks */
-
int ldebugfs_uint(struct seq_file *m, void *data);
int lprocfs_wr_uint(struct file *file, const char __user *buffer,
unsigned long count, void *data);
@@ -114,6 +114,7 @@ struct osc_device {
/* Write stats is actually protected by client_obd's lock. */
struct osc_stats {
+ ktime_t os_init;
u64 os_lockless_writes; /* by bytes */
u64 os_lockless_reads; /* by bytes */
} od_stats;
@@ -270,6 +270,7 @@ struct client_obd {
u32 cl_max_pages_per_rpc;
u32 cl_max_rpcs_in_flight;
u32 cl_max_short_io_bytes;
+ ktime_t cl_stats_init;
struct obd_histogram cl_read_rpc_hist;
struct obd_histogram cl_write_rpc_hist;
struct obd_histogram cl_read_page_hist;
@@ -330,6 +331,7 @@ struct client_obd {
u16 cl_close_rpcs_in_flight;
wait_queue_head_t cl_mod_rpcs_waitq;
unsigned long *cl_mod_tag_bitmap;
+ ktime_t cl_mod_rpcs_init;
struct obd_histogram cl_mod_rpcs_hist;
/* mgc datastruct */
@@ -581,6 +581,7 @@ struct per_process_info {
/* pp_extents[LL_PROCESS_HIST_MAX] will hold the combined process info */
struct ll_rw_extents_info {
+ ktime_t pp_init;
struct per_process_info pp_extents[LL_PROCESS_HIST_MAX + 1];
};
@@ -696,11 +697,13 @@ struct ll_sb_info {
struct lu_site *ll_site;
struct cl_device *ll_cl;
+
/* Statistics */
struct ll_rw_extents_info ll_rw_extents_info;
int ll_extent_process_count;
- struct ll_rw_process_info ll_rw_process_info[LL_PROCESS_HIST_MAX];
unsigned int ll_offset_process_count;
+ ktime_t ll_process_stats_init;
+ struct ll_rw_process_info ll_rw_process_info[LL_PROCESS_HIST_MAX];
struct ll_rw_process_info ll_rw_offset_info[LL_OFFSET_HIST_MAX];
unsigned int ll_rw_offset_entry_count;
int ll_stats_track_id;
@@ -1967,20 +1967,16 @@ static void ll_display_extents_info(struct ll_rw_extents_info *io_extents,
static int ll_rw_extents_stats_pp_seq_show(struct seq_file *seq, void *v)
{
- struct timespec64 now;
struct ll_sb_info *sbi = seq->private;
struct ll_rw_extents_info *io_extents = &sbi->ll_rw_extents_info;
int k;
- ktime_get_real_ts64(&now);
-
if (!sbi->ll_rw_stats_on) {
seq_puts(seq, "disabled\n"
"write anything in this file to activate, then '0' or 'disabled' to deactivate\n");
return 0;
}
- seq_printf(seq, "snapshot_time: %llu.%09lu (secs.usecs)\n",
- (s64)now.tv_sec, (unsigned long)now.tv_nsec);
+ lprocfs_stats_header(seq, ktime_get(), io_extents->pp_init, 25, ":", 1);
seq_printf(seq, "%15s %19s | %20s\n", " ", "read", "write");
seq_printf(seq, "%13s %14s %4s %4s | %14s %4s %4s\n",
"extents", "calls", "%", "cum%",
@@ -2019,6 +2015,7 @@ static ssize_t ll_rw_extents_stats_pp_seq_write(struct file *file,
sbi->ll_rw_stats_on = 1;
spin_lock(&sbi->ll_pp_extent_lock);
+ io_extents->pp_init = ktime_get();
for (i = 0; i < LL_PROCESS_HIST_MAX; i++) {
io_extents->pp_extents[i].pid = 0;
lprocfs_oh_clear(&io_extents->pp_extents[i].pp_r_hist);
@@ -2032,19 +2029,16 @@ static ssize_t ll_rw_extents_stats_pp_seq_write(struct file *file,
static int ll_rw_extents_stats_seq_show(struct seq_file *seq, void *v)
{
- struct timespec64 now;
struct ll_sb_info *sbi = seq->private;
struct ll_rw_extents_info *io_extents = &sbi->ll_rw_extents_info;
- ktime_get_real_ts64(&now);
-
if (!sbi->ll_rw_stats_on) {
seq_puts(seq, "disabled\n"
"write anything in this file to activate, then '0' or 'disabled' to deactivate\n");
return 0;
}
- seq_printf(seq, "snapshot_time: %llu.%09lu (secs.usecs)\n",
- (u64)now.tv_sec, (unsigned long)now.tv_nsec);
+
+ lprocfs_stats_header(seq, ktime_get(), io_extents->pp_init, 25, ":", 1);
seq_printf(seq, "%15s %19s | %20s\n", " ", "read", "write");
seq_printf(seq, "%13s %14s %4s %4s | %14s %4s %4s\n",
@@ -2078,6 +2072,7 @@ static ssize_t ll_rw_extents_stats_seq_write(struct file *file,
sbi->ll_rw_stats_on = 1;
spin_lock(&sbi->ll_pp_extent_lock);
+ io_extents->pp_init = ktime_get();
for (i = 0; i <= LL_PROCESS_HIST_MAX; i++) {
io_extents->pp_extents[i].pid = 0;
lprocfs_oh_clear(&io_extents->pp_extents[i].pp_r_hist);
@@ -2196,23 +2191,20 @@ void ll_rw_stats_tally(struct ll_sb_info *sbi, pid_t pid,
static int ll_rw_offset_stats_seq_show(struct seq_file *seq, void *v)
{
- struct timespec64 now;
struct ll_sb_info *sbi = seq->private;
struct ll_rw_process_info *offset = sbi->ll_rw_offset_info;
struct ll_rw_process_info *process = sbi->ll_rw_process_info;
int i;
- ktime_get_real_ts64(&now);
-
if (!sbi->ll_rw_stats_on) {
seq_puts(seq, "disabled\n"
"write anything in this file to activate, then 0 or \"[D/d]isabled\" to deactivate\n");
return 0;
}
spin_lock(&sbi->ll_process_lock);
+ lprocfs_stats_header(seq, ktime_get(), sbi->ll_process_stats_init, 25,
+ ":", true);
- seq_printf(seq, "snapshot_time: %llu.%09lu (secs.usecs)\n",
- (s64)now.tv_sec, (unsigned long)now.tv_nsec);
seq_printf(seq, "%3s %10s %14s %14s %17s %17s %14s\n",
"R/W", "PID", "RANGE START", "RANGE END",
"SMALLEST EXTENT", "LARGEST EXTENT", "OFFSET");
@@ -2270,6 +2262,7 @@ static ssize_t ll_rw_offset_stats_seq_write(struct file *file,
spin_lock(&sbi->ll_process_lock);
sbi->ll_offset_process_count = 0;
sbi->ll_rw_offset_entry_count = 0;
+ sbi->ll_process_stats_init = ktime_get();
memset(process_info, 0, sizeof(struct ll_rw_process_info) *
LL_PROCESS_HIST_MAX);
memset(offset_info, 0, sizeof(struct ll_rw_process_info) *
@@ -510,14 +510,10 @@ static int mdc_rpc_stats_seq_show(struct seq_file *seq, void *v)
static int mdc_stats_seq_show(struct seq_file *seq, void *v)
{
- struct timespec64 now;
struct obd_device *obd = seq->private;
struct osc_stats *stats = &obd2osc_dev(obd)->od_stats;
- ktime_get_real_ts64(&now);
-
- seq_printf(seq, "snapshot_time: %lld.%09lu (secs.nsecs)\n",
- (s64)now.tv_sec, now.tv_nsec);
+ lprocfs_stats_header(seq, ktime_get(), stats->os_init, 25, ":", true);
seq_printf(seq, "lockless_write_bytes\t\t%llu\n",
stats->os_lockless_writes);
seq_printf(seq, "lockless_read_bytes\t\t%llu\n",
@@ -534,6 +530,8 @@ static ssize_t mdc_stats_seq_write(struct file *file,
struct osc_stats *stats = &obd2osc_dev(obd)->od_stats;
memset(stats, 0, sizeof(*stats));
+ stats->os_init = ktime_get();
+
return len;
}
LDEBUGFS_SEQ_FOPS(mdc_stats);
@@ -1443,15 +1443,11 @@ int obd_set_max_mod_rpcs_in_flight(struct client_obd *cli, u16 max)
int obd_mod_rpc_stats_seq_show(struct client_obd *cli, struct seq_file *seq)
{
unsigned long mod_tot = 0, mod_cum;
- struct timespec64 now;
int i;
- ktime_get_real_ts64(&now);
-
spin_lock(&cli->cl_mod_rpcs_lock);
-
- seq_printf(seq, "snapshot_time: %llu.%9lu (secs.nsecs)\n",
- (s64)now.tv_sec, (unsigned long)now.tv_nsec);
+ lprocfs_stats_header(seq, ktime_get(), cli->cl_mod_rpcs_init, 25,
+ ":", true);
seq_printf(seq, "modify_RPCs_in_flight: %hu\n",
cli->cl_mod_rpcs_in_flight);
@@ -1366,6 +1366,24 @@ static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
return lprocfs_stats_seq_start(p, pos);
}
+void lprocfs_stats_header(struct seq_file *seq, ktime_t now, ktime_t ts_init,
+ int width, const char *colon, bool show_units)
+{
+ const char *units = show_units ? " secs.nsecs" : "";
+ struct timespec64 ts;
+
+ ts = ktime_to_timespec64(now);
+ seq_printf(seq, "%-*s%s %llu.%09lu%s\n", width,
+ "snapshot_time", colon, (s64)ts.tv_sec, ts.tv_nsec, units);
+ ts = ktime_to_timespec64(ts_init);
+ seq_printf(seq, "%-*s%s %llu.%09lu%s\n", width,
+ "start_time", colon, (s64)ts.tv_sec, ts.tv_nsec, units);
+ ts = ktime_to_timespec64(ktime_sub(now, ts_init));
+ seq_printf(seq, "%-*s%s %llu.%09lu%s\n", width,
+ "elapsed_time", colon, (s64)ts.tv_sec, ts.tv_nsec, units);
+}
+EXPORT_SYMBOL(lprocfs_stats_header);
+
/* seq file export of one lprocfs counter */
static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
{
@@ -1374,14 +1392,8 @@ static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
struct lprocfs_counter ctr;
int idx = *(loff_t *)v;
- if (idx == 0) {
- struct timespec64 now;
-
- ktime_get_real_ts64(&now);
- seq_printf(p, "%-25s %llu.%9lu secs.usecs\n",
- "snapshot_time",
- (s64)now.tv_sec, (unsigned long)now.tv_nsec);
- }
+ if (idx == 0)
+ lprocfs_stats_header(p, ktime_get(), stats->ls_init, 25, "", 1);
hdr = &stats->ls_cnt_header[idx];
lprocfs_stats_collect(stats, idx, &ctr);
@@ -695,18 +695,14 @@ static ssize_t grant_shrink_store(struct kobject *kobj, struct attribute *attr,
static int osc_rpc_stats_seq_show(struct seq_file *seq, void *v)
{
- struct timespec64 now;
struct obd_device *obd = seq->private;
struct client_obd *cli = &obd->u.cli;
unsigned long read_tot = 0, write_tot = 0, read_cum, write_cum;
int i;
- ktime_get_real_ts64(&now);
-
spin_lock(&cli->cl_loi_list_lock);
- seq_printf(seq, "snapshot_time: %llu.%9lu (secs.usecs)\n",
- (s64)now.tv_sec, (unsigned long)now.tv_nsec);
+ lprocfs_stats_header(seq, ktime_get(), cli->cl_stats_init, 25, ":", 1);
seq_printf(seq, "read RPCs in flight: %d\n",
cli->cl_r_in_flight);
seq_printf(seq, "write RPCs in flight: %d\n",
@@ -806,6 +802,7 @@ static ssize_t osc_rpc_stats_seq_write(struct file *file,
lprocfs_oh_clear(&cli->cl_write_page_hist);
lprocfs_oh_clear(&cli->cl_read_offset_hist);
lprocfs_oh_clear(&cli->cl_write_offset_hist);
+ cli->cl_stats_init = ktime_get();
return len;
}
@@ -814,14 +811,10 @@ static ssize_t osc_rpc_stats_seq_write(struct file *file,
static int osc_stats_seq_show(struct seq_file *seq, void *v)
{
- struct timespec64 now;
struct obd_device *obd = seq->private;
struct osc_stats *stats = &obd2osc_dev(obd)->od_stats;
- ktime_get_real_ts64(&now);
-
- seq_printf(seq, "snapshot_time: %llu.%9lu (secs.usecs)\n",
- (s64)now.tv_sec, (unsigned long)now.tv_nsec);
+ lprocfs_stats_header(seq, ktime_get(), stats->os_init, 25, ":", true);
seq_printf(seq, "lockless_write_bytes\t\t%llu\n",
stats->os_lockless_writes);
seq_printf(seq, "lockless_read_bytes\t\t%llu\n",
@@ -838,6 +831,8 @@ static ssize_t osc_stats_seq_write(struct file *file,
struct osc_stats *stats = &obd2osc_dev(obd)->od_stats;
memset(stats, 0, sizeof(*stats));
+ stats->os_init = ktime_get();
+
return len;
}