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, update_lsm_md);
2486 LPROCFS_MD_OP_INIT(num_private_stats, stats, merge_attr);
2487 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
2488 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
2489 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
2490 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
2491 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
2492 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
2493 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
2494 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
2495 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
2496 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
2498 EXPORT_SYMBOL(lprocfs_init_mps_stats);
2500 int lprocfs_alloc_md_stats(struct obd_device *obd,
2501 unsigned int num_private_stats)
2503 struct lprocfs_stats *stats;
2504 unsigned int num_stats;
2507 CLASSERT(offsetof(struct md_ops, MD_STATS_FIRST_OP) == 0);
2508 CLASSERT(_MD_COUNTER_OFFSET(MD_STATS_FIRST_OP) == 0);
2509 CLASSERT(_MD_COUNTER_OFFSET(MD_STATS_LAST_OP) > 0);
2511 /* TODO Ensure that this function is only used where
2512 * appropriate by adding an assertion to the effect that
2513 * obd->obd_type->typ_md_ops is not NULL. We can't do this now
2514 * because mdt_procfs_init() uses this function to allocate
2515 * the stats backing /proc/fs/lustre/mdt/.../md_stats but the
2516 * mdt layer does not use the md_ops interface. This is
2517 * confusing and a waste of memory. See LU-2484.
2519 LASSERT(obd->obd_proc_entry != NULL);
2520 LASSERT(obd->obd_md_stats == NULL);
2521 LASSERT(obd->obd_md_cntr_base == 0);
2523 num_stats = NUM_MD_STATS + num_private_stats;
2524 stats = lprocfs_alloc_stats(num_stats, 0);
2528 lprocfs_init_mps_stats(num_private_stats, stats);
2530 for (i = num_private_stats; i < num_stats; i++) {
2531 if (stats->ls_cnt_header[i].lc_name == NULL) {
2532 CERROR("Missing md_stat initializer md_op "
2533 "operation at offset %d. Aborting.\n",
2534 i - num_private_stats);
2539 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
2541 lprocfs_free_stats(&stats);
2543 obd->obd_md_stats = stats;
2544 obd->obd_md_cntr_base = num_private_stats;
2549 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
2551 void lprocfs_free_md_stats(struct obd_device *obd)
2553 struct lprocfs_stats *stats = obd->obd_md_stats;
2555 if (stats != NULL) {
2556 obd->obd_md_stats = NULL;
2557 obd->obd_md_cntr_base = 0;
2558 lprocfs_free_stats(&stats);
2561 EXPORT_SYMBOL(lprocfs_free_md_stats);
2563 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
2565 lprocfs_counter_init(ldlm_stats,
2566 LDLM_ENQUEUE - LDLM_FIRST_OPC,
2567 0, "ldlm_enqueue", "reqs");
2568 lprocfs_counter_init(ldlm_stats,
2569 LDLM_CONVERT - LDLM_FIRST_OPC,
2570 0, "ldlm_convert", "reqs");
2571 lprocfs_counter_init(ldlm_stats,
2572 LDLM_CANCEL - LDLM_FIRST_OPC,
2573 0, "ldlm_cancel", "reqs");
2574 lprocfs_counter_init(ldlm_stats,
2575 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
2576 0, "ldlm_bl_callback", "reqs");
2577 lprocfs_counter_init(ldlm_stats,
2578 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
2579 0, "ldlm_cp_callback", "reqs");
2580 lprocfs_counter_init(ldlm_stats,
2581 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
2582 0, "ldlm_gl_callback", "reqs");
2584 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
2586 #ifdef HAVE_SERVER_SUPPORT
2587 /* No one appears to be using this ?? */
2588 int lprocfs_exp_nid_seq_show(struct seq_file *m, void *data)
2590 struct obd_export *exp = m->private;
2591 LASSERT(exp != NULL);
2592 return seq_printf(m, "%s\n", obd_export_nid2str(exp));
2595 int lprocfs_exp_print_uuid_seq(cfs_hash_t *hs, cfs_hash_bd_t *bd,
2596 cfs_hlist_node_t *hnode, void *cb_data)
2599 struct obd_export *exp = cfs_hash_object(hs, hnode);
2600 struct seq_file *m = cb_data;
2602 if (exp->exp_nid_stats)
2603 seq_printf(m, "%s\n", obd_uuid2str(&exp->exp_client_uuid));
2607 int lprocfs_exp_uuid_seq_show(struct seq_file *m, void *data)
2609 struct nid_stat *stats = m->private;
2610 struct obd_device *obd = stats->nid_obd;
2612 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
2613 lprocfs_exp_print_uuid_seq, m);
2616 LPROC_SEQ_FOPS_RO(lprocfs_exp_uuid);
2618 int lprocfs_exp_print_hash_seq(cfs_hash_t *hs, cfs_hash_bd_t *bd,
2619 cfs_hlist_node_t *hnode, void *cb_data)
2622 struct seq_file *m = cb_data;
2623 struct obd_export *exp = cfs_hash_object(hs, hnode);
2625 if (exp->exp_lock_hash != NULL) {
2626 cfs_hash_debug_header_seq(m);
2627 cfs_hash_debug_str_seq(hs, m);
2632 int lprocfs_exp_hash_seq_show(struct seq_file *m, void *data)
2634 struct nid_stat *stats = m->private;
2635 struct obd_device *obd = stats->nid_obd;
2637 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
2638 lprocfs_exp_print_hash_seq, m);
2641 LPROC_SEQ_FOPS_RO(lprocfs_exp_hash);
2643 int lprocfs_nid_stats_clear_seq_show(struct seq_file *m, void *data)
2645 return seq_printf(m, "%s\n", "Write into this file to clear all nid "
2646 "stats and stale nid entries");
2648 EXPORT_SYMBOL(lprocfs_nid_stats_clear_seq_show);
2650 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
2652 struct nid_stat *stat = obj;
2655 CDEBUG(D_INFO,"refcnt %d\n", atomic_read(&stat->nid_exp_ref_count));
2656 if (atomic_read(&stat->nid_exp_ref_count) == 1) {
2657 /* object has only hash references. */
2658 spin_lock(&stat->nid_obd->obd_nid_lock);
2659 cfs_list_move(&stat->nid_list, data);
2660 spin_unlock(&stat->nid_obd->obd_nid_lock);
2663 /* we has reference to object - only clear data*/
2664 if (stat->nid_stats)
2665 lprocfs_clear_stats(stat->nid_stats);
2671 lprocfs_nid_stats_clear_seq_write(struct file *file, const char *buffer,
2672 size_t count, loff_t *off)
2674 struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
2675 struct nid_stat *client_stat;
2676 CFS_LIST_HEAD(free_list);
2678 cfs_hash_cond_del(obd->obd_nid_stats_hash,
2679 lprocfs_nid_stats_clear_write_cb, &free_list);
2681 while (!cfs_list_empty(&free_list)) {
2682 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
2684 cfs_list_del_init(&client_stat->nid_list);
2685 lprocfs_free_client_stats(client_stat);
2689 EXPORT_SYMBOL(lprocfs_nid_stats_clear_seq_write);
2691 #ifndef HAVE_ONLY_PROCFS_SEQ
2692 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
2693 int *eof, void *data)
2695 struct obd_export *exp = data;
2696 LASSERT(exp != NULL);
2698 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
2701 struct exp_uuid_cb_data {
2709 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
2710 int count, int *eof, int *len)
2712 cb_data->page = page;
2713 cb_data->count = count;
2718 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
2719 cfs_hlist_node_t *hnode, void *cb_data)
2722 struct obd_export *exp = cfs_hash_object(hs, hnode);
2723 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
2725 if (exp->exp_nid_stats)
2726 *data->len += snprintf((data->page + *data->len),
2727 data->count, "%s\n",
2728 obd_uuid2str(&exp->exp_client_uuid));
2732 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
2733 int *eof, void *data)
2735 struct nid_stat *stats = (struct nid_stat *)data;
2736 struct exp_uuid_cb_data cb_data;
2737 struct obd_device *obd = stats->nid_obd;
2742 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
2743 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
2744 lprocfs_exp_print_uuid, &cb_data);
2745 return (*cb_data.len);
2748 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
2749 cfs_hlist_node_t *hnode, void *cb_data)
2752 struct exp_uuid_cb_data *data = cb_data;
2753 struct obd_export *exp = cfs_hash_object(hs, hnode);
2755 if (exp->exp_lock_hash != NULL) {
2757 *data->len += cfs_hash_debug_header(data->page,
2760 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
2767 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
2768 int *eof, void *data)
2770 struct nid_stat *stats = (struct nid_stat *)data;
2771 struct exp_uuid_cb_data cb_data;
2772 struct obd_device *obd = stats->nid_obd;
2777 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
2779 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
2780 lprocfs_exp_print_hash, &cb_data);
2781 return (*cb_data.len);
2784 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
2785 int count, int *eof, void *data)
2788 return snprintf(page, count, "%s\n",
2789 "Write into this file to clear all nid stats and "
2790 "stale nid entries");
2792 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
2794 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
2795 unsigned long count, void *data)
2797 struct obd_device *obd = (struct obd_device *)data;
2798 struct nid_stat *client_stat;
2799 CFS_LIST_HEAD(free_list);
2801 cfs_hash_cond_del(obd->obd_nid_stats_hash,
2802 lprocfs_nid_stats_clear_write_cb, &free_list);
2804 while (!cfs_list_empty(&free_list)) {
2805 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
2807 cfs_list_del_init(&client_stat->nid_list);
2808 lprocfs_free_client_stats(client_stat);
2813 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
2816 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
2818 struct nid_stat *new_stat, *old_stat;
2819 struct obd_device *obd = NULL;
2820 cfs_proc_dir_entry_t *entry;
2821 char *buffer = NULL;
2827 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
2828 !exp->exp_obd->obd_nid_stats_hash)
2831 /* not test against zero because eric say:
2832 * You may only test nid against another nid, or LNET_NID_ANY.
2833 * Anything else is nonsense.*/
2834 if (!nid || *nid == LNET_NID_ANY)
2837 spin_lock(&exp->exp_lock);
2838 if (exp->exp_nid_stats != NULL) {
2839 spin_unlock(&exp->exp_lock);
2842 spin_unlock(&exp->exp_lock);
2846 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
2848 OBD_ALLOC_PTR(new_stat);
2849 if (new_stat == NULL)
2852 new_stat->nid = *nid;
2853 new_stat->nid_obd = exp->exp_obd;
2854 /* we need set default refcount to 1 to balance obd_disconnect */
2855 atomic_set(&new_stat->nid_exp_ref_count, 1);
2857 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
2858 nid, &new_stat->nid_hash);
2859 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
2860 old_stat, libcfs_nid2str(*nid),
2861 atomic_read(&new_stat->nid_exp_ref_count));
2863 /* Return -EALREADY here so that we know that the /proc
2864 * entry already has been created */
2865 if (old_stat != new_stat) {
2866 nidstat_putref(old_stat);
2867 GOTO(destroy_new, rc = -EALREADY);
2869 /* not found - create */
2870 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
2872 GOTO(destroy_new, rc = -ENOMEM);
2874 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
2875 #ifndef HAVE_ONLY_PROCFS_SEQ
2876 new_stat->nid_proc = lprocfs_register(buffer,
2877 obd->obd_proc_exports_entry,
2880 new_stat->nid_proc = lprocfs_seq_register(buffer,
2881 obd->obd_proc_exports_entry,
2884 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
2886 if (IS_ERR(new_stat->nid_proc)) {
2887 rc = PTR_ERR(new_stat->nid_proc);
2888 new_stat->nid_proc = NULL;
2889 CERROR("%s: cannot create proc entry for export %s: rc = %d\n",
2890 obd->obd_name, libcfs_nid2str(*nid), rc);
2891 GOTO(destroy_new_ns, rc);
2894 #ifndef HAVE_ONLY_PROCFS_SEQ
2895 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
2896 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
2898 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
2899 new_stat, &lprocfs_exp_uuid_fops);
2901 if (IS_ERR(entry)) {
2902 CWARN("Error adding the NID stats file\n");
2903 rc = PTR_ERR(entry);
2904 GOTO(destroy_new_ns, rc);
2907 #ifndef HAVE_ONLY_PROCFS_SEQ
2908 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
2909 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
2911 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
2912 new_stat, &lprocfs_exp_hash_fops);
2914 if (IS_ERR(entry)) {
2915 CWARN("Error adding the hash file\n");
2916 rc = PTR_ERR(entry);
2917 GOTO(destroy_new_ns, rc);
2920 spin_lock(&exp->exp_lock);
2921 exp->exp_nid_stats = new_stat;
2922 spin_unlock(&exp->exp_lock);
2924 /* protect competitive add to list, not need locking on destroy */
2925 spin_lock(&obd->obd_nid_lock);
2926 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
2927 spin_unlock(&obd->obd_nid_lock);
2932 if (new_stat->nid_proc != NULL)
2933 lprocfs_remove(&new_stat->nid_proc);
2934 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
2937 nidstat_putref(new_stat);
2938 OBD_FREE_PTR(new_stat);
2941 EXPORT_SYMBOL(lprocfs_exp_setup);
2944 int lprocfs_exp_cleanup(struct obd_export *exp)
2946 struct nid_stat *stat = exp->exp_nid_stats;
2948 if(!stat || !exp->exp_obd)
2951 nidstat_putref(exp->exp_nid_stats);
2952 exp->exp_nid_stats = NULL;
2956 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2958 __s64 lprocfs_read_helper(struct lprocfs_counter *lc,
2959 struct lprocfs_counter_header *header,
2960 enum lprocfs_stats_flags flags,
2961 enum lprocfs_fields_flags field)
2965 if (lc == NULL || header == NULL)
2969 case LPROCFS_FIELDS_FLAGS_CONFIG:
2970 ret = header->lc_config;
2972 case LPROCFS_FIELDS_FLAGS_SUM:
2974 if ((flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
2975 ret += lc->lc_sum_irq;
2977 case LPROCFS_FIELDS_FLAGS_MIN:
2980 case LPROCFS_FIELDS_FLAGS_MAX:
2983 case LPROCFS_FIELDS_FLAGS_AVG:
2984 ret = (lc->lc_max - lc->lc_min) / 2;
2986 case LPROCFS_FIELDS_FLAGS_SUMSQUARE:
2987 ret = lc->lc_sumsquare;
2989 case LPROCFS_FIELDS_FLAGS_COUNT:
2997 EXPORT_SYMBOL(lprocfs_read_helper);
2999 int lprocfs_write_helper(const char *buffer, unsigned long count,
3002 return lprocfs_write_frac_helper(buffer, count, val, 1);
3004 EXPORT_SYMBOL(lprocfs_write_helper);
3006 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
3009 char kernbuf[20], *end, *pbuf;
3011 if (count > (sizeof(kernbuf) - 1))
3014 if (copy_from_user(kernbuf, buffer, count))
3017 kernbuf[count] = '\0';
3024 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
3028 if (end != NULL && *end == '.') {
3029 int temp_val, pow = 1;
3033 if (strlen(pbuf) > 5)
3034 pbuf[5] = '\0'; /*only allow 5bits fractional*/
3036 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
3039 for (i = 0; i < (end - pbuf); i++)
3042 *val += temp_val / pow;
3047 EXPORT_SYMBOL(lprocfs_write_frac_helper);
3049 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
3052 long decimal_val, frac_val;
3058 decimal_val = val / mult;
3059 prtn = snprintf(buffer, count, "%ld", decimal_val);
3060 frac_val = val % mult;
3062 if (prtn < (count - 4) && frac_val > 0) {
3064 int i, temp_mult = 1, frac_bits = 0;
3066 temp_frac = frac_val * 10;
3067 buffer[prtn++] = '.';
3068 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
3069 /* only reserved 2 bits fraction */
3070 buffer[prtn++] ='0';
3075 * Need to think these cases :
3076 * 1. #echo x.00 > /proc/xxx output result : x
3077 * 2. #echo x.0x > /proc/xxx output result : x.0x
3078 * 3. #echo x.x0 > /proc/xxx output result : x.x
3079 * 4. #echo x.xx > /proc/xxx output result : x.xx
3080 * Only reserved 2 bits fraction.
3082 for (i = 0; i < (5 - prtn); i++)
3085 frac_bits = min((int)count - prtn, 3 - frac_bits);
3086 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
3087 frac_val * temp_mult / mult);
3090 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
3092 if (buffer[prtn] == '.') {
3099 buffer[prtn++] ='\n';
3102 EXPORT_SYMBOL(lprocfs_read_frac_helper);
3104 int lprocfs_seq_read_frac_helper(struct seq_file *m, long val, int mult)
3106 long decimal_val, frac_val;
3108 decimal_val = val / mult;
3109 seq_printf(m, "%ld", decimal_val);
3110 frac_val = val % mult;
3117 /* Three cases: x0, xx, 0x */
3118 if ((frac_val % 10) != 0)
3119 seq_printf(m, ".%ld", frac_val);
3121 seq_printf(m, ".%ld", frac_val / 10);
3124 seq_printf(m, "\n");
3127 EXPORT_SYMBOL(lprocfs_seq_read_frac_helper);
3129 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
3131 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
3133 EXPORT_SYMBOL(lprocfs_write_u64_helper);
3135 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
3136 __u64 *val, int mult)
3138 char kernbuf[22], *end, *pbuf;
3139 __u64 whole, frac = 0, units;
3140 unsigned frac_d = 1;
3142 if (count > (sizeof(kernbuf) - 1))
3145 if (copy_from_user(kernbuf, buffer, count))
3148 kernbuf[count] = '\0';
3155 whole = simple_strtoull(pbuf, &end, 10);
3159 if (end != NULL && *end == '.') {
3163 /* need to limit frac_d to a __u32 */
3164 if (strlen(pbuf) > 10)
3167 frac = simple_strtoull(pbuf, &end, 10);
3168 /* count decimal places */
3169 for (i = 0; i < (end - pbuf); i++)
3188 /* Specified units override the multiplier */
3190 mult = mult < 0 ? -units : units;
3193 do_div(frac, frac_d);
3194 *val = whole * mult + frac;
3197 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
3199 static char *lprocfs_strnstr(const char *s1, const char *s2, size_t len)
3208 if (!memcmp(s1, s2, l2))
3216 * Find the string \a name in the input \a buffer, and return a pointer to the
3217 * value immediately following \a name, reducing \a count appropriately.
3218 * If \a name is not found the original \a buffer is returned.
3220 char *lprocfs_find_named_value(const char *buffer, const char *name,
3224 size_t buflen = *count;
3226 /* there is no strnstr() in rhel5 and ubuntu kernels */
3227 val = lprocfs_strnstr(buffer, name, buflen);
3229 return (char *)buffer;
3231 val += strlen(name); /* skip prefix */
3232 while (val < buffer + buflen && isspace(*val)) /* skip separator */
3236 while (val < buffer + buflen && isalnum(*val)) {
3241 return val - *count;
3243 EXPORT_SYMBOL(lprocfs_find_named_value);
3245 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent,
3248 const struct file_operations *seq_fops,
3251 struct proc_dir_entry *entry;
3254 /* Disallow secretly (un)writable entries. */
3255 LASSERT((seq_fops->write == NULL) == ((mode & 0222) == 0));
3257 entry = proc_create_data(name, mode, parent, seq_fops, data);
3264 EXPORT_SYMBOL(lprocfs_seq_create);
3266 int lprocfs_obd_seq_create(struct obd_device *dev,
3269 const struct file_operations *seq_fops,
3272 return (lprocfs_seq_create(dev->obd_proc_entry, name,
3273 mode, seq_fops, data));
3275 EXPORT_SYMBOL(lprocfs_obd_seq_create);
3277 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
3279 if (value >= OBD_HIST_MAX)
3280 value = OBD_HIST_MAX - 1;
3282 spin_lock(&oh->oh_lock);
3283 oh->oh_buckets[value]++;
3284 spin_unlock(&oh->oh_lock);
3286 EXPORT_SYMBOL(lprocfs_oh_tally);
3288 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
3290 unsigned int val = 0;
3292 if (likely(value != 0))
3293 val = min(fls(value - 1), OBD_HIST_MAX);
3295 lprocfs_oh_tally(oh, val);
3297 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
3299 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
3301 unsigned long ret = 0;
3304 for (i = 0; i < OBD_HIST_MAX; i++)
3305 ret += oh->oh_buckets[i];
3308 EXPORT_SYMBOL(lprocfs_oh_sum);
3310 void lprocfs_oh_clear(struct obd_histogram *oh)
3312 spin_lock(&oh->oh_lock);
3313 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
3314 spin_unlock(&oh->oh_lock);
3316 EXPORT_SYMBOL(lprocfs_oh_clear);
3318 #ifdef HAVE_SERVER_SUPPORT
3319 int lprocfs_hash_seq_show(struct seq_file *m, void *data)
3321 struct obd_device *obd = m->private;
3327 c += cfs_hash_debug_header_seq(m);
3328 c += cfs_hash_debug_str_seq(obd->obd_uuid_hash, m);
3329 c += cfs_hash_debug_str_seq(obd->obd_nid_hash, m);
3330 c += cfs_hash_debug_str_seq(obd->obd_nid_stats_hash, m);
3333 EXPORT_SYMBOL(lprocfs_hash_seq_show);
3335 int lprocfs_recovery_status_seq_show(struct seq_file *m, void *data)
3337 struct obd_device *obd = m->private;
3339 LASSERT(obd != NULL);
3341 seq_printf(m, "status: \n");
3342 if (obd->obd_max_recoverable_clients == 0) {
3343 seq_printf(m, "INACTIVE\n");
3347 /* sampled unlocked, but really... */
3348 if (obd->obd_recovering == 0) {
3349 seq_printf(m, "COMPLETE\n");
3350 seq_printf(m, "recovery_start: %lu\n", obd->obd_recovery_start);
3351 seq_printf(m, "recovery_duration: %lu\n",
3352 obd->obd_recovery_end - obd->obd_recovery_start);
3353 /* Number of clients that have completed recovery */
3354 seq_printf(m, "completed_clients: %d/%d\n",
3355 obd->obd_max_recoverable_clients -
3356 obd->obd_stale_clients,
3357 obd->obd_max_recoverable_clients);
3358 seq_printf(m, "replayed_requests: %d\n",
3359 obd->obd_replayed_requests);
3360 seq_printf(m, "last_transno: "LPD64"\n",
3361 obd->obd_next_recovery_transno - 1);
3362 seq_printf(m, "VBR: %s\n", obd->obd_version_recov ?
3363 "ENABLED" : "DISABLED");
3364 seq_printf(m, "IR: %s\n", obd->obd_no_ir ?
3365 "DISABLED" : "ENABLED");
3369 seq_printf(m, "RECOVERING\n");
3370 seq_printf(m, "recovery_start: %lu\n", obd->obd_recovery_start);
3371 seq_printf(m, "time_remaining: %lu\n",
3372 cfs_time_current_sec() >=
3373 obd->obd_recovery_start +
3374 obd->obd_recovery_timeout ? 0 :
3375 obd->obd_recovery_start +
3376 obd->obd_recovery_timeout -
3377 cfs_time_current_sec());
3378 seq_printf(m, "connected_clients: %d/%d\n",
3379 atomic_read(&obd->obd_connected_clients),
3380 obd->obd_max_recoverable_clients);
3381 /* Number of clients that have completed recovery */
3382 seq_printf(m, "req_replay_clients: %d\n",
3383 atomic_read(&obd->obd_req_replay_clients));
3384 seq_printf(m, "lock_repay_clients: %d\n",
3385 atomic_read(&obd->obd_lock_replay_clients));
3386 seq_printf(m, "completed_clients: %d\n",
3387 atomic_read(&obd->obd_connected_clients) -
3388 atomic_read(&obd->obd_lock_replay_clients));
3389 seq_printf(m, "evicted_clients: %d\n", obd->obd_stale_clients);
3390 seq_printf(m, "replayed_requests: %d\n", obd->obd_replayed_requests);
3391 seq_printf(m, "queued_requests: %d\n",
3392 obd->obd_requests_queued_for_recovery);
3393 seq_printf(m, "next_transno: "LPD64"\n",
3394 obd->obd_next_recovery_transno);
3398 EXPORT_SYMBOL(lprocfs_recovery_status_seq_show);
3400 int lprocfs_ir_factor_seq_show(struct seq_file *m, void *data)
3402 struct obd_device *obd = m->private;
3404 LASSERT(obd != NULL);
3405 return seq_printf(m, "%d\n", obd->obd_recovery_ir_factor);
3407 EXPORT_SYMBOL(lprocfs_ir_factor_seq_show);
3410 lprocfs_ir_factor_seq_write(struct file *file, const char *buffer,
3411 size_t count, loff_t *off)
3413 struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
3416 LASSERT(obd != NULL);
3417 rc = lprocfs_write_helper(buffer, count, &val);
3421 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
3424 obd->obd_recovery_ir_factor = val;
3427 EXPORT_SYMBOL(lprocfs_ir_factor_seq_write);
3429 int lprocfs_recovery_time_soft_seq_show(struct seq_file *m, void *data)
3431 struct obd_device *obd = m->private;
3433 LASSERT(obd != NULL);
3434 return seq_printf(m, "%d\n", obd->obd_recovery_timeout);
3436 EXPORT_SYMBOL(lprocfs_recovery_time_soft_seq_show);
3439 lprocfs_recovery_time_soft_seq_write(struct file *file, const char *buffer,
3440 size_t count, loff_t *off)
3442 struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
3445 LASSERT(obd != NULL);
3446 rc = lprocfs_write_helper(buffer, count, &val);
3450 obd->obd_recovery_timeout = val;
3453 EXPORT_SYMBOL(lprocfs_recovery_time_soft_seq_write);
3455 int lprocfs_recovery_time_hard_seq_show(struct seq_file *m, void *data)
3457 struct obd_device *obd = m->private;
3459 LASSERT(obd != NULL);
3460 return seq_printf(m, "%u\n", obd->obd_recovery_time_hard);
3462 EXPORT_SYMBOL(lprocfs_recovery_time_hard_seq_show);
3465 lprocfs_recovery_time_hard_seq_write(struct file *file, const char *buffer,
3466 size_t count, loff_t *off)
3468 struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
3471 LASSERT(obd != NULL);
3472 rc = lprocfs_write_helper(buffer, count, &val);
3476 obd->obd_recovery_time_hard = val;
3479 EXPORT_SYMBOL(lprocfs_recovery_time_hard_seq_write);
3481 int lprocfs_target_instance_seq_show(struct seq_file *m, void *data)
3483 struct obd_device *obd = m->private;
3484 struct obd_device_target *target = &obd->u.obt;
3486 LASSERT(obd != NULL);
3487 LASSERT(target->obt_magic == OBT_MAGIC);
3488 return seq_printf(m, "%u\n", obd->u.obt.obt_instance);
3490 EXPORT_SYMBOL(lprocfs_target_instance_seq_show);
3492 #ifndef HAVE_ONLY_PROCFS_SEQ
3493 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
3494 int count, int *eof, void *data)
3496 struct obd_device *obd = data;
3502 c += cfs_hash_debug_header(page, count);
3503 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
3504 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
3505 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
3509 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
3511 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
3512 int count, int *eof, void *data)
3514 struct obd_device *obd = data;
3517 LASSERT(obd != NULL);
3518 LASSERT(count >= 0);
3520 /* Set start of user data returned to
3521 page + off since the user may have
3522 requested to read much smaller than
3523 what we need to read */
3524 *start = page + off;
3527 * We know we are allocated a page here.
3528 * Also we know that this function will
3529 * not need to write more than a page
3530 * so we can truncate at PAGE_CACHE_SIZE.
3532 size = min(count + (int)off + 1, (int)PAGE_CACHE_SIZE);
3534 /* Initialize the page */
3535 memset(page, 0, size);
3537 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
3539 if (obd->obd_max_recoverable_clients == 0) {
3540 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
3546 /* sampled unlocked, but really... */
3547 if (obd->obd_recovering == 0) {
3548 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
3550 if (lprocfs_obd_snprintf(&page, size, &len,
3551 "recovery_start: %lu\n",
3552 obd->obd_recovery_start) <= 0)
3554 if (lprocfs_obd_snprintf(&page, size, &len,
3555 "recovery_duration: %lu\n",
3556 obd->obd_recovery_end -
3557 obd->obd_recovery_start) <= 0)
3559 /* Number of clients that have completed recovery */
3560 if (lprocfs_obd_snprintf(&page, size, &len,
3561 "completed_clients: %d/%d\n",
3562 obd->obd_max_recoverable_clients -
3563 obd->obd_stale_clients,
3564 obd->obd_max_recoverable_clients) <= 0)
3566 if (lprocfs_obd_snprintf(&page, size, &len,
3567 "replayed_requests: %d\n",
3568 obd->obd_replayed_requests) <= 0)
3570 if (lprocfs_obd_snprintf(&page, size, &len,
3571 "last_transno: "LPD64"\n",
3572 obd->obd_next_recovery_transno - 1)<=0)
3574 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
3575 obd->obd_version_recov ?
3576 "ENABLED" : "DISABLED") <=0)
3578 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
3580 "DISABLED" : "ENABLED") <= 0)
3585 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
3587 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
3588 obd->obd_recovery_start) <= 0)
3590 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
3591 cfs_time_current_sec() >=
3592 obd->obd_recovery_start +
3593 obd->obd_recovery_timeout ? 0 :
3594 obd->obd_recovery_start +
3595 obd->obd_recovery_timeout -
3596 cfs_time_current_sec()) <= 0)
3598 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
3599 atomic_read(&obd->obd_connected_clients),
3600 obd->obd_max_recoverable_clients) <= 0)
3602 /* Number of clients that have completed recovery */
3603 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
3604 atomic_read(&obd->obd_req_replay_clients))
3607 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
3608 atomic_read(&obd->obd_lock_replay_clients))
3611 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
3612 atomic_read(&obd->obd_connected_clients) -
3613 atomic_read(&obd->obd_lock_replay_clients))
3616 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
3617 obd->obd_stale_clients) <= 0)
3619 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
3620 obd->obd_replayed_requests) <= 0)
3622 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
3623 obd->obd_requests_queued_for_recovery) <= 0)
3626 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
3627 obd->obd_next_recovery_transno) <= 0)
3633 return min(count, len - (int)off);
3635 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
3637 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
3638 int count, int *eof, void *data)
3640 struct obd_device *obd = (struct obd_device *)data;
3641 LASSERT(obd != NULL);
3643 return snprintf(page, count, "%d\n",
3644 obd->obd_recovery_ir_factor);
3646 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
3648 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
3649 unsigned long count, void *data)
3651 struct obd_device *obd = (struct obd_device *)data;
3653 LASSERT(obd != NULL);
3655 rc = lprocfs_write_helper(buffer, count, &val);
3659 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
3662 obd->obd_recovery_ir_factor = val;
3665 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
3667 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
3668 int count, int *eof, void *data)
3670 struct obd_device *obd = (struct obd_device *)data;
3671 LASSERT(obd != NULL);
3673 return snprintf(page, count, "%d\n",
3674 obd->obd_recovery_timeout);
3676 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
3678 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
3679 unsigned long count, void *data)
3681 struct obd_device *obd = (struct obd_device *)data;
3683 LASSERT(obd != NULL);
3685 rc = lprocfs_write_helper(buffer, count, &val);
3689 obd->obd_recovery_timeout = val;
3692 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
3694 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
3695 int count, int *eof, void *data)
3697 struct obd_device *obd = data;
3698 LASSERT(obd != NULL);
3700 return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
3702 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
3704 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
3705 unsigned long count, void *data)
3707 struct obd_device *obd = data;
3709 LASSERT(obd != NULL);
3711 rc = lprocfs_write_helper(buffer, count, &val);
3715 obd->obd_recovery_time_hard = val;
3718 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
3720 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
3721 int count, int *eof, void *data)
3723 struct obd_device *obd = (struct obd_device *)data;
3724 struct obd_device_target *target = &obd->u.obt;
3726 LASSERT(obd != NULL);
3727 LASSERT(target->obt_magic == OBT_MAGIC);
3729 return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
3731 EXPORT_SYMBOL(lprocfs_target_rd_instance);
3732 #endif /* HAVE_ONLY_PROCFS_SEQ */
3733 #endif /* HAVE_SERVER_SUPPORT */
3735 int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
3736 int count, int *eof, void *data)
3738 struct obd_device *dev = data;
3739 struct client_obd *cli = &dev->u.cli;
3742 client_obd_list_lock(&cli->cl_loi_list_lock);
3743 rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
3744 client_obd_list_unlock(&cli->cl_loi_list_lock);
3747 EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
3749 int lprocfs_obd_max_pages_per_rpc_seq_show(struct seq_file *m, void *data)
3751 struct obd_device *dev = data;
3752 struct client_obd *cli = &dev->u.cli;
3755 client_obd_list_lock(&cli->cl_loi_list_lock);
3756 rc = seq_printf(m, "%d\n", cli->cl_max_pages_per_rpc);
3757 client_obd_list_unlock(&cli->cl_loi_list_lock);
3760 EXPORT_SYMBOL(lprocfs_obd_max_pages_per_rpc_seq_show);