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, 2013, Intel Corporation.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
36 * lustre/obdclass/lprocfs_status.c
38 * Author: Hariharan Thantry <thantry@users.sourceforge.net>
41 #define DEBUG_SUBSYSTEM S_CLASS
44 #include <liblustre.h>
47 #include <obd_class.h>
48 #include <lprocfs_status.h>
49 #include <lustre/lustre_idl.h>
53 static int lprocfs_no_percpu_stats = 0;
54 CFS_MODULE_PARM(lprocfs_no_percpu_stats, "i", int, 0644,
55 "Do not alloc percpu data for lprocfs stats");
57 #define MAX_STRING_SIZE 128
59 int lprocfs_single_release(struct inode *inode, struct file *file)
61 return single_release(inode, file);
63 EXPORT_SYMBOL(lprocfs_single_release);
65 int lprocfs_seq_release(struct inode *inode, struct file *file)
67 return seq_release(inode, file);
69 EXPORT_SYMBOL(lprocfs_seq_release);
71 #ifndef HAVE_ONLY_PROCFS_SEQ
72 /* for b=10866, global variable */
73 DECLARE_RWSEM(_lprocfs_lock);
74 EXPORT_SYMBOL(_lprocfs_lock);
76 static struct proc_dir_entry *__lprocfs_srch(struct proc_dir_entry *head,
79 struct proc_dir_entry *temp;
85 while (temp != NULL) {
86 if (strcmp(temp->name, name) == 0) {
95 struct proc_dir_entry *lprocfs_srch(struct proc_dir_entry *head,
98 struct proc_dir_entry *temp;
100 LPROCFS_SRCH_ENTRY();
101 temp = __lprocfs_srch(head, name);
105 EXPORT_SYMBOL(lprocfs_srch);
107 /* lprocfs API calls */
109 /* Function that emulates snprintf but also has the side effect of advancing
110 the page pointer for the next write into the buffer, incrementing the total
111 length written to the buffer, and decrementing the size left in the
113 #ifdef HAVE_SERVER_SUPPORT
114 static int lprocfs_obd_snprintf(char **page, int end, int *len,
115 const char *format, ...)
123 va_start(list, format);
124 n = vsnprintf(*page, end - *len, format, list);
127 *page += n; *len += n;
130 #endif /* HAVE_SERVER_SUPPORT */
131 #endif /* HAVE_ONLY_PROCFS_SEQ */
133 cfs_proc_dir_entry_t *lprocfs_add_simple(struct proc_dir_entry *root,
135 #ifndef HAVE_ONLY_PROCFS_SEQ
136 read_proc_t *read_proc,
137 write_proc_t *write_proc,
140 struct file_operations *fops)
142 cfs_proc_dir_entry_t *proc;
145 if (root == NULL || name == NULL)
146 return ERR_PTR(-EINVAL);
149 #ifndef HAVE_ONLY_PROCFS_SEQ
155 LPROCFS_WRITE_ENTRY();
156 proc = create_proc_entry(name, mode, root);
158 CERROR("LprocFS: No memory to create /proc entry %s", name);
159 LPROCFS_WRITE_EXIT();
160 return ERR_PTR(-ENOMEM);
162 proc->read_proc = read_proc;
163 proc->write_proc = write_proc;
165 LPROCFS_WRITE_EXIT();
167 return ERR_PTR(-EINVAL);
174 proc = proc_create_data(name, mode, root, fops, data);
176 CERROR("LprocFS: No memory to create /proc entry %s",
178 return ERR_PTR(-ENOMEM);
183 EXPORT_SYMBOL(lprocfs_add_simple);
185 struct proc_dir_entry *lprocfs_add_symlink(const char *name,
186 struct proc_dir_entry *parent, const char *format, ...)
188 struct proc_dir_entry *entry;
192 if (parent == NULL || format == NULL)
195 OBD_ALLOC_WAIT(dest, MAX_STRING_SIZE + 1);
199 va_start(ap, format);
200 vsnprintf(dest, MAX_STRING_SIZE, format, ap);
203 entry = proc_symlink(name, parent, dest);
205 CERROR("LprocFS: Could not create symbolic link from %s to %s",
208 OBD_FREE(dest, MAX_STRING_SIZE + 1);
211 EXPORT_SYMBOL(lprocfs_add_symlink);
213 #ifndef HAVE_ONLY_PROCFS_SEQ
214 static ssize_t lprocfs_fops_read(struct file *f, char __user *buf,
215 size_t size, loff_t *ppos)
217 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
218 char *page, *start = NULL;
219 int rc = 0, eof = 1, count;
221 if (*ppos >= PAGE_CACHE_SIZE)
224 page = (char *)__get_free_page(GFP_KERNEL);
228 if (LPROCFS_ENTRY_CHECK(dp)) {
233 OBD_FAIL_TIMEOUT(OBD_FAIL_LPROC_REMOVE, 10);
235 rc = dp->read_proc(page, &start, *ppos, PAGE_CACHE_SIZE,
240 /* for lustre proc read, the read count must be less than PAGE_SIZE */
249 start = page + *ppos;
250 } else if (start < page) {
254 count = (rc < size) ? rc : size;
255 if (copy_to_user(buf, start, count)) {
262 free_page((unsigned long)page);
266 static ssize_t lprocfs_fops_write(struct file *f, const char __user *buf,
267 size_t size, loff_t *ppos)
269 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
272 if (LPROCFS_ENTRY_CHECK(dp))
275 rc = dp->write_proc(f, buf, size, dp->data);
279 static struct file_operations lprocfs_generic_fops = {
280 .owner = THIS_MODULE,
281 .read = lprocfs_fops_read,
282 .write = lprocfs_fops_write,
285 static struct file_operations lprocfs_generic_fops = { };
288 #ifdef HAVE_SERVER_SUPPORT
289 int lprocfs_evict_client_open(struct inode *inode, struct file *f)
291 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
292 struct obd_device *obd = dp->data;
294 cfs_atomic_inc(&obd->obd_evict_inprogress);
299 int lprocfs_evict_client_release(struct inode *inode, struct file *f)
301 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
302 struct obd_device *obd = dp->data;
304 cfs_atomic_dec(&obd->obd_evict_inprogress);
305 wake_up(&obd->obd_evict_inprogress_waitq);
310 struct file_operations lprocfs_evict_client_fops = {
311 .owner = THIS_MODULE,
312 .read = lprocfs_fops_read,
313 .write = lprocfs_fops_write,
314 .open = lprocfs_evict_client_open,
315 .release = lprocfs_evict_client_release,
317 EXPORT_SYMBOL(lprocfs_evict_client_fops);
320 #ifndef HAVE_ONLY_PROCFS_SEQ
321 static int __lprocfs_add_vars(struct proc_dir_entry *root,
322 struct lprocfs_vars *list,
327 if (root == NULL || list == NULL)
330 while (list->name != NULL) {
331 struct proc_dir_entry *cur_root, *proc;
332 char *pathcopy, *cur, *next, pathbuf[64];
333 int pathsize = strlen(list->name) + 1;
338 /* need copy of path for strsep */
339 if (strlen(list->name) > sizeof(pathbuf) - 1) {
340 OBD_ALLOC(pathcopy, pathsize);
341 if (pathcopy == NULL)
342 GOTO(out, rc = -ENOMEM);
348 strcpy(pathcopy, list->name);
350 while (cur_root != NULL && (cur = strsep(&next, "/"))) {
351 if (*cur =='\0') /* skip double/trailing "/" */
354 proc = __lprocfs_srch(cur_root, cur);
355 CDEBUG(D_OTHER, "cur_root=%s, cur=%s, next=%s, (%s)\n",
356 cur_root->name, cur, next,
357 (proc ? "exists" : "new"));
359 cur_root = (proc ? proc :
360 proc_mkdir(cur, cur_root));
361 } else if (proc == NULL) {
363 if (list->proc_mode != 0000) {
364 mode = list->proc_mode;
368 if (list->write_fptr)
371 proc = create_proc_entry(cur, mode, cur_root);
375 if (pathcopy != pathbuf)
376 OBD_FREE(pathcopy, pathsize);
378 if (cur_root == NULL || proc == NULL) {
379 CERROR("LprocFS: No memory to create /proc entry %s",
381 GOTO(out, rc = -ENOMEM);
385 proc->proc_fops = list->fops;
387 proc->proc_fops = &lprocfs_generic_fops;
388 proc->read_proc = list->read_fptr;
389 proc->write_proc = list->write_fptr;
390 proc->data = (list->data ? list->data : data);
397 int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list,
402 LPROCFS_WRITE_ENTRY();
403 rc = __lprocfs_add_vars(root, list, data);
404 LPROCFS_WRITE_EXIT();
408 EXPORT_SYMBOL(lprocfs_add_vars);
415 * \param root [in] The parent proc entry on which new entry will be added.
416 * \param list [in] Array of proc entries to be added.
417 * \param data [in] The argument to be passed when entries read/write routines
418 * are called through /proc file.
420 * \retval 0 on success
424 lprocfs_seq_add_vars(struct proc_dir_entry *root, struct lprocfs_seq_vars *list,
427 if (root == NULL || list == NULL)
430 while (list->name != NULL) {
431 struct proc_dir_entry *proc;
434 if (list->proc_mode != 0000) {
435 mode = list->proc_mode;
436 } else if (list->fops) {
437 if (list->fops->read)
439 if (list->fops->write)
442 proc = proc_create_data(list->name, mode, root,
443 list->fops ?: &lprocfs_generic_fops,
451 EXPORT_SYMBOL(lprocfs_seq_add_vars);
453 #ifndef HAVE_ONLY_PROCFS_SEQ
454 void lprocfs_remove_nolock(struct proc_dir_entry **proot)
456 struct proc_dir_entry *root = *proot;
457 struct proc_dir_entry *temp = root;
458 struct proc_dir_entry *rm_entry;
459 struct proc_dir_entry *parent;
462 if (root == NULL || IS_ERR(root))
465 parent = root->parent;
466 LASSERT(parent != NULL);
469 while (temp->subdir != NULL)
475 /* Memory corruption once caused this to fail, and
476 without this LASSERT we would loop here forever. */
477 LASSERTF(strlen(rm_entry->name) == rm_entry->namelen,
478 "0x%p %s/%s len %d\n", rm_entry, temp->name,
479 rm_entry->name, (int)strlen(rm_entry->name));
481 remove_proc_entry(rm_entry->name, temp);
488 void lprocfs_remove(struct proc_dir_entry **rooth)
490 #ifndef HAVE_ONLY_PROCFS_SEQ
491 LPROCFS_WRITE_ENTRY(); /* search vs remove race */
492 lprocfs_remove_nolock(rooth);
493 LPROCFS_WRITE_EXIT();
499 EXPORT_SYMBOL(lprocfs_remove);
501 void lprocfs_remove_proc_entry(const char *name, struct proc_dir_entry *parent)
503 LASSERT(parent != NULL);
504 remove_proc_entry(name, parent);
506 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
508 #ifndef HAVE_ONLY_PROCFS_SEQ
509 void lprocfs_try_remove_proc_entry(const char *name,
510 struct proc_dir_entry *parent)
512 struct proc_dir_entry *t = NULL;
513 struct proc_dir_entry **p;
516 LASSERT(parent != NULL);
519 LPROCFS_WRITE_ENTRY();
521 /* lookup target name */
522 for (p = &parent->subdir; *p; p = &(*p)->next) {
523 if ((*p)->namelen != len)
525 if (memcmp(name, (*p)->name, len))
532 /* verify it's empty: do not count "num_refs" */
533 for (p = &t->subdir; *p; p = &(*p)->next) {
534 if ((*p)->namelen != strlen("num_refs")) {
538 if (memcmp("num_refs", (*p)->name,
539 strlen("num_refs"))) {
547 lprocfs_remove_nolock(&t);
549 LPROCFS_WRITE_EXIT();
553 EXPORT_SYMBOL(lprocfs_try_remove_proc_entry);
555 struct proc_dir_entry *lprocfs_register(const char *name,
556 struct proc_dir_entry *parent,
557 struct lprocfs_vars *list, void *data)
559 struct proc_dir_entry *entry;
562 LPROCFS_WRITE_ENTRY();
563 entry = __lprocfs_srch(parent, name);
565 CERROR("entry '%s' already registered\n", name);
566 GOTO(out, entry = ERR_PTR(-EALREADY));
569 entry = proc_mkdir(name, parent);
571 GOTO(out, entry = ERR_PTR(-ENOMEM));
574 rc = __lprocfs_add_vars(entry, list, data);
576 lprocfs_remove_nolock(&entry);
577 GOTO(out, entry = ERR_PTR(rc));
581 LPROCFS_WRITE_EXIT();
584 EXPORT_SYMBOL(lprocfs_register);
587 struct proc_dir_entry *
588 lprocfs_seq_register(const char *name, struct proc_dir_entry *parent,
589 struct lprocfs_seq_vars *list, void *data)
591 struct proc_dir_entry *newchild;
593 newchild = proc_mkdir(name, parent);
594 if (newchild != NULL && list != NULL) {
595 int rc = lprocfs_seq_add_vars(newchild, list, data);
597 lprocfs_remove(&newchild);
603 EXPORT_SYMBOL(lprocfs_seq_register);
605 /* Generic callbacks */
606 int lprocfs_uint_seq_show(struct seq_file *m, void *data)
608 return seq_printf(m, "%u\n", *(unsigned int *)data);
610 EXPORT_SYMBOL(lprocfs_uint_seq_show);
612 int lprocfs_wr_uint(struct file *file, const char *buffer,
613 unsigned long count, void *data)
616 char dummy[MAX_STRING_SIZE + 1], *end;
619 dummy[MAX_STRING_SIZE] = '\0';
620 if (copy_from_user(dummy, buffer, MAX_STRING_SIZE))
623 tmp = simple_strtoul(dummy, &end, 0);
627 *p = (unsigned int)tmp;
630 EXPORT_SYMBOL(lprocfs_wr_uint);
632 ssize_t lprocfs_uint_seq_write(struct file *file, const char *buffer,
633 size_t count, loff_t *off)
635 int *data = ((struct seq_file *)file->private_data)->private;
638 rc = lprocfs_write_helper(buffer, count, &val);
642 return lprocfs_wr_uint(file, buffer, count, data);
644 EXPORT_SYMBOL(lprocfs_uint_seq_write);
646 int lprocfs_u64_seq_show(struct seq_file *m, void *data)
648 LASSERT(data != NULL);
649 return seq_printf(m, LPU64"\n", *(__u64 *)data);
651 EXPORT_SYMBOL(lprocfs_u64_seq_show);
653 int lprocfs_atomic_seq_show(struct seq_file *m, void *data)
655 cfs_atomic_t *atom = data;
656 LASSERT(atom != NULL);
657 return seq_printf(m, "%d\n", atomic_read(atom));
659 EXPORT_SYMBOL(lprocfs_atomic_seq_show);
662 lprocfs_atomic_seq_write(struct file *file, const char *buffer,
663 size_t count, loff_t *off)
665 cfs_atomic_t *atm = ((struct seq_file *)file->private_data)->private;
669 rc = lprocfs_write_helper(buffer, count, &val);
676 cfs_atomic_set(atm, val);
679 EXPORT_SYMBOL(lprocfs_atomic_seq_write);
681 int lprocfs_uuid_seq_show(struct seq_file *m, void *data)
683 struct obd_device *obd = data;
685 LASSERT(obd != NULL);
686 return seq_printf(m, "%s\n", obd->obd_uuid.uuid);
688 EXPORT_SYMBOL(lprocfs_uuid_seq_show);
690 int lprocfs_name_seq_show(struct seq_file *m, void *data)
692 struct obd_device *dev = data;
694 LASSERT(dev != NULL);
695 return seq_printf(m, "%s\n", dev->obd_name);
697 EXPORT_SYMBOL(lprocfs_name_seq_show);
699 int lprocfs_blksize_seq_show(struct seq_file *m, void *data)
701 struct obd_device *obd = data;
702 struct obd_statfs osfs;
703 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
704 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
707 rc = seq_printf(m, "%u\n", osfs.os_bsize);
710 EXPORT_SYMBOL(lprocfs_blksize_seq_show);
712 int lprocfs_kbytestotal_seq_show(struct seq_file *m, void *data)
714 struct obd_device *obd = data;
715 struct obd_statfs osfs;
716 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
717 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
720 __u32 blk_size = osfs.os_bsize >> 10;
721 __u64 result = osfs.os_blocks;
723 while (blk_size >>= 1)
726 rc = seq_printf(m, LPU64"\n", result);
730 EXPORT_SYMBOL(lprocfs_kbytestotal_seq_show);
732 int lprocfs_kbytesfree_seq_show(struct seq_file *m, void *data)
734 struct obd_device *obd = data;
735 struct obd_statfs osfs;
736 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
737 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
740 __u32 blk_size = osfs.os_bsize >> 10;
741 __u64 result = osfs.os_bfree;
743 while (blk_size >>= 1)
746 rc = seq_printf(m, LPU64"\n", result);
750 EXPORT_SYMBOL(lprocfs_kbytesfree_seq_show);
752 int lprocfs_kbytesavail_seq_show(struct seq_file *m, void *data)
754 struct obd_device *obd = data;
755 struct obd_statfs osfs;
756 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
757 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
760 __u32 blk_size = osfs.os_bsize >> 10;
761 __u64 result = osfs.os_bavail;
763 while (blk_size >>= 1)
766 rc = seq_printf(m, LPU64"\n", result);
770 EXPORT_SYMBOL(lprocfs_kbytesavail_seq_show);
772 int lprocfs_filestotal_seq_show(struct seq_file *m, void *data)
774 struct obd_device *obd = data;
775 struct obd_statfs osfs;
776 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
777 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
780 rc = seq_printf(m, LPU64"\n", osfs.os_files);
783 EXPORT_SYMBOL(lprocfs_filestotal_seq_show);
785 int lprocfs_filesfree_seq_show(struct seq_file *m, void *data)
787 struct obd_device *obd = data;
788 struct obd_statfs osfs;
789 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
790 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
793 rc = seq_printf(m, LPU64"\n", osfs.os_ffree);
796 EXPORT_SYMBOL(lprocfs_filesfree_seq_show);
798 int lprocfs_server_uuid_seq_show(struct seq_file *m, void *data)
800 struct obd_device *obd = data;
801 struct obd_import *imp;
802 char *imp_state_name = NULL;
805 LASSERT(obd != NULL);
806 LPROCFS_CLIMP_CHECK(obd);
807 imp = obd->u.cli.cl_import;
808 imp_state_name = ptlrpc_import_state_name(imp->imp_state);
809 rc = seq_printf(m, "%s\t%s%s\n", obd2cli_tgt(obd), imp_state_name,
810 imp->imp_deactive ? "\tDEACTIVATED" : "");
812 LPROCFS_CLIMP_EXIT(obd);
815 EXPORT_SYMBOL(lprocfs_server_uuid_seq_show);
817 int lprocfs_conn_uuid_seq_show(struct seq_file *m, void *data)
819 struct obd_device *obd = data;
820 struct ptlrpc_connection *conn;
823 LASSERT(obd != NULL);
825 LPROCFS_CLIMP_CHECK(obd);
826 conn = obd->u.cli.cl_import->imp_connection;
827 if (conn && obd->u.cli.cl_import)
828 rc = seq_printf(m, "%s\n", conn->c_remote_uuid.uuid);
830 rc = seq_printf(m, "%s\n", "<none>");
832 LPROCFS_CLIMP_EXIT(obd);
835 EXPORT_SYMBOL(lprocfs_conn_uuid_seq_show);
837 /** add up per-cpu counters */
838 void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
839 struct lprocfs_counter *cnt)
841 unsigned int num_entry;
842 struct lprocfs_counter *percpu_cntr;
844 unsigned long flags = 0;
846 memset(cnt, 0, sizeof(*cnt));
849 /* set count to 1 to avoid divide-by-zero errs in callers */
854 cnt->lc_min = LC_MIN_INIT;
856 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
858 for (i = 0; i < num_entry; i++) {
859 if (stats->ls_percpu[i] == NULL)
861 percpu_cntr = lprocfs_stats_counter_get(stats, i, idx);
863 cnt->lc_count += percpu_cntr->lc_count;
864 cnt->lc_sum += percpu_cntr->lc_sum;
865 if (percpu_cntr->lc_min < cnt->lc_min)
866 cnt->lc_min = percpu_cntr->lc_min;
867 if (percpu_cntr->lc_max > cnt->lc_max)
868 cnt->lc_max = percpu_cntr->lc_max;
869 cnt->lc_sumsquare += percpu_cntr->lc_sumsquare;
872 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
874 EXPORT_SYMBOL(lprocfs_stats_collect);
877 * Append a space separated list of current set flags to str.
879 #define flag2seqstr(flag) \
881 if (imp->imp_##flag) \
882 seq_printf(m, "%s" #flag, first ? "" : ", "); \
884 static int obd_import_flags2seqstr(struct obd_import *imp, struct seq_file *m)
888 if (imp->imp_obd->obd_no_recov) {
889 seq_printf(m, "no_recov");
893 flag2seqstr(invalid);
894 flag2seqstr(deactive);
895 flag2seqstr(replayable);
896 flag2seqstr(pingable);
901 static const char *obd_connect_names[] = {
915 "join_file(obsolete)",
919 "remote_client_by_force",
928 "mds_mds_connection",
931 "alt_checksum_algorithm",
959 static void obd_connect_seq_flags2str(struct seq_file *m, __u64 flags, char *sep)
965 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
967 seq_printf(m, "%s%s",
968 first ? "" : sep, obd_connect_names[i]);
972 if (flags & ~(mask - 1))
973 seq_printf(m, "%sunknown flags "LPX64,
974 first ? "" : sep, flags & ~(mask - 1));
977 int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
982 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
984 ret += snprintf(page + ret, count - ret, "%s%s",
985 ret ? sep : "", obd_connect_names[i]);
987 if (flags & ~(mask - 1))
988 ret += snprintf(page + ret, count - ret,
989 "%sunknown flags "LPX64,
990 ret ? sep : "", flags & ~(mask - 1));
993 EXPORT_SYMBOL(obd_connect_flags2str);
995 int lprocfs_import_seq_show(struct seq_file *m, void *data)
997 struct lprocfs_counter ret;
998 struct lprocfs_counter_header *header;
999 struct obd_device *obd = (struct obd_device *)data;
1000 struct obd_import *imp;
1001 struct obd_import_conn *conn;
1006 LASSERT(obd != NULL);
1007 LPROCFS_CLIMP_CHECK(obd);
1008 imp = obd->u.cli.cl_import;
1010 seq_printf(m,"import:\n"
1015 " connect_flags: [",
1018 ptlrpc_import_state_name(imp->imp_state),
1019 imp->imp_connect_data.ocd_instance);
1020 obd_connect_seq_flags2str(m, imp->imp_connect_data.ocd_connect_flags,
1023 " import_flags: [");
1024 obd_import_flags2seqstr(imp, m);
1028 " failover_nids: [");
1029 spin_lock(&imp->imp_lock);
1031 list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
1032 seq_printf(m, "%s%s", j ? ", " : "",
1033 libcfs_nid2str(conn->oic_conn->c_peer.nid));
1037 " current_connection: %s\n"
1038 " connection_attempts: %u\n"
1040 " in-progress_invalidations: %u\n",
1041 imp->imp_connection == NULL ? "<none>" :
1042 libcfs_nid2str(imp->imp_connection->c_peer.nid),
1044 imp->imp_generation,
1045 atomic_read(&imp->imp_inval_count));
1046 spin_unlock(&imp->imp_lock);
1048 if (obd->obd_svc_stats == NULL)
1051 header = &obd->obd_svc_stats->ls_cnt_header[PTLRPC_REQWAIT_CNTR];
1052 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
1053 if (ret.lc_count != 0) {
1054 /* first argument to do_div MUST be __u64 */
1055 __u64 sum = ret.lc_sum;
1056 do_div(sum, ret.lc_count);
1060 seq_printf(m, " rpcs:\n"
1062 " unregistering: %u\n"
1064 " avg_waittime: "LPU64" %s\n",
1065 atomic_read(&imp->imp_inflight),
1066 atomic_read(&imp->imp_unregistering),
1067 atomic_read(&imp->imp_timeouts),
1068 ret.lc_sum, header->lc_units);
1071 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
1072 if (imp->imp_at.iat_portal[j] == 0)
1074 k = max_t(unsigned int, k,
1075 at_get(&imp->imp_at.iat_service_estimate[j]));
1077 seq_printf(m, " service_estimates:\n"
1078 " services: %u sec\n"
1079 " network: %u sec\n",
1081 at_get(&imp->imp_at.iat_net_latency));
1083 seq_printf(m, " transactions:\n"
1084 " last_replay: "LPU64"\n"
1085 " peer_committed: "LPU64"\n"
1086 " last_checked: "LPU64"\n",
1087 imp->imp_last_replay_transno,
1088 imp->imp_peer_committed_transno,
1089 imp->imp_last_transno_checked);
1091 /* avg data rates */
1092 for (rw = 0; rw <= 1; rw++) {
1093 lprocfs_stats_collect(obd->obd_svc_stats,
1094 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
1096 if (ret.lc_sum > 0 && ret.lc_count > 0) {
1097 /* first argument to do_div MUST be __u64 */
1098 __u64 sum = ret.lc_sum;
1099 do_div(sum, ret.lc_count);
1101 seq_printf(m, " %s_data_averages:\n"
1102 " bytes_per_rpc: "LPU64"\n",
1103 rw ? "write" : "read",
1106 k = (int)ret.lc_sum;
1107 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
1108 header = &obd->obd_svc_stats->ls_cnt_header[j];
1109 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
1110 if (ret.lc_sum > 0 && ret.lc_count != 0) {
1111 /* first argument to do_div MUST be __u64 */
1112 __u64 sum = ret.lc_sum;
1113 do_div(sum, ret.lc_count);
1115 seq_printf(m, " %s_per_rpc: "LPU64"\n",
1116 header->lc_units, ret.lc_sum);
1117 j = (int)ret.lc_sum;
1119 seq_printf(m, " MB_per_sec: %u.%.02u\n",
1120 k / j, (100 * k / j) % 100);
1125 LPROCFS_CLIMP_EXIT(obd);
1128 EXPORT_SYMBOL(lprocfs_import_seq_show);
1130 int lprocfs_state_seq_show(struct seq_file *m, void *data)
1132 struct obd_device *obd = (struct obd_device *)data;
1133 struct obd_import *imp;
1136 LASSERT(obd != NULL);
1137 LPROCFS_CLIMP_CHECK(obd);
1138 imp = obd->u.cli.cl_import;
1140 seq_printf(m, "current_state: %s\n",
1141 ptlrpc_import_state_name(imp->imp_state));
1142 seq_printf(m, "state_history:\n");
1143 k = imp->imp_state_hist_idx;
1144 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
1145 struct import_state_hist *ish =
1146 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
1147 if (ish->ish_state == 0)
1149 seq_printf(m, " - ["CFS_TIME_T", %s]\n",
1151 ptlrpc_import_state_name(ish->ish_state));
1154 LPROCFS_CLIMP_EXIT(obd);
1157 EXPORT_SYMBOL(lprocfs_state_seq_show);
1159 int lprocfs_seq_at_hist_helper(struct seq_file *m, struct adaptive_timeout *at)
1162 for (i = 0; i < AT_BINS; i++)
1163 seq_printf(m, "%3u ", at->at_hist[i]);
1164 seq_printf(m, "\n");
1167 EXPORT_SYMBOL(lprocfs_seq_at_hist_helper);
1169 /* See also ptlrpc_lprocfs_timeouts_show_seq */
1170 int lprocfs_timeouts_seq_show(struct seq_file *m, void *data)
1172 struct obd_device *obd = (struct obd_device *)data;
1173 struct obd_import *imp;
1174 unsigned int cur, worst;
1179 LASSERT(obd != NULL);
1180 LPROCFS_CLIMP_CHECK(obd);
1181 imp = obd->u.cli.cl_import;
1183 now = cfs_time_current_sec();
1185 /* Some network health info for kicks */
1186 s2dhms(&ts, now - imp->imp_last_reply_time);
1187 seq_printf(m, "%-10s : %ld, "DHMS_FMT" ago\n",
1188 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
1190 cur = at_get(&imp->imp_at.iat_net_latency);
1191 worst = imp->imp_at.iat_net_latency.at_worst_ever;
1192 worstt = imp->imp_at.iat_net_latency.at_worst_time;
1193 s2dhms(&ts, now - worstt);
1194 seq_printf(m, "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
1195 "network", cur, worst, worstt, DHMS_VARS(&ts));
1196 lprocfs_seq_at_hist_helper(m, &imp->imp_at.iat_net_latency);
1198 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
1199 if (imp->imp_at.iat_portal[i] == 0)
1201 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
1202 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
1203 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
1204 s2dhms(&ts, now - worstt);
1205 seq_printf(m, "portal %-2d : cur %3u worst %3u (at %ld, "
1206 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
1207 cur, worst, worstt, DHMS_VARS(&ts));
1208 lprocfs_seq_at_hist_helper(m, &imp->imp_at.iat_service_estimate[i]);
1211 LPROCFS_CLIMP_EXIT(obd);
1214 EXPORT_SYMBOL(lprocfs_timeouts_seq_show);
1216 int lprocfs_connect_flags_seq_show(struct seq_file *m, void *data)
1218 struct obd_device *obd = data;
1221 LPROCFS_CLIMP_CHECK(obd);
1222 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1223 seq_printf(m, "flags="LPX64"\n", flags);
1224 obd_connect_seq_flags2str(m, flags, "\n");
1225 seq_printf(m, "\n");
1226 LPROCFS_CLIMP_EXIT(obd);
1229 EXPORT_SYMBOL(lprocfs_connect_flags_seq_show);
1231 #ifndef HAVE_ONLY_PROCFS_SEQ
1233 int lprocfs_rd_uint(char *page, char **start, off_t off,
1234 int count, int *eof, void *data)
1236 unsigned int *temp = data;
1237 return snprintf(page, count, "%u\n", *temp);
1239 EXPORT_SYMBOL(lprocfs_rd_uint);
1241 int lprocfs_rd_u64(char *page, char **start, off_t off,
1242 int count, int *eof, void *data)
1244 LASSERT(data != NULL);
1246 return snprintf(page, count, LPU64"\n", *(__u64 *)data);
1248 EXPORT_SYMBOL(lprocfs_rd_u64);
1250 int lprocfs_rd_atomic(char *page, char **start, off_t off,
1251 int count, int *eof, void *data)
1253 cfs_atomic_t *atom = data;
1254 LASSERT(atom != NULL);
1256 return snprintf(page, count, "%d\n", cfs_atomic_read(atom));
1258 EXPORT_SYMBOL(lprocfs_rd_atomic);
1260 int lprocfs_wr_atomic(struct file *file, const char *buffer,
1261 unsigned long count, void *data)
1263 cfs_atomic_t *atm = data;
1267 rc = lprocfs_write_helper(buffer, count, &val);
1274 cfs_atomic_set(atm, val);
1277 EXPORT_SYMBOL(lprocfs_wr_atomic);
1279 int lprocfs_rd_uuid(char *page, char **start, off_t off, int count,
1280 int *eof, void *data)
1282 struct obd_device *obd = data;
1284 LASSERT(obd != NULL);
1286 return snprintf(page, count, "%s\n", obd->obd_uuid.uuid);
1288 EXPORT_SYMBOL(lprocfs_rd_uuid);
1290 int lprocfs_rd_name(char *page, char **start, off_t off, int count,
1291 int *eof, void *data)
1293 struct obd_device *dev = data;
1295 LASSERT(dev != NULL);
1297 return snprintf(page, count, "%s\n", dev->obd_name);
1299 EXPORT_SYMBOL(lprocfs_rd_name);
1301 int lprocfs_rd_blksize(char *page, char **start, off_t off, int count,
1302 int *eof, void *data)
1304 struct obd_device *obd = data;
1305 struct obd_statfs osfs;
1306 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
1307 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
1308 OBD_STATFS_NODELAY);
1311 rc = snprintf(page, count, "%u\n", osfs.os_bsize);
1315 EXPORT_SYMBOL(lprocfs_rd_blksize);
1317 int lprocfs_rd_kbytestotal(char *page, char **start, off_t off, int count,
1318 int *eof, void *data)
1320 struct obd_device *obd = data;
1321 struct obd_statfs osfs;
1322 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
1323 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
1324 OBD_STATFS_NODELAY);
1326 __u32 blk_size = osfs.os_bsize >> 10;
1327 __u64 result = osfs.os_blocks;
1329 while (blk_size >>= 1)
1333 rc = snprintf(page, count, LPU64"\n", result);
1337 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
1339 int lprocfs_rd_kbytesfree(char *page, char **start, off_t off, int count,
1340 int *eof, void *data)
1342 struct obd_device *obd = data;
1343 struct obd_statfs osfs;
1344 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
1345 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
1346 OBD_STATFS_NODELAY);
1348 __u32 blk_size = osfs.os_bsize >> 10;
1349 __u64 result = osfs.os_bfree;
1351 while (blk_size >>= 1)
1355 rc = snprintf(page, count, LPU64"\n", result);
1359 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
1361 int lprocfs_rd_kbytesavail(char *page, char **start, off_t off, int count,
1362 int *eof, void *data)
1364 struct obd_device *obd = data;
1365 struct obd_statfs osfs;
1366 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
1367 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
1368 OBD_STATFS_NODELAY);
1370 __u32 blk_size = osfs.os_bsize >> 10;
1371 __u64 result = osfs.os_bavail;
1373 while (blk_size >>= 1)
1377 rc = snprintf(page, count, LPU64"\n", result);
1381 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
1383 int lprocfs_rd_filestotal(char *page, char **start, off_t off, int count,
1384 int *eof, void *data)
1386 struct obd_device *obd = data;
1387 struct obd_statfs osfs;
1388 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
1389 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
1390 OBD_STATFS_NODELAY);
1393 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
1398 EXPORT_SYMBOL(lprocfs_rd_filestotal);
1400 int lprocfs_rd_filesfree(char *page, char **start, off_t off, int count,
1401 int *eof, void *data)
1403 struct obd_device *obd = data;
1404 struct obd_statfs osfs;
1405 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
1406 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
1407 OBD_STATFS_NODELAY);
1410 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
1414 EXPORT_SYMBOL(lprocfs_rd_filesfree);
1416 int lprocfs_rd_server_uuid(char *page, char **start, off_t off, int count,
1417 int *eof, void *data)
1419 struct obd_device *obd = data;
1420 struct obd_import *imp;
1421 char *imp_state_name = NULL;
1424 LASSERT(obd != NULL);
1425 LPROCFS_CLIMP_CHECK(obd);
1426 imp = obd->u.cli.cl_import;
1427 imp_state_name = ptlrpc_import_state_name(imp->imp_state);
1429 rc = snprintf(page, count, "%s\t%s%s\n",
1430 obd2cli_tgt(obd), imp_state_name,
1431 imp->imp_deactive ? "\tDEACTIVATED" : "");
1433 LPROCFS_CLIMP_EXIT(obd);
1436 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
1438 int lprocfs_rd_conn_uuid(char *page, char **start, off_t off, int count,
1439 int *eof, void *data)
1441 struct obd_device *obd = data;
1442 struct ptlrpc_connection *conn;
1445 LASSERT(obd != NULL);
1447 LPROCFS_CLIMP_CHECK(obd);
1448 conn = obd->u.cli.cl_import->imp_connection;
1450 if (conn && obd->u.cli.cl_import) {
1451 rc = snprintf(page, count, "%s\n",
1452 conn->c_remote_uuid.uuid);
1454 rc = snprintf(page, count, "%s\n", "<none>");
1457 LPROCFS_CLIMP_EXIT(obd);
1460 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
1463 * Append a space separated list of current set flags to str.
1465 #define flag2str(flag) \
1466 if (imp->imp_##flag && max - len > 0) \
1467 len += snprintf(str + len, max - len, "%s" #flag, len ? ", " : "");
1468 static int obd_import_flags2str(struct obd_import *imp, char *str, int max)
1472 if (imp->imp_obd->obd_no_recov)
1473 len += snprintf(str, max - len, "no_recov");
1477 flag2str(replayable);
1483 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
1484 int *eof, void *data)
1486 struct lprocfs_counter ret;
1487 struct lprocfs_counter_header *header;
1488 struct obd_device *obd = (struct obd_device *)data;
1489 struct obd_import *imp;
1490 struct obd_import_conn *conn;
1496 LASSERT(obd != NULL);
1497 LPROCFS_CLIMP_CHECK(obd);
1498 imp = obd->u.cli.cl_import;
1501 i = snprintf(page, count,
1507 " connect_flags: [",
1510 ptlrpc_import_state_name(imp->imp_state),
1511 imp->imp_connect_data.ocd_instance);
1512 i += obd_connect_flags2str(page + i, count - i,
1513 imp->imp_connect_data.ocd_connect_flags,
1515 i += snprintf(page + i, count - i,
1517 " import_flags: [");
1518 i += obd_import_flags2str(imp, page + i, count - i);
1520 i += snprintf(page + i, count - i,
1523 " failover_nids: [");
1524 spin_lock(&imp->imp_lock);
1526 cfs_list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
1527 i += snprintf(page + i, count - i, "%s%s", j ? ", " : "",
1528 libcfs_nid2str(conn->oic_conn->c_peer.nid));
1531 i += snprintf(page + i, count - i,
1533 " current_connection: %s\n"
1534 " connection_attempts: %u\n"
1536 " in-progress_invalidations: %u\n",
1537 imp->imp_connection == NULL ? "<none>" :
1538 libcfs_nid2str(imp->imp_connection->c_peer.nid),
1540 imp->imp_generation,
1541 cfs_atomic_read(&imp->imp_inval_count));
1542 spin_unlock(&imp->imp_lock);
1544 if (obd->obd_svc_stats == NULL)
1547 header = &obd->obd_svc_stats->ls_cnt_header[PTLRPC_REQWAIT_CNTR];
1548 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
1549 if (ret.lc_count != 0) {
1550 /* first argument to do_div MUST be __u64 */
1551 __u64 sum = ret.lc_sum;
1552 do_div(sum, ret.lc_count);
1556 i += snprintf(page + i, count - i,
1559 " unregistering: %u\n"
1561 " avg_waittime: "LPU64" %s\n",
1562 cfs_atomic_read(&imp->imp_inflight),
1563 cfs_atomic_read(&imp->imp_unregistering),
1564 cfs_atomic_read(&imp->imp_timeouts),
1565 ret.lc_sum, header->lc_units);
1568 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
1569 if (imp->imp_at.iat_portal[j] == 0)
1571 k = max_t(unsigned int, k,
1572 at_get(&imp->imp_at.iat_service_estimate[j]));
1574 i += snprintf(page + i, count - i,
1575 " service_estimates:\n"
1576 " services: %u sec\n"
1577 " network: %u sec\n",
1579 at_get(&imp->imp_at.iat_net_latency));
1581 i += snprintf(page + i, count - i,
1583 " last_replay: "LPU64"\n"
1584 " peer_committed: "LPU64"\n"
1585 " last_checked: "LPU64"\n",
1586 imp->imp_last_replay_transno,
1587 imp->imp_peer_committed_transno,
1588 imp->imp_last_transno_checked);
1590 /* avg data rates */
1591 for (rw = 0; rw <= 1; rw++) {
1592 lprocfs_stats_collect(obd->obd_svc_stats,
1593 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
1595 if (ret.lc_sum > 0 && ret.lc_count > 0) {
1596 /* first argument to do_div MUST be __u64 */
1597 __u64 sum = ret.lc_sum;
1598 do_div(sum, ret.lc_count);
1600 i += snprintf(page + i, count - i,
1601 " %s_data_averages:\n"
1602 " bytes_per_rpc: "LPU64"\n",
1603 rw ? "write" : "read",
1606 k = (int)ret.lc_sum;
1607 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
1608 header = &obd->obd_svc_stats->ls_cnt_header[j];
1609 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
1610 if (ret.lc_sum > 0 && ret.lc_count != 0) {
1611 /* first argument to do_div MUST be __u64 */
1612 __u64 sum = ret.lc_sum;
1613 do_div(sum, ret.lc_count);
1615 i += snprintf(page + i, count - i,
1616 " %s_per_rpc: "LPU64"\n",
1617 header->lc_units, ret.lc_sum);
1618 j = (int)ret.lc_sum;
1620 i += snprintf(page + i, count - i,
1621 " MB_per_sec: %u.%.02u\n",
1622 k / j, (100 * k / j) % 100);
1627 LPROCFS_CLIMP_EXIT(obd);
1630 EXPORT_SYMBOL(lprocfs_rd_import);
1632 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
1633 int *eof, void *data)
1635 struct obd_device *obd = (struct obd_device *)data;
1636 struct obd_import *imp;
1639 LASSERT(obd != NULL);
1640 LPROCFS_CLIMP_CHECK(obd);
1641 imp = obd->u.cli.cl_import;
1644 i = snprintf(page, count, "current_state: %s\n",
1645 ptlrpc_import_state_name(imp->imp_state));
1646 i += snprintf(page + i, count - i,
1647 "state_history:\n");
1648 k = imp->imp_state_hist_idx;
1649 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
1650 struct import_state_hist *ish =
1651 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
1652 if (ish->ish_state == 0)
1654 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
1656 ptlrpc_import_state_name(ish->ish_state));
1659 LPROCFS_CLIMP_EXIT(obd);
1662 EXPORT_SYMBOL(lprocfs_rd_state);
1664 int lprocfs_at_hist_helper(char *page, int count, int rc,
1665 struct adaptive_timeout *at)
1668 for (i = 0; i < AT_BINS; i++)
1669 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
1670 rc += snprintf(page + rc, count - rc, "\n");
1673 EXPORT_SYMBOL(lprocfs_at_hist_helper);
1675 /* See also ptlrpc_lprocfs_rd_timeouts */
1676 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
1677 int *eof, void *data)
1679 struct obd_device *obd = (struct obd_device *)data;
1680 struct obd_import *imp;
1681 unsigned int cur, worst;
1686 LASSERT(obd != NULL);
1687 LPROCFS_CLIMP_CHECK(obd);
1688 imp = obd->u.cli.cl_import;
1691 now = cfs_time_current_sec();
1693 /* Some network health info for kicks */
1694 s2dhms(&ts, now - imp->imp_last_reply_time);
1695 rc += snprintf(page + rc, count - rc,
1696 "%-10s : %ld, "DHMS_FMT" ago\n",
1697 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
1699 cur = at_get(&imp->imp_at.iat_net_latency);
1700 worst = imp->imp_at.iat_net_latency.at_worst_ever;
1701 worstt = imp->imp_at.iat_net_latency.at_worst_time;
1702 s2dhms(&ts, now - worstt);
1703 rc += snprintf(page + rc, count - rc,
1704 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
1705 "network", cur, worst, worstt, DHMS_VARS(&ts));
1706 rc = lprocfs_at_hist_helper(page, count, rc,
1707 &imp->imp_at.iat_net_latency);
1709 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
1710 if (imp->imp_at.iat_portal[i] == 0)
1712 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
1713 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
1714 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
1715 s2dhms(&ts, now - worstt);
1716 rc += snprintf(page + rc, count - rc,
1717 "portal %-2d : cur %3u worst %3u (at %ld, "
1718 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
1719 cur, worst, worstt, DHMS_VARS(&ts));
1720 rc = lprocfs_at_hist_helper(page, count, rc,
1721 &imp->imp_at.iat_service_estimate[i]);
1724 LPROCFS_CLIMP_EXIT(obd);
1727 EXPORT_SYMBOL(lprocfs_rd_timeouts);
1729 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1730 int count, int *eof, void *data)
1732 struct obd_device *obd = data;
1736 LPROCFS_CLIMP_CHECK(obd);
1737 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1738 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1739 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1740 ret += snprintf(page + ret, count - ret, "\n");
1741 LPROCFS_CLIMP_EXIT(obd);
1744 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1746 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1747 int *eof, void *data)
1749 struct obd_device *obd = data;
1751 LASSERT(obd != NULL);
1753 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1755 EXPORT_SYMBOL(lprocfs_rd_num_exports);
1757 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1758 int *eof, void *data)
1760 struct obd_type *class = (struct obd_type*) data;
1762 LASSERT(class != NULL);
1764 return snprintf(page, count, "%d\n", class->typ_refcnt);
1766 EXPORT_SYMBOL(lprocfs_rd_numrefs);
1768 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1772 LASSERT(obd != NULL);
1773 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1774 LASSERT(obd->obd_type->typ_procroot != NULL);
1776 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1777 obd->obd_type->typ_procroot,
1779 if (IS_ERR(obd->obd_proc_entry)) {
1780 rc = PTR_ERR(obd->obd_proc_entry);
1781 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1782 obd->obd_proc_entry = NULL;
1786 EXPORT_SYMBOL(lprocfs_obd_setup);
1790 lprocfs_seq_obd_setup(struct obd_device *obd)
1794 LASSERT(obd != NULL);
1795 LASSERT(obd->obd_vars != NULL);
1796 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1797 LASSERT(obd->obd_type->typ_procroot != NULL);
1799 obd->obd_proc_entry = lprocfs_seq_register(obd->obd_name,
1800 obd->obd_type->typ_procroot,
1801 obd->obd_vars, obd);
1802 if (IS_ERR(obd->obd_proc_entry)) {
1803 rc = PTR_ERR(obd->obd_proc_entry);
1804 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1805 obd->obd_proc_entry = NULL;
1809 EXPORT_SYMBOL(lprocfs_seq_obd_setup);
1811 int lprocfs_obd_cleanup(struct obd_device *obd)
1815 if (obd->obd_proc_exports_entry) {
1816 /* Should be no exports left */
1817 lprocfs_remove(&obd->obd_proc_exports_entry);
1818 obd->obd_proc_exports_entry = NULL;
1820 if (obd->obd_proc_entry) {
1821 lprocfs_remove(&obd->obd_proc_entry);
1822 obd->obd_proc_entry = NULL;
1826 EXPORT_SYMBOL(lprocfs_obd_cleanup);
1828 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1830 CDEBUG(D_CONFIG, "stat %p - data %p/%p\n", client_stat,
1831 client_stat->nid_proc, client_stat->nid_stats);
1833 LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
1834 "nid %s:count %d\n", libcfs_nid2str(client_stat->nid),
1835 atomic_read(&client_stat->nid_exp_ref_count));
1837 if (client_stat->nid_proc)
1838 lprocfs_remove(&client_stat->nid_proc);
1840 if (client_stat->nid_stats)
1841 lprocfs_free_stats(&client_stat->nid_stats);
1843 if (client_stat->nid_ldlm_stats)
1844 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1846 OBD_FREE_PTR(client_stat);
1851 void lprocfs_free_per_client_stats(struct obd_device *obd)
1853 cfs_hash_t *hash = obd->obd_nid_stats_hash;
1854 struct nid_stat *stat;
1857 /* we need extra list - because hash_exit called to early */
1858 /* not need locking because all clients is died */
1859 while (!cfs_list_empty(&obd->obd_nid_stats)) {
1860 stat = cfs_list_entry(obd->obd_nid_stats.next,
1861 struct nid_stat, nid_list);
1862 cfs_list_del_init(&stat->nid_list);
1863 cfs_hash_del(hash, &stat->nid, &stat->nid_hash);
1864 lprocfs_free_client_stats(stat);
1868 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
1870 int lprocfs_stats_alloc_one(struct lprocfs_stats *stats, unsigned int cpuid)
1872 struct lprocfs_counter *cntr;
1873 unsigned int percpusize;
1875 unsigned long flags = 0;
1878 LASSERT(stats->ls_percpu[cpuid] == NULL);
1879 LASSERT((stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU) == 0);
1881 percpusize = lprocfs_stats_counter_size(stats);
1882 LIBCFS_ALLOC_ATOMIC(stats->ls_percpu[cpuid], percpusize);
1883 if (stats->ls_percpu[cpuid] != NULL) {
1885 if (unlikely(stats->ls_biggest_alloc_num <= cpuid)) {
1886 if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
1887 spin_lock_irqsave(&stats->ls_lock, flags);
1889 spin_lock(&stats->ls_lock);
1890 if (stats->ls_biggest_alloc_num <= cpuid)
1891 stats->ls_biggest_alloc_num = cpuid + 1;
1892 if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) {
1893 spin_unlock_irqrestore(&stats->ls_lock, flags);
1895 spin_unlock(&stats->ls_lock);
1898 /* initialize the ls_percpu[cpuid] non-zero counter */
1899 for (i = 0; i < stats->ls_num; ++i) {
1900 cntr = lprocfs_stats_counter_get(stats, cpuid, i);
1901 cntr->lc_min = LC_MIN_INIT;
1906 EXPORT_SYMBOL(lprocfs_stats_alloc_one);
1908 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1909 enum lprocfs_stats_flags flags)
1911 struct lprocfs_stats *stats;
1912 unsigned int num_entry;
1913 unsigned int percpusize = 0;
1919 if (lprocfs_no_percpu_stats != 0)
1920 flags |= LPROCFS_STATS_FLAG_NOPERCPU;
1922 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1925 num_entry = num_possible_cpus();
1927 /* alloc percpu pointers for all possible cpu slots */
1928 LIBCFS_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1932 stats->ls_num = num;
1933 stats->ls_flags = flags;
1934 spin_lock_init(&stats->ls_lock);
1936 /* alloc num of counter headers */
1937 LIBCFS_ALLOC(stats->ls_cnt_header,
1938 stats->ls_num * sizeof(struct lprocfs_counter_header));
1939 if (stats->ls_cnt_header == NULL)
1942 if ((flags & LPROCFS_STATS_FLAG_NOPERCPU) != 0) {
1943 /* contains only one set counters */
1944 percpusize = lprocfs_stats_counter_size(stats);
1945 LIBCFS_ALLOC_ATOMIC(stats->ls_percpu[0], percpusize);
1946 if (stats->ls_percpu[0] == NULL)
1948 stats->ls_biggest_alloc_num = 1;
1949 } else if ((flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0) {
1950 /* alloc all percpu data, currently only obd_memory use this */
1951 for (i = 0; i < num_entry; ++i)
1952 if (lprocfs_stats_alloc_one(stats, i) < 0)
1959 lprocfs_free_stats(&stats);
1962 EXPORT_SYMBOL(lprocfs_alloc_stats);
1964 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1966 struct lprocfs_stats *stats = *statsh;
1967 unsigned int num_entry;
1968 unsigned int percpusize;
1971 if (stats == NULL || stats->ls_num == 0)
1975 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1978 num_entry = num_possible_cpus();
1980 percpusize = lprocfs_stats_counter_size(stats);
1981 for (i = 0; i < num_entry; i++)
1982 if (stats->ls_percpu[i] != NULL)
1983 LIBCFS_FREE(stats->ls_percpu[i], percpusize);
1984 if (stats->ls_cnt_header != NULL)
1985 LIBCFS_FREE(stats->ls_cnt_header, stats->ls_num *
1986 sizeof(struct lprocfs_counter_header));
1987 LIBCFS_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1989 EXPORT_SYMBOL(lprocfs_free_stats);
1991 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1993 struct lprocfs_counter *percpu_cntr;
1996 unsigned int num_entry;
1997 unsigned long flags = 0;
1999 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
2001 for (i = 0; i < num_entry; i++) {
2002 if (stats->ls_percpu[i] == NULL)
2004 for (j = 0; j < stats->ls_num; j++) {
2005 percpu_cntr = lprocfs_stats_counter_get(stats, i, j);
2006 percpu_cntr->lc_count = 0;
2007 percpu_cntr->lc_min = LC_MIN_INIT;
2008 percpu_cntr->lc_max = 0;
2009 percpu_cntr->lc_sumsquare = 0;
2010 percpu_cntr->lc_sum = 0;
2011 if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
2012 percpu_cntr->lc_sum_irq = 0;
2016 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
2018 EXPORT_SYMBOL(lprocfs_clear_stats);
2020 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
2021 size_t len, loff_t *off)
2023 struct seq_file *seq = file->private_data;
2024 struct lprocfs_stats *stats = seq->private;
2026 lprocfs_clear_stats(stats);
2031 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
2033 struct lprocfs_stats *stats = p->private;
2035 return (*pos < stats->ls_num) ? pos : NULL;
2038 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
2042 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
2046 return lprocfs_stats_seq_start(p, pos);
2049 /* seq file export of one lprocfs counter */
2050 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
2052 struct lprocfs_stats *stats = p->private;
2053 struct lprocfs_counter_header *hdr;
2054 struct lprocfs_counter ctr;
2055 int idx = *(loff_t *)v;
2061 do_gettimeofday(&now);
2062 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
2063 "snapshot_time", now.tv_sec, now.tv_usec);
2068 hdr = &stats->ls_cnt_header[idx];
2069 lprocfs_stats_collect(stats, idx, &ctr);
2071 if (ctr.lc_count == 0)
2074 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", hdr->lc_name,
2075 ctr.lc_count, hdr->lc_units);
2079 if ((hdr->lc_config & LPROCFS_CNTR_AVGMINMAX) && ctr.lc_count > 0) {
2080 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
2081 ctr.lc_min, ctr.lc_max, ctr.lc_sum);
2084 if (hdr->lc_config & LPROCFS_CNTR_STDDEV)
2085 rc = seq_printf(p, " "LPD64, ctr.lc_sumsquare);
2089 rc = seq_printf(p, "\n");
2091 return (rc < 0) ? rc : 0;
2094 struct seq_operations lprocfs_stats_seq_sops = {
2095 .start = lprocfs_stats_seq_start,
2096 .stop = lprocfs_stats_seq_stop,
2097 .next = lprocfs_stats_seq_next,
2098 .show = lprocfs_stats_seq_show,
2101 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
2103 struct seq_file *seq;
2106 #ifndef HAVE_ONLY_PROCFS_SEQ
2107 if (LPROCFS_ENTRY_CHECK(PDE(inode)))
2110 rc = seq_open(file, &lprocfs_stats_seq_sops);
2113 seq = file->private_data;
2114 seq->private = PDE_DATA(inode);
2118 struct file_operations lprocfs_stats_seq_fops = {
2119 .owner = THIS_MODULE,
2120 .open = lprocfs_stats_seq_open,
2122 .write = lprocfs_stats_seq_write,
2123 .llseek = seq_lseek,
2124 .release = lprocfs_seq_release,
2127 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
2128 struct lprocfs_stats *stats)
2130 struct proc_dir_entry *entry;
2131 LASSERT(root != NULL);
2133 entry = proc_create_data(name, 0644, root,
2134 &lprocfs_stats_seq_fops, stats);
2139 EXPORT_SYMBOL(lprocfs_register_stats);
2141 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
2142 unsigned conf, const char *name, const char *units)
2144 struct lprocfs_counter_header *header;
2145 struct lprocfs_counter *percpu_cntr;
2146 unsigned long flags = 0;
2148 unsigned int num_cpu;
2150 LASSERT(stats != NULL);
2152 header = &stats->ls_cnt_header[index];
2153 LASSERTF(header != NULL, "Failed to allocate stats header:[%d]%s/%s\n",
2154 index, name, units);
2156 header->lc_config = conf;
2157 header->lc_name = name;
2158 header->lc_units = units;
2160 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
2161 for (i = 0; i < num_cpu; ++i) {
2162 if (stats->ls_percpu[i] == NULL)
2164 percpu_cntr = lprocfs_stats_counter_get(stats, i, index);
2165 percpu_cntr->lc_count = 0;
2166 percpu_cntr->lc_min = LC_MIN_INIT;
2167 percpu_cntr->lc_max = 0;
2168 percpu_cntr->lc_sumsquare = 0;
2169 percpu_cntr->lc_sum = 0;
2170 if ((stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
2171 percpu_cntr->lc_sum_irq = 0;
2173 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
2175 EXPORT_SYMBOL(lprocfs_counter_init);
2177 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
2179 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
2180 LASSERT(coffset < stats->ls_num); \
2181 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
2184 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
2186 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
2187 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
2188 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
2189 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
2190 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
2191 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
2192 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
2193 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
2194 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
2195 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
2196 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
2197 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
2198 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
2199 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
2200 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
2201 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
2202 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
2203 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
2204 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
2205 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
2206 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
2207 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
2208 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
2209 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
2210 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
2211 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
2212 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
2213 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
2214 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
2215 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
2216 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
2217 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
2218 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
2219 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
2220 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
2221 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
2222 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
2223 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
2224 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
2225 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
2226 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
2227 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
2228 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
2229 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
2230 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
2231 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
2232 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
2233 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
2234 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
2235 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
2236 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
2237 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
2238 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
2239 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
2240 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
2241 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
2242 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
2243 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
2244 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
2245 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
2246 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
2247 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
2248 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
2249 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
2250 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
2251 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
2252 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
2254 CLASSERT(NUM_OBD_STATS == OBD_COUNTER_OFFSET(putref) + 1);
2256 EXPORT_SYMBOL(lprocfs_init_ops_stats);
2258 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
2260 struct lprocfs_stats *stats;
2261 unsigned int num_stats;
2264 LASSERT(obd->obd_stats == NULL);
2265 LASSERT(obd->obd_proc_entry != NULL);
2266 LASSERT(obd->obd_cntr_base == 0);
2268 num_stats = NUM_OBD_STATS + num_private_stats;
2269 stats = lprocfs_alloc_stats(num_stats, 0);
2273 lprocfs_init_ops_stats(num_private_stats, stats);
2275 for (i = num_private_stats; i < num_stats; i++) {
2276 /* If this LBUGs, it is likely that an obd
2277 * operation was added to struct obd_ops in
2278 * <obd.h>, and that the corresponding line item
2279 * LPROCFS_OBD_OP_INIT(.., .., opname)
2280 * is missing from the list above. */
2281 LASSERTF(stats->ls_cnt_header[i].lc_name != NULL,
2282 "Missing obd_stat initializer obd_op "
2283 "operation at offset %d.\n", i - num_private_stats);
2285 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
2287 lprocfs_free_stats(&stats);
2289 obd->obd_stats = stats;
2290 obd->obd_cntr_base = num_private_stats;
2294 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
2296 void lprocfs_free_obd_stats(struct obd_device *obd)
2299 lprocfs_free_stats(&obd->obd_stats);
2301 EXPORT_SYMBOL(lprocfs_free_obd_stats);
2303 /* Note that we only init md counters for ops whose offset is less
2304 * than NUM_MD_STATS. This is explained in a comment in the definition
2305 * of struct md_ops. */
2306 #define LPROCFS_MD_OP_INIT(base, stats, op) \
2308 unsigned int _idx = base + MD_COUNTER_OFFSET(op); \
2310 if (MD_COUNTER_OFFSET(op) < NUM_MD_STATS) { \
2311 LASSERT(_idx < stats->ls_num); \
2312 lprocfs_counter_init(stats, _idx, 0, #op, "reqs"); \
2316 void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats)
2318 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
2319 LPROCFS_MD_OP_INIT(num_private_stats, stats, null_inode);
2320 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
2321 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
2322 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
2323 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
2324 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
2325 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
2326 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
2327 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
2328 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
2329 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
2330 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
2331 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
2332 LPROCFS_MD_OP_INIT(num_private_stats, stats, fsync);
2333 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
2334 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
2335 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
2336 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
2337 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
2338 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
2339 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
2340 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
2341 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
2342 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
2343 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
2344 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
2345 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
2346 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
2347 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
2348 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
2349 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
2351 EXPORT_SYMBOL(lprocfs_init_mps_stats);
2353 int lprocfs_alloc_md_stats(struct obd_device *obd,
2354 unsigned int num_private_stats)
2356 struct lprocfs_stats *stats;
2357 unsigned int num_stats;
2360 CLASSERT(offsetof(struct md_ops, MD_STATS_FIRST_OP) == 0);
2361 CLASSERT(_MD_COUNTER_OFFSET(MD_STATS_FIRST_OP) == 0);
2362 CLASSERT(_MD_COUNTER_OFFSET(MD_STATS_LAST_OP) > 0);
2364 /* TODO Ensure that this function is only used where
2365 * appropriate by adding an assertion to the effect that
2366 * obd->obd_type->typ_md_ops is not NULL. We can't do this now
2367 * because mdt_procfs_init() uses this function to allocate
2368 * the stats backing /proc/fs/lustre/mdt/.../md_stats but the
2369 * mdt layer does not use the md_ops interface. This is
2370 * confusing and a waste of memory. See LU-2484.
2372 LASSERT(obd->obd_proc_entry != NULL);
2373 LASSERT(obd->obd_md_stats == NULL);
2374 LASSERT(obd->obd_md_cntr_base == 0);
2376 num_stats = NUM_MD_STATS + num_private_stats;
2377 stats = lprocfs_alloc_stats(num_stats, 0);
2381 lprocfs_init_mps_stats(num_private_stats, stats);
2383 for (i = num_private_stats; i < num_stats; i++) {
2384 if (stats->ls_cnt_header[i].lc_name == NULL) {
2385 CERROR("Missing md_stat initializer md_op "
2386 "operation at offset %d. Aborting.\n",
2387 i - num_private_stats);
2392 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
2394 lprocfs_free_stats(&stats);
2396 obd->obd_md_stats = stats;
2397 obd->obd_md_cntr_base = num_private_stats;
2402 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
2404 void lprocfs_free_md_stats(struct obd_device *obd)
2406 struct lprocfs_stats *stats = obd->obd_md_stats;
2408 if (stats != NULL) {
2409 obd->obd_md_stats = NULL;
2410 obd->obd_md_cntr_base = 0;
2411 lprocfs_free_stats(&stats);
2414 EXPORT_SYMBOL(lprocfs_free_md_stats);
2416 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
2418 lprocfs_counter_init(ldlm_stats,
2419 LDLM_ENQUEUE - LDLM_FIRST_OPC,
2420 0, "ldlm_enqueue", "reqs");
2421 lprocfs_counter_init(ldlm_stats,
2422 LDLM_CONVERT - LDLM_FIRST_OPC,
2423 0, "ldlm_convert", "reqs");
2424 lprocfs_counter_init(ldlm_stats,
2425 LDLM_CANCEL - LDLM_FIRST_OPC,
2426 0, "ldlm_cancel", "reqs");
2427 lprocfs_counter_init(ldlm_stats,
2428 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
2429 0, "ldlm_bl_callback", "reqs");
2430 lprocfs_counter_init(ldlm_stats,
2431 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
2432 0, "ldlm_cp_callback", "reqs");
2433 lprocfs_counter_init(ldlm_stats,
2434 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
2435 0, "ldlm_gl_callback", "reqs");
2437 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
2439 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
2440 int *eof, void *data)
2442 struct obd_export *exp = data;
2443 LASSERT(exp != NULL);
2445 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
2448 struct exp_uuid_cb_data {
2456 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
2457 int count, int *eof, int *len)
2459 cb_data->page = page;
2460 cb_data->count = count;
2465 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
2466 cfs_hlist_node_t *hnode, void *cb_data)
2469 struct obd_export *exp = cfs_hash_object(hs, hnode);
2470 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
2472 if (exp->exp_nid_stats)
2473 *data->len += snprintf((data->page + *data->len),
2474 data->count, "%s\n",
2475 obd_uuid2str(&exp->exp_client_uuid));
2479 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
2480 int *eof, void *data)
2482 struct nid_stat *stats = (struct nid_stat *)data;
2483 struct exp_uuid_cb_data cb_data;
2484 struct obd_device *obd = stats->nid_obd;
2489 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
2490 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
2491 lprocfs_exp_print_uuid, &cb_data);
2492 return (*cb_data.len);
2495 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
2496 cfs_hlist_node_t *hnode, void *cb_data)
2499 struct exp_uuid_cb_data *data = cb_data;
2500 struct obd_export *exp = cfs_hash_object(hs, hnode);
2502 if (exp->exp_lock_hash != NULL) {
2504 *data->len += cfs_hash_debug_header(data->page,
2507 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
2514 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
2515 int *eof, void *data)
2517 struct nid_stat *stats = (struct nid_stat *)data;
2518 struct exp_uuid_cb_data cb_data;
2519 struct obd_device *obd = stats->nid_obd;
2524 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
2526 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
2527 lprocfs_exp_print_hash, &cb_data);
2528 return (*cb_data.len);
2531 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
2532 int count, int *eof, void *data)
2535 return snprintf(page, count, "%s\n",
2536 "Write into this file to clear all nid stats and "
2537 "stale nid entries");
2539 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
2541 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
2543 struct nid_stat *stat = obj;
2546 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
2547 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 1) {
2548 /* object has only hash references. */
2549 spin_lock(&stat->nid_obd->obd_nid_lock);
2550 cfs_list_move(&stat->nid_list, data);
2551 spin_unlock(&stat->nid_obd->obd_nid_lock);
2554 /* we has reference to object - only clear data*/
2555 if (stat->nid_stats)
2556 lprocfs_clear_stats(stat->nid_stats);
2561 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
2562 unsigned long count, void *data)
2564 struct obd_device *obd = (struct obd_device *)data;
2565 struct nid_stat *client_stat;
2566 CFS_LIST_HEAD(free_list);
2568 cfs_hash_cond_del(obd->obd_nid_stats_hash,
2569 lprocfs_nid_stats_clear_write_cb, &free_list);
2571 while (!cfs_list_empty(&free_list)) {
2572 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
2574 cfs_list_del_init(&client_stat->nid_list);
2575 lprocfs_free_client_stats(client_stat);
2580 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
2582 #ifdef HAVE_SERVER_SUPPORT
2583 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
2585 struct nid_stat *new_stat, *old_stat;
2586 struct obd_device *obd = NULL;
2587 cfs_proc_dir_entry_t *entry;
2588 char *buffer = NULL;
2594 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
2595 !exp->exp_obd->obd_nid_stats_hash)
2598 /* not test against zero because eric say:
2599 * You may only test nid against another nid, or LNET_NID_ANY.
2600 * Anything else is nonsense.*/
2601 if (!nid || *nid == LNET_NID_ANY)
2604 spin_lock(&exp->exp_lock);
2605 if (exp->exp_nid_stats != NULL) {
2606 spin_unlock(&exp->exp_lock);
2609 spin_unlock(&exp->exp_lock);
2613 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
2615 OBD_ALLOC_PTR(new_stat);
2616 if (new_stat == NULL)
2619 new_stat->nid = *nid;
2620 new_stat->nid_obd = exp->exp_obd;
2621 /* we need set default refcount to 1 to balance obd_disconnect */
2622 cfs_atomic_set(&new_stat->nid_exp_ref_count, 1);
2624 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
2625 nid, &new_stat->nid_hash);
2626 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
2627 old_stat, libcfs_nid2str(*nid),
2628 cfs_atomic_read(&new_stat->nid_exp_ref_count));
2630 /* Return -EALREADY here so that we know that the /proc
2631 * entry already has been created */
2632 if (old_stat != new_stat) {
2633 nidstat_putref(old_stat);
2634 GOTO(destroy_new, rc = -EALREADY);
2636 /* not found - create */
2637 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
2639 GOTO(destroy_new, rc = -ENOMEM);
2641 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
2642 new_stat->nid_proc = lprocfs_register(buffer,
2643 obd->obd_proc_exports_entry,
2645 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
2647 if (IS_ERR(new_stat->nid_proc)) {
2648 rc = PTR_ERR(new_stat->nid_proc);
2649 new_stat->nid_proc = NULL;
2650 CERROR("%s: cannot create proc entry for export %s: rc = %d\n",
2651 obd->obd_name, libcfs_nid2str(*nid), rc);
2652 GOTO(destroy_new_ns, rc);
2655 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
2656 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
2657 if (IS_ERR(entry)) {
2658 CWARN("Error adding the NID stats file\n");
2659 rc = PTR_ERR(entry);
2660 GOTO(destroy_new_ns, rc);
2663 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
2664 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
2665 if (IS_ERR(entry)) {
2666 CWARN("Error adding the hash file\n");
2667 rc = PTR_ERR(entry);
2668 GOTO(destroy_new_ns, rc);
2671 spin_lock(&exp->exp_lock);
2672 exp->exp_nid_stats = new_stat;
2673 spin_unlock(&exp->exp_lock);
2675 /* protect competitive add to list, not need locking on destroy */
2676 spin_lock(&obd->obd_nid_lock);
2677 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
2678 spin_unlock(&obd->obd_nid_lock);
2683 if (new_stat->nid_proc != NULL)
2684 lprocfs_remove(&new_stat->nid_proc);
2685 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
2688 nidstat_putref(new_stat);
2689 OBD_FREE_PTR(new_stat);
2692 EXPORT_SYMBOL(lprocfs_exp_setup);
2695 int lprocfs_exp_cleanup(struct obd_export *exp)
2697 struct nid_stat *stat = exp->exp_nid_stats;
2699 if(!stat || !exp->exp_obd)
2702 nidstat_putref(exp->exp_nid_stats);
2703 exp->exp_nid_stats = NULL;
2707 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2709 __s64 lprocfs_read_helper(struct lprocfs_counter *lc,
2710 struct lprocfs_counter_header *header,
2711 enum lprocfs_stats_flags flags,
2712 enum lprocfs_fields_flags field)
2716 if (lc == NULL || header == NULL)
2720 case LPROCFS_FIELDS_FLAGS_CONFIG:
2721 ret = header->lc_config;
2723 case LPROCFS_FIELDS_FLAGS_SUM:
2725 if ((flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
2726 ret += lc->lc_sum_irq;
2728 case LPROCFS_FIELDS_FLAGS_MIN:
2731 case LPROCFS_FIELDS_FLAGS_MAX:
2734 case LPROCFS_FIELDS_FLAGS_AVG:
2735 ret = (lc->lc_max - lc->lc_min) / 2;
2737 case LPROCFS_FIELDS_FLAGS_SUMSQUARE:
2738 ret = lc->lc_sumsquare;
2740 case LPROCFS_FIELDS_FLAGS_COUNT:
2748 EXPORT_SYMBOL(lprocfs_read_helper);
2750 int lprocfs_write_helper(const char *buffer, unsigned long count,
2753 return lprocfs_write_frac_helper(buffer, count, val, 1);
2755 EXPORT_SYMBOL(lprocfs_write_helper);
2757 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
2760 char kernbuf[20], *end, *pbuf;
2762 if (count > (sizeof(kernbuf) - 1))
2765 if (copy_from_user(kernbuf, buffer, count))
2768 kernbuf[count] = '\0';
2775 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2779 if (end != NULL && *end == '.') {
2780 int temp_val, pow = 1;
2784 if (strlen(pbuf) > 5)
2785 pbuf[5] = '\0'; /*only allow 5bits fractional*/
2787 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2790 for (i = 0; i < (end - pbuf); i++)
2793 *val += temp_val / pow;
2798 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2800 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
2803 long decimal_val, frac_val;
2809 decimal_val = val / mult;
2810 prtn = snprintf(buffer, count, "%ld", decimal_val);
2811 frac_val = val % mult;
2813 if (prtn < (count - 4) && frac_val > 0) {
2815 int i, temp_mult = 1, frac_bits = 0;
2817 temp_frac = frac_val * 10;
2818 buffer[prtn++] = '.';
2819 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
2820 /* only reserved 2 bits fraction */
2821 buffer[prtn++] ='0';
2826 * Need to think these cases :
2827 * 1. #echo x.00 > /proc/xxx output result : x
2828 * 2. #echo x.0x > /proc/xxx output result : x.0x
2829 * 3. #echo x.x0 > /proc/xxx output result : x.x
2830 * 4. #echo x.xx > /proc/xxx output result : x.xx
2831 * Only reserved 2 bits fraction.
2833 for (i = 0; i < (5 - prtn); i++)
2836 frac_bits = min((int)count - prtn, 3 - frac_bits);
2837 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
2838 frac_val * temp_mult / mult);
2841 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
2843 if (buffer[prtn] == '.') {
2850 buffer[prtn++] ='\n';
2853 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2855 int lprocfs_seq_read_frac_helper(struct seq_file *m, long val, int mult)
2857 long decimal_val, frac_val;
2859 decimal_val = val / mult;
2860 seq_printf(m, "%ld", decimal_val);
2861 frac_val = val % mult;
2868 /* Three cases: x0, xx, 0x */
2869 if ((frac_val % 10) != 0)
2870 seq_printf(m, ".%ld", frac_val);
2872 seq_printf(m, ".%ld", frac_val / 10);
2875 seq_printf(m, "\n");
2878 EXPORT_SYMBOL(lprocfs_seq_read_frac_helper);
2880 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
2882 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
2884 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2886 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
2887 __u64 *val, int mult)
2889 char kernbuf[22], *end, *pbuf;
2890 __u64 whole, frac = 0, units;
2891 unsigned frac_d = 1;
2893 if (count > (sizeof(kernbuf) - 1))
2896 if (copy_from_user(kernbuf, buffer, count))
2899 kernbuf[count] = '\0';
2906 whole = simple_strtoull(pbuf, &end, 10);
2910 if (end != NULL && *end == '.') {
2914 /* need to limit frac_d to a __u32 */
2915 if (strlen(pbuf) > 10)
2918 frac = simple_strtoull(pbuf, &end, 10);
2919 /* count decimal places */
2920 for (i = 0; i < (end - pbuf); i++)
2939 /* Specified units override the multiplier */
2941 mult = mult < 0 ? -units : units;
2944 do_div(frac, frac_d);
2945 *val = whole * mult + frac;
2948 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2950 static char *lprocfs_strnstr(const char *s1, const char *s2, size_t len)
2959 if (!memcmp(s1, s2, l2))
2967 * Find the string \a name in the input \a buffer, and return a pointer to the
2968 * value immediately following \a name, reducing \a count appropriately.
2969 * If \a name is not found the original \a buffer is returned.
2971 char *lprocfs_find_named_value(const char *buffer, const char *name,
2975 size_t buflen = *count;
2977 /* there is no strnstr() in rhel5 and ubuntu kernels */
2978 val = lprocfs_strnstr(buffer, name, buflen);
2980 return (char *)buffer;
2982 val += strlen(name); /* skip prefix */
2983 while (val < buffer + buflen && isspace(*val)) /* skip separator */
2987 while (val < buffer + buflen && isalnum(*val)) {
2992 return val - *count;
2994 EXPORT_SYMBOL(lprocfs_find_named_value);
2996 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent,
2999 const struct file_operations *seq_fops,
3002 struct proc_dir_entry *entry;
3005 /* Disallow secretly (un)writable entries. */
3006 LASSERT((seq_fops->write == NULL) == ((mode & 0222) == 0));
3008 entry = proc_create_data(name, mode, parent, seq_fops, data);
3015 EXPORT_SYMBOL(lprocfs_seq_create);
3017 int lprocfs_obd_seq_create(struct obd_device *dev,
3020 const struct file_operations *seq_fops,
3023 return (lprocfs_seq_create(dev->obd_proc_entry, name,
3024 mode, seq_fops, data));
3026 EXPORT_SYMBOL(lprocfs_obd_seq_create);
3028 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
3030 if (value >= OBD_HIST_MAX)
3031 value = OBD_HIST_MAX - 1;
3033 spin_lock(&oh->oh_lock);
3034 oh->oh_buckets[value]++;
3035 spin_unlock(&oh->oh_lock);
3037 EXPORT_SYMBOL(lprocfs_oh_tally);
3039 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
3041 unsigned int val = 0;
3043 if (likely(value != 0))
3044 val = min(fls(value - 1), OBD_HIST_MAX);
3046 lprocfs_oh_tally(oh, val);
3048 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
3050 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
3052 unsigned long ret = 0;
3055 for (i = 0; i < OBD_HIST_MAX; i++)
3056 ret += oh->oh_buckets[i];
3059 EXPORT_SYMBOL(lprocfs_oh_sum);
3061 void lprocfs_oh_clear(struct obd_histogram *oh)
3063 spin_lock(&oh->oh_lock);
3064 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
3065 spin_unlock(&oh->oh_lock);
3067 EXPORT_SYMBOL(lprocfs_oh_clear);
3069 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
3070 int count, int *eof, void *data)
3072 struct obd_device *obd = data;
3078 c += cfs_hash_debug_header(page, count);
3079 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
3080 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
3081 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
3085 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
3087 #ifdef HAVE_SERVER_SUPPORT
3088 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
3089 int count, int *eof, void *data)
3091 struct obd_device *obd = data;
3094 LASSERT(obd != NULL);
3095 LASSERT(count >= 0);
3097 /* Set start of user data returned to
3098 page + off since the user may have
3099 requested to read much smaller than
3100 what we need to read */
3101 *start = page + off;
3104 * We know we are allocated a page here.
3105 * Also we know that this function will
3106 * not need to write more than a page
3107 * so we can truncate at PAGE_CACHE_SIZE.
3109 size = min(count + (int)off + 1, (int)PAGE_CACHE_SIZE);
3111 /* Initialize the page */
3112 memset(page, 0, size);
3114 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
3116 if (obd->obd_max_recoverable_clients == 0) {
3117 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
3123 /* sampled unlocked, but really... */
3124 if (obd->obd_recovering == 0) {
3125 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
3127 if (lprocfs_obd_snprintf(&page, size, &len,
3128 "recovery_start: %lu\n",
3129 obd->obd_recovery_start) <= 0)
3131 if (lprocfs_obd_snprintf(&page, size, &len,
3132 "recovery_duration: %lu\n",
3133 obd->obd_recovery_end -
3134 obd->obd_recovery_start) <= 0)
3136 /* Number of clients that have completed recovery */
3137 if (lprocfs_obd_snprintf(&page, size, &len,
3138 "completed_clients: %d/%d\n",
3139 obd->obd_max_recoverable_clients -
3140 obd->obd_stale_clients,
3141 obd->obd_max_recoverable_clients) <= 0)
3143 if (lprocfs_obd_snprintf(&page, size, &len,
3144 "replayed_requests: %d\n",
3145 obd->obd_replayed_requests) <= 0)
3147 if (lprocfs_obd_snprintf(&page, size, &len,
3148 "last_transno: "LPD64"\n",
3149 obd->obd_next_recovery_transno - 1)<=0)
3151 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
3152 obd->obd_version_recov ?
3153 "ENABLED" : "DISABLED") <=0)
3155 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
3157 "DISABLED" : "ENABLED") <= 0)
3162 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
3164 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
3165 obd->obd_recovery_start) <= 0)
3167 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
3168 cfs_time_current_sec() >=
3169 obd->obd_recovery_start +
3170 obd->obd_recovery_timeout ? 0 :
3171 obd->obd_recovery_start +
3172 obd->obd_recovery_timeout -
3173 cfs_time_current_sec()) <= 0)
3175 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
3176 cfs_atomic_read(&obd->obd_connected_clients),
3177 obd->obd_max_recoverable_clients) <= 0)
3179 /* Number of clients that have completed recovery */
3180 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
3181 cfs_atomic_read(&obd->obd_req_replay_clients))
3184 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
3185 cfs_atomic_read(&obd->obd_lock_replay_clients))
3188 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
3189 cfs_atomic_read(&obd->obd_connected_clients) -
3190 cfs_atomic_read(&obd->obd_lock_replay_clients))
3193 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
3194 obd->obd_stale_clients) <= 0)
3196 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
3197 obd->obd_replayed_requests) <= 0)
3199 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
3200 obd->obd_requests_queued_for_recovery) <= 0)
3203 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
3204 obd->obd_next_recovery_transno) <= 0)
3210 return min(count, len - (int)off);
3212 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
3215 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
3216 int count, int *eof, void *data)
3218 struct obd_device *obd = (struct obd_device *)data;
3219 LASSERT(obd != NULL);
3221 return snprintf(page, count, "%d\n",
3222 obd->obd_recovery_ir_factor);
3224 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
3226 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
3227 unsigned long count, void *data)
3229 struct obd_device *obd = (struct obd_device *)data;
3231 LASSERT(obd != NULL);
3233 rc = lprocfs_write_helper(buffer, count, &val);
3237 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
3240 obd->obd_recovery_ir_factor = val;
3243 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
3245 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
3246 int count, int *eof, void *data)
3248 struct obd_device *obd = (struct obd_device *)data;
3249 LASSERT(obd != NULL);
3251 return snprintf(page, count, "%d\n",
3252 obd->obd_recovery_timeout);
3254 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
3256 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
3257 unsigned long count, void *data)
3259 struct obd_device *obd = (struct obd_device *)data;
3261 LASSERT(obd != NULL);
3263 rc = lprocfs_write_helper(buffer, count, &val);
3267 obd->obd_recovery_timeout = val;
3270 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
3272 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
3273 int count, int *eof, void *data)
3275 struct obd_device *obd = data;
3276 LASSERT(obd != NULL);
3278 return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
3280 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
3282 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
3283 unsigned long count, void *data)
3285 struct obd_device *obd = data;
3287 LASSERT(obd != NULL);
3289 rc = lprocfs_write_helper(buffer, count, &val);
3293 obd->obd_recovery_time_hard = val;
3296 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
3298 int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
3299 int count, int *eof, void *data)
3301 struct obd_device *dev = data;
3302 struct client_obd *cli = &dev->u.cli;
3305 client_obd_list_lock(&cli->cl_loi_list_lock);
3306 rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
3307 client_obd_list_unlock(&cli->cl_loi_list_lock);
3310 EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
3312 int lprocfs_obd_max_pages_per_rpc_seq_show(struct seq_file *m, void *data)
3314 struct obd_device *dev = data;
3315 struct client_obd *cli = &dev->u.cli;
3318 client_obd_list_lock(&cli->cl_loi_list_lock);
3319 rc = seq_printf(m, "%d\n", cli->cl_max_pages_per_rpc);
3320 client_obd_list_unlock(&cli->cl_loi_list_lock);
3323 EXPORT_SYMBOL(lprocfs_obd_max_pages_per_rpc_seq_show);
3325 #ifdef HAVE_SERVER_SUPPORT
3326 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
3327 int count, int *eof, void *data)
3329 struct obd_device *obd = (struct obd_device *)data;
3330 struct obd_device_target *target = &obd->u.obt;
3332 LASSERT(obd != NULL);
3333 LASSERT(target->obt_magic == OBT_MAGIC);
3335 return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
3337 EXPORT_SYMBOL(lprocfs_target_rd_instance);