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, cfs_time_current_64() - CFS_HZ,
528 rc = snprintf(page, count, "%u\n", osfs.os_bsize);
533 int lprocfs_rd_kbytestotal(char *page, char **start, off_t off, int count,
534 int *eof, void *data)
536 struct obd_statfs osfs;
537 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - CFS_HZ,
540 __u32 blk_size = osfs.os_bsize >> 10;
541 __u64 result = osfs.os_blocks;
543 while (blk_size >>= 1)
547 rc = snprintf(page, count, LPU64"\n", result);
552 int lprocfs_rd_kbytesfree(char *page, char **start, off_t off, int count,
553 int *eof, void *data)
555 struct obd_statfs osfs;
556 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - CFS_HZ,
559 __u32 blk_size = osfs.os_bsize >> 10;
560 __u64 result = osfs.os_bfree;
562 while (blk_size >>= 1)
566 rc = snprintf(page, count, LPU64"\n", result);
571 int lprocfs_rd_kbytesavail(char *page, char **start, off_t off, int count,
572 int *eof, void *data)
574 struct obd_statfs osfs;
575 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - CFS_HZ,
578 __u32 blk_size = osfs.os_bsize >> 10;
579 __u64 result = osfs.os_bavail;
581 while (blk_size >>= 1)
585 rc = snprintf(page, count, LPU64"\n", result);
590 int lprocfs_rd_filestotal(char *page, char **start, off_t off, int count,
591 int *eof, void *data)
593 struct obd_statfs osfs;
594 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - CFS_HZ,
598 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
604 int lprocfs_rd_filesfree(char *page, char **start, off_t off, int count,
605 int *eof, void *data)
607 struct obd_statfs osfs;
608 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - CFS_HZ,
612 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
617 int lprocfs_rd_server_uuid(char *page, char **start, off_t off, int count,
618 int *eof, void *data)
620 struct obd_device *obd = data;
621 struct obd_import *imp;
622 char *imp_state_name = NULL;
625 LASSERT(obd != NULL);
626 LPROCFS_CLIMP_CHECK(obd);
627 imp = obd->u.cli.cl_import;
628 imp_state_name = ptlrpc_import_state_name(imp->imp_state);
630 rc = snprintf(page, count, "%s\t%s%s\n",
631 obd2cli_tgt(obd), imp_state_name,
632 imp->imp_deactive ? "\tDEACTIVATED" : "");
634 LPROCFS_CLIMP_EXIT(obd);
638 int lprocfs_rd_conn_uuid(char *page, char **start, off_t off, int count,
639 int *eof, void *data)
641 struct obd_device *obd = data;
642 struct ptlrpc_connection *conn;
645 LASSERT(obd != NULL);
647 LPROCFS_CLIMP_CHECK(obd);
648 conn = obd->u.cli.cl_import->imp_connection;
650 if (conn && obd->u.cli.cl_import) {
651 rc = snprintf(page, count, "%s\n",
652 conn->c_remote_uuid.uuid);
654 rc = snprintf(page, count, "%s\n", "<none>");
657 LPROCFS_CLIMP_EXIT(obd);
661 /** add up per-cpu counters */
662 void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
663 struct lprocfs_counter *cnt)
665 unsigned int num_cpu;
666 struct lprocfs_counter t;
667 struct lprocfs_counter *percpu_cntr;
670 memset(cnt, 0, sizeof(*cnt));
673 /* set count to 1 to avoid divide-by-zero errs in callers */
678 cnt->lc_min = LC_MIN_INIT;
680 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
683 num_cpu = cfs_num_possible_cpus();
685 for (i = 0; i < num_cpu; i++) {
686 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[idx];
689 centry = cfs_atomic_read(&percpu_cntr-> \
691 t.lc_count = percpu_cntr->lc_count;
692 t.lc_sum = percpu_cntr->lc_sum;
693 t.lc_min = percpu_cntr->lc_min;
694 t.lc_max = percpu_cntr->lc_max;
695 t.lc_sumsquare = percpu_cntr->lc_sumsquare;
696 } while (centry != cfs_atomic_read(&percpu_cntr->lc_cntl. \
698 centry != cfs_atomic_read(&percpu_cntr->lc_cntl. \
700 cnt->lc_count += t.lc_count;
701 cnt->lc_sum += t.lc_sum;
702 if (t.lc_min < cnt->lc_min)
703 cnt->lc_min = t.lc_min;
704 if (t.lc_max > cnt->lc_max)
705 cnt->lc_max = t.lc_max;
706 cnt->lc_sumsquare += t.lc_sumsquare;
709 cnt->lc_units = stats->ls_percpu[0]->lp_cntr[idx].lc_units;
713 * Append a space separated list of current set flags to str.
715 #define flag2str(flag) \
716 if (imp->imp_##flag && max - len > 0) \
717 len += snprintf(str + len, max - len, "%s" #flag, len ? ", " : "");
718 static int obd_import_flags2str(struct obd_import *imp, char *str, int max)
722 if (imp->imp_obd->obd_no_recov)
723 len += snprintf(str, max - len, "no_recov");
727 flag2str(replayable);
733 static const char *obd_connect_names[] = {
747 "join_file(obsolete)",
751 "remote_client_by_force",
760 "mds_mds_connection",
763 "alt_checksum_algorithm",
775 static int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
780 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
782 ret += snprintf(page + ret, count - ret, "%s%s",
783 ret ? sep : "", obd_connect_names[i]);
785 if (flags & ~(mask - 1))
786 ret += snprintf(page + ret, count - ret,
787 "%sunknown flags "LPX64,
788 ret ? sep : "", flags & ~(mask - 1));
792 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
793 int *eof, void *data)
795 struct lprocfs_counter ret;
796 struct obd_device *obd = (struct obd_device *)data;
797 struct obd_import *imp;
798 struct obd_import_conn *conn;
801 LASSERT(obd != NULL);
802 LPROCFS_CLIMP_CHECK(obd);
803 imp = obd->u.cli.cl_import;
806 i = snprintf(page, count,
814 ptlrpc_import_state_name(imp->imp_state));
815 i += obd_connect_flags2str(page + i, count - i,
816 imp->imp_connect_data.ocd_connect_flags,
818 i += snprintf(page + i, count - i,
821 i += obd_import_flags2str(imp, page + i, count - i);
823 i += snprintf(page + i, count - i,
826 " failover_nids: [");
827 cfs_spin_lock(&imp->imp_lock);
829 cfs_list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
830 i += snprintf(page + i, count - i, "%s%s", j ? ", " : "",
831 libcfs_nid2str(conn->oic_conn->c_peer.nid));
834 cfs_spin_unlock(&imp->imp_lock);
835 i += snprintf(page + i, count - i,
837 " current_connection: %s\n"
838 " connection_attempts: %u\n"
840 " in-progress_invalidations: %u\n",
841 libcfs_nid2str(imp->imp_connection->c_peer.nid),
844 cfs_atomic_read(&imp->imp_inval_count));
846 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
847 if (ret.lc_count != 0)
848 do_div(ret.lc_sum, ret.lc_count);
851 i += snprintf(page + i, count - i,
854 " unregistering: %u\n"
856 " avg_waittime: "LPU64" %s\n",
857 cfs_atomic_read(&imp->imp_inflight),
858 cfs_atomic_read(&imp->imp_unregistering),
859 cfs_atomic_read(&imp->imp_timeouts),
860 ret.lc_sum, ret.lc_units);
863 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
864 if (imp->imp_at.iat_portal[j] == 0)
866 k = max_t(unsigned int, k,
867 at_get(&imp->imp_at.iat_service_estimate[j]));
869 i += snprintf(page + i, count - i,
870 " service_estimates:\n"
871 " services: %u sec\n"
872 " network: %u sec\n",
874 at_get(&imp->imp_at.iat_net_latency));
876 i += snprintf(page + i, count - i,
878 " last_replay: "LPU64"\n"
879 " peer_committed: "LPU64"\n"
880 " last_checked: "LPU64"\n",
881 imp->imp_last_replay_transno,
882 imp->imp_peer_committed_transno,
883 imp->imp_last_transno_checked);
886 for (rw = 0; rw <= 1; rw++) {
887 lprocfs_stats_collect(obd->obd_svc_stats,
888 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
890 if (ret.lc_sum > 0 && ret.lc_count > 0) {
891 do_div(ret.lc_sum, ret.lc_count);
892 i += snprintf(page + i, count - i,
893 " %s_data_averages:\n"
894 " bytes_per_rpc: "LPU64"\n",
895 rw ? "write" : "read",
899 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
900 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
901 if (ret.lc_sum > 0 && ret.lc_count != 0) {
902 do_div(ret.lc_sum, ret.lc_count);
903 i += snprintf(page + i, count - i,
904 " %s_per_rpc: "LPU64"\n",
905 ret.lc_units, ret.lc_sum);
908 i += snprintf(page + i, count - i,
909 " MB_per_sec: %u.%.02u\n",
910 k / j, (100 * k / j) % 100);
914 LPROCFS_CLIMP_EXIT(obd);
918 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
919 int *eof, void *data)
921 struct obd_device *obd = (struct obd_device *)data;
922 struct obd_import *imp;
925 LASSERT(obd != NULL);
926 LPROCFS_CLIMP_CHECK(obd);
927 imp = obd->u.cli.cl_import;
930 i = snprintf(page, count, "current_state: %s\n",
931 ptlrpc_import_state_name(imp->imp_state));
932 i += snprintf(page + i, count - i,
934 k = imp->imp_state_hist_idx;
935 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
936 struct import_state_hist *ish =
937 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
938 if (ish->ish_state == 0)
940 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
942 ptlrpc_import_state_name(ish->ish_state));
945 LPROCFS_CLIMP_EXIT(obd);
949 int lprocfs_at_hist_helper(char *page, int count, int rc,
950 struct adaptive_timeout *at)
953 for (i = 0; i < AT_BINS; i++)
954 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
955 rc += snprintf(page + rc, count - rc, "\n");
959 /* See also ptlrpc_lprocfs_rd_timeouts */
960 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
961 int *eof, void *data)
963 struct obd_device *obd = (struct obd_device *)data;
964 struct obd_import *imp;
965 unsigned int cur, worst;
970 LASSERT(obd != NULL);
971 LPROCFS_CLIMP_CHECK(obd);
972 imp = obd->u.cli.cl_import;
975 now = cfs_time_current_sec();
977 /* Some network health info for kicks */
978 s2dhms(&ts, now - imp->imp_last_reply_time);
979 rc += snprintf(page + rc, count - rc,
980 "%-10s : %ld, "DHMS_FMT" ago\n",
981 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
983 cur = at_get(&imp->imp_at.iat_net_latency);
984 worst = imp->imp_at.iat_net_latency.at_worst_ever;
985 worstt = imp->imp_at.iat_net_latency.at_worst_time;
986 s2dhms(&ts, now - worstt);
987 rc += snprintf(page + rc, count - rc,
988 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
989 "network", cur, worst, worstt, DHMS_VARS(&ts));
990 rc = lprocfs_at_hist_helper(page, count, rc,
991 &imp->imp_at.iat_net_latency);
993 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
994 if (imp->imp_at.iat_portal[i] == 0)
996 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
997 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
998 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
999 s2dhms(&ts, now - worstt);
1000 rc += snprintf(page + rc, count - rc,
1001 "portal %-2d : cur %3u worst %3u (at %ld, "
1002 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
1003 cur, worst, worstt, DHMS_VARS(&ts));
1004 rc = lprocfs_at_hist_helper(page, count, rc,
1005 &imp->imp_at.iat_service_estimate[i]);
1008 LPROCFS_CLIMP_EXIT(obd);
1012 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1013 int count, int *eof, void *data)
1015 struct obd_device *obd = data;
1019 LPROCFS_CLIMP_CHECK(obd);
1020 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1021 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1022 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1023 ret += snprintf(page + ret, count - ret, "\n");
1024 LPROCFS_CLIMP_EXIT(obd);
1027 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1029 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1030 int *eof, void *data)
1032 struct obd_device *obd = data;
1034 LASSERT(obd != NULL);
1036 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1039 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1040 int *eof, void *data)
1042 struct obd_type *class = (struct obd_type*) data;
1044 LASSERT(class != NULL);
1046 return snprintf(page, count, "%d\n", class->typ_refcnt);
1049 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1053 LASSERT(obd != NULL);
1054 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1055 LASSERT(obd->obd_type->typ_procroot != NULL);
1057 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1058 obd->obd_type->typ_procroot,
1060 if (IS_ERR(obd->obd_proc_entry)) {
1061 rc = PTR_ERR(obd->obd_proc_entry);
1062 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1063 obd->obd_proc_entry = NULL;
1068 int lprocfs_obd_cleanup(struct obd_device *obd)
1072 if (obd->obd_proc_exports_entry) {
1073 /* Should be no exports left */
1074 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1075 lprocfs_remove(&obd->obd_proc_exports_entry);
1076 obd->obd_proc_exports_entry = NULL;
1078 if (obd->obd_proc_entry) {
1079 lprocfs_remove(&obd->obd_proc_entry);
1080 obd->obd_proc_entry = NULL;
1085 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1087 CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
1088 client_stat->nid_proc, client_stat->nid_stats,
1089 client_stat->nid_brw_stats);
1091 LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
1093 cfs_atomic_read(&client_stat->nid_exp_ref_count));
1095 cfs_hlist_del_init(&client_stat->nid_hash);
1097 if (client_stat->nid_proc)
1098 lprocfs_remove(&client_stat->nid_proc);
1100 if (client_stat->nid_stats)
1101 lprocfs_free_stats(&client_stat->nid_stats);
1103 if (client_stat->nid_brw_stats)
1104 OBD_FREE_PTR(client_stat->nid_brw_stats);
1106 if (client_stat->nid_ldlm_stats)
1107 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1109 OBD_FREE_PTR(client_stat);
1114 void lprocfs_free_per_client_stats(struct obd_device *obd)
1116 struct nid_stat *stat;
1119 /* we need extra list - because hash_exit called to early */
1120 /* not need locking because all clients is died */
1121 while(!cfs_list_empty(&obd->obd_nid_stats)) {
1122 stat = cfs_list_entry(obd->obd_nid_stats.next,
1123 struct nid_stat, nid_list);
1124 cfs_list_del_init(&stat->nid_list);
1125 lprocfs_free_client_stats(stat);
1131 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1132 enum lprocfs_stats_flags flags)
1134 struct lprocfs_stats *stats;
1135 unsigned int percpusize;
1137 unsigned int num_cpu;
1142 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1145 num_cpu = cfs_num_possible_cpus();
1147 OBD_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
1151 if (flags & LPROCFS_STATS_FLAG_NOPERCPU) {
1152 stats->ls_flags = flags;
1153 cfs_spin_lock_init(&stats->ls_lock);
1154 /* Use this lock only if there are no percpu areas */
1156 stats->ls_flags = 0;
1159 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
1161 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1163 for (i = 0; i < num_cpu; i++) {
1164 OBD_ALLOC(stats->ls_percpu[i], percpusize);
1165 if (stats->ls_percpu[i] == NULL) {
1166 for (j = 0; j < i; j++) {
1167 OBD_FREE(stats->ls_percpu[j], percpusize);
1168 stats->ls_percpu[j] = NULL;
1173 if (stats->ls_percpu[0] == NULL) {
1174 OBD_FREE(stats, offsetof(typeof(*stats),
1175 ls_percpu[num_cpu]));
1179 stats->ls_num = num;
1183 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1185 struct lprocfs_stats *stats = *statsh;
1186 unsigned int num_cpu;
1187 unsigned int percpusize;
1190 if (stats == NULL || stats->ls_num == 0)
1194 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1197 num_cpu = cfs_num_possible_cpus();
1199 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
1201 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1202 for (i = 0; i < num_cpu; i++)
1203 OBD_FREE(stats->ls_percpu[i], percpusize);
1204 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
1207 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1209 struct lprocfs_counter *percpu_cntr;
1211 unsigned int num_cpu;
1213 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1215 for (i = 0; i < num_cpu; i++) {
1216 for (j = 0; j < stats->ls_num; j++) {
1217 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
1218 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_entry);
1219 percpu_cntr->lc_count = 0;
1220 percpu_cntr->lc_sum = 0;
1221 percpu_cntr->lc_min = LC_MIN_INIT;
1222 percpu_cntr->lc_max = 0;
1223 percpu_cntr->lc_sumsquare = 0;
1224 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_exit);
1228 lprocfs_stats_unlock(stats);
1231 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1232 size_t len, loff_t *off)
1234 struct seq_file *seq = file->private_data;
1235 struct lprocfs_stats *stats = seq->private;
1237 lprocfs_clear_stats(stats);
1242 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1244 struct lprocfs_stats *stats = p->private;
1245 /* return 1st cpu location */
1246 return (*pos >= stats->ls_num) ? NULL :
1247 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1250 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1254 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1256 struct lprocfs_stats *stats = p->private;
1258 return (*pos >= stats->ls_num) ? NULL :
1259 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1262 /* seq file export of one lprocfs counter */
1263 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1265 struct lprocfs_stats *stats = p->private;
1266 struct lprocfs_counter *cntr = v;
1267 struct lprocfs_counter ret;
1270 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
1272 cfs_gettimeofday(&now);
1273 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1274 "snapshot_time", now.tv_sec, now.tv_usec);
1278 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
1280 lprocfs_stats_collect(stats, idx, &ret);
1282 if (ret.lc_count == 0)
1285 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", cntr->lc_name,
1286 ret.lc_count, cntr->lc_units);
1291 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
1292 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1293 ret.lc_min, ret.lc_max, ret.lc_sum);
1296 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
1297 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1301 rc = seq_printf(p, "\n");
1303 return (rc < 0) ? rc : 0;
1306 struct seq_operations lprocfs_stats_seq_sops = {
1307 start: lprocfs_stats_seq_start,
1308 stop: lprocfs_stats_seq_stop,
1309 next: lprocfs_stats_seq_next,
1310 show: lprocfs_stats_seq_show,
1313 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1315 struct proc_dir_entry *dp = PDE(inode);
1316 struct seq_file *seq;
1319 if (LPROCFS_ENTRY_AND_CHECK(dp))
1322 rc = seq_open(file, &lprocfs_stats_seq_sops);
1327 seq = file->private_data;
1328 seq->private = dp->data;
1332 struct file_operations lprocfs_stats_seq_fops = {
1333 .owner = THIS_MODULE,
1334 .open = lprocfs_stats_seq_open,
1336 .write = lprocfs_stats_seq_write,
1337 .llseek = seq_lseek,
1338 .release = lprocfs_seq_release,
1341 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1342 struct lprocfs_stats *stats)
1344 struct proc_dir_entry *entry;
1345 LASSERT(root != NULL);
1347 entry = create_proc_entry(name, 0644, root);
1350 entry->proc_fops = &lprocfs_stats_seq_fops;
1351 entry->data = stats;
1355 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1356 unsigned conf, const char *name, const char *units)
1358 struct lprocfs_counter *c;
1360 unsigned int num_cpu;
1362 LASSERT(stats != NULL);
1364 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1366 for (i = 0; i < num_cpu; i++) {
1367 c = &(stats->ls_percpu[i]->lp_cntr[index]);
1368 c->lc_config = conf;
1371 c->lc_min = LC_MIN_INIT;
1374 c->lc_units = units;
1377 lprocfs_stats_unlock(stats);
1379 EXPORT_SYMBOL(lprocfs_counter_init);
1381 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1383 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1384 LASSERT(coffset < stats->ls_num); \
1385 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1388 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1390 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1391 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1392 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1393 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1394 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1395 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1396 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1397 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1398 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1399 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1400 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1401 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1402 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1403 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1404 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1405 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1406 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1407 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1408 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
1409 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1410 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1411 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1412 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1413 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1414 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1415 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1416 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1417 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1418 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1419 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1420 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1421 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1422 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1423 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1424 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1425 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1426 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1427 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1428 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1429 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1430 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1431 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1432 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1433 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1434 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
1435 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1436 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1437 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1438 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1439 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1440 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1441 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1442 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1443 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1444 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1445 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1446 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1447 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1448 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1449 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1450 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1451 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quota_adjust_qunit);
1452 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1453 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1454 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1455 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1456 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1457 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1458 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1461 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1463 struct lprocfs_stats *stats;
1464 unsigned int num_stats;
1467 LASSERT(obd->obd_stats == NULL);
1468 LASSERT(obd->obd_proc_entry != NULL);
1469 LASSERT(obd->obd_cntr_base == 0);
1471 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1472 num_private_stats - 1 /* o_owner */;
1473 stats = lprocfs_alloc_stats(num_stats, 0);
1477 lprocfs_init_ops_stats(num_private_stats, stats);
1479 for (i = num_private_stats; i < num_stats; i++) {
1480 /* If this LBUGs, it is likely that an obd
1481 * operation was added to struct obd_ops in
1482 * <obd.h>, and that the corresponding line item
1483 * LPROCFS_OBD_OP_INIT(.., .., opname)
1484 * is missing from the list above. */
1485 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1486 "Missing obd_stat initializer obd_op "
1487 "operation at offset %d.\n", i - num_private_stats);
1489 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1491 lprocfs_free_stats(&stats);
1493 obd->obd_stats = stats;
1494 obd->obd_cntr_base = num_private_stats;
1499 void lprocfs_free_obd_stats(struct obd_device *obd)
1502 lprocfs_free_stats(&obd->obd_stats);
1505 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1507 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1508 LASSERT(coffset < stats->ls_num); \
1509 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1512 int lprocfs_alloc_md_stats(struct obd_device *obd,
1513 unsigned num_private_stats)
1515 struct lprocfs_stats *stats;
1516 unsigned int num_stats;
1519 LASSERT(obd->md_stats == NULL);
1520 LASSERT(obd->obd_proc_entry != NULL);
1521 LASSERT(obd->md_cntr_base == 0);
1523 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1525 stats = lprocfs_alloc_stats(num_stats, 0);
1529 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1530 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1531 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
1532 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1533 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1534 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1535 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1536 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1537 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1538 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1539 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1540 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1541 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1542 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1543 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1544 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1545 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1546 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1547 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1548 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1549 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1550 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1551 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1552 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1553 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1554 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1555 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1556 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1557 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1558 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1559 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1560 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1562 for (i = num_private_stats; i < num_stats; i++) {
1563 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1564 CERROR("Missing md_stat initializer md_op "
1565 "operation at offset %d. Aborting.\n",
1566 i - num_private_stats);
1570 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1572 lprocfs_free_stats(&stats);
1574 obd->md_stats = stats;
1575 obd->md_cntr_base = num_private_stats;
1580 void lprocfs_free_md_stats(struct obd_device *obd)
1582 struct lprocfs_stats *stats = obd->md_stats;
1584 if (stats != NULL) {
1585 obd->md_stats = NULL;
1586 obd->md_cntr_base = 0;
1587 lprocfs_free_stats(&stats);
1591 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1593 lprocfs_counter_init(ldlm_stats,
1594 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1595 0, "ldlm_enqueue", "reqs");
1596 lprocfs_counter_init(ldlm_stats,
1597 LDLM_CONVERT - LDLM_FIRST_OPC,
1598 0, "ldlm_convert", "reqs");
1599 lprocfs_counter_init(ldlm_stats,
1600 LDLM_CANCEL - LDLM_FIRST_OPC,
1601 0, "ldlm_cancel", "reqs");
1602 lprocfs_counter_init(ldlm_stats,
1603 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1604 0, "ldlm_bl_callback", "reqs");
1605 lprocfs_counter_init(ldlm_stats,
1606 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1607 0, "ldlm_cp_callback", "reqs");
1608 lprocfs_counter_init(ldlm_stats,
1609 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1610 0, "ldlm_gl_callback", "reqs");
1613 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1614 int *eof, void *data)
1616 struct obd_export *exp = data;
1617 LASSERT(exp != NULL);
1619 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1622 struct exp_uuid_cb_data {
1630 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1631 int count, int *eof, int *len)
1633 cb_data->page = page;
1634 cb_data->count = count;
1639 void lprocfs_exp_print_uuid(void *obj, void *cb_data)
1641 struct obd_export *exp = (struct obd_export *)obj;
1642 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1644 if (exp->exp_nid_stats)
1645 *data->len += snprintf((data->page + *data->len),
1646 data->count, "%s\n",
1647 obd_uuid2str(&exp->exp_client_uuid));
1650 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1651 int *eof, void *data)
1653 struct nid_stat *stats = (struct nid_stat *)data;
1654 struct exp_uuid_cb_data cb_data;
1655 struct obd_device *obd = stats->nid_obd;
1660 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1661 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1662 lprocfs_exp_print_uuid, &cb_data);
1663 return (*cb_data.len);
1666 void lprocfs_exp_print_hash(void *obj, void *cb_data)
1668 struct exp_uuid_cb_data *data = cb_data;
1669 struct obd_export *exp = obj;
1672 hs = exp->exp_lock_hash;
1675 *data->len += cfs_hash_debug_header(data->page,
1678 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1683 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1684 int *eof, void *data)
1686 struct nid_stat *stats = (struct nid_stat *)data;
1687 struct exp_uuid_cb_data cb_data;
1688 struct obd_device *obd = stats->nid_obd;
1693 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1695 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1696 lprocfs_exp_print_hash, &cb_data);
1697 return (*cb_data.len);
1700 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1701 int count, int *eof, void *data)
1704 return snprintf(page, count, "%s\n",
1705 "Write into this file to clear all nid stats and "
1706 "stale nid entries");
1708 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1710 int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1712 struct nid_stat *stat = obj;
1715 /* object has only hash + iterate_all references.
1716 * add/delete blocked by hash bucket lock */
1717 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
1718 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 2) {
1719 cfs_spin_lock(&stat->nid_obd->obd_nid_lock);
1720 cfs_list_move(&stat->nid_list, data);
1721 cfs_spin_unlock(&stat->nid_obd->obd_nid_lock);
1724 /* we has reference to object - only clear data*/
1725 if (stat->nid_stats)
1726 lprocfs_clear_stats(stat->nid_stats);
1728 if (stat->nid_brw_stats) {
1729 for (i = 0; i < BRW_LAST; i++)
1730 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
1735 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1736 unsigned long count, void *data)
1738 struct obd_device *obd = (struct obd_device *)data;
1739 struct nid_stat *client_stat;
1740 CFS_LIST_HEAD(free_list);
1742 cfs_hash_cond_del(obd->obd_nid_stats_hash,
1743 lprocfs_nid_stats_clear_write_cb, &free_list);
1745 while (!cfs_list_empty(&free_list)) {
1746 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
1748 cfs_list_del_init(&client_stat->nid_list);
1749 lprocfs_free_client_stats(client_stat);
1754 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1756 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1758 struct nid_stat *new_stat, *old_stat;
1759 struct obd_device *obd = NULL;
1760 cfs_proc_dir_entry_t *entry;
1761 char *buffer = NULL;
1767 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1768 !exp->exp_obd->obd_nid_stats_hash)
1771 /* not test against zero because eric say:
1772 * You may only test nid against another nid, or LNET_NID_ANY.
1773 * Anything else is nonsense.*/
1774 if (!nid || *nid == LNET_NID_ANY)
1779 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
1781 OBD_ALLOC_PTR(new_stat);
1782 if (new_stat == NULL)
1785 new_stat->nid = *nid;
1786 new_stat->nid_obd = exp->exp_obd;
1787 cfs_atomic_set(&new_stat->nid_exp_ref_count, 0);
1789 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
1790 nid, &new_stat->nid_hash);
1791 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
1792 old_stat, libcfs_nid2str(*nid),
1793 cfs_atomic_read(&new_stat->nid_exp_ref_count));
1795 /* Return -EALREADY here so that we know that the /proc
1796 * entry already has been created */
1797 if (old_stat != new_stat) {
1798 cfs_spin_lock(&obd->obd_nid_lock);
1799 if (exp->exp_nid_stats != old_stat) {
1800 if (exp->exp_nid_stats)
1801 nidstat_putref(exp->exp_nid_stats);
1802 exp->exp_nid_stats = old_stat;
1804 /* cfs_hash_findadd_unique() has added
1805 * old_stat's refcount */
1806 nidstat_putref(old_stat);
1809 cfs_spin_unlock(&obd->obd_nid_lock);
1811 GOTO(destroy_new, rc = -EALREADY);
1813 /* not found - create */
1814 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
1816 GOTO(destroy_new, rc = -ENOMEM);
1818 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
1819 new_stat->nid_proc = lprocfs_register(buffer,
1820 obd->obd_proc_exports_entry,
1822 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
1824 if (new_stat->nid_proc == NULL) {
1825 CERROR("Error making export directory for nid %s\n",
1826 libcfs_nid2str(*nid));
1827 GOTO(destroy_new_ns, rc = -ENOMEM);
1830 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
1831 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
1832 if (IS_ERR(entry)) {
1833 CWARN("Error adding the NID stats file\n");
1834 rc = PTR_ERR(entry);
1835 GOTO(destroy_new_ns, rc);
1838 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
1839 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
1840 if (IS_ERR(entry)) {
1841 CWARN("Error adding the hash file\n");
1842 rc = PTR_ERR(entry);
1843 GOTO(destroy_new_ns, rc);
1846 if (exp->exp_nid_stats)
1847 nidstat_putref(exp->exp_nid_stats);
1848 nidstat_getref(new_stat);
1849 exp->exp_nid_stats = new_stat;
1851 /* protect competitive add to list, not need locking on destroy */
1852 cfs_spin_lock(&obd->obd_nid_lock);
1853 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
1854 cfs_spin_unlock(&obd->obd_nid_lock);
1859 if (new_stat->nid_proc != NULL)
1860 lprocfs_remove(&new_stat->nid_proc);
1861 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
1864 OBD_FREE_PTR(new_stat);
1868 int lprocfs_exp_cleanup(struct obd_export *exp)
1870 struct nid_stat *stat = exp->exp_nid_stats;
1872 if(!stat || !exp->exp_obd)
1875 nidstat_putref(exp->exp_nid_stats);
1876 exp->exp_nid_stats = NULL;
1881 int lprocfs_write_helper(const char *buffer, unsigned long count,
1884 return lprocfs_write_frac_helper(buffer, count, val, 1);
1887 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
1890 char kernbuf[20], *end, *pbuf;
1892 if (count > (sizeof(kernbuf) - 1))
1895 if (cfs_copy_from_user(kernbuf, buffer, count))
1898 kernbuf[count] = '\0';
1905 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1909 if (end != NULL && *end == '.') {
1910 int temp_val, pow = 1;
1914 if (strlen(pbuf) > 5)
1915 pbuf[5] = '\0'; /*only allow 5bits fractional*/
1917 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1920 for (i = 0; i < (end - pbuf); i++)
1923 *val += temp_val / pow;
1929 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
1932 long decimal_val, frac_val;
1938 decimal_val = val / mult;
1939 prtn = snprintf(buffer, count, "%ld", decimal_val);
1940 frac_val = val % mult;
1942 if (prtn < (count - 4) && frac_val > 0) {
1944 int i, temp_mult = 1, frac_bits = 0;
1946 temp_frac = frac_val * 10;
1947 buffer[prtn++] = '.';
1948 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
1949 /* only reserved 2 bits fraction */
1950 buffer[prtn++] ='0';
1955 * Need to think these cases :
1956 * 1. #echo x.00 > /proc/xxx output result : x
1957 * 2. #echo x.0x > /proc/xxx output result : x.0x
1958 * 3. #echo x.x0 > /proc/xxx output result : x.x
1959 * 4. #echo x.xx > /proc/xxx output result : x.xx
1960 * Only reserved 2 bits fraction.
1962 for (i = 0; i < (5 - prtn); i++)
1965 frac_bits = min((int)count - prtn, 3 - frac_bits);
1966 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
1967 frac_val * temp_mult / mult);
1970 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
1972 if (buffer[prtn] == '.') {
1979 buffer[prtn++] ='\n';
1983 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
1985 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
1988 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
1989 __u64 *val, int mult)
1991 char kernbuf[22], *end, *pbuf;
1992 __u64 whole, frac = 0, units;
1993 unsigned frac_d = 1;
1995 if (count > (sizeof(kernbuf) - 1))
1998 if (cfs_copy_from_user(kernbuf, buffer, count))
2001 kernbuf[count] = '\0';
2008 whole = simple_strtoull(pbuf, &end, 10);
2012 if (end != NULL && *end == '.') {
2016 /* need to limit frac_d to a __u32 */
2017 if (strlen(pbuf) > 10)
2020 frac = simple_strtoull(pbuf, &end, 10);
2021 /* count decimal places */
2022 for (i = 0; i < (end - pbuf); i++)
2039 /* Specified units override the multiplier */
2041 mult = mult < 0 ? -units : units;
2044 do_div(frac, frac_d);
2045 *val = whole * mult + frac;
2049 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent, char *name, mode_t mode,
2050 struct file_operations *seq_fops, void *data)
2052 struct proc_dir_entry *entry;
2055 entry = create_proc_entry(name, mode, parent);
2058 entry->proc_fops = seq_fops;
2063 EXPORT_SYMBOL(lprocfs_seq_create);
2065 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
2067 struct file_operations *seq_fops,
2070 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2071 mode, seq_fops, data));
2073 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2075 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2077 if (value >= OBD_HIST_MAX)
2078 value = OBD_HIST_MAX - 1;
2080 cfs_spin_lock(&oh->oh_lock);
2081 oh->oh_buckets[value]++;
2082 cfs_spin_unlock(&oh->oh_lock);
2084 EXPORT_SYMBOL(lprocfs_oh_tally);
2086 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2090 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2093 lprocfs_oh_tally(oh, val);
2095 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2097 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2099 unsigned long ret = 0;
2102 for (i = 0; i < OBD_HIST_MAX; i++)
2103 ret += oh->oh_buckets[i];
2106 EXPORT_SYMBOL(lprocfs_oh_sum);
2108 void lprocfs_oh_clear(struct obd_histogram *oh)
2110 cfs_spin_lock(&oh->oh_lock);
2111 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2112 cfs_spin_unlock(&oh->oh_lock);
2114 EXPORT_SYMBOL(lprocfs_oh_clear);
2116 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2117 int count, int *eof, void *data)
2119 struct obd_device *obd = data;
2125 c += cfs_hash_debug_header(page, count);
2126 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2127 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2128 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2132 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2134 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2135 int count, int *eof, void *data)
2137 struct obd_device *obd = data;
2140 LASSERT(obd != NULL);
2141 LASSERT(count >= 0);
2143 /* Set start of user data returned to
2144 page + off since the user may have
2145 requested to read much smaller than
2146 what we need to read */
2147 *start = page + off;
2149 /* We know we are allocated a page here.
2150 Also we know that this function will
2151 not need to write more than a page
2152 so we can truncate at CFS_PAGE_SIZE. */
2153 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2155 /* Initialize the page */
2156 memset(page, 0, size);
2158 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2160 if (obd->obd_max_recoverable_clients == 0) {
2161 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2167 /* sampled unlocked, but really... */
2168 if (obd->obd_recovering == 0) {
2169 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2171 if (lprocfs_obd_snprintf(&page, size, &len,
2172 "recovery_start: %lu\n",
2173 obd->obd_recovery_start) <= 0)
2175 if (lprocfs_obd_snprintf(&page, size, &len,
2176 "recovery_duration: %lu\n",
2177 obd->obd_recovery_end -
2178 obd->obd_recovery_start) <= 0)
2180 /* Number of clients that have completed recovery */
2181 if (lprocfs_obd_snprintf(&page, size, &len,
2182 "completed_clients: %d/%d\n",
2183 obd->obd_max_recoverable_clients -
2184 obd->obd_stale_clients,
2185 obd->obd_max_recoverable_clients) <= 0)
2187 if (lprocfs_obd_snprintf(&page, size, &len,
2188 "replayed_requests: %d\n",
2189 obd->obd_replayed_requests) <= 0)
2191 if (lprocfs_obd_snprintf(&page, size, &len,
2192 "last_transno: "LPD64"\n",
2193 obd->obd_next_recovery_transno - 1)<=0)
2195 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2196 obd->obd_version_recov ? "ON" : "OFF")<=0)
2201 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2203 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2204 obd->obd_recovery_start) <= 0)
2206 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2207 cfs_time_current_sec() >= obd->obd_recovery_end ? 0 :
2208 obd->obd_recovery_end - cfs_time_current_sec()) <= 0)
2210 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2211 obd->obd_connected_clients,
2212 obd->obd_max_recoverable_clients) <= 0)
2214 /* Number of clients that have completed recovery */
2215 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2216 cfs_atomic_read(&obd->obd_req_replay_clients))
2219 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2220 cfs_atomic_read(&obd->obd_lock_replay_clients))
2223 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2224 obd->obd_connected_clients -
2225 cfs_atomic_read(&obd->obd_lock_replay_clients))
2228 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2229 obd->obd_stale_clients) <= 0)
2231 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2232 obd->obd_replayed_requests) <= 0)
2234 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2235 obd->obd_requests_queued_for_recovery) <= 0)
2238 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2239 obd->obd_next_recovery_transno) <= 0)
2245 return min(count, len - (int)off);
2247 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2249 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
2250 int count, int *eof, void *data)
2252 struct obd_device *obd = (struct obd_device *)data;
2253 LASSERT(obd != NULL);
2255 return snprintf(page, count, "%d\n",
2256 obd->obd_recovery_timeout);
2258 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
2260 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
2261 unsigned long count, void *data)
2263 struct obd_device *obd = (struct obd_device *)data;
2265 LASSERT(obd != NULL);
2267 rc = lprocfs_write_helper(buffer, count, &val);
2271 obd->obd_recovery_timeout = val;
2274 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
2276 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
2277 int count, int *eof, void *data)
2279 struct obd_device *obd = data;
2280 LASSERT(obd != NULL);
2282 return snprintf(page, count, "%lu\n", obd->obd_recovery_time_hard);
2284 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
2286 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
2287 unsigned long count, void *data)
2289 struct obd_device *obd = data;
2291 LASSERT(obd != NULL);
2293 rc = lprocfs_write_helper(buffer, count, &val);
2297 obd->obd_recovery_time_hard = val;
2300 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
2302 EXPORT_SYMBOL(lprocfs_register);
2303 EXPORT_SYMBOL(lprocfs_srch);
2304 EXPORT_SYMBOL(lprocfs_remove);
2305 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
2306 EXPORT_SYMBOL(lprocfs_add_vars);
2307 EXPORT_SYMBOL(lprocfs_obd_setup);
2308 EXPORT_SYMBOL(lprocfs_obd_cleanup);
2309 EXPORT_SYMBOL(lprocfs_add_simple);
2310 EXPORT_SYMBOL(lprocfs_add_symlink);
2311 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
2312 EXPORT_SYMBOL(lprocfs_alloc_stats);
2313 EXPORT_SYMBOL(lprocfs_free_stats);
2314 EXPORT_SYMBOL(lprocfs_clear_stats);
2315 EXPORT_SYMBOL(lprocfs_register_stats);
2316 EXPORT_SYMBOL(lprocfs_init_ops_stats);
2317 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
2318 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
2319 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
2320 EXPORT_SYMBOL(lprocfs_free_obd_stats);
2321 EXPORT_SYMBOL(lprocfs_free_md_stats);
2322 EXPORT_SYMBOL(lprocfs_exp_setup);
2323 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2325 EXPORT_SYMBOL(lprocfs_rd_u64);
2326 EXPORT_SYMBOL(lprocfs_rd_atomic);
2327 EXPORT_SYMBOL(lprocfs_wr_atomic);
2328 EXPORT_SYMBOL(lprocfs_rd_uint);
2329 EXPORT_SYMBOL(lprocfs_wr_uint);
2330 EXPORT_SYMBOL(lprocfs_rd_uuid);
2331 EXPORT_SYMBOL(lprocfs_rd_name);
2332 EXPORT_SYMBOL(lprocfs_rd_fstype);
2333 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
2334 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
2335 EXPORT_SYMBOL(lprocfs_rd_num_exports);
2336 EXPORT_SYMBOL(lprocfs_rd_numrefs);
2337 EXPORT_SYMBOL(lprocfs_at_hist_helper);
2338 EXPORT_SYMBOL(lprocfs_rd_import);
2339 EXPORT_SYMBOL(lprocfs_rd_state);
2340 EXPORT_SYMBOL(lprocfs_rd_timeouts);
2341 EXPORT_SYMBOL(lprocfs_rd_blksize);
2342 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
2343 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
2344 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
2345 EXPORT_SYMBOL(lprocfs_rd_filestotal);
2346 EXPORT_SYMBOL(lprocfs_rd_filesfree);
2348 EXPORT_SYMBOL(lprocfs_write_helper);
2349 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2350 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2351 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2352 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2353 EXPORT_SYMBOL(lprocfs_stats_collect);