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 int lprocfs_exp_nid_seq_show(struct seq_file *m, void *data)
2589 struct obd_export *exp = m->private;
2590 LASSERT(exp != NULL);
2591 return seq_printf(m, "%s\n", obd_export_nid2str(exp));
2594 int lprocfs_exp_print_uuid_seq(cfs_hash_t *hs, cfs_hash_bd_t *bd,
2595 cfs_hlist_node_t *hnode, void *cb_data)
2598 struct obd_export *exp = cfs_hash_object(hs, hnode);
2599 struct seq_file *m = cb_data;
2601 if (exp->exp_nid_stats)
2602 seq_printf(m, "%s\n", obd_uuid2str(&exp->exp_client_uuid));
2606 int lprocfs_exp_uuid_seq_show(struct seq_file *m, void *data)
2608 struct nid_stat *stats = m->private;
2609 struct obd_device *obd = stats->nid_obd;
2611 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
2612 lprocfs_exp_print_uuid_seq, m);
2615 LPROC_SEQ_FOPS_RO(lprocfs_exp_uuid);
2617 int lprocfs_exp_print_hash_seq(cfs_hash_t *hs, cfs_hash_bd_t *bd,
2618 cfs_hlist_node_t *hnode, void *cb_data)
2621 struct seq_file *m = cb_data;
2622 struct obd_export *exp = cfs_hash_object(hs, hnode);
2624 if (exp->exp_lock_hash != NULL) {
2625 cfs_hash_debug_header_seq(m);
2626 cfs_hash_debug_str_seq(hs, m);
2631 int lprocfs_exp_hash_seq_show(struct seq_file *m, void *data)
2633 struct nid_stat *stats = m->private;
2634 struct obd_device *obd = stats->nid_obd;
2636 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
2637 lprocfs_exp_print_hash_seq, m);
2640 LPROC_SEQ_FOPS_RO(lprocfs_exp_hash);
2642 int lprocfs_nid_stats_clear_seq_show(struct seq_file *m, void *data)
2644 return seq_printf(m, "%s\n", "Write into this file to clear all nid "
2645 "stats and stale nid entries");
2647 EXPORT_SYMBOL(lprocfs_nid_stats_clear_seq_show);
2649 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
2651 struct nid_stat *stat = obj;
2654 CDEBUG(D_INFO,"refcnt %d\n", atomic_read(&stat->nid_exp_ref_count));
2655 if (atomic_read(&stat->nid_exp_ref_count) == 1) {
2656 /* object has only hash references. */
2657 spin_lock(&stat->nid_obd->obd_nid_lock);
2658 cfs_list_move(&stat->nid_list, data);
2659 spin_unlock(&stat->nid_obd->obd_nid_lock);
2662 /* we has reference to object - only clear data*/
2663 if (stat->nid_stats)
2664 lprocfs_clear_stats(stat->nid_stats);
2670 lprocfs_nid_stats_clear_seq_write(struct file *file, const char *buffer,
2671 size_t count, loff_t *off)
2673 struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
2674 struct nid_stat *client_stat;
2675 CFS_LIST_HEAD(free_list);
2677 cfs_hash_cond_del(obd->obd_nid_stats_hash,
2678 lprocfs_nid_stats_clear_write_cb, &free_list);
2680 while (!cfs_list_empty(&free_list)) {
2681 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
2683 cfs_list_del_init(&client_stat->nid_list);
2684 lprocfs_free_client_stats(client_stat);
2688 EXPORT_SYMBOL(lprocfs_nid_stats_clear_seq_write);
2690 #ifndef HAVE_ONLY_PROCFS_SEQ
2691 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
2692 int *eof, void *data)
2694 struct obd_export *exp = data;
2695 LASSERT(exp != NULL);
2697 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
2700 struct exp_uuid_cb_data {
2708 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
2709 int count, int *eof, int *len)
2711 cb_data->page = page;
2712 cb_data->count = count;
2717 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
2718 cfs_hlist_node_t *hnode, void *cb_data)
2721 struct obd_export *exp = cfs_hash_object(hs, hnode);
2722 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
2724 if (exp->exp_nid_stats)
2725 *data->len += snprintf((data->page + *data->len),
2726 data->count, "%s\n",
2727 obd_uuid2str(&exp->exp_client_uuid));
2731 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
2732 int *eof, void *data)
2734 struct nid_stat *stats = (struct nid_stat *)data;
2735 struct exp_uuid_cb_data cb_data;
2736 struct obd_device *obd = stats->nid_obd;
2741 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
2742 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
2743 lprocfs_exp_print_uuid, &cb_data);
2744 return (*cb_data.len);
2747 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
2748 cfs_hlist_node_t *hnode, void *cb_data)
2751 struct exp_uuid_cb_data *data = cb_data;
2752 struct obd_export *exp = cfs_hash_object(hs, hnode);
2754 if (exp->exp_lock_hash != NULL) {
2756 *data->len += cfs_hash_debug_header(data->page,
2759 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
2766 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
2767 int *eof, void *data)
2769 struct nid_stat *stats = (struct nid_stat *)data;
2770 struct exp_uuid_cb_data cb_data;
2771 struct obd_device *obd = stats->nid_obd;
2776 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
2778 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
2779 lprocfs_exp_print_hash, &cb_data);
2780 return (*cb_data.len);
2783 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
2784 int count, int *eof, void *data)
2787 return snprintf(page, count, "%s\n",
2788 "Write into this file to clear all nid stats and "
2789 "stale nid entries");
2791 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
2793 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
2794 unsigned long count, void *data)
2796 struct obd_device *obd = (struct obd_device *)data;
2797 struct nid_stat *client_stat;
2798 CFS_LIST_HEAD(free_list);
2800 cfs_hash_cond_del(obd->obd_nid_stats_hash,
2801 lprocfs_nid_stats_clear_write_cb, &free_list);
2803 while (!cfs_list_empty(&free_list)) {
2804 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
2806 cfs_list_del_init(&client_stat->nid_list);
2807 lprocfs_free_client_stats(client_stat);
2812 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
2815 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
2817 struct nid_stat *new_stat, *old_stat;
2818 struct obd_device *obd = NULL;
2819 cfs_proc_dir_entry_t *entry;
2820 char *buffer = NULL;
2826 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
2827 !exp->exp_obd->obd_nid_stats_hash)
2830 /* not test against zero because eric say:
2831 * You may only test nid against another nid, or LNET_NID_ANY.
2832 * Anything else is nonsense.*/
2833 if (!nid || *nid == LNET_NID_ANY)
2836 spin_lock(&exp->exp_lock);
2837 if (exp->exp_nid_stats != NULL) {
2838 spin_unlock(&exp->exp_lock);
2841 spin_unlock(&exp->exp_lock);
2845 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
2847 OBD_ALLOC_PTR(new_stat);
2848 if (new_stat == NULL)
2851 new_stat->nid = *nid;
2852 new_stat->nid_obd = exp->exp_obd;
2853 /* we need set default refcount to 1 to balance obd_disconnect */
2854 atomic_set(&new_stat->nid_exp_ref_count, 1);
2856 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
2857 nid, &new_stat->nid_hash);
2858 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
2859 old_stat, libcfs_nid2str(*nid),
2860 atomic_read(&new_stat->nid_exp_ref_count));
2862 /* Return -EALREADY here so that we know that the /proc
2863 * entry already has been created */
2864 if (old_stat != new_stat) {
2865 nidstat_putref(old_stat);
2866 GOTO(destroy_new, rc = -EALREADY);
2868 /* not found - create */
2869 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
2871 GOTO(destroy_new, rc = -ENOMEM);
2873 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
2874 #ifndef HAVE_ONLY_PROCFS_SEQ
2875 new_stat->nid_proc = lprocfs_register(buffer,
2876 obd->obd_proc_exports_entry,
2879 new_stat->nid_proc = lprocfs_seq_register(buffer,
2880 obd->obd_proc_exports_entry,
2883 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
2885 if (IS_ERR(new_stat->nid_proc)) {
2886 rc = PTR_ERR(new_stat->nid_proc);
2887 new_stat->nid_proc = NULL;
2888 CERROR("%s: cannot create proc entry for export %s: rc = %d\n",
2889 obd->obd_name, libcfs_nid2str(*nid), rc);
2890 GOTO(destroy_new_ns, rc);
2893 #ifndef HAVE_ONLY_PROCFS_SEQ
2894 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
2895 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
2897 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
2898 new_stat, &lprocfs_exp_uuid_fops);
2900 if (IS_ERR(entry)) {
2901 CWARN("Error adding the NID stats file\n");
2902 rc = PTR_ERR(entry);
2903 GOTO(destroy_new_ns, rc);
2906 #ifndef HAVE_ONLY_PROCFS_SEQ
2907 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
2908 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
2910 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
2911 new_stat, &lprocfs_exp_hash_fops);
2913 if (IS_ERR(entry)) {
2914 CWARN("Error adding the hash file\n");
2915 rc = PTR_ERR(entry);
2916 GOTO(destroy_new_ns, rc);
2919 spin_lock(&exp->exp_lock);
2920 exp->exp_nid_stats = new_stat;
2921 spin_unlock(&exp->exp_lock);
2923 /* protect competitive add to list, not need locking on destroy */
2924 spin_lock(&obd->obd_nid_lock);
2925 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
2926 spin_unlock(&obd->obd_nid_lock);
2931 if (new_stat->nid_proc != NULL)
2932 lprocfs_remove(&new_stat->nid_proc);
2933 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
2936 nidstat_putref(new_stat);
2937 OBD_FREE_PTR(new_stat);
2940 EXPORT_SYMBOL(lprocfs_exp_setup);
2943 int lprocfs_exp_cleanup(struct obd_export *exp)
2945 struct nid_stat *stat = exp->exp_nid_stats;
2947 if(!stat || !exp->exp_obd)
2950 nidstat_putref(exp->exp_nid_stats);
2951 exp->exp_nid_stats = NULL;
2955 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2957 __s64 lprocfs_read_helper(struct lprocfs_counter *lc,
2958 struct lprocfs_counter_header *header,
2959 enum lprocfs_stats_flags flags,
2960 enum lprocfs_fields_flags field)
2964 if (lc == NULL || header == NULL)
2968 case LPROCFS_FIELDS_FLAGS_CONFIG:
2969 ret = header->lc_config;
2971 case LPROCFS_FIELDS_FLAGS_SUM:
2973 if ((flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
2974 ret += lc->lc_sum_irq;
2976 case LPROCFS_FIELDS_FLAGS_MIN:
2979 case LPROCFS_FIELDS_FLAGS_MAX:
2982 case LPROCFS_FIELDS_FLAGS_AVG:
2983 ret = (lc->lc_max - lc->lc_min) / 2;
2985 case LPROCFS_FIELDS_FLAGS_SUMSQUARE:
2986 ret = lc->lc_sumsquare;
2988 case LPROCFS_FIELDS_FLAGS_COUNT:
2996 EXPORT_SYMBOL(lprocfs_read_helper);
2998 int lprocfs_write_helper(const char *buffer, unsigned long count,
3001 return lprocfs_write_frac_helper(buffer, count, val, 1);
3003 EXPORT_SYMBOL(lprocfs_write_helper);
3005 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
3008 char kernbuf[20], *end, *pbuf;
3010 if (count > (sizeof(kernbuf) - 1))
3013 if (copy_from_user(kernbuf, buffer, count))
3016 kernbuf[count] = '\0';
3023 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
3027 if (end != NULL && *end == '.') {
3028 int temp_val, pow = 1;
3032 if (strlen(pbuf) > 5)
3033 pbuf[5] = '\0'; /*only allow 5bits fractional*/
3035 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
3038 for (i = 0; i < (end - pbuf); i++)
3041 *val += temp_val / pow;
3046 EXPORT_SYMBOL(lprocfs_write_frac_helper);
3048 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
3051 long decimal_val, frac_val;
3057 decimal_val = val / mult;
3058 prtn = snprintf(buffer, count, "%ld", decimal_val);
3059 frac_val = val % mult;
3061 if (prtn < (count - 4) && frac_val > 0) {
3063 int i, temp_mult = 1, frac_bits = 0;
3065 temp_frac = frac_val * 10;
3066 buffer[prtn++] = '.';
3067 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
3068 /* only reserved 2 bits fraction */
3069 buffer[prtn++] ='0';
3074 * Need to think these cases :
3075 * 1. #echo x.00 > /proc/xxx output result : x
3076 * 2. #echo x.0x > /proc/xxx output result : x.0x
3077 * 3. #echo x.x0 > /proc/xxx output result : x.x
3078 * 4. #echo x.xx > /proc/xxx output result : x.xx
3079 * Only reserved 2 bits fraction.
3081 for (i = 0; i < (5 - prtn); i++)
3084 frac_bits = min((int)count - prtn, 3 - frac_bits);
3085 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
3086 frac_val * temp_mult / mult);
3089 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
3091 if (buffer[prtn] == '.') {
3098 buffer[prtn++] ='\n';
3101 EXPORT_SYMBOL(lprocfs_read_frac_helper);
3103 int lprocfs_seq_read_frac_helper(struct seq_file *m, long val, int mult)
3105 long decimal_val, frac_val;
3107 decimal_val = val / mult;
3108 seq_printf(m, "%ld", decimal_val);
3109 frac_val = val % mult;
3116 /* Three cases: x0, xx, 0x */
3117 if ((frac_val % 10) != 0)
3118 seq_printf(m, ".%ld", frac_val);
3120 seq_printf(m, ".%ld", frac_val / 10);
3123 seq_printf(m, "\n");
3126 EXPORT_SYMBOL(lprocfs_seq_read_frac_helper);
3128 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
3130 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
3132 EXPORT_SYMBOL(lprocfs_write_u64_helper);
3134 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
3135 __u64 *val, int mult)
3137 char kernbuf[22], *end, *pbuf;
3138 __u64 whole, frac = 0, units;
3139 unsigned frac_d = 1;
3141 if (count > (sizeof(kernbuf) - 1))
3144 if (copy_from_user(kernbuf, buffer, count))
3147 kernbuf[count] = '\0';
3154 whole = simple_strtoull(pbuf, &end, 10);
3158 if (end != NULL && *end == '.') {
3162 /* need to limit frac_d to a __u32 */
3163 if (strlen(pbuf) > 10)
3166 frac = simple_strtoull(pbuf, &end, 10);
3167 /* count decimal places */
3168 for (i = 0; i < (end - pbuf); i++)
3187 /* Specified units override the multiplier */
3189 mult = mult < 0 ? -units : units;
3192 do_div(frac, frac_d);
3193 *val = whole * mult + frac;
3196 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
3198 static char *lprocfs_strnstr(const char *s1, const char *s2, size_t len)
3207 if (!memcmp(s1, s2, l2))
3215 * Find the string \a name in the input \a buffer, and return a pointer to the
3216 * value immediately following \a name, reducing \a count appropriately.
3217 * If \a name is not found the original \a buffer is returned.
3219 char *lprocfs_find_named_value(const char *buffer, const char *name,
3223 size_t buflen = *count;
3225 /* there is no strnstr() in rhel5 and ubuntu kernels */
3226 val = lprocfs_strnstr(buffer, name, buflen);
3228 return (char *)buffer;
3230 val += strlen(name); /* skip prefix */
3231 while (val < buffer + buflen && isspace(*val)) /* skip separator */
3235 while (val < buffer + buflen && isalnum(*val)) {
3240 return val - *count;
3242 EXPORT_SYMBOL(lprocfs_find_named_value);
3244 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent,
3247 const struct file_operations *seq_fops,
3250 struct proc_dir_entry *entry;
3253 /* Disallow secretly (un)writable entries. */
3254 LASSERT((seq_fops->write == NULL) == ((mode & 0222) == 0));
3256 entry = proc_create_data(name, mode, parent, seq_fops, data);
3263 EXPORT_SYMBOL(lprocfs_seq_create);
3265 int lprocfs_obd_seq_create(struct obd_device *dev,
3268 const struct file_operations *seq_fops,
3271 return (lprocfs_seq_create(dev->obd_proc_entry, name,
3272 mode, seq_fops, data));
3274 EXPORT_SYMBOL(lprocfs_obd_seq_create);
3276 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
3278 if (value >= OBD_HIST_MAX)
3279 value = OBD_HIST_MAX - 1;
3281 spin_lock(&oh->oh_lock);
3282 oh->oh_buckets[value]++;
3283 spin_unlock(&oh->oh_lock);
3285 EXPORT_SYMBOL(lprocfs_oh_tally);
3287 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
3289 unsigned int val = 0;
3291 if (likely(value != 0))
3292 val = min(fls(value - 1), OBD_HIST_MAX);
3294 lprocfs_oh_tally(oh, val);
3296 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
3298 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
3300 unsigned long ret = 0;
3303 for (i = 0; i < OBD_HIST_MAX; i++)
3304 ret += oh->oh_buckets[i];
3307 EXPORT_SYMBOL(lprocfs_oh_sum);
3309 void lprocfs_oh_clear(struct obd_histogram *oh)
3311 spin_lock(&oh->oh_lock);
3312 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
3313 spin_unlock(&oh->oh_lock);
3315 EXPORT_SYMBOL(lprocfs_oh_clear);
3317 #ifdef HAVE_SERVER_SUPPORT
3318 int lprocfs_hash_seq_show(struct seq_file *m, void *data)
3320 struct obd_device *obd = m->private;
3326 c += cfs_hash_debug_header_seq(m);
3327 c += cfs_hash_debug_str_seq(obd->obd_uuid_hash, m);
3328 c += cfs_hash_debug_str_seq(obd->obd_nid_hash, m);
3329 c += cfs_hash_debug_str_seq(obd->obd_nid_stats_hash, m);
3332 EXPORT_SYMBOL(lprocfs_hash_seq_show);
3334 int lprocfs_recovery_status_seq_show(struct seq_file *m, void *data)
3336 struct obd_device *obd = m->private;
3338 LASSERT(obd != NULL);
3340 seq_printf(m, "status: \n");
3341 if (obd->obd_max_recoverable_clients == 0) {
3342 seq_printf(m, "INACTIVE\n");
3346 /* sampled unlocked, but really... */
3347 if (obd->obd_recovering == 0) {
3348 seq_printf(m, "COMPLETE\n");
3349 seq_printf(m, "recovery_start: %lu\n", obd->obd_recovery_start);
3350 seq_printf(m, "recovery_duration: %lu\n",
3351 obd->obd_recovery_end - obd->obd_recovery_start);
3352 /* Number of clients that have completed recovery */
3353 seq_printf(m, "completed_clients: %d/%d\n",
3354 obd->obd_max_recoverable_clients -
3355 obd->obd_stale_clients,
3356 obd->obd_max_recoverable_clients);
3357 seq_printf(m, "replayed_requests: %d\n",
3358 obd->obd_replayed_requests);
3359 seq_printf(m, "last_transno: "LPD64"\n",
3360 obd->obd_next_recovery_transno - 1);
3361 seq_printf(m, "VBR: %s\n", obd->obd_version_recov ?
3362 "ENABLED" : "DISABLED");
3363 seq_printf(m, "IR: %s\n", obd->obd_no_ir ?
3364 "DISABLED" : "ENABLED");
3368 seq_printf(m, "RECOVERING\n");
3369 seq_printf(m, "recovery_start: %lu\n", obd->obd_recovery_start);
3370 seq_printf(m, "time_remaining: %lu\n",
3371 cfs_time_current_sec() >=
3372 obd->obd_recovery_start +
3373 obd->obd_recovery_timeout ? 0 :
3374 obd->obd_recovery_start +
3375 obd->obd_recovery_timeout -
3376 cfs_time_current_sec());
3377 seq_printf(m, "connected_clients: %d/%d\n",
3378 atomic_read(&obd->obd_connected_clients),
3379 obd->obd_max_recoverable_clients);
3380 /* Number of clients that have completed recovery */
3381 seq_printf(m, "req_replay_clients: %d\n",
3382 atomic_read(&obd->obd_req_replay_clients));
3383 seq_printf(m, "lock_repay_clients: %d\n",
3384 atomic_read(&obd->obd_lock_replay_clients));
3385 seq_printf(m, "completed_clients: %d\n",
3386 atomic_read(&obd->obd_connected_clients) -
3387 atomic_read(&obd->obd_lock_replay_clients));
3388 seq_printf(m, "evicted_clients: %d\n", obd->obd_stale_clients);
3389 seq_printf(m, "replayed_requests: %d\n", obd->obd_replayed_requests);
3390 seq_printf(m, "queued_requests: %d\n",
3391 obd->obd_requests_queued_for_recovery);
3392 seq_printf(m, "next_transno: "LPD64"\n",
3393 obd->obd_next_recovery_transno);
3397 EXPORT_SYMBOL(lprocfs_recovery_status_seq_show);
3399 int lprocfs_ir_factor_seq_show(struct seq_file *m, void *data)
3401 struct obd_device *obd = m->private;
3403 LASSERT(obd != NULL);
3404 return seq_printf(m, "%d\n", obd->obd_recovery_ir_factor);
3406 EXPORT_SYMBOL(lprocfs_ir_factor_seq_show);
3409 lprocfs_ir_factor_seq_write(struct file *file, const char *buffer,
3410 size_t count, loff_t *off)
3412 struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
3415 LASSERT(obd != NULL);
3416 rc = lprocfs_write_helper(buffer, count, &val);
3420 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
3423 obd->obd_recovery_ir_factor = val;
3426 EXPORT_SYMBOL(lprocfs_ir_factor_seq_write);
3428 int lprocfs_recovery_time_soft_seq_show(struct seq_file *m, void *data)
3430 struct obd_device *obd = m->private;
3432 LASSERT(obd != NULL);
3433 return seq_printf(m, "%d\n", obd->obd_recovery_timeout);
3435 EXPORT_SYMBOL(lprocfs_recovery_time_soft_seq_show);
3438 lprocfs_recovery_time_soft_seq_write(struct file *file, const char *buffer,
3439 size_t count, loff_t *off)
3441 struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
3444 LASSERT(obd != NULL);
3445 rc = lprocfs_write_helper(buffer, count, &val);
3449 obd->obd_recovery_timeout = val;
3452 EXPORT_SYMBOL(lprocfs_recovery_time_soft_seq_write);
3454 int lprocfs_recovery_time_hard_seq_show(struct seq_file *m, void *data)
3456 struct obd_device *obd = m->private;
3458 LASSERT(obd != NULL);
3459 return seq_printf(m, "%u\n", obd->obd_recovery_time_hard);
3461 EXPORT_SYMBOL(lprocfs_recovery_time_hard_seq_show);
3464 lprocfs_recovery_time_hard_seq_write(struct file *file, const char *buffer,
3465 size_t count, loff_t *off)
3467 struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
3470 LASSERT(obd != NULL);
3471 rc = lprocfs_write_helper(buffer, count, &val);
3475 obd->obd_recovery_time_hard = val;
3478 EXPORT_SYMBOL(lprocfs_recovery_time_hard_seq_write);
3480 int lprocfs_target_instance_seq_show(struct seq_file *m, void *data)
3482 struct obd_device *obd = m->private;
3483 struct obd_device_target *target = &obd->u.obt;
3485 LASSERT(obd != NULL);
3486 LASSERT(target->obt_magic == OBT_MAGIC);
3487 return seq_printf(m, "%u\n", obd->u.obt.obt_instance);
3489 EXPORT_SYMBOL(lprocfs_target_instance_seq_show);
3491 #ifndef HAVE_ONLY_PROCFS_SEQ
3492 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
3493 int count, int *eof, void *data)
3495 struct obd_device *obd = data;
3501 c += cfs_hash_debug_header(page, count);
3502 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
3503 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
3504 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
3508 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
3510 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
3511 int count, int *eof, void *data)
3513 struct obd_device *obd = data;
3516 LASSERT(obd != NULL);
3517 LASSERT(count >= 0);
3519 /* Set start of user data returned to
3520 page + off since the user may have
3521 requested to read much smaller than
3522 what we need to read */
3523 *start = page + off;
3526 * We know we are allocated a page here.
3527 * Also we know that this function will
3528 * not need to write more than a page
3529 * so we can truncate at PAGE_CACHE_SIZE.
3531 size = min(count + (int)off + 1, (int)PAGE_CACHE_SIZE);
3533 /* Initialize the page */
3534 memset(page, 0, size);
3536 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
3538 if (obd->obd_max_recoverable_clients == 0) {
3539 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
3545 /* sampled unlocked, but really... */
3546 if (obd->obd_recovering == 0) {
3547 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
3549 if (lprocfs_obd_snprintf(&page, size, &len,
3550 "recovery_start: %lu\n",
3551 obd->obd_recovery_start) <= 0)
3553 if (lprocfs_obd_snprintf(&page, size, &len,
3554 "recovery_duration: %lu\n",
3555 obd->obd_recovery_end -
3556 obd->obd_recovery_start) <= 0)
3558 /* Number of clients that have completed recovery */
3559 if (lprocfs_obd_snprintf(&page, size, &len,
3560 "completed_clients: %d/%d\n",
3561 obd->obd_max_recoverable_clients -
3562 obd->obd_stale_clients,
3563 obd->obd_max_recoverable_clients) <= 0)
3565 if (lprocfs_obd_snprintf(&page, size, &len,
3566 "replayed_requests: %d\n",
3567 obd->obd_replayed_requests) <= 0)
3569 if (lprocfs_obd_snprintf(&page, size, &len,
3570 "last_transno: "LPD64"\n",
3571 obd->obd_next_recovery_transno - 1)<=0)
3573 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
3574 obd->obd_version_recov ?
3575 "ENABLED" : "DISABLED") <=0)
3577 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
3579 "DISABLED" : "ENABLED") <= 0)
3584 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
3586 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
3587 obd->obd_recovery_start) <= 0)
3589 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
3590 cfs_time_current_sec() >=
3591 obd->obd_recovery_start +
3592 obd->obd_recovery_timeout ? 0 :
3593 obd->obd_recovery_start +
3594 obd->obd_recovery_timeout -
3595 cfs_time_current_sec()) <= 0)
3597 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
3598 atomic_read(&obd->obd_connected_clients),
3599 obd->obd_max_recoverable_clients) <= 0)
3601 /* Number of clients that have completed recovery */
3602 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
3603 atomic_read(&obd->obd_req_replay_clients))
3606 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
3607 atomic_read(&obd->obd_lock_replay_clients))
3610 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
3611 atomic_read(&obd->obd_connected_clients) -
3612 atomic_read(&obd->obd_lock_replay_clients))
3615 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
3616 obd->obd_stale_clients) <= 0)
3618 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
3619 obd->obd_replayed_requests) <= 0)
3621 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
3622 obd->obd_requests_queued_for_recovery) <= 0)
3625 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
3626 obd->obd_next_recovery_transno) <= 0)
3632 return min(count, len - (int)off);
3634 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
3636 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
3637 int count, int *eof, void *data)
3639 struct obd_device *obd = (struct obd_device *)data;
3640 LASSERT(obd != NULL);
3642 return snprintf(page, count, "%d\n",
3643 obd->obd_recovery_ir_factor);
3645 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
3647 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
3648 unsigned long count, void *data)
3650 struct obd_device *obd = (struct obd_device *)data;
3652 LASSERT(obd != NULL);
3654 rc = lprocfs_write_helper(buffer, count, &val);
3658 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
3661 obd->obd_recovery_ir_factor = val;
3664 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
3666 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
3667 int count, int *eof, void *data)
3669 struct obd_device *obd = (struct obd_device *)data;
3670 LASSERT(obd != NULL);
3672 return snprintf(page, count, "%d\n",
3673 obd->obd_recovery_timeout);
3675 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
3677 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
3678 unsigned long count, void *data)
3680 struct obd_device *obd = (struct obd_device *)data;
3682 LASSERT(obd != NULL);
3684 rc = lprocfs_write_helper(buffer, count, &val);
3688 obd->obd_recovery_timeout = val;
3691 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
3693 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
3694 int count, int *eof, void *data)
3696 struct obd_device *obd = data;
3697 LASSERT(obd != NULL);
3699 return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
3701 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
3703 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
3704 unsigned long count, void *data)
3706 struct obd_device *obd = data;
3708 LASSERT(obd != NULL);
3710 rc = lprocfs_write_helper(buffer, count, &val);
3714 obd->obd_recovery_time_hard = val;
3717 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
3719 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
3720 int count, int *eof, void *data)
3722 struct obd_device *obd = (struct obd_device *)data;
3723 struct obd_device_target *target = &obd->u.obt;
3725 LASSERT(obd != NULL);
3726 LASSERT(target->obt_magic == OBT_MAGIC);
3728 return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
3730 EXPORT_SYMBOL(lprocfs_target_rd_instance);
3731 #endif /* HAVE_ONLY_PROCFS_SEQ */
3732 #endif /* HAVE_SERVER_SUPPORT */
3734 int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
3735 int count, int *eof, void *data)
3737 struct obd_device *dev = data;
3738 struct client_obd *cli = &dev->u.cli;
3741 client_obd_list_lock(&cli->cl_loi_list_lock);
3742 rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
3743 client_obd_list_unlock(&cli->cl_loi_list_lock);
3746 EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
3748 int lprocfs_obd_max_pages_per_rpc_seq_show(struct seq_file *m, void *data)
3750 struct obd_device *dev = data;
3751 struct client_obd *cli = &dev->u.cli;
3754 client_obd_list_lock(&cli->cl_loi_list_lock);
3755 rc = seq_printf(m, "%d\n", cli->cl_max_pages_per_rpc);
3756 client_obd_list_unlock(&cli->cl_loi_list_lock);
3759 EXPORT_SYMBOL(lprocfs_obd_max_pages_per_rpc_seq_show);