4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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
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
27 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Use is subject to license terms.
30 * Copyright (c) 2011, 2012, Intel Corporation.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
36 #define DEBUG_SUBSYSTEM S_LLITE
38 #include "../include/lustre_lite.h"
39 #include "../include/lprocfs_status.h"
40 #include <linux/seq_file.h>
41 #include "../include/obd_support.h"
43 #include "llite_internal.h"
44 #include "vvp_internal.h"
46 /* /proc/lustre/llite mount point registration */
47 static struct file_operations ll_rw_extents_stats_fops;
48 static struct file_operations ll_rw_extents_stats_pp_fops;
49 static struct file_operations ll_rw_offset_stats_fops;
51 static ssize_t blocksize_show(struct kobject *kobj, struct attribute *attr,
54 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
56 struct obd_statfs osfs;
59 rc = ll_statfs_internal(sbi->ll_sb, &osfs,
60 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
63 return sprintf(buf, "%u\n", osfs.os_bsize);
67 LUSTRE_RO_ATTR(blocksize);
69 static ssize_t kbytestotal_show(struct kobject *kobj, struct attribute *attr,
72 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
74 struct obd_statfs osfs;
77 rc = ll_statfs_internal(sbi->ll_sb, &osfs,
78 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
81 __u32 blk_size = osfs.os_bsize >> 10;
82 __u64 result = osfs.os_blocks;
84 while (blk_size >>= 1)
87 rc = sprintf(buf, "%llu\n", result);
92 LUSTRE_RO_ATTR(kbytestotal);
94 static ssize_t kbytesfree_show(struct kobject *kobj, struct attribute *attr,
97 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
99 struct obd_statfs osfs;
102 rc = ll_statfs_internal(sbi->ll_sb, &osfs,
103 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
106 __u32 blk_size = osfs.os_bsize >> 10;
107 __u64 result = osfs.os_bfree;
109 while (blk_size >>= 1)
112 rc = sprintf(buf, "%llu\n", result);
117 LUSTRE_RO_ATTR(kbytesfree);
119 static ssize_t kbytesavail_show(struct kobject *kobj, struct attribute *attr,
122 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
124 struct obd_statfs osfs;
127 rc = ll_statfs_internal(sbi->ll_sb, &osfs,
128 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
131 __u32 blk_size = osfs.os_bsize >> 10;
132 __u64 result = osfs.os_bavail;
134 while (blk_size >>= 1)
137 rc = sprintf(buf, "%llu\n", result);
142 LUSTRE_RO_ATTR(kbytesavail);
144 static ssize_t filestotal_show(struct kobject *kobj, struct attribute *attr,
147 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
149 struct obd_statfs osfs;
152 rc = ll_statfs_internal(sbi->ll_sb, &osfs,
153 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
156 return sprintf(buf, "%llu\n", osfs.os_files);
160 LUSTRE_RO_ATTR(filestotal);
162 static ssize_t filesfree_show(struct kobject *kobj, struct attribute *attr,
165 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
167 struct obd_statfs osfs;
170 rc = ll_statfs_internal(sbi->ll_sb, &osfs,
171 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
174 return sprintf(buf, "%llu\n", osfs.os_ffree);
178 LUSTRE_RO_ATTR(filesfree);
180 static ssize_t client_type_show(struct kobject *kobj, struct attribute *attr,
183 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
186 return sprintf(buf, "%s client\n",
187 sbi->ll_flags & LL_SBI_RMT_CLIENT ? "remote" : "local");
189 LUSTRE_RO_ATTR(client_type);
191 static ssize_t fstype_show(struct kobject *kobj, struct attribute *attr,
194 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
197 return sprintf(buf, "%s\n", sbi->ll_sb->s_type->name);
199 LUSTRE_RO_ATTR(fstype);
201 static ssize_t uuid_show(struct kobject *kobj, struct attribute *attr,
204 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
207 return sprintf(buf, "%s\n", sbi->ll_sb_uuid.uuid);
209 LUSTRE_RO_ATTR(uuid);
211 static int ll_site_stats_seq_show(struct seq_file *m, void *v)
213 struct super_block *sb = m->private;
216 * See description of statistical counters in struct cl_site, and
219 return cl_site_stats_print(lu2cl_site(ll_s2sbi(sb)->ll_site), m);
221 LPROC_SEQ_FOPS_RO(ll_site_stats);
223 static ssize_t max_read_ahead_mb_show(struct kobject *kobj,
224 struct attribute *attr, char *buf)
226 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
231 spin_lock(&sbi->ll_lock);
232 pages_number = sbi->ll_ra_info.ra_max_pages;
233 spin_unlock(&sbi->ll_lock);
235 mult = 1 << (20 - PAGE_CACHE_SHIFT);
236 return lprocfs_read_frac_helper(buf, PAGE_SIZE, pages_number, mult);
239 static ssize_t max_read_ahead_mb_store(struct kobject *kobj,
240 struct attribute *attr,
244 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
247 unsigned long pages_number;
249 rc = kstrtoul(buffer, 10, &pages_number);
253 pages_number *= 1 << (20 - PAGE_CACHE_SHIFT); /* MB -> pages */
255 if (pages_number > totalram_pages / 2) {
257 CERROR("can't set file readahead more than %lu MB\n",
258 totalram_pages >> (20 - PAGE_CACHE_SHIFT + 1)); /*1/2 of RAM*/
262 spin_lock(&sbi->ll_lock);
263 sbi->ll_ra_info.ra_max_pages = pages_number;
264 spin_unlock(&sbi->ll_lock);
268 LUSTRE_RW_ATTR(max_read_ahead_mb);
270 static ssize_t max_read_ahead_per_file_mb_show(struct kobject *kobj,
271 struct attribute *attr,
274 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
279 spin_lock(&sbi->ll_lock);
280 pages_number = sbi->ll_ra_info.ra_max_pages_per_file;
281 spin_unlock(&sbi->ll_lock);
283 mult = 1 << (20 - PAGE_CACHE_SHIFT);
284 return lprocfs_read_frac_helper(buf, PAGE_SIZE, pages_number, mult);
287 static ssize_t max_read_ahead_per_file_mb_store(struct kobject *kobj,
288 struct attribute *attr,
292 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
295 unsigned long pages_number;
297 rc = kstrtoul(buffer, 10, &pages_number);
301 if (pages_number > sbi->ll_ra_info.ra_max_pages) {
302 CERROR("can't set file readahead more than max_read_ahead_mb %lu MB\n",
303 sbi->ll_ra_info.ra_max_pages);
307 spin_lock(&sbi->ll_lock);
308 sbi->ll_ra_info.ra_max_pages_per_file = pages_number;
309 spin_unlock(&sbi->ll_lock);
313 LUSTRE_RW_ATTR(max_read_ahead_per_file_mb);
315 static int ll_max_read_ahead_whole_mb_seq_show(struct seq_file *m, void *unused)
317 struct super_block *sb = m->private;
318 struct ll_sb_info *sbi = ll_s2sbi(sb);
322 spin_lock(&sbi->ll_lock);
323 pages_number = sbi->ll_ra_info.ra_max_read_ahead_whole_pages;
324 spin_unlock(&sbi->ll_lock);
326 mult = 1 << (20 - PAGE_CACHE_SHIFT);
327 return lprocfs_seq_read_frac_helper(m, pages_number, mult);
330 static ssize_t ll_max_read_ahead_whole_mb_seq_write(struct file *file,
331 const char __user *buffer,
332 size_t count, loff_t *off)
334 struct super_block *sb = ((struct seq_file *)file->private_data)->private;
335 struct ll_sb_info *sbi = ll_s2sbi(sb);
336 int mult, rc, pages_number;
338 mult = 1 << (20 - PAGE_CACHE_SHIFT);
339 rc = lprocfs_write_frac_helper(buffer, count, &pages_number, mult);
343 /* Cap this at the current max readahead window size, the readahead
344 * algorithm does this anyway so it's pointless to set it larger. */
345 if (pages_number < 0 ||
346 pages_number > sbi->ll_ra_info.ra_max_pages_per_file) {
347 CERROR("can't set max_read_ahead_whole_mb more than max_read_ahead_per_file_mb: %lu\n",
348 sbi->ll_ra_info.ra_max_pages_per_file >> (20 - PAGE_CACHE_SHIFT));
352 spin_lock(&sbi->ll_lock);
353 sbi->ll_ra_info.ra_max_read_ahead_whole_pages = pages_number;
354 spin_unlock(&sbi->ll_lock);
358 LPROC_SEQ_FOPS(ll_max_read_ahead_whole_mb);
360 static int ll_max_cached_mb_seq_show(struct seq_file *m, void *v)
362 struct super_block *sb = m->private;
363 struct ll_sb_info *sbi = ll_s2sbi(sb);
364 struct cl_client_cache *cache = &sbi->ll_cache;
365 int shift = 20 - PAGE_CACHE_SHIFT;
369 max_cached_mb = cache->ccc_lru_max >> shift;
370 unused_mb = atomic_read(&cache->ccc_lru_left) >> shift;
373 "max_cached_mb: %d\n"
376 "reclaim_count: %u\n",
377 atomic_read(&cache->ccc_users),
379 max_cached_mb - unused_mb,
381 cache->ccc_lru_shrinkers);
385 static ssize_t ll_max_cached_mb_seq_write(struct file *file,
386 const char __user *buffer,
387 size_t count, loff_t *off)
389 struct super_block *sb = ((struct seq_file *)file->private_data)->private;
390 struct ll_sb_info *sbi = ll_s2sbi(sb);
391 struct cl_client_cache *cache = &sbi->ll_cache;
392 int mult, rc, pages_number;
397 if (count >= sizeof(kernbuf))
400 if (copy_from_user(kernbuf, buffer, count))
404 mult = 1 << (20 - PAGE_CACHE_SHIFT);
405 buffer += lprocfs_find_named_value(kernbuf, "max_cached_mb:", &count) -
407 rc = lprocfs_write_frac_helper(buffer, count, &pages_number, mult);
411 if (pages_number < 0 || pages_number > totalram_pages) {
412 CERROR("%s: can't set max cache more than %lu MB\n",
413 ll_get_fsname(sb, NULL, 0),
414 totalram_pages >> (20 - PAGE_CACHE_SHIFT));
418 spin_lock(&sbi->ll_lock);
419 diff = pages_number - cache->ccc_lru_max;
420 spin_unlock(&sbi->ll_lock);
422 /* easy - add more LRU slots. */
424 atomic_add(diff, &cache->ccc_lru_left);
433 /* reduce LRU budget from free slots. */
437 ov = atomic_read(&cache->ccc_lru_left);
441 nv = ov > diff ? ov - diff : 0;
442 rc = atomic_cmpxchg(&cache->ccc_lru_left, ov, nv);
443 if (likely(ov == rc)) {
453 if (sbi->ll_dt_exp == NULL) { /* being initialized */
458 /* difficult - have to ask OSCs to drop LRU slots. */
460 rc = obd_set_info_async(NULL, sbi->ll_dt_exp,
461 sizeof(KEY_CACHE_LRU_SHRINK),
462 KEY_CACHE_LRU_SHRINK,
463 sizeof(tmp), &tmp, NULL);
470 spin_lock(&sbi->ll_lock);
471 cache->ccc_lru_max = pages_number;
472 spin_unlock(&sbi->ll_lock);
475 atomic_add(nrpages, &cache->ccc_lru_left);
479 LPROC_SEQ_FOPS(ll_max_cached_mb);
481 static int ll_checksum_seq_show(struct seq_file *m, void *v)
483 struct super_block *sb = m->private;
484 struct ll_sb_info *sbi = ll_s2sbi(sb);
486 seq_printf(m, "%u\n", (sbi->ll_flags & LL_SBI_CHECKSUM) ? 1 : 0);
490 static ssize_t ll_checksum_seq_write(struct file *file,
491 const char __user *buffer,
492 size_t count, loff_t *off)
494 struct super_block *sb = ((struct seq_file *)file->private_data)->private;
495 struct ll_sb_info *sbi = ll_s2sbi(sb);
502 rc = lprocfs_write_helper(buffer, count, &val);
506 sbi->ll_flags |= LL_SBI_CHECKSUM;
508 sbi->ll_flags &= ~LL_SBI_CHECKSUM;
510 rc = obd_set_info_async(NULL, sbi->ll_dt_exp, sizeof(KEY_CHECKSUM),
511 KEY_CHECKSUM, sizeof(val), &val, NULL);
513 CWARN("Failed to set OSC checksum flags: %d\n", rc);
517 LPROC_SEQ_FOPS(ll_checksum);
519 static int ll_max_rw_chunk_seq_show(struct seq_file *m, void *v)
521 struct super_block *sb = m->private;
523 seq_printf(m, "%lu\n", ll_s2sbi(sb)->ll_max_rw_chunk);
527 static ssize_t ll_max_rw_chunk_seq_write(struct file *file,
528 const char __user *buffer,
529 size_t count, loff_t *off)
531 struct super_block *sb = ((struct seq_file *)file->private_data)->private;
534 rc = lprocfs_write_helper(buffer, count, &val);
537 ll_s2sbi(sb)->ll_max_rw_chunk = val;
540 LPROC_SEQ_FOPS(ll_max_rw_chunk);
542 static int ll_rd_track_id(struct seq_file *m, enum stats_track_type type)
544 struct super_block *sb = m->private;
546 if (ll_s2sbi(sb)->ll_stats_track_type == type)
547 seq_printf(m, "%d\n", ll_s2sbi(sb)->ll_stats_track_id);
548 else if (ll_s2sbi(sb)->ll_stats_track_type == STATS_TRACK_ALL)
549 seq_puts(m, "0 (all)\n");
551 seq_puts(m, "untracked\n");
556 static int ll_wr_track_id(const char __user *buffer, unsigned long count,
557 void *data, enum stats_track_type type)
559 struct super_block *sb = data;
562 rc = lprocfs_write_helper(buffer, count, &pid);
565 ll_s2sbi(sb)->ll_stats_track_id = pid;
567 ll_s2sbi(sb)->ll_stats_track_type = STATS_TRACK_ALL;
569 ll_s2sbi(sb)->ll_stats_track_type = type;
570 lprocfs_clear_stats(ll_s2sbi(sb)->ll_stats);
574 static int ll_track_pid_seq_show(struct seq_file *m, void *v)
576 return ll_rd_track_id(m, STATS_TRACK_PID);
579 static ssize_t ll_track_pid_seq_write(struct file *file,
580 const char __user *buffer,
581 size_t count, loff_t *off)
583 struct seq_file *seq = file->private_data;
584 return ll_wr_track_id(buffer, count, seq->private, STATS_TRACK_PID);
586 LPROC_SEQ_FOPS(ll_track_pid);
588 static int ll_track_ppid_seq_show(struct seq_file *m, void *v)
590 return ll_rd_track_id(m, STATS_TRACK_PPID);
593 static ssize_t ll_track_ppid_seq_write(struct file *file,
594 const char __user *buffer,
595 size_t count, loff_t *off)
597 struct seq_file *seq = file->private_data;
598 return ll_wr_track_id(buffer, count, seq->private, STATS_TRACK_PPID);
600 LPROC_SEQ_FOPS(ll_track_ppid);
602 static int ll_track_gid_seq_show(struct seq_file *m, void *v)
604 return ll_rd_track_id(m, STATS_TRACK_GID);
607 static ssize_t ll_track_gid_seq_write(struct file *file,
608 const char __user *buffer,
609 size_t count, loff_t *off)
611 struct seq_file *seq = file->private_data;
612 return ll_wr_track_id(buffer, count, seq->private, STATS_TRACK_GID);
614 LPROC_SEQ_FOPS(ll_track_gid);
616 static int ll_statahead_max_seq_show(struct seq_file *m, void *v)
618 struct super_block *sb = m->private;
619 struct ll_sb_info *sbi = ll_s2sbi(sb);
621 seq_printf(m, "%u\n", sbi->ll_sa_max);
625 static ssize_t ll_statahead_max_seq_write(struct file *file,
626 const char __user *buffer,
627 size_t count, loff_t *off)
629 struct super_block *sb = ((struct seq_file *)file->private_data)->private;
630 struct ll_sb_info *sbi = ll_s2sbi(sb);
633 rc = lprocfs_write_helper(buffer, count, &val);
637 if (val >= 0 && val <= LL_SA_RPC_MAX)
638 sbi->ll_sa_max = val;
640 CERROR("Bad statahead_max value %d. Valid values are in the range [0, %d]\n",
645 LPROC_SEQ_FOPS(ll_statahead_max);
647 static int ll_statahead_agl_seq_show(struct seq_file *m, void *v)
649 struct super_block *sb = m->private;
650 struct ll_sb_info *sbi = ll_s2sbi(sb);
652 seq_printf(m, "%u\n", sbi->ll_flags & LL_SBI_AGL_ENABLED ? 1 : 0);
656 static ssize_t ll_statahead_agl_seq_write(struct file *file,
657 const char __user *buffer,
658 size_t count, loff_t *off)
660 struct super_block *sb = ((struct seq_file *)file->private_data)->private;
661 struct ll_sb_info *sbi = ll_s2sbi(sb);
664 rc = lprocfs_write_helper(buffer, count, &val);
669 sbi->ll_flags |= LL_SBI_AGL_ENABLED;
671 sbi->ll_flags &= ~LL_SBI_AGL_ENABLED;
675 LPROC_SEQ_FOPS(ll_statahead_agl);
677 static int ll_statahead_stats_seq_show(struct seq_file *m, void *v)
679 struct super_block *sb = m->private;
680 struct ll_sb_info *sbi = ll_s2sbi(sb);
683 "statahead total: %u\n"
684 "statahead wrong: %u\n"
686 atomic_read(&sbi->ll_sa_total),
687 atomic_read(&sbi->ll_sa_wrong),
688 atomic_read(&sbi->ll_agl_total));
691 LPROC_SEQ_FOPS_RO(ll_statahead_stats);
693 static int ll_lazystatfs_seq_show(struct seq_file *m, void *v)
695 struct super_block *sb = m->private;
696 struct ll_sb_info *sbi = ll_s2sbi(sb);
698 seq_printf(m, "%u\n", sbi->ll_flags & LL_SBI_LAZYSTATFS ? 1 : 0);
702 static ssize_t ll_lazystatfs_seq_write(struct file *file,
703 const char __user *buffer,
704 size_t count, loff_t *off)
706 struct super_block *sb = ((struct seq_file *)file->private_data)->private;
707 struct ll_sb_info *sbi = ll_s2sbi(sb);
710 rc = lprocfs_write_helper(buffer, count, &val);
715 sbi->ll_flags |= LL_SBI_LAZYSTATFS;
717 sbi->ll_flags &= ~LL_SBI_LAZYSTATFS;
721 LPROC_SEQ_FOPS(ll_lazystatfs);
723 static int ll_max_easize_seq_show(struct seq_file *m, void *v)
725 struct super_block *sb = m->private;
726 struct ll_sb_info *sbi = ll_s2sbi(sb);
730 rc = ll_get_max_mdsize(sbi, &ealen);
734 seq_printf(m, "%u\n", ealen);
737 LPROC_SEQ_FOPS_RO(ll_max_easize);
739 static int ll_default_easize_seq_show(struct seq_file *m, void *v)
741 struct super_block *sb = m->private;
742 struct ll_sb_info *sbi = ll_s2sbi(sb);
746 rc = ll_get_default_mdsize(sbi, &ealen);
750 seq_printf(m, "%u\n", ealen);
753 LPROC_SEQ_FOPS_RO(ll_default_easize);
755 static int ll_max_cookiesize_seq_show(struct seq_file *m, void *v)
757 struct super_block *sb = m->private;
758 struct ll_sb_info *sbi = ll_s2sbi(sb);
759 unsigned int cookielen;
762 rc = ll_get_max_cookiesize(sbi, &cookielen);
766 seq_printf(m, "%u\n", cookielen);
769 LPROC_SEQ_FOPS_RO(ll_max_cookiesize);
771 static int ll_default_cookiesize_seq_show(struct seq_file *m, void *v)
773 struct super_block *sb = m->private;
774 struct ll_sb_info *sbi = ll_s2sbi(sb);
775 unsigned int cookielen;
778 rc = ll_get_default_cookiesize(sbi, &cookielen);
782 seq_printf(m, "%u\n", cookielen);
785 LPROC_SEQ_FOPS_RO(ll_default_cookiesize);
787 static int ll_sbi_flags_seq_show(struct seq_file *m, void *v)
789 const char *str[] = LL_SBI_FLAGS;
790 struct super_block *sb = m->private;
791 int flags = ll_s2sbi(sb)->ll_flags;
795 if (ARRAY_SIZE(str) <= i) {
796 CERROR("%s: Revise array LL_SBI_FLAGS to match sbi flags please.\n",
797 ll_get_fsname(sb, NULL, 0));
802 seq_printf(m, "%s ", str[i]);
806 seq_printf(m, "\b\n");
809 LPROC_SEQ_FOPS_RO(ll_sbi_flags);
811 static int ll_xattr_cache_seq_show(struct seq_file *m, void *v)
813 struct super_block *sb = m->private;
814 struct ll_sb_info *sbi = ll_s2sbi(sb);
816 seq_printf(m, "%u\n", sbi->ll_xattr_cache_enabled);
821 static ssize_t ll_xattr_cache_seq_write(struct file *file,
822 const char __user *buffer,
823 size_t count, loff_t *off)
825 struct seq_file *seq = file->private_data;
826 struct super_block *sb = seq->private;
827 struct ll_sb_info *sbi = ll_s2sbi(sb);
830 rc = lprocfs_write_helper(buffer, count, &val);
834 if (val != 0 && val != 1)
837 if (val == 1 && !(sbi->ll_flags & LL_SBI_XATTR_CACHE))
840 sbi->ll_xattr_cache_enabled = val;
844 LPROC_SEQ_FOPS(ll_xattr_cache);
846 static struct lprocfs_vars lprocfs_llite_obd_vars[] = {
847 /* { "mntpt_path", ll_rd_path, 0, 0 }, */
848 { "site", &ll_site_stats_fops, NULL, 0 },
849 /* { "filegroups", lprocfs_rd_filegroups, 0, 0 }, */
850 { "max_read_ahead_whole_mb", &ll_max_read_ahead_whole_mb_fops, NULL },
851 { "max_cached_mb", &ll_max_cached_mb_fops, NULL },
852 { "checksum_pages", &ll_checksum_fops, NULL },
853 { "max_rw_chunk", &ll_max_rw_chunk_fops, NULL },
854 { "stats_track_pid", &ll_track_pid_fops, NULL },
855 { "stats_track_ppid", &ll_track_ppid_fops, NULL },
856 { "stats_track_gid", &ll_track_gid_fops, NULL },
857 { "statahead_max", &ll_statahead_max_fops, NULL },
858 { "statahead_agl", &ll_statahead_agl_fops, NULL },
859 { "statahead_stats", &ll_statahead_stats_fops, NULL, 0 },
860 { "lazystatfs", &ll_lazystatfs_fops, NULL },
861 { "max_easize", &ll_max_easize_fops, NULL, 0 },
862 { "default_easize", &ll_default_easize_fops, NULL, 0 },
863 { "max_cookiesize", &ll_max_cookiesize_fops, NULL, 0 },
864 { "default_cookiesize", &ll_default_cookiesize_fops, NULL, 0 },
865 { "sbi_flags", &ll_sbi_flags_fops, NULL, 0 },
866 { "xattr_cache", &ll_xattr_cache_fops, NULL, 0 },
870 #define MAX_STRING_SIZE 128
872 static struct attribute *llite_attrs[] = {
873 &lustre_attr_blocksize.attr,
874 &lustre_attr_kbytestotal.attr,
875 &lustre_attr_kbytesfree.attr,
876 &lustre_attr_kbytesavail.attr,
877 &lustre_attr_filestotal.attr,
878 &lustre_attr_filesfree.attr,
879 &lustre_attr_client_type.attr,
880 &lustre_attr_fstype.attr,
881 &lustre_attr_uuid.attr,
882 &lustre_attr_max_read_ahead_mb.attr,
883 &lustre_attr_max_read_ahead_per_file_mb.attr,
887 static void llite_sb_release(struct kobject *kobj)
889 struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
891 complete(&sbi->ll_kobj_unregister);
894 static struct kobj_type llite_ktype = {
895 .default_attrs = llite_attrs,
896 .sysfs_ops = &lustre_sysfs_ops,
897 .release = llite_sb_release,
900 static const struct llite_file_opcode {
904 } llite_opcode_table[LPROC_LL_FILE_OPCODES] = {
906 { LPROC_LL_DIRTY_HITS, LPROCFS_TYPE_REGS, "dirty_pages_hits" },
907 { LPROC_LL_DIRTY_MISSES, LPROCFS_TYPE_REGS, "dirty_pages_misses" },
908 { LPROC_LL_READ_BYTES, LPROCFS_CNTR_AVGMINMAX|LPROCFS_TYPE_BYTES,
910 { LPROC_LL_WRITE_BYTES, LPROCFS_CNTR_AVGMINMAX|LPROCFS_TYPE_BYTES,
912 { LPROC_LL_BRW_READ, LPROCFS_CNTR_AVGMINMAX|LPROCFS_TYPE_PAGES,
914 { LPROC_LL_BRW_WRITE, LPROCFS_CNTR_AVGMINMAX|LPROCFS_TYPE_PAGES,
916 { LPROC_LL_OSC_READ, LPROCFS_CNTR_AVGMINMAX|LPROCFS_TYPE_BYTES,
918 { LPROC_LL_OSC_WRITE, LPROCFS_CNTR_AVGMINMAX|LPROCFS_TYPE_BYTES,
920 { LPROC_LL_IOCTL, LPROCFS_TYPE_REGS, "ioctl" },
921 { LPROC_LL_OPEN, LPROCFS_TYPE_REGS, "open" },
922 { LPROC_LL_RELEASE, LPROCFS_TYPE_REGS, "close" },
923 { LPROC_LL_MAP, LPROCFS_TYPE_REGS, "mmap" },
924 { LPROC_LL_LLSEEK, LPROCFS_TYPE_REGS, "seek" },
925 { LPROC_LL_FSYNC, LPROCFS_TYPE_REGS, "fsync" },
926 { LPROC_LL_READDIR, LPROCFS_TYPE_REGS, "readdir" },
927 /* inode operation */
928 { LPROC_LL_SETATTR, LPROCFS_TYPE_REGS, "setattr" },
929 { LPROC_LL_TRUNC, LPROCFS_TYPE_REGS, "truncate" },
930 { LPROC_LL_FLOCK, LPROCFS_TYPE_REGS, "flock" },
931 { LPROC_LL_GETATTR, LPROCFS_TYPE_REGS, "getattr" },
932 /* dir inode operation */
933 { LPROC_LL_CREATE, LPROCFS_TYPE_REGS, "create" },
934 { LPROC_LL_LINK, LPROCFS_TYPE_REGS, "link" },
935 { LPROC_LL_UNLINK, LPROCFS_TYPE_REGS, "unlink" },
936 { LPROC_LL_SYMLINK, LPROCFS_TYPE_REGS, "symlink" },
937 { LPROC_LL_MKDIR, LPROCFS_TYPE_REGS, "mkdir" },
938 { LPROC_LL_RMDIR, LPROCFS_TYPE_REGS, "rmdir" },
939 { LPROC_LL_MKNOD, LPROCFS_TYPE_REGS, "mknod" },
940 { LPROC_LL_RENAME, LPROCFS_TYPE_REGS, "rename" },
941 /* special inode operation */
942 { LPROC_LL_STAFS, LPROCFS_TYPE_REGS, "statfs" },
943 { LPROC_LL_ALLOC_INODE, LPROCFS_TYPE_REGS, "alloc_inode" },
944 { LPROC_LL_SETXATTR, LPROCFS_TYPE_REGS, "setxattr" },
945 { LPROC_LL_GETXATTR, LPROCFS_TYPE_REGS, "getxattr" },
946 { LPROC_LL_GETXATTR_HITS, LPROCFS_TYPE_REGS, "getxattr_hits" },
947 { LPROC_LL_LISTXATTR, LPROCFS_TYPE_REGS, "listxattr" },
948 { LPROC_LL_REMOVEXATTR, LPROCFS_TYPE_REGS, "removexattr" },
949 { LPROC_LL_INODE_PERM, LPROCFS_TYPE_REGS, "inode_permission" },
952 void ll_stats_ops_tally(struct ll_sb_info *sbi, int op, int count)
956 if (sbi->ll_stats_track_type == STATS_TRACK_ALL)
957 lprocfs_counter_add(sbi->ll_stats, op, count);
958 else if (sbi->ll_stats_track_type == STATS_TRACK_PID &&
959 sbi->ll_stats_track_id == current->pid)
960 lprocfs_counter_add(sbi->ll_stats, op, count);
961 else if (sbi->ll_stats_track_type == STATS_TRACK_PPID &&
962 sbi->ll_stats_track_id == current->real_parent->pid)
963 lprocfs_counter_add(sbi->ll_stats, op, count);
964 else if (sbi->ll_stats_track_type == STATS_TRACK_GID &&
965 sbi->ll_stats_track_id ==
966 from_kgid(&init_user_ns, current_gid()))
967 lprocfs_counter_add(sbi->ll_stats, op, count);
969 EXPORT_SYMBOL(ll_stats_ops_tally);
971 static const char *ra_stat_string[] = {
972 [RA_STAT_HIT] = "hits",
973 [RA_STAT_MISS] = "misses",
974 [RA_STAT_DISTANT_READPAGE] = "readpage not consecutive",
975 [RA_STAT_MISS_IN_WINDOW] = "miss inside window",
976 [RA_STAT_FAILED_GRAB_PAGE] = "failed grab_cache_page",
977 [RA_STAT_FAILED_MATCH] = "failed lock match",
978 [RA_STAT_DISCARDED] = "read but discarded",
979 [RA_STAT_ZERO_LEN] = "zero length file",
980 [RA_STAT_ZERO_WINDOW] = "zero size window",
981 [RA_STAT_EOF] = "read-ahead to EOF",
982 [RA_STAT_MAX_IN_FLIGHT] = "hit max r-a issue",
983 [RA_STAT_WRONG_GRAB_PAGE] = "wrong page from grab_cache_page",
986 LPROC_SEQ_FOPS_RO_TYPE(llite, name);
987 LPROC_SEQ_FOPS_RO_TYPE(llite, uuid);
989 int lprocfs_register_mountpoint(struct proc_dir_entry *parent,
990 struct super_block *sb, char *osc, char *mdc)
992 struct lprocfs_vars lvars[2];
993 struct lustre_sb_info *lsi = s2lsi(sb);
994 struct ll_sb_info *sbi = ll_s2sbi(sb);
995 struct obd_device *obd;
996 struct proc_dir_entry *dir;
997 char name[MAX_STRING_SIZE + 1], *ptr;
998 int err, id, len, rc;
1000 memset(lvars, 0, sizeof(lvars));
1002 name[MAX_STRING_SIZE] = '\0';
1003 lvars[0].name = name;
1005 LASSERT(sbi != NULL);
1006 LASSERT(mdc != NULL);
1007 LASSERT(osc != NULL);
1010 len = strlen(lsi->lsi_lmd->lmd_profile);
1011 ptr = strrchr(lsi->lsi_lmd->lmd_profile, '-');
1012 if (ptr && (strcmp(ptr, "-client") == 0))
1016 snprintf(name, MAX_STRING_SIZE, "%.*s-%p", len,
1017 lsi->lsi_lmd->lmd_profile, sb);
1019 sbi->ll_proc_root = lprocfs_register(name, parent, NULL, NULL);
1020 if (IS_ERR(sbi->ll_proc_root)) {
1021 err = PTR_ERR(sbi->ll_proc_root);
1022 sbi->ll_proc_root = NULL;
1026 rc = lprocfs_seq_create(sbi->ll_proc_root, "dump_page_cache", 0444,
1027 &vvp_dump_pgcache_file_ops, sbi);
1029 CWARN("Error adding the dump_page_cache file\n");
1031 rc = lprocfs_seq_create(sbi->ll_proc_root, "extents_stats", 0644,
1032 &ll_rw_extents_stats_fops, sbi);
1034 CWARN("Error adding the extent_stats file\n");
1036 rc = lprocfs_seq_create(sbi->ll_proc_root, "extents_stats_per_process",
1037 0644, &ll_rw_extents_stats_pp_fops, sbi);
1039 CWARN("Error adding the extents_stats_per_process file\n");
1041 rc = lprocfs_seq_create(sbi->ll_proc_root, "offset_stats", 0644,
1042 &ll_rw_offset_stats_fops, sbi);
1044 CWARN("Error adding the offset_stats file\n");
1046 /* File operations stats */
1047 sbi->ll_stats = lprocfs_alloc_stats(LPROC_LL_FILE_OPCODES,
1048 LPROCFS_STATS_FLAG_NONE);
1049 if (sbi->ll_stats == NULL) {
1053 /* do counter init */
1054 for (id = 0; id < LPROC_LL_FILE_OPCODES; id++) {
1055 __u32 type = llite_opcode_table[id].type;
1057 if (type & LPROCFS_TYPE_REGS)
1059 else if (type & LPROCFS_TYPE_BYTES)
1061 else if (type & LPROCFS_TYPE_PAGES)
1063 lprocfs_counter_init(sbi->ll_stats,
1064 llite_opcode_table[id].opcode,
1065 (type & LPROCFS_CNTR_AVGMINMAX),
1066 llite_opcode_table[id].opname, ptr);
1068 err = lprocfs_register_stats(sbi->ll_proc_root, "stats", sbi->ll_stats);
1072 sbi->ll_ra_stats = lprocfs_alloc_stats(ARRAY_SIZE(ra_stat_string),
1073 LPROCFS_STATS_FLAG_NONE);
1074 if (sbi->ll_ra_stats == NULL) {
1079 for (id = 0; id < ARRAY_SIZE(ra_stat_string); id++)
1080 lprocfs_counter_init(sbi->ll_ra_stats, id, 0,
1081 ra_stat_string[id], "pages");
1082 err = lprocfs_register_stats(sbi->ll_proc_root, "read_ahead_stats",
1088 err = lprocfs_add_vars(sbi->ll_proc_root, lprocfs_llite_obd_vars, sb);
1092 sbi->ll_kobj.kset = llite_kset;
1093 init_completion(&sbi->ll_kobj_unregister);
1094 err = kobject_init_and_add(&sbi->ll_kobj, &llite_ktype, NULL,
1100 obd = class_name2obd(mdc);
1102 LASSERT(obd != NULL);
1103 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1104 LASSERT(obd->obd_type->typ_name != NULL);
1106 dir = proc_mkdir(obd->obd_type->typ_name, sbi->ll_proc_root);
1112 snprintf(name, MAX_STRING_SIZE, "common_name");
1113 lvars[0].fops = &llite_name_fops;
1114 err = lprocfs_add_vars(dir, lvars, obd);
1118 snprintf(name, MAX_STRING_SIZE, "uuid");
1119 lvars[0].fops = &llite_uuid_fops;
1120 err = lprocfs_add_vars(dir, lvars, obd);
1125 obd = class_name2obd(osc);
1127 LASSERT(obd != NULL);
1128 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1129 LASSERT(obd->obd_type->typ_name != NULL);
1131 dir = proc_mkdir(obd->obd_type->typ_name, sbi->ll_proc_root);
1137 snprintf(name, MAX_STRING_SIZE, "common_name");
1138 lvars[0].fops = &llite_name_fops;
1139 err = lprocfs_add_vars(dir, lvars, obd);
1143 snprintf(name, MAX_STRING_SIZE, "uuid");
1144 lvars[0].fops = &llite_uuid_fops;
1145 err = lprocfs_add_vars(dir, lvars, obd);
1148 lprocfs_remove(&sbi->ll_proc_root);
1149 lprocfs_free_stats(&sbi->ll_ra_stats);
1150 lprocfs_free_stats(&sbi->ll_stats);
1155 void lprocfs_unregister_mountpoint(struct ll_sb_info *sbi)
1157 if (sbi->ll_proc_root) {
1158 lprocfs_remove(&sbi->ll_proc_root);
1159 kobject_put(&sbi->ll_kobj);
1160 wait_for_completion(&sbi->ll_kobj_unregister);
1161 lprocfs_free_stats(&sbi->ll_ra_stats);
1162 lprocfs_free_stats(&sbi->ll_stats);
1165 #undef MAX_STRING_SIZE
1167 #define pct(a, b) (b ? a * 100 / b : 0)
1169 static void ll_display_extents_info(struct ll_rw_extents_info *io_extents,
1170 struct seq_file *seq, int which)
1172 unsigned long read_tot = 0, write_tot = 0, read_cum, write_cum;
1173 unsigned long start, end, r, w;
1174 char *unitp = "KMGTPEZY";
1176 struct per_process_info *pp_info = &io_extents->pp_extents[which];
1182 for (i = 0; i < LL_HIST_MAX; i++) {
1183 read_tot += pp_info->pp_r_hist.oh_buckets[i];
1184 write_tot += pp_info->pp_w_hist.oh_buckets[i];
1187 for (i = 0; i < LL_HIST_MAX; i++) {
1188 r = pp_info->pp_r_hist.oh_buckets[i];
1189 w = pp_info->pp_w_hist.oh_buckets[i];
1192 end = 1 << (i + LL_HIST_START - units);
1193 seq_printf(seq, "%4lu%c - %4lu%c%c: %14lu %4lu %4lu | %14lu %4lu %4lu\n",
1194 start, *unitp, end, *unitp,
1195 (i == LL_HIST_MAX - 1) ? '+' : ' ',
1196 r, pct(r, read_tot), pct(read_cum, read_tot),
1197 w, pct(w, write_tot), pct(write_cum, write_tot));
1199 if (start == 1<<10) {
1204 if (read_cum == read_tot && write_cum == write_tot)
1209 static int ll_rw_extents_stats_pp_seq_show(struct seq_file *seq, void *v)
1212 struct ll_sb_info *sbi = seq->private;
1213 struct ll_rw_extents_info *io_extents = &sbi->ll_rw_extents_info;
1216 do_gettimeofday(&now);
1218 if (!sbi->ll_rw_stats_on) {
1219 seq_printf(seq, "disabled\n"
1220 "write anything in this file to activate, then 0 or \"[D/d]isabled\" to deactivate\n");
1223 seq_printf(seq, "snapshot_time: %lu.%lu (secs.usecs)\n",
1224 now.tv_sec, (unsigned long)now.tv_usec);
1225 seq_printf(seq, "%15s %19s | %20s\n", " ", "read", "write");
1226 seq_printf(seq, "%13s %14s %4s %4s | %14s %4s %4s\n",
1227 "extents", "calls", "%", "cum%",
1228 "calls", "%", "cum%");
1229 spin_lock(&sbi->ll_pp_extent_lock);
1230 for (k = 0; k < LL_PROCESS_HIST_MAX; k++) {
1231 if (io_extents->pp_extents[k].pid != 0) {
1232 seq_printf(seq, "\nPID: %d\n",
1233 io_extents->pp_extents[k].pid);
1234 ll_display_extents_info(io_extents, seq, k);
1237 spin_unlock(&sbi->ll_pp_extent_lock);
1241 static ssize_t ll_rw_extents_stats_pp_seq_write(struct file *file,
1242 const char __user *buf,
1246 struct seq_file *seq = file->private_data;
1247 struct ll_sb_info *sbi = seq->private;
1248 struct ll_rw_extents_info *io_extents = &sbi->ll_rw_extents_info;
1250 int value = 1, rc = 0;
1255 rc = lprocfs_write_helper(buf, len, &value);
1256 if (rc < 0 && len < 16) {
1259 if (copy_from_user(kernbuf, buf, len))
1263 if (kernbuf[len - 1] == '\n')
1264 kernbuf[len - 1] = 0;
1266 if (strcmp(kernbuf, "disabled") == 0 ||
1267 strcmp(kernbuf, "Disabled") == 0)
1272 sbi->ll_rw_stats_on = 0;
1274 sbi->ll_rw_stats_on = 1;
1276 spin_lock(&sbi->ll_pp_extent_lock);
1277 for (i = 0; i < LL_PROCESS_HIST_MAX; i++) {
1278 io_extents->pp_extents[i].pid = 0;
1279 lprocfs_oh_clear(&io_extents->pp_extents[i].pp_r_hist);
1280 lprocfs_oh_clear(&io_extents->pp_extents[i].pp_w_hist);
1282 spin_unlock(&sbi->ll_pp_extent_lock);
1286 LPROC_SEQ_FOPS(ll_rw_extents_stats_pp);
1288 static int ll_rw_extents_stats_seq_show(struct seq_file *seq, void *v)
1291 struct ll_sb_info *sbi = seq->private;
1292 struct ll_rw_extents_info *io_extents = &sbi->ll_rw_extents_info;
1294 do_gettimeofday(&now);
1296 if (!sbi->ll_rw_stats_on) {
1297 seq_printf(seq, "disabled\n"
1298 "write anything in this file to activate, then 0 or \"[D/d]isabled\" to deactivate\n");
1301 seq_printf(seq, "snapshot_time: %lu.%lu (secs.usecs)\n",
1302 now.tv_sec, (unsigned long)now.tv_usec);
1304 seq_printf(seq, "%15s %19s | %20s\n", " ", "read", "write");
1305 seq_printf(seq, "%13s %14s %4s %4s | %14s %4s %4s\n",
1306 "extents", "calls", "%", "cum%",
1307 "calls", "%", "cum%");
1308 spin_lock(&sbi->ll_lock);
1309 ll_display_extents_info(io_extents, seq, LL_PROCESS_HIST_MAX);
1310 spin_unlock(&sbi->ll_lock);
1315 static ssize_t ll_rw_extents_stats_seq_write(struct file *file,
1316 const char __user *buf,
1317 size_t len, loff_t *off)
1319 struct seq_file *seq = file->private_data;
1320 struct ll_sb_info *sbi = seq->private;
1321 struct ll_rw_extents_info *io_extents = &sbi->ll_rw_extents_info;
1323 int value = 1, rc = 0;
1328 rc = lprocfs_write_helper(buf, len, &value);
1329 if (rc < 0 && len < 16) {
1332 if (copy_from_user(kernbuf, buf, len))
1336 if (kernbuf[len - 1] == '\n')
1337 kernbuf[len - 1] = 0;
1339 if (strcmp(kernbuf, "disabled") == 0 ||
1340 strcmp(kernbuf, "Disabled") == 0)
1345 sbi->ll_rw_stats_on = 0;
1347 sbi->ll_rw_stats_on = 1;
1349 spin_lock(&sbi->ll_pp_extent_lock);
1350 for (i = 0; i <= LL_PROCESS_HIST_MAX; i++) {
1351 io_extents->pp_extents[i].pid = 0;
1352 lprocfs_oh_clear(&io_extents->pp_extents[i].pp_r_hist);
1353 lprocfs_oh_clear(&io_extents->pp_extents[i].pp_w_hist);
1355 spin_unlock(&sbi->ll_pp_extent_lock);
1359 LPROC_SEQ_FOPS(ll_rw_extents_stats);
1361 void ll_rw_stats_tally(struct ll_sb_info *sbi, pid_t pid,
1362 struct ll_file_data *file, loff_t pos,
1363 size_t count, int rw)
1366 struct ll_rw_process_info *process;
1367 struct ll_rw_process_info *offset;
1368 int *off_count = &sbi->ll_rw_offset_entry_count;
1369 int *process_count = &sbi->ll_offset_process_count;
1370 struct ll_rw_extents_info *io_extents = &sbi->ll_rw_extents_info;
1372 if (!sbi->ll_rw_stats_on)
1374 process = sbi->ll_rw_process_info;
1375 offset = sbi->ll_rw_offset_info;
1377 spin_lock(&sbi->ll_pp_extent_lock);
1378 /* Extent statistics */
1379 for (i = 0; i < LL_PROCESS_HIST_MAX; i++) {
1380 if (io_extents->pp_extents[i].pid == pid) {
1388 sbi->ll_extent_process_count =
1389 (sbi->ll_extent_process_count + 1) % LL_PROCESS_HIST_MAX;
1390 cur = sbi->ll_extent_process_count;
1391 io_extents->pp_extents[cur].pid = pid;
1392 lprocfs_oh_clear(&io_extents->pp_extents[cur].pp_r_hist);
1393 lprocfs_oh_clear(&io_extents->pp_extents[cur].pp_w_hist);
1396 for(i = 0; (count >= (1 << LL_HIST_START << i)) &&
1397 (i < (LL_HIST_MAX - 1)); i++);
1399 io_extents->pp_extents[cur].pp_r_hist.oh_buckets[i]++;
1400 io_extents->pp_extents[LL_PROCESS_HIST_MAX].pp_r_hist.oh_buckets[i]++;
1402 io_extents->pp_extents[cur].pp_w_hist.oh_buckets[i]++;
1403 io_extents->pp_extents[LL_PROCESS_HIST_MAX].pp_w_hist.oh_buckets[i]++;
1405 spin_unlock(&sbi->ll_pp_extent_lock);
1407 spin_lock(&sbi->ll_process_lock);
1408 /* Offset statistics */
1409 for (i = 0; i < LL_PROCESS_HIST_MAX; i++) {
1410 if (process[i].rw_pid == pid) {
1411 if (process[i].rw_last_file != file) {
1412 process[i].rw_range_start = pos;
1413 process[i].rw_last_file_pos = pos + count;
1414 process[i].rw_smallest_extent = count;
1415 process[i].rw_largest_extent = count;
1416 process[i].rw_offset = 0;
1417 process[i].rw_last_file = file;
1418 spin_unlock(&sbi->ll_process_lock);
1421 if (process[i].rw_last_file_pos != pos) {
1423 (*off_count + 1) % LL_OFFSET_HIST_MAX;
1424 offset[*off_count].rw_op = process[i].rw_op;
1425 offset[*off_count].rw_pid = pid;
1426 offset[*off_count].rw_range_start =
1427 process[i].rw_range_start;
1428 offset[*off_count].rw_range_end =
1429 process[i].rw_last_file_pos;
1430 offset[*off_count].rw_smallest_extent =
1431 process[i].rw_smallest_extent;
1432 offset[*off_count].rw_largest_extent =
1433 process[i].rw_largest_extent;
1434 offset[*off_count].rw_offset =
1435 process[i].rw_offset;
1436 process[i].rw_op = rw;
1437 process[i].rw_range_start = pos;
1438 process[i].rw_smallest_extent = count;
1439 process[i].rw_largest_extent = count;
1440 process[i].rw_offset = pos -
1441 process[i].rw_last_file_pos;
1443 if (process[i].rw_smallest_extent > count)
1444 process[i].rw_smallest_extent = count;
1445 if (process[i].rw_largest_extent < count)
1446 process[i].rw_largest_extent = count;
1447 process[i].rw_last_file_pos = pos + count;
1448 spin_unlock(&sbi->ll_process_lock);
1452 *process_count = (*process_count + 1) % LL_PROCESS_HIST_MAX;
1453 process[*process_count].rw_pid = pid;
1454 process[*process_count].rw_op = rw;
1455 process[*process_count].rw_range_start = pos;
1456 process[*process_count].rw_last_file_pos = pos + count;
1457 process[*process_count].rw_smallest_extent = count;
1458 process[*process_count].rw_largest_extent = count;
1459 process[*process_count].rw_offset = 0;
1460 process[*process_count].rw_last_file = file;
1461 spin_unlock(&sbi->ll_process_lock);
1464 static int ll_rw_offset_stats_seq_show(struct seq_file *seq, void *v)
1467 struct ll_sb_info *sbi = seq->private;
1468 struct ll_rw_process_info *offset = sbi->ll_rw_offset_info;
1469 struct ll_rw_process_info *process = sbi->ll_rw_process_info;
1472 do_gettimeofday(&now);
1474 if (!sbi->ll_rw_stats_on) {
1475 seq_printf(seq, "disabled\n"
1476 "write anything in this file to activate, then 0 or \"[D/d]isabled\" to deactivate\n");
1479 spin_lock(&sbi->ll_process_lock);
1481 seq_printf(seq, "snapshot_time: %lu.%lu (secs.usecs)\n",
1482 now.tv_sec, (unsigned long)now.tv_usec);
1483 seq_printf(seq, "%3s %10s %14s %14s %17s %17s %14s\n",
1484 "R/W", "PID", "RANGE START", "RANGE END",
1485 "SMALLEST EXTENT", "LARGEST EXTENT", "OFFSET");
1486 /* We stored the discontiguous offsets here; print them first */
1487 for (i = 0; i < LL_OFFSET_HIST_MAX; i++) {
1488 if (offset[i].rw_pid != 0)
1490 "%3c %10d %14Lu %14Lu %17lu %17lu %14Lu",
1491 offset[i].rw_op == READ ? 'R' : 'W',
1493 offset[i].rw_range_start,
1494 offset[i].rw_range_end,
1495 (unsigned long)offset[i].rw_smallest_extent,
1496 (unsigned long)offset[i].rw_largest_extent,
1497 offset[i].rw_offset);
1499 /* Then print the current offsets for each process */
1500 for (i = 0; i < LL_PROCESS_HIST_MAX; i++) {
1501 if (process[i].rw_pid != 0)
1503 "%3c %10d %14Lu %14Lu %17lu %17lu %14Lu",
1504 process[i].rw_op == READ ? 'R' : 'W',
1506 process[i].rw_range_start,
1507 process[i].rw_last_file_pos,
1508 (unsigned long)process[i].rw_smallest_extent,
1509 (unsigned long)process[i].rw_largest_extent,
1510 process[i].rw_offset);
1512 spin_unlock(&sbi->ll_process_lock);
1517 static ssize_t ll_rw_offset_stats_seq_write(struct file *file,
1518 const char __user *buf,
1519 size_t len, loff_t *off)
1521 struct seq_file *seq = file->private_data;
1522 struct ll_sb_info *sbi = seq->private;
1523 struct ll_rw_process_info *process_info = sbi->ll_rw_process_info;
1524 struct ll_rw_process_info *offset_info = sbi->ll_rw_offset_info;
1525 int value = 1, rc = 0;
1530 rc = lprocfs_write_helper(buf, len, &value);
1532 if (rc < 0 && len < 16) {
1535 if (copy_from_user(kernbuf, buf, len))
1539 if (kernbuf[len - 1] == '\n')
1540 kernbuf[len - 1] = 0;
1542 if (strcmp(kernbuf, "disabled") == 0 ||
1543 strcmp(kernbuf, "Disabled") == 0)
1548 sbi->ll_rw_stats_on = 0;
1550 sbi->ll_rw_stats_on = 1;
1552 spin_lock(&sbi->ll_process_lock);
1553 sbi->ll_offset_process_count = 0;
1554 sbi->ll_rw_offset_entry_count = 0;
1555 memset(process_info, 0, sizeof(struct ll_rw_process_info) *
1556 LL_PROCESS_HIST_MAX);
1557 memset(offset_info, 0, sizeof(struct ll_rw_process_info) *
1558 LL_OFFSET_HIST_MAX);
1559 spin_unlock(&sbi->ll_process_lock);
1564 LPROC_SEQ_FOPS(ll_rw_offset_stats);
1566 void lprocfs_llite_init_vars(struct lprocfs_static_vars *lvars)
1568 lvars->module_vars = NULL;
1569 lvars->obd_vars = lprocfs_llite_obd_vars;