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, create);
2353 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
2354 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
2355 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
2356 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
2357 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
2358 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
2359 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
2360 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
2361 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
2362 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
2363 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
2364 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
2365 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
2366 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
2367 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
2368 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
2369 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
2370 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
2371 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
2372 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
2373 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
2374 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
2375 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
2376 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
2377 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
2378 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
2379 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
2380 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
2381 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
2382 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
2384 CLASSERT(NUM_OBD_STATS == OBD_COUNTER_OFFSET(putref) + 1);
2386 EXPORT_SYMBOL(lprocfs_init_ops_stats);
2388 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
2390 struct lprocfs_stats *stats;
2391 unsigned int num_stats;
2394 LASSERT(obd->obd_stats == NULL);
2395 LASSERT(obd->obd_proc_entry != NULL);
2396 LASSERT(obd->obd_cntr_base == 0);
2398 num_stats = NUM_OBD_STATS + num_private_stats;
2399 stats = lprocfs_alloc_stats(num_stats, 0);
2403 lprocfs_init_ops_stats(num_private_stats, stats);
2405 for (i = num_private_stats; i < num_stats; i++) {
2406 /* If this LBUGs, it is likely that an obd
2407 * operation was added to struct obd_ops in
2408 * <obd.h>, and that the corresponding line item
2409 * LPROCFS_OBD_OP_INIT(.., .., opname)
2410 * is missing from the list above. */
2411 LASSERTF(stats->ls_cnt_header[i].lc_name != NULL,
2412 "Missing obd_stat initializer obd_op "
2413 "operation at offset %d.\n", i - num_private_stats);
2415 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
2417 lprocfs_free_stats(&stats);
2419 obd->obd_stats = stats;
2420 obd->obd_cntr_base = num_private_stats;
2424 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
2426 void lprocfs_free_obd_stats(struct obd_device *obd)
2429 lprocfs_free_stats(&obd->obd_stats);
2431 EXPORT_SYMBOL(lprocfs_free_obd_stats);
2433 /* Note that we only init md counters for ops whose offset is less
2434 * than NUM_MD_STATS. This is explained in a comment in the definition
2435 * of struct md_ops. */
2436 #define LPROCFS_MD_OP_INIT(base, stats, op) \
2438 unsigned int _idx = base + MD_COUNTER_OFFSET(op); \
2440 if (MD_COUNTER_OFFSET(op) < NUM_MD_STATS) { \
2441 LASSERT(_idx < stats->ls_num); \
2442 lprocfs_counter_init(stats, _idx, 0, #op, "reqs"); \
2446 void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats)
2448 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
2449 LPROCFS_MD_OP_INIT(num_private_stats, stats, null_inode);
2450 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
2451 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
2452 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
2453 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
2454 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
2455 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
2456 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
2457 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
2458 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
2459 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
2460 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
2461 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
2462 LPROCFS_MD_OP_INIT(num_private_stats, stats, fsync);
2463 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
2464 LPROCFS_MD_OP_INIT(num_private_stats, stats, read_entry);
2465 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
2466 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
2467 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
2468 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
2469 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
2470 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
2471 LPROCFS_MD_OP_INIT(num_private_stats, stats, update_lsm_md);
2472 LPROCFS_MD_OP_INIT(num_private_stats, stats, merge_attr);
2473 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
2474 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
2475 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
2476 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
2477 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
2478 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
2479 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
2480 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
2481 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
2482 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
2484 EXPORT_SYMBOL(lprocfs_init_mps_stats);
2486 int lprocfs_alloc_md_stats(struct obd_device *obd,
2487 unsigned int num_private_stats)
2489 struct lprocfs_stats *stats;
2490 unsigned int num_stats;
2493 CLASSERT(offsetof(struct md_ops, MD_STATS_FIRST_OP) == 0);
2494 CLASSERT(_MD_COUNTER_OFFSET(MD_STATS_FIRST_OP) == 0);
2495 CLASSERT(_MD_COUNTER_OFFSET(MD_STATS_LAST_OP) > 0);
2497 /* TODO Ensure that this function is only used where
2498 * appropriate by adding an assertion to the effect that
2499 * obd->obd_type->typ_md_ops is not NULL. We can't do this now
2500 * because mdt_procfs_init() uses this function to allocate
2501 * the stats backing /proc/fs/lustre/mdt/.../md_stats but the
2502 * mdt layer does not use the md_ops interface. This is
2503 * confusing and a waste of memory. See LU-2484.
2505 LASSERT(obd->obd_proc_entry != NULL);
2506 LASSERT(obd->obd_md_stats == NULL);
2507 LASSERT(obd->obd_md_cntr_base == 0);
2509 num_stats = NUM_MD_STATS + num_private_stats;
2510 stats = lprocfs_alloc_stats(num_stats, 0);
2514 lprocfs_init_mps_stats(num_private_stats, stats);
2516 for (i = num_private_stats; i < num_stats; i++) {
2517 if (stats->ls_cnt_header[i].lc_name == NULL) {
2518 CERROR("Missing md_stat initializer md_op "
2519 "operation at offset %d. Aborting.\n",
2520 i - num_private_stats);
2525 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
2527 lprocfs_free_stats(&stats);
2529 obd->obd_md_stats = stats;
2530 obd->obd_md_cntr_base = num_private_stats;
2535 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
2537 void lprocfs_free_md_stats(struct obd_device *obd)
2539 struct lprocfs_stats *stats = obd->obd_md_stats;
2541 if (stats != NULL) {
2542 obd->obd_md_stats = NULL;
2543 obd->obd_md_cntr_base = 0;
2544 lprocfs_free_stats(&stats);
2547 EXPORT_SYMBOL(lprocfs_free_md_stats);
2549 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
2551 lprocfs_counter_init(ldlm_stats,
2552 LDLM_ENQUEUE - LDLM_FIRST_OPC,
2553 0, "ldlm_enqueue", "reqs");
2554 lprocfs_counter_init(ldlm_stats,
2555 LDLM_CONVERT - LDLM_FIRST_OPC,
2556 0, "ldlm_convert", "reqs");
2557 lprocfs_counter_init(ldlm_stats,
2558 LDLM_CANCEL - LDLM_FIRST_OPC,
2559 0, "ldlm_cancel", "reqs");
2560 lprocfs_counter_init(ldlm_stats,
2561 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
2562 0, "ldlm_bl_callback", "reqs");
2563 lprocfs_counter_init(ldlm_stats,
2564 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
2565 0, "ldlm_cp_callback", "reqs");
2566 lprocfs_counter_init(ldlm_stats,
2567 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
2568 0, "ldlm_gl_callback", "reqs");
2570 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
2572 #ifdef HAVE_SERVER_SUPPORT
2573 int lprocfs_exp_nid_seq_show(struct seq_file *m, void *data)
2575 struct obd_export *exp = m->private;
2576 LASSERT(exp != NULL);
2577 return seq_printf(m, "%s\n", obd_export_nid2str(exp));
2580 int lprocfs_exp_print_uuid_seq(cfs_hash_t *hs, cfs_hash_bd_t *bd,
2581 cfs_hlist_node_t *hnode, void *cb_data)
2584 struct obd_export *exp = cfs_hash_object(hs, hnode);
2585 struct seq_file *m = cb_data;
2587 if (exp->exp_nid_stats)
2588 seq_printf(m, "%s\n", obd_uuid2str(&exp->exp_client_uuid));
2592 int lprocfs_exp_uuid_seq_show(struct seq_file *m, void *data)
2594 struct nid_stat *stats = m->private;
2595 struct obd_device *obd = stats->nid_obd;
2597 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
2598 lprocfs_exp_print_uuid_seq, m);
2601 LPROC_SEQ_FOPS_RO(lprocfs_exp_uuid);
2603 int lprocfs_exp_print_hash_seq(cfs_hash_t *hs, cfs_hash_bd_t *bd,
2604 cfs_hlist_node_t *hnode, void *cb_data)
2607 struct seq_file *m = cb_data;
2608 struct obd_export *exp = cfs_hash_object(hs, hnode);
2610 if (exp->exp_lock_hash != NULL) {
2611 cfs_hash_debug_header_seq(m);
2612 cfs_hash_debug_str_seq(hs, m);
2617 int lprocfs_exp_hash_seq_show(struct seq_file *m, void *data)
2619 struct nid_stat *stats = m->private;
2620 struct obd_device *obd = stats->nid_obd;
2622 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
2623 lprocfs_exp_print_hash_seq, m);
2626 LPROC_SEQ_FOPS_RO(lprocfs_exp_hash);
2628 int lprocfs_nid_stats_clear_seq_show(struct seq_file *m, void *data)
2630 return seq_printf(m, "%s\n", "Write into this file to clear all nid "
2631 "stats and stale nid entries");
2633 EXPORT_SYMBOL(lprocfs_nid_stats_clear_seq_show);
2635 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
2637 struct nid_stat *stat = obj;
2640 CDEBUG(D_INFO,"refcnt %d\n", atomic_read(&stat->nid_exp_ref_count));
2641 if (atomic_read(&stat->nid_exp_ref_count) == 1) {
2642 /* object has only hash references. */
2643 spin_lock(&stat->nid_obd->obd_nid_lock);
2644 cfs_list_move(&stat->nid_list, data);
2645 spin_unlock(&stat->nid_obd->obd_nid_lock);
2648 /* we has reference to object - only clear data*/
2649 if (stat->nid_stats)
2650 lprocfs_clear_stats(stat->nid_stats);
2656 lprocfs_nid_stats_clear_seq_write(struct file *file, const char *buffer,
2657 size_t count, loff_t *off)
2659 struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
2660 struct nid_stat *client_stat;
2661 CFS_LIST_HEAD(free_list);
2663 cfs_hash_cond_del(obd->obd_nid_stats_hash,
2664 lprocfs_nid_stats_clear_write_cb, &free_list);
2666 while (!cfs_list_empty(&free_list)) {
2667 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
2669 cfs_list_del_init(&client_stat->nid_list);
2670 lprocfs_free_client_stats(client_stat);
2674 EXPORT_SYMBOL(lprocfs_nid_stats_clear_seq_write);
2676 #ifndef HAVE_ONLY_PROCFS_SEQ
2677 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
2678 int *eof, void *data)
2680 struct obd_export *exp = data;
2681 LASSERT(exp != NULL);
2683 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
2686 struct exp_uuid_cb_data {
2694 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
2695 int count, int *eof, int *len)
2697 cb_data->page = page;
2698 cb_data->count = count;
2703 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
2704 cfs_hlist_node_t *hnode, void *cb_data)
2707 struct obd_export *exp = cfs_hash_object(hs, hnode);
2708 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
2710 if (exp->exp_nid_stats)
2711 *data->len += snprintf((data->page + *data->len),
2712 data->count, "%s\n",
2713 obd_uuid2str(&exp->exp_client_uuid));
2717 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
2718 int *eof, void *data)
2720 struct nid_stat *stats = (struct nid_stat *)data;
2721 struct exp_uuid_cb_data cb_data;
2722 struct obd_device *obd = stats->nid_obd;
2727 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
2728 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
2729 lprocfs_exp_print_uuid, &cb_data);
2730 return (*cb_data.len);
2733 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
2734 cfs_hlist_node_t *hnode, void *cb_data)
2737 struct exp_uuid_cb_data *data = cb_data;
2738 struct obd_export *exp = cfs_hash_object(hs, hnode);
2740 if (exp->exp_lock_hash != NULL) {
2742 *data->len += cfs_hash_debug_header(data->page,
2745 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
2752 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
2753 int *eof, void *data)
2755 struct nid_stat *stats = (struct nid_stat *)data;
2756 struct exp_uuid_cb_data cb_data;
2757 struct obd_device *obd = stats->nid_obd;
2762 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
2764 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
2765 lprocfs_exp_print_hash, &cb_data);
2766 return (*cb_data.len);
2769 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
2770 int count, int *eof, void *data)
2773 return snprintf(page, count, "%s\n",
2774 "Write into this file to clear all nid stats and "
2775 "stale nid entries");
2777 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
2779 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
2780 unsigned long count, void *data)
2782 struct obd_device *obd = (struct obd_device *)data;
2783 struct nid_stat *client_stat;
2784 CFS_LIST_HEAD(free_list);
2786 cfs_hash_cond_del(obd->obd_nid_stats_hash,
2787 lprocfs_nid_stats_clear_write_cb, &free_list);
2789 while (!cfs_list_empty(&free_list)) {
2790 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
2792 cfs_list_del_init(&client_stat->nid_list);
2793 lprocfs_free_client_stats(client_stat);
2798 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
2801 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
2803 struct nid_stat *new_stat, *old_stat;
2804 struct obd_device *obd = NULL;
2805 cfs_proc_dir_entry_t *entry;
2806 char *buffer = NULL;
2812 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
2813 !exp->exp_obd->obd_nid_stats_hash)
2816 /* not test against zero because eric say:
2817 * You may only test nid against another nid, or LNET_NID_ANY.
2818 * Anything else is nonsense.*/
2819 if (!nid || *nid == LNET_NID_ANY)
2822 spin_lock(&exp->exp_lock);
2823 if (exp->exp_nid_stats != NULL) {
2824 spin_unlock(&exp->exp_lock);
2827 spin_unlock(&exp->exp_lock);
2831 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
2833 OBD_ALLOC_PTR(new_stat);
2834 if (new_stat == NULL)
2837 new_stat->nid = *nid;
2838 new_stat->nid_obd = exp->exp_obd;
2839 /* we need set default refcount to 1 to balance obd_disconnect */
2840 atomic_set(&new_stat->nid_exp_ref_count, 1);
2842 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
2843 nid, &new_stat->nid_hash);
2844 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
2845 old_stat, libcfs_nid2str(*nid),
2846 atomic_read(&new_stat->nid_exp_ref_count));
2848 /* Return -EALREADY here so that we know that the /proc
2849 * entry already has been created */
2850 if (old_stat != new_stat) {
2851 nidstat_putref(old_stat);
2852 GOTO(destroy_new, rc = -EALREADY);
2854 /* not found - create */
2855 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
2857 GOTO(destroy_new, rc = -ENOMEM);
2859 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
2860 #ifndef HAVE_ONLY_PROCFS_SEQ
2861 new_stat->nid_proc = lprocfs_register(buffer,
2862 obd->obd_proc_exports_entry,
2865 new_stat->nid_proc = lprocfs_seq_register(buffer,
2866 obd->obd_proc_exports_entry,
2869 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
2871 if (IS_ERR(new_stat->nid_proc)) {
2872 rc = PTR_ERR(new_stat->nid_proc);
2873 new_stat->nid_proc = NULL;
2874 CERROR("%s: cannot create proc entry for export %s: rc = %d\n",
2875 obd->obd_name, libcfs_nid2str(*nid), rc);
2876 GOTO(destroy_new_ns, rc);
2879 #ifndef HAVE_ONLY_PROCFS_SEQ
2880 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
2881 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
2883 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
2884 new_stat, &lprocfs_exp_uuid_fops);
2886 if (IS_ERR(entry)) {
2887 CWARN("Error adding the NID stats file\n");
2888 rc = PTR_ERR(entry);
2889 GOTO(destroy_new_ns, rc);
2892 #ifndef HAVE_ONLY_PROCFS_SEQ
2893 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
2894 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
2896 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
2897 new_stat, &lprocfs_exp_hash_fops);
2899 if (IS_ERR(entry)) {
2900 CWARN("Error adding the hash file\n");
2901 rc = PTR_ERR(entry);
2902 GOTO(destroy_new_ns, rc);
2905 spin_lock(&exp->exp_lock);
2906 exp->exp_nid_stats = new_stat;
2907 spin_unlock(&exp->exp_lock);
2909 /* protect competitive add to list, not need locking on destroy */
2910 spin_lock(&obd->obd_nid_lock);
2911 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
2912 spin_unlock(&obd->obd_nid_lock);
2917 if (new_stat->nid_proc != NULL)
2918 lprocfs_remove(&new_stat->nid_proc);
2919 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
2922 nidstat_putref(new_stat);
2923 OBD_FREE_PTR(new_stat);
2926 EXPORT_SYMBOL(lprocfs_exp_setup);
2929 int lprocfs_exp_cleanup(struct obd_export *exp)
2931 struct nid_stat *stat = exp->exp_nid_stats;
2933 if(!stat || !exp->exp_obd)
2936 nidstat_putref(exp->exp_nid_stats);
2937 exp->exp_nid_stats = NULL;
2941 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2943 __s64 lprocfs_read_helper(struct lprocfs_counter *lc,
2944 struct lprocfs_counter_header *header,
2945 enum lprocfs_stats_flags flags,
2946 enum lprocfs_fields_flags field)
2950 if (lc == NULL || header == NULL)
2954 case LPROCFS_FIELDS_FLAGS_CONFIG:
2955 ret = header->lc_config;
2957 case LPROCFS_FIELDS_FLAGS_SUM:
2959 if ((flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
2960 ret += lc->lc_sum_irq;
2962 case LPROCFS_FIELDS_FLAGS_MIN:
2965 case LPROCFS_FIELDS_FLAGS_MAX:
2968 case LPROCFS_FIELDS_FLAGS_AVG:
2969 ret = (lc->lc_max - lc->lc_min) / 2;
2971 case LPROCFS_FIELDS_FLAGS_SUMSQUARE:
2972 ret = lc->lc_sumsquare;
2974 case LPROCFS_FIELDS_FLAGS_COUNT:
2982 EXPORT_SYMBOL(lprocfs_read_helper);
2984 int lprocfs_write_helper(const char *buffer, unsigned long count,
2987 return lprocfs_write_frac_helper(buffer, count, val, 1);
2989 EXPORT_SYMBOL(lprocfs_write_helper);
2991 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
2994 char kernbuf[20], *end, *pbuf;
2996 if (count > (sizeof(kernbuf) - 1))
2999 if (copy_from_user(kernbuf, buffer, count))
3002 kernbuf[count] = '\0';
3009 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
3013 if (end != NULL && *end == '.') {
3014 int temp_val, pow = 1;
3018 if (strlen(pbuf) > 5)
3019 pbuf[5] = '\0'; /*only allow 5bits fractional*/
3021 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
3024 for (i = 0; i < (end - pbuf); i++)
3027 *val += temp_val / pow;
3032 EXPORT_SYMBOL(lprocfs_write_frac_helper);
3034 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
3037 long decimal_val, frac_val;
3043 decimal_val = val / mult;
3044 prtn = snprintf(buffer, count, "%ld", decimal_val);
3045 frac_val = val % mult;
3047 if (prtn < (count - 4) && frac_val > 0) {
3049 int i, temp_mult = 1, frac_bits = 0;
3051 temp_frac = frac_val * 10;
3052 buffer[prtn++] = '.';
3053 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
3054 /* only reserved 2 bits fraction */
3055 buffer[prtn++] ='0';
3060 * Need to think these cases :
3061 * 1. #echo x.00 > /proc/xxx output result : x
3062 * 2. #echo x.0x > /proc/xxx output result : x.0x
3063 * 3. #echo x.x0 > /proc/xxx output result : x.x
3064 * 4. #echo x.xx > /proc/xxx output result : x.xx
3065 * Only reserved 2 bits fraction.
3067 for (i = 0; i < (5 - prtn); i++)
3070 frac_bits = min((int)count - prtn, 3 - frac_bits);
3071 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
3072 frac_val * temp_mult / mult);
3075 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
3077 if (buffer[prtn] == '.') {
3084 buffer[prtn++] ='\n';
3087 EXPORT_SYMBOL(lprocfs_read_frac_helper);
3089 int lprocfs_seq_read_frac_helper(struct seq_file *m, long val, int mult)
3091 long decimal_val, frac_val;
3093 decimal_val = val / mult;
3094 seq_printf(m, "%ld", decimal_val);
3095 frac_val = val % mult;
3102 /* Three cases: x0, xx, 0x */
3103 if ((frac_val % 10) != 0)
3104 seq_printf(m, ".%ld", frac_val);
3106 seq_printf(m, ".%ld", frac_val / 10);
3109 seq_printf(m, "\n");
3112 EXPORT_SYMBOL(lprocfs_seq_read_frac_helper);
3114 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
3116 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
3118 EXPORT_SYMBOL(lprocfs_write_u64_helper);
3120 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
3121 __u64 *val, int mult)
3123 char kernbuf[22], *end, *pbuf;
3124 __u64 whole, frac = 0, units;
3125 unsigned frac_d = 1;
3127 if (count > (sizeof(kernbuf) - 1))
3130 if (copy_from_user(kernbuf, buffer, count))
3133 kernbuf[count] = '\0';
3140 whole = simple_strtoull(pbuf, &end, 10);
3144 if (end != NULL && *end == '.') {
3148 /* need to limit frac_d to a __u32 */
3149 if (strlen(pbuf) > 10)
3152 frac = simple_strtoull(pbuf, &end, 10);
3153 /* count decimal places */
3154 for (i = 0; i < (end - pbuf); i++)
3173 /* Specified units override the multiplier */
3175 mult = mult < 0 ? -units : units;
3178 do_div(frac, frac_d);
3179 *val = whole * mult + frac;
3182 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
3184 static char *lprocfs_strnstr(const char *s1, const char *s2, size_t len)
3193 if (!memcmp(s1, s2, l2))
3201 * Find the string \a name in the input \a buffer, and return a pointer to the
3202 * value immediately following \a name, reducing \a count appropriately.
3203 * If \a name is not found the original \a buffer is returned.
3205 char *lprocfs_find_named_value(const char *buffer, const char *name,
3209 size_t buflen = *count;
3211 /* there is no strnstr() in rhel5 and ubuntu kernels */
3212 val = lprocfs_strnstr(buffer, name, buflen);
3214 return (char *)buffer;
3216 val += strlen(name); /* skip prefix */
3217 while (val < buffer + buflen && isspace(*val)) /* skip separator */
3221 while (val < buffer + buflen && isalnum(*val)) {
3226 return val - *count;
3228 EXPORT_SYMBOL(lprocfs_find_named_value);
3230 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent,
3233 const struct file_operations *seq_fops,
3236 struct proc_dir_entry *entry;
3239 /* Disallow secretly (un)writable entries. */
3240 LASSERT((seq_fops->write == NULL) == ((mode & 0222) == 0));
3242 entry = proc_create_data(name, mode, parent, seq_fops, data);
3249 EXPORT_SYMBOL(lprocfs_seq_create);
3251 int lprocfs_obd_seq_create(struct obd_device *dev,
3254 const struct file_operations *seq_fops,
3257 return (lprocfs_seq_create(dev->obd_proc_entry, name,
3258 mode, seq_fops, data));
3260 EXPORT_SYMBOL(lprocfs_obd_seq_create);
3262 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
3264 if (value >= OBD_HIST_MAX)
3265 value = OBD_HIST_MAX - 1;
3267 spin_lock(&oh->oh_lock);
3268 oh->oh_buckets[value]++;
3269 spin_unlock(&oh->oh_lock);
3271 EXPORT_SYMBOL(lprocfs_oh_tally);
3273 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
3275 unsigned int val = 0;
3277 if (likely(value != 0))
3278 val = min(fls(value - 1), OBD_HIST_MAX);
3280 lprocfs_oh_tally(oh, val);
3282 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
3284 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
3286 unsigned long ret = 0;
3289 for (i = 0; i < OBD_HIST_MAX; i++)
3290 ret += oh->oh_buckets[i];
3293 EXPORT_SYMBOL(lprocfs_oh_sum);
3295 void lprocfs_oh_clear(struct obd_histogram *oh)
3297 spin_lock(&oh->oh_lock);
3298 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
3299 spin_unlock(&oh->oh_lock);
3301 EXPORT_SYMBOL(lprocfs_oh_clear);
3303 #ifdef HAVE_SERVER_SUPPORT
3304 int lprocfs_hash_seq_show(struct seq_file *m, void *data)
3306 struct obd_device *obd = m->private;
3312 c += cfs_hash_debug_header_seq(m);
3313 c += cfs_hash_debug_str_seq(obd->obd_uuid_hash, m);
3314 c += cfs_hash_debug_str_seq(obd->obd_nid_hash, m);
3315 c += cfs_hash_debug_str_seq(obd->obd_nid_stats_hash, m);
3318 EXPORT_SYMBOL(lprocfs_hash_seq_show);
3320 int lprocfs_recovery_status_seq_show(struct seq_file *m, void *data)
3322 struct obd_device *obd = m->private;
3324 LASSERT(obd != NULL);
3326 seq_printf(m, "status: \n");
3327 if (obd->obd_max_recoverable_clients == 0) {
3328 seq_printf(m, "INACTIVE\n");
3332 /* sampled unlocked, but really... */
3333 if (obd->obd_recovering == 0) {
3334 seq_printf(m, "COMPLETE\n");
3335 seq_printf(m, "recovery_start: %lu\n", obd->obd_recovery_start);
3336 seq_printf(m, "recovery_duration: %lu\n",
3337 obd->obd_recovery_end - obd->obd_recovery_start);
3338 /* Number of clients that have completed recovery */
3339 seq_printf(m, "completed_clients: %d/%d\n",
3340 obd->obd_max_recoverable_clients -
3341 obd->obd_stale_clients,
3342 obd->obd_max_recoverable_clients);
3343 seq_printf(m, "replayed_requests: %d\n",
3344 obd->obd_replayed_requests);
3345 seq_printf(m, "last_transno: "LPD64"\n",
3346 obd->obd_next_recovery_transno - 1);
3347 seq_printf(m, "VBR: %s\n", obd->obd_version_recov ?
3348 "ENABLED" : "DISABLED");
3349 seq_printf(m, "IR: %s\n", obd->obd_no_ir ?
3350 "DISABLED" : "ENABLED");
3354 seq_printf(m, "RECOVERING\n");
3355 seq_printf(m, "recovery_start: %lu\n", obd->obd_recovery_start);
3356 seq_printf(m, "time_remaining: %lu\n",
3357 cfs_time_current_sec() >=
3358 obd->obd_recovery_start +
3359 obd->obd_recovery_timeout ? 0 :
3360 obd->obd_recovery_start +
3361 obd->obd_recovery_timeout -
3362 cfs_time_current_sec());
3363 seq_printf(m, "connected_clients: %d/%d\n",
3364 atomic_read(&obd->obd_connected_clients),
3365 obd->obd_max_recoverable_clients);
3366 /* Number of clients that have completed recovery */
3367 seq_printf(m, "req_replay_clients: %d\n",
3368 atomic_read(&obd->obd_req_replay_clients));
3369 seq_printf(m, "lock_repay_clients: %d\n",
3370 atomic_read(&obd->obd_lock_replay_clients));
3371 seq_printf(m, "completed_clients: %d\n",
3372 atomic_read(&obd->obd_connected_clients) -
3373 atomic_read(&obd->obd_lock_replay_clients));
3374 seq_printf(m, "evicted_clients: %d\n", obd->obd_stale_clients);
3375 seq_printf(m, "replayed_requests: %d\n", obd->obd_replayed_requests);
3376 seq_printf(m, "queued_requests: %d\n",
3377 obd->obd_requests_queued_for_recovery);
3378 seq_printf(m, "next_transno: "LPD64"\n",
3379 obd->obd_next_recovery_transno);
3383 EXPORT_SYMBOL(lprocfs_recovery_status_seq_show);
3385 int lprocfs_ir_factor_seq_show(struct seq_file *m, void *data)
3387 struct obd_device *obd = m->private;
3389 LASSERT(obd != NULL);
3390 return seq_printf(m, "%d\n", obd->obd_recovery_ir_factor);
3392 EXPORT_SYMBOL(lprocfs_ir_factor_seq_show);
3395 lprocfs_ir_factor_seq_write(struct file *file, const char *buffer,
3396 size_t count, loff_t *off)
3398 struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
3401 LASSERT(obd != NULL);
3402 rc = lprocfs_write_helper(buffer, count, &val);
3406 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
3409 obd->obd_recovery_ir_factor = val;
3412 EXPORT_SYMBOL(lprocfs_ir_factor_seq_write);
3414 int lprocfs_recovery_time_soft_seq_show(struct seq_file *m, void *data)
3416 struct obd_device *obd = m->private;
3418 LASSERT(obd != NULL);
3419 return seq_printf(m, "%d\n", obd->obd_recovery_timeout);
3421 EXPORT_SYMBOL(lprocfs_recovery_time_soft_seq_show);
3424 lprocfs_recovery_time_soft_seq_write(struct file *file, const char *buffer,
3425 size_t count, loff_t *off)
3427 struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
3430 LASSERT(obd != NULL);
3431 rc = lprocfs_write_helper(buffer, count, &val);
3435 obd->obd_recovery_timeout = val;
3438 EXPORT_SYMBOL(lprocfs_recovery_time_soft_seq_write);
3440 int lprocfs_recovery_time_hard_seq_show(struct seq_file *m, void *data)
3442 struct obd_device *obd = m->private;
3444 LASSERT(obd != NULL);
3445 return seq_printf(m, "%u\n", obd->obd_recovery_time_hard);
3447 EXPORT_SYMBOL(lprocfs_recovery_time_hard_seq_show);
3450 lprocfs_recovery_time_hard_seq_write(struct file *file, const char *buffer,
3451 size_t count, loff_t *off)
3453 struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
3456 LASSERT(obd != NULL);
3457 rc = lprocfs_write_helper(buffer, count, &val);
3461 obd->obd_recovery_time_hard = val;
3464 EXPORT_SYMBOL(lprocfs_recovery_time_hard_seq_write);
3466 int lprocfs_target_instance_seq_show(struct seq_file *m, void *data)
3468 struct obd_device *obd = m->private;
3469 struct obd_device_target *target = &obd->u.obt;
3471 LASSERT(obd != NULL);
3472 LASSERT(target->obt_magic == OBT_MAGIC);
3473 return seq_printf(m, "%u\n", obd->u.obt.obt_instance);
3475 EXPORT_SYMBOL(lprocfs_target_instance_seq_show);
3477 #ifndef HAVE_ONLY_PROCFS_SEQ
3478 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
3479 int count, int *eof, void *data)
3481 struct obd_device *obd = data;
3487 c += cfs_hash_debug_header(page, count);
3488 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
3489 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
3490 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
3494 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
3496 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
3497 int count, int *eof, void *data)
3499 struct obd_device *obd = data;
3502 LASSERT(obd != NULL);
3503 LASSERT(count >= 0);
3505 /* Set start of user data returned to
3506 page + off since the user may have
3507 requested to read much smaller than
3508 what we need to read */
3509 *start = page + off;
3512 * We know we are allocated a page here.
3513 * Also we know that this function will
3514 * not need to write more than a page
3515 * so we can truncate at PAGE_CACHE_SIZE.
3517 size = min(count + (int)off + 1, (int)PAGE_CACHE_SIZE);
3519 /* Initialize the page */
3520 memset(page, 0, size);
3522 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
3524 if (obd->obd_max_recoverable_clients == 0) {
3525 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
3531 /* sampled unlocked, but really... */
3532 if (obd->obd_recovering == 0) {
3533 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
3535 if (lprocfs_obd_snprintf(&page, size, &len,
3536 "recovery_start: %lu\n",
3537 obd->obd_recovery_start) <= 0)
3539 if (lprocfs_obd_snprintf(&page, size, &len,
3540 "recovery_duration: %lu\n",
3541 obd->obd_recovery_end -
3542 obd->obd_recovery_start) <= 0)
3544 /* Number of clients that have completed recovery */
3545 if (lprocfs_obd_snprintf(&page, size, &len,
3546 "completed_clients: %d/%d\n",
3547 obd->obd_max_recoverable_clients -
3548 obd->obd_stale_clients,
3549 obd->obd_max_recoverable_clients) <= 0)
3551 if (lprocfs_obd_snprintf(&page, size, &len,
3552 "replayed_requests: %d\n",
3553 obd->obd_replayed_requests) <= 0)
3555 if (lprocfs_obd_snprintf(&page, size, &len,
3556 "last_transno: "LPD64"\n",
3557 obd->obd_next_recovery_transno - 1)<=0)
3559 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
3560 obd->obd_version_recov ?
3561 "ENABLED" : "DISABLED") <=0)
3563 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
3565 "DISABLED" : "ENABLED") <= 0)
3570 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
3572 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
3573 obd->obd_recovery_start) <= 0)
3575 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
3576 cfs_time_current_sec() >=
3577 obd->obd_recovery_start +
3578 obd->obd_recovery_timeout ? 0 :
3579 obd->obd_recovery_start +
3580 obd->obd_recovery_timeout -
3581 cfs_time_current_sec()) <= 0)
3583 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
3584 atomic_read(&obd->obd_connected_clients),
3585 obd->obd_max_recoverable_clients) <= 0)
3587 /* Number of clients that have completed recovery */
3588 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
3589 atomic_read(&obd->obd_req_replay_clients))
3592 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
3593 atomic_read(&obd->obd_lock_replay_clients))
3596 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
3597 atomic_read(&obd->obd_connected_clients) -
3598 atomic_read(&obd->obd_lock_replay_clients))
3601 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
3602 obd->obd_stale_clients) <= 0)
3604 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
3605 obd->obd_replayed_requests) <= 0)
3607 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
3608 obd->obd_requests_queued_for_recovery) <= 0)
3611 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
3612 obd->obd_next_recovery_transno) <= 0)
3618 return min(count, len - (int)off);
3620 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
3622 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
3623 int count, int *eof, void *data)
3625 struct obd_device *obd = (struct obd_device *)data;
3626 LASSERT(obd != NULL);
3628 return snprintf(page, count, "%d\n",
3629 obd->obd_recovery_ir_factor);
3631 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
3633 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
3634 unsigned long count, void *data)
3636 struct obd_device *obd = (struct obd_device *)data;
3638 LASSERT(obd != NULL);
3640 rc = lprocfs_write_helper(buffer, count, &val);
3644 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
3647 obd->obd_recovery_ir_factor = val;
3650 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
3652 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
3653 int count, int *eof, void *data)
3655 struct obd_device *obd = (struct obd_device *)data;
3656 LASSERT(obd != NULL);
3658 return snprintf(page, count, "%d\n",
3659 obd->obd_recovery_timeout);
3661 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
3663 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
3664 unsigned long count, void *data)
3666 struct obd_device *obd = (struct obd_device *)data;
3668 LASSERT(obd != NULL);
3670 rc = lprocfs_write_helper(buffer, count, &val);
3674 obd->obd_recovery_timeout = val;
3677 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
3679 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
3680 int count, int *eof, void *data)
3682 struct obd_device *obd = data;
3683 LASSERT(obd != NULL);
3685 return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
3687 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
3689 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
3690 unsigned long count, void *data)
3692 struct obd_device *obd = data;
3694 LASSERT(obd != NULL);
3696 rc = lprocfs_write_helper(buffer, count, &val);
3700 obd->obd_recovery_time_hard = val;
3703 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
3705 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
3706 int count, int *eof, void *data)
3708 struct obd_device *obd = (struct obd_device *)data;
3709 struct obd_device_target *target = &obd->u.obt;
3711 LASSERT(obd != NULL);
3712 LASSERT(target->obt_magic == OBT_MAGIC);
3714 return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
3716 EXPORT_SYMBOL(lprocfs_target_rd_instance);
3717 #endif /* HAVE_ONLY_PROCFS_SEQ */
3718 #endif /* HAVE_SERVER_SUPPORT */
3720 int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
3721 int count, int *eof, void *data)
3723 struct obd_device *dev = data;
3724 struct client_obd *cli = &dev->u.cli;
3727 client_obd_list_lock(&cli->cl_loi_list_lock);
3728 rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
3729 client_obd_list_unlock(&cli->cl_loi_list_lock);
3732 EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
3734 int lprocfs_obd_max_pages_per_rpc_seq_show(struct seq_file *m, void *data)
3736 struct obd_device *dev = data;
3737 struct client_obd *cli = &dev->u.cli;
3740 client_obd_list_lock(&cli->cl_loi_list_lock);
3741 rc = seq_printf(m, "%d\n", cli->cl_max_pages_per_rpc);
3742 client_obd_list_unlock(&cli->cl_loi_list_lock);
3745 EXPORT_SYMBOL(lprocfs_obd_max_pages_per_rpc_seq_show);