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 2008 Sun Microsystems, Inc. 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",
774 static int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
779 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
781 ret += snprintf(page + ret, count - ret, "%s%s",
782 ret ? sep : "", obd_connect_names[i]);
784 if (flags & ~(mask - 1))
785 ret += snprintf(page + ret, count - ret,
786 "%sunknown flags "LPX64,
787 ret ? sep : "", flags & ~(mask - 1));
791 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
792 int *eof, void *data)
794 struct lprocfs_counter ret;
795 struct obd_device *obd = (struct obd_device *)data;
796 struct obd_import *imp;
797 struct obd_import_conn *conn;
800 LASSERT(obd != NULL);
801 LPROCFS_CLIMP_CHECK(obd);
802 imp = obd->u.cli.cl_import;
805 i = snprintf(page, count,
813 ptlrpc_import_state_name(imp->imp_state));
814 i += obd_connect_flags2str(page + i, count - i,
815 imp->imp_connect_data.ocd_connect_flags,
817 i += snprintf(page + i, count - i,
820 i += obd_import_flags2str(imp, page + i, count - i);
822 i += snprintf(page + i, count - i,
825 " failover_nids: [");
826 cfs_spin_lock(&imp->imp_lock);
828 cfs_list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
829 i += snprintf(page + i, count - i, "%s%s", j ? ", " : "",
830 libcfs_nid2str(conn->oic_conn->c_peer.nid));
833 cfs_spin_unlock(&imp->imp_lock);
834 i += snprintf(page + i, count - i,
836 " current_connection: %s\n"
837 " connection_attempts: %u\n"
839 " in-progress_invalidations: %u\n",
840 libcfs_nid2str(imp->imp_connection->c_peer.nid),
843 cfs_atomic_read(&imp->imp_inval_count));
845 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
846 if (ret.lc_count != 0)
847 do_div(ret.lc_sum, ret.lc_count);
850 i += snprintf(page + i, count - i,
853 " unregistering: %u\n"
855 " avg_waittime: "LPU64" %s\n",
856 cfs_atomic_read(&imp->imp_inflight),
857 cfs_atomic_read(&imp->imp_unregistering),
858 cfs_atomic_read(&imp->imp_timeouts),
859 ret.lc_sum, ret.lc_units);
862 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
863 if (imp->imp_at.iat_portal[j] == 0)
865 k = max_t(unsigned int, k,
866 at_get(&imp->imp_at.iat_service_estimate[j]));
868 i += snprintf(page + i, count - i,
869 " service_estimates:\n"
870 " services: %u sec\n"
871 " network: %u sec\n",
873 at_get(&imp->imp_at.iat_net_latency));
875 i += snprintf(page + i, count - i,
877 " last_replay: "LPU64"\n"
878 " peer_committed: "LPU64"\n"
879 " last_checked: "LPU64"\n",
880 imp->imp_last_replay_transno,
881 imp->imp_peer_committed_transno,
882 imp->imp_last_transno_checked);
885 for (rw = 0; rw <= 1; rw++) {
886 lprocfs_stats_collect(obd->obd_svc_stats,
887 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
889 if (ret.lc_sum > 0 && ret.lc_count > 0) {
890 do_div(ret.lc_sum, ret.lc_count);
891 i += snprintf(page + i, count - i,
892 " %s_data_averages:\n"
893 " bytes_per_rpc: "LPU64"\n",
894 rw ? "write" : "read",
898 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
899 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
900 if (ret.lc_sum > 0 && ret.lc_count != 0) {
901 do_div(ret.lc_sum, ret.lc_count);
902 i += snprintf(page + i, count - i,
903 " %s_per_rpc: "LPU64"\n",
904 ret.lc_units, ret.lc_sum);
907 i += snprintf(page + i, count - i,
908 " MB_per_sec: %u.%.02u\n",
909 k / j, (100 * k / j) % 100);
913 LPROCFS_CLIMP_EXIT(obd);
917 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
918 int *eof, void *data)
920 struct obd_device *obd = (struct obd_device *)data;
921 struct obd_import *imp;
924 LASSERT(obd != NULL);
925 LPROCFS_CLIMP_CHECK(obd);
926 imp = obd->u.cli.cl_import;
929 i = snprintf(page, count, "current_state: %s\n",
930 ptlrpc_import_state_name(imp->imp_state));
931 i += snprintf(page + i, count - i,
933 k = imp->imp_state_hist_idx;
934 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
935 struct import_state_hist *ish =
936 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
937 if (ish->ish_state == 0)
939 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
941 ptlrpc_import_state_name(ish->ish_state));
944 LPROCFS_CLIMP_EXIT(obd);
948 int lprocfs_at_hist_helper(char *page, int count, int rc,
949 struct adaptive_timeout *at)
952 for (i = 0; i < AT_BINS; i++)
953 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
954 rc += snprintf(page + rc, count - rc, "\n");
958 /* See also ptlrpc_lprocfs_rd_timeouts */
959 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
960 int *eof, void *data)
962 struct obd_device *obd = (struct obd_device *)data;
963 struct obd_import *imp;
964 unsigned int cur, worst;
969 LASSERT(obd != NULL);
970 LPROCFS_CLIMP_CHECK(obd);
971 imp = obd->u.cli.cl_import;
974 now = cfs_time_current_sec();
976 /* Some network health info for kicks */
977 s2dhms(&ts, now - imp->imp_last_reply_time);
978 rc += snprintf(page + rc, count - rc,
979 "%-10s : %ld, "DHMS_FMT" ago\n",
980 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
982 cur = at_get(&imp->imp_at.iat_net_latency);
983 worst = imp->imp_at.iat_net_latency.at_worst_ever;
984 worstt = imp->imp_at.iat_net_latency.at_worst_time;
985 s2dhms(&ts, now - worstt);
986 rc += snprintf(page + rc, count - rc,
987 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
988 "network", cur, worst, worstt, DHMS_VARS(&ts));
989 rc = lprocfs_at_hist_helper(page, count, rc,
990 &imp->imp_at.iat_net_latency);
992 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
993 if (imp->imp_at.iat_portal[i] == 0)
995 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
996 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
997 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
998 s2dhms(&ts, now - worstt);
999 rc += snprintf(page + rc, count - rc,
1000 "portal %-2d : cur %3u worst %3u (at %ld, "
1001 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
1002 cur, worst, worstt, DHMS_VARS(&ts));
1003 rc = lprocfs_at_hist_helper(page, count, rc,
1004 &imp->imp_at.iat_service_estimate[i]);
1007 LPROCFS_CLIMP_EXIT(obd);
1011 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1012 int count, int *eof, void *data)
1014 struct obd_device *obd = data;
1018 LPROCFS_CLIMP_CHECK(obd);
1019 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1020 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1021 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1022 ret += snprintf(page + ret, count - ret, "\n");
1023 LPROCFS_CLIMP_EXIT(obd);
1026 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1028 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1029 int *eof, void *data)
1031 struct obd_device *obd = data;
1033 LASSERT(obd != NULL);
1035 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1038 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1039 int *eof, void *data)
1041 struct obd_type *class = (struct obd_type*) data;
1043 LASSERT(class != NULL);
1045 return snprintf(page, count, "%d\n", class->typ_refcnt);
1048 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1052 LASSERT(obd != NULL);
1053 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1054 LASSERT(obd->obd_type->typ_procroot != NULL);
1056 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1057 obd->obd_type->typ_procroot,
1059 if (IS_ERR(obd->obd_proc_entry)) {
1060 rc = PTR_ERR(obd->obd_proc_entry);
1061 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1062 obd->obd_proc_entry = NULL;
1067 int lprocfs_obd_cleanup(struct obd_device *obd)
1071 if (obd->obd_proc_exports_entry) {
1072 /* Should be no exports left */
1073 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1074 lprocfs_remove(&obd->obd_proc_exports_entry);
1075 obd->obd_proc_exports_entry = NULL;
1077 if (obd->obd_proc_entry) {
1078 lprocfs_remove(&obd->obd_proc_entry);
1079 obd->obd_proc_entry = NULL;
1084 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1086 CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
1087 client_stat->nid_proc, client_stat->nid_stats,
1088 client_stat->nid_brw_stats);
1090 LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
1092 cfs_atomic_read(&client_stat->nid_exp_ref_count));
1094 cfs_hlist_del_init(&client_stat->nid_hash);
1096 if (client_stat->nid_proc)
1097 lprocfs_remove(&client_stat->nid_proc);
1099 if (client_stat->nid_stats)
1100 lprocfs_free_stats(&client_stat->nid_stats);
1102 if (client_stat->nid_brw_stats)
1103 OBD_FREE_PTR(client_stat->nid_brw_stats);
1105 if (client_stat->nid_ldlm_stats)
1106 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1108 OBD_FREE_PTR(client_stat);
1113 void lprocfs_free_per_client_stats(struct obd_device *obd)
1115 struct nid_stat *stat;
1118 /* we need extra list - because hash_exit called to early */
1119 /* not need locking because all clients is died */
1120 while(!cfs_list_empty(&obd->obd_nid_stats)) {
1121 stat = cfs_list_entry(obd->obd_nid_stats.next,
1122 struct nid_stat, nid_list);
1123 cfs_list_del_init(&stat->nid_list);
1124 lprocfs_free_client_stats(stat);
1130 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1131 enum lprocfs_stats_flags flags)
1133 struct lprocfs_stats *stats;
1134 unsigned int percpusize;
1136 unsigned int num_cpu;
1141 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1144 num_cpu = cfs_num_possible_cpus();
1146 OBD_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
1150 if (flags & LPROCFS_STATS_FLAG_NOPERCPU) {
1151 stats->ls_flags = flags;
1152 cfs_spin_lock_init(&stats->ls_lock);
1153 /* Use this lock only if there are no percpu areas */
1155 stats->ls_flags = 0;
1158 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
1160 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1162 for (i = 0; i < num_cpu; i++) {
1163 OBD_ALLOC(stats->ls_percpu[i], percpusize);
1164 if (stats->ls_percpu[i] == NULL) {
1165 for (j = 0; j < i; j++) {
1166 OBD_FREE(stats->ls_percpu[j], percpusize);
1167 stats->ls_percpu[j] = NULL;
1172 if (stats->ls_percpu[0] == NULL) {
1173 OBD_FREE(stats, offsetof(typeof(*stats),
1174 ls_percpu[num_cpu]));
1178 stats->ls_num = num;
1182 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1184 struct lprocfs_stats *stats = *statsh;
1185 unsigned int num_cpu;
1186 unsigned int percpusize;
1189 if (stats == NULL || stats->ls_num == 0)
1193 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1196 num_cpu = cfs_num_possible_cpus();
1198 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
1200 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1201 for (i = 0; i < num_cpu; i++)
1202 OBD_FREE(stats->ls_percpu[i], percpusize);
1203 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
1206 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1208 struct lprocfs_counter *percpu_cntr;
1210 unsigned int num_cpu;
1212 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1214 for (i = 0; i < num_cpu; i++) {
1215 for (j = 0; j < stats->ls_num; j++) {
1216 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
1217 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_entry);
1218 percpu_cntr->lc_count = 0;
1219 percpu_cntr->lc_sum = 0;
1220 percpu_cntr->lc_min = LC_MIN_INIT;
1221 percpu_cntr->lc_max = 0;
1222 percpu_cntr->lc_sumsquare = 0;
1223 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_exit);
1227 lprocfs_stats_unlock(stats);
1230 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1231 size_t len, loff_t *off)
1233 struct seq_file *seq = file->private_data;
1234 struct lprocfs_stats *stats = seq->private;
1236 lprocfs_clear_stats(stats);
1241 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1243 struct lprocfs_stats *stats = p->private;
1244 /* return 1st cpu location */
1245 return (*pos >= stats->ls_num) ? NULL :
1246 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1249 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1253 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1255 struct lprocfs_stats *stats = p->private;
1257 return (*pos >= stats->ls_num) ? NULL :
1258 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1261 /* seq file export of one lprocfs counter */
1262 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1264 struct lprocfs_stats *stats = p->private;
1265 struct lprocfs_counter *cntr = v;
1266 struct lprocfs_counter ret;
1269 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
1271 cfs_gettimeofday(&now);
1272 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1273 "snapshot_time", now.tv_sec, now.tv_usec);
1277 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
1279 lprocfs_stats_collect(stats, idx, &ret);
1281 if (ret.lc_count == 0)
1284 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", cntr->lc_name,
1285 ret.lc_count, cntr->lc_units);
1290 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
1291 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1292 ret.lc_min, ret.lc_max, ret.lc_sum);
1295 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
1296 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1300 rc = seq_printf(p, "\n");
1302 return (rc < 0) ? rc : 0;
1305 struct seq_operations lprocfs_stats_seq_sops = {
1306 start: lprocfs_stats_seq_start,
1307 stop: lprocfs_stats_seq_stop,
1308 next: lprocfs_stats_seq_next,
1309 show: lprocfs_stats_seq_show,
1312 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1314 struct proc_dir_entry *dp = PDE(inode);
1315 struct seq_file *seq;
1318 if (LPROCFS_ENTRY_AND_CHECK(dp))
1321 rc = seq_open(file, &lprocfs_stats_seq_sops);
1326 seq = file->private_data;
1327 seq->private = dp->data;
1331 struct file_operations lprocfs_stats_seq_fops = {
1332 .owner = THIS_MODULE,
1333 .open = lprocfs_stats_seq_open,
1335 .write = lprocfs_stats_seq_write,
1336 .llseek = seq_lseek,
1337 .release = lprocfs_seq_release,
1340 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1341 struct lprocfs_stats *stats)
1343 struct proc_dir_entry *entry;
1344 LASSERT(root != NULL);
1346 entry = create_proc_entry(name, 0644, root);
1349 entry->proc_fops = &lprocfs_stats_seq_fops;
1350 entry->data = stats;
1354 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1355 unsigned conf, const char *name, const char *units)
1357 struct lprocfs_counter *c;
1359 unsigned int num_cpu;
1361 LASSERT(stats != NULL);
1363 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1365 for (i = 0; i < num_cpu; i++) {
1366 c = &(stats->ls_percpu[i]->lp_cntr[index]);
1367 c->lc_config = conf;
1370 c->lc_min = LC_MIN_INIT;
1373 c->lc_units = units;
1376 lprocfs_stats_unlock(stats);
1378 EXPORT_SYMBOL(lprocfs_counter_init);
1380 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1382 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1383 LASSERT(coffset < stats->ls_num); \
1384 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1387 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1389 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1390 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1391 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1392 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1393 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1394 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1395 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1396 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1397 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1398 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1399 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1400 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1401 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1402 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1403 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1404 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1405 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1406 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1407 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
1408 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1409 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1410 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1411 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1412 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1413 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1414 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1415 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1416 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1417 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1418 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1419 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1420 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1421 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1422 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1423 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1424 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1425 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1426 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1427 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1428 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1429 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1430 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1431 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1432 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1433 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
1434 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1435 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1436 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1437 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1438 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1439 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1440 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1441 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1442 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1443 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1444 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1445 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1446 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1447 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1448 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1449 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1450 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quota_adjust_qunit);
1451 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1452 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1453 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1454 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1455 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1456 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1457 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1460 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1462 struct lprocfs_stats *stats;
1463 unsigned int num_stats;
1466 LASSERT(obd->obd_stats == NULL);
1467 LASSERT(obd->obd_proc_entry != NULL);
1468 LASSERT(obd->obd_cntr_base == 0);
1470 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1471 num_private_stats - 1 /* o_owner */;
1472 stats = lprocfs_alloc_stats(num_stats, 0);
1476 lprocfs_init_ops_stats(num_private_stats, stats);
1478 for (i = num_private_stats; i < num_stats; i++) {
1479 /* If this LBUGs, it is likely that an obd
1480 * operation was added to struct obd_ops in
1481 * <obd.h>, and that the corresponding line item
1482 * LPROCFS_OBD_OP_INIT(.., .., opname)
1483 * is missing from the list above. */
1484 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1485 "Missing obd_stat initializer obd_op "
1486 "operation at offset %d.\n", i - num_private_stats);
1488 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1490 lprocfs_free_stats(&stats);
1492 obd->obd_stats = stats;
1493 obd->obd_cntr_base = num_private_stats;
1498 void lprocfs_free_obd_stats(struct obd_device *obd)
1501 lprocfs_free_stats(&obd->obd_stats);
1504 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1506 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1507 LASSERT(coffset < stats->ls_num); \
1508 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1511 int lprocfs_alloc_md_stats(struct obd_device *obd,
1512 unsigned num_private_stats)
1514 struct lprocfs_stats *stats;
1515 unsigned int num_stats;
1518 LASSERT(obd->md_stats == NULL);
1519 LASSERT(obd->obd_proc_entry != NULL);
1520 LASSERT(obd->md_cntr_base == 0);
1522 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1524 stats = lprocfs_alloc_stats(num_stats, 0);
1528 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1529 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1530 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
1531 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1532 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1533 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1534 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1535 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1536 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1537 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1538 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1539 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1540 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1541 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1542 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1543 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1544 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1545 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1546 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1547 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1548 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1549 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1550 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1551 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1552 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1553 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1554 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1555 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1556 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1557 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1558 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1559 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1561 for (i = num_private_stats; i < num_stats; i++) {
1562 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1563 CERROR("Missing md_stat initializer md_op "
1564 "operation at offset %d. Aborting.\n",
1565 i - num_private_stats);
1569 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1571 lprocfs_free_stats(&stats);
1573 obd->md_stats = stats;
1574 obd->md_cntr_base = num_private_stats;
1579 void lprocfs_free_md_stats(struct obd_device *obd)
1581 struct lprocfs_stats *stats = obd->md_stats;
1583 if (stats != NULL) {
1584 obd->md_stats = NULL;
1585 obd->md_cntr_base = 0;
1586 lprocfs_free_stats(&stats);
1590 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1592 lprocfs_counter_init(ldlm_stats,
1593 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1594 0, "ldlm_enqueue", "reqs");
1595 lprocfs_counter_init(ldlm_stats,
1596 LDLM_CONVERT - LDLM_FIRST_OPC,
1597 0, "ldlm_convert", "reqs");
1598 lprocfs_counter_init(ldlm_stats,
1599 LDLM_CANCEL - LDLM_FIRST_OPC,
1600 0, "ldlm_cancel", "reqs");
1601 lprocfs_counter_init(ldlm_stats,
1602 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1603 0, "ldlm_bl_callback", "reqs");
1604 lprocfs_counter_init(ldlm_stats,
1605 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1606 0, "ldlm_cp_callback", "reqs");
1607 lprocfs_counter_init(ldlm_stats,
1608 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1609 0, "ldlm_gl_callback", "reqs");
1612 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1613 int *eof, void *data)
1615 struct obd_export *exp = data;
1616 LASSERT(exp != NULL);
1618 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1621 struct exp_uuid_cb_data {
1629 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1630 int count, int *eof, int *len)
1632 cb_data->page = page;
1633 cb_data->count = count;
1638 void lprocfs_exp_print_uuid(void *obj, void *cb_data)
1640 struct obd_export *exp = (struct obd_export *)obj;
1641 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1643 if (exp->exp_nid_stats)
1644 *data->len += snprintf((data->page + *data->len),
1645 data->count, "%s\n",
1646 obd_uuid2str(&exp->exp_client_uuid));
1649 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1650 int *eof, void *data)
1652 struct nid_stat *stats = (struct nid_stat *)data;
1653 struct exp_uuid_cb_data cb_data;
1654 struct obd_device *obd = stats->nid_obd;
1659 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1660 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1661 lprocfs_exp_print_uuid, &cb_data);
1662 return (*cb_data.len);
1665 void lprocfs_exp_print_hash(void *obj, void *cb_data)
1667 struct exp_uuid_cb_data *data = cb_data;
1668 struct obd_export *exp = obj;
1671 hs = exp->exp_lock_hash;
1674 *data->len += cfs_hash_debug_header(data->page,
1677 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1682 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1683 int *eof, void *data)
1685 struct nid_stat *stats = (struct nid_stat *)data;
1686 struct exp_uuid_cb_data cb_data;
1687 struct obd_device *obd = stats->nid_obd;
1692 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1694 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1695 lprocfs_exp_print_hash, &cb_data);
1696 return (*cb_data.len);
1699 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1700 int count, int *eof, void *data)
1703 return snprintf(page, count, "%s\n",
1704 "Write into this file to clear all nid stats and "
1705 "stale nid entries");
1707 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1709 int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1711 struct nid_stat *stat = obj;
1714 /* object has only hash + iterate_all references.
1715 * add/delete blocked by hash bucket lock */
1716 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
1717 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 2) {
1718 cfs_spin_lock(&stat->nid_obd->obd_nid_lock);
1719 cfs_list_move(&stat->nid_list, data);
1720 cfs_spin_unlock(&stat->nid_obd->obd_nid_lock);
1723 /* we has reference to object - only clear data*/
1724 if (stat->nid_stats)
1725 lprocfs_clear_stats(stat->nid_stats);
1727 if (stat->nid_brw_stats) {
1728 for (i = 0; i < BRW_LAST; i++)
1729 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
1734 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1735 unsigned long count, void *data)
1737 struct obd_device *obd = (struct obd_device *)data;
1738 struct nid_stat *client_stat;
1739 CFS_LIST_HEAD(free_list);
1741 cfs_hash_cond_del(obd->obd_nid_stats_hash,
1742 lprocfs_nid_stats_clear_write_cb, &free_list);
1744 while (!cfs_list_empty(&free_list)) {
1745 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
1747 cfs_list_del_init(&client_stat->nid_list);
1748 lprocfs_free_client_stats(client_stat);
1753 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1755 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1757 struct nid_stat *new_stat, *old_stat;
1758 struct obd_device *obd = NULL;
1759 cfs_proc_dir_entry_t *entry;
1760 char *buffer = NULL;
1766 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1767 !exp->exp_obd->obd_nid_stats_hash)
1770 /* not test against zero because eric say:
1771 * You may only test nid against another nid, or LNET_NID_ANY.
1772 * Anything else is nonsense.*/
1773 if (!nid || *nid == LNET_NID_ANY)
1778 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
1780 OBD_ALLOC_PTR(new_stat);
1781 if (new_stat == NULL)
1784 new_stat->nid = *nid;
1785 new_stat->nid_obd = exp->exp_obd;
1786 cfs_atomic_set(&new_stat->nid_exp_ref_count, 0);
1788 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
1789 nid, &new_stat->nid_hash);
1790 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
1791 old_stat, libcfs_nid2str(*nid),
1792 cfs_atomic_read(&new_stat->nid_exp_ref_count));
1794 /* Return -EALREADY here so that we know that the /proc
1795 * entry already has been created */
1796 if (old_stat != new_stat) {
1797 cfs_spin_lock(&obd->obd_nid_lock);
1798 if (exp->exp_nid_stats != old_stat) {
1799 if (exp->exp_nid_stats)
1800 nidstat_putref(exp->exp_nid_stats);
1801 exp->exp_nid_stats = old_stat;
1803 /* cfs_hash_findadd_unique() has added
1804 * old_stat's refcount */
1805 nidstat_putref(old_stat);
1808 cfs_spin_unlock(&obd->obd_nid_lock);
1810 GOTO(destroy_new, rc = -EALREADY);
1812 /* not found - create */
1813 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
1815 GOTO(destroy_new, rc = -ENOMEM);
1817 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
1818 new_stat->nid_proc = lprocfs_register(buffer,
1819 obd->obd_proc_exports_entry,
1821 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
1823 if (new_stat->nid_proc == NULL) {
1824 CERROR("Error making export directory for nid %s\n",
1825 libcfs_nid2str(*nid));
1826 GOTO(destroy_new_ns, rc = -ENOMEM);
1829 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
1830 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
1831 if (IS_ERR(entry)) {
1832 CWARN("Error adding the NID stats file\n");
1833 rc = PTR_ERR(entry);
1834 GOTO(destroy_new_ns, rc);
1837 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
1838 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
1839 if (IS_ERR(entry)) {
1840 CWARN("Error adding the hash file\n");
1841 rc = PTR_ERR(entry);
1842 GOTO(destroy_new_ns, rc);
1845 if (exp->exp_nid_stats)
1846 nidstat_putref(exp->exp_nid_stats);
1847 nidstat_getref(new_stat);
1848 exp->exp_nid_stats = new_stat;
1850 /* protect competitive add to list, not need locking on destroy */
1851 cfs_spin_lock(&obd->obd_nid_lock);
1852 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
1853 cfs_spin_unlock(&obd->obd_nid_lock);
1858 if (new_stat->nid_proc != NULL)
1859 lprocfs_remove(&new_stat->nid_proc);
1860 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
1863 OBD_FREE_PTR(new_stat);
1867 int lprocfs_exp_cleanup(struct obd_export *exp)
1869 struct nid_stat *stat = exp->exp_nid_stats;
1871 if(!stat || !exp->exp_obd)
1874 nidstat_putref(exp->exp_nid_stats);
1875 exp->exp_nid_stats = NULL;
1880 int lprocfs_write_helper(const char *buffer, unsigned long count,
1883 return lprocfs_write_frac_helper(buffer, count, val, 1);
1886 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
1889 char kernbuf[20], *end, *pbuf;
1891 if (count > (sizeof(kernbuf) - 1))
1894 if (cfs_copy_from_user(kernbuf, buffer, count))
1897 kernbuf[count] = '\0';
1904 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1908 if (end != NULL && *end == '.') {
1909 int temp_val, pow = 1;
1913 if (strlen(pbuf) > 5)
1914 pbuf[5] = '\0'; /*only allow 5bits fractional*/
1916 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1919 for (i = 0; i < (end - pbuf); i++)
1922 *val += temp_val / pow;
1928 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
1931 long decimal_val, frac_val;
1937 decimal_val = val / mult;
1938 prtn = snprintf(buffer, count, "%ld", decimal_val);
1939 frac_val = val % mult;
1941 if (prtn < (count - 4) && frac_val > 0) {
1943 int i, temp_mult = 1, frac_bits = 0;
1945 temp_frac = frac_val * 10;
1946 buffer[prtn++] = '.';
1947 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
1948 /* only reserved 2 bits fraction */
1949 buffer[prtn++] ='0';
1954 * Need to think these cases :
1955 * 1. #echo x.00 > /proc/xxx output result : x
1956 * 2. #echo x.0x > /proc/xxx output result : x.0x
1957 * 3. #echo x.x0 > /proc/xxx output result : x.x
1958 * 4. #echo x.xx > /proc/xxx output result : x.xx
1959 * Only reserved 2 bits fraction.
1961 for (i = 0; i < (5 - prtn); i++)
1964 frac_bits = min((int)count - prtn, 3 - frac_bits);
1965 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
1966 frac_val * temp_mult / mult);
1969 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
1971 if (buffer[prtn] == '.') {
1978 buffer[prtn++] ='\n';
1982 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
1984 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
1987 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
1988 __u64 *val, int mult)
1990 char kernbuf[22], *end, *pbuf;
1991 __u64 whole, frac = 0, units;
1992 unsigned frac_d = 1;
1994 if (count > (sizeof(kernbuf) - 1))
1997 if (cfs_copy_from_user(kernbuf, buffer, count))
2000 kernbuf[count] = '\0';
2007 whole = simple_strtoull(pbuf, &end, 10);
2011 if (end != NULL && *end == '.') {
2015 /* need to limit frac_d to a __u32 */
2016 if (strlen(pbuf) > 10)
2019 frac = simple_strtoull(pbuf, &end, 10);
2020 /* count decimal places */
2021 for (i = 0; i < (end - pbuf); i++)
2038 /* Specified units override the multiplier */
2040 mult = mult < 0 ? -units : units;
2043 do_div(frac, frac_d);
2044 *val = whole * mult + frac;
2048 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent, char *name, mode_t mode,
2049 struct file_operations *seq_fops, void *data)
2051 struct proc_dir_entry *entry;
2054 entry = create_proc_entry(name, mode, parent);
2057 entry->proc_fops = seq_fops;
2062 EXPORT_SYMBOL(lprocfs_seq_create);
2064 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
2066 struct file_operations *seq_fops,
2069 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2070 mode, seq_fops, data));
2072 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2074 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2076 if (value >= OBD_HIST_MAX)
2077 value = OBD_HIST_MAX - 1;
2079 cfs_spin_lock(&oh->oh_lock);
2080 oh->oh_buckets[value]++;
2081 cfs_spin_unlock(&oh->oh_lock);
2083 EXPORT_SYMBOL(lprocfs_oh_tally);
2085 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2089 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2092 lprocfs_oh_tally(oh, val);
2094 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2096 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2098 unsigned long ret = 0;
2101 for (i = 0; i < OBD_HIST_MAX; i++)
2102 ret += oh->oh_buckets[i];
2105 EXPORT_SYMBOL(lprocfs_oh_sum);
2107 void lprocfs_oh_clear(struct obd_histogram *oh)
2109 cfs_spin_lock(&oh->oh_lock);
2110 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2111 cfs_spin_unlock(&oh->oh_lock);
2113 EXPORT_SYMBOL(lprocfs_oh_clear);
2115 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2116 int count, int *eof, void *data)
2118 struct obd_device *obd = data;
2124 c += cfs_hash_debug_header(page, count);
2125 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2126 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2127 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2131 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2133 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2134 int count, int *eof, void *data)
2136 struct obd_device *obd = data;
2139 LASSERT(obd != NULL);
2140 LASSERT(count >= 0);
2142 /* Set start of user data returned to
2143 page + off since the user may have
2144 requested to read much smaller than
2145 what we need to read */
2146 *start = page + off;
2148 /* We know we are allocated a page here.
2149 Also we know that this function will
2150 not need to write more than a page
2151 so we can truncate at CFS_PAGE_SIZE. */
2152 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2154 /* Initialize the page */
2155 memset(page, 0, size);
2157 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2159 if (obd->obd_max_recoverable_clients == 0) {
2160 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2166 /* sampled unlocked, but really... */
2167 if (obd->obd_recovering == 0) {
2168 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2170 if (lprocfs_obd_snprintf(&page, size, &len,
2171 "recovery_start: %lu\n",
2172 obd->obd_recovery_start) <= 0)
2174 if (lprocfs_obd_snprintf(&page, size, &len,
2175 "recovery_duration: %lu\n",
2176 obd->obd_recovery_end -
2177 obd->obd_recovery_start) <= 0)
2179 /* Number of clients that have completed recovery */
2180 if (lprocfs_obd_snprintf(&page, size, &len,
2181 "completed_clients: %d/%d\n",
2182 obd->obd_max_recoverable_clients -
2183 obd->obd_stale_clients,
2184 obd->obd_max_recoverable_clients) <= 0)
2186 if (lprocfs_obd_snprintf(&page, size, &len,
2187 "replayed_requests: %d\n",
2188 obd->obd_replayed_requests) <= 0)
2190 if (lprocfs_obd_snprintf(&page, size, &len,
2191 "last_transno: "LPD64"\n",
2192 obd->obd_next_recovery_transno - 1)<=0)
2194 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2195 obd->obd_version_recov ? "ON" : "OFF")<=0)
2200 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2202 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2203 obd->obd_recovery_start) <= 0)
2205 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2206 cfs_time_current_sec() >= obd->obd_recovery_end ? 0 :
2207 obd->obd_recovery_end - cfs_time_current_sec()) <= 0)
2209 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2210 obd->obd_connected_clients,
2211 obd->obd_max_recoverable_clients) <= 0)
2213 /* Number of clients that have completed recovery */
2214 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2215 cfs_atomic_read(&obd->obd_req_replay_clients))
2218 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2219 cfs_atomic_read(&obd->obd_lock_replay_clients))
2222 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2223 obd->obd_connected_clients -
2224 cfs_atomic_read(&obd->obd_lock_replay_clients))
2227 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2228 obd->obd_stale_clients) <= 0)
2230 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2231 obd->obd_replayed_requests) <= 0)
2233 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2234 obd->obd_requests_queued_for_recovery) <= 0)
2237 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2238 obd->obd_next_recovery_transno) <= 0)
2244 return min(count, len - (int)off);
2246 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2248 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
2249 int count, int *eof, void *data)
2251 struct obd_device *obd = (struct obd_device *)data;
2252 LASSERT(obd != NULL);
2254 return snprintf(page, count, "%d\n",
2255 obd->obd_recovery_timeout);
2257 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
2259 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
2260 unsigned long count, void *data)
2262 struct obd_device *obd = (struct obd_device *)data;
2264 LASSERT(obd != NULL);
2266 rc = lprocfs_write_helper(buffer, count, &val);
2270 obd->obd_recovery_timeout = val;
2273 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
2275 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
2276 int count, int *eof, void *data)
2278 struct obd_device *obd = data;
2279 LASSERT(obd != NULL);
2281 return snprintf(page, count, "%lu\n", obd->obd_recovery_time_hard);
2283 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
2285 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
2286 unsigned long count, void *data)
2288 struct obd_device *obd = data;
2290 LASSERT(obd != NULL);
2292 rc = lprocfs_write_helper(buffer, count, &val);
2296 obd->obd_recovery_time_hard = val;
2299 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
2301 EXPORT_SYMBOL(lprocfs_register);
2302 EXPORT_SYMBOL(lprocfs_srch);
2303 EXPORT_SYMBOL(lprocfs_remove);
2304 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
2305 EXPORT_SYMBOL(lprocfs_add_vars);
2306 EXPORT_SYMBOL(lprocfs_obd_setup);
2307 EXPORT_SYMBOL(lprocfs_obd_cleanup);
2308 EXPORT_SYMBOL(lprocfs_add_simple);
2309 EXPORT_SYMBOL(lprocfs_add_symlink);
2310 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
2311 EXPORT_SYMBOL(lprocfs_alloc_stats);
2312 EXPORT_SYMBOL(lprocfs_free_stats);
2313 EXPORT_SYMBOL(lprocfs_clear_stats);
2314 EXPORT_SYMBOL(lprocfs_register_stats);
2315 EXPORT_SYMBOL(lprocfs_init_ops_stats);
2316 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
2317 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
2318 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
2319 EXPORT_SYMBOL(lprocfs_free_obd_stats);
2320 EXPORT_SYMBOL(lprocfs_free_md_stats);
2321 EXPORT_SYMBOL(lprocfs_exp_setup);
2322 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2324 EXPORT_SYMBOL(lprocfs_rd_u64);
2325 EXPORT_SYMBOL(lprocfs_rd_atomic);
2326 EXPORT_SYMBOL(lprocfs_wr_atomic);
2327 EXPORT_SYMBOL(lprocfs_rd_uint);
2328 EXPORT_SYMBOL(lprocfs_wr_uint);
2329 EXPORT_SYMBOL(lprocfs_rd_uuid);
2330 EXPORT_SYMBOL(lprocfs_rd_name);
2331 EXPORT_SYMBOL(lprocfs_rd_fstype);
2332 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
2333 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
2334 EXPORT_SYMBOL(lprocfs_rd_num_exports);
2335 EXPORT_SYMBOL(lprocfs_rd_numrefs);
2336 EXPORT_SYMBOL(lprocfs_at_hist_helper);
2337 EXPORT_SYMBOL(lprocfs_rd_import);
2338 EXPORT_SYMBOL(lprocfs_rd_state);
2339 EXPORT_SYMBOL(lprocfs_rd_timeouts);
2340 EXPORT_SYMBOL(lprocfs_rd_blksize);
2341 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
2342 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
2343 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
2344 EXPORT_SYMBOL(lprocfs_rd_filestotal);
2345 EXPORT_SYMBOL(lprocfs_rd_filesfree);
2347 EXPORT_SYMBOL(lprocfs_write_helper);
2348 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2349 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2350 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2351 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2352 EXPORT_SYMBOL(lprocfs_stats_collect);