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