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 obd_device *obd = PDE_DATA(f->f_dentry->d_inode);
293 atomic_inc(&obd->obd_evict_inprogress);
297 int lprocfs_evict_client_release(struct inode *inode, struct file *f)
299 struct obd_device *obd = PDE_DATA(f->f_dentry->d_inode);
301 atomic_dec(&obd->obd_evict_inprogress);
302 wake_up(&obd->obd_evict_inprogress_waitq);
307 #define BUFLEN (UUID_MAX + 5)
309 #ifndef HAVE_ONLY_PROCFS_SEQ
310 int lprocfs_wr_evict_client(struct file *file, const char __user *buffer,
311 unsigned long count, void *data)
313 struct obd_device *obd = data;
317 OBD_ALLOC(kbuf, BUFLEN);
322 * OBD_ALLOC() will zero kbuf, but we only copy BUFLEN - 1
323 * bytes into kbuf, to ensure that the string is NUL-terminated.
324 * UUID_MAX should include a trailing NUL already.
326 if (copy_from_user(kbuf, buffer,
327 min_t(unsigned long, BUFLEN - 1, count))) {
331 tmpbuf = cfs_firststr(kbuf, min_t(unsigned long, BUFLEN - 1, count));
332 class_incref(obd, __FUNCTION__, current);
334 if (strncmp(tmpbuf, "nid:", 4) == 0)
335 obd_export_evict_by_nid(obd, tmpbuf + 4);
336 else if (strncmp(tmpbuf, "uuid:", 5) == 0)
337 obd_export_evict_by_uuid(obd, tmpbuf + 5);
339 obd_export_evict_by_uuid(obd, tmpbuf);
341 class_decref(obd, __FUNCTION__, current);
343 OBD_FREE(kbuf, BUFLEN);
346 EXPORT_SYMBOL(lprocfs_wr_evict_client);
350 lprocfs_evict_client_seq_write(struct file *file, const char *buffer,
351 size_t count, loff_t *off)
353 struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
356 OBD_ALLOC(kbuf, BUFLEN);
361 * OBD_ALLOC() will zero kbuf, but we only copy BUFLEN - 1
362 * bytes into kbuf, to ensure that the string is NUL-terminated.
363 * UUID_MAX should include a trailing NUL already.
365 if (copy_from_user(kbuf, buffer,
366 min_t(unsigned long, BUFLEN - 1, count))) {
370 tmpbuf = cfs_firststr(kbuf, min_t(unsigned long, BUFLEN - 1, count));
371 class_incref(obd, __FUNCTION__, current);
373 if (strncmp(tmpbuf, "nid:", 4) == 0)
374 obd_export_evict_by_nid(obd, tmpbuf + 4);
375 else if (strncmp(tmpbuf, "uuid:", 5) == 0)
376 obd_export_evict_by_uuid(obd, tmpbuf + 5);
378 obd_export_evict_by_uuid(obd, tmpbuf);
380 class_decref(obd, __FUNCTION__, current);
383 OBD_FREE(kbuf, BUFLEN);
386 EXPORT_SYMBOL(lprocfs_evict_client_seq_write);
390 struct file_operations lprocfs_evict_client_fops = {
391 .owner = THIS_MODULE,
392 .read = lprocfs_fops_read,
393 .write = lprocfs_fops_write,
394 .open = lprocfs_evict_client_open,
395 .release = lprocfs_evict_client_release,
397 EXPORT_SYMBOL(lprocfs_evict_client_fops);
400 #ifndef HAVE_ONLY_PROCFS_SEQ
401 static int __lprocfs_add_vars(struct proc_dir_entry *root,
402 struct lprocfs_vars *list,
407 if (root == NULL || list == NULL)
410 while (list->name != NULL) {
411 struct proc_dir_entry *cur_root, *proc;
412 char *pathcopy, *cur, *next, pathbuf[64];
413 int pathsize = strlen(list->name) + 1;
418 /* need copy of path for strsep */
419 if (strlen(list->name) > sizeof(pathbuf) - 1) {
420 OBD_ALLOC(pathcopy, pathsize);
421 if (pathcopy == NULL)
422 GOTO(out, rc = -ENOMEM);
428 strcpy(pathcopy, list->name);
430 while (cur_root != NULL && (cur = strsep(&next, "/"))) {
431 if (*cur =='\0') /* skip double/trailing "/" */
434 proc = __lprocfs_srch(cur_root, cur);
435 CDEBUG(D_OTHER, "cur_root=%s, cur=%s, next=%s, (%s)\n",
436 cur_root->name, cur, next,
437 (proc ? "exists" : "new"));
439 cur_root = (proc ? proc :
440 proc_mkdir(cur, cur_root));
441 } else if (proc == NULL) {
443 if (list->proc_mode != 0000) {
444 mode = list->proc_mode;
448 if (list->write_fptr)
451 proc = create_proc_entry(cur, mode, cur_root);
455 if (pathcopy != pathbuf)
456 OBD_FREE(pathcopy, pathsize);
458 if (cur_root == NULL || proc == NULL) {
459 CERROR("LprocFS: No memory to create /proc entry %s",
461 GOTO(out, rc = -ENOMEM);
465 proc->proc_fops = list->fops;
467 proc->proc_fops = &lprocfs_generic_fops;
468 proc->read_proc = list->read_fptr;
469 proc->write_proc = list->write_fptr;
470 proc->data = (list->data ? list->data : data);
477 int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list,
482 LPROCFS_WRITE_ENTRY();
483 rc = __lprocfs_add_vars(root, list, data);
484 LPROCFS_WRITE_EXIT();
488 EXPORT_SYMBOL(lprocfs_add_vars);
495 * \param root [in] The parent proc entry on which new entry will be added.
496 * \param list [in] Array of proc entries to be added.
497 * \param data [in] The argument to be passed when entries read/write routines
498 * are called through /proc file.
500 * \retval 0 on success
504 lprocfs_seq_add_vars(struct proc_dir_entry *root, struct lprocfs_seq_vars *list,
507 if (root == NULL || list == NULL)
510 while (list->name != NULL) {
511 struct proc_dir_entry *proc;
514 if (list->proc_mode != 0000) {
515 mode = list->proc_mode;
516 } else if (list->fops) {
517 if (list->fops->read)
519 if (list->fops->write)
522 proc = proc_create_data(list->name, mode, root,
523 list->fops ?: &lprocfs_generic_fops,
531 EXPORT_SYMBOL(lprocfs_seq_add_vars);
533 #ifndef HAVE_ONLY_PROCFS_SEQ
534 void lprocfs_remove_nolock(struct proc_dir_entry **proot)
536 struct proc_dir_entry *root = *proot;
537 struct proc_dir_entry *temp = root;
538 struct proc_dir_entry *rm_entry;
539 struct proc_dir_entry *parent;
542 if (root == NULL || IS_ERR(root))
545 parent = root->parent;
546 LASSERT(parent != NULL);
549 while (temp->subdir != NULL)
555 /* Memory corruption once caused this to fail, and
556 without this LASSERT we would loop here forever. */
557 LASSERTF(strlen(rm_entry->name) == rm_entry->namelen,
558 "0x%p %s/%s len %d\n", rm_entry, temp->name,
559 rm_entry->name, (int)strlen(rm_entry->name));
561 remove_proc_entry(rm_entry->name, temp);
568 void lprocfs_remove(struct proc_dir_entry **rooth)
570 #ifndef HAVE_ONLY_PROCFS_SEQ
571 LPROCFS_WRITE_ENTRY(); /* search vs remove race */
572 lprocfs_remove_nolock(rooth);
573 LPROCFS_WRITE_EXIT();
579 EXPORT_SYMBOL(lprocfs_remove);
581 void lprocfs_remove_proc_entry(const char *name, struct proc_dir_entry *parent)
583 LASSERT(parent != NULL);
584 remove_proc_entry(name, parent);
586 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
588 #ifndef HAVE_ONLY_PROCFS_SEQ
589 void lprocfs_try_remove_proc_entry(const char *name,
590 struct proc_dir_entry *parent)
592 struct proc_dir_entry *t = NULL;
593 struct proc_dir_entry **p;
596 LASSERT(parent != NULL);
599 LPROCFS_WRITE_ENTRY();
601 /* lookup target name */
602 for (p = &parent->subdir; *p; p = &(*p)->next) {
603 if ((*p)->namelen != len)
605 if (memcmp(name, (*p)->name, len))
612 /* verify it's empty: do not count "num_refs" */
613 for (p = &t->subdir; *p; p = &(*p)->next) {
614 if ((*p)->namelen != strlen("num_refs")) {
618 if (memcmp("num_refs", (*p)->name,
619 strlen("num_refs"))) {
627 lprocfs_remove_nolock(&t);
629 LPROCFS_WRITE_EXIT();
633 EXPORT_SYMBOL(lprocfs_try_remove_proc_entry);
635 struct proc_dir_entry *lprocfs_register(const char *name,
636 struct proc_dir_entry *parent,
637 struct lprocfs_vars *list, void *data)
639 struct proc_dir_entry *entry;
642 LPROCFS_WRITE_ENTRY();
643 entry = __lprocfs_srch(parent, name);
645 CERROR("entry '%s' already registered\n", name);
646 GOTO(out, entry = ERR_PTR(-EALREADY));
649 entry = proc_mkdir(name, parent);
651 GOTO(out, entry = ERR_PTR(-ENOMEM));
654 rc = __lprocfs_add_vars(entry, list, data);
656 lprocfs_remove_nolock(&entry);
657 GOTO(out, entry = ERR_PTR(rc));
661 LPROCFS_WRITE_EXIT();
664 EXPORT_SYMBOL(lprocfs_register);
667 struct proc_dir_entry *
668 lprocfs_seq_register(const char *name, struct proc_dir_entry *parent,
669 struct lprocfs_seq_vars *list, void *data)
671 struct proc_dir_entry *newchild;
673 newchild = proc_mkdir(name, parent);
674 if (newchild != NULL && list != NULL) {
675 int rc = lprocfs_seq_add_vars(newchild, list, data);
677 lprocfs_remove(&newchild);
683 EXPORT_SYMBOL(lprocfs_seq_register);
685 /* Generic callbacks */
686 int lprocfs_uint_seq_show(struct seq_file *m, void *data)
688 return seq_printf(m, "%u\n", *(unsigned int *)data);
690 EXPORT_SYMBOL(lprocfs_uint_seq_show);
692 int lprocfs_wr_uint(struct file *file, const char *buffer,
693 unsigned long count, void *data)
696 char dummy[MAX_STRING_SIZE + 1], *end;
699 dummy[MAX_STRING_SIZE] = '\0';
700 if (copy_from_user(dummy, buffer, MAX_STRING_SIZE))
703 tmp = simple_strtoul(dummy, &end, 0);
707 *p = (unsigned int)tmp;
710 EXPORT_SYMBOL(lprocfs_wr_uint);
712 ssize_t lprocfs_uint_seq_write(struct file *file, const char *buffer,
713 size_t count, loff_t *off)
715 int *data = ((struct seq_file *)file->private_data)->private;
718 rc = lprocfs_write_helper(buffer, count, &val);
722 return lprocfs_wr_uint(file, buffer, count, data);
724 EXPORT_SYMBOL(lprocfs_uint_seq_write);
726 int lprocfs_u64_seq_show(struct seq_file *m, void *data)
728 LASSERT(data != NULL);
729 return seq_printf(m, LPU64"\n", *(__u64 *)data);
731 EXPORT_SYMBOL(lprocfs_u64_seq_show);
733 int lprocfs_atomic_seq_show(struct seq_file *m, void *data)
735 atomic_t *atom = data;
736 LASSERT(atom != NULL);
737 return seq_printf(m, "%d\n", atomic_read(atom));
739 EXPORT_SYMBOL(lprocfs_atomic_seq_show);
742 lprocfs_atomic_seq_write(struct file *file, const char *buffer,
743 size_t count, loff_t *off)
745 atomic_t *atm = ((struct seq_file *)file->private_data)->private;
749 rc = lprocfs_write_helper(buffer, count, &val);
756 atomic_set(atm, val);
759 EXPORT_SYMBOL(lprocfs_atomic_seq_write);
761 int lprocfs_uuid_seq_show(struct seq_file *m, void *data)
763 struct obd_device *obd = data;
765 LASSERT(obd != NULL);
766 return seq_printf(m, "%s\n", obd->obd_uuid.uuid);
768 EXPORT_SYMBOL(lprocfs_uuid_seq_show);
770 int lprocfs_name_seq_show(struct seq_file *m, void *data)
772 struct obd_device *dev = data;
774 LASSERT(dev != NULL);
775 return seq_printf(m, "%s\n", dev->obd_name);
777 EXPORT_SYMBOL(lprocfs_name_seq_show);
779 int lprocfs_blksize_seq_show(struct seq_file *m, void *data)
781 struct obd_device *obd = data;
782 struct obd_statfs osfs;
783 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
784 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
787 rc = seq_printf(m, "%u\n", osfs.os_bsize);
790 EXPORT_SYMBOL(lprocfs_blksize_seq_show);
792 int lprocfs_kbytestotal_seq_show(struct seq_file *m, void *data)
794 struct obd_device *obd = data;
795 struct obd_statfs osfs;
796 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
797 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
800 __u32 blk_size = osfs.os_bsize >> 10;
801 __u64 result = osfs.os_blocks;
803 while (blk_size >>= 1)
806 rc = seq_printf(m, LPU64"\n", result);
810 EXPORT_SYMBOL(lprocfs_kbytestotal_seq_show);
812 int lprocfs_kbytesfree_seq_show(struct seq_file *m, void *data)
814 struct obd_device *obd = data;
815 struct obd_statfs osfs;
816 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
817 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
820 __u32 blk_size = osfs.os_bsize >> 10;
821 __u64 result = osfs.os_bfree;
823 while (blk_size >>= 1)
826 rc = seq_printf(m, LPU64"\n", result);
830 EXPORT_SYMBOL(lprocfs_kbytesfree_seq_show);
832 int lprocfs_kbytesavail_seq_show(struct seq_file *m, void *data)
834 struct obd_device *obd = data;
835 struct obd_statfs osfs;
836 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
837 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
840 __u32 blk_size = osfs.os_bsize >> 10;
841 __u64 result = osfs.os_bavail;
843 while (blk_size >>= 1)
846 rc = seq_printf(m, LPU64"\n", result);
850 EXPORT_SYMBOL(lprocfs_kbytesavail_seq_show);
852 int lprocfs_filestotal_seq_show(struct seq_file *m, void *data)
854 struct obd_device *obd = data;
855 struct obd_statfs osfs;
856 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
857 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
860 rc = seq_printf(m, LPU64"\n", osfs.os_files);
863 EXPORT_SYMBOL(lprocfs_filestotal_seq_show);
865 int lprocfs_filesfree_seq_show(struct seq_file *m, void *data)
867 struct obd_device *obd = data;
868 struct obd_statfs osfs;
869 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
870 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
873 rc = seq_printf(m, LPU64"\n", osfs.os_ffree);
876 EXPORT_SYMBOL(lprocfs_filesfree_seq_show);
878 int lprocfs_server_uuid_seq_show(struct seq_file *m, void *data)
880 struct obd_device *obd = data;
881 struct obd_import *imp;
882 char *imp_state_name = NULL;
885 LASSERT(obd != NULL);
886 LPROCFS_CLIMP_CHECK(obd);
887 imp = obd->u.cli.cl_import;
888 imp_state_name = ptlrpc_import_state_name(imp->imp_state);
889 rc = seq_printf(m, "%s\t%s%s\n", obd2cli_tgt(obd), imp_state_name,
890 imp->imp_deactive ? "\tDEACTIVATED" : "");
892 LPROCFS_CLIMP_EXIT(obd);
895 EXPORT_SYMBOL(lprocfs_server_uuid_seq_show);
897 int lprocfs_conn_uuid_seq_show(struct seq_file *m, void *data)
899 struct obd_device *obd = data;
900 struct ptlrpc_connection *conn;
903 LASSERT(obd != NULL);
905 LPROCFS_CLIMP_CHECK(obd);
906 conn = obd->u.cli.cl_import->imp_connection;
907 if (conn && obd->u.cli.cl_import)
908 rc = seq_printf(m, "%s\n", conn->c_remote_uuid.uuid);
910 rc = seq_printf(m, "%s\n", "<none>");
912 LPROCFS_CLIMP_EXIT(obd);
915 EXPORT_SYMBOL(lprocfs_conn_uuid_seq_show);
917 /** add up per-cpu counters */
918 void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
919 struct lprocfs_counter *cnt)
921 unsigned int num_entry;
922 struct lprocfs_counter *percpu_cntr;
924 unsigned long flags = 0;
926 memset(cnt, 0, sizeof(*cnt));
929 /* set count to 1 to avoid divide-by-zero errs in callers */
934 cnt->lc_min = LC_MIN_INIT;
936 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
938 for (i = 0; i < num_entry; i++) {
939 if (stats->ls_percpu[i] == NULL)
941 percpu_cntr = lprocfs_stats_counter_get(stats, i, idx);
943 cnt->lc_count += percpu_cntr->lc_count;
944 cnt->lc_sum += percpu_cntr->lc_sum;
945 if (percpu_cntr->lc_min < cnt->lc_min)
946 cnt->lc_min = percpu_cntr->lc_min;
947 if (percpu_cntr->lc_max > cnt->lc_max)
948 cnt->lc_max = percpu_cntr->lc_max;
949 cnt->lc_sumsquare += percpu_cntr->lc_sumsquare;
952 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
954 EXPORT_SYMBOL(lprocfs_stats_collect);
957 * Append a space separated list of current set flags to str.
959 #define flag2seqstr(flag) \
961 if (imp->imp_##flag) \
962 seq_printf(m, "%s" #flag, first ? "" : ", "); \
964 static int obd_import_flags2seqstr(struct obd_import *imp, struct seq_file *m)
968 if (imp->imp_obd->obd_no_recov) {
969 seq_printf(m, "no_recov");
973 flag2seqstr(invalid);
974 flag2seqstr(deactive);
975 flag2seqstr(replayable);
976 flag2seqstr(pingable);
981 static const char *obd_connect_names[] = {
995 "join_file(obsolete)",
999 "remote_client_by_force",
1004 "early_lock_cancel",
1006 "adaptive_timeouts",
1008 "mds_mds_connection",
1010 "change_qunit_size",
1011 "alt_checksum_algorithm",
1029 "nanoseconds_times",
1039 static void obd_connect_seq_flags2str(struct seq_file *m, __u64 flags, char *sep)
1045 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
1047 seq_printf(m, "%s%s",
1048 first ? "" : sep, obd_connect_names[i]);
1052 if (flags & ~(mask - 1))
1053 seq_printf(m, "%sunknown flags "LPX64,
1054 first ? "" : sep, flags & ~(mask - 1));
1057 int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
1062 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
1064 ret += snprintf(page + ret, count - ret, "%s%s",
1065 ret ? sep : "", obd_connect_names[i]);
1067 if (flags & ~(mask - 1))
1068 ret += snprintf(page + ret, count - ret,
1069 "%sunknown flags "LPX64,
1070 ret ? sep : "", flags & ~(mask - 1));
1073 EXPORT_SYMBOL(obd_connect_flags2str);
1075 static void obd_connect_data_seqprint(struct seq_file *m,
1076 struct obd_connect_data *ocd)
1080 LASSERT(ocd != NULL);
1081 flags = ocd->ocd_connect_flags;
1083 seq_printf(m, " connect_data:\n"
1086 ocd->ocd_connect_flags,
1088 if (flags & OBD_CONNECT_VERSION)
1089 seq_printf(m, " target_version: %u.%u.%u.%u\n",
1090 OBD_OCD_VERSION_MAJOR(ocd->ocd_version),
1091 OBD_OCD_VERSION_MINOR(ocd->ocd_version),
1092 OBD_OCD_VERSION_PATCH(ocd->ocd_version),
1093 OBD_OCD_VERSION_FIX(ocd->ocd_version));
1094 if (flags & OBD_CONNECT_MDS)
1095 seq_printf(m, " mdt_index: %d\n", ocd->ocd_group);
1096 if (flags & OBD_CONNECT_GRANT)
1097 seq_printf(m, " initial_grant: %d\n", ocd->ocd_grant);
1098 if (flags & OBD_CONNECT_INDEX)
1099 seq_printf(m, " target_index: %u\n", ocd->ocd_index);
1100 if (flags & OBD_CONNECT_BRW_SIZE)
1101 seq_printf(m, " max_brw_size: %d\n", ocd->ocd_brw_size);
1102 if (flags & OBD_CONNECT_IBITS)
1103 seq_printf(m, " ibits_known: "LPX64"\n",
1104 ocd->ocd_ibits_known);
1105 if (flags & OBD_CONNECT_GRANT_PARAM)
1106 seq_printf(m, " grant_block_size: %d\n"
1107 " grant_inode_size: %d\n"
1108 " grant_extent_overhead: %d\n",
1110 ocd->ocd_inodespace,
1111 ocd->ocd_grant_extent);
1112 if (flags & OBD_CONNECT_TRANSNO)
1113 seq_printf(m, " first_transno: "LPX64"\n",
1115 if (flags & OBD_CONNECT_CKSUM)
1116 seq_printf(m, " cksum_types: %#x\n",
1117 ocd->ocd_cksum_types);
1118 if (flags & OBD_CONNECT_MAX_EASIZE)
1119 seq_printf(m, " max_easize: %d\n", ocd->ocd_max_easize);
1120 if (flags & OBD_CONNECT_MAXBYTES)
1121 seq_printf(m, " max_object_bytes: "LPU64"\n",
1125 int lprocfs_import_seq_show(struct seq_file *m, void *data)
1127 struct lprocfs_counter ret;
1128 struct lprocfs_counter_header *header;
1129 struct obd_device *obd = (struct obd_device *)data;
1130 struct obd_import *imp;
1131 struct obd_import_conn *conn;
1132 struct obd_connect_data *ocd;
1137 LASSERT(obd != NULL);
1138 LPROCFS_CLIMP_CHECK(obd);
1139 imp = obd->u.cli.cl_import;
1140 ocd = &imp->imp_connect_data;
1142 seq_printf(m, "import:\n"
1146 " connect_flags: [",
1149 ptlrpc_import_state_name(imp->imp_state));
1150 obd_connect_seq_flags2str(m, imp->imp_connect_data.ocd_connect_flags,
1152 seq_printf(m, "]\n");
1153 obd_connect_data_seqprint(m, ocd);
1154 seq_printf(m, " import_flags: [");
1155 obd_import_flags2seqstr(imp, m);
1159 " failover_nids: [");
1160 spin_lock(&imp->imp_lock);
1162 list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
1163 seq_printf(m, "%s%s", j ? ", " : "",
1164 libcfs_nid2str(conn->oic_conn->c_peer.nid));
1168 " current_connection: %s\n"
1169 " connection_attempts: %u\n"
1171 " in-progress_invalidations: %u\n",
1172 imp->imp_connection == NULL ? "<none>" :
1173 libcfs_nid2str(imp->imp_connection->c_peer.nid),
1175 imp->imp_generation,
1176 atomic_read(&imp->imp_inval_count));
1177 spin_unlock(&imp->imp_lock);
1179 if (obd->obd_svc_stats == NULL)
1182 header = &obd->obd_svc_stats->ls_cnt_header[PTLRPC_REQWAIT_CNTR];
1183 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
1184 if (ret.lc_count != 0) {
1185 /* first argument to do_div MUST be __u64 */
1186 __u64 sum = ret.lc_sum;
1187 do_div(sum, ret.lc_count);
1191 seq_printf(m, " rpcs:\n"
1193 " unregistering: %u\n"
1195 " avg_waittime: "LPU64" %s\n",
1196 atomic_read(&imp->imp_inflight),
1197 atomic_read(&imp->imp_unregistering),
1198 atomic_read(&imp->imp_timeouts),
1199 ret.lc_sum, header->lc_units);
1202 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
1203 if (imp->imp_at.iat_portal[j] == 0)
1205 k = max_t(unsigned int, k,
1206 at_get(&imp->imp_at.iat_service_estimate[j]));
1208 seq_printf(m, " service_estimates:\n"
1209 " services: %u sec\n"
1210 " network: %u sec\n",
1212 at_get(&imp->imp_at.iat_net_latency));
1214 seq_printf(m, " transactions:\n"
1215 " last_replay: "LPU64"\n"
1216 " peer_committed: "LPU64"\n"
1217 " last_checked: "LPU64"\n",
1218 imp->imp_last_replay_transno,
1219 imp->imp_peer_committed_transno,
1220 imp->imp_last_transno_checked);
1222 /* avg data rates */
1223 for (rw = 0; rw <= 1; rw++) {
1224 lprocfs_stats_collect(obd->obd_svc_stats,
1225 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
1227 if (ret.lc_sum > 0 && ret.lc_count > 0) {
1228 /* first argument to do_div MUST be __u64 */
1229 __u64 sum = ret.lc_sum;
1230 do_div(sum, ret.lc_count);
1232 seq_printf(m, " %s_data_averages:\n"
1233 " bytes_per_rpc: "LPU64"\n",
1234 rw ? "write" : "read",
1237 k = (int)ret.lc_sum;
1238 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
1239 header = &obd->obd_svc_stats->ls_cnt_header[j];
1240 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
1241 if (ret.lc_sum > 0 && ret.lc_count != 0) {
1242 /* first argument to do_div MUST be __u64 */
1243 __u64 sum = ret.lc_sum;
1244 do_div(sum, ret.lc_count);
1246 seq_printf(m, " %s_per_rpc: "LPU64"\n",
1247 header->lc_units, ret.lc_sum);
1248 j = (int)ret.lc_sum;
1250 seq_printf(m, " MB_per_sec: %u.%.02u\n",
1251 k / j, (100 * k / j) % 100);
1256 LPROCFS_CLIMP_EXIT(obd);
1259 EXPORT_SYMBOL(lprocfs_import_seq_show);
1261 int lprocfs_state_seq_show(struct seq_file *m, void *data)
1263 struct obd_device *obd = (struct obd_device *)data;
1264 struct obd_import *imp;
1267 LASSERT(obd != NULL);
1268 LPROCFS_CLIMP_CHECK(obd);
1269 imp = obd->u.cli.cl_import;
1271 seq_printf(m, "current_state: %s\n",
1272 ptlrpc_import_state_name(imp->imp_state));
1273 seq_printf(m, "state_history:\n");
1274 k = imp->imp_state_hist_idx;
1275 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
1276 struct import_state_hist *ish =
1277 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
1278 if (ish->ish_state == 0)
1280 seq_printf(m, " - ["CFS_TIME_T", %s]\n",
1282 ptlrpc_import_state_name(ish->ish_state));
1285 LPROCFS_CLIMP_EXIT(obd);
1288 EXPORT_SYMBOL(lprocfs_state_seq_show);
1290 int lprocfs_seq_at_hist_helper(struct seq_file *m, struct adaptive_timeout *at)
1293 for (i = 0; i < AT_BINS; i++)
1294 seq_printf(m, "%3u ", at->at_hist[i]);
1295 seq_printf(m, "\n");
1298 EXPORT_SYMBOL(lprocfs_seq_at_hist_helper);
1300 /* See also ptlrpc_lprocfs_timeouts_show_seq */
1301 int lprocfs_timeouts_seq_show(struct seq_file *m, void *data)
1303 struct obd_device *obd = (struct obd_device *)data;
1304 struct obd_import *imp;
1305 unsigned int cur, worst;
1310 LASSERT(obd != NULL);
1311 LPROCFS_CLIMP_CHECK(obd);
1312 imp = obd->u.cli.cl_import;
1314 now = cfs_time_current_sec();
1316 /* Some network health info for kicks */
1317 s2dhms(&ts, now - imp->imp_last_reply_time);
1318 seq_printf(m, "%-10s : %ld, "DHMS_FMT" ago\n",
1319 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
1321 cur = at_get(&imp->imp_at.iat_net_latency);
1322 worst = imp->imp_at.iat_net_latency.at_worst_ever;
1323 worstt = imp->imp_at.iat_net_latency.at_worst_time;
1324 s2dhms(&ts, now - worstt);
1325 seq_printf(m, "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
1326 "network", cur, worst, worstt, DHMS_VARS(&ts));
1327 lprocfs_seq_at_hist_helper(m, &imp->imp_at.iat_net_latency);
1329 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
1330 if (imp->imp_at.iat_portal[i] == 0)
1332 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
1333 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
1334 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
1335 s2dhms(&ts, now - worstt);
1336 seq_printf(m, "portal %-2d : cur %3u worst %3u (at %ld, "
1337 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
1338 cur, worst, worstt, DHMS_VARS(&ts));
1339 lprocfs_seq_at_hist_helper(m, &imp->imp_at.iat_service_estimate[i]);
1342 LPROCFS_CLIMP_EXIT(obd);
1345 EXPORT_SYMBOL(lprocfs_timeouts_seq_show);
1347 int lprocfs_connect_flags_seq_show(struct seq_file *m, void *data)
1349 struct obd_device *obd = data;
1352 LPROCFS_CLIMP_CHECK(obd);
1353 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1354 seq_printf(m, "flags="LPX64"\n", flags);
1355 obd_connect_seq_flags2str(m, flags, "\n");
1356 seq_printf(m, "\n");
1357 LPROCFS_CLIMP_EXIT(obd);
1360 EXPORT_SYMBOL(lprocfs_connect_flags_seq_show);
1362 #ifdef HAVE_SERVER_SUPPORT
1363 int lprocfs_num_exports_seq_show(struct seq_file *m, void *data)
1365 struct obd_device *obd = data;
1367 LASSERT(obd != NULL);
1368 return seq_printf(m, "%u\n", obd->obd_num_exports);
1370 EXPORT_SYMBOL(lprocfs_num_exports_seq_show);
1373 #ifndef HAVE_ONLY_PROCFS_SEQ
1375 int lprocfs_rd_uint(char *page, char **start, off_t off,
1376 int count, int *eof, void *data)
1378 unsigned int *temp = data;
1379 return snprintf(page, count, "%u\n", *temp);
1381 EXPORT_SYMBOL(lprocfs_rd_uint);
1383 int lprocfs_rd_u64(char *page, char **start, off_t off,
1384 int count, int *eof, void *data)
1386 LASSERT(data != NULL);
1388 return snprintf(page, count, LPU64"\n", *(__u64 *)data);
1390 EXPORT_SYMBOL(lprocfs_rd_u64);
1392 int lprocfs_rd_atomic(char *page, char **start, off_t off,
1393 int count, int *eof, void *data)
1395 atomic_t *atom = data;
1396 LASSERT(atom != NULL);
1398 return snprintf(page, count, "%d\n", atomic_read(atom));
1400 EXPORT_SYMBOL(lprocfs_rd_atomic);
1402 int lprocfs_wr_atomic(struct file *file, const char *buffer,
1403 unsigned long count, void *data)
1405 atomic_t *atm = data;
1409 rc = lprocfs_write_helper(buffer, count, &val);
1416 atomic_set(atm, val);
1419 EXPORT_SYMBOL(lprocfs_wr_atomic);
1421 int lprocfs_rd_uuid(char *page, char **start, off_t off, int count,
1422 int *eof, void *data)
1424 struct obd_device *obd = data;
1426 LASSERT(obd != NULL);
1428 return snprintf(page, count, "%s\n", obd->obd_uuid.uuid);
1430 EXPORT_SYMBOL(lprocfs_rd_uuid);
1432 int lprocfs_rd_name(char *page, char **start, off_t off, int count,
1433 int *eof, void *data)
1435 struct obd_device *dev = data;
1437 LASSERT(dev != NULL);
1439 return snprintf(page, count, "%s\n", dev->obd_name);
1441 EXPORT_SYMBOL(lprocfs_rd_name);
1443 int lprocfs_rd_blksize(char *page, char **start, off_t off, int count,
1444 int *eof, void *data)
1446 struct obd_device *obd = data;
1447 struct obd_statfs osfs;
1448 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
1449 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
1450 OBD_STATFS_NODELAY);
1453 rc = snprintf(page, count, "%u\n", osfs.os_bsize);
1457 EXPORT_SYMBOL(lprocfs_rd_blksize);
1459 int lprocfs_rd_kbytestotal(char *page, char **start, off_t off, int count,
1460 int *eof, void *data)
1462 struct obd_device *obd = data;
1463 struct obd_statfs osfs;
1464 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
1465 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
1466 OBD_STATFS_NODELAY);
1468 __u32 blk_size = osfs.os_bsize >> 10;
1469 __u64 result = osfs.os_blocks;
1471 while (blk_size >>= 1)
1475 rc = snprintf(page, count, LPU64"\n", result);
1479 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
1481 int lprocfs_rd_kbytesfree(char *page, char **start, off_t off, int count,
1482 int *eof, void *data)
1484 struct obd_device *obd = data;
1485 struct obd_statfs osfs;
1486 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
1487 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
1488 OBD_STATFS_NODELAY);
1490 __u32 blk_size = osfs.os_bsize >> 10;
1491 __u64 result = osfs.os_bfree;
1493 while (blk_size >>= 1)
1497 rc = snprintf(page, count, LPU64"\n", result);
1501 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
1503 int lprocfs_rd_kbytesavail(char *page, char **start, off_t off, int count,
1504 int *eof, void *data)
1506 struct obd_device *obd = data;
1507 struct obd_statfs osfs;
1508 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
1509 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
1510 OBD_STATFS_NODELAY);
1512 __u32 blk_size = osfs.os_bsize >> 10;
1513 __u64 result = osfs.os_bavail;
1515 while (blk_size >>= 1)
1519 rc = snprintf(page, count, LPU64"\n", result);
1523 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
1525 int lprocfs_rd_filestotal(char *page, char **start, off_t off, int count,
1526 int *eof, void *data)
1528 struct obd_device *obd = data;
1529 struct obd_statfs osfs;
1530 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
1531 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
1532 OBD_STATFS_NODELAY);
1535 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
1540 EXPORT_SYMBOL(lprocfs_rd_filestotal);
1542 int lprocfs_rd_filesfree(char *page, char **start, off_t off, int count,
1543 int *eof, void *data)
1545 struct obd_device *obd = data;
1546 struct obd_statfs osfs;
1547 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
1548 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
1549 OBD_STATFS_NODELAY);
1552 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
1556 EXPORT_SYMBOL(lprocfs_rd_filesfree);
1558 int lprocfs_rd_server_uuid(char *page, char **start, off_t off, int count,
1559 int *eof, void *data)
1561 struct obd_device *obd = data;
1562 struct obd_import *imp;
1563 char *imp_state_name = NULL;
1566 LASSERT(obd != NULL);
1567 LPROCFS_CLIMP_CHECK(obd);
1568 imp = obd->u.cli.cl_import;
1569 imp_state_name = ptlrpc_import_state_name(imp->imp_state);
1571 rc = snprintf(page, count, "%s\t%s%s\n",
1572 obd2cli_tgt(obd), imp_state_name,
1573 imp->imp_deactive ? "\tDEACTIVATED" : "");
1575 LPROCFS_CLIMP_EXIT(obd);
1578 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
1580 int lprocfs_rd_conn_uuid(char *page, char **start, off_t off, int count,
1581 int *eof, void *data)
1583 struct obd_device *obd = data;
1584 struct ptlrpc_connection *conn;
1587 LASSERT(obd != NULL);
1589 LPROCFS_CLIMP_CHECK(obd);
1590 conn = obd->u.cli.cl_import->imp_connection;
1592 if (conn && obd->u.cli.cl_import) {
1593 rc = snprintf(page, count, "%s\n",
1594 conn->c_remote_uuid.uuid);
1596 rc = snprintf(page, count, "%s\n", "<none>");
1599 LPROCFS_CLIMP_EXIT(obd);
1602 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
1605 * Append a space separated list of current set flags to str.
1607 #define flag2str(flag) \
1608 if (imp->imp_##flag && max - len > 0) \
1609 len += snprintf(str + len, max - len, "%s" #flag, len ? ", " : "");
1610 static int obd_import_flags2str(struct obd_import *imp, char *str, int max)
1614 if (imp->imp_obd->obd_no_recov)
1615 len += snprintf(str, max - len, "no_recov");
1619 flag2str(replayable);
1625 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
1626 int *eof, void *data)
1628 struct lprocfs_counter ret;
1629 struct lprocfs_counter_header *header;
1630 struct obd_device *obd = (struct obd_device *)data;
1631 struct obd_import *imp;
1632 struct obd_import_conn *conn;
1638 LASSERT(obd != NULL);
1639 LPROCFS_CLIMP_CHECK(obd);
1640 imp = obd->u.cli.cl_import;
1643 i = snprintf(page, count,
1649 " connect_flags: [",
1652 ptlrpc_import_state_name(imp->imp_state),
1653 imp->imp_connect_data.ocd_instance);
1654 i += obd_connect_flags2str(page + i, count - i,
1655 imp->imp_connect_data.ocd_connect_flags,
1657 i += snprintf(page + i, count - i,
1659 " import_flags: [");
1660 i += obd_import_flags2str(imp, page + i, count - i);
1662 i += snprintf(page + i, count - i,
1665 " failover_nids: [");
1666 spin_lock(&imp->imp_lock);
1668 cfs_list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
1669 i += snprintf(page + i, count - i, "%s%s", j ? ", " : "",
1670 libcfs_nid2str(conn->oic_conn->c_peer.nid));
1673 i += snprintf(page + i, count - i,
1675 " current_connection: %s\n"
1676 " connection_attempts: %u\n"
1678 " in-progress_invalidations: %u\n",
1679 imp->imp_connection == NULL ? "<none>" :
1680 libcfs_nid2str(imp->imp_connection->c_peer.nid),
1682 imp->imp_generation,
1683 atomic_read(&imp->imp_inval_count));
1684 spin_unlock(&imp->imp_lock);
1686 if (obd->obd_svc_stats == NULL)
1689 header = &obd->obd_svc_stats->ls_cnt_header[PTLRPC_REQWAIT_CNTR];
1690 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
1691 if (ret.lc_count != 0) {
1692 /* first argument to do_div MUST be __u64 */
1693 __u64 sum = ret.lc_sum;
1694 do_div(sum, ret.lc_count);
1698 i += snprintf(page + i, count - i,
1701 " unregistering: %u\n"
1703 " avg_waittime: "LPU64" %s\n",
1704 atomic_read(&imp->imp_inflight),
1705 atomic_read(&imp->imp_unregistering),
1706 atomic_read(&imp->imp_timeouts),
1707 ret.lc_sum, header->lc_units);
1710 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
1711 if (imp->imp_at.iat_portal[j] == 0)
1713 k = max_t(unsigned int, k,
1714 at_get(&imp->imp_at.iat_service_estimate[j]));
1716 i += snprintf(page + i, count - i,
1717 " service_estimates:\n"
1718 " services: %u sec\n"
1719 " network: %u sec\n",
1721 at_get(&imp->imp_at.iat_net_latency));
1723 i += snprintf(page + i, count - i,
1725 " last_replay: "LPU64"\n"
1726 " peer_committed: "LPU64"\n"
1727 " last_checked: "LPU64"\n",
1728 imp->imp_last_replay_transno,
1729 imp->imp_peer_committed_transno,
1730 imp->imp_last_transno_checked);
1732 /* avg data rates */
1733 for (rw = 0; rw <= 1; rw++) {
1734 lprocfs_stats_collect(obd->obd_svc_stats,
1735 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
1737 if (ret.lc_sum > 0 && ret.lc_count > 0) {
1738 /* first argument to do_div MUST be __u64 */
1739 __u64 sum = ret.lc_sum;
1740 do_div(sum, ret.lc_count);
1742 i += snprintf(page + i, count - i,
1743 " %s_data_averages:\n"
1744 " bytes_per_rpc: "LPU64"\n",
1745 rw ? "write" : "read",
1748 k = (int)ret.lc_sum;
1749 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
1750 header = &obd->obd_svc_stats->ls_cnt_header[j];
1751 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
1752 if (ret.lc_sum > 0 && ret.lc_count != 0) {
1753 /* first argument to do_div MUST be __u64 */
1754 __u64 sum = ret.lc_sum;
1755 do_div(sum, ret.lc_count);
1757 i += snprintf(page + i, count - i,
1758 " %s_per_rpc: "LPU64"\n",
1759 header->lc_units, ret.lc_sum);
1760 j = (int)ret.lc_sum;
1762 i += snprintf(page + i, count - i,
1763 " MB_per_sec: %u.%.02u\n",
1764 k / j, (100 * k / j) % 100);
1769 LPROCFS_CLIMP_EXIT(obd);
1772 EXPORT_SYMBOL(lprocfs_rd_import);
1774 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
1775 int *eof, void *data)
1777 struct obd_device *obd = (struct obd_device *)data;
1778 struct obd_import *imp;
1781 LASSERT(obd != NULL);
1782 LPROCFS_CLIMP_CHECK(obd);
1783 imp = obd->u.cli.cl_import;
1786 i = snprintf(page, count, "current_state: %s\n",
1787 ptlrpc_import_state_name(imp->imp_state));
1788 i += snprintf(page + i, count - i,
1789 "state_history:\n");
1790 k = imp->imp_state_hist_idx;
1791 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
1792 struct import_state_hist *ish =
1793 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
1794 if (ish->ish_state == 0)
1796 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
1798 ptlrpc_import_state_name(ish->ish_state));
1801 LPROCFS_CLIMP_EXIT(obd);
1804 EXPORT_SYMBOL(lprocfs_rd_state);
1806 int lprocfs_at_hist_helper(char *page, int count, int rc,
1807 struct adaptive_timeout *at)
1810 for (i = 0; i < AT_BINS; i++)
1811 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
1812 rc += snprintf(page + rc, count - rc, "\n");
1815 EXPORT_SYMBOL(lprocfs_at_hist_helper);
1817 /* See also ptlrpc_lprocfs_rd_timeouts */
1818 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
1819 int *eof, void *data)
1821 struct obd_device *obd = (struct obd_device *)data;
1822 struct obd_import *imp;
1823 unsigned int cur, worst;
1828 LASSERT(obd != NULL);
1829 LPROCFS_CLIMP_CHECK(obd);
1830 imp = obd->u.cli.cl_import;
1833 now = cfs_time_current_sec();
1835 /* Some network health info for kicks */
1836 s2dhms(&ts, now - imp->imp_last_reply_time);
1837 rc += snprintf(page + rc, count - rc,
1838 "%-10s : %ld, "DHMS_FMT" ago\n",
1839 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
1841 cur = at_get(&imp->imp_at.iat_net_latency);
1842 worst = imp->imp_at.iat_net_latency.at_worst_ever;
1843 worstt = imp->imp_at.iat_net_latency.at_worst_time;
1844 s2dhms(&ts, now - worstt);
1845 rc += snprintf(page + rc, count - rc,
1846 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
1847 "network", cur, worst, worstt, DHMS_VARS(&ts));
1848 rc = lprocfs_at_hist_helper(page, count, rc,
1849 &imp->imp_at.iat_net_latency);
1851 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
1852 if (imp->imp_at.iat_portal[i] == 0)
1854 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
1855 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
1856 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
1857 s2dhms(&ts, now - worstt);
1858 rc += snprintf(page + rc, count - rc,
1859 "portal %-2d : cur %3u worst %3u (at %ld, "
1860 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
1861 cur, worst, worstt, DHMS_VARS(&ts));
1862 rc = lprocfs_at_hist_helper(page, count, rc,
1863 &imp->imp_at.iat_service_estimate[i]);
1866 LPROCFS_CLIMP_EXIT(obd);
1869 EXPORT_SYMBOL(lprocfs_rd_timeouts);
1871 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1872 int count, int *eof, void *data)
1874 struct obd_device *obd = data;
1878 LPROCFS_CLIMP_CHECK(obd);
1879 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1880 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1881 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1882 ret += snprintf(page + ret, count - ret, "\n");
1883 LPROCFS_CLIMP_EXIT(obd);
1886 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1888 #ifdef HAVE_SERVER_SUPPORT
1889 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1890 int *eof, void *data)
1892 struct obd_device *obd = data;
1894 LASSERT(obd != NULL);
1896 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1898 EXPORT_SYMBOL(lprocfs_rd_num_exports);
1901 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1902 int *eof, void *data)
1904 struct obd_type *class = (struct obd_type*) data;
1906 LASSERT(class != NULL);
1908 return snprintf(page, count, "%d\n", class->typ_refcnt);
1910 EXPORT_SYMBOL(lprocfs_rd_numrefs);
1912 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1916 LASSERT(obd != NULL);
1917 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1918 LASSERT(obd->obd_type->typ_procroot != NULL);
1920 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1921 obd->obd_type->typ_procroot,
1923 if (IS_ERR(obd->obd_proc_entry)) {
1924 rc = PTR_ERR(obd->obd_proc_entry);
1925 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1926 obd->obd_proc_entry = NULL;
1930 EXPORT_SYMBOL(lprocfs_obd_setup);
1934 lprocfs_seq_obd_setup(struct obd_device *obd)
1938 LASSERT(obd != NULL);
1939 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1940 LASSERT(obd->obd_type->typ_procroot != NULL);
1942 obd->obd_proc_entry = lprocfs_seq_register(obd->obd_name,
1943 obd->obd_type->typ_procroot,
1944 obd->obd_vars, obd);
1945 if (IS_ERR(obd->obd_proc_entry)) {
1946 rc = PTR_ERR(obd->obd_proc_entry);
1947 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1948 obd->obd_proc_entry = NULL;
1952 EXPORT_SYMBOL(lprocfs_seq_obd_setup);
1954 int lprocfs_obd_cleanup(struct obd_device *obd)
1958 if (obd->obd_proc_exports_entry) {
1959 /* Should be no exports left */
1960 lprocfs_remove(&obd->obd_proc_exports_entry);
1961 obd->obd_proc_exports_entry = NULL;
1963 if (obd->obd_proc_entry) {
1964 lprocfs_remove(&obd->obd_proc_entry);
1965 obd->obd_proc_entry = NULL;
1969 EXPORT_SYMBOL(lprocfs_obd_cleanup);
1971 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1973 CDEBUG(D_CONFIG, "stat %p - data %p/%p\n", client_stat,
1974 client_stat->nid_proc, client_stat->nid_stats);
1976 LASSERTF(atomic_read(&client_stat->nid_exp_ref_count) == 0,
1977 "nid %s:count %d\n", libcfs_nid2str(client_stat->nid),
1978 atomic_read(&client_stat->nid_exp_ref_count));
1980 if (client_stat->nid_proc)
1981 lprocfs_remove(&client_stat->nid_proc);
1983 if (client_stat->nid_stats)
1984 lprocfs_free_stats(&client_stat->nid_stats);
1986 if (client_stat->nid_ldlm_stats)
1987 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1989 OBD_FREE_PTR(client_stat);
1994 void lprocfs_free_per_client_stats(struct obd_device *obd)
1996 cfs_hash_t *hash = obd->obd_nid_stats_hash;
1997 struct nid_stat *stat;
2000 /* we need extra list - because hash_exit called to early */
2001 /* not need locking because all clients is died */
2002 while (!cfs_list_empty(&obd->obd_nid_stats)) {
2003 stat = cfs_list_entry(obd->obd_nid_stats.next,
2004 struct nid_stat, nid_list);
2005 cfs_list_del_init(&stat->nid_list);
2006 cfs_hash_del(hash, &stat->nid, &stat->nid_hash);
2007 lprocfs_free_client_stats(stat);
2011 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
2013 int lprocfs_stats_alloc_one(struct lprocfs_stats *stats, unsigned int cpuid)
2015 struct lprocfs_counter *cntr;
2016 unsigned int percpusize;
2018 unsigned long flags = 0;
2021 LASSERT(stats->ls_percpu[cpuid] == NULL);
2022 LASSERT((stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU) == 0);
2024 percpusize = lprocfs_stats_counter_size(stats);
2025 LIBCFS_ALLOC_ATOMIC(stats->ls_percpu[cpuid], percpusize);
2026 if (stats->ls_percpu[cpuid] != NULL) {
2028 if (unlikely(stats->ls_biggest_alloc_num <= cpuid)) {
2029 if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
2030 spin_lock_irqsave(&stats->ls_lock, flags);
2032 spin_lock(&stats->ls_lock);
2033 if (stats->ls_biggest_alloc_num <= cpuid)
2034 stats->ls_biggest_alloc_num = cpuid + 1;
2035 if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) {
2036 spin_unlock_irqrestore(&stats->ls_lock, flags);
2038 spin_unlock(&stats->ls_lock);
2041 /* initialize the ls_percpu[cpuid] non-zero counter */
2042 for (i = 0; i < stats->ls_num; ++i) {
2043 cntr = lprocfs_stats_counter_get(stats, cpuid, i);
2044 cntr->lc_min = LC_MIN_INIT;
2049 EXPORT_SYMBOL(lprocfs_stats_alloc_one);
2051 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
2052 enum lprocfs_stats_flags flags)
2054 struct lprocfs_stats *stats;
2055 unsigned int num_entry;
2056 unsigned int percpusize = 0;
2062 if (lprocfs_no_percpu_stats != 0)
2063 flags |= LPROCFS_STATS_FLAG_NOPERCPU;
2065 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
2068 num_entry = num_possible_cpus();
2070 /* alloc percpu pointers for all possible cpu slots */
2071 LIBCFS_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
2075 stats->ls_num = num;
2076 stats->ls_flags = flags;
2077 spin_lock_init(&stats->ls_lock);
2079 /* alloc num of counter headers */
2080 LIBCFS_ALLOC(stats->ls_cnt_header,
2081 stats->ls_num * sizeof(struct lprocfs_counter_header));
2082 if (stats->ls_cnt_header == NULL)
2085 if ((flags & LPROCFS_STATS_FLAG_NOPERCPU) != 0) {
2086 /* contains only one set counters */
2087 percpusize = lprocfs_stats_counter_size(stats);
2088 LIBCFS_ALLOC_ATOMIC(stats->ls_percpu[0], percpusize);
2089 if (stats->ls_percpu[0] == NULL)
2091 stats->ls_biggest_alloc_num = 1;
2092 } else if ((flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0) {
2093 /* alloc all percpu data, currently only obd_memory use this */
2094 for (i = 0; i < num_entry; ++i)
2095 if (lprocfs_stats_alloc_one(stats, i) < 0)
2102 lprocfs_free_stats(&stats);
2105 EXPORT_SYMBOL(lprocfs_alloc_stats);
2107 void lprocfs_free_stats(struct lprocfs_stats **statsh)
2109 struct lprocfs_stats *stats = *statsh;
2110 unsigned int num_entry;
2111 unsigned int percpusize;
2114 if (stats == NULL || stats->ls_num == 0)
2118 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
2121 num_entry = num_possible_cpus();
2123 percpusize = lprocfs_stats_counter_size(stats);
2124 for (i = 0; i < num_entry; i++)
2125 if (stats->ls_percpu[i] != NULL)
2126 LIBCFS_FREE(stats->ls_percpu[i], percpusize);
2127 if (stats->ls_cnt_header != NULL)
2128 LIBCFS_FREE(stats->ls_cnt_header, stats->ls_num *
2129 sizeof(struct lprocfs_counter_header));
2130 LIBCFS_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
2132 EXPORT_SYMBOL(lprocfs_free_stats);
2134 void lprocfs_clear_stats(struct lprocfs_stats *stats)
2136 struct lprocfs_counter *percpu_cntr;
2139 unsigned int num_entry;
2140 unsigned long flags = 0;
2142 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
2144 for (i = 0; i < num_entry; i++) {
2145 if (stats->ls_percpu[i] == NULL)
2147 for (j = 0; j < stats->ls_num; j++) {
2148 percpu_cntr = lprocfs_stats_counter_get(stats, i, j);
2149 percpu_cntr->lc_count = 0;
2150 percpu_cntr->lc_min = LC_MIN_INIT;
2151 percpu_cntr->lc_max = 0;
2152 percpu_cntr->lc_sumsquare = 0;
2153 percpu_cntr->lc_sum = 0;
2154 if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
2155 percpu_cntr->lc_sum_irq = 0;
2159 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
2161 EXPORT_SYMBOL(lprocfs_clear_stats);
2163 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
2164 size_t len, loff_t *off)
2166 struct seq_file *seq = file->private_data;
2167 struct lprocfs_stats *stats = seq->private;
2169 lprocfs_clear_stats(stats);
2174 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
2176 struct lprocfs_stats *stats = p->private;
2178 return (*pos < stats->ls_num) ? pos : NULL;
2181 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
2185 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
2189 return lprocfs_stats_seq_start(p, pos);
2192 /* seq file export of one lprocfs counter */
2193 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
2195 struct lprocfs_stats *stats = p->private;
2196 struct lprocfs_counter_header *hdr;
2197 struct lprocfs_counter ctr;
2198 int idx = *(loff_t *)v;
2204 do_gettimeofday(&now);
2205 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
2206 "snapshot_time", now.tv_sec, now.tv_usec);
2211 hdr = &stats->ls_cnt_header[idx];
2212 lprocfs_stats_collect(stats, idx, &ctr);
2214 if (ctr.lc_count == 0)
2217 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", hdr->lc_name,
2218 ctr.lc_count, hdr->lc_units);
2222 if ((hdr->lc_config & LPROCFS_CNTR_AVGMINMAX) && ctr.lc_count > 0) {
2223 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
2224 ctr.lc_min, ctr.lc_max, ctr.lc_sum);
2227 if (hdr->lc_config & LPROCFS_CNTR_STDDEV)
2228 rc = seq_printf(p, " "LPD64, ctr.lc_sumsquare);
2232 rc = seq_printf(p, "\n");
2234 return (rc < 0) ? rc : 0;
2237 struct seq_operations lprocfs_stats_seq_sops = {
2238 .start = lprocfs_stats_seq_start,
2239 .stop = lprocfs_stats_seq_stop,
2240 .next = lprocfs_stats_seq_next,
2241 .show = lprocfs_stats_seq_show,
2244 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
2246 struct seq_file *seq;
2249 #ifndef HAVE_ONLY_PROCFS_SEQ
2250 if (LPROCFS_ENTRY_CHECK(PDE(inode)))
2253 rc = seq_open(file, &lprocfs_stats_seq_sops);
2256 seq = file->private_data;
2257 seq->private = PDE_DATA(inode);
2261 struct file_operations lprocfs_stats_seq_fops = {
2262 .owner = THIS_MODULE,
2263 .open = lprocfs_stats_seq_open,
2265 .write = lprocfs_stats_seq_write,
2266 .llseek = seq_lseek,
2267 .release = lprocfs_seq_release,
2270 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
2271 struct lprocfs_stats *stats)
2273 struct proc_dir_entry *entry;
2274 LASSERT(root != NULL);
2276 entry = proc_create_data(name, 0644, root,
2277 &lprocfs_stats_seq_fops, stats);
2282 EXPORT_SYMBOL(lprocfs_register_stats);
2284 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
2285 unsigned conf, const char *name, const char *units)
2287 struct lprocfs_counter_header *header;
2288 struct lprocfs_counter *percpu_cntr;
2289 unsigned long flags = 0;
2291 unsigned int num_cpu;
2293 LASSERT(stats != NULL);
2295 header = &stats->ls_cnt_header[index];
2296 LASSERTF(header != NULL, "Failed to allocate stats header:[%d]%s/%s\n",
2297 index, name, units);
2299 header->lc_config = conf;
2300 header->lc_name = name;
2301 header->lc_units = units;
2303 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
2304 for (i = 0; i < num_cpu; ++i) {
2305 if (stats->ls_percpu[i] == NULL)
2307 percpu_cntr = lprocfs_stats_counter_get(stats, i, index);
2308 percpu_cntr->lc_count = 0;
2309 percpu_cntr->lc_min = LC_MIN_INIT;
2310 percpu_cntr->lc_max = 0;
2311 percpu_cntr->lc_sumsquare = 0;
2312 percpu_cntr->lc_sum = 0;
2313 if ((stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
2314 percpu_cntr->lc_sum_irq = 0;
2316 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
2318 EXPORT_SYMBOL(lprocfs_counter_init);
2320 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
2322 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
2323 LASSERT(coffset < stats->ls_num); \
2324 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
2327 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
2329 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
2330 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
2331 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
2332 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
2333 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
2334 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
2335 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
2336 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
2337 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
2338 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
2339 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
2340 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
2341 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
2342 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
2343 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
2344 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
2345 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
2346 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
2347 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
2348 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
2349 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
2350 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
2351 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
2352 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
2353 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
2354 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
2355 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
2356 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
2357 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
2358 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
2359 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
2360 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
2361 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
2362 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
2363 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
2364 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
2365 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
2366 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
2367 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
2368 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
2369 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
2370 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
2371 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
2372 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
2373 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
2374 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
2375 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
2376 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
2377 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
2378 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
2379 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
2380 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
2381 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
2383 CLASSERT(NUM_OBD_STATS == OBD_COUNTER_OFFSET(putref) + 1);
2385 EXPORT_SYMBOL(lprocfs_init_ops_stats);
2387 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
2389 struct lprocfs_stats *stats;
2390 unsigned int num_stats;
2393 LASSERT(obd->obd_stats == NULL);
2394 LASSERT(obd->obd_proc_entry != NULL);
2395 LASSERT(obd->obd_cntr_base == 0);
2397 num_stats = NUM_OBD_STATS + num_private_stats;
2398 stats = lprocfs_alloc_stats(num_stats, 0);
2402 lprocfs_init_ops_stats(num_private_stats, stats);
2404 for (i = num_private_stats; i < num_stats; i++) {
2405 /* If this LBUGs, it is likely that an obd
2406 * operation was added to struct obd_ops in
2407 * <obd.h>, and that the corresponding line item
2408 * LPROCFS_OBD_OP_INIT(.., .., opname)
2409 * is missing from the list above. */
2410 LASSERTF(stats->ls_cnt_header[i].lc_name != NULL,
2411 "Missing obd_stat initializer obd_op "
2412 "operation at offset %d.\n", i - num_private_stats);
2414 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
2416 lprocfs_free_stats(&stats);
2418 obd->obd_stats = stats;
2419 obd->obd_cntr_base = num_private_stats;
2423 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
2425 void lprocfs_free_obd_stats(struct obd_device *obd)
2428 lprocfs_free_stats(&obd->obd_stats);
2430 EXPORT_SYMBOL(lprocfs_free_obd_stats);
2432 /* Note that we only init md counters for ops whose offset is less
2433 * than NUM_MD_STATS. This is explained in a comment in the definition
2434 * of struct md_ops. */
2435 #define LPROCFS_MD_OP_INIT(base, stats, op) \
2437 unsigned int _idx = base + MD_COUNTER_OFFSET(op); \
2439 if (MD_COUNTER_OFFSET(op) < NUM_MD_STATS) { \
2440 LASSERT(_idx < stats->ls_num); \
2441 lprocfs_counter_init(stats, _idx, 0, #op, "reqs"); \
2445 void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats)
2447 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
2448 LPROCFS_MD_OP_INIT(num_private_stats, stats, null_inode);
2449 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
2450 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
2451 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
2452 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
2453 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
2454 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
2455 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
2456 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
2457 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
2458 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
2459 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
2460 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
2461 LPROCFS_MD_OP_INIT(num_private_stats, stats, fsync);
2462 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
2463 LPROCFS_MD_OP_INIT(num_private_stats, stats, read_entry);
2464 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
2465 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
2466 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
2467 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
2468 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
2469 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
2470 LPROCFS_MD_OP_INIT(num_private_stats, stats, update_lsm_md);
2471 LPROCFS_MD_OP_INIT(num_private_stats, stats, merge_attr);
2472 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
2473 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
2474 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
2475 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
2476 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
2477 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
2478 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
2479 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
2480 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
2481 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
2483 EXPORT_SYMBOL(lprocfs_init_mps_stats);
2485 int lprocfs_alloc_md_stats(struct obd_device *obd,
2486 unsigned int num_private_stats)
2488 struct lprocfs_stats *stats;
2489 unsigned int num_stats;
2492 CLASSERT(offsetof(struct md_ops, MD_STATS_FIRST_OP) == 0);
2493 CLASSERT(_MD_COUNTER_OFFSET(MD_STATS_FIRST_OP) == 0);
2494 CLASSERT(_MD_COUNTER_OFFSET(MD_STATS_LAST_OP) > 0);
2496 /* TODO Ensure that this function is only used where
2497 * appropriate by adding an assertion to the effect that
2498 * obd->obd_type->typ_md_ops is not NULL. We can't do this now
2499 * because mdt_procfs_init() uses this function to allocate
2500 * the stats backing /proc/fs/lustre/mdt/.../md_stats but the
2501 * mdt layer does not use the md_ops interface. This is
2502 * confusing and a waste of memory. See LU-2484.
2504 LASSERT(obd->obd_proc_entry != NULL);
2505 LASSERT(obd->obd_md_stats == NULL);
2506 LASSERT(obd->obd_md_cntr_base == 0);
2508 num_stats = NUM_MD_STATS + num_private_stats;
2509 stats = lprocfs_alloc_stats(num_stats, 0);
2513 lprocfs_init_mps_stats(num_private_stats, stats);
2515 for (i = num_private_stats; i < num_stats; i++) {
2516 if (stats->ls_cnt_header[i].lc_name == NULL) {
2517 CERROR("Missing md_stat initializer md_op "
2518 "operation at offset %d. Aborting.\n",
2519 i - num_private_stats);
2524 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
2526 lprocfs_free_stats(&stats);
2528 obd->obd_md_stats = stats;
2529 obd->obd_md_cntr_base = num_private_stats;
2534 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
2536 void lprocfs_free_md_stats(struct obd_device *obd)
2538 struct lprocfs_stats *stats = obd->obd_md_stats;
2540 if (stats != NULL) {
2541 obd->obd_md_stats = NULL;
2542 obd->obd_md_cntr_base = 0;
2543 lprocfs_free_stats(&stats);
2546 EXPORT_SYMBOL(lprocfs_free_md_stats);
2548 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
2550 lprocfs_counter_init(ldlm_stats,
2551 LDLM_ENQUEUE - LDLM_FIRST_OPC,
2552 0, "ldlm_enqueue", "reqs");
2553 lprocfs_counter_init(ldlm_stats,
2554 LDLM_CONVERT - LDLM_FIRST_OPC,
2555 0, "ldlm_convert", "reqs");
2556 lprocfs_counter_init(ldlm_stats,
2557 LDLM_CANCEL - LDLM_FIRST_OPC,
2558 0, "ldlm_cancel", "reqs");
2559 lprocfs_counter_init(ldlm_stats,
2560 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
2561 0, "ldlm_bl_callback", "reqs");
2562 lprocfs_counter_init(ldlm_stats,
2563 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
2564 0, "ldlm_cp_callback", "reqs");
2565 lprocfs_counter_init(ldlm_stats,
2566 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
2567 0, "ldlm_gl_callback", "reqs");
2569 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
2571 #ifdef HAVE_SERVER_SUPPORT
2572 int lprocfs_exp_nid_seq_show(struct seq_file *m, void *data)
2574 struct obd_export *exp = m->private;
2575 LASSERT(exp != NULL);
2576 return seq_printf(m, "%s\n", obd_export_nid2str(exp));
2579 int lprocfs_exp_print_uuid_seq(cfs_hash_t *hs, cfs_hash_bd_t *bd,
2580 cfs_hlist_node_t *hnode, void *cb_data)
2583 struct obd_export *exp = cfs_hash_object(hs, hnode);
2584 struct seq_file *m = cb_data;
2586 if (exp->exp_nid_stats)
2587 seq_printf(m, "%s\n", obd_uuid2str(&exp->exp_client_uuid));
2591 int lprocfs_exp_uuid_seq_show(struct seq_file *m, void *data)
2593 struct nid_stat *stats = m->private;
2594 struct obd_device *obd = stats->nid_obd;
2596 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
2597 lprocfs_exp_print_uuid_seq, m);
2600 LPROC_SEQ_FOPS_RO(lprocfs_exp_uuid);
2602 int lprocfs_exp_print_hash_seq(cfs_hash_t *hs, cfs_hash_bd_t *bd,
2603 cfs_hlist_node_t *hnode, void *cb_data)
2606 struct seq_file *m = cb_data;
2607 struct obd_export *exp = cfs_hash_object(hs, hnode);
2609 if (exp->exp_lock_hash != NULL) {
2610 cfs_hash_debug_header_seq(m);
2611 cfs_hash_debug_str_seq(hs, m);
2616 int lprocfs_exp_hash_seq_show(struct seq_file *m, void *data)
2618 struct nid_stat *stats = m->private;
2619 struct obd_device *obd = stats->nid_obd;
2621 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
2622 lprocfs_exp_print_hash_seq, m);
2625 LPROC_SEQ_FOPS_RO(lprocfs_exp_hash);
2627 int lprocfs_nid_stats_clear_seq_show(struct seq_file *m, void *data)
2629 return seq_printf(m, "%s\n", "Write into this file to clear all nid "
2630 "stats and stale nid entries");
2632 EXPORT_SYMBOL(lprocfs_nid_stats_clear_seq_show);
2634 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
2636 struct nid_stat *stat = obj;
2639 CDEBUG(D_INFO,"refcnt %d\n", atomic_read(&stat->nid_exp_ref_count));
2640 if (atomic_read(&stat->nid_exp_ref_count) == 1) {
2641 /* object has only hash references. */
2642 spin_lock(&stat->nid_obd->obd_nid_lock);
2643 cfs_list_move(&stat->nid_list, data);
2644 spin_unlock(&stat->nid_obd->obd_nid_lock);
2647 /* we has reference to object - only clear data*/
2648 if (stat->nid_stats)
2649 lprocfs_clear_stats(stat->nid_stats);
2655 lprocfs_nid_stats_clear_seq_write(struct file *file, const char *buffer,
2656 size_t count, loff_t *off)
2658 struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
2659 struct nid_stat *client_stat;
2660 CFS_LIST_HEAD(free_list);
2662 cfs_hash_cond_del(obd->obd_nid_stats_hash,
2663 lprocfs_nid_stats_clear_write_cb, &free_list);
2665 while (!cfs_list_empty(&free_list)) {
2666 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
2668 cfs_list_del_init(&client_stat->nid_list);
2669 lprocfs_free_client_stats(client_stat);
2673 EXPORT_SYMBOL(lprocfs_nid_stats_clear_seq_write);
2675 #ifndef HAVE_ONLY_PROCFS_SEQ
2676 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
2677 int *eof, void *data)
2679 struct obd_export *exp = data;
2680 LASSERT(exp != NULL);
2682 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
2685 struct exp_uuid_cb_data {
2693 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
2694 int count, int *eof, int *len)
2696 cb_data->page = page;
2697 cb_data->count = count;
2702 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
2703 cfs_hlist_node_t *hnode, void *cb_data)
2706 struct obd_export *exp = cfs_hash_object(hs, hnode);
2707 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
2709 if (exp->exp_nid_stats)
2710 *data->len += snprintf((data->page + *data->len),
2711 data->count, "%s\n",
2712 obd_uuid2str(&exp->exp_client_uuid));
2716 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
2717 int *eof, void *data)
2719 struct nid_stat *stats = (struct nid_stat *)data;
2720 struct exp_uuid_cb_data cb_data;
2721 struct obd_device *obd = stats->nid_obd;
2726 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
2727 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
2728 lprocfs_exp_print_uuid, &cb_data);
2729 return (*cb_data.len);
2732 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
2733 cfs_hlist_node_t *hnode, void *cb_data)
2736 struct exp_uuid_cb_data *data = cb_data;
2737 struct obd_export *exp = cfs_hash_object(hs, hnode);
2739 if (exp->exp_lock_hash != NULL) {
2741 *data->len += cfs_hash_debug_header(data->page,
2744 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
2751 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
2752 int *eof, void *data)
2754 struct nid_stat *stats = (struct nid_stat *)data;
2755 struct exp_uuid_cb_data cb_data;
2756 struct obd_device *obd = stats->nid_obd;
2761 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
2763 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
2764 lprocfs_exp_print_hash, &cb_data);
2765 return (*cb_data.len);
2768 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
2769 int count, int *eof, void *data)
2772 return snprintf(page, count, "%s\n",
2773 "Write into this file to clear all nid stats and "
2774 "stale nid entries");
2776 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
2778 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
2779 unsigned long count, void *data)
2781 struct obd_device *obd = (struct obd_device *)data;
2782 struct nid_stat *client_stat;
2783 CFS_LIST_HEAD(free_list);
2785 cfs_hash_cond_del(obd->obd_nid_stats_hash,
2786 lprocfs_nid_stats_clear_write_cb, &free_list);
2788 while (!cfs_list_empty(&free_list)) {
2789 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
2791 cfs_list_del_init(&client_stat->nid_list);
2792 lprocfs_free_client_stats(client_stat);
2797 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
2800 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
2802 struct nid_stat *new_stat, *old_stat;
2803 struct obd_device *obd = NULL;
2804 cfs_proc_dir_entry_t *entry;
2805 char *buffer = NULL;
2811 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
2812 !exp->exp_obd->obd_nid_stats_hash)
2815 /* not test against zero because eric say:
2816 * You may only test nid against another nid, or LNET_NID_ANY.
2817 * Anything else is nonsense.*/
2818 if (!nid || *nid == LNET_NID_ANY)
2821 spin_lock(&exp->exp_lock);
2822 if (exp->exp_nid_stats != NULL) {
2823 spin_unlock(&exp->exp_lock);
2826 spin_unlock(&exp->exp_lock);
2830 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
2832 OBD_ALLOC_PTR(new_stat);
2833 if (new_stat == NULL)
2836 new_stat->nid = *nid;
2837 new_stat->nid_obd = exp->exp_obd;
2838 /* we need set default refcount to 1 to balance obd_disconnect */
2839 atomic_set(&new_stat->nid_exp_ref_count, 1);
2841 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
2842 nid, &new_stat->nid_hash);
2843 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
2844 old_stat, libcfs_nid2str(*nid),
2845 atomic_read(&new_stat->nid_exp_ref_count));
2847 /* Return -EALREADY here so that we know that the /proc
2848 * entry already has been created */
2849 if (old_stat != new_stat) {
2850 spin_lock(&exp->exp_lock);
2851 if (exp->exp_nid_stats) {
2852 LASSERT(exp->exp_nid_stats == old_stat);
2853 nidstat_putref(exp->exp_nid_stats);
2855 exp->exp_nid_stats = old_stat;
2856 spin_unlock(&exp->exp_lock);
2857 GOTO(destroy_new, rc = -EALREADY);
2859 /* not found - create */
2860 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
2862 GOTO(destroy_new, rc = -ENOMEM);
2864 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
2865 #ifndef HAVE_ONLY_PROCFS_SEQ
2866 new_stat->nid_proc = lprocfs_register(buffer,
2867 obd->obd_proc_exports_entry,
2870 new_stat->nid_proc = lprocfs_seq_register(buffer,
2871 obd->obd_proc_exports_entry,
2874 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
2876 if (IS_ERR(new_stat->nid_proc)) {
2877 rc = PTR_ERR(new_stat->nid_proc);
2878 new_stat->nid_proc = NULL;
2879 CERROR("%s: cannot create proc entry for export %s: rc = %d\n",
2880 obd->obd_name, libcfs_nid2str(*nid), rc);
2881 GOTO(destroy_new_ns, rc);
2884 #ifndef HAVE_ONLY_PROCFS_SEQ
2885 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
2886 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
2888 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
2889 new_stat, &lprocfs_exp_uuid_fops);
2891 if (IS_ERR(entry)) {
2892 CWARN("Error adding the NID stats file\n");
2893 rc = PTR_ERR(entry);
2894 GOTO(destroy_new_ns, rc);
2897 #ifndef HAVE_ONLY_PROCFS_SEQ
2898 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
2899 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
2901 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
2902 new_stat, &lprocfs_exp_hash_fops);
2904 if (IS_ERR(entry)) {
2905 CWARN("Error adding the hash file\n");
2906 rc = PTR_ERR(entry);
2907 GOTO(destroy_new_ns, rc);
2910 spin_lock(&exp->exp_lock);
2911 exp->exp_nid_stats = new_stat;
2912 spin_unlock(&exp->exp_lock);
2914 /* protect competitive add to list, not need locking on destroy */
2915 spin_lock(&obd->obd_nid_lock);
2916 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
2917 spin_unlock(&obd->obd_nid_lock);
2922 if (new_stat->nid_proc != NULL)
2923 lprocfs_remove(&new_stat->nid_proc);
2924 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
2927 nidstat_putref(new_stat);
2928 OBD_FREE_PTR(new_stat);
2931 EXPORT_SYMBOL(lprocfs_exp_setup);
2934 int lprocfs_exp_cleanup(struct obd_export *exp)
2936 struct nid_stat *stat = exp->exp_nid_stats;
2938 if(!stat || !exp->exp_obd)
2941 nidstat_putref(exp->exp_nid_stats);
2942 exp->exp_nid_stats = NULL;
2946 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2948 __s64 lprocfs_read_helper(struct lprocfs_counter *lc,
2949 struct lprocfs_counter_header *header,
2950 enum lprocfs_stats_flags flags,
2951 enum lprocfs_fields_flags field)
2955 if (lc == NULL || header == NULL)
2959 case LPROCFS_FIELDS_FLAGS_CONFIG:
2960 ret = header->lc_config;
2962 case LPROCFS_FIELDS_FLAGS_SUM:
2964 if ((flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
2965 ret += lc->lc_sum_irq;
2967 case LPROCFS_FIELDS_FLAGS_MIN:
2970 case LPROCFS_FIELDS_FLAGS_MAX:
2973 case LPROCFS_FIELDS_FLAGS_AVG:
2974 ret = (lc->lc_max - lc->lc_min) / 2;
2976 case LPROCFS_FIELDS_FLAGS_SUMSQUARE:
2977 ret = lc->lc_sumsquare;
2979 case LPROCFS_FIELDS_FLAGS_COUNT:
2987 EXPORT_SYMBOL(lprocfs_read_helper);
2989 int lprocfs_write_helper(const char *buffer, unsigned long count,
2992 return lprocfs_write_frac_helper(buffer, count, val, 1);
2994 EXPORT_SYMBOL(lprocfs_write_helper);
2996 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
2999 char kernbuf[20], *end, *pbuf;
3001 if (count > (sizeof(kernbuf) - 1))
3004 if (copy_from_user(kernbuf, buffer, count))
3007 kernbuf[count] = '\0';
3014 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
3018 if (end != NULL && *end == '.') {
3019 int temp_val, pow = 1;
3023 if (strlen(pbuf) > 5)
3024 pbuf[5] = '\0'; /*only allow 5bits fractional*/
3026 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
3029 for (i = 0; i < (end - pbuf); i++)
3032 *val += temp_val / pow;
3037 EXPORT_SYMBOL(lprocfs_write_frac_helper);
3039 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
3042 long decimal_val, frac_val;
3048 decimal_val = val / mult;
3049 prtn = snprintf(buffer, count, "%ld", decimal_val);
3050 frac_val = val % mult;
3052 if (prtn < (count - 4) && frac_val > 0) {
3054 int i, temp_mult = 1, frac_bits = 0;
3056 temp_frac = frac_val * 10;
3057 buffer[prtn++] = '.';
3058 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
3059 /* only reserved 2 bits fraction */
3060 buffer[prtn++] ='0';
3065 * Need to think these cases :
3066 * 1. #echo x.00 > /proc/xxx output result : x
3067 * 2. #echo x.0x > /proc/xxx output result : x.0x
3068 * 3. #echo x.x0 > /proc/xxx output result : x.x
3069 * 4. #echo x.xx > /proc/xxx output result : x.xx
3070 * Only reserved 2 bits fraction.
3072 for (i = 0; i < (5 - prtn); i++)
3075 frac_bits = min((int)count - prtn, 3 - frac_bits);
3076 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
3077 frac_val * temp_mult / mult);
3080 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
3082 if (buffer[prtn] == '.') {
3089 buffer[prtn++] ='\n';
3092 EXPORT_SYMBOL(lprocfs_read_frac_helper);
3094 int lprocfs_seq_read_frac_helper(struct seq_file *m, long val, int mult)
3096 long decimal_val, frac_val;
3098 decimal_val = val / mult;
3099 seq_printf(m, "%ld", decimal_val);
3100 frac_val = val % mult;
3107 /* Three cases: x0, xx, 0x */
3108 if ((frac_val % 10) != 0)
3109 seq_printf(m, ".%ld", frac_val);
3111 seq_printf(m, ".%ld", frac_val / 10);
3114 seq_printf(m, "\n");
3117 EXPORT_SYMBOL(lprocfs_seq_read_frac_helper);
3119 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
3121 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
3123 EXPORT_SYMBOL(lprocfs_write_u64_helper);
3125 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
3126 __u64 *val, int mult)
3128 char kernbuf[22], *end, *pbuf;
3129 __u64 whole, frac = 0, units;
3130 unsigned frac_d = 1;
3132 if (count > (sizeof(kernbuf) - 1))
3135 if (copy_from_user(kernbuf, buffer, count))
3138 kernbuf[count] = '\0';
3145 whole = simple_strtoull(pbuf, &end, 10);
3149 if (end != NULL && *end == '.') {
3153 /* need to limit frac_d to a __u32 */
3154 if (strlen(pbuf) > 10)
3157 frac = simple_strtoull(pbuf, &end, 10);
3158 /* count decimal places */
3159 for (i = 0; i < (end - pbuf); i++)
3178 /* Specified units override the multiplier */
3180 mult = mult < 0 ? -units : units;
3183 do_div(frac, frac_d);
3184 *val = whole * mult + frac;
3187 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
3189 static char *lprocfs_strnstr(const char *s1, const char *s2, size_t len)
3198 if (!memcmp(s1, s2, l2))
3206 * Find the string \a name in the input \a buffer, and return a pointer to the
3207 * value immediately following \a name, reducing \a count appropriately.
3208 * If \a name is not found the original \a buffer is returned.
3210 char *lprocfs_find_named_value(const char *buffer, const char *name,
3214 size_t buflen = *count;
3216 /* there is no strnstr() in rhel5 and ubuntu kernels */
3217 val = lprocfs_strnstr(buffer, name, buflen);
3219 return (char *)buffer;
3221 val += strlen(name); /* skip prefix */
3222 while (val < buffer + buflen && isspace(*val)) /* skip separator */
3226 while (val < buffer + buflen && isalnum(*val)) {
3231 return val - *count;
3233 EXPORT_SYMBOL(lprocfs_find_named_value);
3235 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent,
3238 const struct file_operations *seq_fops,
3241 struct proc_dir_entry *entry;
3244 /* Disallow secretly (un)writable entries. */
3245 LASSERT((seq_fops->write == NULL) == ((mode & 0222) == 0));
3247 entry = proc_create_data(name, mode, parent, seq_fops, data);
3254 EXPORT_SYMBOL(lprocfs_seq_create);
3256 int lprocfs_obd_seq_create(struct obd_device *dev,
3259 const struct file_operations *seq_fops,
3262 return (lprocfs_seq_create(dev->obd_proc_entry, name,
3263 mode, seq_fops, data));
3265 EXPORT_SYMBOL(lprocfs_obd_seq_create);
3267 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
3269 if (value >= OBD_HIST_MAX)
3270 value = OBD_HIST_MAX - 1;
3272 spin_lock(&oh->oh_lock);
3273 oh->oh_buckets[value]++;
3274 spin_unlock(&oh->oh_lock);
3276 EXPORT_SYMBOL(lprocfs_oh_tally);
3278 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
3280 unsigned int val = 0;
3282 if (likely(value != 0))
3283 val = min(fls(value - 1), OBD_HIST_MAX);
3285 lprocfs_oh_tally(oh, val);
3287 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
3289 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
3291 unsigned long ret = 0;
3294 for (i = 0; i < OBD_HIST_MAX; i++)
3295 ret += oh->oh_buckets[i];
3298 EXPORT_SYMBOL(lprocfs_oh_sum);
3300 void lprocfs_oh_clear(struct obd_histogram *oh)
3302 spin_lock(&oh->oh_lock);
3303 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
3304 spin_unlock(&oh->oh_lock);
3306 EXPORT_SYMBOL(lprocfs_oh_clear);
3308 #ifdef HAVE_SERVER_SUPPORT
3309 int lprocfs_hash_seq_show(struct seq_file *m, void *data)
3311 struct obd_device *obd = m->private;
3317 c += cfs_hash_debug_header_seq(m);
3318 c += cfs_hash_debug_str_seq(obd->obd_uuid_hash, m);
3319 c += cfs_hash_debug_str_seq(obd->obd_nid_hash, m);
3320 c += cfs_hash_debug_str_seq(obd->obd_nid_stats_hash, m);
3323 EXPORT_SYMBOL(lprocfs_hash_seq_show);
3325 int lprocfs_recovery_status_seq_show(struct seq_file *m, void *data)
3327 struct obd_device *obd = m->private;
3329 LASSERT(obd != NULL);
3331 seq_printf(m, "status: \n");
3332 if (obd->obd_max_recoverable_clients == 0) {
3333 seq_printf(m, "INACTIVE\n");
3337 /* sampled unlocked, but really... */
3338 if (obd->obd_recovering == 0) {
3339 seq_printf(m, "COMPLETE\n");
3340 seq_printf(m, "recovery_start: %lu\n", obd->obd_recovery_start);
3341 seq_printf(m, "recovery_duration: %lu\n",
3342 obd->obd_recovery_end - obd->obd_recovery_start);
3343 /* Number of clients that have completed recovery */
3344 seq_printf(m, "completed_clients: %d/%d\n",
3345 obd->obd_max_recoverable_clients -
3346 obd->obd_stale_clients,
3347 obd->obd_max_recoverable_clients);
3348 seq_printf(m, "replayed_requests: %d\n",
3349 obd->obd_replayed_requests);
3350 seq_printf(m, "last_transno: "LPD64"\n",
3351 obd->obd_next_recovery_transno - 1);
3352 seq_printf(m, "VBR: %s\n", obd->obd_version_recov ?
3353 "ENABLED" : "DISABLED");
3354 seq_printf(m, "IR: %s\n", obd->obd_no_ir ?
3355 "DISABLED" : "ENABLED");
3359 seq_printf(m, "RECOVERING\n");
3360 seq_printf(m, "recovery_start: %lu\n", obd->obd_recovery_start);
3361 seq_printf(m, "time_remaining: %lu\n",
3362 cfs_time_current_sec() >=
3363 obd->obd_recovery_start +
3364 obd->obd_recovery_timeout ? 0 :
3365 obd->obd_recovery_start +
3366 obd->obd_recovery_timeout -
3367 cfs_time_current_sec());
3368 seq_printf(m, "connected_clients: %d/%d\n",
3369 atomic_read(&obd->obd_connected_clients),
3370 obd->obd_max_recoverable_clients);
3371 /* Number of clients that have completed recovery */
3372 seq_printf(m, "req_replay_clients: %d\n",
3373 atomic_read(&obd->obd_req_replay_clients));
3374 seq_printf(m, "lock_repay_clients: %d\n",
3375 atomic_read(&obd->obd_lock_replay_clients));
3376 seq_printf(m, "completed_clients: %d\n",
3377 atomic_read(&obd->obd_connected_clients) -
3378 atomic_read(&obd->obd_lock_replay_clients));
3379 seq_printf(m, "evicted_clients: %d\n", obd->obd_stale_clients);
3380 seq_printf(m, "replayed_requests: %d\n", obd->obd_replayed_requests);
3381 seq_printf(m, "queued_requests: %d\n",
3382 obd->obd_requests_queued_for_recovery);
3383 seq_printf(m, "next_transno: "LPD64"\n",
3384 obd->obd_next_recovery_transno);
3388 EXPORT_SYMBOL(lprocfs_recovery_status_seq_show);
3390 int lprocfs_ir_factor_seq_show(struct seq_file *m, void *data)
3392 struct obd_device *obd = m->private;
3394 LASSERT(obd != NULL);
3395 return seq_printf(m, "%d\n", obd->obd_recovery_ir_factor);
3397 EXPORT_SYMBOL(lprocfs_ir_factor_seq_show);
3400 lprocfs_ir_factor_seq_write(struct file *file, const char *buffer,
3401 size_t count, loff_t *off)
3403 struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
3406 LASSERT(obd != NULL);
3407 rc = lprocfs_write_helper(buffer, count, &val);
3411 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
3414 obd->obd_recovery_ir_factor = val;
3417 EXPORT_SYMBOL(lprocfs_ir_factor_seq_write);
3419 int lprocfs_recovery_time_soft_seq_show(struct seq_file *m, void *data)
3421 struct obd_device *obd = m->private;
3423 LASSERT(obd != NULL);
3424 return seq_printf(m, "%d\n", obd->obd_recovery_timeout);
3426 EXPORT_SYMBOL(lprocfs_recovery_time_soft_seq_show);
3429 lprocfs_recovery_time_soft_seq_write(struct file *file, const char *buffer,
3430 size_t count, loff_t *off)
3432 struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
3435 LASSERT(obd != NULL);
3436 rc = lprocfs_write_helper(buffer, count, &val);
3440 obd->obd_recovery_timeout = val;
3443 EXPORT_SYMBOL(lprocfs_recovery_time_soft_seq_write);
3445 int lprocfs_recovery_time_hard_seq_show(struct seq_file *m, void *data)
3447 struct obd_device *obd = m->private;
3449 LASSERT(obd != NULL);
3450 return seq_printf(m, "%u\n", obd->obd_recovery_time_hard);
3452 EXPORT_SYMBOL(lprocfs_recovery_time_hard_seq_show);
3455 lprocfs_recovery_time_hard_seq_write(struct file *file, const char *buffer,
3456 size_t count, loff_t *off)
3458 struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
3461 LASSERT(obd != NULL);
3462 rc = lprocfs_write_helper(buffer, count, &val);
3466 obd->obd_recovery_time_hard = val;
3469 EXPORT_SYMBOL(lprocfs_recovery_time_hard_seq_write);
3471 int lprocfs_target_instance_seq_show(struct seq_file *m, void *data)
3473 struct obd_device *obd = m->private;
3474 struct obd_device_target *target = &obd->u.obt;
3476 LASSERT(obd != NULL);
3477 LASSERT(target->obt_magic == OBT_MAGIC);
3478 return seq_printf(m, "%u\n", obd->u.obt.obt_instance);
3480 EXPORT_SYMBOL(lprocfs_target_instance_seq_show);
3482 #ifndef HAVE_ONLY_PROCFS_SEQ
3483 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
3484 int count, int *eof, void *data)
3486 struct obd_device *obd = data;
3492 c += cfs_hash_debug_header(page, count);
3493 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
3494 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
3495 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
3499 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
3501 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
3502 int count, int *eof, void *data)
3504 struct obd_device *obd = data;
3507 LASSERT(obd != NULL);
3508 LASSERT(count >= 0);
3510 /* Set start of user data returned to
3511 page + off since the user may have
3512 requested to read much smaller than
3513 what we need to read */
3514 *start = page + off;
3517 * We know we are allocated a page here.
3518 * Also we know that this function will
3519 * not need to write more than a page
3520 * so we can truncate at PAGE_CACHE_SIZE.
3522 size = min(count + (int)off + 1, (int)PAGE_CACHE_SIZE);
3524 /* Initialize the page */
3525 memset(page, 0, size);
3527 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
3529 if (obd->obd_max_recoverable_clients == 0) {
3530 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
3536 /* sampled unlocked, but really... */
3537 if (obd->obd_recovering == 0) {
3538 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
3540 if (lprocfs_obd_snprintf(&page, size, &len,
3541 "recovery_start: %lu\n",
3542 obd->obd_recovery_start) <= 0)
3544 if (lprocfs_obd_snprintf(&page, size, &len,
3545 "recovery_duration: %lu\n",
3546 obd->obd_recovery_end -
3547 obd->obd_recovery_start) <= 0)
3549 /* Number of clients that have completed recovery */
3550 if (lprocfs_obd_snprintf(&page, size, &len,
3551 "completed_clients: %d/%d\n",
3552 obd->obd_max_recoverable_clients -
3553 obd->obd_stale_clients,
3554 obd->obd_max_recoverable_clients) <= 0)
3556 if (lprocfs_obd_snprintf(&page, size, &len,
3557 "replayed_requests: %d\n",
3558 obd->obd_replayed_requests) <= 0)
3560 if (lprocfs_obd_snprintf(&page, size, &len,
3561 "last_transno: "LPD64"\n",
3562 obd->obd_next_recovery_transno - 1)<=0)
3564 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
3565 obd->obd_version_recov ?
3566 "ENABLED" : "DISABLED") <=0)
3568 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
3570 "DISABLED" : "ENABLED") <= 0)
3575 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
3577 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
3578 obd->obd_recovery_start) <= 0)
3580 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
3581 cfs_time_current_sec() >=
3582 obd->obd_recovery_start +
3583 obd->obd_recovery_timeout ? 0 :
3584 obd->obd_recovery_start +
3585 obd->obd_recovery_timeout -
3586 cfs_time_current_sec()) <= 0)
3588 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
3589 atomic_read(&obd->obd_connected_clients),
3590 obd->obd_max_recoverable_clients) <= 0)
3592 /* Number of clients that have completed recovery */
3593 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
3594 atomic_read(&obd->obd_req_replay_clients))
3597 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
3598 atomic_read(&obd->obd_lock_replay_clients))
3601 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
3602 atomic_read(&obd->obd_connected_clients) -
3603 atomic_read(&obd->obd_lock_replay_clients))
3606 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
3607 obd->obd_stale_clients) <= 0)
3609 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
3610 obd->obd_replayed_requests) <= 0)
3612 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
3613 obd->obd_requests_queued_for_recovery) <= 0)
3616 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
3617 obd->obd_next_recovery_transno) <= 0)
3623 return min(count, len - (int)off);
3625 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
3627 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
3628 int count, int *eof, void *data)
3630 struct obd_device *obd = (struct obd_device *)data;
3631 LASSERT(obd != NULL);
3633 return snprintf(page, count, "%d\n",
3634 obd->obd_recovery_ir_factor);
3636 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
3638 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
3639 unsigned long count, void *data)
3641 struct obd_device *obd = (struct obd_device *)data;
3643 LASSERT(obd != NULL);
3645 rc = lprocfs_write_helper(buffer, count, &val);
3649 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
3652 obd->obd_recovery_ir_factor = val;
3655 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
3657 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
3658 int count, int *eof, void *data)
3660 struct obd_device *obd = (struct obd_device *)data;
3661 LASSERT(obd != NULL);
3663 return snprintf(page, count, "%d\n",
3664 obd->obd_recovery_timeout);
3666 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
3668 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
3669 unsigned long count, void *data)
3671 struct obd_device *obd = (struct obd_device *)data;
3673 LASSERT(obd != NULL);
3675 rc = lprocfs_write_helper(buffer, count, &val);
3679 obd->obd_recovery_timeout = val;
3682 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
3684 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
3685 int count, int *eof, void *data)
3687 struct obd_device *obd = data;
3688 LASSERT(obd != NULL);
3690 return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
3692 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
3694 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
3695 unsigned long count, void *data)
3697 struct obd_device *obd = data;
3699 LASSERT(obd != NULL);
3701 rc = lprocfs_write_helper(buffer, count, &val);
3705 obd->obd_recovery_time_hard = val;
3708 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
3710 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
3711 int count, int *eof, void *data)
3713 struct obd_device *obd = (struct obd_device *)data;
3714 struct obd_device_target *target = &obd->u.obt;
3716 LASSERT(obd != NULL);
3717 LASSERT(target->obt_magic == OBT_MAGIC);
3719 return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
3721 EXPORT_SYMBOL(lprocfs_target_rd_instance);
3722 #endif /* HAVE_ONLY_PROCFS_SEQ */
3723 #endif /* HAVE_SERVER_SUPPORT */
3725 int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
3726 int count, int *eof, void *data)
3728 struct obd_device *dev = data;
3729 struct client_obd *cli = &dev->u.cli;
3732 client_obd_list_lock(&cli->cl_loi_list_lock);
3733 rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
3734 client_obd_list_unlock(&cli->cl_loi_list_lock);
3737 EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
3739 int lprocfs_obd_max_pages_per_rpc_seq_show(struct seq_file *m, void *data)
3741 struct obd_device *dev = data;
3742 struct client_obd *cli = &dev->u.cli;
3745 client_obd_list_lock(&cli->cl_loi_list_lock);
3746 rc = seq_printf(m, "%d\n", cli->cl_max_pages_per_rpc);
3747 client_obd_list_unlock(&cli->cl_loi_list_lock);
3750 EXPORT_SYMBOL(lprocfs_obd_max_pages_per_rpc_seq_show);