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