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 int ll_blksize_seq_show(struct seq_file
*m
, void *v
)
53 struct super_block
*sb
= (struct super_block
*)m
->private;
54 struct obd_statfs osfs
;
58 rc
= ll_statfs_internal(sb
, &osfs
,
59 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS
),
62 rc
= seq_printf(m
, "%u\n", osfs
.os_bsize
);
66 LPROC_SEQ_FOPS_RO(ll_blksize
);
68 static int ll_kbytestotal_seq_show(struct seq_file
*m
, void *v
)
70 struct super_block
*sb
= (struct super_block
*)m
->private;
71 struct obd_statfs osfs
;
75 rc
= ll_statfs_internal(sb
, &osfs
,
76 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS
),
79 __u32 blk_size
= osfs
.os_bsize
>> 10;
80 __u64 result
= osfs
.os_blocks
;
82 while (blk_size
>>= 1)
85 rc
= seq_printf(m
, "%llu\n", result
);
89 LPROC_SEQ_FOPS_RO(ll_kbytestotal
);
91 static int ll_kbytesfree_seq_show(struct seq_file
*m
, void *v
)
93 struct super_block
*sb
= (struct super_block
*)m
->private;
94 struct obd_statfs osfs
;
98 rc
= ll_statfs_internal(sb
, &osfs
,
99 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS
),
102 __u32 blk_size
= osfs
.os_bsize
>> 10;
103 __u64 result
= osfs
.os_bfree
;
105 while (blk_size
>>= 1)
108 rc
= seq_printf(m
, "%llu\n", result
);
112 LPROC_SEQ_FOPS_RO(ll_kbytesfree
);
114 static int ll_kbytesavail_seq_show(struct seq_file
*m
, void *v
)
116 struct super_block
*sb
= (struct super_block
*)m
->private;
117 struct obd_statfs osfs
;
121 rc
= ll_statfs_internal(sb
, &osfs
,
122 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS
),
125 __u32 blk_size
= osfs
.os_bsize
>> 10;
126 __u64 result
= osfs
.os_bavail
;
128 while (blk_size
>>= 1)
131 rc
= seq_printf(m
, "%llu\n", result
);
135 LPROC_SEQ_FOPS_RO(ll_kbytesavail
);
137 static int ll_filestotal_seq_show(struct seq_file
*m
, void *v
)
139 struct super_block
*sb
= (struct super_block
*)m
->private;
140 struct obd_statfs osfs
;
144 rc
= ll_statfs_internal(sb
, &osfs
,
145 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS
),
148 rc
= seq_printf(m
, "%llu\n", osfs
.os_files
);
151 LPROC_SEQ_FOPS_RO(ll_filestotal
);
153 static int ll_filesfree_seq_show(struct seq_file
*m
, void *v
)
155 struct super_block
*sb
= (struct super_block
*)m
->private;
156 struct obd_statfs osfs
;
160 rc
= ll_statfs_internal(sb
, &osfs
,
161 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS
),
164 rc
= seq_printf(m
, "%llu\n", osfs
.os_ffree
);
167 LPROC_SEQ_FOPS_RO(ll_filesfree
);
169 static int ll_client_type_seq_show(struct seq_file
*m
, void *v
)
171 struct ll_sb_info
*sbi
= ll_s2sbi((struct super_block
*)m
->private);
174 LASSERT(sbi
!= NULL
);
176 if (sbi
->ll_flags
& LL_SBI_RMT_CLIENT
)
177 rc
= seq_printf(m
, "remote client\n");
179 rc
= seq_printf(m
, "local client\n");
183 LPROC_SEQ_FOPS_RO(ll_client_type
);
185 static int ll_fstype_seq_show(struct seq_file
*m
, void *v
)
187 struct super_block
*sb
= (struct super_block
*)m
->private;
190 seq_printf(m
, "%s\n", sb
->s_type
->name
);
193 LPROC_SEQ_FOPS_RO(ll_fstype
);
195 static int ll_sb_uuid_seq_show(struct seq_file
*m
, void *v
)
197 struct super_block
*sb
= (struct super_block
*)m
->private;
200 seq_printf(m
, "%s\n", ll_s2sbi(sb
)->ll_sb_uuid
.uuid
);
203 LPROC_SEQ_FOPS_RO(ll_sb_uuid
);
205 static int ll_site_stats_seq_show(struct seq_file
*m
, void *v
)
207 struct super_block
*sb
= m
->private;
210 * See description of statistical counters in struct cl_site, and
213 return cl_site_stats_print(lu2cl_site(ll_s2sbi(sb
)->ll_site
), m
);
215 LPROC_SEQ_FOPS_RO(ll_site_stats
);
217 static int ll_max_readahead_mb_seq_show(struct seq_file
*m
, void *v
)
219 struct super_block
*sb
= m
->private;
220 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
224 spin_lock(&sbi
->ll_lock
);
225 pages_number
= sbi
->ll_ra_info
.ra_max_pages
;
226 spin_unlock(&sbi
->ll_lock
);
228 mult
= 1 << (20 - PAGE_CACHE_SHIFT
);
229 return lprocfs_seq_read_frac_helper(m
, pages_number
, mult
);
232 static ssize_t
ll_max_readahead_mb_seq_write(struct file
*file
,
233 const char __user
*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
,
275 const char __user
*buffer
,
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 max_read_ahead_mb %lu MB\n",
290 sbi
->ll_ra_info
.ra_max_pages
);
294 spin_lock(&sbi
->ll_lock
);
295 sbi
->ll_ra_info
.ra_max_pages_per_file
= pages_number
;
296 spin_unlock(&sbi
->ll_lock
);
300 LPROC_SEQ_FOPS(ll_max_readahead_per_file_mb
);
302 static int ll_max_read_ahead_whole_mb_seq_show(struct seq_file
*m
, void *unused
)
304 struct super_block
*sb
= m
->private;
305 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
309 spin_lock(&sbi
->ll_lock
);
310 pages_number
= sbi
->ll_ra_info
.ra_max_read_ahead_whole_pages
;
311 spin_unlock(&sbi
->ll_lock
);
313 mult
= 1 << (20 - PAGE_CACHE_SHIFT
);
314 return lprocfs_seq_read_frac_helper(m
, pages_number
, mult
);
317 static ssize_t
ll_max_read_ahead_whole_mb_seq_write(struct file
*file
,
318 const char __user
*buffer
,
319 size_t count
, loff_t
*off
)
321 struct super_block
*sb
= ((struct seq_file
*)file
->private_data
)->private;
322 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
323 int mult
, rc
, pages_number
;
325 mult
= 1 << (20 - PAGE_CACHE_SHIFT
);
326 rc
= lprocfs_write_frac_helper(buffer
, count
, &pages_number
, mult
);
330 /* Cap this at the current max readahead window size, the readahead
331 * algorithm does this anyway so it's pointless to set it larger. */
332 if (pages_number
< 0 ||
333 pages_number
> sbi
->ll_ra_info
.ra_max_pages_per_file
) {
334 CERROR("can't set max_read_ahead_whole_mb more than max_read_ahead_per_file_mb: %lu\n",
335 sbi
->ll_ra_info
.ra_max_pages_per_file
>> (20 - PAGE_CACHE_SHIFT
));
339 spin_lock(&sbi
->ll_lock
);
340 sbi
->ll_ra_info
.ra_max_read_ahead_whole_pages
= pages_number
;
341 spin_unlock(&sbi
->ll_lock
);
345 LPROC_SEQ_FOPS(ll_max_read_ahead_whole_mb
);
347 static int ll_max_cached_mb_seq_show(struct seq_file
*m
, void *v
)
349 struct super_block
*sb
= m
->private;
350 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
351 struct cl_client_cache
*cache
= &sbi
->ll_cache
;
352 int shift
= 20 - PAGE_CACHE_SHIFT
;
356 max_cached_mb
= cache
->ccc_lru_max
>> shift
;
357 unused_mb
= atomic_read(&cache
->ccc_lru_left
) >> shift
;
360 "max_cached_mb: %d\n"
363 "reclaim_count: %u\n",
364 atomic_read(&cache
->ccc_users
),
366 max_cached_mb
- unused_mb
,
368 cache
->ccc_lru_shrinkers
);
372 static ssize_t
ll_max_cached_mb_seq_write(struct file
*file
,
373 const char __user
*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
;
384 if (count
>= sizeof(kernbuf
))
387 if (copy_from_user(kernbuf
, buffer
, count
))
391 mult
= 1 << (20 - PAGE_CACHE_SHIFT
);
392 buffer
+= lprocfs_find_named_value(kernbuf
, "max_cached_mb:", &count
) -
394 rc
= lprocfs_write_frac_helper(buffer
, count
, &pages_number
, mult
);
398 if (pages_number
< 0 || pages_number
> totalram_pages
) {
399 CERROR("%s: can't set max cache more than %lu MB\n",
400 ll_get_fsname(sb
, NULL
, 0),
401 totalram_pages
>> (20 - PAGE_CACHE_SHIFT
));
405 spin_lock(&sbi
->ll_lock
);
406 diff
= pages_number
- cache
->ccc_lru_max
;
407 spin_unlock(&sbi
->ll_lock
);
409 /* easy - add more LRU slots. */
411 atomic_add(diff
, &cache
->ccc_lru_left
);
420 /* reduce LRU budget from free slots. */
424 ov
= atomic_read(&cache
->ccc_lru_left
);
428 nv
= ov
> diff
? ov
- diff
: 0;
429 rc
= atomic_cmpxchg(&cache
->ccc_lru_left
, ov
, nv
);
430 if (likely(ov
== rc
)) {
440 if (sbi
->ll_dt_exp
== NULL
) { /* being initialized */
445 /* difficult - have to ask OSCs to drop LRU slots. */
447 rc
= obd_set_info_async(NULL
, sbi
->ll_dt_exp
,
448 sizeof(KEY_CACHE_LRU_SHRINK
),
449 KEY_CACHE_LRU_SHRINK
,
450 sizeof(tmp
), &tmp
, NULL
);
457 spin_lock(&sbi
->ll_lock
);
458 cache
->ccc_lru_max
= pages_number
;
459 spin_unlock(&sbi
->ll_lock
);
462 atomic_add(nrpages
, &cache
->ccc_lru_left
);
466 LPROC_SEQ_FOPS(ll_max_cached_mb
);
468 static int ll_checksum_seq_show(struct seq_file
*m
, void *v
)
470 struct super_block
*sb
= m
->private;
471 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
473 seq_printf(m
, "%u\n", (sbi
->ll_flags
& LL_SBI_CHECKSUM
) ? 1 : 0);
477 static ssize_t
ll_checksum_seq_write(struct file
*file
,
478 const char __user
*buffer
,
479 size_t count
, loff_t
*off
)
481 struct super_block
*sb
= ((struct seq_file
*)file
->private_data
)->private;
482 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
489 rc
= lprocfs_write_helper(buffer
, count
, &val
);
493 sbi
->ll_flags
|= LL_SBI_CHECKSUM
;
495 sbi
->ll_flags
&= ~LL_SBI_CHECKSUM
;
497 rc
= obd_set_info_async(NULL
, sbi
->ll_dt_exp
, sizeof(KEY_CHECKSUM
),
498 KEY_CHECKSUM
, sizeof(val
), &val
, NULL
);
500 CWARN("Failed to set OSC checksum flags: %d\n", rc
);
504 LPROC_SEQ_FOPS(ll_checksum
);
506 static int ll_max_rw_chunk_seq_show(struct seq_file
*m
, void *v
)
508 struct super_block
*sb
= m
->private;
510 seq_printf(m
, "%lu\n", ll_s2sbi(sb
)->ll_max_rw_chunk
);
514 static ssize_t
ll_max_rw_chunk_seq_write(struct file
*file
,
515 const char __user
*buffer
,
516 size_t count
, loff_t
*off
)
518 struct super_block
*sb
= ((struct seq_file
*)file
->private_data
)->private;
521 rc
= lprocfs_write_helper(buffer
, count
, &val
);
524 ll_s2sbi(sb
)->ll_max_rw_chunk
= val
;
527 LPROC_SEQ_FOPS(ll_max_rw_chunk
);
529 static int ll_rd_track_id(struct seq_file
*m
, enum stats_track_type type
)
531 struct super_block
*sb
= m
->private;
533 if (ll_s2sbi(sb
)->ll_stats_track_type
== type
)
534 seq_printf(m
, "%d\n", ll_s2sbi(sb
)->ll_stats_track_id
);
535 else if (ll_s2sbi(sb
)->ll_stats_track_type
== STATS_TRACK_ALL
)
536 seq_puts(m
, "0 (all)\n");
538 seq_puts(m
, "untracked\n");
543 static int ll_wr_track_id(const char __user
*buffer
, unsigned long count
,
544 void *data
, enum stats_track_type type
)
546 struct super_block
*sb
= data
;
549 rc
= lprocfs_write_helper(buffer
, count
, &pid
);
552 ll_s2sbi(sb
)->ll_stats_track_id
= pid
;
554 ll_s2sbi(sb
)->ll_stats_track_type
= STATS_TRACK_ALL
;
556 ll_s2sbi(sb
)->ll_stats_track_type
= type
;
557 lprocfs_clear_stats(ll_s2sbi(sb
)->ll_stats
);
561 static int ll_track_pid_seq_show(struct seq_file
*m
, void *v
)
563 return ll_rd_track_id(m
, STATS_TRACK_PID
);
566 static ssize_t
ll_track_pid_seq_write(struct file
*file
,
567 const char __user
*buffer
,
568 size_t count
, loff_t
*off
)
570 struct seq_file
*seq
= file
->private_data
;
571 return ll_wr_track_id(buffer
, count
, seq
->private, STATS_TRACK_PID
);
573 LPROC_SEQ_FOPS(ll_track_pid
);
575 static int ll_track_ppid_seq_show(struct seq_file
*m
, void *v
)
577 return ll_rd_track_id(m
, STATS_TRACK_PPID
);
580 static ssize_t
ll_track_ppid_seq_write(struct file
*file
,
581 const char __user
*buffer
,
582 size_t count
, loff_t
*off
)
584 struct seq_file
*seq
= file
->private_data
;
585 return ll_wr_track_id(buffer
, count
, seq
->private, STATS_TRACK_PPID
);
587 LPROC_SEQ_FOPS(ll_track_ppid
);
589 static int ll_track_gid_seq_show(struct seq_file
*m
, void *v
)
591 return ll_rd_track_id(m
, STATS_TRACK_GID
);
594 static ssize_t
ll_track_gid_seq_write(struct file
*file
,
595 const char __user
*buffer
,
596 size_t count
, loff_t
*off
)
598 struct seq_file
*seq
= file
->private_data
;
599 return ll_wr_track_id(buffer
, count
, seq
->private, STATS_TRACK_GID
);
601 LPROC_SEQ_FOPS(ll_track_gid
);
603 static int ll_statahead_max_seq_show(struct seq_file
*m
, void *v
)
605 struct super_block
*sb
= m
->private;
606 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
608 seq_printf(m
, "%u\n", sbi
->ll_sa_max
);
612 static ssize_t
ll_statahead_max_seq_write(struct file
*file
,
613 const char __user
*buffer
,
614 size_t count
, loff_t
*off
)
616 struct super_block
*sb
= ((struct seq_file
*)file
->private_data
)->private;
617 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
620 rc
= lprocfs_write_helper(buffer
, count
, &val
);
624 if (val
>= 0 && val
<= LL_SA_RPC_MAX
)
625 sbi
->ll_sa_max
= val
;
627 CERROR("Bad statahead_max value %d. Valid values are in the range [0, %d]\n",
632 LPROC_SEQ_FOPS(ll_statahead_max
);
634 static int ll_statahead_agl_seq_show(struct seq_file
*m
, void *v
)
636 struct super_block
*sb
= m
->private;
637 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
639 seq_printf(m
, "%u\n", sbi
->ll_flags
& LL_SBI_AGL_ENABLED
? 1 : 0);
643 static ssize_t
ll_statahead_agl_seq_write(struct file
*file
,
644 const char __user
*buffer
,
645 size_t count
, loff_t
*off
)
647 struct super_block
*sb
= ((struct seq_file
*)file
->private_data
)->private;
648 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
651 rc
= lprocfs_write_helper(buffer
, count
, &val
);
656 sbi
->ll_flags
|= LL_SBI_AGL_ENABLED
;
658 sbi
->ll_flags
&= ~LL_SBI_AGL_ENABLED
;
662 LPROC_SEQ_FOPS(ll_statahead_agl
);
664 static int ll_statahead_stats_seq_show(struct seq_file
*m
, void *v
)
666 struct super_block
*sb
= m
->private;
667 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
670 "statahead total: %u\n"
671 "statahead wrong: %u\n"
673 atomic_read(&sbi
->ll_sa_total
),
674 atomic_read(&sbi
->ll_sa_wrong
),
675 atomic_read(&sbi
->ll_agl_total
));
678 LPROC_SEQ_FOPS_RO(ll_statahead_stats
);
680 static int ll_lazystatfs_seq_show(struct seq_file
*m
, void *v
)
682 struct super_block
*sb
= m
->private;
683 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
685 seq_printf(m
, "%u\n", sbi
->ll_flags
& LL_SBI_LAZYSTATFS
? 1 : 0);
689 static ssize_t
ll_lazystatfs_seq_write(struct file
*file
,
690 const char __user
*buffer
,
691 size_t count
, loff_t
*off
)
693 struct super_block
*sb
= ((struct seq_file
*)file
->private_data
)->private;
694 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
697 rc
= lprocfs_write_helper(buffer
, count
, &val
);
702 sbi
->ll_flags
|= LL_SBI_LAZYSTATFS
;
704 sbi
->ll_flags
&= ~LL_SBI_LAZYSTATFS
;
708 LPROC_SEQ_FOPS(ll_lazystatfs
);
710 static int ll_max_easize_seq_show(struct seq_file
*m
, void *v
)
712 struct super_block
*sb
= m
->private;
713 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
717 rc
= ll_get_max_mdsize(sbi
, &ealen
);
721 seq_printf(m
, "%u\n", ealen
);
724 LPROC_SEQ_FOPS_RO(ll_max_easize
);
726 static int ll_defult_easize_seq_show(struct seq_file
*m
, void *v
)
728 struct super_block
*sb
= m
->private;
729 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
733 rc
= ll_get_default_mdsize(sbi
, &ealen
);
737 seq_printf(m
, "%u\n", ealen
);
740 LPROC_SEQ_FOPS_RO(ll_defult_easize
);
742 static int ll_max_cookiesize_seq_show(struct seq_file
*m
, void *v
)
744 struct super_block
*sb
= m
->private;
745 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
746 unsigned int cookielen
;
749 rc
= ll_get_max_cookiesize(sbi
, &cookielen
);
753 seq_printf(m
, "%u\n", cookielen
);
756 LPROC_SEQ_FOPS_RO(ll_max_cookiesize
);
758 static int ll_defult_cookiesize_seq_show(struct seq_file
*m
, void *v
)
760 struct super_block
*sb
= m
->private;
761 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
762 unsigned int cookielen
;
765 rc
= ll_get_default_cookiesize(sbi
, &cookielen
);
769 seq_printf(m
, "%u\n", cookielen
);
772 LPROC_SEQ_FOPS_RO(ll_defult_cookiesize
);
774 static int ll_sbi_flags_seq_show(struct seq_file
*m
, void *v
)
776 const char *str
[] = LL_SBI_FLAGS
;
777 struct super_block
*sb
= m
->private;
778 int flags
= ll_s2sbi(sb
)->ll_flags
;
782 if (ARRAY_SIZE(str
) <= i
) {
783 CERROR("%s: Revise array LL_SBI_FLAGS to match sbi flags please.\n",
784 ll_get_fsname(sb
, NULL
, 0));
789 seq_printf(m
, "%s ", str
[i
]);
793 seq_printf(m
, "\b\n");
796 LPROC_SEQ_FOPS_RO(ll_sbi_flags
);
798 static int ll_xattr_cache_seq_show(struct seq_file
*m
, void *v
)
800 struct super_block
*sb
= m
->private;
801 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
803 return seq_printf(m
, "%u\n", sbi
->ll_xattr_cache_enabled
);
806 static ssize_t
ll_xattr_cache_seq_write(struct file
*file
,
807 const char __user
*buffer
,
808 size_t count
, loff_t
*off
)
810 struct seq_file
*seq
= file
->private_data
;
811 struct super_block
*sb
= seq
->private;
812 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
815 rc
= lprocfs_write_helper(buffer
, count
, &val
);
819 if (val
!= 0 && val
!= 1)
822 if (val
== 1 && !(sbi
->ll_flags
& LL_SBI_XATTR_CACHE
))
825 sbi
->ll_xattr_cache_enabled
= val
;
829 LPROC_SEQ_FOPS(ll_xattr_cache
);
831 static struct lprocfs_vars lprocfs_llite_obd_vars
[] = {
832 { "uuid", &ll_sb_uuid_fops
, NULL
, 0 },
833 /* { "mntpt_path", ll_rd_path, 0, 0 }, */
834 { "fstype", &ll_fstype_fops
, NULL
, 0 },
835 { "site", &ll_site_stats_fops
, NULL
, 0 },
836 { "blocksize", &ll_blksize_fops
, NULL
, 0 },
837 { "kbytestotal", &ll_kbytestotal_fops
, NULL
, 0 },
838 { "kbytesfree", &ll_kbytesfree_fops
, NULL
, 0 },
839 { "kbytesavail", &ll_kbytesavail_fops
, NULL
, 0 },
840 { "filestotal", &ll_filestotal_fops
, NULL
, 0 },
841 { "filesfree", &ll_filesfree_fops
, NULL
, 0 },
842 { "client_type", &ll_client_type_fops
, NULL
, 0 },
843 /* { "filegroups", lprocfs_rd_filegroups, 0, 0 }, */
844 { "max_read_ahead_mb", &ll_max_readahead_mb_fops
, NULL
},
845 { "max_read_ahead_per_file_mb", &ll_max_readahead_per_file_mb_fops
,
847 { "max_read_ahead_whole_mb", &ll_max_read_ahead_whole_mb_fops
, NULL
},
848 { "max_cached_mb", &ll_max_cached_mb_fops
, NULL
},
849 { "checksum_pages", &ll_checksum_fops
, NULL
},
850 { "max_rw_chunk", &ll_max_rw_chunk_fops
, NULL
},
851 { "stats_track_pid", &ll_track_pid_fops
, NULL
},
852 { "stats_track_ppid", &ll_track_ppid_fops
, NULL
},
853 { "stats_track_gid", &ll_track_gid_fops
, NULL
},
854 { "statahead_max", &ll_statahead_max_fops
, NULL
},
855 { "statahead_agl", &ll_statahead_agl_fops
, NULL
},
856 { "statahead_stats", &ll_statahead_stats_fops
, NULL
, 0 },
857 { "lazystatfs", &ll_lazystatfs_fops
, NULL
},
858 { "max_easize", &ll_max_easize_fops
, NULL
, 0 },
859 { "default_easize", &ll_defult_easize_fops
, NULL
, 0 },
860 { "max_cookiesize", &ll_max_cookiesize_fops
, NULL
, 0 },
861 { "default_cookiesize", &ll_defult_cookiesize_fops
, NULL
, 0 },
862 { "sbi_flags", &ll_sbi_flags_fops
, NULL
, 0 },
863 { "xattr_cache", &ll_xattr_cache_fops
, NULL
, 0 },
867 #define MAX_STRING_SIZE 128
869 static const struct llite_file_opcode
{
873 } llite_opcode_table
[LPROC_LL_FILE_OPCODES
] = {
875 { LPROC_LL_DIRTY_HITS
, LPROCFS_TYPE_REGS
, "dirty_pages_hits" },
876 { LPROC_LL_DIRTY_MISSES
, LPROCFS_TYPE_REGS
, "dirty_pages_misses" },
877 { LPROC_LL_READ_BYTES
, LPROCFS_CNTR_AVGMINMAX
|LPROCFS_TYPE_BYTES
,
879 { LPROC_LL_WRITE_BYTES
, LPROCFS_CNTR_AVGMINMAX
|LPROCFS_TYPE_BYTES
,
881 { LPROC_LL_BRW_READ
, LPROCFS_CNTR_AVGMINMAX
|LPROCFS_TYPE_PAGES
,
883 { LPROC_LL_BRW_WRITE
, LPROCFS_CNTR_AVGMINMAX
|LPROCFS_TYPE_PAGES
,
885 { LPROC_LL_OSC_READ
, LPROCFS_CNTR_AVGMINMAX
|LPROCFS_TYPE_BYTES
,
887 { LPROC_LL_OSC_WRITE
, LPROCFS_CNTR_AVGMINMAX
|LPROCFS_TYPE_BYTES
,
889 { LPROC_LL_IOCTL
, LPROCFS_TYPE_REGS
, "ioctl" },
890 { LPROC_LL_OPEN
, LPROCFS_TYPE_REGS
, "open" },
891 { LPROC_LL_RELEASE
, LPROCFS_TYPE_REGS
, "close" },
892 { LPROC_LL_MAP
, LPROCFS_TYPE_REGS
, "mmap" },
893 { LPROC_LL_LLSEEK
, LPROCFS_TYPE_REGS
, "seek" },
894 { LPROC_LL_FSYNC
, LPROCFS_TYPE_REGS
, "fsync" },
895 { LPROC_LL_READDIR
, LPROCFS_TYPE_REGS
, "readdir" },
896 /* inode operation */
897 { LPROC_LL_SETATTR
, LPROCFS_TYPE_REGS
, "setattr" },
898 { LPROC_LL_TRUNC
, LPROCFS_TYPE_REGS
, "truncate" },
899 { LPROC_LL_FLOCK
, LPROCFS_TYPE_REGS
, "flock" },
900 { LPROC_LL_GETATTR
, LPROCFS_TYPE_REGS
, "getattr" },
901 /* dir inode operation */
902 { LPROC_LL_CREATE
, LPROCFS_TYPE_REGS
, "create" },
903 { LPROC_LL_LINK
, LPROCFS_TYPE_REGS
, "link" },
904 { LPROC_LL_UNLINK
, LPROCFS_TYPE_REGS
, "unlink" },
905 { LPROC_LL_SYMLINK
, LPROCFS_TYPE_REGS
, "symlink" },
906 { LPROC_LL_MKDIR
, LPROCFS_TYPE_REGS
, "mkdir" },
907 { LPROC_LL_RMDIR
, LPROCFS_TYPE_REGS
, "rmdir" },
908 { LPROC_LL_MKNOD
, LPROCFS_TYPE_REGS
, "mknod" },
909 { LPROC_LL_RENAME
, LPROCFS_TYPE_REGS
, "rename" },
910 /* special inode operation */
911 { LPROC_LL_STAFS
, LPROCFS_TYPE_REGS
, "statfs" },
912 { LPROC_LL_ALLOC_INODE
, LPROCFS_TYPE_REGS
, "alloc_inode" },
913 { LPROC_LL_SETXATTR
, LPROCFS_TYPE_REGS
, "setxattr" },
914 { LPROC_LL_GETXATTR
, LPROCFS_TYPE_REGS
, "getxattr" },
915 { LPROC_LL_GETXATTR_HITS
, LPROCFS_TYPE_REGS
, "getxattr_hits" },
916 { LPROC_LL_LISTXATTR
, LPROCFS_TYPE_REGS
, "listxattr" },
917 { LPROC_LL_REMOVEXATTR
, LPROCFS_TYPE_REGS
, "removexattr" },
918 { LPROC_LL_INODE_PERM
, LPROCFS_TYPE_REGS
, "inode_permission" },
921 void ll_stats_ops_tally(struct ll_sb_info
*sbi
, int op
, int count
)
925 if (sbi
->ll_stats_track_type
== STATS_TRACK_ALL
)
926 lprocfs_counter_add(sbi
->ll_stats
, op
, count
);
927 else if (sbi
->ll_stats_track_type
== STATS_TRACK_PID
&&
928 sbi
->ll_stats_track_id
== current
->pid
)
929 lprocfs_counter_add(sbi
->ll_stats
, op
, count
);
930 else if (sbi
->ll_stats_track_type
== STATS_TRACK_PPID
&&
931 sbi
->ll_stats_track_id
== current
->real_parent
->pid
)
932 lprocfs_counter_add(sbi
->ll_stats
, op
, count
);
933 else if (sbi
->ll_stats_track_type
== STATS_TRACK_GID
&&
934 sbi
->ll_stats_track_id
==
935 from_kgid(&init_user_ns
, current_gid()))
936 lprocfs_counter_add(sbi
->ll_stats
, op
, count
);
938 EXPORT_SYMBOL(ll_stats_ops_tally
);
940 static const char *ra_stat_string
[] = {
941 [RA_STAT_HIT
] = "hits",
942 [RA_STAT_MISS
] = "misses",
943 [RA_STAT_DISTANT_READPAGE
] = "readpage not consecutive",
944 [RA_STAT_MISS_IN_WINDOW
] = "miss inside window",
945 [RA_STAT_FAILED_GRAB_PAGE
] = "failed grab_cache_page",
946 [RA_STAT_FAILED_MATCH
] = "failed lock match",
947 [RA_STAT_DISCARDED
] = "read but discarded",
948 [RA_STAT_ZERO_LEN
] = "zero length file",
949 [RA_STAT_ZERO_WINDOW
] = "zero size window",
950 [RA_STAT_EOF
] = "read-ahead to EOF",
951 [RA_STAT_MAX_IN_FLIGHT
] = "hit max r-a issue",
952 [RA_STAT_WRONG_GRAB_PAGE
] = "wrong page from grab_cache_page",
955 LPROC_SEQ_FOPS_RO_TYPE(llite
, name
);
956 LPROC_SEQ_FOPS_RO_TYPE(llite
, uuid
);
958 int lprocfs_register_mountpoint(struct proc_dir_entry
*parent
,
959 struct super_block
*sb
, char *osc
, char *mdc
)
961 struct lprocfs_vars lvars
[2];
962 struct lustre_sb_info
*lsi
= s2lsi(sb
);
963 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
964 struct obd_device
*obd
;
965 struct proc_dir_entry
*dir
;
966 char name
[MAX_STRING_SIZE
+ 1], *ptr
;
967 int err
, id
, len
, rc
;
969 memset(lvars
, 0, sizeof(lvars
));
971 name
[MAX_STRING_SIZE
] = '\0';
972 lvars
[0].name
= name
;
974 LASSERT(sbi
!= NULL
);
975 LASSERT(mdc
!= NULL
);
976 LASSERT(osc
!= NULL
);
979 len
= strlen(lsi
->lsi_lmd
->lmd_profile
);
980 ptr
= strrchr(lsi
->lsi_lmd
->lmd_profile
, '-');
981 if (ptr
&& (strcmp(ptr
, "-client") == 0))
985 snprintf(name
, MAX_STRING_SIZE
, "%.*s-%p", len
,
986 lsi
->lsi_lmd
->lmd_profile
, sb
);
988 sbi
->ll_proc_root
= lprocfs_register(name
, parent
, NULL
, NULL
);
989 if (IS_ERR(sbi
->ll_proc_root
)) {
990 err
= PTR_ERR(sbi
->ll_proc_root
);
991 sbi
->ll_proc_root
= NULL
;
995 rc
= lprocfs_seq_create(sbi
->ll_proc_root
, "dump_page_cache", 0444,
996 &vvp_dump_pgcache_file_ops
, sbi
);
998 CWARN("Error adding the dump_page_cache file\n");
1000 rc
= lprocfs_seq_create(sbi
->ll_proc_root
, "extents_stats", 0644,
1001 &ll_rw_extents_stats_fops
, sbi
);
1003 CWARN("Error adding the extent_stats file\n");
1005 rc
= lprocfs_seq_create(sbi
->ll_proc_root
, "extents_stats_per_process",
1006 0644, &ll_rw_extents_stats_pp_fops
, sbi
);
1008 CWARN("Error adding the extents_stats_per_process file\n");
1010 rc
= lprocfs_seq_create(sbi
->ll_proc_root
, "offset_stats", 0644,
1011 &ll_rw_offset_stats_fops
, sbi
);
1013 CWARN("Error adding the offset_stats file\n");
1015 /* File operations stats */
1016 sbi
->ll_stats
= lprocfs_alloc_stats(LPROC_LL_FILE_OPCODES
,
1017 LPROCFS_STATS_FLAG_NONE
);
1018 if (sbi
->ll_stats
== NULL
) {
1022 /* do counter init */
1023 for (id
= 0; id
< LPROC_LL_FILE_OPCODES
; id
++) {
1024 __u32 type
= llite_opcode_table
[id
].type
;
1026 if (type
& LPROCFS_TYPE_REGS
)
1028 else if (type
& LPROCFS_TYPE_BYTES
)
1030 else if (type
& LPROCFS_TYPE_PAGES
)
1032 lprocfs_counter_init(sbi
->ll_stats
,
1033 llite_opcode_table
[id
].opcode
,
1034 (type
& LPROCFS_CNTR_AVGMINMAX
),
1035 llite_opcode_table
[id
].opname
, ptr
);
1037 err
= lprocfs_register_stats(sbi
->ll_proc_root
, "stats", sbi
->ll_stats
);
1041 sbi
->ll_ra_stats
= lprocfs_alloc_stats(ARRAY_SIZE(ra_stat_string
),
1042 LPROCFS_STATS_FLAG_NONE
);
1043 if (sbi
->ll_ra_stats
== NULL
) {
1048 for (id
= 0; id
< ARRAY_SIZE(ra_stat_string
); id
++)
1049 lprocfs_counter_init(sbi
->ll_ra_stats
, id
, 0,
1050 ra_stat_string
[id
], "pages");
1051 err
= lprocfs_register_stats(sbi
->ll_proc_root
, "read_ahead_stats",
1057 err
= lprocfs_add_vars(sbi
->ll_proc_root
, lprocfs_llite_obd_vars
, sb
);
1062 obd
= class_name2obd(mdc
);
1064 LASSERT(obd
!= NULL
);
1065 LASSERT(obd
->obd_magic
== OBD_DEVICE_MAGIC
);
1066 LASSERT(obd
->obd_type
->typ_name
!= NULL
);
1068 dir
= proc_mkdir(obd
->obd_type
->typ_name
, sbi
->ll_proc_root
);
1074 snprintf(name
, MAX_STRING_SIZE
, "common_name");
1075 lvars
[0].fops
= &llite_name_fops
;
1076 err
= lprocfs_add_vars(dir
, lvars
, obd
);
1080 snprintf(name
, MAX_STRING_SIZE
, "uuid");
1081 lvars
[0].fops
= &llite_uuid_fops
;
1082 err
= lprocfs_add_vars(dir
, lvars
, obd
);
1087 obd
= class_name2obd(osc
);
1089 LASSERT(obd
!= NULL
);
1090 LASSERT(obd
->obd_magic
== OBD_DEVICE_MAGIC
);
1091 LASSERT(obd
->obd_type
->typ_name
!= NULL
);
1093 dir
= proc_mkdir(obd
->obd_type
->typ_name
, sbi
->ll_proc_root
);
1099 snprintf(name
, MAX_STRING_SIZE
, "common_name");
1100 lvars
[0].fops
= &llite_name_fops
;
1101 err
= lprocfs_add_vars(dir
, lvars
, obd
);
1105 snprintf(name
, MAX_STRING_SIZE
, "uuid");
1106 lvars
[0].fops
= &llite_uuid_fops
;
1107 err
= lprocfs_add_vars(dir
, lvars
, obd
);
1110 lprocfs_remove(&sbi
->ll_proc_root
);
1111 lprocfs_free_stats(&sbi
->ll_ra_stats
);
1112 lprocfs_free_stats(&sbi
->ll_stats
);
1117 void lprocfs_unregister_mountpoint(struct ll_sb_info
*sbi
)
1119 if (sbi
->ll_proc_root
) {
1120 lprocfs_remove(&sbi
->ll_proc_root
);
1121 lprocfs_free_stats(&sbi
->ll_ra_stats
);
1122 lprocfs_free_stats(&sbi
->ll_stats
);
1125 #undef MAX_STRING_SIZE
1127 #define pct(a, b) (b ? a * 100 / b : 0)
1129 static void ll_display_extents_info(struct ll_rw_extents_info
*io_extents
,
1130 struct seq_file
*seq
, int which
)
1132 unsigned long read_tot
= 0, write_tot
= 0, read_cum
, write_cum
;
1133 unsigned long start
, end
, r
, w
;
1134 char *unitp
= "KMGTPEZY";
1136 struct per_process_info
*pp_info
= &io_extents
->pp_extents
[which
];
1142 for (i
= 0; i
< LL_HIST_MAX
; i
++) {
1143 read_tot
+= pp_info
->pp_r_hist
.oh_buckets
[i
];
1144 write_tot
+= pp_info
->pp_w_hist
.oh_buckets
[i
];
1147 for (i
= 0; i
< LL_HIST_MAX
; i
++) {
1148 r
= pp_info
->pp_r_hist
.oh_buckets
[i
];
1149 w
= pp_info
->pp_w_hist
.oh_buckets
[i
];
1152 end
= 1 << (i
+ LL_HIST_START
- units
);
1153 seq_printf(seq
, "%4lu%c - %4lu%c%c: %14lu %4lu %4lu | %14lu %4lu %4lu\n",
1154 start
, *unitp
, end
, *unitp
,
1155 (i
== LL_HIST_MAX
- 1) ? '+' : ' ',
1156 r
, pct(r
, read_tot
), pct(read_cum
, read_tot
),
1157 w
, pct(w
, write_tot
), pct(write_cum
, write_tot
));
1159 if (start
== 1<<10) {
1164 if (read_cum
== read_tot
&& write_cum
== write_tot
)
1169 static int ll_rw_extents_stats_pp_seq_show(struct seq_file
*seq
, void *v
)
1172 struct ll_sb_info
*sbi
= seq
->private;
1173 struct ll_rw_extents_info
*io_extents
= &sbi
->ll_rw_extents_info
;
1176 do_gettimeofday(&now
);
1178 if (!sbi
->ll_rw_stats_on
) {
1179 seq_printf(seq
, "disabled\n"
1180 "write anything in this file to activate, then 0 or \"[D/d]isabled\" to deactivate\n");
1183 seq_printf(seq
, "snapshot_time: %lu.%lu (secs.usecs)\n",
1184 now
.tv_sec
, (unsigned long)now
.tv_usec
);
1185 seq_printf(seq
, "%15s %19s | %20s\n", " ", "read", "write");
1186 seq_printf(seq
, "%13s %14s %4s %4s | %14s %4s %4s\n",
1187 "extents", "calls", "%", "cum%",
1188 "calls", "%", "cum%");
1189 spin_lock(&sbi
->ll_pp_extent_lock
);
1190 for (k
= 0; k
< LL_PROCESS_HIST_MAX
; k
++) {
1191 if (io_extents
->pp_extents
[k
].pid
!= 0) {
1192 seq_printf(seq
, "\nPID: %d\n",
1193 io_extents
->pp_extents
[k
].pid
);
1194 ll_display_extents_info(io_extents
, seq
, k
);
1197 spin_unlock(&sbi
->ll_pp_extent_lock
);
1201 static ssize_t
ll_rw_extents_stats_pp_seq_write(struct file
*file
,
1202 const char __user
*buf
,
1206 struct seq_file
*seq
= file
->private_data
;
1207 struct ll_sb_info
*sbi
= seq
->private;
1208 struct ll_rw_extents_info
*io_extents
= &sbi
->ll_rw_extents_info
;
1210 int value
= 1, rc
= 0;
1215 rc
= lprocfs_write_helper(buf
, len
, &value
);
1216 if (rc
< 0 && len
< 16) {
1219 if (copy_from_user(kernbuf
, buf
, len
))
1223 if (kernbuf
[len
- 1] == '\n')
1224 kernbuf
[len
- 1] = 0;
1226 if (strcmp(kernbuf
, "disabled") == 0 ||
1227 strcmp(kernbuf
, "Disabled") == 0)
1232 sbi
->ll_rw_stats_on
= 0;
1234 sbi
->ll_rw_stats_on
= 1;
1236 spin_lock(&sbi
->ll_pp_extent_lock
);
1237 for (i
= 0; i
< LL_PROCESS_HIST_MAX
; i
++) {
1238 io_extents
->pp_extents
[i
].pid
= 0;
1239 lprocfs_oh_clear(&io_extents
->pp_extents
[i
].pp_r_hist
);
1240 lprocfs_oh_clear(&io_extents
->pp_extents
[i
].pp_w_hist
);
1242 spin_unlock(&sbi
->ll_pp_extent_lock
);
1246 LPROC_SEQ_FOPS(ll_rw_extents_stats_pp
);
1248 static int ll_rw_extents_stats_seq_show(struct seq_file
*seq
, void *v
)
1251 struct ll_sb_info
*sbi
= seq
->private;
1252 struct ll_rw_extents_info
*io_extents
= &sbi
->ll_rw_extents_info
;
1254 do_gettimeofday(&now
);
1256 if (!sbi
->ll_rw_stats_on
) {
1257 seq_printf(seq
, "disabled\n"
1258 "write anything in this file to activate, then 0 or \"[D/d]isabled\" to deactivate\n");
1261 seq_printf(seq
, "snapshot_time: %lu.%lu (secs.usecs)\n",
1262 now
.tv_sec
, (unsigned long)now
.tv_usec
);
1264 seq_printf(seq
, "%15s %19s | %20s\n", " ", "read", "write");
1265 seq_printf(seq
, "%13s %14s %4s %4s | %14s %4s %4s\n",
1266 "extents", "calls", "%", "cum%",
1267 "calls", "%", "cum%");
1268 spin_lock(&sbi
->ll_lock
);
1269 ll_display_extents_info(io_extents
, seq
, LL_PROCESS_HIST_MAX
);
1270 spin_unlock(&sbi
->ll_lock
);
1275 static ssize_t
ll_rw_extents_stats_seq_write(struct file
*file
,
1276 const char __user
*buf
,
1277 size_t len
, loff_t
*off
)
1279 struct seq_file
*seq
= file
->private_data
;
1280 struct ll_sb_info
*sbi
= seq
->private;
1281 struct ll_rw_extents_info
*io_extents
= &sbi
->ll_rw_extents_info
;
1283 int value
= 1, rc
= 0;
1288 rc
= lprocfs_write_helper(buf
, len
, &value
);
1289 if (rc
< 0 && len
< 16) {
1292 if (copy_from_user(kernbuf
, buf
, len
))
1296 if (kernbuf
[len
- 1] == '\n')
1297 kernbuf
[len
- 1] = 0;
1299 if (strcmp(kernbuf
, "disabled") == 0 ||
1300 strcmp(kernbuf
, "Disabled") == 0)
1305 sbi
->ll_rw_stats_on
= 0;
1307 sbi
->ll_rw_stats_on
= 1;
1309 spin_lock(&sbi
->ll_pp_extent_lock
);
1310 for (i
= 0; i
<= LL_PROCESS_HIST_MAX
; i
++) {
1311 io_extents
->pp_extents
[i
].pid
= 0;
1312 lprocfs_oh_clear(&io_extents
->pp_extents
[i
].pp_r_hist
);
1313 lprocfs_oh_clear(&io_extents
->pp_extents
[i
].pp_w_hist
);
1315 spin_unlock(&sbi
->ll_pp_extent_lock
);
1319 LPROC_SEQ_FOPS(ll_rw_extents_stats
);
1321 void ll_rw_stats_tally(struct ll_sb_info
*sbi
, pid_t pid
,
1322 struct ll_file_data
*file
, loff_t pos
,
1323 size_t count
, int rw
)
1326 struct ll_rw_process_info
*process
;
1327 struct ll_rw_process_info
*offset
;
1328 int *off_count
= &sbi
->ll_rw_offset_entry_count
;
1329 int *process_count
= &sbi
->ll_offset_process_count
;
1330 struct ll_rw_extents_info
*io_extents
= &sbi
->ll_rw_extents_info
;
1332 if (!sbi
->ll_rw_stats_on
)
1334 process
= sbi
->ll_rw_process_info
;
1335 offset
= sbi
->ll_rw_offset_info
;
1337 spin_lock(&sbi
->ll_pp_extent_lock
);
1338 /* Extent statistics */
1339 for (i
= 0; i
< LL_PROCESS_HIST_MAX
; i
++) {
1340 if (io_extents
->pp_extents
[i
].pid
== pid
) {
1348 sbi
->ll_extent_process_count
=
1349 (sbi
->ll_extent_process_count
+ 1) % LL_PROCESS_HIST_MAX
;
1350 cur
= sbi
->ll_extent_process_count
;
1351 io_extents
->pp_extents
[cur
].pid
= pid
;
1352 lprocfs_oh_clear(&io_extents
->pp_extents
[cur
].pp_r_hist
);
1353 lprocfs_oh_clear(&io_extents
->pp_extents
[cur
].pp_w_hist
);
1356 for(i
= 0; (count
>= (1 << LL_HIST_START
<< i
)) &&
1357 (i
< (LL_HIST_MAX
- 1)); i
++);
1359 io_extents
->pp_extents
[cur
].pp_r_hist
.oh_buckets
[i
]++;
1360 io_extents
->pp_extents
[LL_PROCESS_HIST_MAX
].pp_r_hist
.oh_buckets
[i
]++;
1362 io_extents
->pp_extents
[cur
].pp_w_hist
.oh_buckets
[i
]++;
1363 io_extents
->pp_extents
[LL_PROCESS_HIST_MAX
].pp_w_hist
.oh_buckets
[i
]++;
1365 spin_unlock(&sbi
->ll_pp_extent_lock
);
1367 spin_lock(&sbi
->ll_process_lock
);
1368 /* Offset statistics */
1369 for (i
= 0; i
< LL_PROCESS_HIST_MAX
; i
++) {
1370 if (process
[i
].rw_pid
== pid
) {
1371 if (process
[i
].rw_last_file
!= file
) {
1372 process
[i
].rw_range_start
= pos
;
1373 process
[i
].rw_last_file_pos
= pos
+ count
;
1374 process
[i
].rw_smallest_extent
= count
;
1375 process
[i
].rw_largest_extent
= count
;
1376 process
[i
].rw_offset
= 0;
1377 process
[i
].rw_last_file
= file
;
1378 spin_unlock(&sbi
->ll_process_lock
);
1381 if (process
[i
].rw_last_file_pos
!= pos
) {
1383 (*off_count
+ 1) % LL_OFFSET_HIST_MAX
;
1384 offset
[*off_count
].rw_op
= process
[i
].rw_op
;
1385 offset
[*off_count
].rw_pid
= pid
;
1386 offset
[*off_count
].rw_range_start
=
1387 process
[i
].rw_range_start
;
1388 offset
[*off_count
].rw_range_end
=
1389 process
[i
].rw_last_file_pos
;
1390 offset
[*off_count
].rw_smallest_extent
=
1391 process
[i
].rw_smallest_extent
;
1392 offset
[*off_count
].rw_largest_extent
=
1393 process
[i
].rw_largest_extent
;
1394 offset
[*off_count
].rw_offset
=
1395 process
[i
].rw_offset
;
1396 process
[i
].rw_op
= rw
;
1397 process
[i
].rw_range_start
= pos
;
1398 process
[i
].rw_smallest_extent
= count
;
1399 process
[i
].rw_largest_extent
= count
;
1400 process
[i
].rw_offset
= pos
-
1401 process
[i
].rw_last_file_pos
;
1403 if (process
[i
].rw_smallest_extent
> count
)
1404 process
[i
].rw_smallest_extent
= count
;
1405 if (process
[i
].rw_largest_extent
< count
)
1406 process
[i
].rw_largest_extent
= count
;
1407 process
[i
].rw_last_file_pos
= pos
+ count
;
1408 spin_unlock(&sbi
->ll_process_lock
);
1412 *process_count
= (*process_count
+ 1) % LL_PROCESS_HIST_MAX
;
1413 process
[*process_count
].rw_pid
= pid
;
1414 process
[*process_count
].rw_op
= rw
;
1415 process
[*process_count
].rw_range_start
= pos
;
1416 process
[*process_count
].rw_last_file_pos
= pos
+ count
;
1417 process
[*process_count
].rw_smallest_extent
= count
;
1418 process
[*process_count
].rw_largest_extent
= count
;
1419 process
[*process_count
].rw_offset
= 0;
1420 process
[*process_count
].rw_last_file
= file
;
1421 spin_unlock(&sbi
->ll_process_lock
);
1424 static int ll_rw_offset_stats_seq_show(struct seq_file
*seq
, void *v
)
1427 struct ll_sb_info
*sbi
= seq
->private;
1428 struct ll_rw_process_info
*offset
= sbi
->ll_rw_offset_info
;
1429 struct ll_rw_process_info
*process
= sbi
->ll_rw_process_info
;
1432 do_gettimeofday(&now
);
1434 if (!sbi
->ll_rw_stats_on
) {
1435 seq_printf(seq
, "disabled\n"
1436 "write anything in this file to activate, then 0 or \"[D/d]isabled\" to deactivate\n");
1439 spin_lock(&sbi
->ll_process_lock
);
1441 seq_printf(seq
, "snapshot_time: %lu.%lu (secs.usecs)\n",
1442 now
.tv_sec
, (unsigned long)now
.tv_usec
);
1443 seq_printf(seq
, "%3s %10s %14s %14s %17s %17s %14s\n",
1444 "R/W", "PID", "RANGE START", "RANGE END",
1445 "SMALLEST EXTENT", "LARGEST EXTENT", "OFFSET");
1446 /* We stored the discontiguous offsets here; print them first */
1447 for (i
= 0; i
< LL_OFFSET_HIST_MAX
; i
++) {
1448 if (offset
[i
].rw_pid
!= 0)
1450 "%3c %10d %14Lu %14Lu %17lu %17lu %14Lu",
1451 offset
[i
].rw_op
== READ
? 'R' : 'W',
1453 offset
[i
].rw_range_start
,
1454 offset
[i
].rw_range_end
,
1455 (unsigned long)offset
[i
].rw_smallest_extent
,
1456 (unsigned long)offset
[i
].rw_largest_extent
,
1457 offset
[i
].rw_offset
);
1459 /* Then print the current offsets for each process */
1460 for (i
= 0; i
< LL_PROCESS_HIST_MAX
; i
++) {
1461 if (process
[i
].rw_pid
!= 0)
1463 "%3c %10d %14Lu %14Lu %17lu %17lu %14Lu",
1464 process
[i
].rw_op
== READ
? 'R' : 'W',
1466 process
[i
].rw_range_start
,
1467 process
[i
].rw_last_file_pos
,
1468 (unsigned long)process
[i
].rw_smallest_extent
,
1469 (unsigned long)process
[i
].rw_largest_extent
,
1470 process
[i
].rw_offset
);
1472 spin_unlock(&sbi
->ll_process_lock
);
1477 static ssize_t
ll_rw_offset_stats_seq_write(struct file
*file
,
1478 const char __user
*buf
,
1479 size_t len
, loff_t
*off
)
1481 struct seq_file
*seq
= file
->private_data
;
1482 struct ll_sb_info
*sbi
= seq
->private;
1483 struct ll_rw_process_info
*process_info
= sbi
->ll_rw_process_info
;
1484 struct ll_rw_process_info
*offset_info
= sbi
->ll_rw_offset_info
;
1485 int value
= 1, rc
= 0;
1490 rc
= lprocfs_write_helper(buf
, len
, &value
);
1492 if (rc
< 0 && len
< 16) {
1495 if (copy_from_user(kernbuf
, buf
, len
))
1499 if (kernbuf
[len
- 1] == '\n')
1500 kernbuf
[len
- 1] = 0;
1502 if (strcmp(kernbuf
, "disabled") == 0 ||
1503 strcmp(kernbuf
, "Disabled") == 0)
1508 sbi
->ll_rw_stats_on
= 0;
1510 sbi
->ll_rw_stats_on
= 1;
1512 spin_lock(&sbi
->ll_process_lock
);
1513 sbi
->ll_offset_process_count
= 0;
1514 sbi
->ll_rw_offset_entry_count
= 0;
1515 memset(process_info
, 0, sizeof(struct ll_rw_process_info
) *
1516 LL_PROCESS_HIST_MAX
);
1517 memset(offset_info
, 0, sizeof(struct ll_rw_process_info
) *
1518 LL_OFFSET_HIST_MAX
);
1519 spin_unlock(&sbi
->ll_process_lock
);
1524 LPROC_SEQ_FOPS(ll_rw_offset_stats
);
1526 void lprocfs_llite_init_vars(struct lprocfs_static_vars
*lvars
)
1528 lvars
->module_vars
= NULL
;
1529 lvars
->obd_vars
= lprocfs_llite_obd_vars
;