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 *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_vars != NULL);
1940 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1941 LASSERT(obd->obd_type->typ_procroot != NULL);
1943 obd->obd_proc_entry = lprocfs_seq_register(obd->obd_name,
1944 obd->obd_type->typ_procroot,
1945 obd->obd_vars, obd);
1946 if (IS_ERR(obd->obd_proc_entry)) {
1947 rc = PTR_ERR(obd->obd_proc_entry);
1948 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1949 obd->obd_proc_entry = NULL;
1953 EXPORT_SYMBOL(lprocfs_seq_obd_setup);
1955 int lprocfs_obd_cleanup(struct obd_device *obd)
1959 if (obd->obd_proc_exports_entry) {
1960 /* Should be no exports left */
1961 lprocfs_remove(&obd->obd_proc_exports_entry);
1962 obd->obd_proc_exports_entry = NULL;
1964 if (obd->obd_proc_entry) {
1965 lprocfs_remove(&obd->obd_proc_entry);
1966 obd->obd_proc_entry = NULL;
1970 EXPORT_SYMBOL(lprocfs_obd_cleanup);
1972 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1974 CDEBUG(D_CONFIG, "stat %p - data %p/%p\n", client_stat,
1975 client_stat->nid_proc, client_stat->nid_stats);
1977 LASSERTF(atomic_read(&client_stat->nid_exp_ref_count) == 0,
1978 "nid %s:count %d\n", libcfs_nid2str(client_stat->nid),
1979 atomic_read(&client_stat->nid_exp_ref_count));
1981 if (client_stat->nid_proc)
1982 lprocfs_remove(&client_stat->nid_proc);
1984 if (client_stat->nid_stats)
1985 lprocfs_free_stats(&client_stat->nid_stats);
1987 if (client_stat->nid_ldlm_stats)
1988 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1990 OBD_FREE_PTR(client_stat);
1995 void lprocfs_free_per_client_stats(struct obd_device *obd)
1997 cfs_hash_t *hash = obd->obd_nid_stats_hash;
1998 struct nid_stat *stat;
2001 /* we need extra list - because hash_exit called to early */
2002 /* not need locking because all clients is died */
2003 while (!cfs_list_empty(&obd->obd_nid_stats)) {
2004 stat = cfs_list_entry(obd->obd_nid_stats.next,
2005 struct nid_stat, nid_list);
2006 cfs_list_del_init(&stat->nid_list);
2007 cfs_hash_del(hash, &stat->nid, &stat->nid_hash);
2008 lprocfs_free_client_stats(stat);
2012 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
2014 int lprocfs_stats_alloc_one(struct lprocfs_stats *stats, unsigned int cpuid)
2016 struct lprocfs_counter *cntr;
2017 unsigned int percpusize;
2019 unsigned long flags = 0;
2022 LASSERT(stats->ls_percpu[cpuid] == NULL);
2023 LASSERT((stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU) == 0);
2025 percpusize = lprocfs_stats_counter_size(stats);
2026 LIBCFS_ALLOC_ATOMIC(stats->ls_percpu[cpuid], percpusize);
2027 if (stats->ls_percpu[cpuid] != NULL) {
2029 if (unlikely(stats->ls_biggest_alloc_num <= cpuid)) {
2030 if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
2031 spin_lock_irqsave(&stats->ls_lock, flags);
2033 spin_lock(&stats->ls_lock);
2034 if (stats->ls_biggest_alloc_num <= cpuid)
2035 stats->ls_biggest_alloc_num = cpuid + 1;
2036 if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) {
2037 spin_unlock_irqrestore(&stats->ls_lock, flags);
2039 spin_unlock(&stats->ls_lock);
2042 /* initialize the ls_percpu[cpuid] non-zero counter */
2043 for (i = 0; i < stats->ls_num; ++i) {
2044 cntr = lprocfs_stats_counter_get(stats, cpuid, i);
2045 cntr->lc_min = LC_MIN_INIT;
2050 EXPORT_SYMBOL(lprocfs_stats_alloc_one);
2052 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
2053 enum lprocfs_stats_flags flags)
2055 struct lprocfs_stats *stats;
2056 unsigned int num_entry;
2057 unsigned int percpusize = 0;
2063 if (lprocfs_no_percpu_stats != 0)
2064 flags |= LPROCFS_STATS_FLAG_NOPERCPU;
2066 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
2069 num_entry = num_possible_cpus();
2071 /* alloc percpu pointers for all possible cpu slots */
2072 LIBCFS_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
2076 stats->ls_num = num;
2077 stats->ls_flags = flags;
2078 spin_lock_init(&stats->ls_lock);
2080 /* alloc num of counter headers */
2081 LIBCFS_ALLOC(stats->ls_cnt_header,
2082 stats->ls_num * sizeof(struct lprocfs_counter_header));
2083 if (stats->ls_cnt_header == NULL)
2086 if ((flags & LPROCFS_STATS_FLAG_NOPERCPU) != 0) {
2087 /* contains only one set counters */
2088 percpusize = lprocfs_stats_counter_size(stats);
2089 LIBCFS_ALLOC_ATOMIC(stats->ls_percpu[0], percpusize);
2090 if (stats->ls_percpu[0] == NULL)
2092 stats->ls_biggest_alloc_num = 1;
2093 } else if ((flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0) {
2094 /* alloc all percpu data, currently only obd_memory use this */
2095 for (i = 0; i < num_entry; ++i)
2096 if (lprocfs_stats_alloc_one(stats, i) < 0)
2103 lprocfs_free_stats(&stats);
2106 EXPORT_SYMBOL(lprocfs_alloc_stats);
2108 void lprocfs_free_stats(struct lprocfs_stats **statsh)
2110 struct lprocfs_stats *stats = *statsh;
2111 unsigned int num_entry;
2112 unsigned int percpusize;
2115 if (stats == NULL || stats->ls_num == 0)
2119 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
2122 num_entry = num_possible_cpus();
2124 percpusize = lprocfs_stats_counter_size(stats);
2125 for (i = 0; i < num_entry; i++)
2126 if (stats->ls_percpu[i] != NULL)
2127 LIBCFS_FREE(stats->ls_percpu[i], percpusize);
2128 if (stats->ls_cnt_header != NULL)
2129 LIBCFS_FREE(stats->ls_cnt_header, stats->ls_num *
2130 sizeof(struct lprocfs_counter_header));
2131 LIBCFS_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
2133 EXPORT_SYMBOL(lprocfs_free_stats);
2135 void lprocfs_clear_stats(struct lprocfs_stats *stats)
2137 struct lprocfs_counter *percpu_cntr;
2140 unsigned int num_entry;
2141 unsigned long flags = 0;
2143 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
2145 for (i = 0; i < num_entry; i++) {
2146 if (stats->ls_percpu[i] == NULL)
2148 for (j = 0; j < stats->ls_num; j++) {
2149 percpu_cntr = lprocfs_stats_counter_get(stats, i, j);
2150 percpu_cntr->lc_count = 0;
2151 percpu_cntr->lc_min = LC_MIN_INIT;
2152 percpu_cntr->lc_max = 0;
2153 percpu_cntr->lc_sumsquare = 0;
2154 percpu_cntr->lc_sum = 0;
2155 if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
2156 percpu_cntr->lc_sum_irq = 0;
2160 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
2162 EXPORT_SYMBOL(lprocfs_clear_stats);
2164 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
2165 size_t len, loff_t *off)
2167 struct seq_file *seq = file->private_data;
2168 struct lprocfs_stats *stats = seq->private;
2170 lprocfs_clear_stats(stats);
2175 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
2177 struct lprocfs_stats *stats = p->private;
2179 return (*pos < stats->ls_num) ? pos : NULL;
2182 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
2186 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
2190 return lprocfs_stats_seq_start(p, pos);
2193 /* seq file export of one lprocfs counter */
2194 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
2196 struct lprocfs_stats *stats = p->private;
2197 struct lprocfs_counter_header *hdr;
2198 struct lprocfs_counter ctr;
2199 int idx = *(loff_t *)v;
2205 do_gettimeofday(&now);
2206 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
2207 "snapshot_time", now.tv_sec, now.tv_usec);
2212 hdr = &stats->ls_cnt_header[idx];
2213 lprocfs_stats_collect(stats, idx, &ctr);
2215 if (ctr.lc_count == 0)
2218 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", hdr->lc_name,
2219 ctr.lc_count, hdr->lc_units);
2223 if ((hdr->lc_config & LPROCFS_CNTR_AVGMINMAX) && ctr.lc_count > 0) {
2224 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
2225 ctr.lc_min, ctr.lc_max, ctr.lc_sum);
2228 if (hdr->lc_config & LPROCFS_CNTR_STDDEV)
2229 rc = seq_printf(p, " "LPD64, ctr.lc_sumsquare);
2233 rc = seq_printf(p, "\n");
2235 return (rc < 0) ? rc : 0;
2238 struct seq_operations lprocfs_stats_seq_sops = {
2239 .start = lprocfs_stats_seq_start,
2240 .stop = lprocfs_stats_seq_stop,
2241 .next = lprocfs_stats_seq_next,
2242 .show = lprocfs_stats_seq_show,
2245 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
2247 struct seq_file *seq;
2250 #ifndef HAVE_ONLY_PROCFS_SEQ
2251 if (LPROCFS_ENTRY_CHECK(PDE(inode)))
2254 rc = seq_open(file, &lprocfs_stats_seq_sops);
2257 seq = file->private_data;
2258 seq->private = PDE_DATA(inode);
2262 struct file_operations lprocfs_stats_seq_fops = {
2263 .owner = THIS_MODULE,
2264 .open = lprocfs_stats_seq_open,
2266 .write = lprocfs_stats_seq_write,
2267 .llseek = seq_lseek,
2268 .release = lprocfs_seq_release,
2271 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
2272 struct lprocfs_stats *stats)
2274 struct proc_dir_entry *entry;
2275 LASSERT(root != NULL);
2277 entry = proc_create_data(name, 0644, root,
2278 &lprocfs_stats_seq_fops, stats);
2283 EXPORT_SYMBOL(lprocfs_register_stats);
2285 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
2286 unsigned conf, const char *name, const char *units)
2288 struct lprocfs_counter_header *header;
2289 struct lprocfs_counter *percpu_cntr;
2290 unsigned long flags = 0;
2292 unsigned int num_cpu;
2294 LASSERT(stats != NULL);
2296 header = &stats->ls_cnt_header[index];
2297 LASSERTF(header != NULL, "Failed to allocate stats header:[%d]%s/%s\n",
2298 index, name, units);
2300 header->lc_config = conf;
2301 header->lc_name = name;
2302 header->lc_units = units;
2304 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
2305 for (i = 0; i < num_cpu; ++i) {
2306 if (stats->ls_percpu[i] == NULL)
2308 percpu_cntr = lprocfs_stats_counter_get(stats, i, index);
2309 percpu_cntr->lc_count = 0;
2310 percpu_cntr->lc_min = LC_MIN_INIT;
2311 percpu_cntr->lc_max = 0;
2312 percpu_cntr->lc_sumsquare = 0;
2313 percpu_cntr->lc_sum = 0;
2314 if ((stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
2315 percpu_cntr->lc_sum_irq = 0;
2317 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
2319 EXPORT_SYMBOL(lprocfs_counter_init);
2321 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
2323 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
2324 LASSERT(coffset < stats->ls_num); \
2325 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
2328 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
2330 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
2331 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
2332 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
2333 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
2334 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
2335 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
2336 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
2337 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
2338 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
2339 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
2340 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
2341 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
2342 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
2343 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
2344 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
2345 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
2346 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
2347 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
2348 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
2349 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
2350 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
2351 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
2352 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
2353 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
2354 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
2355 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
2356 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
2357 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
2358 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
2359 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
2360 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
2361 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
2362 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
2363 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
2364 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
2365 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
2366 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
2367 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
2368 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
2369 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
2370 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
2371 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
2372 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
2373 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
2374 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
2375 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
2376 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
2377 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
2378 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
2379 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
2380 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
2381 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
2382 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
2383 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
2384 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
2385 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
2386 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
2387 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
2388 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
2389 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
2390 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
2391 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
2392 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
2393 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
2394 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
2395 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
2396 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
2398 CLASSERT(NUM_OBD_STATS == OBD_COUNTER_OFFSET(putref) + 1);
2400 EXPORT_SYMBOL(lprocfs_init_ops_stats);
2402 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
2404 struct lprocfs_stats *stats;
2405 unsigned int num_stats;
2408 LASSERT(obd->obd_stats == NULL);
2409 LASSERT(obd->obd_proc_entry != NULL);
2410 LASSERT(obd->obd_cntr_base == 0);
2412 num_stats = NUM_OBD_STATS + num_private_stats;
2413 stats = lprocfs_alloc_stats(num_stats, 0);
2417 lprocfs_init_ops_stats(num_private_stats, stats);
2419 for (i = num_private_stats; i < num_stats; i++) {
2420 /* If this LBUGs, it is likely that an obd
2421 * operation was added to struct obd_ops in
2422 * <obd.h>, and that the corresponding line item
2423 * LPROCFS_OBD_OP_INIT(.., .., opname)
2424 * is missing from the list above. */
2425 LASSERTF(stats->ls_cnt_header[i].lc_name != NULL,
2426 "Missing obd_stat initializer obd_op "
2427 "operation at offset %d.\n", i - num_private_stats);
2429 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
2431 lprocfs_free_stats(&stats);
2433 obd->obd_stats = stats;
2434 obd->obd_cntr_base = num_private_stats;
2438 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
2440 void lprocfs_free_obd_stats(struct obd_device *obd)
2443 lprocfs_free_stats(&obd->obd_stats);
2445 EXPORT_SYMBOL(lprocfs_free_obd_stats);
2447 /* Note that we only init md counters for ops whose offset is less
2448 * than NUM_MD_STATS. This is explained in a comment in the definition
2449 * of struct md_ops. */
2450 #define LPROCFS_MD_OP_INIT(base, stats, op) \
2452 unsigned int _idx = base + MD_COUNTER_OFFSET(op); \
2454 if (MD_COUNTER_OFFSET(op) < NUM_MD_STATS) { \
2455 LASSERT(_idx < stats->ls_num); \
2456 lprocfs_counter_init(stats, _idx, 0, #op, "reqs"); \
2460 void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats)
2462 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
2463 LPROCFS_MD_OP_INIT(num_private_stats, stats, null_inode);
2464 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
2465 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
2466 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
2467 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
2468 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
2469 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
2470 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
2471 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
2472 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
2473 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
2474 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
2475 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
2476 LPROCFS_MD_OP_INIT(num_private_stats, stats, fsync);
2477 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
2478 LPROCFS_MD_OP_INIT(num_private_stats, stats, read_entry);
2479 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
2480 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
2481 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
2482 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
2483 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
2484 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
2485 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
2486 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
2487 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
2488 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
2489 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
2490 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
2491 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
2492 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
2493 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
2494 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
2496 EXPORT_SYMBOL(lprocfs_init_mps_stats);
2498 int lprocfs_alloc_md_stats(struct obd_device *obd,
2499 unsigned int num_private_stats)
2501 struct lprocfs_stats *stats;
2502 unsigned int num_stats;
2505 CLASSERT(offsetof(struct md_ops, MD_STATS_FIRST_OP) == 0);
2506 CLASSERT(_MD_COUNTER_OFFSET(MD_STATS_FIRST_OP) == 0);
2507 CLASSERT(_MD_COUNTER_OFFSET(MD_STATS_LAST_OP) > 0);
2509 /* TODO Ensure that this function is only used where
2510 * appropriate by adding an assertion to the effect that
2511 * obd->obd_type->typ_md_ops is not NULL. We can't do this now
2512 * because mdt_procfs_init() uses this function to allocate
2513 * the stats backing /proc/fs/lustre/mdt/.../md_stats but the
2514 * mdt layer does not use the md_ops interface. This is
2515 * confusing and a waste of memory. See LU-2484.
2517 LASSERT(obd->obd_proc_entry != NULL);
2518 LASSERT(obd->obd_md_stats == NULL);
2519 LASSERT(obd->obd_md_cntr_base == 0);
2521 num_stats = NUM_MD_STATS + num_private_stats;
2522 stats = lprocfs_alloc_stats(num_stats, 0);
2526 lprocfs_init_mps_stats(num_private_stats, stats);
2528 for (i = num_private_stats; i < num_stats; i++) {
2529 if (stats->ls_cnt_header[i].lc_name == NULL) {
2530 CERROR("Missing md_stat initializer md_op "
2531 "operation at offset %d. Aborting.\n",
2532 i - num_private_stats);
2537 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
2539 lprocfs_free_stats(&stats);
2541 obd->obd_md_stats = stats;
2542 obd->obd_md_cntr_base = num_private_stats;
2547 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
2549 void lprocfs_free_md_stats(struct obd_device *obd)
2551 struct lprocfs_stats *stats = obd->obd_md_stats;
2553 if (stats != NULL) {
2554 obd->obd_md_stats = NULL;
2555 obd->obd_md_cntr_base = 0;
2556 lprocfs_free_stats(&stats);
2559 EXPORT_SYMBOL(lprocfs_free_md_stats);
2561 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
2563 lprocfs_counter_init(ldlm_stats,
2564 LDLM_ENQUEUE - LDLM_FIRST_OPC,
2565 0, "ldlm_enqueue", "reqs");
2566 lprocfs_counter_init(ldlm_stats,
2567 LDLM_CONVERT - LDLM_FIRST_OPC,
2568 0, "ldlm_convert", "reqs");
2569 lprocfs_counter_init(ldlm_stats,
2570 LDLM_CANCEL - LDLM_FIRST_OPC,
2571 0, "ldlm_cancel", "reqs");
2572 lprocfs_counter_init(ldlm_stats,
2573 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
2574 0, "ldlm_bl_callback", "reqs");
2575 lprocfs_counter_init(ldlm_stats,
2576 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
2577 0, "ldlm_cp_callback", "reqs");
2578 lprocfs_counter_init(ldlm_stats,
2579 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
2580 0, "ldlm_gl_callback", "reqs");
2582 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
2584 #ifdef HAVE_SERVER_SUPPORT
2585 /* No one appears to be using this ?? */
2586 int lprocfs_exp_nid_seq_show(struct seq_file *m, void *data)
2588 struct obd_export *exp = m->private;
2589 LASSERT(exp != NULL);
2590 return seq_printf(m, "%s\n", obd_export_nid2str(exp));
2593 int lprocfs_exp_print_uuid_seq(cfs_hash_t *hs, cfs_hash_bd_t *bd,
2594 cfs_hlist_node_t *hnode, void *cb_data)
2597 struct obd_export *exp = cfs_hash_object(hs, hnode);
2598 struct seq_file *m = cb_data;
2600 if (exp->exp_nid_stats)
2601 seq_printf(m, "%s\n", obd_uuid2str(&exp->exp_client_uuid));
2605 int lprocfs_exp_uuid_seq_show(struct seq_file *m, void *data)
2607 struct nid_stat *stats = m->private;
2608 struct obd_device *obd = stats->nid_obd;
2610 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
2611 lprocfs_exp_print_uuid_seq, m);
2614 LPROC_SEQ_FOPS_RO(lprocfs_exp_uuid);
2616 int lprocfs_exp_print_hash_seq(cfs_hash_t *hs, cfs_hash_bd_t *bd,
2617 cfs_hlist_node_t *hnode, void *cb_data)
2620 struct seq_file *m = cb_data;
2621 struct obd_export *exp = cfs_hash_object(hs, hnode);
2623 if (exp->exp_lock_hash != NULL) {
2624 cfs_hash_debug_header_seq(m);
2625 cfs_hash_debug_str_seq(hs, m);
2630 int lprocfs_exp_hash_seq_show(struct seq_file *m, void *data)
2632 struct nid_stat *stats = m->private;
2633 struct obd_device *obd = stats->nid_obd;
2635 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
2636 lprocfs_exp_print_hash_seq, m);
2639 LPROC_SEQ_FOPS_RO(lprocfs_exp_hash);
2641 int lprocfs_nid_stats_clear_seq_show(struct seq_file *m, void *data)
2643 return seq_printf(m, "%s\n", "Write into this file to clear all nid "
2644 "stats and stale nid entries");
2646 EXPORT_SYMBOL(lprocfs_nid_stats_clear_seq_show);
2648 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
2650 struct nid_stat *stat = obj;
2653 CDEBUG(D_INFO,"refcnt %d\n", atomic_read(&stat->nid_exp_ref_count));
2654 if (atomic_read(&stat->nid_exp_ref_count) == 1) {
2655 /* object has only hash references. */
2656 spin_lock(&stat->nid_obd->obd_nid_lock);
2657 cfs_list_move(&stat->nid_list, data);
2658 spin_unlock(&stat->nid_obd->obd_nid_lock);
2661 /* we has reference to object - only clear data*/
2662 if (stat->nid_stats)
2663 lprocfs_clear_stats(stat->nid_stats);
2669 lprocfs_nid_stats_clear_seq_write(struct file *file, const char *buffer,
2670 size_t count, loff_t *off)
2672 struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
2673 struct nid_stat *client_stat;
2674 CFS_LIST_HEAD(free_list);
2676 cfs_hash_cond_del(obd->obd_nid_stats_hash,
2677 lprocfs_nid_stats_clear_write_cb, &free_list);
2679 while (!cfs_list_empty(&free_list)) {
2680 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
2682 cfs_list_del_init(&client_stat->nid_list);
2683 lprocfs_free_client_stats(client_stat);
2687 EXPORT_SYMBOL(lprocfs_nid_stats_clear_seq_write);
2689 #ifndef HAVE_ONLY_PROCFS_SEQ
2690 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
2691 int *eof, void *data)
2693 struct obd_export *exp = data;
2694 LASSERT(exp != NULL);
2696 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
2699 struct exp_uuid_cb_data {
2707 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
2708 int count, int *eof, int *len)
2710 cb_data->page = page;
2711 cb_data->count = count;
2716 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
2717 cfs_hlist_node_t *hnode, void *cb_data)
2720 struct obd_export *exp = cfs_hash_object(hs, hnode);
2721 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
2723 if (exp->exp_nid_stats)
2724 *data->len += snprintf((data->page + *data->len),
2725 data->count, "%s\n",
2726 obd_uuid2str(&exp->exp_client_uuid));
2730 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
2731 int *eof, void *data)
2733 struct nid_stat *stats = (struct nid_stat *)data;
2734 struct exp_uuid_cb_data cb_data;
2735 struct obd_device *obd = stats->nid_obd;
2740 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
2741 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
2742 lprocfs_exp_print_uuid, &cb_data);
2743 return (*cb_data.len);
2746 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
2747 cfs_hlist_node_t *hnode, void *cb_data)
2750 struct exp_uuid_cb_data *data = cb_data;
2751 struct obd_export *exp = cfs_hash_object(hs, hnode);
2753 if (exp->exp_lock_hash != NULL) {
2755 *data->len += cfs_hash_debug_header(data->page,
2758 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
2765 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
2766 int *eof, void *data)
2768 struct nid_stat *stats = (struct nid_stat *)data;
2769 struct exp_uuid_cb_data cb_data;
2770 struct obd_device *obd = stats->nid_obd;
2775 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
2777 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
2778 lprocfs_exp_print_hash, &cb_data);
2779 return (*cb_data.len);
2782 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
2783 int count, int *eof, void *data)
2786 return snprintf(page, count, "%s\n",
2787 "Write into this file to clear all nid stats and "
2788 "stale nid entries");
2790 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
2792 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
2793 unsigned long count, void *data)
2795 struct obd_device *obd = (struct obd_device *)data;
2796 struct nid_stat *client_stat;
2797 CFS_LIST_HEAD(free_list);
2799 cfs_hash_cond_del(obd->obd_nid_stats_hash,
2800 lprocfs_nid_stats_clear_write_cb, &free_list);
2802 while (!cfs_list_empty(&free_list)) {
2803 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
2805 cfs_list_del_init(&client_stat->nid_list);
2806 lprocfs_free_client_stats(client_stat);
2811 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
2814 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
2816 struct nid_stat *new_stat, *old_stat;
2817 struct obd_device *obd = NULL;
2818 cfs_proc_dir_entry_t *entry;
2819 char *buffer = NULL;
2825 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
2826 !exp->exp_obd->obd_nid_stats_hash)
2829 /* not test against zero because eric say:
2830 * You may only test nid against another nid, or LNET_NID_ANY.
2831 * Anything else is nonsense.*/
2832 if (!nid || *nid == LNET_NID_ANY)
2835 spin_lock(&exp->exp_lock);
2836 if (exp->exp_nid_stats != NULL) {
2837 spin_unlock(&exp->exp_lock);
2840 spin_unlock(&exp->exp_lock);
2844 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
2846 OBD_ALLOC_PTR(new_stat);
2847 if (new_stat == NULL)
2850 new_stat->nid = *nid;
2851 new_stat->nid_obd = exp->exp_obd;
2852 /* we need set default refcount to 1 to balance obd_disconnect */
2853 atomic_set(&new_stat->nid_exp_ref_count, 1);
2855 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
2856 nid, &new_stat->nid_hash);
2857 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
2858 old_stat, libcfs_nid2str(*nid),
2859 atomic_read(&new_stat->nid_exp_ref_count));
2861 /* Return -EALREADY here so that we know that the /proc
2862 * entry already has been created */
2863 if (old_stat != new_stat) {
2864 nidstat_putref(old_stat);
2865 GOTO(destroy_new, rc = -EALREADY);
2867 /* not found - create */
2868 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
2870 GOTO(destroy_new, rc = -ENOMEM);
2872 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
2873 #ifndef HAVE_ONLY_PROCFS_SEQ
2874 new_stat->nid_proc = lprocfs_register(buffer,
2875 obd->obd_proc_exports_entry,
2878 new_stat->nid_proc = lprocfs_seq_register(buffer,
2879 obd->obd_proc_exports_entry,
2882 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
2884 if (IS_ERR(new_stat->nid_proc)) {
2885 rc = PTR_ERR(new_stat->nid_proc);
2886 new_stat->nid_proc = NULL;
2887 CERROR("%s: cannot create proc entry for export %s: rc = %d\n",
2888 obd->obd_name, libcfs_nid2str(*nid), rc);
2889 GOTO(destroy_new_ns, rc);
2892 #ifndef HAVE_ONLY_PROCFS_SEQ
2893 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
2894 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
2896 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
2897 new_stat, &lprocfs_exp_uuid_fops);
2899 if (IS_ERR(entry)) {
2900 CWARN("Error adding the NID stats file\n");
2901 rc = PTR_ERR(entry);
2902 GOTO(destroy_new_ns, rc);
2905 #ifndef HAVE_ONLY_PROCFS_SEQ
2906 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
2907 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
2909 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
2910 new_stat, &lprocfs_exp_hash_fops);
2912 if (IS_ERR(entry)) {
2913 CWARN("Error adding the hash file\n");
2914 rc = PTR_ERR(entry);
2915 GOTO(destroy_new_ns, rc);
2918 spin_lock(&exp->exp_lock);
2919 exp->exp_nid_stats = new_stat;
2920 spin_unlock(&exp->exp_lock);
2922 /* protect competitive add to list, not need locking on destroy */
2923 spin_lock(&obd->obd_nid_lock);
2924 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
2925 spin_unlock(&obd->obd_nid_lock);
2930 if (new_stat->nid_proc != NULL)
2931 lprocfs_remove(&new_stat->nid_proc);
2932 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
2935 nidstat_putref(new_stat);
2936 OBD_FREE_PTR(new_stat);
2939 EXPORT_SYMBOL(lprocfs_exp_setup);
2942 int lprocfs_exp_cleanup(struct obd_export *exp)
2944 struct nid_stat *stat = exp->exp_nid_stats;
2946 if(!stat || !exp->exp_obd)
2949 nidstat_putref(exp->exp_nid_stats);
2950 exp->exp_nid_stats = NULL;
2954 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2956 __s64 lprocfs_read_helper(struct lprocfs_counter *lc,
2957 struct lprocfs_counter_header *header,
2958 enum lprocfs_stats_flags flags,
2959 enum lprocfs_fields_flags field)
2963 if (lc == NULL || header == NULL)
2967 case LPROCFS_FIELDS_FLAGS_CONFIG:
2968 ret = header->lc_config;
2970 case LPROCFS_FIELDS_FLAGS_SUM:
2972 if ((flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
2973 ret += lc->lc_sum_irq;
2975 case LPROCFS_FIELDS_FLAGS_MIN:
2978 case LPROCFS_FIELDS_FLAGS_MAX:
2981 case LPROCFS_FIELDS_FLAGS_AVG:
2982 ret = (lc->lc_max - lc->lc_min) / 2;
2984 case LPROCFS_FIELDS_FLAGS_SUMSQUARE:
2985 ret = lc->lc_sumsquare;
2987 case LPROCFS_FIELDS_FLAGS_COUNT:
2995 EXPORT_SYMBOL(lprocfs_read_helper);
2997 int lprocfs_write_helper(const char *buffer, unsigned long count,
3000 return lprocfs_write_frac_helper(buffer, count, val, 1);
3002 EXPORT_SYMBOL(lprocfs_write_helper);
3004 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
3007 char kernbuf[20], *end, *pbuf;
3009 if (count > (sizeof(kernbuf) - 1))
3012 if (copy_from_user(kernbuf, buffer, count))
3015 kernbuf[count] = '\0';
3022 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
3026 if (end != NULL && *end == '.') {
3027 int temp_val, pow = 1;
3031 if (strlen(pbuf) > 5)
3032 pbuf[5] = '\0'; /*only allow 5bits fractional*/
3034 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
3037 for (i = 0; i < (end - pbuf); i++)
3040 *val += temp_val / pow;
3045 EXPORT_SYMBOL(lprocfs_write_frac_helper);
3047 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
3050 long decimal_val, frac_val;
3056 decimal_val = val / mult;
3057 prtn = snprintf(buffer, count, "%ld", decimal_val);
3058 frac_val = val % mult;
3060 if (prtn < (count - 4) && frac_val > 0) {
3062 int i, temp_mult = 1, frac_bits = 0;
3064 temp_frac = frac_val * 10;
3065 buffer[prtn++] = '.';
3066 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
3067 /* only reserved 2 bits fraction */
3068 buffer[prtn++] ='0';
3073 * Need to think these cases :
3074 * 1. #echo x.00 > /proc/xxx output result : x
3075 * 2. #echo x.0x > /proc/xxx output result : x.0x
3076 * 3. #echo x.x0 > /proc/xxx output result : x.x
3077 * 4. #echo x.xx > /proc/xxx output result : x.xx
3078 * Only reserved 2 bits fraction.
3080 for (i = 0; i < (5 - prtn); i++)
3083 frac_bits = min((int)count - prtn, 3 - frac_bits);
3084 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
3085 frac_val * temp_mult / mult);
3088 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
3090 if (buffer[prtn] == '.') {
3097 buffer[prtn++] ='\n';
3100 EXPORT_SYMBOL(lprocfs_read_frac_helper);
3102 int lprocfs_seq_read_frac_helper(struct seq_file *m, long val, int mult)
3104 long decimal_val, frac_val;
3106 decimal_val = val / mult;
3107 seq_printf(m, "%ld", decimal_val);
3108 frac_val = val % mult;
3115 /* Three cases: x0, xx, 0x */
3116 if ((frac_val % 10) != 0)
3117 seq_printf(m, ".%ld", frac_val);
3119 seq_printf(m, ".%ld", frac_val / 10);
3122 seq_printf(m, "\n");
3125 EXPORT_SYMBOL(lprocfs_seq_read_frac_helper);
3127 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
3129 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
3131 EXPORT_SYMBOL(lprocfs_write_u64_helper);
3133 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
3134 __u64 *val, int mult)
3136 char kernbuf[22], *end, *pbuf;
3137 __u64 whole, frac = 0, units;
3138 unsigned frac_d = 1;
3140 if (count > (sizeof(kernbuf) - 1))
3143 if (copy_from_user(kernbuf, buffer, count))
3146 kernbuf[count] = '\0';
3153 whole = simple_strtoull(pbuf, &end, 10);
3157 if (end != NULL && *end == '.') {
3161 /* need to limit frac_d to a __u32 */
3162 if (strlen(pbuf) > 10)
3165 frac = simple_strtoull(pbuf, &end, 10);
3166 /* count decimal places */
3167 for (i = 0; i < (end - pbuf); i++)
3186 /* Specified units override the multiplier */
3188 mult = mult < 0 ? -units : units;
3191 do_div(frac, frac_d);
3192 *val = whole * mult + frac;
3195 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
3197 static char *lprocfs_strnstr(const char *s1, const char *s2, size_t len)
3206 if (!memcmp(s1, s2, l2))
3214 * Find the string \a name in the input \a buffer, and return a pointer to the
3215 * value immediately following \a name, reducing \a count appropriately.
3216 * If \a name is not found the original \a buffer is returned.
3218 char *lprocfs_find_named_value(const char *buffer, const char *name,
3222 size_t buflen = *count;
3224 /* there is no strnstr() in rhel5 and ubuntu kernels */
3225 val = lprocfs_strnstr(buffer, name, buflen);
3227 return (char *)buffer;
3229 val += strlen(name); /* skip prefix */
3230 while (val < buffer + buflen && isspace(*val)) /* skip separator */
3234 while (val < buffer + buflen && isalnum(*val)) {
3239 return val - *count;
3241 EXPORT_SYMBOL(lprocfs_find_named_value);
3243 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent,
3246 const struct file_operations *seq_fops,
3249 struct proc_dir_entry *entry;
3252 /* Disallow secretly (un)writable entries. */
3253 LASSERT((seq_fops->write == NULL) == ((mode & 0222) == 0));
3255 entry = proc_create_data(name, mode, parent, seq_fops, data);
3262 EXPORT_SYMBOL(lprocfs_seq_create);
3264 int lprocfs_obd_seq_create(struct obd_device *dev,
3267 const struct file_operations *seq_fops,
3270 return (lprocfs_seq_create(dev->obd_proc_entry, name,
3271 mode, seq_fops, data));
3273 EXPORT_SYMBOL(lprocfs_obd_seq_create);
3275 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
3277 if (value >= OBD_HIST_MAX)
3278 value = OBD_HIST_MAX - 1;
3280 spin_lock(&oh->oh_lock);
3281 oh->oh_buckets[value]++;
3282 spin_unlock(&oh->oh_lock);
3284 EXPORT_SYMBOL(lprocfs_oh_tally);
3286 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
3288 unsigned int val = 0;
3290 if (likely(value != 0))
3291 val = min(fls(value - 1), OBD_HIST_MAX);
3293 lprocfs_oh_tally(oh, val);
3295 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
3297 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
3299 unsigned long ret = 0;
3302 for (i = 0; i < OBD_HIST_MAX; i++)
3303 ret += oh->oh_buckets[i];
3306 EXPORT_SYMBOL(lprocfs_oh_sum);
3308 void lprocfs_oh_clear(struct obd_histogram *oh)
3310 spin_lock(&oh->oh_lock);
3311 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
3312 spin_unlock(&oh->oh_lock);
3314 EXPORT_SYMBOL(lprocfs_oh_clear);
3316 #ifdef HAVE_SERVER_SUPPORT
3317 int lprocfs_hash_seq_show(struct seq_file *m, void *data)
3319 struct obd_device *obd = m->private;
3325 c += cfs_hash_debug_header_seq(m);
3326 c += cfs_hash_debug_str_seq(obd->obd_uuid_hash, m);
3327 c += cfs_hash_debug_str_seq(obd->obd_nid_hash, m);
3328 c += cfs_hash_debug_str_seq(obd->obd_nid_stats_hash, m);
3331 EXPORT_SYMBOL(lprocfs_hash_seq_show);
3333 int lprocfs_recovery_status_seq_show(struct seq_file *m, void *data)
3335 struct obd_device *obd = m->private;
3337 LASSERT(obd != NULL);
3339 seq_printf(m, "status: \n");
3340 if (obd->obd_max_recoverable_clients == 0) {
3341 seq_printf(m, "INACTIVE\n");
3345 /* sampled unlocked, but really... */
3346 if (obd->obd_recovering == 0) {
3347 seq_printf(m, "COMPLETE\n");
3348 seq_printf(m, "recovery_start: %lu\n", obd->obd_recovery_start);
3349 seq_printf(m, "recovery_duration: %lu\n",
3350 obd->obd_recovery_end - obd->obd_recovery_start);
3351 /* Number of clients that have completed recovery */
3352 seq_printf(m, "completed_clients: %d/%d\n",
3353 obd->obd_max_recoverable_clients -
3354 obd->obd_stale_clients,
3355 obd->obd_max_recoverable_clients);
3356 seq_printf(m, "replayed_requests: %d\n",
3357 obd->obd_replayed_requests);
3358 seq_printf(m, "last_transno: "LPD64"\n",
3359 obd->obd_next_recovery_transno - 1);
3360 seq_printf(m, "VBR: %s\n", obd->obd_version_recov ?
3361 "ENABLED" : "DISABLED");
3362 seq_printf(m, "IR: %s\n", obd->obd_no_ir ?
3363 "DISABLED" : "ENABLED");
3367 seq_printf(m, "RECOVERING\n");
3368 seq_printf(m, "recovery_start: %lu\n", obd->obd_recovery_start);
3369 seq_printf(m, "time_remaining: %lu\n",
3370 cfs_time_current_sec() >=
3371 obd->obd_recovery_start +
3372 obd->obd_recovery_timeout ? 0 :
3373 obd->obd_recovery_start +
3374 obd->obd_recovery_timeout -
3375 cfs_time_current_sec());
3376 seq_printf(m, "connected_clients: %d/%d\n",
3377 atomic_read(&obd->obd_connected_clients),
3378 obd->obd_max_recoverable_clients);
3379 /* Number of clients that have completed recovery */
3380 seq_printf(m, "req_replay_clients: %d\n",
3381 atomic_read(&obd->obd_req_replay_clients));
3382 seq_printf(m, "lock_repay_clients: %d\n",
3383 atomic_read(&obd->obd_lock_replay_clients));
3384 seq_printf(m, "completed_clients: %d\n",
3385 atomic_read(&obd->obd_connected_clients) -
3386 atomic_read(&obd->obd_lock_replay_clients));
3387 seq_printf(m, "evicted_clients: %d\n", obd->obd_stale_clients);
3388 seq_printf(m, "replayed_requests: %d\n", obd->obd_replayed_requests);
3389 seq_printf(m, "queued_requests: %d\n",
3390 obd->obd_requests_queued_for_recovery);
3391 seq_printf(m, "next_transno: "LPD64"\n",
3392 obd->obd_next_recovery_transno);
3396 EXPORT_SYMBOL(lprocfs_recovery_status_seq_show);
3398 int lprocfs_ir_factor_seq_show(struct seq_file *m, void *data)
3400 struct obd_device *obd = m->private;
3402 LASSERT(obd != NULL);
3403 return seq_printf(m, "%d\n", obd->obd_recovery_ir_factor);
3405 EXPORT_SYMBOL(lprocfs_ir_factor_seq_show);
3408 lprocfs_ir_factor_seq_write(struct file *file, const char *buffer,
3409 size_t count, loff_t *off)
3411 struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
3414 LASSERT(obd != NULL);
3415 rc = lprocfs_write_helper(buffer, count, &val);
3419 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
3422 obd->obd_recovery_ir_factor = val;
3425 EXPORT_SYMBOL(lprocfs_ir_factor_seq_write);
3427 int lprocfs_recovery_time_soft_seq_show(struct seq_file *m, void *data)
3429 struct obd_device *obd = m->private;
3431 LASSERT(obd != NULL);
3432 return seq_printf(m, "%d\n", obd->obd_recovery_timeout);
3434 EXPORT_SYMBOL(lprocfs_recovery_time_soft_seq_show);
3437 lprocfs_recovery_time_soft_seq_write(struct file *file, const char *buffer,
3438 size_t count, loff_t *off)
3440 struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
3443 LASSERT(obd != NULL);
3444 rc = lprocfs_write_helper(buffer, count, &val);
3448 obd->obd_recovery_timeout = val;
3451 EXPORT_SYMBOL(lprocfs_recovery_time_soft_seq_write);
3453 int lprocfs_recovery_time_hard_seq_show(struct seq_file *m, void *data)
3455 struct obd_device *obd = m->private;
3457 LASSERT(obd != NULL);
3458 return seq_printf(m, "%u\n", obd->obd_recovery_time_hard);
3460 EXPORT_SYMBOL(lprocfs_recovery_time_hard_seq_show);
3463 lprocfs_recovery_time_hard_seq_write(struct file *file, const char *buffer,
3464 size_t count, loff_t *off)
3466 struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
3469 LASSERT(obd != NULL);
3470 rc = lprocfs_write_helper(buffer, count, &val);
3474 obd->obd_recovery_time_hard = val;
3477 EXPORT_SYMBOL(lprocfs_recovery_time_hard_seq_write);
3479 int lprocfs_target_instance_seq_show(struct seq_file *m, void *data)
3481 struct obd_device *obd = m->private;
3482 struct obd_device_target *target = &obd->u.obt;
3484 LASSERT(obd != NULL);
3485 LASSERT(target->obt_magic == OBT_MAGIC);
3486 return seq_printf(m, "%u\n", obd->u.obt.obt_instance);
3488 EXPORT_SYMBOL(lprocfs_target_instance_seq_show);
3490 #ifndef HAVE_ONLY_PROCFS_SEQ
3491 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
3492 int count, int *eof, void *data)
3494 struct obd_device *obd = data;
3500 c += cfs_hash_debug_header(page, count);
3501 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
3502 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
3503 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
3507 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
3509 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
3510 int count, int *eof, void *data)
3512 struct obd_device *obd = data;
3515 LASSERT(obd != NULL);
3516 LASSERT(count >= 0);
3518 /* Set start of user data returned to
3519 page + off since the user may have
3520 requested to read much smaller than
3521 what we need to read */
3522 *start = page + off;
3525 * We know we are allocated a page here.
3526 * Also we know that this function will
3527 * not need to write more than a page
3528 * so we can truncate at PAGE_CACHE_SIZE.
3530 size = min(count + (int)off + 1, (int)PAGE_CACHE_SIZE);
3532 /* Initialize the page */
3533 memset(page, 0, size);
3535 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
3537 if (obd->obd_max_recoverable_clients == 0) {
3538 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
3544 /* sampled unlocked, but really... */
3545 if (obd->obd_recovering == 0) {
3546 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
3548 if (lprocfs_obd_snprintf(&page, size, &len,
3549 "recovery_start: %lu\n",
3550 obd->obd_recovery_start) <= 0)
3552 if (lprocfs_obd_snprintf(&page, size, &len,
3553 "recovery_duration: %lu\n",
3554 obd->obd_recovery_end -
3555 obd->obd_recovery_start) <= 0)
3557 /* Number of clients that have completed recovery */
3558 if (lprocfs_obd_snprintf(&page, size, &len,
3559 "completed_clients: %d/%d\n",
3560 obd->obd_max_recoverable_clients -
3561 obd->obd_stale_clients,
3562 obd->obd_max_recoverable_clients) <= 0)
3564 if (lprocfs_obd_snprintf(&page, size, &len,
3565 "replayed_requests: %d\n",
3566 obd->obd_replayed_requests) <= 0)
3568 if (lprocfs_obd_snprintf(&page, size, &len,
3569 "last_transno: "LPD64"\n",
3570 obd->obd_next_recovery_transno - 1)<=0)
3572 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
3573 obd->obd_version_recov ?
3574 "ENABLED" : "DISABLED") <=0)
3576 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
3578 "DISABLED" : "ENABLED") <= 0)
3583 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
3585 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
3586 obd->obd_recovery_start) <= 0)
3588 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
3589 cfs_time_current_sec() >=
3590 obd->obd_recovery_start +
3591 obd->obd_recovery_timeout ? 0 :
3592 obd->obd_recovery_start +
3593 obd->obd_recovery_timeout -
3594 cfs_time_current_sec()) <= 0)
3596 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
3597 atomic_read(&obd->obd_connected_clients),
3598 obd->obd_max_recoverable_clients) <= 0)
3600 /* Number of clients that have completed recovery */
3601 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
3602 atomic_read(&obd->obd_req_replay_clients))
3605 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
3606 atomic_read(&obd->obd_lock_replay_clients))
3609 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
3610 atomic_read(&obd->obd_connected_clients) -
3611 atomic_read(&obd->obd_lock_replay_clients))
3614 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
3615 obd->obd_stale_clients) <= 0)
3617 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
3618 obd->obd_replayed_requests) <= 0)
3620 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
3621 obd->obd_requests_queued_for_recovery) <= 0)
3624 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
3625 obd->obd_next_recovery_transno) <= 0)
3631 return min(count, len - (int)off);
3633 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
3635 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
3636 int count, int *eof, void *data)
3638 struct obd_device *obd = (struct obd_device *)data;
3639 LASSERT(obd != NULL);
3641 return snprintf(page, count, "%d\n",
3642 obd->obd_recovery_ir_factor);
3644 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
3646 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
3647 unsigned long count, void *data)
3649 struct obd_device *obd = (struct obd_device *)data;
3651 LASSERT(obd != NULL);
3653 rc = lprocfs_write_helper(buffer, count, &val);
3657 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
3660 obd->obd_recovery_ir_factor = val;
3663 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
3665 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
3666 int count, int *eof, void *data)
3668 struct obd_device *obd = (struct obd_device *)data;
3669 LASSERT(obd != NULL);
3671 return snprintf(page, count, "%d\n",
3672 obd->obd_recovery_timeout);
3674 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
3676 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
3677 unsigned long count, void *data)
3679 struct obd_device *obd = (struct obd_device *)data;
3681 LASSERT(obd != NULL);
3683 rc = lprocfs_write_helper(buffer, count, &val);
3687 obd->obd_recovery_timeout = val;
3690 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
3692 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
3693 int count, int *eof, void *data)
3695 struct obd_device *obd = data;
3696 LASSERT(obd != NULL);
3698 return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
3700 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
3702 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
3703 unsigned long count, void *data)
3705 struct obd_device *obd = data;
3707 LASSERT(obd != NULL);
3709 rc = lprocfs_write_helper(buffer, count, &val);
3713 obd->obd_recovery_time_hard = val;
3716 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
3718 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
3719 int count, int *eof, void *data)
3721 struct obd_device *obd = (struct obd_device *)data;
3722 struct obd_device_target *target = &obd->u.obt;
3724 LASSERT(obd != NULL);
3725 LASSERT(target->obt_magic == OBT_MAGIC);
3727 return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
3729 EXPORT_SYMBOL(lprocfs_target_rd_instance);
3730 #endif /* HAVE_ONLY_PROCFS_SEQ */
3731 #endif /* HAVE_SERVER_SUPPORT */
3733 int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
3734 int count, int *eof, void *data)
3736 struct obd_device *dev = data;
3737 struct client_obd *cli = &dev->u.cli;
3740 client_obd_list_lock(&cli->cl_loi_list_lock);
3741 rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
3742 client_obd_list_unlock(&cli->cl_loi_list_lock);
3745 EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
3747 int lprocfs_obd_max_pages_per_rpc_seq_show(struct seq_file *m, void *data)
3749 struct obd_device *dev = data;
3750 struct client_obd *cli = &dev->u.cli;
3753 client_obd_list_lock(&cli->cl_loi_list_lock);
3754 rc = seq_printf(m, "%d\n", cli->cl_max_pages_per_rpc);
3755 client_obd_list_unlock(&cli->cl_loi_list_lock);
3758 EXPORT_SYMBOL(lprocfs_obd_max_pages_per_rpc_seq_show);