1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32#define DEBUG_SUBSYSTEM S_LLITE
33
34#include "../include/lprocfs_status.h"
35#include <linux/seq_file.h>
36#include "../include/obd_support.h"
37
38#include "llite_internal.h"
39#include "vvp_internal.h"
40
41
42static struct file_operations ll_rw_extents_stats_fops;
43static struct file_operations ll_rw_extents_stats_pp_fops;
44static struct file_operations ll_rw_offset_stats_fops;
45
46static ssize_t blocksize_show(struct kobject *kobj, struct attribute *attr,
47 char *buf)
48{
49 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
50 ll_kobj);
51 struct obd_statfs osfs;
52 int rc;
53
54 rc = ll_statfs_internal(sbi->ll_sb, &osfs,
55 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
56 OBD_STATFS_NODELAY);
57 if (!rc)
58 return sprintf(buf, "%u\n", osfs.os_bsize);
59
60 return rc;
61}
62LUSTRE_RO_ATTR(blocksize);
63
64static ssize_t kbytestotal_show(struct kobject *kobj, struct attribute *attr,
65 char *buf)
66{
67 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
68 ll_kobj);
69 struct obd_statfs osfs;
70 int rc;
71
72 rc = ll_statfs_internal(sbi->ll_sb, &osfs,
73 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
74 OBD_STATFS_NODELAY);
75 if (!rc) {
76 __u32 blk_size = osfs.os_bsize >> 10;
77 __u64 result = osfs.os_blocks;
78
79 while (blk_size >>= 1)
80 result <<= 1;
81
82 rc = sprintf(buf, "%llu\n", result);
83 }
84
85 return rc;
86}
87LUSTRE_RO_ATTR(kbytestotal);
88
89static ssize_t kbytesfree_show(struct kobject *kobj, struct attribute *attr,
90 char *buf)
91{
92 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
93 ll_kobj);
94 struct obd_statfs osfs;
95 int rc;
96
97 rc = ll_statfs_internal(sbi->ll_sb, &osfs,
98 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
99 OBD_STATFS_NODELAY);
100 if (!rc) {
101 __u32 blk_size = osfs.os_bsize >> 10;
102 __u64 result = osfs.os_bfree;
103
104 while (blk_size >>= 1)
105 result <<= 1;
106
107 rc = sprintf(buf, "%llu\n", result);
108 }
109
110 return rc;
111}
112LUSTRE_RO_ATTR(kbytesfree);
113
114static ssize_t kbytesavail_show(struct kobject *kobj, struct attribute *attr,
115 char *buf)
116{
117 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
118 ll_kobj);
119 struct obd_statfs osfs;
120 int rc;
121
122 rc = ll_statfs_internal(sbi->ll_sb, &osfs,
123 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
124 OBD_STATFS_NODELAY);
125 if (!rc) {
126 __u32 blk_size = osfs.os_bsize >> 10;
127 __u64 result = osfs.os_bavail;
128
129 while (blk_size >>= 1)
130 result <<= 1;
131
132 rc = sprintf(buf, "%llu\n", result);
133 }
134
135 return rc;
136}
137LUSTRE_RO_ATTR(kbytesavail);
138
139static ssize_t filestotal_show(struct kobject *kobj, struct attribute *attr,
140 char *buf)
141{
142 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
143 ll_kobj);
144 struct obd_statfs osfs;
145 int rc;
146
147 rc = ll_statfs_internal(sbi->ll_sb, &osfs,
148 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
149 OBD_STATFS_NODELAY);
150 if (!rc)
151 return sprintf(buf, "%llu\n", osfs.os_files);
152
153 return rc;
154}
155LUSTRE_RO_ATTR(filestotal);
156
157static ssize_t filesfree_show(struct kobject *kobj, struct attribute *attr,
158 char *buf)
159{
160 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
161 ll_kobj);
162 struct obd_statfs osfs;
163 int rc;
164
165 rc = ll_statfs_internal(sbi->ll_sb, &osfs,
166 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
167 OBD_STATFS_NODELAY);
168 if (!rc)
169 return sprintf(buf, "%llu\n", osfs.os_ffree);
170
171 return rc;
172}
173LUSTRE_RO_ATTR(filesfree);
174
175static ssize_t client_type_show(struct kobject *kobj, struct attribute *attr,
176 char *buf)
177{
178 return sprintf(buf, "local client\n");
179}
180LUSTRE_RO_ATTR(client_type);
181
182static ssize_t fstype_show(struct kobject *kobj, struct attribute *attr,
183 char *buf)
184{
185 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
186 ll_kobj);
187
188 return sprintf(buf, "%s\n", sbi->ll_sb->s_type->name);
189}
190LUSTRE_RO_ATTR(fstype);
191
192static ssize_t uuid_show(struct kobject *kobj, struct attribute *attr,
193 char *buf)
194{
195 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
196 ll_kobj);
197
198 return sprintf(buf, "%s\n", sbi->ll_sb_uuid.uuid);
199}
200LUSTRE_RO_ATTR(uuid);
201
202static int ll_site_stats_seq_show(struct seq_file *m, void *v)
203{
204 struct super_block *sb = m->private;
205
206
207
208
209
210 return cl_site_stats_print(lu2cl_site(ll_s2sbi(sb)->ll_site), m);
211}
212
213LPROC_SEQ_FOPS_RO(ll_site_stats);
214
215static ssize_t max_read_ahead_mb_show(struct kobject *kobj,
216 struct attribute *attr, char *buf)
217{
218 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
219 ll_kobj);
220 long pages_number;
221 int mult;
222
223 spin_lock(&sbi->ll_lock);
224 pages_number = sbi->ll_ra_info.ra_max_pages;
225 spin_unlock(&sbi->ll_lock);
226
227 mult = 1 << (20 - PAGE_SHIFT);
228 return lprocfs_read_frac_helper(buf, PAGE_SIZE, pages_number, mult);
229}
230
231static ssize_t max_read_ahead_mb_store(struct kobject *kobj,
232 struct attribute *attr,
233 const char *buffer,
234 size_t count)
235{
236 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
237 ll_kobj);
238 int rc;
239 unsigned long pages_number;
240
241 rc = kstrtoul(buffer, 10, &pages_number);
242 if (rc)
243 return rc;
244
245 pages_number *= 1 << (20 - PAGE_SHIFT);
246
247 if (pages_number > totalram_pages / 2) {
248 CERROR("can't set file readahead more than %lu MB\n",
249 totalram_pages >> (20 - PAGE_SHIFT + 1));
250 return -ERANGE;
251 }
252
253 spin_lock(&sbi->ll_lock);
254 sbi->ll_ra_info.ra_max_pages = pages_number;
255 spin_unlock(&sbi->ll_lock);
256
257 return count;
258}
259LUSTRE_RW_ATTR(max_read_ahead_mb);
260
261static ssize_t max_read_ahead_per_file_mb_show(struct kobject *kobj,
262 struct attribute *attr,
263 char *buf)
264{
265 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
266 ll_kobj);
267 long pages_number;
268 int mult;
269
270 spin_lock(&sbi->ll_lock);
271 pages_number = sbi->ll_ra_info.ra_max_pages_per_file;
272 spin_unlock(&sbi->ll_lock);
273
274 mult = 1 << (20 - PAGE_SHIFT);
275 return lprocfs_read_frac_helper(buf, PAGE_SIZE, pages_number, mult);
276}
277
278static ssize_t max_read_ahead_per_file_mb_store(struct kobject *kobj,
279 struct attribute *attr,
280 const char *buffer,
281 size_t count)
282{
283 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
284 ll_kobj);
285 int rc;
286 unsigned long pages_number;
287
288 rc = kstrtoul(buffer, 10, &pages_number);
289 if (rc)
290 return rc;
291
292 if (pages_number > sbi->ll_ra_info.ra_max_pages) {
293 CERROR("can't set file readahead more than max_read_ahead_mb %lu MB\n",
294 sbi->ll_ra_info.ra_max_pages);
295 return -ERANGE;
296 }
297
298 spin_lock(&sbi->ll_lock);
299 sbi->ll_ra_info.ra_max_pages_per_file = pages_number;
300 spin_unlock(&sbi->ll_lock);
301
302 return count;
303}
304LUSTRE_RW_ATTR(max_read_ahead_per_file_mb);
305
306static ssize_t max_read_ahead_whole_mb_show(struct kobject *kobj,
307 struct attribute *attr,
308 char *buf)
309{
310 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
311 ll_kobj);
312 long pages_number;
313 int mult;
314
315 spin_lock(&sbi->ll_lock);
316 pages_number = sbi->ll_ra_info.ra_max_read_ahead_whole_pages;
317 spin_unlock(&sbi->ll_lock);
318
319 mult = 1 << (20 - PAGE_SHIFT);
320 return lprocfs_read_frac_helper(buf, PAGE_SIZE, pages_number, mult);
321}
322
323static ssize_t max_read_ahead_whole_mb_store(struct kobject *kobj,
324 struct attribute *attr,
325 const char *buffer,
326 size_t count)
327{
328 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
329 ll_kobj);
330 int rc;
331 unsigned long pages_number;
332
333 rc = kstrtoul(buffer, 10, &pages_number);
334 if (rc)
335 return rc;
336
337
338
339
340 if (pages_number > sbi->ll_ra_info.ra_max_pages_per_file) {
341 CERROR("can't set max_read_ahead_whole_mb more than max_read_ahead_per_file_mb: %lu\n",
342 sbi->ll_ra_info.ra_max_pages_per_file >> (20 - PAGE_SHIFT));
343 return -ERANGE;
344 }
345
346 spin_lock(&sbi->ll_lock);
347 sbi->ll_ra_info.ra_max_read_ahead_whole_pages = pages_number;
348 spin_unlock(&sbi->ll_lock);
349
350 return count;
351}
352LUSTRE_RW_ATTR(max_read_ahead_whole_mb);
353
354static int ll_max_cached_mb_seq_show(struct seq_file *m, void *v)
355{
356 struct super_block *sb = m->private;
357 struct ll_sb_info *sbi = ll_s2sbi(sb);
358 struct cl_client_cache *cache = sbi->ll_cache;
359 int shift = 20 - PAGE_SHIFT;
360 long max_cached_mb;
361 long unused_mb;
362
363 max_cached_mb = cache->ccc_lru_max >> shift;
364 unused_mb = atomic_long_read(&cache->ccc_lru_left) >> shift;
365 seq_printf(m,
366 "users: %d\n"
367 "max_cached_mb: %ld\n"
368 "used_mb: %ld\n"
369 "unused_mb: %ld\n"
370 "reclaim_count: %u\n",
371 atomic_read(&cache->ccc_users),
372 max_cached_mb,
373 max_cached_mb - unused_mb,
374 unused_mb,
375 cache->ccc_lru_shrinkers);
376 return 0;
377}
378
379static ssize_t ll_max_cached_mb_seq_write(struct file *file,
380 const char __user *buffer,
381 size_t count, loff_t *off)
382{
383 struct super_block *sb = ((struct seq_file *)file->private_data)->private;
384 struct ll_sb_info *sbi = ll_s2sbi(sb);
385 struct cl_client_cache *cache = sbi->ll_cache;
386 struct lu_env *env;
387 long diff = 0;
388 long nrpages = 0;
389 int refcheck;
390 long pages_number;
391 int mult;
392 long rc;
393 u64 val;
394 char kernbuf[128];
395
396 if (count >= sizeof(kernbuf))
397 return -EINVAL;
398
399 if (copy_from_user(kernbuf, buffer, count))
400 return -EFAULT;
401 kernbuf[count] = 0;
402
403 mult = 1 << (20 - PAGE_SHIFT);
404 buffer += lprocfs_find_named_value(kernbuf, "max_cached_mb:", &count) -
405 kernbuf;
406 rc = lprocfs_write_frac_u64_helper(buffer, count, &val, mult);
407 if (rc)
408 return rc;
409
410 if (val > LONG_MAX)
411 return -ERANGE;
412 pages_number = (long)val;
413
414 if (pages_number < 0 || pages_number > totalram_pages) {
415 CERROR("%s: can't set max cache more than %lu MB\n",
416 ll_get_fsname(sb, NULL, 0),
417 totalram_pages >> (20 - PAGE_SHIFT));
418 return -ERANGE;
419 }
420
421 spin_lock(&sbi->ll_lock);
422 diff = pages_number - cache->ccc_lru_max;
423 spin_unlock(&sbi->ll_lock);
424
425
426 if (diff >= 0) {
427 atomic_long_add(diff, &cache->ccc_lru_left);
428 rc = 0;
429 goto out;
430 }
431
432 env = cl_env_get(&refcheck);
433 if (IS_ERR(env))
434 return 0;
435
436 diff = -diff;
437 while (diff > 0) {
438 long tmp;
439
440
441 do {
442 long ov, nv;
443
444 ov = atomic_long_read(&cache->ccc_lru_left);
445 if (ov == 0)
446 break;
447
448 nv = ov > diff ? ov - diff : 0;
449 rc = atomic_long_cmpxchg(&cache->ccc_lru_left, ov, nv);
450 if (likely(ov == rc)) {
451 diff -= ov - nv;
452 nrpages += ov - nv;
453 break;
454 }
455 } while (1);
456
457 if (diff <= 0)
458 break;
459
460 if (!sbi->ll_dt_exp) {
461 rc = 0;
462 goto out;
463 }
464
465
466 tmp = diff << 1;
467 rc = obd_set_info_async(env, sbi->ll_dt_exp,
468 sizeof(KEY_CACHE_LRU_SHRINK),
469 KEY_CACHE_LRU_SHRINK,
470 sizeof(tmp), &tmp, NULL);
471 if (rc < 0)
472 break;
473 }
474 cl_env_put(env, &refcheck);
475
476out:
477 if (rc >= 0) {
478 spin_lock(&sbi->ll_lock);
479 cache->ccc_lru_max = pages_number;
480 spin_unlock(&sbi->ll_lock);
481 rc = count;
482 } else {
483 atomic_long_add(nrpages, &cache->ccc_lru_left);
484 }
485 return rc;
486}
487
488LPROC_SEQ_FOPS(ll_max_cached_mb);
489
490static ssize_t checksum_pages_show(struct kobject *kobj, struct attribute *attr,
491 char *buf)
492{
493 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
494 ll_kobj);
495
496 return sprintf(buf, "%u\n", (sbi->ll_flags & LL_SBI_CHECKSUM) ? 1 : 0);
497}
498
499static ssize_t checksum_pages_store(struct kobject *kobj,
500 struct attribute *attr,
501 const char *buffer,
502 size_t count)
503{
504 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
505 ll_kobj);
506 int rc;
507 unsigned long val;
508
509 if (!sbi->ll_dt_exp)
510
511 return -EAGAIN;
512
513 rc = kstrtoul(buffer, 10, &val);
514 if (rc)
515 return rc;
516 if (val)
517 sbi->ll_flags |= LL_SBI_CHECKSUM;
518 else
519 sbi->ll_flags &= ~LL_SBI_CHECKSUM;
520
521 rc = obd_set_info_async(NULL, sbi->ll_dt_exp, sizeof(KEY_CHECKSUM),
522 KEY_CHECKSUM, sizeof(val), &val, NULL);
523 if (rc)
524 CWARN("Failed to set OSC checksum flags: %d\n", rc);
525
526 return count;
527}
528LUSTRE_RW_ATTR(checksum_pages);
529
530static ssize_t ll_rd_track_id(struct kobject *kobj, char *buf,
531 enum stats_track_type type)
532{
533 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
534 ll_kobj);
535
536 if (sbi->ll_stats_track_type == type)
537 return sprintf(buf, "%d\n", sbi->ll_stats_track_id);
538 else if (sbi->ll_stats_track_type == STATS_TRACK_ALL)
539 return sprintf(buf, "0 (all)\n");
540 else
541 return sprintf(buf, "untracked\n");
542}
543
544static ssize_t ll_wr_track_id(struct kobject *kobj, const char *buffer,
545 size_t count,
546 enum stats_track_type type)
547{
548 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
549 ll_kobj);
550 int rc;
551 unsigned long pid;
552
553 rc = kstrtoul(buffer, 10, &pid);
554 if (rc)
555 return rc;
556 sbi->ll_stats_track_id = pid;
557 if (pid == 0)
558 sbi->ll_stats_track_type = STATS_TRACK_ALL;
559 else
560 sbi->ll_stats_track_type = type;
561 lprocfs_clear_stats(sbi->ll_stats);
562 return count;
563}
564
565static ssize_t stats_track_pid_show(struct kobject *kobj,
566 struct attribute *attr,
567 char *buf)
568{
569 return ll_rd_track_id(kobj, buf, STATS_TRACK_PID);
570}
571
572static ssize_t stats_track_pid_store(struct kobject *kobj,
573 struct attribute *attr,
574 const char *buffer,
575 size_t count)
576{
577 return ll_wr_track_id(kobj, buffer, count, STATS_TRACK_PID);
578}
579LUSTRE_RW_ATTR(stats_track_pid);
580
581static ssize_t stats_track_ppid_show(struct kobject *kobj,
582 struct attribute *attr,
583 char *buf)
584{
585 return ll_rd_track_id(kobj, buf, STATS_TRACK_PPID);
586}
587
588static ssize_t stats_track_ppid_store(struct kobject *kobj,
589 struct attribute *attr,
590 const char *buffer,
591 size_t count)
592{
593 return ll_wr_track_id(kobj, buffer, count, STATS_TRACK_PPID);
594}
595LUSTRE_RW_ATTR(stats_track_ppid);
596
597static ssize_t stats_track_gid_show(struct kobject *kobj,
598 struct attribute *attr,
599 char *buf)
600{
601 return ll_rd_track_id(kobj, buf, STATS_TRACK_GID);
602}
603
604static ssize_t stats_track_gid_store(struct kobject *kobj,
605 struct attribute *attr,
606 const char *buffer,
607 size_t count)
608{
609 return ll_wr_track_id(kobj, buffer, count, STATS_TRACK_GID);
610}
611LUSTRE_RW_ATTR(stats_track_gid);
612
613static ssize_t statahead_max_show(struct kobject *kobj,
614 struct attribute *attr,
615 char *buf)
616{
617 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
618 ll_kobj);
619
620 return sprintf(buf, "%u\n", sbi->ll_sa_max);
621}
622
623static ssize_t statahead_max_store(struct kobject *kobj,
624 struct attribute *attr,
625 const char *buffer,
626 size_t count)
627{
628 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
629 ll_kobj);
630 int rc;
631 unsigned long val;
632
633 rc = kstrtoul(buffer, 10, &val);
634 if (rc)
635 return rc;
636
637 if (val <= LL_SA_RPC_MAX)
638 sbi->ll_sa_max = val;
639 else
640 CERROR("Bad statahead_max value %lu. Valid values are in the range [0, %d]\n",
641 val, LL_SA_RPC_MAX);
642
643 return count;
644}
645LUSTRE_RW_ATTR(statahead_max);
646
647static ssize_t statahead_agl_show(struct kobject *kobj,
648 struct attribute *attr,
649 char *buf)
650{
651 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
652 ll_kobj);
653
654 return sprintf(buf, "%u\n", sbi->ll_flags & LL_SBI_AGL_ENABLED ? 1 : 0);
655}
656
657static ssize_t statahead_agl_store(struct kobject *kobj,
658 struct attribute *attr,
659 const char *buffer,
660 size_t count)
661{
662 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
663 ll_kobj);
664 int rc;
665 unsigned long val;
666
667 rc = kstrtoul(buffer, 10, &val);
668 if (rc)
669 return rc;
670
671 if (val)
672 sbi->ll_flags |= LL_SBI_AGL_ENABLED;
673 else
674 sbi->ll_flags &= ~LL_SBI_AGL_ENABLED;
675
676 return count;
677}
678LUSTRE_RW_ATTR(statahead_agl);
679
680static int ll_statahead_stats_seq_show(struct seq_file *m, void *v)
681{
682 struct super_block *sb = m->private;
683 struct ll_sb_info *sbi = ll_s2sbi(sb);
684
685 seq_printf(m,
686 "statahead total: %u\n"
687 "statahead wrong: %u\n"
688 "agl total: %u\n",
689 atomic_read(&sbi->ll_sa_total),
690 atomic_read(&sbi->ll_sa_wrong),
691 atomic_read(&sbi->ll_agl_total));
692 return 0;
693}
694
695LPROC_SEQ_FOPS_RO(ll_statahead_stats);
696
697static ssize_t lazystatfs_show(struct kobject *kobj,
698 struct attribute *attr,
699 char *buf)
700{
701 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
702 ll_kobj);
703
704 return sprintf(buf, "%u\n", sbi->ll_flags & LL_SBI_LAZYSTATFS ? 1 : 0);
705}
706
707static ssize_t lazystatfs_store(struct kobject *kobj,
708 struct attribute *attr,
709 const char *buffer,
710 size_t count)
711{
712 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
713 ll_kobj);
714 int rc;
715 unsigned long val;
716
717 rc = kstrtoul(buffer, 10, &val);
718 if (rc)
719 return rc;
720
721 if (val)
722 sbi->ll_flags |= LL_SBI_LAZYSTATFS;
723 else
724 sbi->ll_flags &= ~LL_SBI_LAZYSTATFS;
725
726 return count;
727}
728LUSTRE_RW_ATTR(lazystatfs);
729
730static ssize_t max_easize_show(struct kobject *kobj,
731 struct attribute *attr,
732 char *buf)
733{
734 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
735 ll_kobj);
736 unsigned int ealen;
737 int rc;
738
739 rc = ll_get_max_mdsize(sbi, &ealen);
740 if (rc)
741 return rc;
742
743 return sprintf(buf, "%u\n", ealen);
744}
745LUSTRE_RO_ATTR(max_easize);
746
747
748
749
750
751
752
753
754
755
756
757
758
759static ssize_t default_easize_show(struct kobject *kobj,
760 struct attribute *attr,
761 char *buf)
762{
763 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
764 ll_kobj);
765 unsigned int ealen;
766 int rc;
767
768 rc = ll_get_default_mdsize(sbi, &ealen);
769 if (rc)
770 return rc;
771
772 return sprintf(buf, "%u\n", ealen);
773}
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791static ssize_t default_easize_store(struct kobject *kobj,
792 struct attribute *attr,
793 const char *buffer,
794 size_t count)
795{
796 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
797 ll_kobj);
798 unsigned long val;
799 int rc;
800
801 rc = kstrtoul(buffer, 10, &val);
802 if (rc)
803 return rc;
804
805 rc = ll_set_default_mdsize(sbi, val);
806 if (rc)
807 return rc;
808
809 return count;
810}
811LUSTRE_RW_ATTR(default_easize);
812
813static int ll_sbi_flags_seq_show(struct seq_file *m, void *v)
814{
815 const char *str[] = LL_SBI_FLAGS;
816 struct super_block *sb = m->private;
817 int flags = ll_s2sbi(sb)->ll_flags;
818 int i = 0;
819
820 while (flags != 0) {
821 if (ARRAY_SIZE(str) <= i) {
822 CERROR("%s: Revise array LL_SBI_FLAGS to match sbi flags please.\n",
823 ll_get_fsname(sb, NULL, 0));
824 return -EINVAL;
825 }
826
827 if (flags & 0x1)
828 seq_printf(m, "%s ", str[i]);
829 flags >>= 1;
830 ++i;
831 }
832 seq_puts(m, "\b\n");
833 return 0;
834}
835
836LPROC_SEQ_FOPS_RO(ll_sbi_flags);
837
838static ssize_t xattr_cache_show(struct kobject *kobj,
839 struct attribute *attr,
840 char *buf)
841{
842 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
843 ll_kobj);
844
845 return sprintf(buf, "%u\n", sbi->ll_xattr_cache_enabled);
846}
847
848static ssize_t xattr_cache_store(struct kobject *kobj,
849 struct attribute *attr,
850 const char *buffer,
851 size_t count)
852{
853 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
854 ll_kobj);
855 int rc;
856 unsigned long val;
857
858 rc = kstrtoul(buffer, 10, &val);
859 if (rc)
860 return rc;
861
862 if (val != 0 && val != 1)
863 return -ERANGE;
864
865 if (val == 1 && !(sbi->ll_flags & LL_SBI_XATTR_CACHE))
866 return -ENOTSUPP;
867
868 sbi->ll_xattr_cache_enabled = val;
869
870 return count;
871}
872LUSTRE_RW_ATTR(xattr_cache);
873
874static int ll_unstable_stats_seq_show(struct seq_file *m, void *v)
875{
876 struct super_block *sb = m->private;
877 struct ll_sb_info *sbi = ll_s2sbi(sb);
878 struct cl_client_cache *cache = sbi->ll_cache;
879 long pages;
880 int mb;
881
882 pages = atomic_long_read(&cache->ccc_unstable_nr);
883 mb = (pages * PAGE_SIZE) >> 20;
884
885 seq_printf(m,
886 "unstable_check: %8d\n"
887 "unstable_pages: %12ld\n"
888 "unstable_mb: %8d\n",
889 cache->ccc_unstable_check, pages, mb);
890
891 return 0;
892}
893
894static ssize_t ll_unstable_stats_seq_write(struct file *file,
895 const char __user *buffer,
896 size_t count, loff_t *off)
897{
898 struct super_block *sb = ((struct seq_file *)file->private_data)->private;
899 struct ll_sb_info *sbi = ll_s2sbi(sb);
900 char kernbuf[128];
901 int val, rc;
902
903 if (!count)
904 return 0;
905 if (count >= sizeof(kernbuf))
906 return -EINVAL;
907
908 if (copy_from_user(kernbuf, buffer, count))
909 return -EFAULT;
910 kernbuf[count] = 0;
911
912 buffer += lprocfs_find_named_value(kernbuf, "unstable_check:", &count) -
913 kernbuf;
914 rc = lprocfs_write_helper(buffer, count, &val);
915 if (rc < 0)
916 return rc;
917
918
919 spin_lock(&sbi->ll_cache->ccc_lru_lock);
920 sbi->ll_cache->ccc_unstable_check = !!val;
921 spin_unlock(&sbi->ll_cache->ccc_lru_lock);
922
923 return count;
924}
925LPROC_SEQ_FOPS(ll_unstable_stats);
926
927static ssize_t root_squash_show(struct kobject *kobj, struct attribute *attr,
928 char *buf)
929{
930 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
931 ll_kobj);
932 struct root_squash_info *squash = &sbi->ll_squash;
933
934 return sprintf(buf, "%u:%u\n", squash->rsi_uid, squash->rsi_gid);
935}
936
937static ssize_t root_squash_store(struct kobject *kobj, struct attribute *attr,
938 const char *buffer, size_t count)
939{
940 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
941 ll_kobj);
942 struct root_squash_info *squash = &sbi->ll_squash;
943
944 return lprocfs_wr_root_squash(buffer, count, squash,
945 ll_get_fsname(sbi->ll_sb, NULL, 0));
946}
947LUSTRE_RW_ATTR(root_squash);
948
949static int ll_nosquash_nids_seq_show(struct seq_file *m, void *v)
950{
951 struct super_block *sb = m->private;
952 struct ll_sb_info *sbi = ll_s2sbi(sb);
953 struct root_squash_info *squash = &sbi->ll_squash;
954 int len;
955
956 down_read(&squash->rsi_sem);
957 if (!list_empty(&squash->rsi_nosquash_nids)) {
958 len = cfs_print_nidlist(m->buf + m->count, m->size - m->count,
959 &squash->rsi_nosquash_nids);
960 m->count += len;
961 seq_puts(m, "\n");
962 } else {
963 seq_puts(m, "NONE\n");
964 }
965 up_read(&squash->rsi_sem);
966
967 return 0;
968}
969
970static ssize_t ll_nosquash_nids_seq_write(struct file *file,
971 const char __user *buffer,
972 size_t count, loff_t *off)
973{
974 struct seq_file *m = file->private_data;
975 struct super_block *sb = m->private;
976 struct ll_sb_info *sbi = ll_s2sbi(sb);
977 struct root_squash_info *squash = &sbi->ll_squash;
978 int rc;
979
980 rc = lprocfs_wr_nosquash_nids(buffer, count, squash,
981 ll_get_fsname(sb, NULL, 0));
982 if (rc < 0)
983 return rc;
984
985 ll_compute_rootsquash_state(sbi);
986
987 return rc;
988}
989
990LPROC_SEQ_FOPS(ll_nosquash_nids);
991
992static struct lprocfs_vars lprocfs_llite_obd_vars[] = {
993
994 { "site", &ll_site_stats_fops, NULL, 0 },
995
996 { "max_cached_mb", &ll_max_cached_mb_fops, NULL },
997 { "statahead_stats", &ll_statahead_stats_fops, NULL, 0 },
998 { "unstable_stats", &ll_unstable_stats_fops, NULL },
999 { "sbi_flags", &ll_sbi_flags_fops, NULL, 0 },
1000 { .name = "nosquash_nids",
1001 .fops = &ll_nosquash_nids_fops },
1002 { NULL }
1003};
1004
1005#define MAX_STRING_SIZE 128
1006
1007static struct attribute *llite_attrs[] = {
1008 &lustre_attr_blocksize.attr,
1009 &lustre_attr_kbytestotal.attr,
1010 &lustre_attr_kbytesfree.attr,
1011 &lustre_attr_kbytesavail.attr,
1012 &lustre_attr_filestotal.attr,
1013 &lustre_attr_filesfree.attr,
1014 &lustre_attr_client_type.attr,
1015 &lustre_attr_fstype.attr,
1016 &lustre_attr_uuid.attr,
1017 &lustre_attr_max_read_ahead_mb.attr,
1018 &lustre_attr_max_read_ahead_per_file_mb.attr,
1019 &lustre_attr_max_read_ahead_whole_mb.attr,
1020 &lustre_attr_checksum_pages.attr,
1021 &lustre_attr_stats_track_pid.attr,
1022 &lustre_attr_stats_track_ppid.attr,
1023 &lustre_attr_stats_track_gid.attr,
1024 &lustre_attr_statahead_max.attr,
1025 &lustre_attr_statahead_agl.attr,
1026 &lustre_attr_lazystatfs.attr,
1027 &lustre_attr_max_easize.attr,
1028 &lustre_attr_default_easize.attr,
1029 &lustre_attr_xattr_cache.attr,
1030 &lustre_attr_root_squash.attr,
1031 NULL,
1032};
1033
1034static void llite_sb_release(struct kobject *kobj)
1035{
1036 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
1037 ll_kobj);
1038 complete(&sbi->ll_kobj_unregister);
1039}
1040
1041static struct kobj_type llite_ktype = {
1042 .default_attrs = llite_attrs,
1043 .sysfs_ops = &lustre_sysfs_ops,
1044 .release = llite_sb_release,
1045};
1046
1047static const struct llite_file_opcode {
1048 __u32 opcode;
1049 __u32 type;
1050 const char *opname;
1051} llite_opcode_table[LPROC_LL_FILE_OPCODES] = {
1052
1053 { LPROC_LL_DIRTY_HITS, LPROCFS_TYPE_REGS, "dirty_pages_hits" },
1054 { LPROC_LL_DIRTY_MISSES, LPROCFS_TYPE_REGS, "dirty_pages_misses" },
1055 { LPROC_LL_READ_BYTES, LPROCFS_CNTR_AVGMINMAX | LPROCFS_TYPE_BYTES,
1056 "read_bytes" },
1057 { LPROC_LL_WRITE_BYTES, LPROCFS_CNTR_AVGMINMAX | LPROCFS_TYPE_BYTES,
1058 "write_bytes" },
1059 { LPROC_LL_BRW_READ, LPROCFS_CNTR_AVGMINMAX | LPROCFS_TYPE_PAGES,
1060 "brw_read" },
1061 { LPROC_LL_BRW_WRITE, LPROCFS_CNTR_AVGMINMAX | LPROCFS_TYPE_PAGES,
1062 "brw_write" },
1063 { LPROC_LL_OSC_READ, LPROCFS_CNTR_AVGMINMAX | LPROCFS_TYPE_BYTES,
1064 "osc_read" },
1065 { LPROC_LL_OSC_WRITE, LPROCFS_CNTR_AVGMINMAX | LPROCFS_TYPE_BYTES,
1066 "osc_write" },
1067 { LPROC_LL_IOCTL, LPROCFS_TYPE_REGS, "ioctl" },
1068 { LPROC_LL_OPEN, LPROCFS_TYPE_REGS, "open" },
1069 { LPROC_LL_RELEASE, LPROCFS_TYPE_REGS, "close" },
1070 { LPROC_LL_MAP, LPROCFS_TYPE_REGS, "mmap" },
1071 { LPROC_LL_LLSEEK, LPROCFS_TYPE_REGS, "seek" },
1072 { LPROC_LL_FSYNC, LPROCFS_TYPE_REGS, "fsync" },
1073 { LPROC_LL_READDIR, LPROCFS_TYPE_REGS, "readdir" },
1074
1075 { LPROC_LL_SETATTR, LPROCFS_TYPE_REGS, "setattr" },
1076 { LPROC_LL_TRUNC, LPROCFS_TYPE_REGS, "truncate" },
1077 { LPROC_LL_FLOCK, LPROCFS_TYPE_REGS, "flock" },
1078 { LPROC_LL_GETATTR, LPROCFS_TYPE_REGS, "getattr" },
1079
1080 { LPROC_LL_CREATE, LPROCFS_TYPE_REGS, "create" },
1081 { LPROC_LL_LINK, LPROCFS_TYPE_REGS, "link" },
1082 { LPROC_LL_UNLINK, LPROCFS_TYPE_REGS, "unlink" },
1083 { LPROC_LL_SYMLINK, LPROCFS_TYPE_REGS, "symlink" },
1084 { LPROC_LL_MKDIR, LPROCFS_TYPE_REGS, "mkdir" },
1085 { LPROC_LL_RMDIR, LPROCFS_TYPE_REGS, "rmdir" },
1086 { LPROC_LL_MKNOD, LPROCFS_TYPE_REGS, "mknod" },
1087 { LPROC_LL_RENAME, LPROCFS_TYPE_REGS, "rename" },
1088
1089 { LPROC_LL_STAFS, LPROCFS_TYPE_REGS, "statfs" },
1090 { LPROC_LL_ALLOC_INODE, LPROCFS_TYPE_REGS, "alloc_inode" },
1091 { LPROC_LL_SETXATTR, LPROCFS_TYPE_REGS, "setxattr" },
1092 { LPROC_LL_GETXATTR, LPROCFS_TYPE_REGS, "getxattr" },
1093 { LPROC_LL_GETXATTR_HITS, LPROCFS_TYPE_REGS, "getxattr_hits" },
1094 { LPROC_LL_LISTXATTR, LPROCFS_TYPE_REGS, "listxattr" },
1095 { LPROC_LL_REMOVEXATTR, LPROCFS_TYPE_REGS, "removexattr" },
1096 { LPROC_LL_INODE_PERM, LPROCFS_TYPE_REGS, "inode_permission" },
1097};
1098
1099void ll_stats_ops_tally(struct ll_sb_info *sbi, int op, int count)
1100{
1101 if (!sbi->ll_stats)
1102 return;
1103 if (sbi->ll_stats_track_type == STATS_TRACK_ALL)
1104 lprocfs_counter_add(sbi->ll_stats, op, count);
1105 else if (sbi->ll_stats_track_type == STATS_TRACK_PID &&
1106 sbi->ll_stats_track_id == current->pid)
1107 lprocfs_counter_add(sbi->ll_stats, op, count);
1108 else if (sbi->ll_stats_track_type == STATS_TRACK_PPID &&
1109 sbi->ll_stats_track_id == current->real_parent->pid)
1110 lprocfs_counter_add(sbi->ll_stats, op, count);
1111 else if (sbi->ll_stats_track_type == STATS_TRACK_GID &&
1112 sbi->ll_stats_track_id ==
1113 from_kgid(&init_user_ns, current_gid()))
1114 lprocfs_counter_add(sbi->ll_stats, op, count);
1115}
1116EXPORT_SYMBOL(ll_stats_ops_tally);
1117
1118static const char *ra_stat_string[] = {
1119 [RA_STAT_HIT] = "hits",
1120 [RA_STAT_MISS] = "misses",
1121 [RA_STAT_DISTANT_READPAGE] = "readpage not consecutive",
1122 [RA_STAT_MISS_IN_WINDOW] = "miss inside window",
1123 [RA_STAT_FAILED_GRAB_PAGE] = "failed grab_cache_page",
1124 [RA_STAT_FAILED_MATCH] = "failed lock match",
1125 [RA_STAT_DISCARDED] = "read but discarded",
1126 [RA_STAT_ZERO_LEN] = "zero length file",
1127 [RA_STAT_ZERO_WINDOW] = "zero size window",
1128 [RA_STAT_EOF] = "read-ahead to EOF",
1129 [RA_STAT_MAX_IN_FLIGHT] = "hit max r-a issue",
1130 [RA_STAT_WRONG_GRAB_PAGE] = "wrong page from grab_cache_page",
1131 [RA_STAT_FAILED_REACH_END] = "failed to reach end"
1132};
1133
1134int ldebugfs_register_mountpoint(struct dentry *parent,
1135 struct super_block *sb, char *osc, char *mdc)
1136{
1137 struct lustre_sb_info *lsi = s2lsi(sb);
1138 struct ll_sb_info *sbi = ll_s2sbi(sb);
1139 struct obd_device *obd;
1140 struct dentry *dir;
1141 char name[MAX_STRING_SIZE + 1], *ptr;
1142 int err, id, len, rc;
1143
1144 name[MAX_STRING_SIZE] = '\0';
1145
1146 LASSERT(sbi);
1147 LASSERT(mdc);
1148 LASSERT(osc);
1149
1150
1151 len = strlen(lsi->lsi_lmd->lmd_profile);
1152 ptr = strrchr(lsi->lsi_lmd->lmd_profile, '-');
1153 if (ptr && (strcmp(ptr, "-client") == 0))
1154 len -= 7;
1155
1156
1157 snprintf(name, MAX_STRING_SIZE, "%.*s-%p", len,
1158 lsi->lsi_lmd->lmd_profile, sb);
1159
1160 dir = ldebugfs_register(name, parent, NULL, NULL);
1161 if (IS_ERR_OR_NULL(dir)) {
1162 err = dir ? PTR_ERR(dir) : -ENOMEM;
1163 sbi->ll_debugfs_entry = NULL;
1164 return err;
1165 }
1166 sbi->ll_debugfs_entry = dir;
1167
1168 rc = ldebugfs_seq_create(sbi->ll_debugfs_entry, "dump_page_cache", 0444,
1169 &vvp_dump_pgcache_file_ops, sbi);
1170 if (rc)
1171 CWARN("Error adding the dump_page_cache file\n");
1172
1173 rc = ldebugfs_seq_create(sbi->ll_debugfs_entry, "extents_stats", 0644,
1174 &ll_rw_extents_stats_fops, sbi);
1175 if (rc)
1176 CWARN("Error adding the extent_stats file\n");
1177
1178 rc = ldebugfs_seq_create(sbi->ll_debugfs_entry,
1179 "extents_stats_per_process",
1180 0644, &ll_rw_extents_stats_pp_fops, sbi);
1181 if (rc)
1182 CWARN("Error adding the extents_stats_per_process file\n");
1183
1184 rc = ldebugfs_seq_create(sbi->ll_debugfs_entry, "offset_stats", 0644,
1185 &ll_rw_offset_stats_fops, sbi);
1186 if (rc)
1187 CWARN("Error adding the offset_stats file\n");
1188
1189
1190 sbi->ll_stats = lprocfs_alloc_stats(LPROC_LL_FILE_OPCODES,
1191 LPROCFS_STATS_FLAG_NONE);
1192 if (!sbi->ll_stats) {
1193 err = -ENOMEM;
1194 goto out;
1195 }
1196
1197 for (id = 0; id < LPROC_LL_FILE_OPCODES; id++) {
1198 __u32 type = llite_opcode_table[id].type;
1199 void *ptr = NULL;
1200
1201 if (type & LPROCFS_TYPE_REGS)
1202 ptr = "regs";
1203 else if (type & LPROCFS_TYPE_BYTES)
1204 ptr = "bytes";
1205 else if (type & LPROCFS_TYPE_PAGES)
1206 ptr = "pages";
1207 lprocfs_counter_init(sbi->ll_stats,
1208 llite_opcode_table[id].opcode,
1209 (type & LPROCFS_CNTR_AVGMINMAX),
1210 llite_opcode_table[id].opname, ptr);
1211 }
1212 err = ldebugfs_register_stats(sbi->ll_debugfs_entry, "stats",
1213 sbi->ll_stats);
1214 if (err)
1215 goto out;
1216
1217 sbi->ll_ra_stats = lprocfs_alloc_stats(ARRAY_SIZE(ra_stat_string),
1218 LPROCFS_STATS_FLAG_NONE);
1219 if (!sbi->ll_ra_stats) {
1220 err = -ENOMEM;
1221 goto out;
1222 }
1223
1224 for (id = 0; id < ARRAY_SIZE(ra_stat_string); id++)
1225 lprocfs_counter_init(sbi->ll_ra_stats, id, 0,
1226 ra_stat_string[id], "pages");
1227
1228 err = ldebugfs_register_stats(sbi->ll_debugfs_entry, "read_ahead_stats",
1229 sbi->ll_ra_stats);
1230 if (err)
1231 goto out;
1232
1233 err = ldebugfs_add_vars(sbi->ll_debugfs_entry,
1234 lprocfs_llite_obd_vars, sb);
1235 if (err)
1236 goto out;
1237
1238 sbi->ll_kobj.kset = llite_kset;
1239 init_completion(&sbi->ll_kobj_unregister);
1240 err = kobject_init_and_add(&sbi->ll_kobj, &llite_ktype, NULL,
1241 "%s", name);
1242 if (err)
1243 goto out;
1244
1245
1246 obd = class_name2obd(mdc);
1247
1248 err = sysfs_create_link(&sbi->ll_kobj, &obd->obd_kobj,
1249 obd->obd_type->typ_name);
1250 if (err)
1251 goto out;
1252
1253
1254 obd = class_name2obd(osc);
1255
1256 err = sysfs_create_link(&sbi->ll_kobj, &obd->obd_kobj,
1257 obd->obd_type->typ_name);
1258out:
1259 if (err) {
1260 ldebugfs_remove(&sbi->ll_debugfs_entry);
1261 lprocfs_free_stats(&sbi->ll_ra_stats);
1262 lprocfs_free_stats(&sbi->ll_stats);
1263 }
1264 return err;
1265}
1266
1267void ldebugfs_unregister_mountpoint(struct ll_sb_info *sbi)
1268{
1269 if (sbi->ll_debugfs_entry) {
1270 ldebugfs_remove(&sbi->ll_debugfs_entry);
1271 kobject_put(&sbi->ll_kobj);
1272 wait_for_completion(&sbi->ll_kobj_unregister);
1273 lprocfs_free_stats(&sbi->ll_ra_stats);
1274 lprocfs_free_stats(&sbi->ll_stats);
1275 }
1276}
1277
1278#undef MAX_STRING_SIZE
1279
1280#define pct(a, b) (b ? a * 100 / b : 0)
1281
1282static void ll_display_extents_info(struct ll_rw_extents_info *io_extents,
1283 struct seq_file *seq, int which)
1284{
1285 unsigned long read_tot = 0, write_tot = 0, read_cum, write_cum;
1286 unsigned long start, end, r, w;
1287 char *unitp = "KMGTPEZY";
1288 int i, units = 10;
1289 struct per_process_info *pp_info = &io_extents->pp_extents[which];
1290
1291 read_cum = 0;
1292 write_cum = 0;
1293 start = 0;
1294
1295 for (i = 0; i < LL_HIST_MAX; i++) {
1296 read_tot += pp_info->pp_r_hist.oh_buckets[i];
1297 write_tot += pp_info->pp_w_hist.oh_buckets[i];
1298 }
1299
1300 for (i = 0; i < LL_HIST_MAX; i++) {
1301 r = pp_info->pp_r_hist.oh_buckets[i];
1302 w = pp_info->pp_w_hist.oh_buckets[i];
1303 read_cum += r;
1304 write_cum += w;
1305 end = 1 << (i + LL_HIST_START - units);
1306 seq_printf(seq, "%4lu%c - %4lu%c%c: %14lu %4lu %4lu | %14lu %4lu %4lu\n",
1307 start, *unitp, end, *unitp,
1308 (i == LL_HIST_MAX - 1) ? '+' : ' ',
1309 r, pct(r, read_tot), pct(read_cum, read_tot),
1310 w, pct(w, write_tot), pct(write_cum, write_tot));
1311 start = end;
1312 if (start == 1 << 10) {
1313 start = 1;
1314 units += 10;
1315 unitp++;
1316 }
1317 if (read_cum == read_tot && write_cum == write_tot)
1318 break;
1319 }
1320}
1321
1322static int ll_rw_extents_stats_pp_seq_show(struct seq_file *seq, void *v)
1323{
1324 struct timespec64 now;
1325 struct ll_sb_info *sbi = seq->private;
1326 struct ll_rw_extents_info *io_extents = &sbi->ll_rw_extents_info;
1327 int k;
1328
1329 ktime_get_real_ts64(&now);
1330
1331 if (!sbi->ll_rw_stats_on) {
1332 seq_printf(seq, "disabled\n"
1333 "write anything in this file to activate, then 0 or \"[D/d]isabled\" to deactivate\n");
1334 return 0;
1335 }
1336 seq_printf(seq, "snapshot_time: %llu.%09lu (secs.usecs)\n",
1337 (s64)now.tv_sec, (unsigned long)now.tv_nsec);
1338 seq_printf(seq, "%15s %19s | %20s\n", " ", "read", "write");
1339 seq_printf(seq, "%13s %14s %4s %4s | %14s %4s %4s\n",
1340 "extents", "calls", "%", "cum%",
1341 "calls", "%", "cum%");
1342 spin_lock(&sbi->ll_pp_extent_lock);
1343 for (k = 0; k < LL_PROCESS_HIST_MAX; k++) {
1344 if (io_extents->pp_extents[k].pid != 0) {
1345 seq_printf(seq, "\nPID: %d\n",
1346 io_extents->pp_extents[k].pid);
1347 ll_display_extents_info(io_extents, seq, k);
1348 }
1349 }
1350 spin_unlock(&sbi->ll_pp_extent_lock);
1351 return 0;
1352}
1353
1354static ssize_t ll_rw_extents_stats_pp_seq_write(struct file *file,
1355 const char __user *buf,
1356 size_t len,
1357 loff_t *off)
1358{
1359 struct seq_file *seq = file->private_data;
1360 struct ll_sb_info *sbi = seq->private;
1361 struct ll_rw_extents_info *io_extents = &sbi->ll_rw_extents_info;
1362 int i;
1363 int value = 1, rc = 0;
1364
1365 if (len == 0)
1366 return -EINVAL;
1367
1368 rc = lprocfs_write_helper(buf, len, &value);
1369 if (rc < 0 && len < 16) {
1370 char kernbuf[16];
1371
1372 if (copy_from_user(kernbuf, buf, len))
1373 return -EFAULT;
1374 kernbuf[len] = 0;
1375
1376 if (kernbuf[len - 1] == '\n')
1377 kernbuf[len - 1] = 0;
1378
1379 if (strcmp(kernbuf, "disabled") == 0 ||
1380 strcmp(kernbuf, "Disabled") == 0)
1381 value = 0;
1382 }
1383
1384 if (value == 0)
1385 sbi->ll_rw_stats_on = 0;
1386 else
1387 sbi->ll_rw_stats_on = 1;
1388
1389 spin_lock(&sbi->ll_pp_extent_lock);
1390 for (i = 0; i < LL_PROCESS_HIST_MAX; i++) {
1391 io_extents->pp_extents[i].pid = 0;
1392 lprocfs_oh_clear(&io_extents->pp_extents[i].pp_r_hist);
1393 lprocfs_oh_clear(&io_extents->pp_extents[i].pp_w_hist);
1394 }
1395 spin_unlock(&sbi->ll_pp_extent_lock);
1396 return len;
1397}
1398
1399LPROC_SEQ_FOPS(ll_rw_extents_stats_pp);
1400
1401static int ll_rw_extents_stats_seq_show(struct seq_file *seq, void *v)
1402{
1403 struct timespec64 now;
1404 struct ll_sb_info *sbi = seq->private;
1405 struct ll_rw_extents_info *io_extents = &sbi->ll_rw_extents_info;
1406
1407 ktime_get_real_ts64(&now);
1408
1409 if (!sbi->ll_rw_stats_on) {
1410 seq_printf(seq, "disabled\n"
1411 "write anything in this file to activate, then 0 or \"[D/d]isabled\" to deactivate\n");
1412 return 0;
1413 }
1414 seq_printf(seq, "snapshot_time: %llu.%09lu (secs.usecs)\n",
1415 (u64)now.tv_sec, (unsigned long)now.tv_nsec);
1416
1417 seq_printf(seq, "%15s %19s | %20s\n", " ", "read", "write");
1418 seq_printf(seq, "%13s %14s %4s %4s | %14s %4s %4s\n",
1419 "extents", "calls", "%", "cum%",
1420 "calls", "%", "cum%");
1421 spin_lock(&sbi->ll_lock);
1422 ll_display_extents_info(io_extents, seq, LL_PROCESS_HIST_MAX);
1423 spin_unlock(&sbi->ll_lock);
1424
1425 return 0;
1426}
1427
1428static ssize_t ll_rw_extents_stats_seq_write(struct file *file,
1429 const char __user *buf,
1430 size_t len, loff_t *off)
1431{
1432 struct seq_file *seq = file->private_data;
1433 struct ll_sb_info *sbi = seq->private;
1434 struct ll_rw_extents_info *io_extents = &sbi->ll_rw_extents_info;
1435 int i;
1436 int value = 1, rc = 0;
1437
1438 if (len == 0)
1439 return -EINVAL;
1440
1441 rc = lprocfs_write_helper(buf, len, &value);
1442 if (rc < 0 && len < 16) {
1443 char kernbuf[16];
1444
1445 if (copy_from_user(kernbuf, buf, len))
1446 return -EFAULT;
1447 kernbuf[len] = 0;
1448
1449 if (kernbuf[len - 1] == '\n')
1450 kernbuf[len - 1] = 0;
1451
1452 if (strcmp(kernbuf, "disabled") == 0 ||
1453 strcmp(kernbuf, "Disabled") == 0)
1454 value = 0;
1455 }
1456
1457 if (value == 0)
1458 sbi->ll_rw_stats_on = 0;
1459 else
1460 sbi->ll_rw_stats_on = 1;
1461
1462 spin_lock(&sbi->ll_pp_extent_lock);
1463 for (i = 0; i <= LL_PROCESS_HIST_MAX; i++) {
1464 io_extents->pp_extents[i].pid = 0;
1465 lprocfs_oh_clear(&io_extents->pp_extents[i].pp_r_hist);
1466 lprocfs_oh_clear(&io_extents->pp_extents[i].pp_w_hist);
1467 }
1468 spin_unlock(&sbi->ll_pp_extent_lock);
1469
1470 return len;
1471}
1472
1473LPROC_SEQ_FOPS(ll_rw_extents_stats);
1474
1475void ll_rw_stats_tally(struct ll_sb_info *sbi, pid_t pid,
1476 struct ll_file_data *file, loff_t pos,
1477 size_t count, int rw)
1478{
1479 int i, cur = -1;
1480 struct ll_rw_process_info *process;
1481 struct ll_rw_process_info *offset;
1482 int *off_count = &sbi->ll_rw_offset_entry_count;
1483 int *process_count = &sbi->ll_offset_process_count;
1484 struct ll_rw_extents_info *io_extents = &sbi->ll_rw_extents_info;
1485
1486 if (!sbi->ll_rw_stats_on)
1487 return;
1488 process = sbi->ll_rw_process_info;
1489 offset = sbi->ll_rw_offset_info;
1490
1491 spin_lock(&sbi->ll_pp_extent_lock);
1492
1493 for (i = 0; i < LL_PROCESS_HIST_MAX; i++) {
1494 if (io_extents->pp_extents[i].pid == pid) {
1495 cur = i;
1496 break;
1497 }
1498 }
1499
1500 if (cur == -1) {
1501
1502 sbi->ll_extent_process_count =
1503 (sbi->ll_extent_process_count + 1) % LL_PROCESS_HIST_MAX;
1504 cur = sbi->ll_extent_process_count;
1505 io_extents->pp_extents[cur].pid = pid;
1506 lprocfs_oh_clear(&io_extents->pp_extents[cur].pp_r_hist);
1507 lprocfs_oh_clear(&io_extents->pp_extents[cur].pp_w_hist);
1508 }
1509
1510 for (i = 0; (count >= (1 << LL_HIST_START << i)) &&
1511 (i < (LL_HIST_MAX - 1)); i++)
1512 ;
1513 if (rw == 0) {
1514 io_extents->pp_extents[cur].pp_r_hist.oh_buckets[i]++;
1515 io_extents->pp_extents[LL_PROCESS_HIST_MAX].pp_r_hist.oh_buckets[i]++;
1516 } else {
1517 io_extents->pp_extents[cur].pp_w_hist.oh_buckets[i]++;
1518 io_extents->pp_extents[LL_PROCESS_HIST_MAX].pp_w_hist.oh_buckets[i]++;
1519 }
1520 spin_unlock(&sbi->ll_pp_extent_lock);
1521
1522 spin_lock(&sbi->ll_process_lock);
1523
1524 for (i = 0; i < LL_PROCESS_HIST_MAX; i++) {
1525 if (process[i].rw_pid == pid) {
1526 if (process[i].rw_last_file != file) {
1527 process[i].rw_range_start = pos;
1528 process[i].rw_last_file_pos = pos + count;
1529 process[i].rw_smallest_extent = count;
1530 process[i].rw_largest_extent = count;
1531 process[i].rw_offset = 0;
1532 process[i].rw_last_file = file;
1533 spin_unlock(&sbi->ll_process_lock);
1534 return;
1535 }
1536 if (process[i].rw_last_file_pos != pos) {
1537 *off_count =
1538 (*off_count + 1) % LL_OFFSET_HIST_MAX;
1539 offset[*off_count].rw_op = process[i].rw_op;
1540 offset[*off_count].rw_pid = pid;
1541 offset[*off_count].rw_range_start =
1542 process[i].rw_range_start;
1543 offset[*off_count].rw_range_end =
1544 process[i].rw_last_file_pos;
1545 offset[*off_count].rw_smallest_extent =
1546 process[i].rw_smallest_extent;
1547 offset[*off_count].rw_largest_extent =
1548 process[i].rw_largest_extent;
1549 offset[*off_count].rw_offset =
1550 process[i].rw_offset;
1551 process[i].rw_op = rw;
1552 process[i].rw_range_start = pos;
1553 process[i].rw_smallest_extent = count;
1554 process[i].rw_largest_extent = count;
1555 process[i].rw_offset = pos -
1556 process[i].rw_last_file_pos;
1557 }
1558 if (process[i].rw_smallest_extent > count)
1559 process[i].rw_smallest_extent = count;
1560 if (process[i].rw_largest_extent < count)
1561 process[i].rw_largest_extent = count;
1562 process[i].rw_last_file_pos = pos + count;
1563 spin_unlock(&sbi->ll_process_lock);
1564 return;
1565 }
1566 }
1567 *process_count = (*process_count + 1) % LL_PROCESS_HIST_MAX;
1568 process[*process_count].rw_pid = pid;
1569 process[*process_count].rw_op = rw;
1570 process[*process_count].rw_range_start = pos;
1571 process[*process_count].rw_last_file_pos = pos + count;
1572 process[*process_count].rw_smallest_extent = count;
1573 process[*process_count].rw_largest_extent = count;
1574 process[*process_count].rw_offset = 0;
1575 process[*process_count].rw_last_file = file;
1576 spin_unlock(&sbi->ll_process_lock);
1577}
1578
1579static int ll_rw_offset_stats_seq_show(struct seq_file *seq, void *v)
1580{
1581 struct timespec64 now;
1582 struct ll_sb_info *sbi = seq->private;
1583 struct ll_rw_process_info *offset = sbi->ll_rw_offset_info;
1584 struct ll_rw_process_info *process = sbi->ll_rw_process_info;
1585 int i;
1586
1587 ktime_get_real_ts64(&now);
1588
1589 if (!sbi->ll_rw_stats_on) {
1590 seq_printf(seq, "disabled\n"
1591 "write anything in this file to activate, then 0 or \"[D/d]isabled\" to deactivate\n");
1592 return 0;
1593 }
1594 spin_lock(&sbi->ll_process_lock);
1595
1596 seq_printf(seq, "snapshot_time: %llu.%09lu (secs.usecs)\n",
1597 (s64)now.tv_sec, (unsigned long)now.tv_nsec);
1598 seq_printf(seq, "%3s %10s %14s %14s %17s %17s %14s\n",
1599 "R/W", "PID", "RANGE START", "RANGE END",
1600 "SMALLEST EXTENT", "LARGEST EXTENT", "OFFSET");
1601
1602 for (i = 0; i < LL_OFFSET_HIST_MAX; i++) {
1603 if (offset[i].rw_pid != 0)
1604 seq_printf(seq,
1605 "%3c %10d %14Lu %14Lu %17lu %17lu %14Lu",
1606 offset[i].rw_op == READ ? 'R' : 'W',
1607 offset[i].rw_pid,
1608 offset[i].rw_range_start,
1609 offset[i].rw_range_end,
1610 (unsigned long)offset[i].rw_smallest_extent,
1611 (unsigned long)offset[i].rw_largest_extent,
1612 offset[i].rw_offset);
1613 }
1614
1615 for (i = 0; i < LL_PROCESS_HIST_MAX; i++) {
1616 if (process[i].rw_pid != 0)
1617 seq_printf(seq,
1618 "%3c %10d %14Lu %14Lu %17lu %17lu %14Lu",
1619 process[i].rw_op == READ ? 'R' : 'W',
1620 process[i].rw_pid,
1621 process[i].rw_range_start,
1622 process[i].rw_last_file_pos,
1623 (unsigned long)process[i].rw_smallest_extent,
1624 (unsigned long)process[i].rw_largest_extent,
1625 process[i].rw_offset);
1626 }
1627 spin_unlock(&sbi->ll_process_lock);
1628
1629 return 0;
1630}
1631
1632static ssize_t ll_rw_offset_stats_seq_write(struct file *file,
1633 const char __user *buf,
1634 size_t len, loff_t *off)
1635{
1636 struct seq_file *seq = file->private_data;
1637 struct ll_sb_info *sbi = seq->private;
1638 struct ll_rw_process_info *process_info = sbi->ll_rw_process_info;
1639 struct ll_rw_process_info *offset_info = sbi->ll_rw_offset_info;
1640 int value = 1, rc = 0;
1641
1642 if (len == 0)
1643 return -EINVAL;
1644
1645 rc = lprocfs_write_helper(buf, len, &value);
1646
1647 if (rc < 0 && len < 16) {
1648 char kernbuf[16];
1649
1650 if (copy_from_user(kernbuf, buf, len))
1651 return -EFAULT;
1652 kernbuf[len] = 0;
1653
1654 if (kernbuf[len - 1] == '\n')
1655 kernbuf[len - 1] = 0;
1656
1657 if (strcmp(kernbuf, "disabled") == 0 ||
1658 strcmp(kernbuf, "Disabled") == 0)
1659 value = 0;
1660 }
1661
1662 if (value == 0)
1663 sbi->ll_rw_stats_on = 0;
1664 else
1665 sbi->ll_rw_stats_on = 1;
1666
1667 spin_lock(&sbi->ll_process_lock);
1668 sbi->ll_offset_process_count = 0;
1669 sbi->ll_rw_offset_entry_count = 0;
1670 memset(process_info, 0, sizeof(struct ll_rw_process_info) *
1671 LL_PROCESS_HIST_MAX);
1672 memset(offset_info, 0, sizeof(struct ll_rw_process_info) *
1673 LL_OFFSET_HIST_MAX);
1674 spin_unlock(&sbi->ll_process_lock);
1675
1676 return len;
1677}
1678
1679LPROC_SEQ_FOPS(ll_rw_offset_stats);
1680
1681void lprocfs_llite_init_vars(struct lprocfs_static_vars *lvars)
1682{
1683 lvars->obd_vars = lprocfs_llite_obd_vars;
1684}
1685