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 <lustre_lite.h>
39 #include <lprocfs_status.h>
40 #include <linux/seq_file.h>
41 #include <obd_support.h>
43 #include "llite_internal.h"
45 struct proc_dir_entry
*proc_lustre_fs_root
;
48 /* /proc/lustre/llite mount point registration */
49 extern struct file_operations vvp_dump_pgcache_file_ops
;
50 struct file_operations ll_rw_extents_stats_fops
;
51 struct file_operations ll_rw_extents_stats_pp_fops
;
52 struct file_operations ll_rw_offset_stats_fops
;
54 static int ll_blksize_seq_show(struct seq_file
*m
, void *v
)
56 struct super_block
*sb
= (struct super_block
*)m
->private;
57 struct obd_statfs osfs
;
61 rc
= ll_statfs_internal(sb
, &osfs
,
62 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS
),
65 rc
= seq_printf(m
, "%u\n", osfs
.os_bsize
);
69 LPROC_SEQ_FOPS_RO(ll_blksize
);
71 static int ll_kbytestotal_seq_show(struct seq_file
*m
, void *v
)
73 struct super_block
*sb
= (struct super_block
*)m
->private;
74 struct obd_statfs osfs
;
78 rc
= ll_statfs_internal(sb
, &osfs
,
79 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS
),
82 __u32 blk_size
= osfs
.os_bsize
>> 10;
83 __u64 result
= osfs
.os_blocks
;
85 while (blk_size
>>= 1)
88 rc
= seq_printf(m
, LPU64
"\n", result
);
92 LPROC_SEQ_FOPS_RO(ll_kbytestotal
);
94 static int ll_kbytesfree_seq_show(struct seq_file
*m
, void *v
)
96 struct super_block
*sb
= (struct super_block
*)m
->private;
97 struct obd_statfs osfs
;
101 rc
= ll_statfs_internal(sb
, &osfs
,
102 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS
),
105 __u32 blk_size
= osfs
.os_bsize
>> 10;
106 __u64 result
= osfs
.os_bfree
;
108 while (blk_size
>>= 1)
111 rc
= seq_printf(m
, LPU64
"\n", result
);
115 LPROC_SEQ_FOPS_RO(ll_kbytesfree
);
117 static int ll_kbytesavail_seq_show(struct seq_file
*m
, void *v
)
119 struct super_block
*sb
= (struct super_block
*)m
->private;
120 struct obd_statfs osfs
;
124 rc
= ll_statfs_internal(sb
, &osfs
,
125 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS
),
128 __u32 blk_size
= osfs
.os_bsize
>> 10;
129 __u64 result
= osfs
.os_bavail
;
131 while (blk_size
>>= 1)
134 rc
= seq_printf(m
, LPU64
"\n", result
);
138 LPROC_SEQ_FOPS_RO(ll_kbytesavail
);
140 static int ll_filestotal_seq_show(struct seq_file
*m
, void *v
)
142 struct super_block
*sb
= (struct super_block
*)m
->private;
143 struct obd_statfs osfs
;
147 rc
= ll_statfs_internal(sb
, &osfs
,
148 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS
),
151 rc
= seq_printf(m
, LPU64
"\n", osfs
.os_files
);
154 LPROC_SEQ_FOPS_RO(ll_filestotal
);
156 static int ll_filesfree_seq_show(struct seq_file
*m
, void *v
)
158 struct super_block
*sb
= (struct super_block
*)m
->private;
159 struct obd_statfs osfs
;
163 rc
= ll_statfs_internal(sb
, &osfs
,
164 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS
),
167 rc
= seq_printf(m
, LPU64
"\n", osfs
.os_ffree
);
170 LPROC_SEQ_FOPS_RO(ll_filesfree
);
172 static int ll_client_type_seq_show(struct seq_file
*m
, void *v
)
174 struct ll_sb_info
*sbi
= ll_s2sbi((struct super_block
*)m
->private);
177 LASSERT(sbi
!= NULL
);
179 if (sbi
->ll_flags
& LL_SBI_RMT_CLIENT
)
180 rc
= seq_printf(m
, "remote client\n");
182 rc
= seq_printf(m
, "local client\n");
186 LPROC_SEQ_FOPS_RO(ll_client_type
);
188 static int ll_fstype_seq_show(struct seq_file
*m
, void *v
)
190 struct super_block
*sb
= (struct super_block
*)m
->private;
193 return seq_printf(m
, "%s\n", sb
->s_type
->name
);
195 LPROC_SEQ_FOPS_RO(ll_fstype
);
197 static int ll_sb_uuid_seq_show(struct seq_file
*m
, void *v
)
199 struct super_block
*sb
= (struct super_block
*)m
->private;
202 return seq_printf(m
, "%s\n", ll_s2sbi(sb
)->ll_sb_uuid
.uuid
);
204 LPROC_SEQ_FOPS_RO(ll_sb_uuid
);
206 static int ll_site_stats_seq_show(struct seq_file
*m
, void *v
)
208 struct super_block
*sb
= m
->private;
211 * See description of statistical counters in struct cl_site, and
214 return cl_site_stats_print(lu2cl_site(ll_s2sbi(sb
)->ll_site
), m
);
216 LPROC_SEQ_FOPS_RO(ll_site_stats
);
218 static int ll_max_readahead_mb_seq_show(struct seq_file
*m
, void *v
)
220 struct super_block
*sb
= m
->private;
221 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
225 spin_lock(&sbi
->ll_lock
);
226 pages_number
= sbi
->ll_ra_info
.ra_max_pages
;
227 spin_unlock(&sbi
->ll_lock
);
229 mult
= 1 << (20 - PAGE_CACHE_SHIFT
);
230 return lprocfs_seq_read_frac_helper(m
, pages_number
, mult
);
233 static ssize_t
ll_max_readahead_mb_seq_write(struct file
*file
, const char *buffer
,
234 size_t count
, loff_t
*off
)
236 struct super_block
*sb
= ((struct seq_file
*)file
->private_data
)->private;
237 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
238 int mult
, rc
, pages_number
;
240 mult
= 1 << (20 - PAGE_CACHE_SHIFT
);
241 rc
= lprocfs_write_frac_helper(buffer
, count
, &pages_number
, mult
);
245 if (pages_number
< 0 || pages_number
> totalram_pages
/ 2) {
246 CERROR("can't set file readahead more than %lu MB\n",
247 totalram_pages
>> (20 - PAGE_CACHE_SHIFT
+ 1)); /*1/2 of RAM*/
251 spin_lock(&sbi
->ll_lock
);
252 sbi
->ll_ra_info
.ra_max_pages
= pages_number
;
253 spin_unlock(&sbi
->ll_lock
);
257 LPROC_SEQ_FOPS(ll_max_readahead_mb
);
259 static int ll_max_readahead_per_file_mb_seq_show(struct seq_file
*m
, void *v
)
261 struct super_block
*sb
= m
->private;
262 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
266 spin_lock(&sbi
->ll_lock
);
267 pages_number
= sbi
->ll_ra_info
.ra_max_pages_per_file
;
268 spin_unlock(&sbi
->ll_lock
);
270 mult
= 1 << (20 - PAGE_CACHE_SHIFT
);
271 return lprocfs_seq_read_frac_helper(m
, pages_number
, mult
);
274 static ssize_t
ll_max_readahead_per_file_mb_seq_write(struct file
*file
,
276 size_t count
, loff_t
*off
)
278 struct super_block
*sb
= ((struct seq_file
*)file
->private_data
)->private;
279 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
280 int mult
, rc
, pages_number
;
282 mult
= 1 << (20 - PAGE_CACHE_SHIFT
);
283 rc
= lprocfs_write_frac_helper(buffer
, count
, &pages_number
, mult
);
287 if (pages_number
< 0 ||
288 pages_number
> sbi
->ll_ra_info
.ra_max_pages
) {
289 CERROR("can't set file readahead more than"
290 "max_read_ahead_mb %lu MB\n",
291 sbi
->ll_ra_info
.ra_max_pages
);
295 spin_lock(&sbi
->ll_lock
);
296 sbi
->ll_ra_info
.ra_max_pages_per_file
= pages_number
;
297 spin_unlock(&sbi
->ll_lock
);
301 LPROC_SEQ_FOPS(ll_max_readahead_per_file_mb
);
303 static int ll_max_read_ahead_whole_mb_seq_show(struct seq_file
*m
, void *unused
)
305 struct super_block
*sb
= m
->private;
306 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
310 spin_lock(&sbi
->ll_lock
);
311 pages_number
= sbi
->ll_ra_info
.ra_max_read_ahead_whole_pages
;
312 spin_unlock(&sbi
->ll_lock
);
314 mult
= 1 << (20 - PAGE_CACHE_SHIFT
);
315 return lprocfs_seq_read_frac_helper(m
, pages_number
, mult
);
318 static ssize_t
ll_max_read_ahead_whole_mb_seq_write(struct file
*file
,
320 size_t count
, loff_t
*off
)
322 struct super_block
*sb
= ((struct seq_file
*)file
->private_data
)->private;
323 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
324 int mult
, rc
, pages_number
;
326 mult
= 1 << (20 - PAGE_CACHE_SHIFT
);
327 rc
= lprocfs_write_frac_helper(buffer
, count
, &pages_number
, mult
);
331 /* Cap this at the current max readahead window size, the readahead
332 * algorithm does this anyway so it's pointless to set it larger. */
333 if (pages_number
< 0 ||
334 pages_number
> sbi
->ll_ra_info
.ra_max_pages_per_file
) {
335 CERROR("can't set max_read_ahead_whole_mb more than "
336 "max_read_ahead_per_file_mb: %lu\n",
337 sbi
->ll_ra_info
.ra_max_pages_per_file
>> (20 - PAGE_CACHE_SHIFT
));
341 spin_lock(&sbi
->ll_lock
);
342 sbi
->ll_ra_info
.ra_max_read_ahead_whole_pages
= pages_number
;
343 spin_unlock(&sbi
->ll_lock
);
347 LPROC_SEQ_FOPS(ll_max_read_ahead_whole_mb
);
349 static int ll_max_cached_mb_seq_show(struct seq_file
*m
, void *v
)
351 struct super_block
*sb
= m
->private;
352 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
353 struct cl_client_cache
*cache
= &sbi
->ll_cache
;
354 int shift
= 20 - PAGE_CACHE_SHIFT
;
358 max_cached_mb
= cache
->ccc_lru_max
>> shift
;
359 unused_mb
= atomic_read(&cache
->ccc_lru_left
) >> shift
;
362 "max_cached_mb: %d\n"
365 "reclaim_count: %u\n",
366 atomic_read(&cache
->ccc_users
),
368 max_cached_mb
- unused_mb
,
370 cache
->ccc_lru_shrinkers
);
373 static ssize_t
ll_max_cached_mb_seq_write(struct file
*file
, const char *buffer
,
374 size_t count
, loff_t
*off
)
376 struct super_block
*sb
= ((struct seq_file
*)file
->private_data
)->private;
377 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
378 struct cl_client_cache
*cache
= &sbi
->ll_cache
;
379 int mult
, rc
, pages_number
;
383 mult
= 1 << (20 - PAGE_CACHE_SHIFT
);
384 buffer
= lprocfs_find_named_value(buffer
, "max_cached_mb:", &count
);
385 rc
= lprocfs_write_frac_helper(buffer
, count
, &pages_number
, mult
);
389 if (pages_number
< 0 || pages_number
> totalram_pages
) {
390 CERROR("%s: can't set max cache more than %lu MB\n",
391 ll_get_fsname(sb
, NULL
, 0),
392 totalram_pages
>> (20 - PAGE_CACHE_SHIFT
));
396 if (sbi
->ll_dt_exp
== NULL
)
399 spin_lock(&sbi
->ll_lock
);
400 diff
= pages_number
- cache
->ccc_lru_max
;
401 spin_unlock(&sbi
->ll_lock
);
403 /* easy - add more LRU slots. */
405 atomic_add(diff
, &cache
->ccc_lru_left
);
413 /* reduce LRU budget from free slots. */
417 ov
= atomic_read(&cache
->ccc_lru_left
);
421 nv
= ov
> diff
? ov
- diff
: 0;
422 rc
= cfs_atomic_cmpxchg(&cache
->ccc_lru_left
, ov
, nv
);
423 if (likely(ov
== rc
)) {
433 /* difficult - have to ask OSCs to drop LRU slots. */
435 rc
= obd_set_info_async(NULL
, sbi
->ll_dt_exp
,
436 sizeof(KEY_CACHE_LRU_SHRINK
),
437 KEY_CACHE_LRU_SHRINK
,
438 sizeof(tmp
), &tmp
, NULL
);
445 spin_lock(&sbi
->ll_lock
);
446 cache
->ccc_lru_max
= pages_number
;
447 spin_unlock(&sbi
->ll_lock
);
450 atomic_add(nrpages
, &cache
->ccc_lru_left
);
454 LPROC_SEQ_FOPS(ll_max_cached_mb
);
456 static int ll_checksum_seq_show(struct seq_file
*m
, void *v
)
458 struct super_block
*sb
= m
->private;
459 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
461 return seq_printf(m
, "%u\n", (sbi
->ll_flags
& LL_SBI_CHECKSUM
) ? 1 : 0);
464 static ssize_t
ll_checksum_seq_write(struct file
*file
, const char *buffer
,
465 size_t count
, loff_t
*off
)
467 struct super_block
*sb
= ((struct seq_file
*)file
->private_data
)->private;
468 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
475 rc
= lprocfs_write_helper(buffer
, count
, &val
);
479 sbi
->ll_flags
|= LL_SBI_CHECKSUM
;
481 sbi
->ll_flags
&= ~LL_SBI_CHECKSUM
;
483 rc
= obd_set_info_async(NULL
, sbi
->ll_dt_exp
, sizeof(KEY_CHECKSUM
),
484 KEY_CHECKSUM
, sizeof(val
), &val
, NULL
);
486 CWARN("Failed to set OSC checksum flags: %d\n", rc
);
490 LPROC_SEQ_FOPS(ll_checksum
);
492 static int ll_max_rw_chunk_seq_show(struct seq_file
*m
, void *v
)
494 struct super_block
*sb
= m
->private;
496 return seq_printf(m
, "%lu\n", ll_s2sbi(sb
)->ll_max_rw_chunk
);
499 static ssize_t
ll_max_rw_chunk_seq_write(struct file
*file
, const char *buffer
,
500 size_t count
, loff_t
*off
)
502 struct super_block
*sb
= ((struct seq_file
*)file
->private_data
)->private;
505 rc
= lprocfs_write_helper(buffer
, count
, &val
);
508 ll_s2sbi(sb
)->ll_max_rw_chunk
= val
;
511 LPROC_SEQ_FOPS(ll_max_rw_chunk
);
513 static int ll_rd_track_id(struct seq_file
*m
, enum stats_track_type type
)
515 struct super_block
*sb
= m
->private;
517 if (ll_s2sbi(sb
)->ll_stats_track_type
== type
) {
518 return seq_printf(m
, "%d\n",
519 ll_s2sbi(sb
)->ll_stats_track_id
);
521 } else if (ll_s2sbi(sb
)->ll_stats_track_type
== STATS_TRACK_ALL
) {
522 return seq_printf(m
, "0 (all)\n");
524 return seq_printf(m
, "untracked\n");
528 static int ll_wr_track_id(const char *buffer
, unsigned long count
, void *data
,
529 enum stats_track_type type
)
531 struct super_block
*sb
= data
;
534 rc
= lprocfs_write_helper(buffer
, count
, &pid
);
537 ll_s2sbi(sb
)->ll_stats_track_id
= pid
;
539 ll_s2sbi(sb
)->ll_stats_track_type
= STATS_TRACK_ALL
;
541 ll_s2sbi(sb
)->ll_stats_track_type
= type
;
542 lprocfs_clear_stats(ll_s2sbi(sb
)->ll_stats
);
546 static int ll_track_pid_seq_show(struct seq_file
*m
, void *v
)
548 return ll_rd_track_id(m
, STATS_TRACK_PID
);
551 static ssize_t
ll_track_pid_seq_write(struct file
*file
, const char *buffer
,
552 size_t count
, loff_t
*off
)
554 struct seq_file
*seq
= file
->private_data
;
555 return ll_wr_track_id(buffer
, count
, seq
->private, STATS_TRACK_PID
);
557 LPROC_SEQ_FOPS(ll_track_pid
);
559 static int ll_track_ppid_seq_show(struct seq_file
*m
, void *v
)
561 return ll_rd_track_id(m
, STATS_TRACK_PPID
);
564 static ssize_t
ll_track_ppid_seq_write(struct file
*file
, const char *buffer
,
565 size_t count
, loff_t
*off
)
567 struct seq_file
*seq
= file
->private_data
;
568 return ll_wr_track_id(buffer
, count
, seq
->private, STATS_TRACK_PPID
);
570 LPROC_SEQ_FOPS(ll_track_ppid
);
572 static int ll_track_gid_seq_show(struct seq_file
*m
, void *v
)
574 return ll_rd_track_id(m
, STATS_TRACK_GID
);
577 static ssize_t
ll_track_gid_seq_write(struct file
*file
, const char *buffer
,
578 size_t count
, loff_t
*off
)
580 struct seq_file
*seq
= file
->private_data
;
581 return ll_wr_track_id(buffer
, count
, seq
->private, STATS_TRACK_GID
);
583 LPROC_SEQ_FOPS(ll_track_gid
);
585 static int ll_statahead_max_seq_show(struct seq_file
*m
, void *v
)
587 struct super_block
*sb
= m
->private;
588 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
590 return seq_printf(m
, "%u\n", sbi
->ll_sa_max
);
593 static ssize_t
ll_statahead_max_seq_write(struct file
*file
, const char *buffer
,
594 size_t count
, loff_t
*off
)
596 struct super_block
*sb
= ((struct seq_file
*)file
->private_data
)->private;
597 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
600 rc
= lprocfs_write_helper(buffer
, count
, &val
);
604 if (val
>= 0 && val
<= LL_SA_RPC_MAX
)
605 sbi
->ll_sa_max
= val
;
607 CERROR("Bad statahead_max value %d. Valid values are in the "
608 "range [0, %d]\n", val
, LL_SA_RPC_MAX
);
612 LPROC_SEQ_FOPS(ll_statahead_max
);
614 static int ll_statahead_agl_seq_show(struct seq_file
*m
, void *v
)
616 struct super_block
*sb
= m
->private;
617 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
619 return seq_printf(m
, "%u\n",
620 sbi
->ll_flags
& LL_SBI_AGL_ENABLED
? 1 : 0);
623 static ssize_t
ll_statahead_agl_seq_write(struct file
*file
, const char *buffer
,
624 size_t count
, loff_t
*off
)
626 struct super_block
*sb
= ((struct seq_file
*)file
->private_data
)->private;
627 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
630 rc
= lprocfs_write_helper(buffer
, count
, &val
);
635 sbi
->ll_flags
|= LL_SBI_AGL_ENABLED
;
637 sbi
->ll_flags
&= ~LL_SBI_AGL_ENABLED
;
641 LPROC_SEQ_FOPS(ll_statahead_agl
);
643 static int ll_statahead_stats_seq_show(struct seq_file
*m
, void *v
)
645 struct super_block
*sb
= m
->private;
646 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
649 "statahead total: %u\n"
650 "statahead wrong: %u\n"
652 atomic_read(&sbi
->ll_sa_total
),
653 atomic_read(&sbi
->ll_sa_wrong
),
654 atomic_read(&sbi
->ll_agl_total
));
656 LPROC_SEQ_FOPS_RO(ll_statahead_stats
);
658 static int ll_lazystatfs_seq_show(struct seq_file
*m
, void *v
)
660 struct super_block
*sb
= m
->private;
661 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
663 return seq_printf(m
, "%u\n",
664 (sbi
->ll_flags
& LL_SBI_LAZYSTATFS
) ? 1 : 0);
667 static ssize_t
ll_lazystatfs_seq_write(struct file
*file
, const char *buffer
,
668 size_t count
, loff_t
*off
)
670 struct super_block
*sb
= ((struct seq_file
*)file
->private_data
)->private;
671 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
674 rc
= lprocfs_write_helper(buffer
, count
, &val
);
679 sbi
->ll_flags
|= LL_SBI_LAZYSTATFS
;
681 sbi
->ll_flags
&= ~LL_SBI_LAZYSTATFS
;
685 LPROC_SEQ_FOPS(ll_lazystatfs
);
687 static int ll_maxea_size_seq_show(struct seq_file
*m
, void *v
)
689 struct super_block
*sb
= m
->private;
690 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
694 rc
= ll_get_max_mdsize(sbi
, &ealen
);
698 return seq_printf(m
, "%u\n", ealen
);
700 LPROC_SEQ_FOPS_RO(ll_maxea_size
);
702 static int ll_sbi_flags_seq_show(struct seq_file
*m
, void *v
)
704 const char *str
[] = LL_SBI_FLAGS
;
705 struct super_block
*sb
= m
->private;
706 int flags
= ll_s2sbi(sb
)->ll_flags
;
710 if (ARRAY_SIZE(str
) <= i
) {
711 CERROR("%s: Revise array LL_SBI_FLAGS to match sbi "
712 "flags please.\n", ll_get_fsname(sb
, NULL
, 0));
717 seq_printf(m
, "%s ", str
[i
]);
721 seq_printf(m
, "\b\n");
724 LPROC_SEQ_FOPS_RO(ll_sbi_flags
);
726 static struct lprocfs_vars lprocfs_llite_obd_vars
[] = {
727 { "uuid", &ll_sb_uuid_fops
, 0, 0 },
728 //{ "mntpt_path", ll_rd_path, 0, 0 },
729 { "fstype", &ll_fstype_fops
, 0, 0 },
730 { "site", &ll_site_stats_fops
, 0, 0 },
731 { "blocksize", &ll_blksize_fops
, 0, 0 },
732 { "kbytestotal", &ll_kbytestotal_fops
, 0, 0 },
733 { "kbytesfree", &ll_kbytesfree_fops
, 0, 0 },
734 { "kbytesavail", &ll_kbytesavail_fops
, 0, 0 },
735 { "filestotal", &ll_filestotal_fops
, 0, 0 },
736 { "filesfree", &ll_filesfree_fops
, 0, 0 },
737 { "client_type", &ll_client_type_fops
, 0, 0 },
738 //{ "filegroups", lprocfs_rd_filegroups, 0, 0 },
739 { "max_read_ahead_mb", &ll_max_readahead_mb_fops
, 0 },
740 { "max_read_ahead_per_file_mb", &ll_max_readahead_per_file_mb_fops
, 0 },
741 { "max_read_ahead_whole_mb", &ll_max_read_ahead_whole_mb_fops
, 0 },
742 { "max_cached_mb", &ll_max_cached_mb_fops
, 0 },
743 { "checksum_pages", &ll_checksum_fops
, 0 },
744 { "max_rw_chunk", &ll_max_rw_chunk_fops
, 0 },
745 { "stats_track_pid", &ll_track_pid_fops
, 0 },
746 { "stats_track_ppid", &ll_track_ppid_fops
, 0 },
747 { "stats_track_gid", &ll_track_gid_fops
, 0 },
748 { "statahead_max", &ll_statahead_max_fops
, 0 },
749 { "statahead_agl", &ll_statahead_agl_fops
, 0 },
750 { "statahead_stats", &ll_statahead_stats_fops
, 0, 0 },
751 { "lazystatfs", &ll_lazystatfs_fops
, 0 },
752 { "max_easize", &ll_maxea_size_fops
, 0, 0 },
753 { "sbi_flags", &ll_sbi_flags_fops
, 0, 0 },
757 #define MAX_STRING_SIZE 128
759 struct llite_file_opcode
{
763 } llite_opcode_table
[LPROC_LL_FILE_OPCODES
] = {
765 { LPROC_LL_DIRTY_HITS
, LPROCFS_TYPE_REGS
, "dirty_pages_hits" },
766 { LPROC_LL_DIRTY_MISSES
, LPROCFS_TYPE_REGS
, "dirty_pages_misses" },
767 { LPROC_LL_READ_BYTES
, LPROCFS_CNTR_AVGMINMAX
|LPROCFS_TYPE_BYTES
,
769 { LPROC_LL_WRITE_BYTES
, LPROCFS_CNTR_AVGMINMAX
|LPROCFS_TYPE_BYTES
,
771 { LPROC_LL_BRW_READ
, LPROCFS_CNTR_AVGMINMAX
|LPROCFS_TYPE_PAGES
,
773 { LPROC_LL_BRW_WRITE
, LPROCFS_CNTR_AVGMINMAX
|LPROCFS_TYPE_PAGES
,
775 { LPROC_LL_OSC_READ
, LPROCFS_CNTR_AVGMINMAX
|LPROCFS_TYPE_BYTES
,
777 { LPROC_LL_OSC_WRITE
, LPROCFS_CNTR_AVGMINMAX
|LPROCFS_TYPE_BYTES
,
779 { LPROC_LL_IOCTL
, LPROCFS_TYPE_REGS
, "ioctl" },
780 { LPROC_LL_OPEN
, LPROCFS_TYPE_REGS
, "open" },
781 { LPROC_LL_RELEASE
, LPROCFS_TYPE_REGS
, "close" },
782 { LPROC_LL_MAP
, LPROCFS_TYPE_REGS
, "mmap" },
783 { LPROC_LL_LLSEEK
, LPROCFS_TYPE_REGS
, "seek" },
784 { LPROC_LL_FSYNC
, LPROCFS_TYPE_REGS
, "fsync" },
785 { LPROC_LL_READDIR
, LPROCFS_TYPE_REGS
, "readdir" },
786 /* inode operation */
787 { LPROC_LL_SETATTR
, LPROCFS_TYPE_REGS
, "setattr" },
788 { LPROC_LL_TRUNC
, LPROCFS_TYPE_REGS
, "truncate" },
789 { LPROC_LL_FLOCK
, LPROCFS_TYPE_REGS
, "flock" },
790 { LPROC_LL_GETATTR
, LPROCFS_TYPE_REGS
, "getattr" },
791 /* dir inode operation */
792 { LPROC_LL_CREATE
, LPROCFS_TYPE_REGS
, "create" },
793 { LPROC_LL_LINK
, LPROCFS_TYPE_REGS
, "link" },
794 { LPROC_LL_UNLINK
, LPROCFS_TYPE_REGS
, "unlink" },
795 { LPROC_LL_SYMLINK
, LPROCFS_TYPE_REGS
, "symlink" },
796 { LPROC_LL_MKDIR
, LPROCFS_TYPE_REGS
, "mkdir" },
797 { LPROC_LL_RMDIR
, LPROCFS_TYPE_REGS
, "rmdir" },
798 { LPROC_LL_MKNOD
, LPROCFS_TYPE_REGS
, "mknod" },
799 { LPROC_LL_RENAME
, LPROCFS_TYPE_REGS
, "rename" },
800 /* special inode operation */
801 { LPROC_LL_STAFS
, LPROCFS_TYPE_REGS
, "statfs" },
802 { LPROC_LL_ALLOC_INODE
, LPROCFS_TYPE_REGS
, "alloc_inode" },
803 { LPROC_LL_SETXATTR
, LPROCFS_TYPE_REGS
, "setxattr" },
804 { LPROC_LL_GETXATTR
, LPROCFS_TYPE_REGS
, "getxattr" },
805 { LPROC_LL_LISTXATTR
, LPROCFS_TYPE_REGS
, "listxattr" },
806 { LPROC_LL_REMOVEXATTR
, LPROCFS_TYPE_REGS
, "removexattr" },
807 { LPROC_LL_INODE_PERM
, LPROCFS_TYPE_REGS
, "inode_permission" },
810 void ll_stats_ops_tally(struct ll_sb_info
*sbi
, int op
, int count
)
814 if (sbi
->ll_stats_track_type
== STATS_TRACK_ALL
)
815 lprocfs_counter_add(sbi
->ll_stats
, op
, count
);
816 else if (sbi
->ll_stats_track_type
== STATS_TRACK_PID
&&
817 sbi
->ll_stats_track_id
== current
->pid
)
818 lprocfs_counter_add(sbi
->ll_stats
, op
, count
);
819 else if (sbi
->ll_stats_track_type
== STATS_TRACK_PPID
&&
820 sbi
->ll_stats_track_id
== current
->parent
->pid
)
821 lprocfs_counter_add(sbi
->ll_stats
, op
, count
);
822 else if (sbi
->ll_stats_track_type
== STATS_TRACK_GID
&&
823 sbi
->ll_stats_track_id
==
824 from_kgid(&init_user_ns
, current_gid()))
825 lprocfs_counter_add(sbi
->ll_stats
, op
, count
);
827 EXPORT_SYMBOL(ll_stats_ops_tally
);
829 static const char *ra_stat_string
[] = {
830 [RA_STAT_HIT
] = "hits",
831 [RA_STAT_MISS
] = "misses",
832 [RA_STAT_DISTANT_READPAGE
] = "readpage not consecutive",
833 [RA_STAT_MISS_IN_WINDOW
] = "miss inside window",
834 [RA_STAT_FAILED_GRAB_PAGE
] = "failed grab_cache_page",
835 [RA_STAT_FAILED_MATCH
] = "failed lock match",
836 [RA_STAT_DISCARDED
] = "read but discarded",
837 [RA_STAT_ZERO_LEN
] = "zero length file",
838 [RA_STAT_ZERO_WINDOW
] = "zero size window",
839 [RA_STAT_EOF
] = "read-ahead to EOF",
840 [RA_STAT_MAX_IN_FLIGHT
] = "hit max r-a issue",
841 [RA_STAT_WRONG_GRAB_PAGE
] = "wrong page from grab_cache_page",
844 LPROC_SEQ_FOPS_RO_TYPE(llite
, name
);
845 LPROC_SEQ_FOPS_RO_TYPE(llite
, uuid
);
847 int lprocfs_register_mountpoint(struct proc_dir_entry
*parent
,
848 struct super_block
*sb
, char *osc
, char *mdc
)
850 struct lprocfs_vars lvars
[2];
851 struct lustre_sb_info
*lsi
= s2lsi(sb
);
852 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
853 struct obd_device
*obd
;
854 proc_dir_entry_t
*dir
;
855 char name
[MAX_STRING_SIZE
+ 1], *ptr
;
856 int err
, id
, len
, rc
;
858 memset(lvars
, 0, sizeof(lvars
));
860 name
[MAX_STRING_SIZE
] = '\0';
861 lvars
[0].name
= name
;
863 LASSERT(sbi
!= NULL
);
864 LASSERT(mdc
!= NULL
);
865 LASSERT(osc
!= NULL
);
868 len
= strlen(lsi
->lsi_lmd
->lmd_profile
);
869 ptr
= strrchr(lsi
->lsi_lmd
->lmd_profile
, '-');
870 if (ptr
&& (strcmp(ptr
, "-client") == 0))
874 snprintf(name
, MAX_STRING_SIZE
, "%.*s-%p", len
,
875 lsi
->lsi_lmd
->lmd_profile
, sb
);
877 sbi
->ll_proc_root
= lprocfs_register(name
, parent
, NULL
, NULL
);
878 if (IS_ERR(sbi
->ll_proc_root
)) {
879 err
= PTR_ERR(sbi
->ll_proc_root
);
880 sbi
->ll_proc_root
= NULL
;
884 rc
= lprocfs_seq_create(sbi
->ll_proc_root
, "dump_page_cache", 0444,
885 &vvp_dump_pgcache_file_ops
, sbi
);
887 CWARN("Error adding the dump_page_cache file\n");
889 rc
= lprocfs_seq_create(sbi
->ll_proc_root
, "extents_stats", 0644,
890 &ll_rw_extents_stats_fops
, sbi
);
892 CWARN("Error adding the extent_stats file\n");
894 rc
= lprocfs_seq_create(sbi
->ll_proc_root
, "extents_stats_per_process",
895 0644, &ll_rw_extents_stats_pp_fops
, sbi
);
897 CWARN("Error adding the extents_stats_per_process file\n");
899 rc
= lprocfs_seq_create(sbi
->ll_proc_root
, "offset_stats", 0644,
900 &ll_rw_offset_stats_fops
, sbi
);
902 CWARN("Error adding the offset_stats file\n");
904 /* File operations stats */
905 sbi
->ll_stats
= lprocfs_alloc_stats(LPROC_LL_FILE_OPCODES
,
906 LPROCFS_STATS_FLAG_NONE
);
907 if (sbi
->ll_stats
== NULL
)
908 GOTO(out
, err
= -ENOMEM
);
909 /* do counter init */
910 for (id
= 0; id
< LPROC_LL_FILE_OPCODES
; id
++) {
911 __u32 type
= llite_opcode_table
[id
].type
;
913 if (type
& LPROCFS_TYPE_REGS
)
915 else if (type
& LPROCFS_TYPE_BYTES
)
917 else if (type
& LPROCFS_TYPE_PAGES
)
919 lprocfs_counter_init(sbi
->ll_stats
,
920 llite_opcode_table
[id
].opcode
,
921 (type
& LPROCFS_CNTR_AVGMINMAX
),
922 llite_opcode_table
[id
].opname
, ptr
);
924 err
= lprocfs_register_stats(sbi
->ll_proc_root
, "stats", sbi
->ll_stats
);
928 sbi
->ll_ra_stats
= lprocfs_alloc_stats(ARRAY_SIZE(ra_stat_string
),
929 LPROCFS_STATS_FLAG_NONE
);
930 if (sbi
->ll_ra_stats
== NULL
)
931 GOTO(out
, err
= -ENOMEM
);
933 for (id
= 0; id
< ARRAY_SIZE(ra_stat_string
); id
++)
934 lprocfs_counter_init(sbi
->ll_ra_stats
, id
, 0,
935 ra_stat_string
[id
], "pages");
936 err
= lprocfs_register_stats(sbi
->ll_proc_root
, "read_ahead_stats",
942 err
= lprocfs_add_vars(sbi
->ll_proc_root
, lprocfs_llite_obd_vars
, sb
);
947 obd
= class_name2obd(mdc
);
949 LASSERT(obd
!= NULL
);
950 LASSERT(obd
->obd_magic
== OBD_DEVICE_MAGIC
);
951 LASSERT(obd
->obd_type
->typ_name
!= NULL
);
953 dir
= proc_mkdir(obd
->obd_type
->typ_name
, sbi
->ll_proc_root
);
955 GOTO(out
, err
= -ENOMEM
);
957 snprintf(name
, MAX_STRING_SIZE
, "common_name");
958 lvars
[0].fops
= &llite_name_fops
;
959 err
= lprocfs_add_vars(dir
, lvars
, obd
);
963 snprintf(name
, MAX_STRING_SIZE
, "uuid");
964 lvars
[0].fops
= &llite_uuid_fops
;
965 err
= lprocfs_add_vars(dir
, lvars
, obd
);
970 obd
= class_name2obd(osc
);
972 LASSERT(obd
!= NULL
);
973 LASSERT(obd
->obd_magic
== OBD_DEVICE_MAGIC
);
974 LASSERT(obd
->obd_type
->typ_name
!= NULL
);
976 dir
= proc_mkdir(obd
->obd_type
->typ_name
, sbi
->ll_proc_root
);
978 GOTO(out
, err
= -ENOMEM
);
980 snprintf(name
, MAX_STRING_SIZE
, "common_name");
981 lvars
[0].fops
= &llite_name_fops
;
982 err
= lprocfs_add_vars(dir
, lvars
, obd
);
986 snprintf(name
, MAX_STRING_SIZE
, "uuid");
987 lvars
[0].fops
= &llite_uuid_fops
;
988 err
= lprocfs_add_vars(dir
, lvars
, obd
);
991 lprocfs_remove(&sbi
->ll_proc_root
);
992 lprocfs_free_stats(&sbi
->ll_ra_stats
);
993 lprocfs_free_stats(&sbi
->ll_stats
);
998 void lprocfs_unregister_mountpoint(struct ll_sb_info
*sbi
)
1000 if (sbi
->ll_proc_root
) {
1001 lprocfs_remove(&sbi
->ll_proc_root
);
1002 lprocfs_free_stats(&sbi
->ll_ra_stats
);
1003 lprocfs_free_stats(&sbi
->ll_stats
);
1006 #undef MAX_STRING_SIZE
1008 #define pct(a,b) (b ? a * 100 / b : 0)
1010 static void ll_display_extents_info(struct ll_rw_extents_info
*io_extents
,
1011 struct seq_file
*seq
, int which
)
1013 unsigned long read_tot
= 0, write_tot
= 0, read_cum
, write_cum
;
1014 unsigned long start
, end
, r
, w
;
1015 char *unitp
= "KMGTPEZY";
1017 struct per_process_info
*pp_info
= &io_extents
->pp_extents
[which
];
1023 for(i
= 0; i
< LL_HIST_MAX
; i
++) {
1024 read_tot
+= pp_info
->pp_r_hist
.oh_buckets
[i
];
1025 write_tot
+= pp_info
->pp_w_hist
.oh_buckets
[i
];
1028 for(i
= 0; i
< LL_HIST_MAX
; i
++) {
1029 r
= pp_info
->pp_r_hist
.oh_buckets
[i
];
1030 w
= pp_info
->pp_w_hist
.oh_buckets
[i
];
1033 end
= 1 << (i
+ LL_HIST_START
- units
);
1034 seq_printf(seq
, "%4lu%c - %4lu%c%c: %14lu %4lu %4lu | "
1035 "%14lu %4lu %4lu\n", start
, *unitp
, end
, *unitp
,
1036 (i
== LL_HIST_MAX
- 1) ? '+' : ' ',
1037 r
, pct(r
, read_tot
), pct(read_cum
, read_tot
),
1038 w
, pct(w
, write_tot
), pct(write_cum
, write_tot
));
1040 if (start
== 1<<10) {
1045 if (read_cum
== read_tot
&& write_cum
== write_tot
)
1050 static int ll_rw_extents_stats_pp_seq_show(struct seq_file
*seq
, void *v
)
1053 struct ll_sb_info
*sbi
= seq
->private;
1054 struct ll_rw_extents_info
*io_extents
= &sbi
->ll_rw_extents_info
;
1057 do_gettimeofday(&now
);
1059 if (!sbi
->ll_rw_stats_on
) {
1060 seq_printf(seq
, "disabled\n"
1061 "write anything in this file to activate, "
1062 "then 0 or \"[D/d]isabled\" to deactivate\n");
1065 seq_printf(seq
, "snapshot_time: %lu.%lu (secs.usecs)\n",
1066 now
.tv_sec
, now
.tv_usec
);
1067 seq_printf(seq
, "%15s %19s | %20s\n", " ", "read", "write");
1068 seq_printf(seq
, "%13s %14s %4s %4s | %14s %4s %4s\n",
1069 "extents", "calls", "%", "cum%",
1070 "calls", "%", "cum%");
1071 spin_lock(&sbi
->ll_pp_extent_lock
);
1072 for (k
= 0; k
< LL_PROCESS_HIST_MAX
; k
++) {
1073 if (io_extents
->pp_extents
[k
].pid
!= 0) {
1074 seq_printf(seq
, "\nPID: %d\n",
1075 io_extents
->pp_extents
[k
].pid
);
1076 ll_display_extents_info(io_extents
, seq
, k
);
1079 spin_unlock(&sbi
->ll_pp_extent_lock
);
1083 static ssize_t
ll_rw_extents_stats_pp_seq_write(struct file
*file
,
1084 const char *buf
, size_t len
,
1087 struct seq_file
*seq
= file
->private_data
;
1088 struct ll_sb_info
*sbi
= seq
->private;
1089 struct ll_rw_extents_info
*io_extents
= &sbi
->ll_rw_extents_info
;
1091 int value
= 1, rc
= 0;
1093 rc
= lprocfs_write_helper(buf
, len
, &value
);
1094 if (rc
< 0 && (strcmp(buf
, "disabled") == 0 ||
1095 strcmp(buf
, "Disabled") == 0))
1099 sbi
->ll_rw_stats_on
= 0;
1101 sbi
->ll_rw_stats_on
= 1;
1103 spin_lock(&sbi
->ll_pp_extent_lock
);
1104 for (i
= 0; i
< LL_PROCESS_HIST_MAX
; i
++) {
1105 io_extents
->pp_extents
[i
].pid
= 0;
1106 lprocfs_oh_clear(&io_extents
->pp_extents
[i
].pp_r_hist
);
1107 lprocfs_oh_clear(&io_extents
->pp_extents
[i
].pp_w_hist
);
1109 spin_unlock(&sbi
->ll_pp_extent_lock
);
1113 LPROC_SEQ_FOPS(ll_rw_extents_stats_pp
);
1115 static int ll_rw_extents_stats_seq_show(struct seq_file
*seq
, void *v
)
1118 struct ll_sb_info
*sbi
= seq
->private;
1119 struct ll_rw_extents_info
*io_extents
= &sbi
->ll_rw_extents_info
;
1121 do_gettimeofday(&now
);
1123 if (!sbi
->ll_rw_stats_on
) {
1124 seq_printf(seq
, "disabled\n"
1125 "write anything in this file to activate, "
1126 "then 0 or \"[D/d]isabled\" to deactivate\n");
1129 seq_printf(seq
, "snapshot_time: %lu.%lu (secs.usecs)\n",
1130 now
.tv_sec
, now
.tv_usec
);
1132 seq_printf(seq
, "%15s %19s | %20s\n", " ", "read", "write");
1133 seq_printf(seq
, "%13s %14s %4s %4s | %14s %4s %4s\n",
1134 "extents", "calls", "%", "cum%",
1135 "calls", "%", "cum%");
1136 spin_lock(&sbi
->ll_lock
);
1137 ll_display_extents_info(io_extents
, seq
, LL_PROCESS_HIST_MAX
);
1138 spin_unlock(&sbi
->ll_lock
);
1143 static ssize_t
ll_rw_extents_stats_seq_write(struct file
*file
, const char *buf
,
1144 size_t len
, loff_t
*off
)
1146 struct seq_file
*seq
= file
->private_data
;
1147 struct ll_sb_info
*sbi
= seq
->private;
1148 struct ll_rw_extents_info
*io_extents
= &sbi
->ll_rw_extents_info
;
1150 int value
= 1, rc
= 0;
1152 rc
= lprocfs_write_helper(buf
, len
, &value
);
1153 if (rc
< 0 && (strcmp(buf
, "disabled") == 0 ||
1154 strcmp(buf
, "Disabled") == 0))
1158 sbi
->ll_rw_stats_on
= 0;
1160 sbi
->ll_rw_stats_on
= 1;
1161 spin_lock(&sbi
->ll_pp_extent_lock
);
1162 for (i
= 0; i
<= LL_PROCESS_HIST_MAX
; i
++) {
1163 io_extents
->pp_extents
[i
].pid
= 0;
1164 lprocfs_oh_clear(&io_extents
->pp_extents
[i
].pp_r_hist
);
1165 lprocfs_oh_clear(&io_extents
->pp_extents
[i
].pp_w_hist
);
1167 spin_unlock(&sbi
->ll_pp_extent_lock
);
1172 LPROC_SEQ_FOPS(ll_rw_extents_stats
);
1174 void ll_rw_stats_tally(struct ll_sb_info
*sbi
, pid_t pid
,
1175 struct ll_file_data
*file
, loff_t pos
,
1176 size_t count
, int rw
)
1179 struct ll_rw_process_info
*process
;
1180 struct ll_rw_process_info
*offset
;
1181 int *off_count
= &sbi
->ll_rw_offset_entry_count
;
1182 int *process_count
= &sbi
->ll_offset_process_count
;
1183 struct ll_rw_extents_info
*io_extents
= &sbi
->ll_rw_extents_info
;
1185 if(!sbi
->ll_rw_stats_on
)
1187 process
= sbi
->ll_rw_process_info
;
1188 offset
= sbi
->ll_rw_offset_info
;
1190 spin_lock(&sbi
->ll_pp_extent_lock
);
1191 /* Extent statistics */
1192 for(i
= 0; i
< LL_PROCESS_HIST_MAX
; i
++) {
1193 if(io_extents
->pp_extents
[i
].pid
== pid
) {
1201 sbi
->ll_extent_process_count
=
1202 (sbi
->ll_extent_process_count
+ 1) % LL_PROCESS_HIST_MAX
;
1203 cur
= sbi
->ll_extent_process_count
;
1204 io_extents
->pp_extents
[cur
].pid
= pid
;
1205 lprocfs_oh_clear(&io_extents
->pp_extents
[cur
].pp_r_hist
);
1206 lprocfs_oh_clear(&io_extents
->pp_extents
[cur
].pp_w_hist
);
1209 for(i
= 0; (count
>= (1 << LL_HIST_START
<< i
)) &&
1210 (i
< (LL_HIST_MAX
- 1)); i
++);
1212 io_extents
->pp_extents
[cur
].pp_r_hist
.oh_buckets
[i
]++;
1213 io_extents
->pp_extents
[LL_PROCESS_HIST_MAX
].pp_r_hist
.oh_buckets
[i
]++;
1215 io_extents
->pp_extents
[cur
].pp_w_hist
.oh_buckets
[i
]++;
1216 io_extents
->pp_extents
[LL_PROCESS_HIST_MAX
].pp_w_hist
.oh_buckets
[i
]++;
1218 spin_unlock(&sbi
->ll_pp_extent_lock
);
1220 spin_lock(&sbi
->ll_process_lock
);
1221 /* Offset statistics */
1222 for (i
= 0; i
< LL_PROCESS_HIST_MAX
; i
++) {
1223 if (process
[i
].rw_pid
== pid
) {
1224 if (process
[i
].rw_last_file
!= file
) {
1225 process
[i
].rw_range_start
= pos
;
1226 process
[i
].rw_last_file_pos
= pos
+ count
;
1227 process
[i
].rw_smallest_extent
= count
;
1228 process
[i
].rw_largest_extent
= count
;
1229 process
[i
].rw_offset
= 0;
1230 process
[i
].rw_last_file
= file
;
1231 spin_unlock(&sbi
->ll_process_lock
);
1234 if (process
[i
].rw_last_file_pos
!= pos
) {
1236 (*off_count
+ 1) % LL_OFFSET_HIST_MAX
;
1237 offset
[*off_count
].rw_op
= process
[i
].rw_op
;
1238 offset
[*off_count
].rw_pid
= pid
;
1239 offset
[*off_count
].rw_range_start
=
1240 process
[i
].rw_range_start
;
1241 offset
[*off_count
].rw_range_end
=
1242 process
[i
].rw_last_file_pos
;
1243 offset
[*off_count
].rw_smallest_extent
=
1244 process
[i
].rw_smallest_extent
;
1245 offset
[*off_count
].rw_largest_extent
=
1246 process
[i
].rw_largest_extent
;
1247 offset
[*off_count
].rw_offset
=
1248 process
[i
].rw_offset
;
1249 process
[i
].rw_op
= rw
;
1250 process
[i
].rw_range_start
= pos
;
1251 process
[i
].rw_smallest_extent
= count
;
1252 process
[i
].rw_largest_extent
= count
;
1253 process
[i
].rw_offset
= pos
-
1254 process
[i
].rw_last_file_pos
;
1256 if(process
[i
].rw_smallest_extent
> count
)
1257 process
[i
].rw_smallest_extent
= count
;
1258 if(process
[i
].rw_largest_extent
< count
)
1259 process
[i
].rw_largest_extent
= count
;
1260 process
[i
].rw_last_file_pos
= pos
+ count
;
1261 spin_unlock(&sbi
->ll_process_lock
);
1265 *process_count
= (*process_count
+ 1) % LL_PROCESS_HIST_MAX
;
1266 process
[*process_count
].rw_pid
= pid
;
1267 process
[*process_count
].rw_op
= rw
;
1268 process
[*process_count
].rw_range_start
= pos
;
1269 process
[*process_count
].rw_last_file_pos
= pos
+ count
;
1270 process
[*process_count
].rw_smallest_extent
= count
;
1271 process
[*process_count
].rw_largest_extent
= count
;
1272 process
[*process_count
].rw_offset
= 0;
1273 process
[*process_count
].rw_last_file
= file
;
1274 spin_unlock(&sbi
->ll_process_lock
);
1277 static int ll_rw_offset_stats_seq_show(struct seq_file
*seq
, void *v
)
1280 struct ll_sb_info
*sbi
= seq
->private;
1281 struct ll_rw_process_info
*offset
= sbi
->ll_rw_offset_info
;
1282 struct ll_rw_process_info
*process
= sbi
->ll_rw_process_info
;
1285 do_gettimeofday(&now
);
1287 if (!sbi
->ll_rw_stats_on
) {
1288 seq_printf(seq
, "disabled\n"
1289 "write anything in this file to activate, "
1290 "then 0 or \"[D/d]isabled\" to deactivate\n");
1293 spin_lock(&sbi
->ll_process_lock
);
1295 seq_printf(seq
, "snapshot_time: %lu.%lu (secs.usecs)\n",
1296 now
.tv_sec
, now
.tv_usec
);
1297 seq_printf(seq
, "%3s %10s %14s %14s %17s %17s %14s\n",
1298 "R/W", "PID", "RANGE START", "RANGE END",
1299 "SMALLEST EXTENT", "LARGEST EXTENT", "OFFSET");
1300 /* We stored the discontiguous offsets here; print them first */
1301 for(i
= 0; i
< LL_OFFSET_HIST_MAX
; i
++) {
1302 if (offset
[i
].rw_pid
!= 0)
1304 "%3c %10d %14Lu %14Lu %17lu %17lu %14Lu",
1305 offset
[i
].rw_op
== READ
? 'R' : 'W',
1307 offset
[i
].rw_range_start
,
1308 offset
[i
].rw_range_end
,
1309 (unsigned long)offset
[i
].rw_smallest_extent
,
1310 (unsigned long)offset
[i
].rw_largest_extent
,
1311 offset
[i
].rw_offset
);
1313 /* Then print the current offsets for each process */
1314 for(i
= 0; i
< LL_PROCESS_HIST_MAX
; i
++) {
1315 if (process
[i
].rw_pid
!= 0)
1317 "%3c %10d %14Lu %14Lu %17lu %17lu %14Lu",
1318 process
[i
].rw_op
== READ
? 'R' : 'W',
1320 process
[i
].rw_range_start
,
1321 process
[i
].rw_last_file_pos
,
1322 (unsigned long)process
[i
].rw_smallest_extent
,
1323 (unsigned long)process
[i
].rw_largest_extent
,
1324 process
[i
].rw_offset
);
1326 spin_unlock(&sbi
->ll_process_lock
);
1331 static ssize_t
ll_rw_offset_stats_seq_write(struct file
*file
, const char *buf
,
1332 size_t len
, loff_t
*off
)
1334 struct seq_file
*seq
= file
->private_data
;
1335 struct ll_sb_info
*sbi
= seq
->private;
1336 struct ll_rw_process_info
*process_info
= sbi
->ll_rw_process_info
;
1337 struct ll_rw_process_info
*offset_info
= sbi
->ll_rw_offset_info
;
1338 int value
= 1, rc
= 0;
1340 rc
= lprocfs_write_helper(buf
, len
, &value
);
1342 if (rc
< 0 && (strcmp(buf
, "disabled") == 0 ||
1343 strcmp(buf
, "Disabled") == 0))
1347 sbi
->ll_rw_stats_on
= 0;
1349 sbi
->ll_rw_stats_on
= 1;
1351 spin_lock(&sbi
->ll_process_lock
);
1352 sbi
->ll_offset_process_count
= 0;
1353 sbi
->ll_rw_offset_entry_count
= 0;
1354 memset(process_info
, 0, sizeof(struct ll_rw_process_info
) *
1355 LL_PROCESS_HIST_MAX
);
1356 memset(offset_info
, 0, sizeof(struct ll_rw_process_info
) *
1357 LL_OFFSET_HIST_MAX
);
1358 spin_unlock(&sbi
->ll_process_lock
);
1363 LPROC_SEQ_FOPS(ll_rw_offset_stats
);
1365 void lprocfs_llite_init_vars(struct lprocfs_static_vars
*lvars
)
1367 lvars
->module_vars
= NULL
;
1368 lvars
->obd_vars
= lprocfs_llite_obd_vars
;
1370 #endif /* LPROCFS */