]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - drivers/staging/lustre/lustre/llite/lproc_llite.c
staging/lustre/llite: move /proc/fs/lustre/llite/uuid to sysfs
[mirror_ubuntu-hirsute-kernel.git] / drivers / staging / lustre / lustre / llite / lproc_llite.c
CommitLineData
d7e09d03
PT
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.sun.com/software/products/lustre/docs/GPLv2.pdf
19 *
20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21 * CA 95054 USA or visit www.sun.com if you need additional information or
22 * have any questions.
23 *
24 * GPL HEADER END
25 */
26/*
27 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Use is subject to license terms.
29 *
30 * Copyright (c) 2011, 2012, Intel Corporation.
31 */
32/*
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
35 */
36#define DEBUG_SUBSYSTEM S_LLITE
37
67a235f5
GKH
38#include "../include/lustre_lite.h"
39#include "../include/lprocfs_status.h"
d7e09d03 40#include <linux/seq_file.h>
67a235f5 41#include "../include/obd_support.h"
d7e09d03
PT
42
43#include "llite_internal.h"
2d95f10e 44#include "vvp_internal.h"
d7e09d03 45
d7e09d03 46/* /proc/lustre/llite mount point registration */
b9c98cfa
FF
47static struct file_operations ll_rw_extents_stats_fops;
48static struct file_operations ll_rw_extents_stats_pp_fops;
49static struct file_operations ll_rw_offset_stats_fops;
d7e09d03 50
364bcfc8
OD
51static ssize_t blocksize_show(struct kobject *kobj, struct attribute *attr,
52 char *buf)
d7e09d03 53{
364bcfc8
OD
54 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
55 ll_kobj);
d7e09d03
PT
56 struct obd_statfs osfs;
57 int rc;
58
364bcfc8 59 rc = ll_statfs_internal(sbi->ll_sb, &osfs,
d7e09d03
PT
60 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
61 OBD_STATFS_NODELAY);
73bb1da6 62 if (!rc)
364bcfc8 63 return sprintf(buf, "%u\n", osfs.os_bsize);
d7e09d03
PT
64
65 return rc;
66}
364bcfc8 67LUSTRE_RO_ATTR(blocksize);
d7e09d03 68
5804b11e
OD
69static ssize_t kbytestotal_show(struct kobject *kobj, struct attribute *attr,
70 char *buf)
d7e09d03 71{
5804b11e
OD
72 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
73 ll_kobj);
d7e09d03
PT
74 struct obd_statfs osfs;
75 int rc;
76
5804b11e 77 rc = ll_statfs_internal(sbi->ll_sb, &osfs,
d7e09d03
PT
78 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
79 OBD_STATFS_NODELAY);
80 if (!rc) {
81 __u32 blk_size = osfs.os_bsize >> 10;
82 __u64 result = osfs.os_blocks;
83
84 while (blk_size >>= 1)
85 result <<= 1;
86
5804b11e 87 rc = sprintf(buf, "%llu\n", result);
d7e09d03 88 }
ab75fb2d 89
d7e09d03 90 return rc;
d7e09d03 91}
5804b11e 92LUSTRE_RO_ATTR(kbytestotal);
d7e09d03 93
5804b11e
OD
94static ssize_t kbytesfree_show(struct kobject *kobj, struct attribute *attr,
95 char *buf)
d7e09d03 96{
5804b11e
OD
97 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
98 ll_kobj);
d7e09d03
PT
99 struct obd_statfs osfs;
100 int rc;
101
5804b11e 102 rc = ll_statfs_internal(sbi->ll_sb, &osfs,
d7e09d03
PT
103 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
104 OBD_STATFS_NODELAY);
105 if (!rc) {
106 __u32 blk_size = osfs.os_bsize >> 10;
107 __u64 result = osfs.os_bfree;
108
109 while (blk_size >>= 1)
110 result <<= 1;
111
5804b11e 112 rc = sprintf(buf, "%llu\n", result);
d7e09d03 113 }
ab75fb2d 114
d7e09d03
PT
115 return rc;
116}
5804b11e 117LUSTRE_RO_ATTR(kbytesfree);
d7e09d03 118
5804b11e
OD
119static ssize_t kbytesavail_show(struct kobject *kobj, struct attribute *attr,
120 char *buf)
d7e09d03 121{
5804b11e
OD
122 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
123 ll_kobj);
d7e09d03
PT
124 struct obd_statfs osfs;
125 int rc;
126
5804b11e 127 rc = ll_statfs_internal(sbi->ll_sb, &osfs,
d7e09d03
PT
128 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
129 OBD_STATFS_NODELAY);
130 if (!rc) {
131 __u32 blk_size = osfs.os_bsize >> 10;
132 __u64 result = osfs.os_bavail;
133
134 while (blk_size >>= 1)
135 result <<= 1;
136
5804b11e 137 rc = sprintf(buf, "%llu\n", result);
d7e09d03 138 }
ab75fb2d 139
d7e09d03
PT
140 return rc;
141}
5804b11e 142LUSTRE_RO_ATTR(kbytesavail);
d7e09d03 143
7267ec0d
OD
144static ssize_t filestotal_show(struct kobject *kobj, struct attribute *attr,
145 char *buf)
d7e09d03 146{
7267ec0d
OD
147 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
148 ll_kobj);
d7e09d03
PT
149 struct obd_statfs osfs;
150 int rc;
151
7267ec0d 152 rc = ll_statfs_internal(sbi->ll_sb, &osfs,
d7e09d03
PT
153 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
154 OBD_STATFS_NODELAY);
73bb1da6 155 if (!rc)
7267ec0d 156 return sprintf(buf, "%llu\n", osfs.os_files);
ab75fb2d 157
d7e09d03
PT
158 return rc;
159}
7267ec0d 160LUSTRE_RO_ATTR(filestotal);
d7e09d03 161
7267ec0d
OD
162static ssize_t filesfree_show(struct kobject *kobj, struct attribute *attr,
163 char *buf)
d7e09d03 164{
7267ec0d
OD
165 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
166 ll_kobj);
d7e09d03
PT
167 struct obd_statfs osfs;
168 int rc;
169
7267ec0d 170 rc = ll_statfs_internal(sbi->ll_sb, &osfs,
d7e09d03
PT
171 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
172 OBD_STATFS_NODELAY);
73bb1da6 173 if (!rc)
7267ec0d 174 return sprintf(buf, "%llu\n", osfs.os_ffree);
ab75fb2d 175
d7e09d03 176 return rc;
d7e09d03 177}
7267ec0d 178LUSTRE_RO_ATTR(filesfree);
d7e09d03 179
95e1b6b0
OD
180static ssize_t client_type_show(struct kobject *kobj, struct attribute *attr,
181 char *buf)
d7e09d03 182{
95e1b6b0
OD
183 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
184 ll_kobj);
d7e09d03 185
95e1b6b0
OD
186 return sprintf(buf, "%s client\n",
187 sbi->ll_flags & LL_SBI_RMT_CLIENT ? "remote" : "local");
d7e09d03 188}
95e1b6b0 189LUSTRE_RO_ATTR(client_type);
d7e09d03 190
0cee6676
OD
191static ssize_t fstype_show(struct kobject *kobj, struct attribute *attr,
192 char *buf)
d7e09d03 193{
0cee6676
OD
194 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
195 ll_kobj);
d7e09d03 196
0cee6676 197 return sprintf(buf, "%s\n", sbi->ll_sb->s_type->name);
d7e09d03 198}
0cee6676 199LUSTRE_RO_ATTR(fstype);
d7e09d03 200
ec55a629
OD
201static ssize_t uuid_show(struct kobject *kobj, struct attribute *attr,
202 char *buf)
d7e09d03 203{
ec55a629
OD
204 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
205 ll_kobj);
d7e09d03 206
ec55a629 207 return sprintf(buf, "%s\n", sbi->ll_sb_uuid.uuid);
d7e09d03 208}
ec55a629 209LUSTRE_RO_ATTR(uuid);
d7e09d03 210
73bb1da6 211static int ll_site_stats_seq_show(struct seq_file *m, void *v)
d7e09d03 212{
73bb1da6 213 struct super_block *sb = m->private;
d7e09d03
PT
214
215 /*
216 * See description of statistical counters in struct cl_site, and
217 * struct lu_site.
218 */
73bb1da6 219 return cl_site_stats_print(lu2cl_site(ll_s2sbi(sb)->ll_site), m);
d7e09d03 220}
73bb1da6 221LPROC_SEQ_FOPS_RO(ll_site_stats);
d7e09d03 222
73bb1da6 223static int ll_max_readahead_mb_seq_show(struct seq_file *m, void *v)
d7e09d03 224{
73bb1da6 225 struct super_block *sb = m->private;
d7e09d03
PT
226 struct ll_sb_info *sbi = ll_s2sbi(sb);
227 long pages_number;
228 int mult;
229
230 spin_lock(&sbi->ll_lock);
231 pages_number = sbi->ll_ra_info.ra_max_pages;
232 spin_unlock(&sbi->ll_lock);
233
234 mult = 1 << (20 - PAGE_CACHE_SHIFT);
73bb1da6 235 return lprocfs_seq_read_frac_helper(m, pages_number, mult);
d7e09d03
PT
236}
237
5a13503e
AL
238static ssize_t ll_max_readahead_mb_seq_write(struct file *file,
239 const char __user *buffer,
240 size_t count, loff_t *off)
d7e09d03 241{
73bb1da6 242 struct super_block *sb = ((struct seq_file *)file->private_data)->private;
d7e09d03
PT
243 struct ll_sb_info *sbi = ll_s2sbi(sb);
244 int mult, rc, pages_number;
245
246 mult = 1 << (20 - PAGE_CACHE_SHIFT);
247 rc = lprocfs_write_frac_helper(buffer, count, &pages_number, mult);
248 if (rc)
249 return rc;
250
4f6cc9ab 251 if (pages_number < 0 || pages_number > totalram_pages / 2) {
d7e09d03 252 CERROR("can't set file readahead more than %lu MB\n",
4f6cc9ab 253 totalram_pages >> (20 - PAGE_CACHE_SHIFT + 1)); /*1/2 of RAM*/
d7e09d03
PT
254 return -ERANGE;
255 }
256
257 spin_lock(&sbi->ll_lock);
258 sbi->ll_ra_info.ra_max_pages = pages_number;
259 spin_unlock(&sbi->ll_lock);
260
261 return count;
262}
73bb1da6 263LPROC_SEQ_FOPS(ll_max_readahead_mb);
d7e09d03 264
73bb1da6 265static int ll_max_readahead_per_file_mb_seq_show(struct seq_file *m, void *v)
d7e09d03 266{
73bb1da6 267 struct super_block *sb = m->private;
d7e09d03
PT
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_per_file;
274 spin_unlock(&sbi->ll_lock);
275
276 mult = 1 << (20 - PAGE_CACHE_SHIFT);
73bb1da6 277 return lprocfs_seq_read_frac_helper(m, pages_number, mult);
d7e09d03
PT
278}
279
73bb1da6 280static ssize_t ll_max_readahead_per_file_mb_seq_write(struct file *file,
5a13503e 281 const char __user *buffer,
73bb1da6 282 size_t count, loff_t *off)
d7e09d03 283{
73bb1da6 284 struct super_block *sb = ((struct seq_file *)file->private_data)->private;
d7e09d03
PT
285 struct ll_sb_info *sbi = ll_s2sbi(sb);
286 int mult, rc, pages_number;
287
288 mult = 1 << (20 - PAGE_CACHE_SHIFT);
289 rc = lprocfs_write_frac_helper(buffer, count, &pages_number, mult);
290 if (rc)
291 return rc;
292
293 if (pages_number < 0 ||
294 pages_number > sbi->ll_ra_info.ra_max_pages) {
2d00bd17 295 CERROR("can't set file readahead more than max_read_ahead_mb %lu MB\n",
d7e09d03
PT
296 sbi->ll_ra_info.ra_max_pages);
297 return -ERANGE;
298 }
299
300 spin_lock(&sbi->ll_lock);
301 sbi->ll_ra_info.ra_max_pages_per_file = pages_number;
302 spin_unlock(&sbi->ll_lock);
303
304 return count;
305}
73bb1da6 306LPROC_SEQ_FOPS(ll_max_readahead_per_file_mb);
d7e09d03 307
73bb1da6 308static int ll_max_read_ahead_whole_mb_seq_show(struct seq_file *m, void *unused)
d7e09d03 309{
73bb1da6 310 struct super_block *sb = m->private;
d7e09d03
PT
311 struct ll_sb_info *sbi = ll_s2sbi(sb);
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_CACHE_SHIFT);
73bb1da6 320 return lprocfs_seq_read_frac_helper(m, pages_number, mult);
d7e09d03
PT
321}
322
73bb1da6 323static ssize_t ll_max_read_ahead_whole_mb_seq_write(struct file *file,
5a13503e 324 const char __user *buffer,
73bb1da6 325 size_t count, loff_t *off)
d7e09d03 326{
73bb1da6 327 struct super_block *sb = ((struct seq_file *)file->private_data)->private;
d7e09d03
PT
328 struct ll_sb_info *sbi = ll_s2sbi(sb);
329 int mult, rc, pages_number;
330
331 mult = 1 << (20 - PAGE_CACHE_SHIFT);
332 rc = lprocfs_write_frac_helper(buffer, count, &pages_number, mult);
333 if (rc)
334 return rc;
335
336 /* Cap this at the current max readahead window size, the readahead
337 * algorithm does this anyway so it's pointless to set it larger. */
338 if (pages_number < 0 ||
339 pages_number > sbi->ll_ra_info.ra_max_pages_per_file) {
2d00bd17
JP
340 CERROR("can't set max_read_ahead_whole_mb more than max_read_ahead_per_file_mb: %lu\n",
341 sbi->ll_ra_info.ra_max_pages_per_file >> (20 - PAGE_CACHE_SHIFT));
d7e09d03
PT
342 return -ERANGE;
343 }
344
345 spin_lock(&sbi->ll_lock);
346 sbi->ll_ra_info.ra_max_read_ahead_whole_pages = pages_number;
347 spin_unlock(&sbi->ll_lock);
348
349 return count;
350}
73bb1da6 351LPROC_SEQ_FOPS(ll_max_read_ahead_whole_mb);
d7e09d03 352
73bb1da6 353static int ll_max_cached_mb_seq_show(struct seq_file *m, void *v)
d7e09d03 354{
73bb1da6 355 struct super_block *sb = m->private;
d7e09d03
PT
356 struct ll_sb_info *sbi = ll_s2sbi(sb);
357 struct cl_client_cache *cache = &sbi->ll_cache;
358 int shift = 20 - PAGE_CACHE_SHIFT;
359 int max_cached_mb;
360 int unused_mb;
361
d7e09d03
PT
362 max_cached_mb = cache->ccc_lru_max >> shift;
363 unused_mb = atomic_read(&cache->ccc_lru_left) >> shift;
8faeebdf
JP
364 seq_printf(m,
365 "users: %d\n"
366 "max_cached_mb: %d\n"
367 "used_mb: %d\n"
368 "unused_mb: %d\n"
369 "reclaim_count: %u\n",
370 atomic_read(&cache->ccc_users),
371 max_cached_mb,
372 max_cached_mb - unused_mb,
373 unused_mb,
374 cache->ccc_lru_shrinkers);
375 return 0;
d7e09d03
PT
376}
377
a1e7e2d4
OD
378static ssize_t ll_max_cached_mb_seq_write(struct file *file,
379 const char __user *buffer,
380 size_t count, loff_t *off)
d7e09d03 381{
73bb1da6 382 struct super_block *sb = ((struct seq_file *)file->private_data)->private;
d7e09d03
PT
383 struct ll_sb_info *sbi = ll_s2sbi(sb);
384 struct cl_client_cache *cache = &sbi->ll_cache;
385 int mult, rc, pages_number;
386 int diff = 0;
387 int nrpages = 0;
a1e7e2d4
OD
388 char kernbuf[128];
389
390 if (count >= sizeof(kernbuf))
391 return -EINVAL;
392
393 if (copy_from_user(kernbuf, buffer, count))
394 return -EFAULT;
395 kernbuf[count] = 0;
d7e09d03
PT
396
397 mult = 1 << (20 - PAGE_CACHE_SHIFT);
a1e7e2d4
OD
398 buffer += lprocfs_find_named_value(kernbuf, "max_cached_mb:", &count) -
399 kernbuf;
d7e09d03
PT
400 rc = lprocfs_write_frac_helper(buffer, count, &pages_number, mult);
401 if (rc)
0a3bdb00 402 return rc;
d7e09d03 403
4f6cc9ab 404 if (pages_number < 0 || pages_number > totalram_pages) {
d7e09d03
PT
405 CERROR("%s: can't set max cache more than %lu MB\n",
406 ll_get_fsname(sb, NULL, 0),
4f6cc9ab 407 totalram_pages >> (20 - PAGE_CACHE_SHIFT));
0a3bdb00 408 return -ERANGE;
d7e09d03
PT
409 }
410
d7e09d03
PT
411 spin_lock(&sbi->ll_lock);
412 diff = pages_number - cache->ccc_lru_max;
413 spin_unlock(&sbi->ll_lock);
414
415 /* easy - add more LRU slots. */
416 if (diff >= 0) {
417 atomic_add(diff, &cache->ccc_lru_left);
34e1f2bb
JL
418 rc = 0;
419 goto out;
d7e09d03
PT
420 }
421
422 diff = -diff;
423 while (diff > 0) {
424 int tmp;
425
426 /* reduce LRU budget from free slots. */
427 do {
428 int ov, nv;
429
430 ov = atomic_read(&cache->ccc_lru_left);
431 if (ov == 0)
432 break;
433
434 nv = ov > diff ? ov - diff : 0;
305ec768 435 rc = atomic_cmpxchg(&cache->ccc_lru_left, ov, nv);
d7e09d03
PT
436 if (likely(ov == rc)) {
437 diff -= ov - nv;
438 nrpages += ov - nv;
439 break;
440 }
441 } while (1);
442
443 if (diff <= 0)
444 break;
445
c2fcdf6c
JX
446 if (sbi->ll_dt_exp == NULL) { /* being initialized */
447 rc = -ENODEV;
448 break;
449 }
450
d7e09d03
PT
451 /* difficult - have to ask OSCs to drop LRU slots. */
452 tmp = diff << 1;
453 rc = obd_set_info_async(NULL, sbi->ll_dt_exp,
454 sizeof(KEY_CACHE_LRU_SHRINK),
455 KEY_CACHE_LRU_SHRINK,
456 sizeof(tmp), &tmp, NULL);
457 if (rc < 0)
458 break;
459 }
460
461out:
462 if (rc >= 0) {
463 spin_lock(&sbi->ll_lock);
464 cache->ccc_lru_max = pages_number;
465 spin_unlock(&sbi->ll_lock);
466 rc = count;
467 } else {
468 atomic_add(nrpages, &cache->ccc_lru_left);
469 }
470 return rc;
471}
73bb1da6 472LPROC_SEQ_FOPS(ll_max_cached_mb);
d7e09d03 473
73bb1da6 474static int ll_checksum_seq_show(struct seq_file *m, void *v)
d7e09d03 475{
73bb1da6 476 struct super_block *sb = m->private;
d7e09d03
PT
477 struct ll_sb_info *sbi = ll_s2sbi(sb);
478
8faeebdf
JP
479 seq_printf(m, "%u\n", (sbi->ll_flags & LL_SBI_CHECKSUM) ? 1 : 0);
480 return 0;
d7e09d03
PT
481}
482
5a13503e
AL
483static ssize_t ll_checksum_seq_write(struct file *file,
484 const char __user *buffer,
485 size_t count, loff_t *off)
d7e09d03 486{
73bb1da6 487 struct super_block *sb = ((struct seq_file *)file->private_data)->private;
d7e09d03
PT
488 struct ll_sb_info *sbi = ll_s2sbi(sb);
489 int val, rc;
490
491 if (!sbi->ll_dt_exp)
492 /* Not set up yet */
493 return -EAGAIN;
494
495 rc = lprocfs_write_helper(buffer, count, &val);
496 if (rc)
497 return rc;
498 if (val)
499 sbi->ll_flags |= LL_SBI_CHECKSUM;
500 else
501 sbi->ll_flags &= ~LL_SBI_CHECKSUM;
502
503 rc = obd_set_info_async(NULL, sbi->ll_dt_exp, sizeof(KEY_CHECKSUM),
504 KEY_CHECKSUM, sizeof(val), &val, NULL);
505 if (rc)
506 CWARN("Failed to set OSC checksum flags: %d\n", rc);
507
508 return count;
509}
73bb1da6 510LPROC_SEQ_FOPS(ll_checksum);
d7e09d03 511
73bb1da6 512static int ll_max_rw_chunk_seq_show(struct seq_file *m, void *v)
d7e09d03 513{
73bb1da6 514 struct super_block *sb = m->private;
d7e09d03 515
8faeebdf
JP
516 seq_printf(m, "%lu\n", ll_s2sbi(sb)->ll_max_rw_chunk);
517 return 0;
d7e09d03
PT
518}
519
5a13503e
AL
520static ssize_t ll_max_rw_chunk_seq_write(struct file *file,
521 const char __user *buffer,
522 size_t count, loff_t *off)
d7e09d03 523{
73bb1da6 524 struct super_block *sb = ((struct seq_file *)file->private_data)->private;
d7e09d03
PT
525 int rc, val;
526
527 rc = lprocfs_write_helper(buffer, count, &val);
528 if (rc)
529 return rc;
530 ll_s2sbi(sb)->ll_max_rw_chunk = val;
531 return count;
532}
73bb1da6 533LPROC_SEQ_FOPS(ll_max_rw_chunk);
d7e09d03 534
73bb1da6 535static int ll_rd_track_id(struct seq_file *m, enum stats_track_type type)
d7e09d03 536{
73bb1da6 537 struct super_block *sb = m->private;
d7e09d03 538
8faeebdf
JP
539 if (ll_s2sbi(sb)->ll_stats_track_type == type)
540 seq_printf(m, "%d\n", ll_s2sbi(sb)->ll_stats_track_id);
541 else if (ll_s2sbi(sb)->ll_stats_track_type == STATS_TRACK_ALL)
542 seq_puts(m, "0 (all)\n");
543 else
544 seq_puts(m, "untracked\n");
d7e09d03 545
8faeebdf 546 return 0;
d7e09d03
PT
547}
548
5a13503e
AL
549static int ll_wr_track_id(const char __user *buffer, unsigned long count,
550 void *data, enum stats_track_type type)
d7e09d03
PT
551{
552 struct super_block *sb = data;
553 int rc, pid;
554
555 rc = lprocfs_write_helper(buffer, count, &pid);
556 if (rc)
557 return rc;
558 ll_s2sbi(sb)->ll_stats_track_id = pid;
559 if (pid == 0)
560 ll_s2sbi(sb)->ll_stats_track_type = STATS_TRACK_ALL;
561 else
562 ll_s2sbi(sb)->ll_stats_track_type = type;
563 lprocfs_clear_stats(ll_s2sbi(sb)->ll_stats);
564 return count;
565}
566
73bb1da6 567static int ll_track_pid_seq_show(struct seq_file *m, void *v)
d7e09d03 568{
73bb1da6 569 return ll_rd_track_id(m, STATS_TRACK_PID);
d7e09d03
PT
570}
571
5a13503e
AL
572static ssize_t ll_track_pid_seq_write(struct file *file,
573 const char __user *buffer,
574 size_t count, loff_t *off)
d7e09d03 575{
73bb1da6
PT
576 struct seq_file *seq = file->private_data;
577 return ll_wr_track_id(buffer, count, seq->private, STATS_TRACK_PID);
d7e09d03 578}
73bb1da6 579LPROC_SEQ_FOPS(ll_track_pid);
d7e09d03 580
73bb1da6 581static int ll_track_ppid_seq_show(struct seq_file *m, void *v)
d7e09d03 582{
73bb1da6 583 return ll_rd_track_id(m, STATS_TRACK_PPID);
d7e09d03
PT
584}
585
5a13503e
AL
586static ssize_t ll_track_ppid_seq_write(struct file *file,
587 const char __user *buffer,
588 size_t count, loff_t *off)
d7e09d03 589{
73bb1da6
PT
590 struct seq_file *seq = file->private_data;
591 return ll_wr_track_id(buffer, count, seq->private, STATS_TRACK_PPID);
d7e09d03 592}
73bb1da6 593LPROC_SEQ_FOPS(ll_track_ppid);
d7e09d03 594
73bb1da6 595static int ll_track_gid_seq_show(struct seq_file *m, void *v)
d7e09d03 596{
73bb1da6 597 return ll_rd_track_id(m, STATS_TRACK_GID);
d7e09d03
PT
598}
599
5a13503e
AL
600static ssize_t ll_track_gid_seq_write(struct file *file,
601 const char __user *buffer,
602 size_t count, loff_t *off)
d7e09d03 603{
73bb1da6
PT
604 struct seq_file *seq = file->private_data;
605 return ll_wr_track_id(buffer, count, seq->private, STATS_TRACK_GID);
d7e09d03 606}
73bb1da6 607LPROC_SEQ_FOPS(ll_track_gid);
d7e09d03 608
73bb1da6 609static int ll_statahead_max_seq_show(struct seq_file *m, void *v)
d7e09d03 610{
73bb1da6 611 struct super_block *sb = m->private;
d7e09d03
PT
612 struct ll_sb_info *sbi = ll_s2sbi(sb);
613
8faeebdf
JP
614 seq_printf(m, "%u\n", sbi->ll_sa_max);
615 return 0;
d7e09d03
PT
616}
617
5a13503e
AL
618static ssize_t ll_statahead_max_seq_write(struct file *file,
619 const char __user *buffer,
620 size_t count, loff_t *off)
d7e09d03 621{
73bb1da6 622 struct super_block *sb = ((struct seq_file *)file->private_data)->private;
d7e09d03
PT
623 struct ll_sb_info *sbi = ll_s2sbi(sb);
624 int val, rc;
625
626 rc = lprocfs_write_helper(buffer, count, &val);
627 if (rc)
628 return rc;
629
630 if (val >= 0 && val <= LL_SA_RPC_MAX)
631 sbi->ll_sa_max = val;
632 else
2d00bd17
JP
633 CERROR("Bad statahead_max value %d. Valid values are in the range [0, %d]\n",
634 val, LL_SA_RPC_MAX);
d7e09d03
PT
635
636 return count;
637}
73bb1da6 638LPROC_SEQ_FOPS(ll_statahead_max);
d7e09d03 639
73bb1da6 640static int ll_statahead_agl_seq_show(struct seq_file *m, void *v)
d7e09d03 641{
73bb1da6 642 struct super_block *sb = m->private;
d7e09d03
PT
643 struct ll_sb_info *sbi = ll_s2sbi(sb);
644
8faeebdf
JP
645 seq_printf(m, "%u\n", sbi->ll_flags & LL_SBI_AGL_ENABLED ? 1 : 0);
646 return 0;
d7e09d03
PT
647}
648
5a13503e
AL
649static ssize_t ll_statahead_agl_seq_write(struct file *file,
650 const char __user *buffer,
651 size_t count, loff_t *off)
d7e09d03 652{
73bb1da6 653 struct super_block *sb = ((struct seq_file *)file->private_data)->private;
d7e09d03
PT
654 struct ll_sb_info *sbi = ll_s2sbi(sb);
655 int val, rc;
656
657 rc = lprocfs_write_helper(buffer, count, &val);
658 if (rc)
659 return rc;
660
661 if (val)
662 sbi->ll_flags |= LL_SBI_AGL_ENABLED;
663 else
664 sbi->ll_flags &= ~LL_SBI_AGL_ENABLED;
665
666 return count;
667}
73bb1da6 668LPROC_SEQ_FOPS(ll_statahead_agl);
d7e09d03 669
73bb1da6 670static int ll_statahead_stats_seq_show(struct seq_file *m, void *v)
d7e09d03 671{
73bb1da6 672 struct super_block *sb = m->private;
d7e09d03
PT
673 struct ll_sb_info *sbi = ll_s2sbi(sb);
674
8faeebdf
JP
675 seq_printf(m,
676 "statahead total: %u\n"
677 "statahead wrong: %u\n"
678 "agl total: %u\n",
679 atomic_read(&sbi->ll_sa_total),
680 atomic_read(&sbi->ll_sa_wrong),
681 atomic_read(&sbi->ll_agl_total));
682 return 0;
d7e09d03 683}
73bb1da6 684LPROC_SEQ_FOPS_RO(ll_statahead_stats);
d7e09d03 685
73bb1da6 686static int ll_lazystatfs_seq_show(struct seq_file *m, void *v)
d7e09d03 687{
73bb1da6 688 struct super_block *sb = m->private;
d7e09d03
PT
689 struct ll_sb_info *sbi = ll_s2sbi(sb);
690
8faeebdf
JP
691 seq_printf(m, "%u\n", sbi->ll_flags & LL_SBI_LAZYSTATFS ? 1 : 0);
692 return 0;
d7e09d03
PT
693}
694
5a13503e
AL
695static ssize_t ll_lazystatfs_seq_write(struct file *file,
696 const char __user *buffer,
697 size_t count, loff_t *off)
d7e09d03 698{
73bb1da6 699 struct super_block *sb = ((struct seq_file *)file->private_data)->private;
d7e09d03
PT
700 struct ll_sb_info *sbi = ll_s2sbi(sb);
701 int val, rc;
702
703 rc = lprocfs_write_helper(buffer, count, &val);
704 if (rc)
705 return rc;
706
707 if (val)
708 sbi->ll_flags |= LL_SBI_LAZYSTATFS;
709 else
710 sbi->ll_flags &= ~LL_SBI_LAZYSTATFS;
711
712 return count;
713}
73bb1da6 714LPROC_SEQ_FOPS(ll_lazystatfs);
d7e09d03 715
44779340 716static int ll_max_easize_seq_show(struct seq_file *m, void *v)
d7e09d03 717{
73bb1da6 718 struct super_block *sb = m->private;
d7e09d03
PT
719 struct ll_sb_info *sbi = ll_s2sbi(sb);
720 unsigned int ealen;
721 int rc;
722
723 rc = ll_get_max_mdsize(sbi, &ealen);
724 if (rc)
725 return rc;
726
8faeebdf
JP
727 seq_printf(m, "%u\n", ealen);
728 return 0;
d7e09d03 729}
44779340
BB
730LPROC_SEQ_FOPS_RO(ll_max_easize);
731
dfc16973 732static int ll_default_easize_seq_show(struct seq_file *m, void *v)
44779340
BB
733{
734 struct super_block *sb = m->private;
735 struct ll_sb_info *sbi = ll_s2sbi(sb);
736 unsigned int ealen;
737 int rc;
738
739 rc = ll_get_default_mdsize(sbi, &ealen);
740 if (rc)
741 return rc;
742
8faeebdf
JP
743 seq_printf(m, "%u\n", ealen);
744 return 0;
44779340 745}
dfc16973 746LPROC_SEQ_FOPS_RO(ll_default_easize);
44779340
BB
747
748static int ll_max_cookiesize_seq_show(struct seq_file *m, void *v)
749{
750 struct super_block *sb = m->private;
751 struct ll_sb_info *sbi = ll_s2sbi(sb);
752 unsigned int cookielen;
753 int rc;
754
755 rc = ll_get_max_cookiesize(sbi, &cookielen);
756 if (rc)
757 return rc;
758
8faeebdf
JP
759 seq_printf(m, "%u\n", cookielen);
760 return 0;
44779340
BB
761}
762LPROC_SEQ_FOPS_RO(ll_max_cookiesize);
763
dfc16973 764static int ll_default_cookiesize_seq_show(struct seq_file *m, void *v)
44779340
BB
765{
766 struct super_block *sb = m->private;
767 struct ll_sb_info *sbi = ll_s2sbi(sb);
768 unsigned int cookielen;
769 int rc;
770
771 rc = ll_get_default_cookiesize(sbi, &cookielen);
772 if (rc)
773 return rc;
774
8faeebdf
JP
775 seq_printf(m, "%u\n", cookielen);
776 return 0;
44779340 777}
dfc16973 778LPROC_SEQ_FOPS_RO(ll_default_cookiesize);
d7e09d03 779
73bb1da6 780static int ll_sbi_flags_seq_show(struct seq_file *m, void *v)
d7e09d03
PT
781{
782 const char *str[] = LL_SBI_FLAGS;
73bb1da6 783 struct super_block *sb = m->private;
d7e09d03
PT
784 int flags = ll_s2sbi(sb)->ll_flags;
785 int i = 0;
d7e09d03
PT
786
787 while (flags != 0) {
788 if (ARRAY_SIZE(str) <= i) {
2d00bd17
JP
789 CERROR("%s: Revise array LL_SBI_FLAGS to match sbi flags please.\n",
790 ll_get_fsname(sb, NULL, 0));
d7e09d03
PT
791 return -EINVAL;
792 }
793
794 if (flags & 0x1)
73bb1da6 795 seq_printf(m, "%s ", str[i]);
d7e09d03
PT
796 flags >>= 1;
797 ++i;
798 }
73bb1da6
PT
799 seq_printf(m, "\b\n");
800 return 0;
d7e09d03 801}
73bb1da6 802LPROC_SEQ_FOPS_RO(ll_sbi_flags);
d7e09d03 803
7fc1f831
AP
804static int ll_xattr_cache_seq_show(struct seq_file *m, void *v)
805{
806 struct super_block *sb = m->private;
807 struct ll_sb_info *sbi = ll_s2sbi(sb);
7fc1f831 808
91b3a685
JP
809 seq_printf(m, "%u\n", sbi->ll_xattr_cache_enabled);
810
811 return 0;
7fc1f831
AP
812}
813
5a13503e
AL
814static ssize_t ll_xattr_cache_seq_write(struct file *file,
815 const char __user *buffer,
7fc1f831
AP
816 size_t count, loff_t *off)
817{
818 struct seq_file *seq = file->private_data;
819 struct super_block *sb = seq->private;
820 struct ll_sb_info *sbi = ll_s2sbi(sb);
821 int val, rc;
822
823 rc = lprocfs_write_helper(buffer, count, &val);
824 if (rc)
825 return rc;
826
827 if (val != 0 && val != 1)
828 return -ERANGE;
829
830 if (val == 1 && !(sbi->ll_flags & LL_SBI_XATTR_CACHE))
831 return -ENOTSUPP;
832
833 sbi->ll_xattr_cache_enabled = val;
834
835 return count;
836}
837LPROC_SEQ_FOPS(ll_xattr_cache);
838
d7e09d03 839static struct lprocfs_vars lprocfs_llite_obd_vars[] = {
588bf52a 840 /* { "mntpt_path", ll_rd_path, 0, 0 }, */
95b86a76 841 { "site", &ll_site_stats_fops, NULL, 0 },
588bf52a 842 /* { "filegroups", lprocfs_rd_filegroups, 0, 0 }, */
95b86a76
SL
843 { "max_read_ahead_mb", &ll_max_readahead_mb_fops, NULL },
844 { "max_read_ahead_per_file_mb", &ll_max_readahead_per_file_mb_fops,
845 NULL },
846 { "max_read_ahead_whole_mb", &ll_max_read_ahead_whole_mb_fops, NULL },
847 { "max_cached_mb", &ll_max_cached_mb_fops, NULL },
848 { "checksum_pages", &ll_checksum_fops, NULL },
849 { "max_rw_chunk", &ll_max_rw_chunk_fops, NULL },
850 { "stats_track_pid", &ll_track_pid_fops, NULL },
851 { "stats_track_ppid", &ll_track_ppid_fops, NULL },
852 { "stats_track_gid", &ll_track_gid_fops, NULL },
853 { "statahead_max", &ll_statahead_max_fops, NULL },
854 { "statahead_agl", &ll_statahead_agl_fops, NULL },
855 { "statahead_stats", &ll_statahead_stats_fops, NULL, 0 },
856 { "lazystatfs", &ll_lazystatfs_fops, NULL },
857 { "max_easize", &ll_max_easize_fops, NULL, 0 },
dfc16973 858 { "default_easize", &ll_default_easize_fops, NULL, 0 },
95b86a76 859 { "max_cookiesize", &ll_max_cookiesize_fops, NULL, 0 },
dfc16973 860 { "default_cookiesize", &ll_default_cookiesize_fops, NULL, 0 },
95b86a76
SL
861 { "sbi_flags", &ll_sbi_flags_fops, NULL, 0 },
862 { "xattr_cache", &ll_xattr_cache_fops, NULL, 0 },
ea7893bb 863 { NULL }
d7e09d03
PT
864};
865
866#define MAX_STRING_SIZE 128
867
fd0d04ba 868static struct attribute *llite_attrs[] = {
364bcfc8 869 &lustre_attr_blocksize.attr,
5804b11e
OD
870 &lustre_attr_kbytestotal.attr,
871 &lustre_attr_kbytesfree.attr,
872 &lustre_attr_kbytesavail.attr,
7267ec0d
OD
873 &lustre_attr_filestotal.attr,
874 &lustre_attr_filesfree.attr,
95e1b6b0 875 &lustre_attr_client_type.attr,
0cee6676 876 &lustre_attr_fstype.attr,
ec55a629 877 &lustre_attr_uuid.attr,
fd0d04ba
OD
878 NULL,
879};
880
881static void llite_sb_release(struct kobject *kobj)
882{
883 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
884 ll_kobj);
885 complete(&sbi->ll_kobj_unregister);
886}
887
888static struct kobj_type llite_ktype = {
889 .default_attrs = llite_attrs,
890 .sysfs_ops = &lustre_sysfs_ops,
891 .release = llite_sb_release,
892};
893
2d95f10e 894static const struct llite_file_opcode {
d7e09d03
PT
895 __u32 opcode;
896 __u32 type;
897 const char *opname;
898} llite_opcode_table[LPROC_LL_FILE_OPCODES] = {
899 /* file operation */
900 { LPROC_LL_DIRTY_HITS, LPROCFS_TYPE_REGS, "dirty_pages_hits" },
901 { LPROC_LL_DIRTY_MISSES, LPROCFS_TYPE_REGS, "dirty_pages_misses" },
902 { LPROC_LL_READ_BYTES, LPROCFS_CNTR_AVGMINMAX|LPROCFS_TYPE_BYTES,
903 "read_bytes" },
904 { LPROC_LL_WRITE_BYTES, LPROCFS_CNTR_AVGMINMAX|LPROCFS_TYPE_BYTES,
905 "write_bytes" },
906 { LPROC_LL_BRW_READ, LPROCFS_CNTR_AVGMINMAX|LPROCFS_TYPE_PAGES,
907 "brw_read" },
908 { LPROC_LL_BRW_WRITE, LPROCFS_CNTR_AVGMINMAX|LPROCFS_TYPE_PAGES,
909 "brw_write" },
910 { LPROC_LL_OSC_READ, LPROCFS_CNTR_AVGMINMAX|LPROCFS_TYPE_BYTES,
911 "osc_read" },
912 { LPROC_LL_OSC_WRITE, LPROCFS_CNTR_AVGMINMAX|LPROCFS_TYPE_BYTES,
913 "osc_write" },
914 { LPROC_LL_IOCTL, LPROCFS_TYPE_REGS, "ioctl" },
915 { LPROC_LL_OPEN, LPROCFS_TYPE_REGS, "open" },
916 { LPROC_LL_RELEASE, LPROCFS_TYPE_REGS, "close" },
917 { LPROC_LL_MAP, LPROCFS_TYPE_REGS, "mmap" },
918 { LPROC_LL_LLSEEK, LPROCFS_TYPE_REGS, "seek" },
919 { LPROC_LL_FSYNC, LPROCFS_TYPE_REGS, "fsync" },
920 { LPROC_LL_READDIR, LPROCFS_TYPE_REGS, "readdir" },
921 /* inode operation */
922 { LPROC_LL_SETATTR, LPROCFS_TYPE_REGS, "setattr" },
923 { LPROC_LL_TRUNC, LPROCFS_TYPE_REGS, "truncate" },
924 { LPROC_LL_FLOCK, LPROCFS_TYPE_REGS, "flock" },
925 { LPROC_LL_GETATTR, LPROCFS_TYPE_REGS, "getattr" },
926 /* dir inode operation */
927 { LPROC_LL_CREATE, LPROCFS_TYPE_REGS, "create" },
928 { LPROC_LL_LINK, LPROCFS_TYPE_REGS, "link" },
929 { LPROC_LL_UNLINK, LPROCFS_TYPE_REGS, "unlink" },
930 { LPROC_LL_SYMLINK, LPROCFS_TYPE_REGS, "symlink" },
931 { LPROC_LL_MKDIR, LPROCFS_TYPE_REGS, "mkdir" },
932 { LPROC_LL_RMDIR, LPROCFS_TYPE_REGS, "rmdir" },
933 { LPROC_LL_MKNOD, LPROCFS_TYPE_REGS, "mknod" },
934 { LPROC_LL_RENAME, LPROCFS_TYPE_REGS, "rename" },
935 /* special inode operation */
936 { LPROC_LL_STAFS, LPROCFS_TYPE_REGS, "statfs" },
937 { LPROC_LL_ALLOC_INODE, LPROCFS_TYPE_REGS, "alloc_inode" },
938 { LPROC_LL_SETXATTR, LPROCFS_TYPE_REGS, "setxattr" },
939 { LPROC_LL_GETXATTR, LPROCFS_TYPE_REGS, "getxattr" },
7fc1f831 940 { LPROC_LL_GETXATTR_HITS, LPROCFS_TYPE_REGS, "getxattr_hits" },
d7e09d03
PT
941 { LPROC_LL_LISTXATTR, LPROCFS_TYPE_REGS, "listxattr" },
942 { LPROC_LL_REMOVEXATTR, LPROCFS_TYPE_REGS, "removexattr" },
943 { LPROC_LL_INODE_PERM, LPROCFS_TYPE_REGS, "inode_permission" },
944};
945
946void ll_stats_ops_tally(struct ll_sb_info *sbi, int op, int count)
947{
948 if (!sbi->ll_stats)
949 return;
950 if (sbi->ll_stats_track_type == STATS_TRACK_ALL)
951 lprocfs_counter_add(sbi->ll_stats, op, count);
952 else if (sbi->ll_stats_track_type == STATS_TRACK_PID &&
953 sbi->ll_stats_track_id == current->pid)
954 lprocfs_counter_add(sbi->ll_stats, op, count);
955 else if (sbi->ll_stats_track_type == STATS_TRACK_PPID &&
b1beb91b 956 sbi->ll_stats_track_id == current->real_parent->pid)
d7e09d03
PT
957 lprocfs_counter_add(sbi->ll_stats, op, count);
958 else if (sbi->ll_stats_track_type == STATS_TRACK_GID &&
4b1a25f0
PT
959 sbi->ll_stats_track_id ==
960 from_kgid(&init_user_ns, current_gid()))
d7e09d03
PT
961 lprocfs_counter_add(sbi->ll_stats, op, count);
962}
963EXPORT_SYMBOL(ll_stats_ops_tally);
964
965static const char *ra_stat_string[] = {
966 [RA_STAT_HIT] = "hits",
967 [RA_STAT_MISS] = "misses",
968 [RA_STAT_DISTANT_READPAGE] = "readpage not consecutive",
969 [RA_STAT_MISS_IN_WINDOW] = "miss inside window",
970 [RA_STAT_FAILED_GRAB_PAGE] = "failed grab_cache_page",
971 [RA_STAT_FAILED_MATCH] = "failed lock match",
972 [RA_STAT_DISCARDED] = "read but discarded",
973 [RA_STAT_ZERO_LEN] = "zero length file",
974 [RA_STAT_ZERO_WINDOW] = "zero size window",
975 [RA_STAT_EOF] = "read-ahead to EOF",
976 [RA_STAT_MAX_IN_FLIGHT] = "hit max r-a issue",
977 [RA_STAT_WRONG_GRAB_PAGE] = "wrong page from grab_cache_page",
978};
979
73bb1da6
PT
980LPROC_SEQ_FOPS_RO_TYPE(llite, name);
981LPROC_SEQ_FOPS_RO_TYPE(llite, uuid);
d7e09d03
PT
982
983int lprocfs_register_mountpoint(struct proc_dir_entry *parent,
984 struct super_block *sb, char *osc, char *mdc)
985{
986 struct lprocfs_vars lvars[2];
987 struct lustre_sb_info *lsi = s2lsi(sb);
988 struct ll_sb_info *sbi = ll_s2sbi(sb);
989 struct obd_device *obd;
b59fe845 990 struct proc_dir_entry *dir;
d7e09d03
PT
991 char name[MAX_STRING_SIZE + 1], *ptr;
992 int err, id, len, rc;
d7e09d03
PT
993
994 memset(lvars, 0, sizeof(lvars));
995
996 name[MAX_STRING_SIZE] = '\0';
997 lvars[0].name = name;
998
999 LASSERT(sbi != NULL);
1000 LASSERT(mdc != NULL);
1001 LASSERT(osc != NULL);
1002
1003 /* Get fsname */
1004 len = strlen(lsi->lsi_lmd->lmd_profile);
1005 ptr = strrchr(lsi->lsi_lmd->lmd_profile, '-');
1006 if (ptr && (strcmp(ptr, "-client") == 0))
1007 len -= 7;
1008
1009 /* Mount info */
1010 snprintf(name, MAX_STRING_SIZE, "%.*s-%p", len,
1011 lsi->lsi_lmd->lmd_profile, sb);
1012
1013 sbi->ll_proc_root = lprocfs_register(name, parent, NULL, NULL);
1014 if (IS_ERR(sbi->ll_proc_root)) {
1015 err = PTR_ERR(sbi->ll_proc_root);
1016 sbi->ll_proc_root = NULL;
0a3bdb00 1017 return err;
d7e09d03
PT
1018 }
1019
1020 rc = lprocfs_seq_create(sbi->ll_proc_root, "dump_page_cache", 0444,
1021 &vvp_dump_pgcache_file_ops, sbi);
1022 if (rc)
1023 CWARN("Error adding the dump_page_cache file\n");
1024
1025 rc = lprocfs_seq_create(sbi->ll_proc_root, "extents_stats", 0644,
1026 &ll_rw_extents_stats_fops, sbi);
1027 if (rc)
1028 CWARN("Error adding the extent_stats file\n");
1029
1030 rc = lprocfs_seq_create(sbi->ll_proc_root, "extents_stats_per_process",
1031 0644, &ll_rw_extents_stats_pp_fops, sbi);
1032 if (rc)
1033 CWARN("Error adding the extents_stats_per_process file\n");
1034
1035 rc = lprocfs_seq_create(sbi->ll_proc_root, "offset_stats", 0644,
1036 &ll_rw_offset_stats_fops, sbi);
1037 if (rc)
1038 CWARN("Error adding the offset_stats file\n");
1039
1040 /* File operations stats */
1041 sbi->ll_stats = lprocfs_alloc_stats(LPROC_LL_FILE_OPCODES,
1042 LPROCFS_STATS_FLAG_NONE);
34e1f2bb
JL
1043 if (sbi->ll_stats == NULL) {
1044 err = -ENOMEM;
1045 goto out;
1046 }
d7e09d03
PT
1047 /* do counter init */
1048 for (id = 0; id < LPROC_LL_FILE_OPCODES; id++) {
1049 __u32 type = llite_opcode_table[id].type;
1050 void *ptr = NULL;
1051 if (type & LPROCFS_TYPE_REGS)
1052 ptr = "regs";
1053 else if (type & LPROCFS_TYPE_BYTES)
1054 ptr = "bytes";
1055 else if (type & LPROCFS_TYPE_PAGES)
1056 ptr = "pages";
1057 lprocfs_counter_init(sbi->ll_stats,
1058 llite_opcode_table[id].opcode,
1059 (type & LPROCFS_CNTR_AVGMINMAX),
1060 llite_opcode_table[id].opname, ptr);
1061 }
1062 err = lprocfs_register_stats(sbi->ll_proc_root, "stats", sbi->ll_stats);
1063 if (err)
34e1f2bb 1064 goto out;
d7e09d03
PT
1065
1066 sbi->ll_ra_stats = lprocfs_alloc_stats(ARRAY_SIZE(ra_stat_string),
1067 LPROCFS_STATS_FLAG_NONE);
34e1f2bb
JL
1068 if (sbi->ll_ra_stats == NULL) {
1069 err = -ENOMEM;
1070 goto out;
1071 }
d7e09d03
PT
1072
1073 for (id = 0; id < ARRAY_SIZE(ra_stat_string); id++)
1074 lprocfs_counter_init(sbi->ll_ra_stats, id, 0,
1075 ra_stat_string[id], "pages");
1076 err = lprocfs_register_stats(sbi->ll_proc_root, "read_ahead_stats",
1077 sbi->ll_ra_stats);
1078 if (err)
34e1f2bb 1079 goto out;
d7e09d03
PT
1080
1081
1082 err = lprocfs_add_vars(sbi->ll_proc_root, lprocfs_llite_obd_vars, sb);
1083 if (err)
34e1f2bb 1084 goto out;
d7e09d03 1085
fd0d04ba
OD
1086 sbi->ll_kobj.kset = llite_kset;
1087 init_completion(&sbi->ll_kobj_unregister);
1088 err = kobject_init_and_add(&sbi->ll_kobj, &llite_ktype, NULL,
1089 "%s", name);
1090 if (err)
1091 goto out;
1092
d7e09d03
PT
1093 /* MDC info */
1094 obd = class_name2obd(mdc);
1095
1096 LASSERT(obd != NULL);
1097 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1098 LASSERT(obd->obd_type->typ_name != NULL);
1099
73bb1da6 1100 dir = proc_mkdir(obd->obd_type->typ_name, sbi->ll_proc_root);
34e1f2bb
JL
1101 if (dir == NULL) {
1102 err = -ENOMEM;
1103 goto out;
1104 }
73bb1da6
PT
1105
1106 snprintf(name, MAX_STRING_SIZE, "common_name");
1107 lvars[0].fops = &llite_name_fops;
1108 err = lprocfs_add_vars(dir, lvars, obd);
d7e09d03 1109 if (err)
34e1f2bb 1110 goto out;
d7e09d03 1111
73bb1da6
PT
1112 snprintf(name, MAX_STRING_SIZE, "uuid");
1113 lvars[0].fops = &llite_uuid_fops;
1114 err = lprocfs_add_vars(dir, lvars, obd);
d7e09d03 1115 if (err)
34e1f2bb 1116 goto out;
d7e09d03
PT
1117
1118 /* OSC */
1119 obd = class_name2obd(osc);
1120
1121 LASSERT(obd != NULL);
1122 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1123 LASSERT(obd->obd_type->typ_name != NULL);
1124
73bb1da6 1125 dir = proc_mkdir(obd->obd_type->typ_name, sbi->ll_proc_root);
34e1f2bb
JL
1126 if (dir == NULL) {
1127 err = -ENOMEM;
1128 goto out;
1129 }
73bb1da6
PT
1130
1131 snprintf(name, MAX_STRING_SIZE, "common_name");
1132 lvars[0].fops = &llite_name_fops;
1133 err = lprocfs_add_vars(dir, lvars, obd);
d7e09d03 1134 if (err)
34e1f2bb 1135 goto out;
d7e09d03 1136
73bb1da6
PT
1137 snprintf(name, MAX_STRING_SIZE, "uuid");
1138 lvars[0].fops = &llite_uuid_fops;
1139 err = lprocfs_add_vars(dir, lvars, obd);
d7e09d03
PT
1140out:
1141 if (err) {
1142 lprocfs_remove(&sbi->ll_proc_root);
1143 lprocfs_free_stats(&sbi->ll_ra_stats);
1144 lprocfs_free_stats(&sbi->ll_stats);
1145 }
0a3bdb00 1146 return err;
d7e09d03
PT
1147}
1148
1149void lprocfs_unregister_mountpoint(struct ll_sb_info *sbi)
1150{
1151 if (sbi->ll_proc_root) {
1152 lprocfs_remove(&sbi->ll_proc_root);
fd0d04ba
OD
1153 kobject_put(&sbi->ll_kobj);
1154 wait_for_completion(&sbi->ll_kobj_unregister);
d7e09d03
PT
1155 lprocfs_free_stats(&sbi->ll_ra_stats);
1156 lprocfs_free_stats(&sbi->ll_stats);
1157 }
1158}
1159#undef MAX_STRING_SIZE
1160
1d8cb70c 1161#define pct(a, b) (b ? a * 100 / b : 0)
d7e09d03
PT
1162
1163static void ll_display_extents_info(struct ll_rw_extents_info *io_extents,
1164 struct seq_file *seq, int which)
1165{
1166 unsigned long read_tot = 0, write_tot = 0, read_cum, write_cum;
1167 unsigned long start, end, r, w;
1168 char *unitp = "KMGTPEZY";
1169 int i, units = 10;
1170 struct per_process_info *pp_info = &io_extents->pp_extents[which];
1171
1172 read_cum = 0;
1173 write_cum = 0;
1174 start = 0;
1175
a58a38ac 1176 for (i = 0; i < LL_HIST_MAX; i++) {
d7e09d03
PT
1177 read_tot += pp_info->pp_r_hist.oh_buckets[i];
1178 write_tot += pp_info->pp_w_hist.oh_buckets[i];
1179 }
1180
a58a38ac 1181 for (i = 0; i < LL_HIST_MAX; i++) {
d7e09d03
PT
1182 r = pp_info->pp_r_hist.oh_buckets[i];
1183 w = pp_info->pp_w_hist.oh_buckets[i];
1184 read_cum += r;
1185 write_cum += w;
1186 end = 1 << (i + LL_HIST_START - units);
2d00bd17
JP
1187 seq_printf(seq, "%4lu%c - %4lu%c%c: %14lu %4lu %4lu | %14lu %4lu %4lu\n",
1188 start, *unitp, end, *unitp,
d7e09d03
PT
1189 (i == LL_HIST_MAX - 1) ? '+' : ' ',
1190 r, pct(r, read_tot), pct(read_cum, read_tot),
1191 w, pct(w, write_tot), pct(write_cum, write_tot));
1192 start = end;
1193 if (start == 1<<10) {
1194 start = 1;
1195 units += 10;
1196 unitp++;
1197 }
1198 if (read_cum == read_tot && write_cum == write_tot)
1199 break;
1200 }
1201}
1202
1203static int ll_rw_extents_stats_pp_seq_show(struct seq_file *seq, void *v)
1204{
1205 struct timeval now;
1206 struct ll_sb_info *sbi = seq->private;
1207 struct ll_rw_extents_info *io_extents = &sbi->ll_rw_extents_info;
1208 int k;
1209
1210 do_gettimeofday(&now);
1211
1212 if (!sbi->ll_rw_stats_on) {
1213 seq_printf(seq, "disabled\n"
2d00bd17 1214 "write anything in this file to activate, then 0 or \"[D/d]isabled\" to deactivate\n");
d7e09d03
PT
1215 return 0;
1216 }
1217 seq_printf(seq, "snapshot_time: %lu.%lu (secs.usecs)\n",
996adff8 1218 now.tv_sec, (unsigned long)now.tv_usec);
d7e09d03
PT
1219 seq_printf(seq, "%15s %19s | %20s\n", " ", "read", "write");
1220 seq_printf(seq, "%13s %14s %4s %4s | %14s %4s %4s\n",
1221 "extents", "calls", "%", "cum%",
1222 "calls", "%", "cum%");
1223 spin_lock(&sbi->ll_pp_extent_lock);
1224 for (k = 0; k < LL_PROCESS_HIST_MAX; k++) {
1225 if (io_extents->pp_extents[k].pid != 0) {
1226 seq_printf(seq, "\nPID: %d\n",
1227 io_extents->pp_extents[k].pid);
1228 ll_display_extents_info(io_extents, seq, k);
1229 }
1230 }
1231 spin_unlock(&sbi->ll_pp_extent_lock);
1232 return 0;
1233}
1234
1235static ssize_t ll_rw_extents_stats_pp_seq_write(struct file *file,
a1e7e2d4
OD
1236 const char __user *buf,
1237 size_t len,
d7e09d03
PT
1238 loff_t *off)
1239{
1240 struct seq_file *seq = file->private_data;
1241 struct ll_sb_info *sbi = seq->private;
1242 struct ll_rw_extents_info *io_extents = &sbi->ll_rw_extents_info;
1243 int i;
1244 int value = 1, rc = 0;
1245
a1e7e2d4
OD
1246 if (len == 0)
1247 return -EINVAL;
1248
d7e09d03 1249 rc = lprocfs_write_helper(buf, len, &value);
a1e7e2d4
OD
1250 if (rc < 0 && len < 16) {
1251 char kernbuf[16];
1252
1253 if (copy_from_user(kernbuf, buf, len))
1254 return -EFAULT;
1255 kernbuf[len] = 0;
1256
1257 if (kernbuf[len - 1] == '\n')
1258 kernbuf[len - 1] = 0;
1259
1260 if (strcmp(kernbuf, "disabled") == 0 ||
1261 strcmp(kernbuf, "Disabled") == 0)
1262 value = 0;
1263 }
d7e09d03
PT
1264
1265 if (value == 0)
1266 sbi->ll_rw_stats_on = 0;
1267 else
1268 sbi->ll_rw_stats_on = 1;
1269
1270 spin_lock(&sbi->ll_pp_extent_lock);
1271 for (i = 0; i < LL_PROCESS_HIST_MAX; i++) {
1272 io_extents->pp_extents[i].pid = 0;
1273 lprocfs_oh_clear(&io_extents->pp_extents[i].pp_r_hist);
1274 lprocfs_oh_clear(&io_extents->pp_extents[i].pp_w_hist);
1275 }
1276 spin_unlock(&sbi->ll_pp_extent_lock);
1277 return len;
1278}
1279
1280LPROC_SEQ_FOPS(ll_rw_extents_stats_pp);
1281
1282static int ll_rw_extents_stats_seq_show(struct seq_file *seq, void *v)
1283{
1284 struct timeval now;
1285 struct ll_sb_info *sbi = seq->private;
1286 struct ll_rw_extents_info *io_extents = &sbi->ll_rw_extents_info;
1287
1288 do_gettimeofday(&now);
1289
1290 if (!sbi->ll_rw_stats_on) {
1291 seq_printf(seq, "disabled\n"
2d00bd17 1292 "write anything in this file to activate, then 0 or \"[D/d]isabled\" to deactivate\n");
d7e09d03
PT
1293 return 0;
1294 }
1295 seq_printf(seq, "snapshot_time: %lu.%lu (secs.usecs)\n",
996adff8 1296 now.tv_sec, (unsigned long)now.tv_usec);
d7e09d03
PT
1297
1298 seq_printf(seq, "%15s %19s | %20s\n", " ", "read", "write");
1299 seq_printf(seq, "%13s %14s %4s %4s | %14s %4s %4s\n",
1300 "extents", "calls", "%", "cum%",
1301 "calls", "%", "cum%");
1302 spin_lock(&sbi->ll_lock);
1303 ll_display_extents_info(io_extents, seq, LL_PROCESS_HIST_MAX);
1304 spin_unlock(&sbi->ll_lock);
1305
1306 return 0;
1307}
1308
a1e7e2d4
OD
1309static ssize_t ll_rw_extents_stats_seq_write(struct file *file,
1310 const char __user *buf,
1311 size_t len, loff_t *off)
d7e09d03
PT
1312{
1313 struct seq_file *seq = file->private_data;
1314 struct ll_sb_info *sbi = seq->private;
1315 struct ll_rw_extents_info *io_extents = &sbi->ll_rw_extents_info;
1316 int i;
1317 int value = 1, rc = 0;
1318
a1e7e2d4
OD
1319 if (len == 0)
1320 return -EINVAL;
1321
d7e09d03 1322 rc = lprocfs_write_helper(buf, len, &value);
a1e7e2d4
OD
1323 if (rc < 0 && len < 16) {
1324 char kernbuf[16];
1325
1326 if (copy_from_user(kernbuf, buf, len))
1327 return -EFAULT;
1328 kernbuf[len] = 0;
1329
1330 if (kernbuf[len - 1] == '\n')
1331 kernbuf[len - 1] = 0;
1332
1333 if (strcmp(kernbuf, "disabled") == 0 ||
1334 strcmp(kernbuf, "Disabled") == 0)
1335 value = 0;
1336 }
d7e09d03
PT
1337
1338 if (value == 0)
1339 sbi->ll_rw_stats_on = 0;
1340 else
1341 sbi->ll_rw_stats_on = 1;
a1e7e2d4 1342
d7e09d03
PT
1343 spin_lock(&sbi->ll_pp_extent_lock);
1344 for (i = 0; i <= LL_PROCESS_HIST_MAX; i++) {
1345 io_extents->pp_extents[i].pid = 0;
1346 lprocfs_oh_clear(&io_extents->pp_extents[i].pp_r_hist);
1347 lprocfs_oh_clear(&io_extents->pp_extents[i].pp_w_hist);
1348 }
1349 spin_unlock(&sbi->ll_pp_extent_lock);
1350
1351 return len;
1352}
d7e09d03
PT
1353LPROC_SEQ_FOPS(ll_rw_extents_stats);
1354
1355void ll_rw_stats_tally(struct ll_sb_info *sbi, pid_t pid,
1356 struct ll_file_data *file, loff_t pos,
1357 size_t count, int rw)
1358{
1359 int i, cur = -1;
1360 struct ll_rw_process_info *process;
1361 struct ll_rw_process_info *offset;
1362 int *off_count = &sbi->ll_rw_offset_entry_count;
1363 int *process_count = &sbi->ll_offset_process_count;
1364 struct ll_rw_extents_info *io_extents = &sbi->ll_rw_extents_info;
1365
a58a38ac 1366 if (!sbi->ll_rw_stats_on)
d7e09d03
PT
1367 return;
1368 process = sbi->ll_rw_process_info;
1369 offset = sbi->ll_rw_offset_info;
1370
1371 spin_lock(&sbi->ll_pp_extent_lock);
1372 /* Extent statistics */
a58a38ac
GD
1373 for (i = 0; i < LL_PROCESS_HIST_MAX; i++) {
1374 if (io_extents->pp_extents[i].pid == pid) {
d7e09d03
PT
1375 cur = i;
1376 break;
1377 }
1378 }
1379
1380 if (cur == -1) {
1381 /* new process */
1382 sbi->ll_extent_process_count =
1383 (sbi->ll_extent_process_count + 1) % LL_PROCESS_HIST_MAX;
1384 cur = sbi->ll_extent_process_count;
1385 io_extents->pp_extents[cur].pid = pid;
1386 lprocfs_oh_clear(&io_extents->pp_extents[cur].pp_r_hist);
1387 lprocfs_oh_clear(&io_extents->pp_extents[cur].pp_w_hist);
1388 }
1389
1390 for(i = 0; (count >= (1 << LL_HIST_START << i)) &&
1391 (i < (LL_HIST_MAX - 1)); i++);
1392 if (rw == 0) {
1393 io_extents->pp_extents[cur].pp_r_hist.oh_buckets[i]++;
1394 io_extents->pp_extents[LL_PROCESS_HIST_MAX].pp_r_hist.oh_buckets[i]++;
1395 } else {
1396 io_extents->pp_extents[cur].pp_w_hist.oh_buckets[i]++;
1397 io_extents->pp_extents[LL_PROCESS_HIST_MAX].pp_w_hist.oh_buckets[i]++;
1398 }
1399 spin_unlock(&sbi->ll_pp_extent_lock);
1400
1401 spin_lock(&sbi->ll_process_lock);
1402 /* Offset statistics */
1403 for (i = 0; i < LL_PROCESS_HIST_MAX; i++) {
1404 if (process[i].rw_pid == pid) {
1405 if (process[i].rw_last_file != file) {
1406 process[i].rw_range_start = pos;
1407 process[i].rw_last_file_pos = pos + count;
1408 process[i].rw_smallest_extent = count;
1409 process[i].rw_largest_extent = count;
1410 process[i].rw_offset = 0;
1411 process[i].rw_last_file = file;
1412 spin_unlock(&sbi->ll_process_lock);
1413 return;
1414 }
1415 if (process[i].rw_last_file_pos != pos) {
1416 *off_count =
1417 (*off_count + 1) % LL_OFFSET_HIST_MAX;
1418 offset[*off_count].rw_op = process[i].rw_op;
1419 offset[*off_count].rw_pid = pid;
1420 offset[*off_count].rw_range_start =
1421 process[i].rw_range_start;
1422 offset[*off_count].rw_range_end =
1423 process[i].rw_last_file_pos;
1424 offset[*off_count].rw_smallest_extent =
1425 process[i].rw_smallest_extent;
1426 offset[*off_count].rw_largest_extent =
1427 process[i].rw_largest_extent;
1428 offset[*off_count].rw_offset =
1429 process[i].rw_offset;
1430 process[i].rw_op = rw;
1431 process[i].rw_range_start = pos;
1432 process[i].rw_smallest_extent = count;
1433 process[i].rw_largest_extent = count;
1434 process[i].rw_offset = pos -
1435 process[i].rw_last_file_pos;
1436 }
a58a38ac 1437 if (process[i].rw_smallest_extent > count)
d7e09d03 1438 process[i].rw_smallest_extent = count;
a58a38ac 1439 if (process[i].rw_largest_extent < count)
d7e09d03
PT
1440 process[i].rw_largest_extent = count;
1441 process[i].rw_last_file_pos = pos + count;
1442 spin_unlock(&sbi->ll_process_lock);
1443 return;
1444 }
1445 }
1446 *process_count = (*process_count + 1) % LL_PROCESS_HIST_MAX;
1447 process[*process_count].rw_pid = pid;
1448 process[*process_count].rw_op = rw;
1449 process[*process_count].rw_range_start = pos;
1450 process[*process_count].rw_last_file_pos = pos + count;
1451 process[*process_count].rw_smallest_extent = count;
1452 process[*process_count].rw_largest_extent = count;
1453 process[*process_count].rw_offset = 0;
1454 process[*process_count].rw_last_file = file;
1455 spin_unlock(&sbi->ll_process_lock);
1456}
1457
1458static int ll_rw_offset_stats_seq_show(struct seq_file *seq, void *v)
1459{
1460 struct timeval now;
1461 struct ll_sb_info *sbi = seq->private;
1462 struct ll_rw_process_info *offset = sbi->ll_rw_offset_info;
1463 struct ll_rw_process_info *process = sbi->ll_rw_process_info;
1464 int i;
1465
1466 do_gettimeofday(&now);
1467
1468 if (!sbi->ll_rw_stats_on) {
1469 seq_printf(seq, "disabled\n"
2d00bd17 1470 "write anything in this file to activate, then 0 or \"[D/d]isabled\" to deactivate\n");
d7e09d03
PT
1471 return 0;
1472 }
1473 spin_lock(&sbi->ll_process_lock);
1474
1475 seq_printf(seq, "snapshot_time: %lu.%lu (secs.usecs)\n",
996adff8 1476 now.tv_sec, (unsigned long)now.tv_usec);
d7e09d03
PT
1477 seq_printf(seq, "%3s %10s %14s %14s %17s %17s %14s\n",
1478 "R/W", "PID", "RANGE START", "RANGE END",
1479 "SMALLEST EXTENT", "LARGEST EXTENT", "OFFSET");
1480 /* We stored the discontiguous offsets here; print them first */
a58a38ac 1481 for (i = 0; i < LL_OFFSET_HIST_MAX; i++) {
d7e09d03 1482 if (offset[i].rw_pid != 0)
4f37bc04
JH
1483 seq_printf(seq,
1484 "%3c %10d %14Lu %14Lu %17lu %17lu %14Lu",
1485 offset[i].rw_op == READ ? 'R' : 'W',
d7e09d03
PT
1486 offset[i].rw_pid,
1487 offset[i].rw_range_start,
1488 offset[i].rw_range_end,
1489 (unsigned long)offset[i].rw_smallest_extent,
1490 (unsigned long)offset[i].rw_largest_extent,
1491 offset[i].rw_offset);
1492 }
1493 /* Then print the current offsets for each process */
a58a38ac 1494 for (i = 0; i < LL_PROCESS_HIST_MAX; i++) {
d7e09d03 1495 if (process[i].rw_pid != 0)
4f37bc04
JH
1496 seq_printf(seq,
1497 "%3c %10d %14Lu %14Lu %17lu %17lu %14Lu",
1498 process[i].rw_op == READ ? 'R' : 'W',
d7e09d03
PT
1499 process[i].rw_pid,
1500 process[i].rw_range_start,
1501 process[i].rw_last_file_pos,
1502 (unsigned long)process[i].rw_smallest_extent,
1503 (unsigned long)process[i].rw_largest_extent,
1504 process[i].rw_offset);
1505 }
1506 spin_unlock(&sbi->ll_process_lock);
1507
1508 return 0;
1509}
1510
a1e7e2d4
OD
1511static ssize_t ll_rw_offset_stats_seq_write(struct file *file,
1512 const char __user *buf,
1513 size_t len, loff_t *off)
d7e09d03
PT
1514{
1515 struct seq_file *seq = file->private_data;
1516 struct ll_sb_info *sbi = seq->private;
1517 struct ll_rw_process_info *process_info = sbi->ll_rw_process_info;
1518 struct ll_rw_process_info *offset_info = sbi->ll_rw_offset_info;
1519 int value = 1, rc = 0;
1520
a1e7e2d4
OD
1521 if (len == 0)
1522 return -EINVAL;
1523
d7e09d03
PT
1524 rc = lprocfs_write_helper(buf, len, &value);
1525
a1e7e2d4
OD
1526 if (rc < 0 && len < 16) {
1527 char kernbuf[16];
1528
1529 if (copy_from_user(kernbuf, buf, len))
1530 return -EFAULT;
1531 kernbuf[len] = 0;
1532
1533 if (kernbuf[len - 1] == '\n')
1534 kernbuf[len - 1] = 0;
1535
1536 if (strcmp(kernbuf, "disabled") == 0 ||
1537 strcmp(kernbuf, "Disabled") == 0)
1538 value = 0;
1539 }
d7e09d03
PT
1540
1541 if (value == 0)
1542 sbi->ll_rw_stats_on = 0;
1543 else
1544 sbi->ll_rw_stats_on = 1;
1545
1546 spin_lock(&sbi->ll_process_lock);
1547 sbi->ll_offset_process_count = 0;
1548 sbi->ll_rw_offset_entry_count = 0;
1549 memset(process_info, 0, sizeof(struct ll_rw_process_info) *
1550 LL_PROCESS_HIST_MAX);
1551 memset(offset_info, 0, sizeof(struct ll_rw_process_info) *
1552 LL_OFFSET_HIST_MAX);
1553 spin_unlock(&sbi->ll_process_lock);
1554
1555 return len;
1556}
1557
1558LPROC_SEQ_FOPS(ll_rw_offset_stats);
1559
1560void lprocfs_llite_init_vars(struct lprocfs_static_vars *lvars)
1561{
1562 lvars->module_vars = NULL;
1563 lvars->obd_vars = lprocfs_llite_obd_vars;
1564}