Linux-libre 4.9.174-gnu
[librecmc/linux-libre.git] / drivers / staging / lustre / lustre / osc / lproc_osc.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.gnu.org/licenses/gpl-2.0.html
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Use is subject to license terms.
25  *
26  * Copyright (c) 2011, 2015, Intel Corporation.
27  */
28 /*
29  * This file is part of Lustre, http://www.lustre.org/
30  * Lustre is a trademark of Sun Microsystems, Inc.
31  */
32 #define DEBUG_SUBSYSTEM S_CLASS
33
34 #include <linux/statfs.h>
35 #include "../include/obd_cksum.h"
36 #include "../include/obd_class.h"
37 #include "../include/lprocfs_status.h"
38 #include <linux/seq_file.h>
39 #include "osc_internal.h"
40
41 static ssize_t active_show(struct kobject *kobj, struct attribute *attr,
42                            char *buf)
43 {
44         struct obd_device *dev = container_of(kobj, struct obd_device,
45                                               obd_kobj);
46
47         return sprintf(buf, "%d\n", !dev->u.cli.cl_import->imp_deactive);
48 }
49
50 static ssize_t active_store(struct kobject *kobj, struct attribute *attr,
51                             const char *buffer,
52                             size_t count)
53 {
54         struct obd_device *dev = container_of(kobj, struct obd_device,
55                                               obd_kobj);
56         int rc;
57         unsigned long val;
58
59         rc = kstrtoul(buffer, 10, &val);
60         if (rc)
61                 return rc;
62         if (val > 1)
63                 return -ERANGE;
64
65         /* opposite senses */
66         if (dev->u.cli.cl_import->imp_deactive == val)
67                 rc = ptlrpc_set_import_active(dev->u.cli.cl_import, val);
68         else
69                 CDEBUG(D_CONFIG, "activate %ld: ignoring repeat request\n",
70                        val);
71
72         return count;
73 }
74 LUSTRE_RW_ATTR(active);
75
76 static ssize_t max_rpcs_in_flight_show(struct kobject *kobj,
77                                        struct attribute *attr,
78                                        char *buf)
79 {
80         struct obd_device *dev = container_of(kobj, struct obd_device,
81                                               obd_kobj);
82         struct client_obd *cli = &dev->u.cli;
83
84         return sprintf(buf, "%u\n", cli->cl_max_rpcs_in_flight);
85 }
86
87 static ssize_t max_rpcs_in_flight_store(struct kobject *kobj,
88                                         struct attribute *attr,
89                                         const char *buffer,
90                                         size_t count)
91 {
92         struct obd_device *dev = container_of(kobj, struct obd_device,
93                                               obd_kobj);
94         struct client_obd *cli = &dev->u.cli;
95         int rc;
96         unsigned long val;
97         int adding, added, req_count;
98
99         rc = kstrtoul(buffer, 10, &val);
100         if (rc)
101                 return rc;
102
103         if (val < 1 || val > OSC_MAX_RIF_MAX)
104                 return -ERANGE;
105
106         adding = val - cli->cl_max_rpcs_in_flight;
107         req_count = atomic_read(&osc_pool_req_count);
108         if (adding > 0 && req_count < osc_reqpool_maxreqcount) {
109                 /*
110                  * There might be some race which will cause over-limit
111                  * allocation, but it is fine.
112                  */
113                 if (req_count + adding > osc_reqpool_maxreqcount)
114                         adding = osc_reqpool_maxreqcount - req_count;
115
116                 added = osc_rq_pool->prp_populate(osc_rq_pool, adding);
117                 atomic_add(added, &osc_pool_req_count);
118         }
119
120         spin_lock(&cli->cl_loi_list_lock);
121         cli->cl_max_rpcs_in_flight = val;
122         client_adjust_max_dirty(cli);
123         spin_unlock(&cli->cl_loi_list_lock);
124
125         return count;
126 }
127 LUSTRE_RW_ATTR(max_rpcs_in_flight);
128
129 static ssize_t max_dirty_mb_show(struct kobject *kobj,
130                                  struct attribute *attr,
131                                  char *buf)
132 {
133         struct obd_device *dev = container_of(kobj, struct obd_device,
134                                               obd_kobj);
135         struct client_obd *cli = &dev->u.cli;
136         long val;
137         int mult;
138
139         spin_lock(&cli->cl_loi_list_lock);
140         val = cli->cl_dirty_max_pages;
141         spin_unlock(&cli->cl_loi_list_lock);
142
143         mult = 1 << (20 - PAGE_SHIFT);
144         return lprocfs_read_frac_helper(buf, PAGE_SIZE, val, mult);
145 }
146
147 static ssize_t max_dirty_mb_store(struct kobject *kobj,
148                                   struct attribute *attr,
149                                   const char *buffer,
150                                   size_t count)
151 {
152         struct obd_device *dev = container_of(kobj, struct obd_device,
153                                               obd_kobj);
154         struct client_obd *cli = &dev->u.cli;
155         int rc;
156         unsigned long pages_number;
157
158         rc = kstrtoul(buffer, 10, &pages_number);
159         if (rc)
160                 return rc;
161
162         pages_number *= 1 << (20 - PAGE_SHIFT); /* MB -> pages */
163
164         if (pages_number <= 0 ||
165             pages_number > OSC_MAX_DIRTY_MB_MAX << (20 - PAGE_SHIFT) ||
166             pages_number > totalram_pages / 4) /* 1/4 of RAM */
167                 return -ERANGE;
168
169         spin_lock(&cli->cl_loi_list_lock);
170         cli->cl_dirty_max_pages = pages_number;
171         osc_wake_cache_waiters(cli);
172         spin_unlock(&cli->cl_loi_list_lock);
173
174         return count;
175 }
176 LUSTRE_RW_ATTR(max_dirty_mb);
177
178 static int osc_cached_mb_seq_show(struct seq_file *m, void *v)
179 {
180         struct obd_device *dev = m->private;
181         struct client_obd *cli = &dev->u.cli;
182         int shift = 20 - PAGE_SHIFT;
183
184         seq_printf(m,
185                    "used_mb: %ld\n"
186                    "busy_cnt: %ld\n",
187                    (atomic_long_read(&cli->cl_lru_in_list) +
188                     atomic_long_read(&cli->cl_lru_busy)) >> shift,
189                    atomic_long_read(&cli->cl_lru_busy));
190
191         return 0;
192 }
193
194 /* shrink the number of caching pages to a specific number */
195 static ssize_t osc_cached_mb_seq_write(struct file *file,
196                                        const char __user *buffer,
197                                        size_t count, loff_t *off)
198 {
199         struct obd_device *dev = ((struct seq_file *)file->private_data)->private;
200         struct client_obd *cli = &dev->u.cli;
201         long pages_number, rc;
202         char kernbuf[128];
203         int mult;
204         u64 val;
205
206         if (count >= sizeof(kernbuf))
207                 return -EINVAL;
208
209         if (copy_from_user(kernbuf, buffer, count))
210                 return -EFAULT;
211         kernbuf[count] = 0;
212
213         mult = 1 << (20 - PAGE_SHIFT);
214         buffer += lprocfs_find_named_value(kernbuf, "used_mb:", &count) -
215                   kernbuf;
216         rc = lprocfs_write_frac_u64_helper(buffer, count, &val, mult);
217         if (rc)
218                 return rc;
219
220         if (val > LONG_MAX)
221                 return -ERANGE;
222         pages_number = (long)val;
223
224         if (pages_number < 0)
225                 return -ERANGE;
226
227         rc = atomic_long_read(&cli->cl_lru_in_list) - pages_number;
228         if (rc > 0) {
229                 struct lu_env *env;
230                 int refcheck;
231
232                 env = cl_env_get(&refcheck);
233                 if (!IS_ERR(env)) {
234                         (void)osc_lru_shrink(env, cli, rc, true);
235                         cl_env_put(env, &refcheck);
236                 }
237         }
238
239         return count;
240 }
241
242 LPROC_SEQ_FOPS(osc_cached_mb);
243
244 static ssize_t cur_dirty_bytes_show(struct kobject *kobj,
245                                     struct attribute *attr,
246                                     char *buf)
247 {
248         struct obd_device *dev = container_of(kobj, struct obd_device,
249                                               obd_kobj);
250         struct client_obd *cli = &dev->u.cli;
251         int len;
252
253         spin_lock(&cli->cl_loi_list_lock);
254         len = sprintf(buf, "%lu\n", cli->cl_dirty_pages << PAGE_SHIFT);
255         spin_unlock(&cli->cl_loi_list_lock);
256
257         return len;
258 }
259 LUSTRE_RO_ATTR(cur_dirty_bytes);
260
261 static ssize_t cur_grant_bytes_show(struct kobject *kobj,
262                                     struct attribute *attr,
263                                     char *buf)
264 {
265         struct obd_device *dev = container_of(kobj, struct obd_device,
266                                               obd_kobj);
267         struct client_obd *cli = &dev->u.cli;
268         int len;
269
270         spin_lock(&cli->cl_loi_list_lock);
271         len = sprintf(buf, "%lu\n", cli->cl_avail_grant);
272         spin_unlock(&cli->cl_loi_list_lock);
273
274         return len;
275 }
276
277 static ssize_t cur_grant_bytes_store(struct kobject *kobj,
278                                      struct attribute *attr,
279                                      const char *buffer,
280                                      size_t count)
281 {
282         struct obd_device *obd = container_of(kobj, struct obd_device,
283                                               obd_kobj);
284         struct client_obd *cli = &obd->u.cli;
285         int rc;
286         unsigned long long val;
287
288         rc = kstrtoull(buffer, 10, &val);
289         if (rc)
290                 return rc;
291
292         /* this is only for shrinking grant */
293         spin_lock(&cli->cl_loi_list_lock);
294         if (val >= cli->cl_avail_grant) {
295                 spin_unlock(&cli->cl_loi_list_lock);
296                 return -EINVAL;
297         }
298         spin_unlock(&cli->cl_loi_list_lock);
299
300         if (cli->cl_import->imp_state == LUSTRE_IMP_FULL)
301                 rc = osc_shrink_grant_to_target(cli, val);
302         if (rc)
303                 return rc;
304         return count;
305 }
306 LUSTRE_RW_ATTR(cur_grant_bytes);
307
308 static ssize_t cur_lost_grant_bytes_show(struct kobject *kobj,
309                                          struct attribute *attr,
310                                          char *buf)
311 {
312         struct obd_device *dev = container_of(kobj, struct obd_device,
313                                               obd_kobj);
314         struct client_obd *cli = &dev->u.cli;
315         int len;
316
317         spin_lock(&cli->cl_loi_list_lock);
318         len = sprintf(buf, "%lu\n", cli->cl_lost_grant);
319         spin_unlock(&cli->cl_loi_list_lock);
320
321         return len;
322 }
323 LUSTRE_RO_ATTR(cur_lost_grant_bytes);
324
325 static ssize_t grant_shrink_interval_show(struct kobject *kobj,
326                                           struct attribute *attr,
327                                           char *buf)
328 {
329         struct obd_device *obd = container_of(kobj, struct obd_device,
330                                               obd_kobj);
331
332         return sprintf(buf, "%d\n", obd->u.cli.cl_grant_shrink_interval);
333 }
334
335 static ssize_t grant_shrink_interval_store(struct kobject *kobj,
336                                            struct attribute *attr,
337                                            const char *buffer,
338                                            size_t count)
339 {
340         struct obd_device *obd = container_of(kobj, struct obd_device,
341                                               obd_kobj);
342         int rc;
343         unsigned long val;
344
345         rc = kstrtoul(buffer, 10, &val);
346         if (rc)
347                 return rc;
348
349         if (val <= 0)
350                 return -ERANGE;
351
352         obd->u.cli.cl_grant_shrink_interval = val;
353
354         return count;
355 }
356 LUSTRE_RW_ATTR(grant_shrink_interval);
357
358 static ssize_t checksums_show(struct kobject *kobj,
359                               struct attribute *attr,
360                               char *buf)
361 {
362         struct obd_device *obd = container_of(kobj, struct obd_device,
363                                               obd_kobj);
364
365         return sprintf(buf, "%d\n", obd->u.cli.cl_checksum ? 1 : 0);
366 }
367
368 static ssize_t checksums_store(struct kobject *kobj,
369                                struct attribute *attr,
370                                const char *buffer,
371                                size_t count)
372 {
373         struct obd_device *obd = container_of(kobj, struct obd_device,
374                                               obd_kobj);
375         int rc;
376         unsigned long val;
377
378         rc = kstrtoul(buffer, 10, &val);
379         if (rc)
380                 return rc;
381
382         obd->u.cli.cl_checksum = (val ? 1 : 0);
383
384         return count;
385 }
386 LUSTRE_RW_ATTR(checksums);
387
388 static int osc_checksum_type_seq_show(struct seq_file *m, void *v)
389 {
390         struct obd_device *obd = m->private;
391         int i;
392
393         DECLARE_CKSUM_NAME;
394
395         if (!obd)
396                 return 0;
397
398         for (i = 0; i < ARRAY_SIZE(cksum_name); i++) {
399                 if (((1 << i) & obd->u.cli.cl_supp_cksum_types) == 0)
400                         continue;
401                 if (obd->u.cli.cl_cksum_type == (1 << i))
402                         seq_printf(m, "[%s] ", cksum_name[i]);
403                 else
404                         seq_printf(m, "%s ", cksum_name[i]);
405         }
406         seq_putc(m, '\n');
407         return 0;
408 }
409
410 static ssize_t osc_checksum_type_seq_write(struct file *file,
411                                            const char __user *buffer,
412                                            size_t count, loff_t *off)
413 {
414         struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
415         int i;
416
417         DECLARE_CKSUM_NAME;
418         char kernbuf[10];
419
420         if (!obd)
421                 return 0;
422
423         if (count > sizeof(kernbuf) - 1)
424                 return -EINVAL;
425         if (copy_from_user(kernbuf, buffer, count))
426                 return -EFAULT;
427         if (count > 0 && kernbuf[count - 1] == '\n')
428                 kernbuf[count - 1] = '\0';
429         else
430                 kernbuf[count] = '\0';
431
432         for (i = 0; i < ARRAY_SIZE(cksum_name); i++) {
433                 if (((1 << i) & obd->u.cli.cl_supp_cksum_types) == 0)
434                         continue;
435                 if (!strcmp(kernbuf, cksum_name[i])) {
436                         obd->u.cli.cl_cksum_type = 1 << i;
437                         return count;
438                 }
439         }
440         return -EINVAL;
441 }
442
443 LPROC_SEQ_FOPS(osc_checksum_type);
444
445 static ssize_t resend_count_show(struct kobject *kobj,
446                                  struct attribute *attr,
447                                  char *buf)
448 {
449         struct obd_device *obd = container_of(kobj, struct obd_device,
450                                               obd_kobj);
451
452         return sprintf(buf, "%u\n", atomic_read(&obd->u.cli.cl_resends));
453 }
454
455 static ssize_t resend_count_store(struct kobject *kobj,
456                                   struct attribute *attr,
457                                   const char *buffer,
458                                   size_t count)
459 {
460         struct obd_device *obd = container_of(kobj, struct obd_device,
461                                               obd_kobj);
462         int rc;
463         unsigned long val;
464
465         rc = kstrtoul(buffer, 10, &val);
466         if (rc)
467                 return rc;
468
469         atomic_set(&obd->u.cli.cl_resends, val);
470
471         return count;
472 }
473 LUSTRE_RW_ATTR(resend_count);
474
475 static ssize_t contention_seconds_show(struct kobject *kobj,
476                                        struct attribute *attr,
477                                        char *buf)
478 {
479         struct obd_device *obd = container_of(kobj, struct obd_device,
480                                               obd_kobj);
481         struct osc_device *od  = obd2osc_dev(obd);
482
483         return sprintf(buf, "%u\n", od->od_contention_time);
484 }
485
486 static ssize_t contention_seconds_store(struct kobject *kobj,
487                                         struct attribute *attr,
488                                         const char *buffer,
489                                         size_t count)
490 {
491         struct obd_device *obd = container_of(kobj, struct obd_device,
492                                               obd_kobj);
493         struct osc_device *od  = obd2osc_dev(obd);
494         int rc;
495         int val;
496
497         rc = kstrtoint(buffer, 10, &val);
498         if (rc)
499                 return rc;
500
501         if (val < 0)
502                 return -EINVAL;
503
504         od->od_contention_time = val;
505
506         return count;
507 }
508 LUSTRE_RW_ATTR(contention_seconds);
509
510 static ssize_t lockless_truncate_show(struct kobject *kobj,
511                                       struct attribute *attr,
512                                       char *buf)
513 {
514         struct obd_device *obd = container_of(kobj, struct obd_device,
515                                               obd_kobj);
516         struct osc_device *od  = obd2osc_dev(obd);
517
518         return sprintf(buf, "%u\n", od->od_lockless_truncate);
519 }
520
521 static ssize_t lockless_truncate_store(struct kobject *kobj,
522                                        struct attribute *attr,
523                                        const char *buffer,
524                                        size_t count)
525 {
526         struct obd_device *obd = container_of(kobj, struct obd_device,
527                                               obd_kobj);
528         struct osc_device *od  = obd2osc_dev(obd);
529         int rc;
530         unsigned int val;
531
532         rc = kstrtouint(buffer, 10, &val);
533         if (rc)
534                 return rc;
535
536         od->od_lockless_truncate = val;
537
538         return count;
539 }
540 LUSTRE_RW_ATTR(lockless_truncate);
541
542 static ssize_t destroys_in_flight_show(struct kobject *kobj,
543                                        struct attribute *attr,
544                                        char *buf)
545 {
546         struct obd_device *obd = container_of(kobj, struct obd_device,
547                                               obd_kobj);
548
549         return sprintf(buf, "%u\n",
550                        atomic_read(&obd->u.cli.cl_destroy_in_flight));
551 }
552 LUSTRE_RO_ATTR(destroys_in_flight);
553
554 static ssize_t max_pages_per_rpc_show(struct kobject *kobj,
555                                       struct attribute *attr,
556                                       char *buf)
557 {
558         struct obd_device *dev = container_of(kobj, struct obd_device,
559                                               obd_kobj);
560         struct client_obd *cli = &dev->u.cli;
561
562         return sprintf(buf, "%d\n", cli->cl_max_pages_per_rpc);
563 }
564
565 static ssize_t max_pages_per_rpc_store(struct kobject *kobj,
566                                        struct attribute *attr,
567                                        const char *buffer,
568                                        size_t count)
569 {
570         struct obd_device *dev = container_of(kobj, struct obd_device,
571                                               obd_kobj);
572         struct client_obd *cli = &dev->u.cli;
573         struct obd_connect_data *ocd = &cli->cl_import->imp_connect_data;
574         int chunk_mask, rc;
575         unsigned long long val;
576
577         rc = kstrtoull(buffer, 10, &val);
578         if (rc)
579                 return rc;
580
581         /* if the max_pages is specified in bytes, convert to pages */
582         if (val >= ONE_MB_BRW_SIZE)
583                 val >>= PAGE_SHIFT;
584
585         chunk_mask = ~((1 << (cli->cl_chunkbits - PAGE_SHIFT)) - 1);
586         /* max_pages_per_rpc must be chunk aligned */
587         val = (val + ~chunk_mask) & chunk_mask;
588         if (val == 0 || val > ocd->ocd_brw_size >> PAGE_SHIFT) {
589                 return -ERANGE;
590         }
591         spin_lock(&cli->cl_loi_list_lock);
592         cli->cl_max_pages_per_rpc = val;
593         client_adjust_max_dirty(cli);
594         spin_unlock(&cli->cl_loi_list_lock);
595
596         return count;
597 }
598 LUSTRE_RW_ATTR(max_pages_per_rpc);
599
600 static ssize_t unstable_stats_show(struct kobject *kobj,
601                                    struct attribute *attr,
602                                    char *buf)
603 {
604         struct obd_device *dev = container_of(kobj, struct obd_device,
605                                               obd_kobj);
606         struct client_obd *cli = &dev->u.cli;
607         long pages;
608         int mb;
609
610         pages = atomic_long_read(&cli->cl_unstable_count);
611         mb = (pages * PAGE_SIZE) >> 20;
612
613         return sprintf(buf, "unstable_pages: %20ld\n"
614                        "unstable_mb:              %10d\n", pages, mb);
615 }
616 LUSTRE_RO_ATTR(unstable_stats);
617
618 LPROC_SEQ_FOPS_RO_TYPE(osc, connect_flags);
619 LPROC_SEQ_FOPS_RO_TYPE(osc, server_uuid);
620 LPROC_SEQ_FOPS_RO_TYPE(osc, conn_uuid);
621 LPROC_SEQ_FOPS_RO_TYPE(osc, timeouts);
622 LPROC_SEQ_FOPS_RO_TYPE(osc, state);
623
624 LPROC_SEQ_FOPS_WR_ONLY(osc, ping);
625
626 LPROC_SEQ_FOPS_RW_TYPE(osc, import);
627 LPROC_SEQ_FOPS_RW_TYPE(osc, pinger_recov);
628
629 static struct lprocfs_vars lprocfs_osc_obd_vars[] = {
630         { "ping",            &osc_ping_fops,    NULL, 0222 },
631         { "connect_flags",   &osc_connect_flags_fops, NULL, 0 },
632         /*{ "filegroups",      lprocfs_rd_filegroups,  NULL, 0 },*/
633         { "ost_server_uuid", &osc_server_uuid_fops, NULL, 0 },
634         { "ost_conn_uuid",   &osc_conn_uuid_fops, NULL, 0 },
635         { "osc_cached_mb",   &osc_cached_mb_fops, NULL },
636         { "checksum_type",   &osc_checksum_type_fops, NULL },
637         { "timeouts",        &osc_timeouts_fops, NULL, 0 },
638         { "import",             &osc_import_fops, NULL },
639         { "state",              &osc_state_fops, NULL, 0 },
640         { "pinger_recov",       &osc_pinger_recov_fops, NULL },
641         { NULL }
642 };
643
644 #define pct(a, b) (b ? a * 100 / b : 0)
645
646 static int osc_rpc_stats_seq_show(struct seq_file *seq, void *v)
647 {
648         struct timespec64 now;
649         struct obd_device *dev = seq->private;
650         struct client_obd *cli = &dev->u.cli;
651         unsigned long read_tot = 0, write_tot = 0, read_cum, write_cum;
652         int i;
653
654         ktime_get_real_ts64(&now);
655
656         spin_lock(&cli->cl_loi_list_lock);
657
658         seq_printf(seq, "snapshot_time:  %llu.%9lu (secs.usecs)\n",
659                    (s64)now.tv_sec, (unsigned long)now.tv_nsec);
660         seq_printf(seq, "read RPCs in flight:  %d\n",
661                    cli->cl_r_in_flight);
662         seq_printf(seq, "write RPCs in flight: %d\n",
663                    cli->cl_w_in_flight);
664         seq_printf(seq, "pending write pages:  %d\n",
665                    atomic_read(&cli->cl_pending_w_pages));
666         seq_printf(seq, "pending read pages:   %d\n",
667                    atomic_read(&cli->cl_pending_r_pages));
668
669         seq_puts(seq, "\n\t\t\tread\t\t\twrite\n");
670         seq_puts(seq, "pages per rpc     rpcs   % cum % |");
671         seq_puts(seq, "       rpcs   % cum %\n");
672
673         read_tot = lprocfs_oh_sum(&cli->cl_read_page_hist);
674         write_tot = lprocfs_oh_sum(&cli->cl_write_page_hist);
675
676         read_cum = 0;
677         write_cum = 0;
678         for (i = 0; i < OBD_HIST_MAX; i++) {
679                 unsigned long r = cli->cl_read_page_hist.oh_buckets[i];
680                 unsigned long w = cli->cl_write_page_hist.oh_buckets[i];
681
682                 read_cum += r;
683                 write_cum += w;
684                 seq_printf(seq, "%d:\t\t%10lu %3lu %3lu   | %10lu %3lu %3lu\n",
685                            1 << i, r, pct(r, read_tot),
686                            pct(read_cum, read_tot), w,
687                            pct(w, write_tot),
688                            pct(write_cum, write_tot));
689                 if (read_cum == read_tot && write_cum == write_tot)
690                         break;
691         }
692
693         seq_puts(seq, "\n\t\t\tread\t\t\twrite\n");
694         seq_puts(seq, "rpcs in flight   rpcs   % cum % |");
695         seq_puts(seq, "       rpcs   % cum %\n");
696
697         read_tot = lprocfs_oh_sum(&cli->cl_read_rpc_hist);
698         write_tot = lprocfs_oh_sum(&cli->cl_write_rpc_hist);
699
700         read_cum = 0;
701         write_cum = 0;
702         for (i = 0; i < OBD_HIST_MAX; i++) {
703                 unsigned long r = cli->cl_read_rpc_hist.oh_buckets[i];
704                 unsigned long w = cli->cl_write_rpc_hist.oh_buckets[i];
705
706                 read_cum += r;
707                 write_cum += w;
708                 seq_printf(seq, "%d:\t\t%10lu %3lu %3lu   | %10lu %3lu %3lu\n",
709                            i, r, pct(r, read_tot),
710                            pct(read_cum, read_tot), w,
711                            pct(w, write_tot),
712                            pct(write_cum, write_tot));
713                 if (read_cum == read_tot && write_cum == write_tot)
714                         break;
715         }
716
717         seq_puts(seq, "\n\t\t\tread\t\t\twrite\n");
718         seq_puts(seq, "offset           rpcs   % cum % |");
719         seq_puts(seq, "       rpcs   % cum %\n");
720
721         read_tot = lprocfs_oh_sum(&cli->cl_read_offset_hist);
722         write_tot = lprocfs_oh_sum(&cli->cl_write_offset_hist);
723
724         read_cum = 0;
725         write_cum = 0;
726         for (i = 0; i < OBD_HIST_MAX; i++) {
727                 unsigned long r = cli->cl_read_offset_hist.oh_buckets[i];
728                 unsigned long w = cli->cl_write_offset_hist.oh_buckets[i];
729
730                 read_cum += r;
731                 write_cum += w;
732                 seq_printf(seq, "%d:\t\t%10lu %3lu %3lu   | %10lu %3lu %3lu\n",
733                            (i == 0) ? 0 : 1 << (i - 1),
734                            r, pct(r, read_tot), pct(read_cum, read_tot),
735                            w, pct(w, write_tot), pct(write_cum, write_tot));
736                 if (read_cum == read_tot && write_cum == write_tot)
737                         break;
738         }
739
740         spin_unlock(&cli->cl_loi_list_lock);
741
742         return 0;
743 }
744
745 #undef pct
746
747 static ssize_t osc_rpc_stats_seq_write(struct file *file,
748                                        const char __user *buf,
749                                        size_t len, loff_t *off)
750 {
751         struct seq_file *seq = file->private_data;
752         struct obd_device *dev = seq->private;
753         struct client_obd *cli = &dev->u.cli;
754
755         lprocfs_oh_clear(&cli->cl_read_rpc_hist);
756         lprocfs_oh_clear(&cli->cl_write_rpc_hist);
757         lprocfs_oh_clear(&cli->cl_read_page_hist);
758         lprocfs_oh_clear(&cli->cl_write_page_hist);
759         lprocfs_oh_clear(&cli->cl_read_offset_hist);
760         lprocfs_oh_clear(&cli->cl_write_offset_hist);
761
762         return len;
763 }
764
765 LPROC_SEQ_FOPS(osc_rpc_stats);
766
767 static int osc_stats_seq_show(struct seq_file *seq, void *v)
768 {
769         struct timespec64 now;
770         struct obd_device *dev = seq->private;
771         struct osc_stats *stats = &obd2osc_dev(dev)->od_stats;
772
773         ktime_get_real_ts64(&now);
774
775         seq_printf(seq, "snapshot_time:  %llu.%9lu (secs.usecs)\n",
776                    (s64)now.tv_sec, (unsigned long)now.tv_nsec);
777         seq_printf(seq, "lockless_write_bytes\t\t%llu\n",
778                    stats->os_lockless_writes);
779         seq_printf(seq, "lockless_read_bytes\t\t%llu\n",
780                    stats->os_lockless_reads);
781         seq_printf(seq, "lockless_truncate\t\t%llu\n",
782                    stats->os_lockless_truncates);
783         return 0;
784 }
785
786 static ssize_t osc_stats_seq_write(struct file *file,
787                                    const char __user *buf,
788                                    size_t len, loff_t *off)
789 {
790         struct seq_file *seq = file->private_data;
791         struct obd_device *dev = seq->private;
792         struct osc_stats *stats = &obd2osc_dev(dev)->od_stats;
793
794         memset(stats, 0, sizeof(*stats));
795         return len;
796 }
797
798 LPROC_SEQ_FOPS(osc_stats);
799
800 int lproc_osc_attach_seqstat(struct obd_device *dev)
801 {
802         int rc;
803
804         rc = ldebugfs_seq_create(dev->obd_debugfs_entry, "osc_stats", 0644,
805                                  &osc_stats_fops, dev);
806         if (rc == 0)
807                 rc = ldebugfs_obd_seq_create(dev, "rpc_stats", 0644,
808                                              &osc_rpc_stats_fops, dev);
809
810         return rc;
811 }
812
813 static struct attribute *osc_attrs[] = {
814         &lustre_attr_active.attr,
815         &lustre_attr_checksums.attr,
816         &lustre_attr_contention_seconds.attr,
817         &lustre_attr_cur_dirty_bytes.attr,
818         &lustre_attr_cur_grant_bytes.attr,
819         &lustre_attr_cur_lost_grant_bytes.attr,
820         &lustre_attr_destroys_in_flight.attr,
821         &lustre_attr_grant_shrink_interval.attr,
822         &lustre_attr_lockless_truncate.attr,
823         &lustre_attr_max_dirty_mb.attr,
824         &lustre_attr_max_pages_per_rpc.attr,
825         &lustre_attr_max_rpcs_in_flight.attr,
826         &lustre_attr_resend_count.attr,
827         &lustre_attr_unstable_stats.attr,
828         NULL,
829 };
830
831 static struct attribute_group osc_attr_group = {
832         .attrs = osc_attrs,
833 };
834
835 void lprocfs_osc_init_vars(struct lprocfs_static_vars *lvars)
836 {
837         lvars->sysfs_vars  = &osc_attr_group;
838         lvars->obd_vars    = lprocfs_osc_obd_vars;
839 }