1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 only,
10 * as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License version 2 for more details (a copy is included
16 * in the LICENSE file that accompanied this code).
18 * You should have received a copy of the GNU General Public License
19 * version 2 along with this program; If not, see
20 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
22 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23 * CA 95054 USA or visit www.sun.com if you need additional information or
29 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
30 * Use is subject to license terms.
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>
42 # define EXPORT_SYMTAB
44 #define DEBUG_SUBSYSTEM S_CLASS
47 # include <liblustre.h>
50 #include <obd_class.h>
51 #include <lprocfs_status.h>
52 #include <lustre_fsfilt.h>
53 #include <lustre_log.h>
54 #include <lustre/lustre_idl.h>
58 #define MAX_STRING_SIZE 128
60 /* for bug 10866, global variable */
61 CFS_DECLARE_RWSEM(_lprocfs_lock);
62 EXPORT_SYMBOL(_lprocfs_lock);
64 int lprocfs_seq_release(struct inode *inode, struct file *file)
67 return seq_release(inode, file);
69 EXPORT_SYMBOL(lprocfs_seq_release);
71 struct proc_dir_entry *lprocfs_srch(struct proc_dir_entry *head,
74 struct proc_dir_entry *temp;
81 while (temp != NULL) {
82 if (strcmp(temp->name, name) == 0) {
93 /* lprocfs API calls */
95 /* Function that emulates snprintf but also has the side effect of advancing
96 the page pointer for the next write into the buffer, incrementing the total
97 length written to the buffer, and decrementing the size left in the
99 static int lprocfs_obd_snprintf(char **page, int end, int *len,
100 const char *format, ...)
108 va_start(list, format);
109 n = vsnprintf(*page, end - *len, format, list);
112 *page += n; *len += n;
116 cfs_proc_dir_entry_t *lprocfs_add_simple(struct proc_dir_entry *root,
118 read_proc_t *read_proc,
119 write_proc_t *write_proc,
121 struct file_operations *fops)
123 cfs_proc_dir_entry_t *proc;
126 if (root == NULL || name == NULL)
127 return ERR_PTR(-EINVAL);
134 proc = create_proc_entry(name, mode, root);
136 CERROR("LprocFS: No memory to create /proc entry %s", name);
137 return ERR_PTR(-ENOMEM);
139 proc->read_proc = read_proc;
140 proc->write_proc = write_proc;
143 proc->proc_fops = fops;
147 struct proc_dir_entry *lprocfs_add_symlink(const char *name,
148 struct proc_dir_entry *parent, const char *format, ...)
150 struct proc_dir_entry *entry;
154 if (parent == NULL || format == NULL)
157 OBD_ALLOC_WAIT(dest, MAX_STRING_SIZE + 1);
161 va_start(ap, format);
162 vsnprintf(dest, MAX_STRING_SIZE, format, ap);
165 entry = proc_symlink(name, parent, dest);
167 CERROR("LprocFS: Could not create symbolic link from %s to %s",
170 OBD_FREE(dest, MAX_STRING_SIZE + 1);
174 static ssize_t lprocfs_fops_read(struct file *f, char __user *buf,
175 size_t size, loff_t *ppos)
177 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
178 char *page, *start = NULL;
179 int rc = 0, eof = 1, count;
181 if (*ppos >= CFS_PAGE_SIZE)
184 page = (char *)__get_free_page(GFP_KERNEL);
188 if (LPROCFS_ENTRY_AND_CHECK(dp))
191 OBD_FAIL_TIMEOUT(OBD_FAIL_LPROC_REMOVE, 10);
193 rc = dp->read_proc(page, &start, *ppos, CFS_PAGE_SIZE,
199 /* for lustre proc read, the read count must be less than PAGE_SIZE */
208 start = page + *ppos;
209 } else if (start < page) {
213 count = (rc < size) ? rc : size;
214 if (cfs_copy_to_user(buf, start, count)) {
221 free_page((unsigned long)page);
225 static ssize_t lprocfs_fops_write(struct file *f, const char __user *buf,
226 size_t size, loff_t *ppos)
228 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
231 if (LPROCFS_ENTRY_AND_CHECK(dp))
234 rc = dp->write_proc(f, buf, size, dp->data);
239 static struct file_operations lprocfs_generic_fops = {
240 .owner = THIS_MODULE,
241 .read = lprocfs_fops_read,
242 .write = lprocfs_fops_write,
245 int lprocfs_evict_client_open(struct inode *inode, struct file *f)
247 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
248 struct obd_device *obd = dp->data;
250 cfs_atomic_inc(&obd->obd_evict_inprogress);
255 int lprocfs_evict_client_release(struct inode *inode, struct file *f)
257 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
258 struct obd_device *obd = dp->data;
260 cfs_atomic_dec(&obd->obd_evict_inprogress);
261 cfs_waitq_signal(&obd->obd_evict_inprogress_waitq);
266 struct file_operations lprocfs_evict_client_fops = {
267 .owner = THIS_MODULE,
268 .read = lprocfs_fops_read,
269 .write = lprocfs_fops_write,
270 .open = lprocfs_evict_client_open,
271 .release = lprocfs_evict_client_release,
273 EXPORT_SYMBOL(lprocfs_evict_client_fops);
278 * \param root [in] The parent proc entry on which new entry will be added.
279 * \param list [in] Array of proc entries to be added.
280 * \param data [in] The argument to be passed when entries read/write routines
281 * are called through /proc file.
283 * \retval 0 on success
286 int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list,
289 if (root == NULL || list == NULL)
292 while (list->name != NULL) {
293 struct proc_dir_entry *cur_root, *proc;
294 char *pathcopy, *cur, *next, pathbuf[64];
295 int pathsize = strlen(list->name) + 1;
300 /* need copy of path for strsep */
301 if (strlen(list->name) > sizeof(pathbuf) - 1) {
302 OBD_ALLOC(pathcopy, pathsize);
303 if (pathcopy == NULL)
310 strcpy(pathcopy, list->name);
312 while (cur_root != NULL && (cur = strsep(&next, "/"))) {
313 if (*cur =='\0') /* skip double/trailing "/" */
316 proc = lprocfs_srch(cur_root, cur);
317 CDEBUG(D_OTHER, "cur_root=%s, cur=%s, next=%s, (%s)\n",
318 cur_root->name, cur, next,
319 (proc ? "exists" : "new"));
321 cur_root = (proc ? proc :
322 proc_mkdir(cur, cur_root));
323 } else if (proc == NULL) {
325 if (list->proc_mode != 0000) {
326 mode = list->proc_mode;
330 if (list->write_fptr)
333 proc = create_proc_entry(cur, mode, cur_root);
337 if (pathcopy != pathbuf)
338 OBD_FREE(pathcopy, pathsize);
340 if (cur_root == NULL || proc == NULL) {
341 CERROR("LprocFS: No memory to create /proc entry %s",
347 proc->proc_fops = list->fops;
349 proc->proc_fops = &lprocfs_generic_fops;
350 proc->read_proc = list->read_fptr;
351 proc->write_proc = list->write_fptr;
352 proc->data = (list->data ? list->data : data);
358 void lprocfs_remove(struct proc_dir_entry **rooth)
360 struct proc_dir_entry *root = *rooth;
361 struct proc_dir_entry *temp = root;
362 struct proc_dir_entry *rm_entry;
363 struct proc_dir_entry *parent;
369 parent = root->parent;
370 LASSERT(parent != NULL);
371 LPROCFS_WRITE_ENTRY(); /* search vs remove race */
374 while (temp->subdir != NULL)
380 /* Memory corruption once caused this to fail, and
381 without this LASSERT we would loop here forever. */
382 LASSERTF(strlen(rm_entry->name) == rm_entry->namelen,
383 "0x%p %s/%s len %d\n", rm_entry, temp->name,
384 rm_entry->name, (int)strlen(rm_entry->name));
386 /* Now, the rm_entry->deleted flags is protected
387 * by _lprocfs_lock. */
388 rm_entry->data = NULL;
389 remove_proc_entry(rm_entry->name, temp);
393 LPROCFS_WRITE_EXIT();
396 void lprocfs_remove_proc_entry(const char *name, struct proc_dir_entry *parent)
398 LASSERT(parent != NULL);
399 remove_proc_entry(name, parent);
402 struct proc_dir_entry *lprocfs_register(const char *name,
403 struct proc_dir_entry *parent,
404 struct lprocfs_vars *list, void *data)
406 struct proc_dir_entry *newchild;
408 newchild = lprocfs_srch(parent, name);
409 if (newchild != NULL) {
410 CERROR(" Lproc: Attempting to register %s more than once \n",
412 return ERR_PTR(-EALREADY);
415 newchild = proc_mkdir(name, parent);
416 if (newchild != NULL && list != NULL) {
417 int rc = lprocfs_add_vars(newchild, list, data);
419 lprocfs_remove(&newchild);
426 /* Generic callbacks */
427 int lprocfs_rd_uint(char *page, char **start, off_t off,
428 int count, int *eof, void *data)
430 unsigned int *temp = data;
431 return snprintf(page, count, "%u\n", *temp);
434 int lprocfs_wr_uint(struct file *file, const char *buffer,
435 unsigned long count, void *data)
438 char dummy[MAX_STRING_SIZE + 1], *end;
441 dummy[MAX_STRING_SIZE] = '\0';
442 if (cfs_copy_from_user(dummy, buffer, MAX_STRING_SIZE))
445 tmp = simple_strtoul(dummy, &end, 0);
449 *p = (unsigned int)tmp;
453 int lprocfs_rd_u64(char *page, char **start, off_t off,
454 int count, int *eof, void *data)
456 LASSERT(data != NULL);
458 return snprintf(page, count, LPU64"\n", *(__u64 *)data);
461 int lprocfs_rd_atomic(char *page, char **start, off_t off,
462 int count, int *eof, void *data)
464 cfs_atomic_t *atom = data;
465 LASSERT(atom != NULL);
467 return snprintf(page, count, "%d\n", cfs_atomic_read(atom));
470 int lprocfs_wr_atomic(struct file *file, const char *buffer,
471 unsigned long count, void *data)
473 cfs_atomic_t *atm = data;
477 rc = lprocfs_write_helper(buffer, count, &val);
484 cfs_atomic_set(atm, val);
488 int lprocfs_rd_uuid(char *page, char **start, off_t off, int count,
489 int *eof, void *data)
491 struct obd_device *obd = data;
493 LASSERT(obd != NULL);
495 return snprintf(page, count, "%s\n", obd->obd_uuid.uuid);
498 int lprocfs_rd_name(char *page, char **start, off_t off, int count,
499 int *eof, void *data)
501 struct obd_device *dev = data;
503 LASSERT(dev != NULL);
504 LASSERT(dev->obd_name != NULL);
506 return snprintf(page, count, "%s\n", dev->obd_name);
509 int lprocfs_rd_fstype(char *page, char **start, off_t off, int count, int *eof,
512 struct obd_device *obd = data;
514 LASSERT(obd != NULL);
515 LASSERT(obd->obd_fsops != NULL);
516 LASSERT(obd->obd_fsops->fs_type != NULL);
517 return snprintf(page, count, "%s\n", obd->obd_fsops->fs_type);
520 int lprocfs_rd_blksize(char *page, char **start, off_t off, int count,
521 int *eof, void *data)
523 struct obd_statfs osfs;
524 int rc = obd_statfs(data, &osfs,
525 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
529 rc = snprintf(page, count, "%u\n", osfs.os_bsize);
534 int lprocfs_rd_kbytestotal(char *page, char **start, off_t off, int count,
535 int *eof, void *data)
537 struct obd_statfs osfs;
538 int rc = obd_statfs(data, &osfs,
539 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
542 __u32 blk_size = osfs.os_bsize >> 10;
543 __u64 result = osfs.os_blocks;
545 while (blk_size >>= 1)
549 rc = snprintf(page, count, LPU64"\n", result);
554 int lprocfs_rd_kbytesfree(char *page, char **start, off_t off, int count,
555 int *eof, void *data)
557 struct obd_statfs osfs;
558 int rc = obd_statfs(data, &osfs,
559 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
562 __u32 blk_size = osfs.os_bsize >> 10;
563 __u64 result = osfs.os_bfree;
565 while (blk_size >>= 1)
569 rc = snprintf(page, count, LPU64"\n", result);
574 int lprocfs_rd_kbytesavail(char *page, char **start, off_t off, int count,
575 int *eof, void *data)
577 struct obd_statfs osfs;
578 int rc = obd_statfs(data, &osfs,
579 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
582 __u32 blk_size = osfs.os_bsize >> 10;
583 __u64 result = osfs.os_bavail;
585 while (blk_size >>= 1)
589 rc = snprintf(page, count, LPU64"\n", result);
594 int lprocfs_rd_filestotal(char *page, char **start, off_t off, int count,
595 int *eof, void *data)
597 struct obd_statfs osfs;
598 int rc = obd_statfs(data, &osfs,
599 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
603 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
609 int lprocfs_rd_filesfree(char *page, char **start, off_t off, int count,
610 int *eof, void *data)
612 struct obd_statfs osfs;
613 int rc = obd_statfs(data, &osfs,
614 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
618 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
623 int lprocfs_rd_server_uuid(char *page, char **start, off_t off, int count,
624 int *eof, void *data)
626 struct obd_device *obd = data;
627 struct obd_import *imp;
628 char *imp_state_name = NULL;
631 LASSERT(obd != NULL);
632 LPROCFS_CLIMP_CHECK(obd);
633 imp = obd->u.cli.cl_import;
634 imp_state_name = ptlrpc_import_state_name(imp->imp_state);
636 rc = snprintf(page, count, "%s\t%s%s\n",
637 obd2cli_tgt(obd), imp_state_name,
638 imp->imp_deactive ? "\tDEACTIVATED" : "");
640 LPROCFS_CLIMP_EXIT(obd);
644 int lprocfs_rd_conn_uuid(char *page, char **start, off_t off, int count,
645 int *eof, void *data)
647 struct obd_device *obd = data;
648 struct ptlrpc_connection *conn;
651 LASSERT(obd != NULL);
653 LPROCFS_CLIMP_CHECK(obd);
654 conn = obd->u.cli.cl_import->imp_connection;
656 if (conn && obd->u.cli.cl_import) {
657 rc = snprintf(page, count, "%s\n",
658 conn->c_remote_uuid.uuid);
660 rc = snprintf(page, count, "%s\n", "<none>");
663 LPROCFS_CLIMP_EXIT(obd);
667 /** add up per-cpu counters */
668 void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
669 struct lprocfs_counter *cnt)
671 unsigned int num_cpu;
672 struct lprocfs_counter t;
673 struct lprocfs_counter *percpu_cntr;
676 memset(cnt, 0, sizeof(*cnt));
679 /* set count to 1 to avoid divide-by-zero errs in callers */
684 cnt->lc_min = LC_MIN_INIT;
686 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
689 num_cpu = cfs_num_possible_cpus();
691 for (i = 0; i < num_cpu; i++) {
692 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[idx];
695 centry = cfs_atomic_read(&percpu_cntr-> \
697 t.lc_count = percpu_cntr->lc_count;
698 t.lc_sum = percpu_cntr->lc_sum;
699 t.lc_min = percpu_cntr->lc_min;
700 t.lc_max = percpu_cntr->lc_max;
701 t.lc_sumsquare = percpu_cntr->lc_sumsquare;
702 } while (centry != cfs_atomic_read(&percpu_cntr->lc_cntl. \
704 centry != cfs_atomic_read(&percpu_cntr->lc_cntl. \
706 cnt->lc_count += t.lc_count;
707 cnt->lc_sum += t.lc_sum;
708 if (t.lc_min < cnt->lc_min)
709 cnt->lc_min = t.lc_min;
710 if (t.lc_max > cnt->lc_max)
711 cnt->lc_max = t.lc_max;
712 cnt->lc_sumsquare += t.lc_sumsquare;
715 cnt->lc_units = stats->ls_percpu[0]->lp_cntr[idx].lc_units;
719 * Append a space separated list of current set flags to str.
721 #define flag2str(flag) \
722 if (imp->imp_##flag && max - len > 0) \
723 len += snprintf(str + len, max - len, "%s" #flag, len ? ", " : "");
724 static int obd_import_flags2str(struct obd_import *imp, char *str, int max)
728 if (imp->imp_obd->obd_no_recov)
729 len += snprintf(str, max - len, "no_recov");
733 flag2str(replayable);
739 static const char *obd_connect_names[] = {
753 "join_file(obsolete)",
757 "remote_client_by_force",
766 "mds_mds_connection",
769 "alt_checksum_algorithm",
781 static int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
786 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
788 ret += snprintf(page + ret, count - ret, "%s%s",
789 ret ? sep : "", obd_connect_names[i]);
791 if (flags & ~(mask - 1))
792 ret += snprintf(page + ret, count - ret,
793 "%sunknown flags "LPX64,
794 ret ? sep : "", flags & ~(mask - 1));
798 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
799 int *eof, void *data)
801 struct lprocfs_counter ret;
802 struct obd_device *obd = (struct obd_device *)data;
803 struct obd_import *imp;
804 struct obd_import_conn *conn;
807 LASSERT(obd != NULL);
808 LPROCFS_CLIMP_CHECK(obd);
809 imp = obd->u.cli.cl_import;
812 i = snprintf(page, count,
820 ptlrpc_import_state_name(imp->imp_state));
821 i += obd_connect_flags2str(page + i, count - i,
822 imp->imp_connect_data.ocd_connect_flags,
824 i += snprintf(page + i, count - i,
827 i += obd_import_flags2str(imp, page + i, count - i);
829 i += snprintf(page + i, count - i,
832 " failover_nids: [");
833 cfs_spin_lock(&imp->imp_lock);
835 cfs_list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
836 i += snprintf(page + i, count - i, "%s%s", j ? ", " : "",
837 libcfs_nid2str(conn->oic_conn->c_peer.nid));
840 cfs_spin_unlock(&imp->imp_lock);
841 i += snprintf(page + i, count - i,
843 " current_connection: %s\n"
844 " connection_attempts: %u\n"
846 " in-progress_invalidations: %u\n",
847 libcfs_nid2str(imp->imp_connection->c_peer.nid),
850 cfs_atomic_read(&imp->imp_inval_count));
852 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
853 if (ret.lc_count != 0)
854 do_div(ret.lc_sum, ret.lc_count);
857 i += snprintf(page + i, count - i,
860 " unregistering: %u\n"
862 " avg_waittime: "LPU64" %s\n",
863 cfs_atomic_read(&imp->imp_inflight),
864 cfs_atomic_read(&imp->imp_unregistering),
865 cfs_atomic_read(&imp->imp_timeouts),
866 ret.lc_sum, ret.lc_units);
869 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
870 if (imp->imp_at.iat_portal[j] == 0)
872 k = max_t(unsigned int, k,
873 at_get(&imp->imp_at.iat_service_estimate[j]));
875 i += snprintf(page + i, count - i,
876 " service_estimates:\n"
877 " services: %u sec\n"
878 " network: %u sec\n",
880 at_get(&imp->imp_at.iat_net_latency));
882 i += snprintf(page + i, count - i,
884 " last_replay: "LPU64"\n"
885 " peer_committed: "LPU64"\n"
886 " last_checked: "LPU64"\n",
887 imp->imp_last_replay_transno,
888 imp->imp_peer_committed_transno,
889 imp->imp_last_transno_checked);
892 for (rw = 0; rw <= 1; rw++) {
893 lprocfs_stats_collect(obd->obd_svc_stats,
894 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
896 if (ret.lc_sum > 0 && ret.lc_count > 0) {
897 do_div(ret.lc_sum, ret.lc_count);
898 i += snprintf(page + i, count - i,
899 " %s_data_averages:\n"
900 " bytes_per_rpc: "LPU64"\n",
901 rw ? "write" : "read",
905 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
906 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
907 if (ret.lc_sum > 0 && ret.lc_count != 0) {
908 do_div(ret.lc_sum, ret.lc_count);
909 i += snprintf(page + i, count - i,
910 " %s_per_rpc: "LPU64"\n",
911 ret.lc_units, ret.lc_sum);
914 i += snprintf(page + i, count - i,
915 " MB_per_sec: %u.%.02u\n",
916 k / j, (100 * k / j) % 100);
920 LPROCFS_CLIMP_EXIT(obd);
924 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
925 int *eof, void *data)
927 struct obd_device *obd = (struct obd_device *)data;
928 struct obd_import *imp;
931 LASSERT(obd != NULL);
932 LPROCFS_CLIMP_CHECK(obd);
933 imp = obd->u.cli.cl_import;
936 i = snprintf(page, count, "current_state: %s\n",
937 ptlrpc_import_state_name(imp->imp_state));
938 i += snprintf(page + i, count - i,
940 k = imp->imp_state_hist_idx;
941 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
942 struct import_state_hist *ish =
943 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
944 if (ish->ish_state == 0)
946 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
948 ptlrpc_import_state_name(ish->ish_state));
951 LPROCFS_CLIMP_EXIT(obd);
955 int lprocfs_at_hist_helper(char *page, int count, int rc,
956 struct adaptive_timeout *at)
959 for (i = 0; i < AT_BINS; i++)
960 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
961 rc += snprintf(page + rc, count - rc, "\n");
965 /* See also ptlrpc_lprocfs_rd_timeouts */
966 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
967 int *eof, void *data)
969 struct obd_device *obd = (struct obd_device *)data;
970 struct obd_import *imp;
971 unsigned int cur, worst;
976 LASSERT(obd != NULL);
977 LPROCFS_CLIMP_CHECK(obd);
978 imp = obd->u.cli.cl_import;
981 now = cfs_time_current_sec();
983 /* Some network health info for kicks */
984 s2dhms(&ts, now - imp->imp_last_reply_time);
985 rc += snprintf(page + rc, count - rc,
986 "%-10s : %ld, "DHMS_FMT" ago\n",
987 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
989 cur = at_get(&imp->imp_at.iat_net_latency);
990 worst = imp->imp_at.iat_net_latency.at_worst_ever;
991 worstt = imp->imp_at.iat_net_latency.at_worst_time;
992 s2dhms(&ts, now - worstt);
993 rc += snprintf(page + rc, count - rc,
994 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
995 "network", cur, worst, worstt, DHMS_VARS(&ts));
996 rc = lprocfs_at_hist_helper(page, count, rc,
997 &imp->imp_at.iat_net_latency);
999 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
1000 if (imp->imp_at.iat_portal[i] == 0)
1002 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
1003 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
1004 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
1005 s2dhms(&ts, now - worstt);
1006 rc += snprintf(page + rc, count - rc,
1007 "portal %-2d : cur %3u worst %3u (at %ld, "
1008 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
1009 cur, worst, worstt, DHMS_VARS(&ts));
1010 rc = lprocfs_at_hist_helper(page, count, rc,
1011 &imp->imp_at.iat_service_estimate[i]);
1014 LPROCFS_CLIMP_EXIT(obd);
1018 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1019 int count, int *eof, void *data)
1021 struct obd_device *obd = data;
1025 LPROCFS_CLIMP_CHECK(obd);
1026 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1027 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1028 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1029 ret += snprintf(page + ret, count - ret, "\n");
1030 LPROCFS_CLIMP_EXIT(obd);
1033 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1035 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1036 int *eof, void *data)
1038 struct obd_device *obd = data;
1040 LASSERT(obd != NULL);
1042 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1045 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1046 int *eof, void *data)
1048 struct obd_type *class = (struct obd_type*) data;
1050 LASSERT(class != NULL);
1052 return snprintf(page, count, "%d\n", class->typ_refcnt);
1055 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1059 LASSERT(obd != NULL);
1060 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1061 LASSERT(obd->obd_type->typ_procroot != NULL);
1063 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1064 obd->obd_type->typ_procroot,
1066 if (IS_ERR(obd->obd_proc_entry)) {
1067 rc = PTR_ERR(obd->obd_proc_entry);
1068 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1069 obd->obd_proc_entry = NULL;
1074 int lprocfs_obd_cleanup(struct obd_device *obd)
1078 if (obd->obd_proc_exports_entry) {
1079 /* Should be no exports left */
1080 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1081 lprocfs_remove(&obd->obd_proc_exports_entry);
1082 obd->obd_proc_exports_entry = NULL;
1084 if (obd->obd_proc_entry) {
1085 lprocfs_remove(&obd->obd_proc_entry);
1086 obd->obd_proc_entry = NULL;
1091 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1093 CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
1094 client_stat->nid_proc, client_stat->nid_stats,
1095 client_stat->nid_brw_stats);
1097 LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
1099 cfs_atomic_read(&client_stat->nid_exp_ref_count));
1101 cfs_hlist_del_init(&client_stat->nid_hash);
1103 if (client_stat->nid_proc)
1104 lprocfs_remove(&client_stat->nid_proc);
1106 if (client_stat->nid_stats)
1107 lprocfs_free_stats(&client_stat->nid_stats);
1109 if (client_stat->nid_brw_stats)
1110 OBD_FREE_PTR(client_stat->nid_brw_stats);
1112 if (client_stat->nid_ldlm_stats)
1113 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1115 OBD_FREE_PTR(client_stat);
1120 void lprocfs_free_per_client_stats(struct obd_device *obd)
1122 struct nid_stat *stat;
1125 /* we need extra list - because hash_exit called to early */
1126 /* not need locking because all clients is died */
1127 while(!cfs_list_empty(&obd->obd_nid_stats)) {
1128 stat = cfs_list_entry(obd->obd_nid_stats.next,
1129 struct nid_stat, nid_list);
1130 cfs_list_del_init(&stat->nid_list);
1131 lprocfs_free_client_stats(stat);
1137 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1138 enum lprocfs_stats_flags flags)
1140 struct lprocfs_stats *stats;
1141 unsigned int percpusize;
1143 unsigned int num_cpu;
1148 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1151 num_cpu = cfs_num_possible_cpus();
1153 OBD_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
1157 if (flags & LPROCFS_STATS_FLAG_NOPERCPU) {
1158 stats->ls_flags = flags;
1159 cfs_spin_lock_init(&stats->ls_lock);
1160 /* Use this lock only if there are no percpu areas */
1162 stats->ls_flags = 0;
1165 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
1167 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1169 for (i = 0; i < num_cpu; i++) {
1170 OBD_ALLOC(stats->ls_percpu[i], percpusize);
1171 if (stats->ls_percpu[i] == NULL) {
1172 for (j = 0; j < i; j++) {
1173 OBD_FREE(stats->ls_percpu[j], percpusize);
1174 stats->ls_percpu[j] = NULL;
1179 if (stats->ls_percpu[0] == NULL) {
1180 OBD_FREE(stats, offsetof(typeof(*stats),
1181 ls_percpu[num_cpu]));
1185 stats->ls_num = num;
1189 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1191 struct lprocfs_stats *stats = *statsh;
1192 unsigned int num_cpu;
1193 unsigned int percpusize;
1196 if (stats == NULL || stats->ls_num == 0)
1200 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1203 num_cpu = cfs_num_possible_cpus();
1205 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
1207 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1208 for (i = 0; i < num_cpu; i++)
1209 OBD_FREE(stats->ls_percpu[i], percpusize);
1210 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
1213 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1215 struct lprocfs_counter *percpu_cntr;
1217 unsigned int num_cpu;
1219 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1221 for (i = 0; i < num_cpu; i++) {
1222 for (j = 0; j < stats->ls_num; j++) {
1223 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
1224 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_entry);
1225 percpu_cntr->lc_count = 0;
1226 percpu_cntr->lc_sum = 0;
1227 percpu_cntr->lc_min = LC_MIN_INIT;
1228 percpu_cntr->lc_max = 0;
1229 percpu_cntr->lc_sumsquare = 0;
1230 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_exit);
1234 lprocfs_stats_unlock(stats);
1237 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1238 size_t len, loff_t *off)
1240 struct seq_file *seq = file->private_data;
1241 struct lprocfs_stats *stats = seq->private;
1243 lprocfs_clear_stats(stats);
1248 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1250 struct lprocfs_stats *stats = p->private;
1251 /* return 1st cpu location */
1252 return (*pos >= stats->ls_num) ? NULL :
1253 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1256 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1260 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1262 struct lprocfs_stats *stats = p->private;
1264 return (*pos >= stats->ls_num) ? NULL :
1265 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1268 /* seq file export of one lprocfs counter */
1269 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1271 struct lprocfs_stats *stats = p->private;
1272 struct lprocfs_counter *cntr = v;
1273 struct lprocfs_counter ret;
1276 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
1278 cfs_gettimeofday(&now);
1279 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1280 "snapshot_time", now.tv_sec, now.tv_usec);
1284 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
1286 lprocfs_stats_collect(stats, idx, &ret);
1288 if (ret.lc_count == 0)
1291 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", cntr->lc_name,
1292 ret.lc_count, cntr->lc_units);
1297 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
1298 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1299 ret.lc_min, ret.lc_max, ret.lc_sum);
1302 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
1303 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1307 rc = seq_printf(p, "\n");
1309 return (rc < 0) ? rc : 0;
1312 struct seq_operations lprocfs_stats_seq_sops = {
1313 start: lprocfs_stats_seq_start,
1314 stop: lprocfs_stats_seq_stop,
1315 next: lprocfs_stats_seq_next,
1316 show: lprocfs_stats_seq_show,
1319 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1321 struct proc_dir_entry *dp = PDE(inode);
1322 struct seq_file *seq;
1325 if (LPROCFS_ENTRY_AND_CHECK(dp))
1328 rc = seq_open(file, &lprocfs_stats_seq_sops);
1333 seq = file->private_data;
1334 seq->private = dp->data;
1338 struct file_operations lprocfs_stats_seq_fops = {
1339 .owner = THIS_MODULE,
1340 .open = lprocfs_stats_seq_open,
1342 .write = lprocfs_stats_seq_write,
1343 .llseek = seq_lseek,
1344 .release = lprocfs_seq_release,
1347 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1348 struct lprocfs_stats *stats)
1350 struct proc_dir_entry *entry;
1351 LASSERT(root != NULL);
1353 entry = create_proc_entry(name, 0644, root);
1356 entry->proc_fops = &lprocfs_stats_seq_fops;
1357 entry->data = stats;
1361 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1362 unsigned conf, const char *name, const char *units)
1364 struct lprocfs_counter *c;
1366 unsigned int num_cpu;
1368 LASSERT(stats != NULL);
1370 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1372 for (i = 0; i < num_cpu; i++) {
1373 c = &(stats->ls_percpu[i]->lp_cntr[index]);
1374 c->lc_config = conf;
1377 c->lc_min = LC_MIN_INIT;
1380 c->lc_units = units;
1383 lprocfs_stats_unlock(stats);
1385 EXPORT_SYMBOL(lprocfs_counter_init);
1387 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1389 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1390 LASSERT(coffset < stats->ls_num); \
1391 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1394 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1396 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1397 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1398 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1399 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1400 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1401 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1402 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1403 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1404 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1405 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1406 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1407 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1408 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1409 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1410 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1411 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1412 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1413 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1414 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
1415 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1416 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1417 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1418 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1419 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1420 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1421 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1422 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1423 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1424 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1425 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1426 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1427 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1428 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1429 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1430 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1431 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1432 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1433 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1434 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1435 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1436 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1437 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1438 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1439 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1440 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
1441 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1442 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1443 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1444 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1445 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1446 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1447 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1448 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1449 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1450 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1451 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1452 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1453 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1454 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1455 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1456 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1457 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quota_adjust_qunit);
1458 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1459 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1460 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1461 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1462 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1463 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1464 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1467 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1469 struct lprocfs_stats *stats;
1470 unsigned int num_stats;
1473 LASSERT(obd->obd_stats == NULL);
1474 LASSERT(obd->obd_proc_entry != NULL);
1475 LASSERT(obd->obd_cntr_base == 0);
1477 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1478 num_private_stats - 1 /* o_owner */;
1479 stats = lprocfs_alloc_stats(num_stats, 0);
1483 lprocfs_init_ops_stats(num_private_stats, stats);
1485 for (i = num_private_stats; i < num_stats; i++) {
1486 /* If this LBUGs, it is likely that an obd
1487 * operation was added to struct obd_ops in
1488 * <obd.h>, and that the corresponding line item
1489 * LPROCFS_OBD_OP_INIT(.., .., opname)
1490 * is missing from the list above. */
1491 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1492 "Missing obd_stat initializer obd_op "
1493 "operation at offset %d.\n", i - num_private_stats);
1495 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1497 lprocfs_free_stats(&stats);
1499 obd->obd_stats = stats;
1500 obd->obd_cntr_base = num_private_stats;
1505 void lprocfs_free_obd_stats(struct obd_device *obd)
1508 lprocfs_free_stats(&obd->obd_stats);
1511 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1513 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1514 LASSERT(coffset < stats->ls_num); \
1515 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1518 int lprocfs_alloc_md_stats(struct obd_device *obd,
1519 unsigned num_private_stats)
1521 struct lprocfs_stats *stats;
1522 unsigned int num_stats;
1525 LASSERT(obd->md_stats == NULL);
1526 LASSERT(obd->obd_proc_entry != NULL);
1527 LASSERT(obd->md_cntr_base == 0);
1529 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1531 stats = lprocfs_alloc_stats(num_stats, 0);
1535 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1536 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1537 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
1538 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1539 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1540 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1541 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1542 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1543 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1544 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1545 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1546 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1547 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1548 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1549 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1550 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1551 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1552 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1553 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1554 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1555 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1556 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1557 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1558 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1559 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1560 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1561 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1562 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1563 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1564 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1565 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1566 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1568 for (i = num_private_stats; i < num_stats; i++) {
1569 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1570 CERROR("Missing md_stat initializer md_op "
1571 "operation at offset %d. Aborting.\n",
1572 i - num_private_stats);
1576 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1578 lprocfs_free_stats(&stats);
1580 obd->md_stats = stats;
1581 obd->md_cntr_base = num_private_stats;
1586 void lprocfs_free_md_stats(struct obd_device *obd)
1588 struct lprocfs_stats *stats = obd->md_stats;
1590 if (stats != NULL) {
1591 obd->md_stats = NULL;
1592 obd->md_cntr_base = 0;
1593 lprocfs_free_stats(&stats);
1597 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1599 lprocfs_counter_init(ldlm_stats,
1600 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1601 0, "ldlm_enqueue", "reqs");
1602 lprocfs_counter_init(ldlm_stats,
1603 LDLM_CONVERT - LDLM_FIRST_OPC,
1604 0, "ldlm_convert", "reqs");
1605 lprocfs_counter_init(ldlm_stats,
1606 LDLM_CANCEL - LDLM_FIRST_OPC,
1607 0, "ldlm_cancel", "reqs");
1608 lprocfs_counter_init(ldlm_stats,
1609 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1610 0, "ldlm_bl_callback", "reqs");
1611 lprocfs_counter_init(ldlm_stats,
1612 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1613 0, "ldlm_cp_callback", "reqs");
1614 lprocfs_counter_init(ldlm_stats,
1615 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1616 0, "ldlm_gl_callback", "reqs");
1619 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1620 int *eof, void *data)
1622 struct obd_export *exp = data;
1623 LASSERT(exp != NULL);
1625 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1628 struct exp_uuid_cb_data {
1636 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1637 int count, int *eof, int *len)
1639 cb_data->page = page;
1640 cb_data->count = count;
1645 void lprocfs_exp_print_uuid(void *obj, void *cb_data)
1647 struct obd_export *exp = (struct obd_export *)obj;
1648 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1650 if (exp->exp_nid_stats)
1651 *data->len += snprintf((data->page + *data->len),
1652 data->count, "%s\n",
1653 obd_uuid2str(&exp->exp_client_uuid));
1656 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1657 int *eof, void *data)
1659 struct nid_stat *stats = (struct nid_stat *)data;
1660 struct exp_uuid_cb_data cb_data;
1661 struct obd_device *obd = stats->nid_obd;
1666 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1667 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1668 lprocfs_exp_print_uuid, &cb_data);
1669 return (*cb_data.len);
1672 void lprocfs_exp_print_hash(void *obj, void *cb_data)
1674 struct exp_uuid_cb_data *data = cb_data;
1675 struct obd_export *exp = obj;
1678 hs = exp->exp_lock_hash;
1681 *data->len += cfs_hash_debug_header(data->page,
1684 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1689 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1690 int *eof, void *data)
1692 struct nid_stat *stats = (struct nid_stat *)data;
1693 struct exp_uuid_cb_data cb_data;
1694 struct obd_device *obd = stats->nid_obd;
1699 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1701 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1702 lprocfs_exp_print_hash, &cb_data);
1703 return (*cb_data.len);
1706 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1707 int count, int *eof, void *data)
1710 return snprintf(page, count, "%s\n",
1711 "Write into this file to clear all nid stats and "
1712 "stale nid entries");
1714 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1716 int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1718 struct nid_stat *stat = obj;
1721 /* object has only hash + iterate_all references.
1722 * add/delete blocked by hash bucket lock */
1723 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
1724 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 2) {
1725 cfs_spin_lock(&stat->nid_obd->obd_nid_lock);
1726 cfs_list_move(&stat->nid_list, data);
1727 cfs_spin_unlock(&stat->nid_obd->obd_nid_lock);
1730 /* we has reference to object - only clear data*/
1731 if (stat->nid_stats)
1732 lprocfs_clear_stats(stat->nid_stats);
1734 if (stat->nid_brw_stats) {
1735 for (i = 0; i < BRW_LAST; i++)
1736 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
1741 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1742 unsigned long count, void *data)
1744 struct obd_device *obd = (struct obd_device *)data;
1745 struct nid_stat *client_stat;
1746 CFS_LIST_HEAD(free_list);
1748 cfs_hash_cond_del(obd->obd_nid_stats_hash,
1749 lprocfs_nid_stats_clear_write_cb, &free_list);
1751 while (!cfs_list_empty(&free_list)) {
1752 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
1754 cfs_list_del_init(&client_stat->nid_list);
1755 lprocfs_free_client_stats(client_stat);
1760 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1762 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1764 struct nid_stat *new_stat, *old_stat;
1765 struct obd_device *obd = NULL;
1766 cfs_proc_dir_entry_t *entry;
1767 char *buffer = NULL;
1773 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1774 !exp->exp_obd->obd_nid_stats_hash)
1777 /* not test against zero because eric say:
1778 * You may only test nid against another nid, or LNET_NID_ANY.
1779 * Anything else is nonsense.*/
1780 if (!nid || *nid == LNET_NID_ANY)
1785 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
1787 OBD_ALLOC_PTR(new_stat);
1788 if (new_stat == NULL)
1791 new_stat->nid = *nid;
1792 new_stat->nid_obd = exp->exp_obd;
1793 cfs_atomic_set(&new_stat->nid_exp_ref_count, 0);
1795 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
1796 nid, &new_stat->nid_hash);
1797 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
1798 old_stat, libcfs_nid2str(*nid),
1799 cfs_atomic_read(&new_stat->nid_exp_ref_count));
1801 /* Return -EALREADY here so that we know that the /proc
1802 * entry already has been created */
1803 if (old_stat != new_stat) {
1804 cfs_spin_lock(&obd->obd_nid_lock);
1805 if (exp->exp_nid_stats != old_stat) {
1806 if (exp->exp_nid_stats)
1807 nidstat_putref(exp->exp_nid_stats);
1808 exp->exp_nid_stats = old_stat;
1810 /* cfs_hash_findadd_unique() has added
1811 * old_stat's refcount */
1812 nidstat_putref(old_stat);
1815 cfs_spin_unlock(&obd->obd_nid_lock);
1817 GOTO(destroy_new, rc = -EALREADY);
1819 /* not found - create */
1820 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
1822 GOTO(destroy_new, rc = -ENOMEM);
1824 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
1825 new_stat->nid_proc = lprocfs_register(buffer,
1826 obd->obd_proc_exports_entry,
1828 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
1830 if (new_stat->nid_proc == NULL) {
1831 CERROR("Error making export directory for nid %s\n",
1832 libcfs_nid2str(*nid));
1833 GOTO(destroy_new_ns, rc = -ENOMEM);
1836 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
1837 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
1838 if (IS_ERR(entry)) {
1839 CWARN("Error adding the NID stats file\n");
1840 rc = PTR_ERR(entry);
1841 GOTO(destroy_new_ns, rc);
1844 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
1845 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
1846 if (IS_ERR(entry)) {
1847 CWARN("Error adding the hash file\n");
1848 rc = PTR_ERR(entry);
1849 GOTO(destroy_new_ns, rc);
1852 if (exp->exp_nid_stats)
1853 nidstat_putref(exp->exp_nid_stats);
1854 nidstat_getref(new_stat);
1855 exp->exp_nid_stats = new_stat;
1857 /* protect competitive add to list, not need locking on destroy */
1858 cfs_spin_lock(&obd->obd_nid_lock);
1859 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
1860 cfs_spin_unlock(&obd->obd_nid_lock);
1865 if (new_stat->nid_proc != NULL)
1866 lprocfs_remove(&new_stat->nid_proc);
1867 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
1870 OBD_FREE_PTR(new_stat);
1874 int lprocfs_exp_cleanup(struct obd_export *exp)
1876 struct nid_stat *stat = exp->exp_nid_stats;
1878 if(!stat || !exp->exp_obd)
1881 nidstat_putref(exp->exp_nid_stats);
1882 exp->exp_nid_stats = NULL;
1887 int lprocfs_write_helper(const char *buffer, unsigned long count,
1890 return lprocfs_write_frac_helper(buffer, count, val, 1);
1893 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
1896 char kernbuf[20], *end, *pbuf;
1898 if (count > (sizeof(kernbuf) - 1))
1901 if (cfs_copy_from_user(kernbuf, buffer, count))
1904 kernbuf[count] = '\0';
1911 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1915 if (end != NULL && *end == '.') {
1916 int temp_val, pow = 1;
1920 if (strlen(pbuf) > 5)
1921 pbuf[5] = '\0'; /*only allow 5bits fractional*/
1923 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1926 for (i = 0; i < (end - pbuf); i++)
1929 *val += temp_val / pow;
1935 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
1938 long decimal_val, frac_val;
1944 decimal_val = val / mult;
1945 prtn = snprintf(buffer, count, "%ld", decimal_val);
1946 frac_val = val % mult;
1948 if (prtn < (count - 4) && frac_val > 0) {
1950 int i, temp_mult = 1, frac_bits = 0;
1952 temp_frac = frac_val * 10;
1953 buffer[prtn++] = '.';
1954 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
1955 /* only reserved 2 bits fraction */
1956 buffer[prtn++] ='0';
1961 * Need to think these cases :
1962 * 1. #echo x.00 > /proc/xxx output result : x
1963 * 2. #echo x.0x > /proc/xxx output result : x.0x
1964 * 3. #echo x.x0 > /proc/xxx output result : x.x
1965 * 4. #echo x.xx > /proc/xxx output result : x.xx
1966 * Only reserved 2 bits fraction.
1968 for (i = 0; i < (5 - prtn); i++)
1971 frac_bits = min((int)count - prtn, 3 - frac_bits);
1972 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
1973 frac_val * temp_mult / mult);
1976 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
1978 if (buffer[prtn] == '.') {
1985 buffer[prtn++] ='\n';
1989 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
1991 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
1994 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
1995 __u64 *val, int mult)
1997 char kernbuf[22], *end, *pbuf;
1998 __u64 whole, frac = 0, units;
1999 unsigned frac_d = 1;
2001 if (count > (sizeof(kernbuf) - 1))
2004 if (cfs_copy_from_user(kernbuf, buffer, count))
2007 kernbuf[count] = '\0';
2014 whole = simple_strtoull(pbuf, &end, 10);
2018 if (end != NULL && *end == '.') {
2022 /* need to limit frac_d to a __u32 */
2023 if (strlen(pbuf) > 10)
2026 frac = simple_strtoull(pbuf, &end, 10);
2027 /* count decimal places */
2028 for (i = 0; i < (end - pbuf); i++)
2045 /* Specified units override the multiplier */
2047 mult = mult < 0 ? -units : units;
2050 do_div(frac, frac_d);
2051 *val = whole * mult + frac;
2055 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent, char *name, mode_t mode,
2056 struct file_operations *seq_fops, void *data)
2058 struct proc_dir_entry *entry;
2061 entry = create_proc_entry(name, mode, parent);
2064 entry->proc_fops = seq_fops;
2069 EXPORT_SYMBOL(lprocfs_seq_create);
2071 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
2073 struct file_operations *seq_fops,
2076 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2077 mode, seq_fops, data));
2079 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2081 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2083 if (value >= OBD_HIST_MAX)
2084 value = OBD_HIST_MAX - 1;
2086 cfs_spin_lock(&oh->oh_lock);
2087 oh->oh_buckets[value]++;
2088 cfs_spin_unlock(&oh->oh_lock);
2090 EXPORT_SYMBOL(lprocfs_oh_tally);
2092 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2096 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2099 lprocfs_oh_tally(oh, val);
2101 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2103 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2105 unsigned long ret = 0;
2108 for (i = 0; i < OBD_HIST_MAX; i++)
2109 ret += oh->oh_buckets[i];
2112 EXPORT_SYMBOL(lprocfs_oh_sum);
2114 void lprocfs_oh_clear(struct obd_histogram *oh)
2116 cfs_spin_lock(&oh->oh_lock);
2117 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2118 cfs_spin_unlock(&oh->oh_lock);
2120 EXPORT_SYMBOL(lprocfs_oh_clear);
2122 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2123 int count, int *eof, void *data)
2125 struct obd_device *obd = data;
2131 c += cfs_hash_debug_header(page, count);
2132 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2133 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2134 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2138 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2140 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2141 int count, int *eof, void *data)
2143 struct obd_device *obd = data;
2146 LASSERT(obd != NULL);
2147 LASSERT(count >= 0);
2149 /* Set start of user data returned to
2150 page + off since the user may have
2151 requested to read much smaller than
2152 what we need to read */
2153 *start = page + off;
2155 /* We know we are allocated a page here.
2156 Also we know that this function will
2157 not need to write more than a page
2158 so we can truncate at CFS_PAGE_SIZE. */
2159 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2161 /* Initialize the page */
2162 memset(page, 0, size);
2164 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2166 if (obd->obd_max_recoverable_clients == 0) {
2167 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2173 /* sampled unlocked, but really... */
2174 if (obd->obd_recovering == 0) {
2175 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2177 if (lprocfs_obd_snprintf(&page, size, &len,
2178 "recovery_start: %lu\n",
2179 obd->obd_recovery_start) <= 0)
2181 if (lprocfs_obd_snprintf(&page, size, &len,
2182 "recovery_duration: %lu\n",
2183 obd->obd_recovery_end -
2184 obd->obd_recovery_start) <= 0)
2186 /* Number of clients that have completed recovery */
2187 if (lprocfs_obd_snprintf(&page, size, &len,
2188 "completed_clients: %d/%d\n",
2189 obd->obd_max_recoverable_clients -
2190 obd->obd_stale_clients,
2191 obd->obd_max_recoverable_clients) <= 0)
2193 if (lprocfs_obd_snprintf(&page, size, &len,
2194 "replayed_requests: %d\n",
2195 obd->obd_replayed_requests) <= 0)
2197 if (lprocfs_obd_snprintf(&page, size, &len,
2198 "last_transno: "LPD64"\n",
2199 obd->obd_next_recovery_transno - 1)<=0)
2201 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2202 obd->obd_version_recov ? "ON" : "OFF")<=0)
2207 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2209 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2210 obd->obd_recovery_start) <= 0)
2212 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2213 cfs_time_current_sec() >= obd->obd_recovery_end ? 0 :
2214 obd->obd_recovery_end - cfs_time_current_sec()) <= 0)
2216 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2217 obd->obd_connected_clients,
2218 obd->obd_max_recoverable_clients) <= 0)
2220 /* Number of clients that have completed recovery */
2221 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2222 cfs_atomic_read(&obd->obd_req_replay_clients))
2225 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2226 cfs_atomic_read(&obd->obd_lock_replay_clients))
2229 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2230 obd->obd_connected_clients -
2231 cfs_atomic_read(&obd->obd_lock_replay_clients))
2234 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2235 obd->obd_stale_clients) <= 0)
2237 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2238 obd->obd_replayed_requests) <= 0)
2240 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2241 obd->obd_requests_queued_for_recovery) <= 0)
2244 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2245 obd->obd_next_recovery_transno) <= 0)
2251 return min(count, len - (int)off);
2253 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2255 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
2256 int count, int *eof, void *data)
2258 struct obd_device *obd = (struct obd_device *)data;
2259 LASSERT(obd != NULL);
2261 return snprintf(page, count, "%d\n",
2262 obd->obd_recovery_timeout);
2264 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
2266 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
2267 unsigned long count, void *data)
2269 struct obd_device *obd = (struct obd_device *)data;
2271 LASSERT(obd != NULL);
2273 rc = lprocfs_write_helper(buffer, count, &val);
2277 obd->obd_recovery_timeout = val;
2280 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
2282 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
2283 int count, int *eof, void *data)
2285 struct obd_device *obd = data;
2286 LASSERT(obd != NULL);
2288 return snprintf(page, count, "%lu\n", obd->obd_recovery_time_hard);
2290 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
2292 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
2293 unsigned long count, void *data)
2295 struct obd_device *obd = data;
2297 LASSERT(obd != NULL);
2299 rc = lprocfs_write_helper(buffer, count, &val);
2303 obd->obd_recovery_time_hard = val;
2306 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
2308 int lprocfs_obd_rd_mntdev(char *page, char **start, off_t off,
2309 int count, int *eof, void *data)
2311 struct obd_device *obd = (struct obd_device *)data;
2313 LASSERT(obd != NULL);
2314 LASSERT(obd->u.obt.obt_vfsmnt->mnt_devname);
2316 return snprintf(page, count, "%s\n",
2317 obd->u.obt.obt_vfsmnt->mnt_devname);
2319 EXPORT_SYMBOL(lprocfs_obd_rd_mntdev);
2321 EXPORT_SYMBOL(lprocfs_register);
2322 EXPORT_SYMBOL(lprocfs_srch);
2323 EXPORT_SYMBOL(lprocfs_remove);
2324 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
2325 EXPORT_SYMBOL(lprocfs_add_vars);
2326 EXPORT_SYMBOL(lprocfs_obd_setup);
2327 EXPORT_SYMBOL(lprocfs_obd_cleanup);
2328 EXPORT_SYMBOL(lprocfs_add_simple);
2329 EXPORT_SYMBOL(lprocfs_add_symlink);
2330 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
2331 EXPORT_SYMBOL(lprocfs_alloc_stats);
2332 EXPORT_SYMBOL(lprocfs_free_stats);
2333 EXPORT_SYMBOL(lprocfs_clear_stats);
2334 EXPORT_SYMBOL(lprocfs_register_stats);
2335 EXPORT_SYMBOL(lprocfs_init_ops_stats);
2336 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
2337 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
2338 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
2339 EXPORT_SYMBOL(lprocfs_free_obd_stats);
2340 EXPORT_SYMBOL(lprocfs_free_md_stats);
2341 EXPORT_SYMBOL(lprocfs_exp_setup);
2342 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2344 EXPORT_SYMBOL(lprocfs_rd_u64);
2345 EXPORT_SYMBOL(lprocfs_rd_atomic);
2346 EXPORT_SYMBOL(lprocfs_wr_atomic);
2347 EXPORT_SYMBOL(lprocfs_rd_uint);
2348 EXPORT_SYMBOL(lprocfs_wr_uint);
2349 EXPORT_SYMBOL(lprocfs_rd_uuid);
2350 EXPORT_SYMBOL(lprocfs_rd_name);
2351 EXPORT_SYMBOL(lprocfs_rd_fstype);
2352 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
2353 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
2354 EXPORT_SYMBOL(lprocfs_rd_num_exports);
2355 EXPORT_SYMBOL(lprocfs_rd_numrefs);
2356 EXPORT_SYMBOL(lprocfs_at_hist_helper);
2357 EXPORT_SYMBOL(lprocfs_rd_import);
2358 EXPORT_SYMBOL(lprocfs_rd_state);
2359 EXPORT_SYMBOL(lprocfs_rd_timeouts);
2360 EXPORT_SYMBOL(lprocfs_rd_blksize);
2361 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
2362 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
2363 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
2364 EXPORT_SYMBOL(lprocfs_rd_filestotal);
2365 EXPORT_SYMBOL(lprocfs_rd_filesfree);
2367 EXPORT_SYMBOL(lprocfs_write_helper);
2368 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2369 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2370 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2371 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2372 EXPORT_SYMBOL(lprocfs_stats_collect);