1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2002 Cluster File Systems, Inc.
6 * This file is part of Lustre, http://www.lustre.org.
8 * Lustre is free software; you can redistribute it and/or
9 * modify it under the terms of version 2 of the GNU General Public
10 * License as published by the Free Software Foundation.
12 * Lustre is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Lustre; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #define DEBUG_SUBSYSTEM S_LLITE
24 #include <linux/version.h>
25 #include <lustre_lite.h>
26 #include <lprocfs_status.h>
27 #include <linux/seq_file.h>
28 #include <obd_support.h>
30 #include "llite_internal.h"
32 struct proc_dir_entry *proc_lustre_fs_root;
35 /* /proc/lustre/llite mount point registration */
36 struct file_operations llite_dump_pgcache_fops;
37 struct file_operations ll_ra_stats_fops;
39 static int ll_rd_blksize(char *page, char **start, off_t off, int count,
42 struct super_block *sb = (struct super_block *)data;
43 struct obd_statfs osfs;
47 rc = ll_statfs_internal(sb, &osfs, cfs_time_current_64() - HZ);
50 rc = snprintf(page, count, "%u\n", osfs.os_bsize);
56 static int ll_rd_kbytestotal(char *page, char **start, off_t off, int count,
59 struct super_block *sb = (struct super_block *)data;
60 struct obd_statfs osfs;
64 rc = ll_statfs_internal(sb, &osfs, cfs_time_current_64() - HZ);
66 __u32 blk_size = osfs.os_bsize >> 10;
67 __u64 result = osfs.os_blocks;
69 while (blk_size >>= 1)
73 rc = snprintf(page, count, LPU64"\n", result);
79 static int ll_rd_kbytesfree(char *page, char **start, off_t off, int count,
82 struct super_block *sb = (struct super_block *)data;
83 struct obd_statfs osfs;
87 rc = ll_statfs_internal(sb, &osfs, cfs_time_current_64() - HZ);
89 __u32 blk_size = osfs.os_bsize >> 10;
90 __u64 result = osfs.os_bfree;
92 while (blk_size >>= 1)
96 rc = snprintf(page, count, LPU64"\n", result);
101 static int ll_rd_kbytesavail(char *page, char **start, off_t off, int count,
102 int *eof, void *data)
104 struct super_block *sb = (struct super_block *)data;
105 struct obd_statfs osfs;
109 rc = ll_statfs_internal(sb, &osfs, cfs_time_current_64() - HZ);
111 __u32 blk_size = osfs.os_bsize >> 10;
112 __u64 result = osfs.os_bavail;
114 while (blk_size >>= 1)
118 rc = snprintf(page, count, LPU64"\n", result);
123 static int ll_rd_filestotal(char *page, char **start, off_t off, int count,
124 int *eof, void *data)
126 struct super_block *sb = (struct super_block *)data;
127 struct obd_statfs osfs;
131 rc = ll_statfs_internal(sb, &osfs, cfs_time_current_64() - HZ);
134 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
139 static int ll_rd_filesfree(char *page, char **start, off_t off, int count,
140 int *eof, void *data)
142 struct super_block *sb = (struct super_block *)data;
143 struct obd_statfs osfs;
147 rc = ll_statfs_internal(sb, &osfs, cfs_time_current_64() - HZ);
150 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
156 static int ll_rd_fstype(char *page, char **start, off_t off, int count,
157 int *eof, void *data)
159 struct super_block *sb = (struct super_block*)data;
163 return snprintf(page, count, "%s\n", sb->s_type->name);
166 static int ll_rd_sb_uuid(char *page, char **start, off_t off, int count,
167 int *eof, void *data)
169 struct super_block *sb = (struct super_block *)data;
173 return snprintf(page, count, "%s\n", ll_s2sbi(sb)->ll_sb_uuid.uuid);
176 static int ll_rd_max_readahead_mb(char *page, char **start, off_t off,
177 int count, int *eof, void *data)
179 struct super_block *sb = data;
180 struct ll_sb_info *sbi = ll_s2sbi(sb);
184 spin_lock(&sbi->ll_lock);
185 pages_number = sbi->ll_ra_info.ra_max_pages;
186 spin_unlock(&sbi->ll_lock);
188 mult = 1 << (20 - PAGE_CACHE_SHIFT);
189 return lprocfs_read_frac_helper(page, count, pages_number, mult);
192 static int ll_wr_max_readahead_mb(struct file *file, const char *buffer,
193 unsigned long count, void *data)
195 struct super_block *sb = data;
196 struct ll_sb_info *sbi = ll_s2sbi(sb);
197 int mult, rc, pages_number;
199 mult = 1 << (20 - PAGE_CACHE_SHIFT);
200 rc = lprocfs_write_frac_helper(buffer, count, &pages_number, mult);
204 if (pages_number < 0 || pages_number > num_physpages / 2) {
205 CERROR("can't set file readahead more than %lu MB\n",
206 num_physpages >> (20 - PAGE_CACHE_SHIFT + 1)); /*1/2 of RAM*/
210 spin_lock(&sbi->ll_lock);
211 sbi->ll_ra_info.ra_max_pages = pages_number;
212 spin_unlock(&sbi->ll_lock);
217 static int ll_rd_max_read_ahead_whole_mb(char *page, char **start, off_t off,
218 int count, int *eof, void *data)
220 struct super_block *sb = data;
221 struct ll_sb_info *sbi = ll_s2sbi(sb);
225 spin_lock(&sbi->ll_lock);
226 pages_number = sbi->ll_ra_info.ra_max_read_ahead_whole_pages;
227 spin_unlock(&sbi->ll_lock);
229 mult = 1 << (20 - PAGE_CACHE_SHIFT);
230 return lprocfs_read_frac_helper(page, count, pages_number, mult);
233 static int ll_wr_max_read_ahead_whole_mb(struct file *file, const char *buffer,
234 unsigned long count, void *data)
236 struct super_block *sb = data;
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 /* Cap this at the current max readahead window size, the readahead
246 * algorithm does this anyway so it's pointless to set it larger. */
247 if (pages_number < 0 || pages_number > sbi->ll_ra_info.ra_max_pages) {
248 CERROR("can't set max_read_ahead_whole_mb more than "
249 "max_read_ahead_mb: %lu\n",
250 sbi->ll_ra_info.ra_max_pages >> (20 - PAGE_CACHE_SHIFT));
254 spin_lock(&sbi->ll_lock);
255 sbi->ll_ra_info.ra_max_read_ahead_whole_pages = pages_number;
256 spin_unlock(&sbi->ll_lock);
261 static int ll_rd_max_cached_mb(char *page, char **start, off_t off,
262 int count, int *eof, void *data)
264 struct super_block *sb = data;
265 struct ll_sb_info *sbi = ll_s2sbi(sb);
269 spin_lock(&sbi->ll_lock);
270 pages_number = sbi->ll_async_page_max;
271 spin_unlock(&sbi->ll_lock);
273 mult = 1 << (20 - PAGE_CACHE_SHIFT);
274 return lprocfs_read_frac_helper(page, count, pages_number, mult);;
277 static int ll_wr_max_cached_mb(struct file *file, const char *buffer,
278 unsigned long count, void *data)
280 struct super_block *sb = data;
281 struct ll_sb_info *sbi = ll_s2sbi(sb);
282 int mult, rc, pages_number;
284 mult = 1 << (20 - PAGE_CACHE_SHIFT);
285 rc = lprocfs_write_frac_helper(buffer, count, &pages_number, mult);
289 if (pages_number < 0 || pages_number > num_physpages) {
290 CERROR("can't set max cache more than %lu MB\n",
291 num_physpages >> (20 - PAGE_CACHE_SHIFT));
295 spin_lock(&sbi->ll_lock);
296 sbi->ll_async_page_max = pages_number ;
297 spin_unlock(&sbi->ll_lock);
300 /* Not set up yet, don't call llap_shrink_cache */
303 if (sbi->ll_async_page_count >= sbi->ll_async_page_max)
304 llap_shrink_cache(sbi, 0);
309 static int ll_rd_checksum(char *page, char **start, off_t off,
310 int count, int *eof, void *data)
312 struct super_block *sb = data;
313 struct ll_sb_info *sbi = ll_s2sbi(sb);
315 return snprintf(page, count, "%u\n",
316 (sbi->ll_flags & LL_SBI_CHECKSUM) ? 1 : 0);
319 static int ll_wr_checksum(struct file *file, const char *buffer,
320 unsigned long count, void *data)
322 struct super_block *sb = data;
323 struct ll_sb_info *sbi = ll_s2sbi(sb);
330 rc = lprocfs_write_helper(buffer, count, &val);
334 sbi->ll_flags |= LL_SBI_CHECKSUM;
336 sbi->ll_flags &= ~LL_SBI_CHECKSUM;
338 rc = obd_set_info_async(sbi->ll_dt_exp, strlen("checksum"), "checksum",
339 sizeof(val), &val, NULL);
341 CWARN("Failed to set OSC checksum flags: %d\n", rc);
346 static int ll_rd_max_rw_chunk(char *page, char **start, off_t off,
347 int count, int *eof, void *data)
349 struct super_block *sb = data;
351 return snprintf(page, count, "%lu\n", ll_s2sbi(sb)->ll_max_rw_chunk);
354 static int ll_wr_max_rw_chunk(struct file *file, const char *buffer,
355 unsigned long count, void *data)
357 struct super_block *sb = data;
360 rc = lprocfs_write_helper(buffer, count, &val);
363 ll_s2sbi(sb)->ll_max_rw_chunk = val;
367 static struct lprocfs_vars lprocfs_obd_vars[] = {
368 { "uuid", ll_rd_sb_uuid, 0, 0 },
369 //{ "mntpt_path", ll_rd_path, 0, 0 },
370 { "fstype", ll_rd_fstype, 0, 0 },
371 { "blocksize", ll_rd_blksize, 0, 0 },
372 { "kbytestotal", ll_rd_kbytestotal, 0, 0 },
373 { "kbytesfree", ll_rd_kbytesfree, 0, 0 },
374 { "kbytesavail", ll_rd_kbytesavail, 0, 0 },
375 { "filestotal", ll_rd_filestotal, 0, 0 },
376 { "filesfree", ll_rd_filesfree, 0, 0 },
377 //{ "filegroups", lprocfs_rd_filegroups, 0, 0 },
378 { "max_read_ahead_mb", ll_rd_max_readahead_mb,
379 ll_wr_max_readahead_mb, 0 },
380 { "max_read_ahead_whole_mb", ll_rd_max_read_ahead_whole_mb,
381 ll_wr_max_read_ahead_whole_mb, 0 },
382 { "max_cached_mb", ll_rd_max_cached_mb, ll_wr_max_cached_mb, 0 },
383 { "checksum_pages", ll_rd_checksum, ll_wr_checksum, 0 },
384 { "max_rw_chunk", ll_rd_max_rw_chunk, ll_wr_max_rw_chunk, 0 },
388 #define MAX_STRING_SIZE 128
390 struct llite_file_opcode {
394 } llite_opcode_table[LPROC_LL_FILE_OPCODES] = {
396 { LPROC_LL_DIRTY_HITS, LPROCFS_TYPE_REGS, "dirty_pages_hits" },
397 { LPROC_LL_DIRTY_MISSES, LPROCFS_TYPE_REGS, "dirty_pages_misses" },
398 { LPROC_LL_WB_WRITEPAGE, LPROCFS_CNTR_AVGMINMAX|LPROCFS_TYPE_PAGES,
399 "writeback_from_writepage" },
400 { LPROC_LL_WB_PRESSURE, LPROCFS_CNTR_AVGMINMAX|LPROCFS_TYPE_PAGES,
401 "writeback_from_pressure" },
402 { LPROC_LL_WB_OK, LPROCFS_CNTR_AVGMINMAX|LPROCFS_TYPE_PAGES,
403 "writeback_ok_pages" },
404 { LPROC_LL_WB_FAIL, LPROCFS_CNTR_AVGMINMAX|LPROCFS_TYPE_PAGES,
405 "writeback_failed_pages" },
406 { LPROC_LL_READ_BYTES, LPROCFS_CNTR_AVGMINMAX|LPROCFS_TYPE_BYTES,
408 { LPROC_LL_WRITE_BYTES, LPROCFS_CNTR_AVGMINMAX|LPROCFS_TYPE_BYTES,
410 { LPROC_LL_BRW_READ, LPROCFS_CNTR_AVGMINMAX|LPROCFS_TYPE_PAGES,
412 { LPROC_LL_BRW_WRITE, LPROCFS_CNTR_AVGMINMAX|LPROCFS_TYPE_PAGES,
415 { LPROC_LL_IOCTL, LPROCFS_TYPE_REGS, "ioctl" },
416 { LPROC_LL_OPEN, LPROCFS_TYPE_REGS, "open" },
417 { LPROC_LL_RELEASE, LPROCFS_TYPE_REGS, "close" },
418 { LPROC_LL_MAP, LPROCFS_TYPE_REGS, "mmap" },
419 { LPROC_LL_LLSEEK, LPROCFS_TYPE_REGS, "seek" },
420 { LPROC_LL_FSYNC, LPROCFS_TYPE_REGS, "fsync" },
421 /* inode operation */
422 { LPROC_LL_SETATTR, LPROCFS_TYPE_REGS, "setattr" },
423 { LPROC_LL_TRUNC, LPROCFS_TYPE_REGS, "punch" },
424 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
425 { LPROC_LL_GETATTR, LPROCFS_TYPE_REGS, "getattr" },
427 { LPROC_LL_REVALIDATE, LPROCFS_TYPE_REGS, "getattr" },
429 /* special inode operation */
430 { LPROC_LL_STAFS, LPROCFS_TYPE_REGS, "statfs" },
431 { LPROC_LL_ALLOC_INODE, LPROCFS_TYPE_REGS, "alloc_inode" },
432 { LPROC_LL_SETXATTR, LPROCFS_TYPE_REGS, "setxattr" },
433 { LPROC_LL_GETXATTR, LPROCFS_TYPE_REGS, "getxattr" },
434 { LPROC_LL_DIRECT_READ, LPROCFS_CNTR_AVGMINMAX|LPROCFS_TYPE_PAGES,
436 { LPROC_LL_DIRECT_WRITE, LPROCFS_CNTR_AVGMINMAX|LPROCFS_TYPE_PAGES,
441 int lprocfs_register_mountpoint(struct proc_dir_entry *parent,
442 struct super_block *sb, char *osc, char *mdc)
444 struct lprocfs_vars lvars[2];
445 struct lustre_sb_info *lsi = s2lsi(sb);
446 struct ll_sb_info *sbi = ll_s2sbi(sb);
447 struct obd_device *obd;
448 char name[MAX_STRING_SIZE + 1], *ptr;
450 struct lprocfs_stats *svc_stats = NULL;
451 struct proc_dir_entry *entry;
454 memset(lvars, 0, sizeof(lvars));
456 name[MAX_STRING_SIZE] = '\0';
457 lvars[0].name = name;
459 LASSERT(sbi != NULL);
460 LASSERT(mdc != NULL);
461 LASSERT(osc != NULL);
464 len = strlen(lsi->lsi_lmd->lmd_profile);
465 ptr = strrchr(lsi->lsi_lmd->lmd_profile, '-');
466 if (ptr && (strcmp(ptr, "-client") == 0))
470 snprintf(name, MAX_STRING_SIZE, "%.*s-%p", len,
471 lsi->lsi_lmd->lmd_profile, sb);
473 sbi->ll_proc_root = lprocfs_register(name, parent, NULL, NULL);
474 if (IS_ERR(sbi->ll_proc_root)) {
475 err = PTR_ERR(sbi->ll_proc_root);
476 sbi->ll_proc_root = NULL;
480 entry = create_proc_entry("dump_page_cache", 0444, sbi->ll_proc_root);
482 GOTO(out, err = -ENOMEM);
483 entry->proc_fops = &llite_dump_pgcache_fops;
486 entry = create_proc_entry("read_ahead_stats", 0444, sbi->ll_proc_root);
488 GOTO(out, err = -ENOMEM);
489 entry->proc_fops = &ll_ra_stats_fops;
492 svc_stats = lprocfs_alloc_stats(LPROC_LL_FILE_OPCODES);
493 if (svc_stats == NULL) {
497 /* do counter init */
498 for (id = 0; id < LPROC_LL_FILE_OPCODES; id++) {
499 __u32 type = llite_opcode_table[id].type;
501 if (type & LPROCFS_TYPE_REGS)
504 if (type & LPROCFS_TYPE_BYTES)
507 if (type & LPROCFS_TYPE_PAGES)
511 lprocfs_counter_init(svc_stats, llite_opcode_table[id].opcode,
512 (type & LPROCFS_CNTR_AVGMINMAX),
513 llite_opcode_table[id].opname, ptr);
515 err = lprocfs_register_stats(sbi->ll_proc_root, "stats", svc_stats);
519 sbi->ll_stats = svc_stats;
520 /* need place to keep svc_stats */
522 /* Static configuration info */
523 err = lprocfs_add_vars(sbi->ll_proc_root, lprocfs_obd_vars, sb);
528 obd = class_name2obd(mdc);
530 LASSERT(obd != NULL);
531 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
532 LASSERT(obd->obd_type->typ_name != NULL);
534 snprintf(name, MAX_STRING_SIZE, "%s/common_name",
535 obd->obd_type->typ_name);
536 lvars[0].read_fptr = lprocfs_rd_name;
537 err = lprocfs_add_vars(sbi->ll_proc_root, lvars, obd);
541 snprintf(name, MAX_STRING_SIZE, "%s/uuid", obd->obd_type->typ_name);
542 lvars[0].read_fptr = lprocfs_rd_uuid;
543 err = lprocfs_add_vars(sbi->ll_proc_root, lvars, obd);
548 obd = class_name2obd(osc);
550 LASSERT(obd != NULL);
551 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
552 LASSERT(obd->obd_type->typ_name != NULL);
554 snprintf(name, MAX_STRING_SIZE, "%s/common_name",
555 obd->obd_type->typ_name);
556 lvars[0].read_fptr = lprocfs_rd_name;
557 err = lprocfs_add_vars(sbi->ll_proc_root, lvars, obd);
561 snprintf(name, MAX_STRING_SIZE, "%s/uuid", obd->obd_type->typ_name);
562 lvars[0].read_fptr = lprocfs_rd_uuid;
563 err = lprocfs_add_vars(sbi->ll_proc_root, lvars, obd);
567 lprocfs_free_stats(svc_stats);
568 if (sbi->ll_proc_root)
569 lprocfs_remove(sbi->ll_proc_root);
570 sbi->ll_proc_root = NULL;
575 void lprocfs_unregister_mountpoint(struct ll_sb_info *sbi)
577 if (sbi->ll_proc_root) {
578 struct proc_dir_entry *file_stats =
579 lprocfs_srch(sbi->ll_proc_root, "stats");
581 lprocfs_free_stats(sbi->ll_stats);
582 lprocfs_remove(sbi->ll_proc_root);
583 sbi->ll_proc_root = NULL;
586 #undef MAX_STRING_SIZE
588 #define seq_page_flag(seq, page, flag, has_flags) do { \
589 if (test_bit(PG_##flag, &(page)->flags)) { \
593 seq_putc(seq, '|'); \
594 seq_puts(seq, #flag); \
598 static void *llite_dump_pgcache_seq_start(struct seq_file *seq, loff_t *pos)
600 struct ll_async_page *dummy_llap = seq->private;
602 if (dummy_llap->llap_magic == 2)
608 static int llite_dump_pgcache_seq_show(struct seq_file *seq, void *v)
610 struct ll_async_page *llap, *dummy_llap = seq->private;
611 struct ll_sb_info *sbi = dummy_llap->llap_cookie;
613 /* 2.4 doesn't seem to have SEQ_START_TOKEN, so we implement
614 * it in our own state */
615 if (dummy_llap->llap_magic == 0) {
616 seq_printf(seq, "gener | llap cookie origin wq du | page "
617 "inode index count [ page flags ]\n");
621 spin_lock(&sbi->ll_lock);
623 llap = llite_pglist_next_llap(sbi, &dummy_llap->llap_pglist_item);
626 struct page *page = llap->llap_page;
628 LASSERTF(llap->llap_origin < LLAP__ORIGIN_MAX, "%u\n",
631 seq_printf(seq, "%5lu | %p %p %s %s %s | %p %p %lu %u [",
633 llap, llap->llap_cookie,
634 llap_origins[llap->llap_origin],
635 llap->llap_write_queued ? "wq" : "- ",
636 llap->llap_defer_uptodate ? "du" : "- ",
637 page, page->mapping->host, page->index,
639 seq_page_flag(seq, page, locked, has_flags);
640 seq_page_flag(seq, page, error, has_flags);
641 seq_page_flag(seq, page, referenced, has_flags);
642 seq_page_flag(seq, page, uptodate, has_flags);
643 seq_page_flag(seq, page, dirty, has_flags);
644 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,12))
645 seq_page_flag(seq, page, highmem, has_flags);
648 seq_puts(seq, "-]\n");
650 seq_puts(seq, "]\n");
653 spin_unlock(&sbi->ll_lock);
658 static void *llite_dump_pgcache_seq_next(struct seq_file *seq, void *v,
661 struct ll_async_page *llap, *dummy_llap = seq->private;
662 struct ll_sb_info *sbi = dummy_llap->llap_cookie;
664 /* bail if we just displayed the banner */
665 if (dummy_llap->llap_magic == 0) {
666 dummy_llap->llap_magic = 1;
670 /* we've just displayed the llap that is after us in the list.
671 * we advance to a position beyond it, returning null if there
672 * isn't another llap in the list beyond that new position. */
673 spin_lock(&sbi->ll_lock);
674 llap = llite_pglist_next_llap(sbi, &dummy_llap->llap_pglist_item);
675 list_del_init(&dummy_llap->llap_pglist_item);
677 list_add(&dummy_llap->llap_pglist_item,&llap->llap_pglist_item);
678 llap =llite_pglist_next_llap(sbi,&dummy_llap->llap_pglist_item);
680 spin_unlock(&sbi->ll_lock);
684 dummy_llap->llap_magic = 2;
690 static void llite_dump_pgcache_seq_stop(struct seq_file *seq, void *v)
694 struct seq_operations llite_dump_pgcache_seq_sops = {
695 .start = llite_dump_pgcache_seq_start,
696 .stop = llite_dump_pgcache_seq_stop,
697 .next = llite_dump_pgcache_seq_next,
698 .show = llite_dump_pgcache_seq_show,
701 /* we're displaying llaps in a list_head list. we don't want to hold a lock
702 * while we walk the entire list, and we don't want to have to seek into
703 * the right position in the list as an app advances with many syscalls. we
704 * allocate a dummy llap and hang it off file->private. its position in
705 * the list records where the app is currently displaying. this way our
706 * seq .start and .stop don't actually do anything. .next returns null
707 * when the dummy hits the end of the list which eventually leads to .release
708 * where we tear down. this kind of displaying is super-racey, so we put
709 * a generation counter on the list so the output shows when the list
710 * changes between reads.
712 static int llite_dump_pgcache_seq_open(struct inode *inode, struct file *file)
714 struct proc_dir_entry *dp = PDE(inode);
715 struct ll_async_page *dummy_llap;
716 struct seq_file *seq;
717 struct ll_sb_info *sbi = dp->data;
720 OBD_ALLOC_GFP(dummy_llap, sizeof(*dummy_llap), GFP_KERNEL);
721 if (dummy_llap == NULL)
723 dummy_llap->llap_page = NULL;
724 dummy_llap->llap_cookie = sbi;
725 dummy_llap->llap_magic = 0;
727 rc = seq_open(file, &llite_dump_pgcache_seq_sops);
729 OBD_FREE(dummy_llap, sizeof(*dummy_llap));
732 seq = file->private_data;
733 seq->private = dummy_llap;
735 spin_lock(&sbi->ll_lock);
736 list_add(&dummy_llap->llap_pglist_item, &sbi->ll_pglist);
737 spin_unlock(&sbi->ll_lock);
742 static int llite_dump_pgcache_seq_release(struct inode *inode,
745 struct seq_file *seq = file->private_data;
746 struct ll_async_page *dummy_llap = seq->private;
747 struct ll_sb_info *sbi = dummy_llap->llap_cookie;
749 spin_lock(&sbi->ll_lock);
750 if (!list_empty(&dummy_llap->llap_pglist_item))
751 list_del_init(&dummy_llap->llap_pglist_item);
752 spin_unlock(&sbi->ll_lock);
753 OBD_FREE(dummy_llap, sizeof(*dummy_llap));
755 return seq_release(inode, file);
758 struct file_operations llite_dump_pgcache_fops = {
759 .owner = THIS_MODULE,
760 .open = llite_dump_pgcache_seq_open,
762 .release = llite_dump_pgcache_seq_release,
765 static int ll_ra_stats_seq_show(struct seq_file *seq, void *v)
768 struct ll_sb_info *sbi = seq->private;
769 struct ll_ra_info *ra = &sbi->ll_ra_info;
771 static char *ra_stat_strings[] = {
772 [RA_STAT_HIT] = "hits",
773 [RA_STAT_MISS] = "misses",
774 [RA_STAT_DISTANT_READPAGE] = "readpage not consecutive",
775 [RA_STAT_MISS_IN_WINDOW] = "miss inside window",
776 [RA_STAT_FAILED_GRAB_PAGE] = "failed grab_cache_page",
777 [RA_STAT_FAILED_MATCH] = "failed lock match",
778 [RA_STAT_DISCARDED] = "read but discarded",
779 [RA_STAT_ZERO_LEN] = "zero length file",
780 [RA_STAT_ZERO_WINDOW] = "zero size window",
781 [RA_STAT_EOF] = "read-ahead to EOF",
782 [RA_STAT_MAX_IN_FLIGHT] = "hit max r-a issue",
783 [RA_STAT_WRONG_GRAB_PAGE] = "wrong page from grab_cache_page",
786 do_gettimeofday(&now);
788 spin_lock(&sbi->ll_lock);
790 seq_printf(seq, "snapshot_time: %lu.%lu (secs.usecs)\n",
791 now.tv_sec, now.tv_usec);
792 seq_printf(seq, "pending issued pages: %lu\n",
795 for(i = 0; i < _NR_RA_STAT; i++)
796 seq_printf(seq, "%-25s %lu\n", ra_stat_strings[i],
799 spin_unlock(&sbi->ll_lock);
804 static void *ll_ra_stats_seq_start(struct seq_file *p, loff_t *pos)
810 static void *ll_ra_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
815 static void ll_ra_stats_seq_stop(struct seq_file *p, void *v)
818 struct seq_operations ll_ra_stats_seq_sops = {
819 .start = ll_ra_stats_seq_start,
820 .stop = ll_ra_stats_seq_stop,
821 .next = ll_ra_stats_seq_next,
822 .show = ll_ra_stats_seq_show,
825 static int ll_ra_stats_seq_open(struct inode *inode, struct file *file)
827 struct proc_dir_entry *dp = PDE(inode);
828 struct seq_file *seq;
831 rc = seq_open(file, &ll_ra_stats_seq_sops);
834 seq = file->private_data;
835 seq->private = dp->data;
839 static ssize_t ll_ra_stats_seq_write(struct file *file, const char *buf,
840 size_t len, loff_t *off)
842 struct seq_file *seq = file->private_data;
843 struct ll_sb_info *sbi = seq->private;
844 struct ll_ra_info *ra = &sbi->ll_ra_info;
846 spin_lock(&sbi->ll_lock);
847 memset(ra->ra_stats, 0, sizeof(ra->ra_stats));
848 spin_unlock(&sbi->ll_lock);
853 struct file_operations ll_ra_stats_fops = {
854 .owner = THIS_MODULE,
855 .open = ll_ra_stats_seq_open,
857 .write = ll_ra_stats_seq_write,
859 .release = seq_release,
862 LPROCFS_INIT_VARS(llite, NULL, lprocfs_obd_vars)