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 return seq_printf(m
, "%s\n", sb
->s_type
->name
);
192 LPROC_SEQ_FOPS_RO(ll_fstype
);
194 static int ll_sb_uuid_seq_show(struct seq_file
*m
, void *v
)
196 struct super_block
*sb
= (struct super_block
*)m
->private;
199 return seq_printf(m
, "%s\n", ll_s2sbi(sb
)->ll_sb_uuid
.uuid
);
201 LPROC_SEQ_FOPS_RO(ll_sb_uuid
);
203 static int ll_site_stats_seq_show(struct seq_file
*m
, void *v
)
205 struct super_block
*sb
= m
->private;
208 * See description of statistical counters in struct cl_site, and
211 return cl_site_stats_print(lu2cl_site(ll_s2sbi(sb
)->ll_site
), m
);
213 LPROC_SEQ_FOPS_RO(ll_site_stats
);
215 static int ll_max_readahead_mb_seq_show(struct seq_file
*m
, void *v
)
217 struct super_block
*sb
= m
->private;
218 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
222 spin_lock(&sbi
->ll_lock
);
223 pages_number
= sbi
->ll_ra_info
.ra_max_pages
;
224 spin_unlock(&sbi
->ll_lock
);
226 mult
= 1 << (20 - PAGE_CACHE_SHIFT
);
227 return lprocfs_seq_read_frac_helper(m
, pages_number
, mult
);
230 static ssize_t
ll_max_readahead_mb_seq_write(struct file
*file
,
231 const char __user
*buffer
,
232 size_t count
, loff_t
*off
)
234 struct super_block
*sb
= ((struct seq_file
*)file
->private_data
)->private;
235 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
236 int mult
, rc
, pages_number
;
238 mult
= 1 << (20 - PAGE_CACHE_SHIFT
);
239 rc
= lprocfs_write_frac_helper(buffer
, count
, &pages_number
, mult
);
243 if (pages_number
< 0 || pages_number
> totalram_pages
/ 2) {
244 CERROR("can't set file readahead more than %lu MB\n",
245 totalram_pages
>> (20 - PAGE_CACHE_SHIFT
+ 1)); /*1/2 of RAM*/
249 spin_lock(&sbi
->ll_lock
);
250 sbi
->ll_ra_info
.ra_max_pages
= pages_number
;
251 spin_unlock(&sbi
->ll_lock
);
255 LPROC_SEQ_FOPS(ll_max_readahead_mb
);
257 static int ll_max_readahead_per_file_mb_seq_show(struct seq_file
*m
, void *v
)
259 struct super_block
*sb
= m
->private;
260 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
264 spin_lock(&sbi
->ll_lock
);
265 pages_number
= sbi
->ll_ra_info
.ra_max_pages_per_file
;
266 spin_unlock(&sbi
->ll_lock
);
268 mult
= 1 << (20 - PAGE_CACHE_SHIFT
);
269 return lprocfs_seq_read_frac_helper(m
, pages_number
, mult
);
272 static ssize_t
ll_max_readahead_per_file_mb_seq_write(struct file
*file
,
273 const char __user
*buffer
,
274 size_t count
, loff_t
*off
)
276 struct super_block
*sb
= ((struct seq_file
*)file
->private_data
)->private;
277 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
278 int mult
, rc
, pages_number
;
280 mult
= 1 << (20 - PAGE_CACHE_SHIFT
);
281 rc
= lprocfs_write_frac_helper(buffer
, count
, &pages_number
, mult
);
285 if (pages_number
< 0 ||
286 pages_number
> sbi
->ll_ra_info
.ra_max_pages
) {
287 CERROR("can't set file readahead more than max_read_ahead_mb %lu MB\n",
288 sbi
->ll_ra_info
.ra_max_pages
);
292 spin_lock(&sbi
->ll_lock
);
293 sbi
->ll_ra_info
.ra_max_pages_per_file
= pages_number
;
294 spin_unlock(&sbi
->ll_lock
);
298 LPROC_SEQ_FOPS(ll_max_readahead_per_file_mb
);
300 static int ll_max_read_ahead_whole_mb_seq_show(struct seq_file
*m
, void *unused
)
302 struct super_block
*sb
= m
->private;
303 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
307 spin_lock(&sbi
->ll_lock
);
308 pages_number
= sbi
->ll_ra_info
.ra_max_read_ahead_whole_pages
;
309 spin_unlock(&sbi
->ll_lock
);
311 mult
= 1 << (20 - PAGE_CACHE_SHIFT
);
312 return lprocfs_seq_read_frac_helper(m
, pages_number
, mult
);
315 static ssize_t
ll_max_read_ahead_whole_mb_seq_write(struct file
*file
,
316 const char __user
*buffer
,
317 size_t count
, loff_t
*off
)
319 struct super_block
*sb
= ((struct seq_file
*)file
->private_data
)->private;
320 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
321 int mult
, rc
, pages_number
;
323 mult
= 1 << (20 - PAGE_CACHE_SHIFT
);
324 rc
= lprocfs_write_frac_helper(buffer
, count
, &pages_number
, mult
);
328 /* Cap this at the current max readahead window size, the readahead
329 * algorithm does this anyway so it's pointless to set it larger. */
330 if (pages_number
< 0 ||
331 pages_number
> sbi
->ll_ra_info
.ra_max_pages_per_file
) {
332 CERROR("can't set max_read_ahead_whole_mb more than max_read_ahead_per_file_mb: %lu\n",
333 sbi
->ll_ra_info
.ra_max_pages_per_file
>> (20 - PAGE_CACHE_SHIFT
));
337 spin_lock(&sbi
->ll_lock
);
338 sbi
->ll_ra_info
.ra_max_read_ahead_whole_pages
= pages_number
;
339 spin_unlock(&sbi
->ll_lock
);
343 LPROC_SEQ_FOPS(ll_max_read_ahead_whole_mb
);
345 static int ll_max_cached_mb_seq_show(struct seq_file
*m
, void *v
)
347 struct super_block
*sb
= m
->private;
348 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
349 struct cl_client_cache
*cache
= &sbi
->ll_cache
;
350 int shift
= 20 - PAGE_CACHE_SHIFT
;
354 max_cached_mb
= cache
->ccc_lru_max
>> shift
;
355 unused_mb
= atomic_read(&cache
->ccc_lru_left
) >> shift
;
358 "max_cached_mb: %d\n"
361 "reclaim_count: %u\n",
362 atomic_read(&cache
->ccc_users
),
364 max_cached_mb
- unused_mb
,
366 cache
->ccc_lru_shrinkers
);
369 static ssize_t
ll_max_cached_mb_seq_write(struct file
*file
,
370 const char __user
*buffer
,
371 size_t count
, loff_t
*off
)
373 struct super_block
*sb
= ((struct seq_file
*)file
->private_data
)->private;
374 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
375 struct cl_client_cache
*cache
= &sbi
->ll_cache
;
376 int mult
, rc
, pages_number
;
381 if (count
>= sizeof(kernbuf
))
384 if (copy_from_user(kernbuf
, buffer
, count
))
388 mult
= 1 << (20 - PAGE_CACHE_SHIFT
);
389 buffer
+= lprocfs_find_named_value(kernbuf
, "max_cached_mb:", &count
) -
391 rc
= lprocfs_write_frac_helper(buffer
, count
, &pages_number
, mult
);
395 if (pages_number
< 0 || pages_number
> totalram_pages
) {
396 CERROR("%s: can't set max cache more than %lu MB\n",
397 ll_get_fsname(sb
, NULL
, 0),
398 totalram_pages
>> (20 - PAGE_CACHE_SHIFT
));
402 if (sbi
->ll_dt_exp
== NULL
)
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 /* difficult - have to ask OSCs to drop LRU slots. */
442 rc
= obd_set_info_async(NULL
, sbi
->ll_dt_exp
,
443 sizeof(KEY_CACHE_LRU_SHRINK
),
444 KEY_CACHE_LRU_SHRINK
,
445 sizeof(tmp
), &tmp
, NULL
);
452 spin_lock(&sbi
->ll_lock
);
453 cache
->ccc_lru_max
= pages_number
;
454 spin_unlock(&sbi
->ll_lock
);
457 atomic_add(nrpages
, &cache
->ccc_lru_left
);
461 LPROC_SEQ_FOPS(ll_max_cached_mb
);
463 static int ll_checksum_seq_show(struct seq_file
*m
, void *v
)
465 struct super_block
*sb
= m
->private;
466 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
468 return seq_printf(m
, "%u\n", (sbi
->ll_flags
& LL_SBI_CHECKSUM
) ? 1 : 0);
471 static ssize_t
ll_checksum_seq_write(struct file
*file
,
472 const char __user
*buffer
,
473 size_t count
, loff_t
*off
)
475 struct super_block
*sb
= ((struct seq_file
*)file
->private_data
)->private;
476 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
483 rc
= lprocfs_write_helper(buffer
, count
, &val
);
487 sbi
->ll_flags
|= LL_SBI_CHECKSUM
;
489 sbi
->ll_flags
&= ~LL_SBI_CHECKSUM
;
491 rc
= obd_set_info_async(NULL
, sbi
->ll_dt_exp
, sizeof(KEY_CHECKSUM
),
492 KEY_CHECKSUM
, sizeof(val
), &val
, NULL
);
494 CWARN("Failed to set OSC checksum flags: %d\n", rc
);
498 LPROC_SEQ_FOPS(ll_checksum
);
500 static int ll_max_rw_chunk_seq_show(struct seq_file
*m
, void *v
)
502 struct super_block
*sb
= m
->private;
504 return seq_printf(m
, "%lu\n", ll_s2sbi(sb
)->ll_max_rw_chunk
);
507 static ssize_t
ll_max_rw_chunk_seq_write(struct file
*file
,
508 const char __user
*buffer
,
509 size_t count
, loff_t
*off
)
511 struct super_block
*sb
= ((struct seq_file
*)file
->private_data
)->private;
514 rc
= lprocfs_write_helper(buffer
, count
, &val
);
517 ll_s2sbi(sb
)->ll_max_rw_chunk
= val
;
520 LPROC_SEQ_FOPS(ll_max_rw_chunk
);
522 static int ll_rd_track_id(struct seq_file
*m
, enum stats_track_type type
)
524 struct super_block
*sb
= m
->private;
526 if (ll_s2sbi(sb
)->ll_stats_track_type
== type
) {
527 return seq_printf(m
, "%d\n",
528 ll_s2sbi(sb
)->ll_stats_track_id
);
530 } else if (ll_s2sbi(sb
)->ll_stats_track_type
== STATS_TRACK_ALL
) {
531 return seq_printf(m
, "0 (all)\n");
533 return seq_printf(m
, "untracked\n");
537 static int ll_wr_track_id(const char __user
*buffer
, unsigned long count
,
538 void *data
, enum stats_track_type type
)
540 struct super_block
*sb
= data
;
543 rc
= lprocfs_write_helper(buffer
, count
, &pid
);
546 ll_s2sbi(sb
)->ll_stats_track_id
= pid
;
548 ll_s2sbi(sb
)->ll_stats_track_type
= STATS_TRACK_ALL
;
550 ll_s2sbi(sb
)->ll_stats_track_type
= type
;
551 lprocfs_clear_stats(ll_s2sbi(sb
)->ll_stats
);
555 static int ll_track_pid_seq_show(struct seq_file
*m
, void *v
)
557 return ll_rd_track_id(m
, STATS_TRACK_PID
);
560 static ssize_t
ll_track_pid_seq_write(struct file
*file
,
561 const char __user
*buffer
,
562 size_t count
, loff_t
*off
)
564 struct seq_file
*seq
= file
->private_data
;
565 return ll_wr_track_id(buffer
, count
, seq
->private, STATS_TRACK_PID
);
567 LPROC_SEQ_FOPS(ll_track_pid
);
569 static int ll_track_ppid_seq_show(struct seq_file
*m
, void *v
)
571 return ll_rd_track_id(m
, STATS_TRACK_PPID
);
574 static ssize_t
ll_track_ppid_seq_write(struct file
*file
,
575 const char __user
*buffer
,
576 size_t count
, loff_t
*off
)
578 struct seq_file
*seq
= file
->private_data
;
579 return ll_wr_track_id(buffer
, count
, seq
->private, STATS_TRACK_PPID
);
581 LPROC_SEQ_FOPS(ll_track_ppid
);
583 static int ll_track_gid_seq_show(struct seq_file
*m
, void *v
)
585 return ll_rd_track_id(m
, STATS_TRACK_GID
);
588 static ssize_t
ll_track_gid_seq_write(struct file
*file
,
589 const char __user
*buffer
,
590 size_t count
, loff_t
*off
)
592 struct seq_file
*seq
= file
->private_data
;
593 return ll_wr_track_id(buffer
, count
, seq
->private, STATS_TRACK_GID
);
595 LPROC_SEQ_FOPS(ll_track_gid
);
597 static int ll_statahead_max_seq_show(struct seq_file
*m
, void *v
)
599 struct super_block
*sb
= m
->private;
600 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
602 return seq_printf(m
, "%u\n", sbi
->ll_sa_max
);
605 static ssize_t
ll_statahead_max_seq_write(struct file
*file
,
606 const char __user
*buffer
,
607 size_t count
, loff_t
*off
)
609 struct super_block
*sb
= ((struct seq_file
*)file
->private_data
)->private;
610 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
613 rc
= lprocfs_write_helper(buffer
, count
, &val
);
617 if (val
>= 0 && val
<= LL_SA_RPC_MAX
)
618 sbi
->ll_sa_max
= val
;
620 CERROR("Bad statahead_max value %d. Valid values are in the range [0, %d]\n",
625 LPROC_SEQ_FOPS(ll_statahead_max
);
627 static int ll_statahead_agl_seq_show(struct seq_file
*m
, void *v
)
629 struct super_block
*sb
= m
->private;
630 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
632 return seq_printf(m
, "%u\n",
633 sbi
->ll_flags
& LL_SBI_AGL_ENABLED
? 1 : 0);
636 static ssize_t
ll_statahead_agl_seq_write(struct file
*file
,
637 const char __user
*buffer
,
638 size_t count
, loff_t
*off
)
640 struct super_block
*sb
= ((struct seq_file
*)file
->private_data
)->private;
641 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
644 rc
= lprocfs_write_helper(buffer
, count
, &val
);
649 sbi
->ll_flags
|= LL_SBI_AGL_ENABLED
;
651 sbi
->ll_flags
&= ~LL_SBI_AGL_ENABLED
;
655 LPROC_SEQ_FOPS(ll_statahead_agl
);
657 static int ll_statahead_stats_seq_show(struct seq_file
*m
, void *v
)
659 struct super_block
*sb
= m
->private;
660 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
663 "statahead total: %u\n"
664 "statahead wrong: %u\n"
666 atomic_read(&sbi
->ll_sa_total
),
667 atomic_read(&sbi
->ll_sa_wrong
),
668 atomic_read(&sbi
->ll_agl_total
));
670 LPROC_SEQ_FOPS_RO(ll_statahead_stats
);
672 static int ll_lazystatfs_seq_show(struct seq_file
*m
, void *v
)
674 struct super_block
*sb
= m
->private;
675 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
677 return seq_printf(m
, "%u\n",
678 (sbi
->ll_flags
& LL_SBI_LAZYSTATFS
) ? 1 : 0);
681 static ssize_t
ll_lazystatfs_seq_write(struct file
*file
,
682 const char __user
*buffer
,
683 size_t count
, loff_t
*off
)
685 struct super_block
*sb
= ((struct seq_file
*)file
->private_data
)->private;
686 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
689 rc
= lprocfs_write_helper(buffer
, count
, &val
);
694 sbi
->ll_flags
|= LL_SBI_LAZYSTATFS
;
696 sbi
->ll_flags
&= ~LL_SBI_LAZYSTATFS
;
700 LPROC_SEQ_FOPS(ll_lazystatfs
);
702 static int ll_max_easize_seq_show(struct seq_file
*m
, void *v
)
704 struct super_block
*sb
= m
->private;
705 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
709 rc
= ll_get_max_mdsize(sbi
, &ealen
);
713 return seq_printf(m
, "%u\n", ealen
);
715 LPROC_SEQ_FOPS_RO(ll_max_easize
);
717 static int ll_defult_easize_seq_show(struct seq_file
*m
, void *v
)
719 struct super_block
*sb
= m
->private;
720 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
724 rc
= ll_get_default_mdsize(sbi
, &ealen
);
728 return seq_printf(m
, "%u\n", ealen
);
730 LPROC_SEQ_FOPS_RO(ll_defult_easize
);
732 static int ll_max_cookiesize_seq_show(struct seq_file
*m
, void *v
)
734 struct super_block
*sb
= m
->private;
735 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
736 unsigned int cookielen
;
739 rc
= ll_get_max_cookiesize(sbi
, &cookielen
);
743 return seq_printf(m
, "%u\n", cookielen
);
745 LPROC_SEQ_FOPS_RO(ll_max_cookiesize
);
747 static int ll_defult_cookiesize_seq_show(struct seq_file
*m
, void *v
)
749 struct super_block
*sb
= m
->private;
750 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
751 unsigned int cookielen
;
754 rc
= ll_get_default_cookiesize(sbi
, &cookielen
);
758 return seq_printf(m
, "%u\n", cookielen
);
760 LPROC_SEQ_FOPS_RO(ll_defult_cookiesize
);
762 static int ll_sbi_flags_seq_show(struct seq_file
*m
, void *v
)
764 const char *str
[] = LL_SBI_FLAGS
;
765 struct super_block
*sb
= m
->private;
766 int flags
= ll_s2sbi(sb
)->ll_flags
;
770 if (ARRAY_SIZE(str
) <= i
) {
771 CERROR("%s: Revise array LL_SBI_FLAGS to match sbi flags please.\n",
772 ll_get_fsname(sb
, NULL
, 0));
777 seq_printf(m
, "%s ", str
[i
]);
781 seq_printf(m
, "\b\n");
784 LPROC_SEQ_FOPS_RO(ll_sbi_flags
);
786 static int ll_xattr_cache_seq_show(struct seq_file
*m
, void *v
)
788 struct super_block
*sb
= m
->private;
789 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
792 rc
= seq_printf(m
, "%u\n", sbi
->ll_xattr_cache_enabled
);
797 static ssize_t
ll_xattr_cache_seq_write(struct file
*file
,
798 const char __user
*buffer
,
799 size_t count
, loff_t
*off
)
801 struct seq_file
*seq
= file
->private_data
;
802 struct super_block
*sb
= seq
->private;
803 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
806 rc
= lprocfs_write_helper(buffer
, count
, &val
);
810 if (val
!= 0 && val
!= 1)
813 if (val
== 1 && !(sbi
->ll_flags
& LL_SBI_XATTR_CACHE
))
816 sbi
->ll_xattr_cache_enabled
= val
;
820 LPROC_SEQ_FOPS(ll_xattr_cache
);
822 static struct lprocfs_vars lprocfs_llite_obd_vars
[] = {
823 { "uuid", &ll_sb_uuid_fops
, NULL
, 0 },
824 /* { "mntpt_path", ll_rd_path, 0, 0 }, */
825 { "fstype", &ll_fstype_fops
, NULL
, 0 },
826 { "site", &ll_site_stats_fops
, NULL
, 0 },
827 { "blocksize", &ll_blksize_fops
, NULL
, 0 },
828 { "kbytestotal", &ll_kbytestotal_fops
, NULL
, 0 },
829 { "kbytesfree", &ll_kbytesfree_fops
, NULL
, 0 },
830 { "kbytesavail", &ll_kbytesavail_fops
, NULL
, 0 },
831 { "filestotal", &ll_filestotal_fops
, NULL
, 0 },
832 { "filesfree", &ll_filesfree_fops
, NULL
, 0 },
833 { "client_type", &ll_client_type_fops
, NULL
, 0 },
834 /* { "filegroups", lprocfs_rd_filegroups, 0, 0 }, */
835 { "max_read_ahead_mb", &ll_max_readahead_mb_fops
, NULL
},
836 { "max_read_ahead_per_file_mb", &ll_max_readahead_per_file_mb_fops
,
838 { "max_read_ahead_whole_mb", &ll_max_read_ahead_whole_mb_fops
, NULL
},
839 { "max_cached_mb", &ll_max_cached_mb_fops
, NULL
},
840 { "checksum_pages", &ll_checksum_fops
, NULL
},
841 { "max_rw_chunk", &ll_max_rw_chunk_fops
, NULL
},
842 { "stats_track_pid", &ll_track_pid_fops
, NULL
},
843 { "stats_track_ppid", &ll_track_ppid_fops
, NULL
},
844 { "stats_track_gid", &ll_track_gid_fops
, NULL
},
845 { "statahead_max", &ll_statahead_max_fops
, NULL
},
846 { "statahead_agl", &ll_statahead_agl_fops
, NULL
},
847 { "statahead_stats", &ll_statahead_stats_fops
, NULL
, 0 },
848 { "lazystatfs", &ll_lazystatfs_fops
, NULL
},
849 { "max_easize", &ll_max_easize_fops
, NULL
, 0 },
850 { "default_easize", &ll_defult_easize_fops
, NULL
, 0 },
851 { "max_cookiesize", &ll_max_cookiesize_fops
, NULL
, 0 },
852 { "default_cookiesize", &ll_defult_cookiesize_fops
, NULL
, 0 },
853 { "sbi_flags", &ll_sbi_flags_fops
, NULL
, 0 },
854 { "xattr_cache", &ll_xattr_cache_fops
, NULL
, 0 },
858 #define MAX_STRING_SIZE 128
860 static const struct llite_file_opcode
{
864 } llite_opcode_table
[LPROC_LL_FILE_OPCODES
] = {
866 { LPROC_LL_DIRTY_HITS
, LPROCFS_TYPE_REGS
, "dirty_pages_hits" },
867 { LPROC_LL_DIRTY_MISSES
, LPROCFS_TYPE_REGS
, "dirty_pages_misses" },
868 { LPROC_LL_READ_BYTES
, LPROCFS_CNTR_AVGMINMAX
|LPROCFS_TYPE_BYTES
,
870 { LPROC_LL_WRITE_BYTES
, LPROCFS_CNTR_AVGMINMAX
|LPROCFS_TYPE_BYTES
,
872 { LPROC_LL_BRW_READ
, LPROCFS_CNTR_AVGMINMAX
|LPROCFS_TYPE_PAGES
,
874 { LPROC_LL_BRW_WRITE
, LPROCFS_CNTR_AVGMINMAX
|LPROCFS_TYPE_PAGES
,
876 { LPROC_LL_OSC_READ
, LPROCFS_CNTR_AVGMINMAX
|LPROCFS_TYPE_BYTES
,
878 { LPROC_LL_OSC_WRITE
, LPROCFS_CNTR_AVGMINMAX
|LPROCFS_TYPE_BYTES
,
880 { LPROC_LL_IOCTL
, LPROCFS_TYPE_REGS
, "ioctl" },
881 { LPROC_LL_OPEN
, LPROCFS_TYPE_REGS
, "open" },
882 { LPROC_LL_RELEASE
, LPROCFS_TYPE_REGS
, "close" },
883 { LPROC_LL_MAP
, LPROCFS_TYPE_REGS
, "mmap" },
884 { LPROC_LL_LLSEEK
, LPROCFS_TYPE_REGS
, "seek" },
885 { LPROC_LL_FSYNC
, LPROCFS_TYPE_REGS
, "fsync" },
886 { LPROC_LL_READDIR
, LPROCFS_TYPE_REGS
, "readdir" },
887 /* inode operation */
888 { LPROC_LL_SETATTR
, LPROCFS_TYPE_REGS
, "setattr" },
889 { LPROC_LL_TRUNC
, LPROCFS_TYPE_REGS
, "truncate" },
890 { LPROC_LL_FLOCK
, LPROCFS_TYPE_REGS
, "flock" },
891 { LPROC_LL_GETATTR
, LPROCFS_TYPE_REGS
, "getattr" },
892 /* dir inode operation */
893 { LPROC_LL_CREATE
, LPROCFS_TYPE_REGS
, "create" },
894 { LPROC_LL_LINK
, LPROCFS_TYPE_REGS
, "link" },
895 { LPROC_LL_UNLINK
, LPROCFS_TYPE_REGS
, "unlink" },
896 { LPROC_LL_SYMLINK
, LPROCFS_TYPE_REGS
, "symlink" },
897 { LPROC_LL_MKDIR
, LPROCFS_TYPE_REGS
, "mkdir" },
898 { LPROC_LL_RMDIR
, LPROCFS_TYPE_REGS
, "rmdir" },
899 { LPROC_LL_MKNOD
, LPROCFS_TYPE_REGS
, "mknod" },
900 { LPROC_LL_RENAME
, LPROCFS_TYPE_REGS
, "rename" },
901 /* special inode operation */
902 { LPROC_LL_STAFS
, LPROCFS_TYPE_REGS
, "statfs" },
903 { LPROC_LL_ALLOC_INODE
, LPROCFS_TYPE_REGS
, "alloc_inode" },
904 { LPROC_LL_SETXATTR
, LPROCFS_TYPE_REGS
, "setxattr" },
905 { LPROC_LL_GETXATTR
, LPROCFS_TYPE_REGS
, "getxattr" },
906 { LPROC_LL_GETXATTR_HITS
, LPROCFS_TYPE_REGS
, "getxattr_hits" },
907 { LPROC_LL_LISTXATTR
, LPROCFS_TYPE_REGS
, "listxattr" },
908 { LPROC_LL_REMOVEXATTR
, LPROCFS_TYPE_REGS
, "removexattr" },
909 { LPROC_LL_INODE_PERM
, LPROCFS_TYPE_REGS
, "inode_permission" },
912 void ll_stats_ops_tally(struct ll_sb_info
*sbi
, int op
, int count
)
916 if (sbi
->ll_stats_track_type
== STATS_TRACK_ALL
)
917 lprocfs_counter_add(sbi
->ll_stats
, op
, count
);
918 else if (sbi
->ll_stats_track_type
== STATS_TRACK_PID
&&
919 sbi
->ll_stats_track_id
== current
->pid
)
920 lprocfs_counter_add(sbi
->ll_stats
, op
, count
);
921 else if (sbi
->ll_stats_track_type
== STATS_TRACK_PPID
&&
922 sbi
->ll_stats_track_id
== current
->real_parent
->pid
)
923 lprocfs_counter_add(sbi
->ll_stats
, op
, count
);
924 else if (sbi
->ll_stats_track_type
== STATS_TRACK_GID
&&
925 sbi
->ll_stats_track_id
==
926 from_kgid(&init_user_ns
, current_gid()))
927 lprocfs_counter_add(sbi
->ll_stats
, op
, count
);
929 EXPORT_SYMBOL(ll_stats_ops_tally
);
931 static const char *ra_stat_string
[] = {
932 [RA_STAT_HIT
] = "hits",
933 [RA_STAT_MISS
] = "misses",
934 [RA_STAT_DISTANT_READPAGE
] = "readpage not consecutive",
935 [RA_STAT_MISS_IN_WINDOW
] = "miss inside window",
936 [RA_STAT_FAILED_GRAB_PAGE
] = "failed grab_cache_page",
937 [RA_STAT_FAILED_MATCH
] = "failed lock match",
938 [RA_STAT_DISCARDED
] = "read but discarded",
939 [RA_STAT_ZERO_LEN
] = "zero length file",
940 [RA_STAT_ZERO_WINDOW
] = "zero size window",
941 [RA_STAT_EOF
] = "read-ahead to EOF",
942 [RA_STAT_MAX_IN_FLIGHT
] = "hit max r-a issue",
943 [RA_STAT_WRONG_GRAB_PAGE
] = "wrong page from grab_cache_page",
946 LPROC_SEQ_FOPS_RO_TYPE(llite
, name
);
947 LPROC_SEQ_FOPS_RO_TYPE(llite
, uuid
);
949 int lprocfs_register_mountpoint(struct proc_dir_entry
*parent
,
950 struct super_block
*sb
, char *osc
, char *mdc
)
952 struct lprocfs_vars lvars
[2];
953 struct lustre_sb_info
*lsi
= s2lsi(sb
);
954 struct ll_sb_info
*sbi
= ll_s2sbi(sb
);
955 struct obd_device
*obd
;
956 struct proc_dir_entry
*dir
;
957 char name
[MAX_STRING_SIZE
+ 1], *ptr
;
958 int err
, id
, len
, rc
;
960 memset(lvars
, 0, sizeof(lvars
));
962 name
[MAX_STRING_SIZE
] = '\0';
963 lvars
[0].name
= name
;
965 LASSERT(sbi
!= NULL
);
966 LASSERT(mdc
!= NULL
);
967 LASSERT(osc
!= NULL
);
970 len
= strlen(lsi
->lsi_lmd
->lmd_profile
);
971 ptr
= strrchr(lsi
->lsi_lmd
->lmd_profile
, '-');
972 if (ptr
&& (strcmp(ptr
, "-client") == 0))
976 snprintf(name
, MAX_STRING_SIZE
, "%.*s-%p", len
,
977 lsi
->lsi_lmd
->lmd_profile
, sb
);
979 sbi
->ll_proc_root
= lprocfs_register(name
, parent
, NULL
, NULL
);
980 if (IS_ERR(sbi
->ll_proc_root
)) {
981 err
= PTR_ERR(sbi
->ll_proc_root
);
982 sbi
->ll_proc_root
= NULL
;
986 rc
= lprocfs_seq_create(sbi
->ll_proc_root
, "dump_page_cache", 0444,
987 &vvp_dump_pgcache_file_ops
, sbi
);
989 CWARN("Error adding the dump_page_cache file\n");
991 rc
= lprocfs_seq_create(sbi
->ll_proc_root
, "extents_stats", 0644,
992 &ll_rw_extents_stats_fops
, sbi
);
994 CWARN("Error adding the extent_stats file\n");
996 rc
= lprocfs_seq_create(sbi
->ll_proc_root
, "extents_stats_per_process",
997 0644, &ll_rw_extents_stats_pp_fops
, sbi
);
999 CWARN("Error adding the extents_stats_per_process file\n");
1001 rc
= lprocfs_seq_create(sbi
->ll_proc_root
, "offset_stats", 0644,
1002 &ll_rw_offset_stats_fops
, sbi
);
1004 CWARN("Error adding the offset_stats file\n");
1006 /* File operations stats */
1007 sbi
->ll_stats
= lprocfs_alloc_stats(LPROC_LL_FILE_OPCODES
,
1008 LPROCFS_STATS_FLAG_NONE
);
1009 if (sbi
->ll_stats
== NULL
) {
1013 /* do counter init */
1014 for (id
= 0; id
< LPROC_LL_FILE_OPCODES
; id
++) {
1015 __u32 type
= llite_opcode_table
[id
].type
;
1017 if (type
& LPROCFS_TYPE_REGS
)
1019 else if (type
& LPROCFS_TYPE_BYTES
)
1021 else if (type
& LPROCFS_TYPE_PAGES
)
1023 lprocfs_counter_init(sbi
->ll_stats
,
1024 llite_opcode_table
[id
].opcode
,
1025 (type
& LPROCFS_CNTR_AVGMINMAX
),
1026 llite_opcode_table
[id
].opname
, ptr
);
1028 err
= lprocfs_register_stats(sbi
->ll_proc_root
, "stats", sbi
->ll_stats
);
1032 sbi
->ll_ra_stats
= lprocfs_alloc_stats(ARRAY_SIZE(ra_stat_string
),
1033 LPROCFS_STATS_FLAG_NONE
);
1034 if (sbi
->ll_ra_stats
== NULL
) {
1039 for (id
= 0; id
< ARRAY_SIZE(ra_stat_string
); id
++)
1040 lprocfs_counter_init(sbi
->ll_ra_stats
, id
, 0,
1041 ra_stat_string
[id
], "pages");
1042 err
= lprocfs_register_stats(sbi
->ll_proc_root
, "read_ahead_stats",
1048 err
= lprocfs_add_vars(sbi
->ll_proc_root
, lprocfs_llite_obd_vars
, sb
);
1053 obd
= class_name2obd(mdc
);
1055 LASSERT(obd
!= NULL
);
1056 LASSERT(obd
->obd_magic
== OBD_DEVICE_MAGIC
);
1057 LASSERT(obd
->obd_type
->typ_name
!= NULL
);
1059 dir
= proc_mkdir(obd
->obd_type
->typ_name
, sbi
->ll_proc_root
);
1065 snprintf(name
, MAX_STRING_SIZE
, "common_name");
1066 lvars
[0].fops
= &llite_name_fops
;
1067 err
= lprocfs_add_vars(dir
, lvars
, obd
);
1071 snprintf(name
, MAX_STRING_SIZE
, "uuid");
1072 lvars
[0].fops
= &llite_uuid_fops
;
1073 err
= lprocfs_add_vars(dir
, lvars
, obd
);
1078 obd
= class_name2obd(osc
);
1080 LASSERT(obd
!= NULL
);
1081 LASSERT(obd
->obd_magic
== OBD_DEVICE_MAGIC
);
1082 LASSERT(obd
->obd_type
->typ_name
!= NULL
);
1084 dir
= proc_mkdir(obd
->obd_type
->typ_name
, sbi
->ll_proc_root
);
1090 snprintf(name
, MAX_STRING_SIZE
, "common_name");
1091 lvars
[0].fops
= &llite_name_fops
;
1092 err
= lprocfs_add_vars(dir
, lvars
, obd
);
1096 snprintf(name
, MAX_STRING_SIZE
, "uuid");
1097 lvars
[0].fops
= &llite_uuid_fops
;
1098 err
= lprocfs_add_vars(dir
, lvars
, obd
);
1101 lprocfs_remove(&sbi
->ll_proc_root
);
1102 lprocfs_free_stats(&sbi
->ll_ra_stats
);
1103 lprocfs_free_stats(&sbi
->ll_stats
);
1108 void lprocfs_unregister_mountpoint(struct ll_sb_info
*sbi
)
1110 if (sbi
->ll_proc_root
) {
1111 lprocfs_remove(&sbi
->ll_proc_root
);
1112 lprocfs_free_stats(&sbi
->ll_ra_stats
);
1113 lprocfs_free_stats(&sbi
->ll_stats
);
1116 #undef MAX_STRING_SIZE
1118 #define pct(a, b) (b ? a * 100 / b : 0)
1120 static void ll_display_extents_info(struct ll_rw_extents_info
*io_extents
,
1121 struct seq_file
*seq
, int which
)
1123 unsigned long read_tot
= 0, write_tot
= 0, read_cum
, write_cum
;
1124 unsigned long start
, end
, r
, w
;
1125 char *unitp
= "KMGTPEZY";
1127 struct per_process_info
*pp_info
= &io_extents
->pp_extents
[which
];
1133 for (i
= 0; i
< LL_HIST_MAX
; i
++) {
1134 read_tot
+= pp_info
->pp_r_hist
.oh_buckets
[i
];
1135 write_tot
+= pp_info
->pp_w_hist
.oh_buckets
[i
];
1138 for (i
= 0; i
< LL_HIST_MAX
; i
++) {
1139 r
= pp_info
->pp_r_hist
.oh_buckets
[i
];
1140 w
= pp_info
->pp_w_hist
.oh_buckets
[i
];
1143 end
= 1 << (i
+ LL_HIST_START
- units
);
1144 seq_printf(seq
, "%4lu%c - %4lu%c%c: %14lu %4lu %4lu | %14lu %4lu %4lu\n",
1145 start
, *unitp
, end
, *unitp
,
1146 (i
== LL_HIST_MAX
- 1) ? '+' : ' ',
1147 r
, pct(r
, read_tot
), pct(read_cum
, read_tot
),
1148 w
, pct(w
, write_tot
), pct(write_cum
, write_tot
));
1150 if (start
== 1<<10) {
1155 if (read_cum
== read_tot
&& write_cum
== write_tot
)
1160 static int ll_rw_extents_stats_pp_seq_show(struct seq_file
*seq
, void *v
)
1163 struct ll_sb_info
*sbi
= seq
->private;
1164 struct ll_rw_extents_info
*io_extents
= &sbi
->ll_rw_extents_info
;
1167 do_gettimeofday(&now
);
1169 if (!sbi
->ll_rw_stats_on
) {
1170 seq_printf(seq
, "disabled\n"
1171 "write anything in this file to activate, then 0 or \"[D/d]isabled\" to deactivate\n");
1174 seq_printf(seq
, "snapshot_time: %lu.%lu (secs.usecs)\n",
1175 now
.tv_sec
, (unsigned long)now
.tv_usec
);
1176 seq_printf(seq
, "%15s %19s | %20s\n", " ", "read", "write");
1177 seq_printf(seq
, "%13s %14s %4s %4s | %14s %4s %4s\n",
1178 "extents", "calls", "%", "cum%",
1179 "calls", "%", "cum%");
1180 spin_lock(&sbi
->ll_pp_extent_lock
);
1181 for (k
= 0; k
< LL_PROCESS_HIST_MAX
; k
++) {
1182 if (io_extents
->pp_extents
[k
].pid
!= 0) {
1183 seq_printf(seq
, "\nPID: %d\n",
1184 io_extents
->pp_extents
[k
].pid
);
1185 ll_display_extents_info(io_extents
, seq
, k
);
1188 spin_unlock(&sbi
->ll_pp_extent_lock
);
1192 static ssize_t
ll_rw_extents_stats_pp_seq_write(struct file
*file
,
1193 const char __user
*buf
,
1197 struct seq_file
*seq
= file
->private_data
;
1198 struct ll_sb_info
*sbi
= seq
->private;
1199 struct ll_rw_extents_info
*io_extents
= &sbi
->ll_rw_extents_info
;
1201 int value
= 1, rc
= 0;
1206 rc
= lprocfs_write_helper(buf
, len
, &value
);
1207 if (rc
< 0 && len
< 16) {
1210 if (copy_from_user(kernbuf
, buf
, len
))
1214 if (kernbuf
[len
- 1] == '\n')
1215 kernbuf
[len
- 1] = 0;
1217 if (strcmp(kernbuf
, "disabled") == 0 ||
1218 strcmp(kernbuf
, "Disabled") == 0)
1223 sbi
->ll_rw_stats_on
= 0;
1225 sbi
->ll_rw_stats_on
= 1;
1227 spin_lock(&sbi
->ll_pp_extent_lock
);
1228 for (i
= 0; i
< LL_PROCESS_HIST_MAX
; i
++) {
1229 io_extents
->pp_extents
[i
].pid
= 0;
1230 lprocfs_oh_clear(&io_extents
->pp_extents
[i
].pp_r_hist
);
1231 lprocfs_oh_clear(&io_extents
->pp_extents
[i
].pp_w_hist
);
1233 spin_unlock(&sbi
->ll_pp_extent_lock
);
1237 LPROC_SEQ_FOPS(ll_rw_extents_stats_pp
);
1239 static int ll_rw_extents_stats_seq_show(struct seq_file
*seq
, void *v
)
1242 struct ll_sb_info
*sbi
= seq
->private;
1243 struct ll_rw_extents_info
*io_extents
= &sbi
->ll_rw_extents_info
;
1245 do_gettimeofday(&now
);
1247 if (!sbi
->ll_rw_stats_on
) {
1248 seq_printf(seq
, "disabled\n"
1249 "write anything in this file to activate, then 0 or \"[D/d]isabled\" to deactivate\n");
1252 seq_printf(seq
, "snapshot_time: %lu.%lu (secs.usecs)\n",
1253 now
.tv_sec
, (unsigned long)now
.tv_usec
);
1255 seq_printf(seq
, "%15s %19s | %20s\n", " ", "read", "write");
1256 seq_printf(seq
, "%13s %14s %4s %4s | %14s %4s %4s\n",
1257 "extents", "calls", "%", "cum%",
1258 "calls", "%", "cum%");
1259 spin_lock(&sbi
->ll_lock
);
1260 ll_display_extents_info(io_extents
, seq
, LL_PROCESS_HIST_MAX
);
1261 spin_unlock(&sbi
->ll_lock
);
1266 static ssize_t
ll_rw_extents_stats_seq_write(struct file
*file
,
1267 const char __user
*buf
,
1268 size_t len
, loff_t
*off
)
1270 struct seq_file
*seq
= file
->private_data
;
1271 struct ll_sb_info
*sbi
= seq
->private;
1272 struct ll_rw_extents_info
*io_extents
= &sbi
->ll_rw_extents_info
;
1274 int value
= 1, rc
= 0;
1279 rc
= lprocfs_write_helper(buf
, len
, &value
);
1280 if (rc
< 0 && len
< 16) {
1283 if (copy_from_user(kernbuf
, buf
, len
))
1287 if (kernbuf
[len
- 1] == '\n')
1288 kernbuf
[len
- 1] = 0;
1290 if (strcmp(kernbuf
, "disabled") == 0 ||
1291 strcmp(kernbuf
, "Disabled") == 0)
1296 sbi
->ll_rw_stats_on
= 0;
1298 sbi
->ll_rw_stats_on
= 1;
1300 spin_lock(&sbi
->ll_pp_extent_lock
);
1301 for (i
= 0; i
<= LL_PROCESS_HIST_MAX
; i
++) {
1302 io_extents
->pp_extents
[i
].pid
= 0;
1303 lprocfs_oh_clear(&io_extents
->pp_extents
[i
].pp_r_hist
);
1304 lprocfs_oh_clear(&io_extents
->pp_extents
[i
].pp_w_hist
);
1306 spin_unlock(&sbi
->ll_pp_extent_lock
);
1310 LPROC_SEQ_FOPS(ll_rw_extents_stats
);
1312 void ll_rw_stats_tally(struct ll_sb_info
*sbi
, pid_t pid
,
1313 struct ll_file_data
*file
, loff_t pos
,
1314 size_t count
, int rw
)
1317 struct ll_rw_process_info
*process
;
1318 struct ll_rw_process_info
*offset
;
1319 int *off_count
= &sbi
->ll_rw_offset_entry_count
;
1320 int *process_count
= &sbi
->ll_offset_process_count
;
1321 struct ll_rw_extents_info
*io_extents
= &sbi
->ll_rw_extents_info
;
1323 if (!sbi
->ll_rw_stats_on
)
1325 process
= sbi
->ll_rw_process_info
;
1326 offset
= sbi
->ll_rw_offset_info
;
1328 spin_lock(&sbi
->ll_pp_extent_lock
);
1329 /* Extent statistics */
1330 for (i
= 0; i
< LL_PROCESS_HIST_MAX
; i
++) {
1331 if (io_extents
->pp_extents
[i
].pid
== pid
) {
1339 sbi
->ll_extent_process_count
=
1340 (sbi
->ll_extent_process_count
+ 1) % LL_PROCESS_HIST_MAX
;
1341 cur
= sbi
->ll_extent_process_count
;
1342 io_extents
->pp_extents
[cur
].pid
= pid
;
1343 lprocfs_oh_clear(&io_extents
->pp_extents
[cur
].pp_r_hist
);
1344 lprocfs_oh_clear(&io_extents
->pp_extents
[cur
].pp_w_hist
);
1347 for(i
= 0; (count
>= (1 << LL_HIST_START
<< i
)) &&
1348 (i
< (LL_HIST_MAX
- 1)); i
++);
1350 io_extents
->pp_extents
[cur
].pp_r_hist
.oh_buckets
[i
]++;
1351 io_extents
->pp_extents
[LL_PROCESS_HIST_MAX
].pp_r_hist
.oh_buckets
[i
]++;
1353 io_extents
->pp_extents
[cur
].pp_w_hist
.oh_buckets
[i
]++;
1354 io_extents
->pp_extents
[LL_PROCESS_HIST_MAX
].pp_w_hist
.oh_buckets
[i
]++;
1356 spin_unlock(&sbi
->ll_pp_extent_lock
);
1358 spin_lock(&sbi
->ll_process_lock
);
1359 /* Offset statistics */
1360 for (i
= 0; i
< LL_PROCESS_HIST_MAX
; i
++) {
1361 if (process
[i
].rw_pid
== pid
) {
1362 if (process
[i
].rw_last_file
!= file
) {
1363 process
[i
].rw_range_start
= pos
;
1364 process
[i
].rw_last_file_pos
= pos
+ count
;
1365 process
[i
].rw_smallest_extent
= count
;
1366 process
[i
].rw_largest_extent
= count
;
1367 process
[i
].rw_offset
= 0;
1368 process
[i
].rw_last_file
= file
;
1369 spin_unlock(&sbi
->ll_process_lock
);
1372 if (process
[i
].rw_last_file_pos
!= pos
) {
1374 (*off_count
+ 1) % LL_OFFSET_HIST_MAX
;
1375 offset
[*off_count
].rw_op
= process
[i
].rw_op
;
1376 offset
[*off_count
].rw_pid
= pid
;
1377 offset
[*off_count
].rw_range_start
=
1378 process
[i
].rw_range_start
;
1379 offset
[*off_count
].rw_range_end
=
1380 process
[i
].rw_last_file_pos
;
1381 offset
[*off_count
].rw_smallest_extent
=
1382 process
[i
].rw_smallest_extent
;
1383 offset
[*off_count
].rw_largest_extent
=
1384 process
[i
].rw_largest_extent
;
1385 offset
[*off_count
].rw_offset
=
1386 process
[i
].rw_offset
;
1387 process
[i
].rw_op
= rw
;
1388 process
[i
].rw_range_start
= pos
;
1389 process
[i
].rw_smallest_extent
= count
;
1390 process
[i
].rw_largest_extent
= count
;
1391 process
[i
].rw_offset
= pos
-
1392 process
[i
].rw_last_file_pos
;
1394 if (process
[i
].rw_smallest_extent
> count
)
1395 process
[i
].rw_smallest_extent
= count
;
1396 if (process
[i
].rw_largest_extent
< count
)
1397 process
[i
].rw_largest_extent
= count
;
1398 process
[i
].rw_last_file_pos
= pos
+ count
;
1399 spin_unlock(&sbi
->ll_process_lock
);
1403 *process_count
= (*process_count
+ 1) % LL_PROCESS_HIST_MAX
;
1404 process
[*process_count
].rw_pid
= pid
;
1405 process
[*process_count
].rw_op
= rw
;
1406 process
[*process_count
].rw_range_start
= pos
;
1407 process
[*process_count
].rw_last_file_pos
= pos
+ count
;
1408 process
[*process_count
].rw_smallest_extent
= count
;
1409 process
[*process_count
].rw_largest_extent
= count
;
1410 process
[*process_count
].rw_offset
= 0;
1411 process
[*process_count
].rw_last_file
= file
;
1412 spin_unlock(&sbi
->ll_process_lock
);
1415 static int ll_rw_offset_stats_seq_show(struct seq_file
*seq
, void *v
)
1418 struct ll_sb_info
*sbi
= seq
->private;
1419 struct ll_rw_process_info
*offset
= sbi
->ll_rw_offset_info
;
1420 struct ll_rw_process_info
*process
= sbi
->ll_rw_process_info
;
1423 do_gettimeofday(&now
);
1425 if (!sbi
->ll_rw_stats_on
) {
1426 seq_printf(seq
, "disabled\n"
1427 "write anything in this file to activate, then 0 or \"[D/d]isabled\" to deactivate\n");
1430 spin_lock(&sbi
->ll_process_lock
);
1432 seq_printf(seq
, "snapshot_time: %lu.%lu (secs.usecs)\n",
1433 now
.tv_sec
, (unsigned long)now
.tv_usec
);
1434 seq_printf(seq
, "%3s %10s %14s %14s %17s %17s %14s\n",
1435 "R/W", "PID", "RANGE START", "RANGE END",
1436 "SMALLEST EXTENT", "LARGEST EXTENT", "OFFSET");
1437 /* We stored the discontiguous offsets here; print them first */
1438 for (i
= 0; i
< LL_OFFSET_HIST_MAX
; i
++) {
1439 if (offset
[i
].rw_pid
!= 0)
1441 "%3c %10d %14Lu %14Lu %17lu %17lu %14Lu",
1442 offset
[i
].rw_op
== READ
? 'R' : 'W',
1444 offset
[i
].rw_range_start
,
1445 offset
[i
].rw_range_end
,
1446 (unsigned long)offset
[i
].rw_smallest_extent
,
1447 (unsigned long)offset
[i
].rw_largest_extent
,
1448 offset
[i
].rw_offset
);
1450 /* Then print the current offsets for each process */
1451 for (i
= 0; i
< LL_PROCESS_HIST_MAX
; i
++) {
1452 if (process
[i
].rw_pid
!= 0)
1454 "%3c %10d %14Lu %14Lu %17lu %17lu %14Lu",
1455 process
[i
].rw_op
== READ
? 'R' : 'W',
1457 process
[i
].rw_range_start
,
1458 process
[i
].rw_last_file_pos
,
1459 (unsigned long)process
[i
].rw_smallest_extent
,
1460 (unsigned long)process
[i
].rw_largest_extent
,
1461 process
[i
].rw_offset
);
1463 spin_unlock(&sbi
->ll_process_lock
);
1468 static ssize_t
ll_rw_offset_stats_seq_write(struct file
*file
,
1469 const char __user
*buf
,
1470 size_t len
, loff_t
*off
)
1472 struct seq_file
*seq
= file
->private_data
;
1473 struct ll_sb_info
*sbi
= seq
->private;
1474 struct ll_rw_process_info
*process_info
= sbi
->ll_rw_process_info
;
1475 struct ll_rw_process_info
*offset_info
= sbi
->ll_rw_offset_info
;
1476 int value
= 1, rc
= 0;
1481 rc
= lprocfs_write_helper(buf
, len
, &value
);
1483 if (rc
< 0 && len
< 16) {
1486 if (copy_from_user(kernbuf
, buf
, len
))
1490 if (kernbuf
[len
- 1] == '\n')
1491 kernbuf
[len
- 1] = 0;
1493 if (strcmp(kernbuf
, "disabled") == 0 ||
1494 strcmp(kernbuf
, "Disabled") == 0)
1499 sbi
->ll_rw_stats_on
= 0;
1501 sbi
->ll_rw_stats_on
= 1;
1503 spin_lock(&sbi
->ll_process_lock
);
1504 sbi
->ll_offset_process_count
= 0;
1505 sbi
->ll_rw_offset_entry_count
= 0;
1506 memset(process_info
, 0, sizeof(struct ll_rw_process_info
) *
1507 LL_PROCESS_HIST_MAX
);
1508 memset(offset_info
, 0, sizeof(struct ll_rw_process_info
) *
1509 LL_OFFSET_HIST_MAX
);
1510 spin_unlock(&sbi
->ll_process_lock
);
1515 LPROC_SEQ_FOPS(ll_rw_offset_stats
);
1517 void lprocfs_llite_init_vars(struct lprocfs_static_vars
*lvars
)
1519 lvars
->module_vars
= NULL
;
1520 lvars
->obd_vars
= lprocfs_llite_obd_vars
;