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)) {
193 OBD_FAIL_TIMEOUT(OBD_FAIL_LPROC_REMOVE, 10);
195 rc = dp->read_proc(page, &start, *ppos, CFS_PAGE_SIZE,
201 /* for lustre proc read, the read count must be less than PAGE_SIZE */
210 start = page + *ppos;
211 } else if (start < page) {
215 count = (rc < size) ? rc : size;
216 if (cfs_copy_to_user(buf, start, count)) {
223 free_page((unsigned long)page);
227 static ssize_t lprocfs_fops_write(struct file *f, const char __user *buf,
228 size_t size, loff_t *ppos)
230 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
233 if (LPROCFS_ENTRY_AND_CHECK(dp))
236 rc = dp->write_proc(f, buf, size, dp->data);
241 static struct file_operations lprocfs_generic_fops = {
242 .owner = THIS_MODULE,
243 .read = lprocfs_fops_read,
244 .write = lprocfs_fops_write,
247 int lprocfs_evict_client_open(struct inode *inode, struct file *f)
249 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
250 struct obd_device *obd = dp->data;
252 cfs_atomic_inc(&obd->obd_evict_inprogress);
257 int lprocfs_evict_client_release(struct inode *inode, struct file *f)
259 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
260 struct obd_device *obd = dp->data;
262 cfs_atomic_dec(&obd->obd_evict_inprogress);
263 cfs_waitq_signal(&obd->obd_evict_inprogress_waitq);
268 struct file_operations lprocfs_evict_client_fops = {
269 .owner = THIS_MODULE,
270 .read = lprocfs_fops_read,
271 .write = lprocfs_fops_write,
272 .open = lprocfs_evict_client_open,
273 .release = lprocfs_evict_client_release,
275 EXPORT_SYMBOL(lprocfs_evict_client_fops);
280 * \param root [in] The parent proc entry on which new entry will be added.
281 * \param list [in] Array of proc entries to be added.
282 * \param data [in] The argument to be passed when entries read/write routines
283 * are called through /proc file.
285 * \retval 0 on success
288 int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list,
291 if (root == NULL || list == NULL)
294 while (list->name != NULL) {
295 struct proc_dir_entry *cur_root, *proc;
296 char *pathcopy, *cur, *next, pathbuf[64];
297 int pathsize = strlen(list->name) + 1;
302 /* need copy of path for strsep */
303 if (strlen(list->name) > sizeof(pathbuf) - 1) {
304 OBD_ALLOC(pathcopy, pathsize);
305 if (pathcopy == NULL)
312 strcpy(pathcopy, list->name);
314 while (cur_root != NULL && (cur = strsep(&next, "/"))) {
315 if (*cur =='\0') /* skip double/trailing "/" */
318 proc = lprocfs_srch(cur_root, cur);
319 CDEBUG(D_OTHER, "cur_root=%s, cur=%s, next=%s, (%s)\n",
320 cur_root->name, cur, next,
321 (proc ? "exists" : "new"));
323 cur_root = (proc ? proc :
324 proc_mkdir(cur, cur_root));
325 } else if (proc == NULL) {
327 if (list->proc_mode != 0000) {
328 mode = list->proc_mode;
332 if (list->write_fptr)
335 proc = create_proc_entry(cur, mode, cur_root);
339 if (pathcopy != pathbuf)
340 OBD_FREE(pathcopy, pathsize);
342 if (cur_root == NULL || proc == NULL) {
343 CERROR("LprocFS: No memory to create /proc entry %s",
349 proc->proc_fops = list->fops;
351 proc->proc_fops = &lprocfs_generic_fops;
352 proc->read_proc = list->read_fptr;
353 proc->write_proc = list->write_fptr;
354 proc->data = (list->data ? list->data : data);
360 void lprocfs_remove(struct proc_dir_entry **rooth)
362 struct proc_dir_entry *root = *rooth;
363 struct proc_dir_entry *temp = root;
364 struct proc_dir_entry *rm_entry;
365 struct proc_dir_entry *parent;
371 parent = root->parent;
372 LASSERT(parent != NULL);
373 LPROCFS_WRITE_ENTRY(); /* search vs remove race */
376 while (temp->subdir != NULL)
382 /* Memory corruption once caused this to fail, and
383 without this LASSERT we would loop here forever. */
384 LASSERTF(strlen(rm_entry->name) == rm_entry->namelen,
385 "0x%p %s/%s len %d\n", rm_entry, temp->name,
386 rm_entry->name, (int)strlen(rm_entry->name));
388 /* Now, the rm_entry->deleted flags is protected
389 * by _lprocfs_lock. */
390 rm_entry->data = NULL;
391 remove_proc_entry(rm_entry->name, temp);
395 LPROCFS_WRITE_EXIT();
398 void lprocfs_remove_proc_entry(const char *name, struct proc_dir_entry *parent)
400 LASSERT(parent != NULL);
401 remove_proc_entry(name, parent);
404 struct proc_dir_entry *lprocfs_register(const char *name,
405 struct proc_dir_entry *parent,
406 struct lprocfs_vars *list, void *data)
408 struct proc_dir_entry *newchild;
410 newchild = lprocfs_srch(parent, name);
411 if (newchild != NULL) {
412 CERROR(" Lproc: Attempting to register %s more than once \n",
414 return ERR_PTR(-EALREADY);
417 newchild = proc_mkdir(name, parent);
418 if (newchild != NULL && list != NULL) {
419 int rc = lprocfs_add_vars(newchild, list, data);
421 lprocfs_remove(&newchild);
428 /* Generic callbacks */
429 int lprocfs_rd_uint(char *page, char **start, off_t off,
430 int count, int *eof, void *data)
432 unsigned int *temp = data;
433 return snprintf(page, count, "%u\n", *temp);
436 int lprocfs_wr_uint(struct file *file, const char *buffer,
437 unsigned long count, void *data)
440 char dummy[MAX_STRING_SIZE + 1], *end;
443 dummy[MAX_STRING_SIZE] = '\0';
444 if (cfs_copy_from_user(dummy, buffer, MAX_STRING_SIZE))
447 tmp = simple_strtoul(dummy, &end, 0);
451 *p = (unsigned int)tmp;
455 int lprocfs_rd_u64(char *page, char **start, off_t off,
456 int count, int *eof, void *data)
458 LASSERT(data != NULL);
460 return snprintf(page, count, LPU64"\n", *(__u64 *)data);
463 int lprocfs_rd_atomic(char *page, char **start, off_t off,
464 int count, int *eof, void *data)
466 cfs_atomic_t *atom = data;
467 LASSERT(atom != NULL);
469 return snprintf(page, count, "%d\n", cfs_atomic_read(atom));
472 int lprocfs_wr_atomic(struct file *file, const char *buffer,
473 unsigned long count, void *data)
475 cfs_atomic_t *atm = data;
479 rc = lprocfs_write_helper(buffer, count, &val);
486 cfs_atomic_set(atm, val);
490 int lprocfs_rd_uuid(char *page, char **start, off_t off, int count,
491 int *eof, void *data)
493 struct obd_device *obd = data;
495 LASSERT(obd != NULL);
497 return snprintf(page, count, "%s\n", obd->obd_uuid.uuid);
500 int lprocfs_rd_name(char *page, char **start, off_t off, int count,
501 int *eof, void *data)
503 struct obd_device *dev = data;
505 LASSERT(dev != NULL);
506 LASSERT(dev->obd_name != NULL);
508 return snprintf(page, count, "%s\n", dev->obd_name);
511 int lprocfs_rd_fstype(char *page, char **start, off_t off, int count, int *eof,
514 struct obd_device *obd = data;
516 LASSERT(obd != NULL);
517 LASSERT(obd->obd_fsops != NULL);
518 LASSERT(obd->obd_fsops->fs_type != NULL);
519 return snprintf(page, count, "%s\n", obd->obd_fsops->fs_type);
522 int lprocfs_rd_blksize(char *page, char **start, off_t off, int count,
523 int *eof, void *data)
525 struct obd_statfs osfs;
526 int rc = obd_statfs(data, &osfs,
527 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
531 rc = snprintf(page, count, "%u\n", osfs.os_bsize);
536 int lprocfs_rd_kbytestotal(char *page, char **start, off_t off, int count,
537 int *eof, void *data)
539 struct obd_statfs osfs;
540 int rc = obd_statfs(data, &osfs,
541 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
544 __u32 blk_size = osfs.os_bsize >> 10;
545 __u64 result = osfs.os_blocks;
547 while (blk_size >>= 1)
551 rc = snprintf(page, count, LPU64"\n", result);
556 int lprocfs_rd_kbytesfree(char *page, char **start, off_t off, int count,
557 int *eof, void *data)
559 struct obd_statfs osfs;
560 int rc = obd_statfs(data, &osfs,
561 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
564 __u32 blk_size = osfs.os_bsize >> 10;
565 __u64 result = osfs.os_bfree;
567 while (blk_size >>= 1)
571 rc = snprintf(page, count, LPU64"\n", result);
576 int lprocfs_rd_kbytesavail(char *page, char **start, off_t off, int count,
577 int *eof, void *data)
579 struct obd_statfs osfs;
580 int rc = obd_statfs(data, &osfs,
581 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
584 __u32 blk_size = osfs.os_bsize >> 10;
585 __u64 result = osfs.os_bavail;
587 while (blk_size >>= 1)
591 rc = snprintf(page, count, LPU64"\n", result);
596 int lprocfs_rd_filestotal(char *page, char **start, off_t off, int count,
597 int *eof, void *data)
599 struct obd_statfs osfs;
600 int rc = obd_statfs(data, &osfs,
601 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
605 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
611 int lprocfs_rd_filesfree(char *page, char **start, off_t off, int count,
612 int *eof, void *data)
614 struct obd_statfs osfs;
615 int rc = obd_statfs(data, &osfs,
616 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
620 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
625 int lprocfs_rd_server_uuid(char *page, char **start, off_t off, int count,
626 int *eof, void *data)
628 struct obd_device *obd = data;
629 struct obd_import *imp;
630 char *imp_state_name = NULL;
633 LASSERT(obd != NULL);
634 LPROCFS_CLIMP_CHECK(obd);
635 imp = obd->u.cli.cl_import;
636 imp_state_name = ptlrpc_import_state_name(imp->imp_state);
638 rc = snprintf(page, count, "%s\t%s%s\n",
639 obd2cli_tgt(obd), imp_state_name,
640 imp->imp_deactive ? "\tDEACTIVATED" : "");
642 LPROCFS_CLIMP_EXIT(obd);
646 int lprocfs_rd_conn_uuid(char *page, char **start, off_t off, int count,
647 int *eof, void *data)
649 struct obd_device *obd = data;
650 struct ptlrpc_connection *conn;
653 LASSERT(obd != NULL);
655 LPROCFS_CLIMP_CHECK(obd);
656 conn = obd->u.cli.cl_import->imp_connection;
658 if (conn && obd->u.cli.cl_import) {
659 rc = snprintf(page, count, "%s\n",
660 conn->c_remote_uuid.uuid);
662 rc = snprintf(page, count, "%s\n", "<none>");
665 LPROCFS_CLIMP_EXIT(obd);
669 /** add up per-cpu counters */
670 void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
671 struct lprocfs_counter *cnt)
673 unsigned int num_cpu;
674 struct lprocfs_counter t;
675 struct lprocfs_counter *percpu_cntr;
678 memset(cnt, 0, sizeof(*cnt));
681 /* set count to 1 to avoid divide-by-zero errs in callers */
686 cnt->lc_min = LC_MIN_INIT;
688 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
691 num_cpu = cfs_num_possible_cpus();
693 for (i = 0; i < num_cpu; i++) {
694 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[idx];
697 centry = cfs_atomic_read(&percpu_cntr-> \
699 t.lc_count = percpu_cntr->lc_count;
700 t.lc_sum = percpu_cntr->lc_sum;
701 t.lc_min = percpu_cntr->lc_min;
702 t.lc_max = percpu_cntr->lc_max;
703 t.lc_sumsquare = percpu_cntr->lc_sumsquare;
704 } while (centry != cfs_atomic_read(&percpu_cntr->lc_cntl. \
706 centry != cfs_atomic_read(&percpu_cntr->lc_cntl. \
708 cnt->lc_count += t.lc_count;
709 cnt->lc_sum += t.lc_sum;
710 if (t.lc_min < cnt->lc_min)
711 cnt->lc_min = t.lc_min;
712 if (t.lc_max > cnt->lc_max)
713 cnt->lc_max = t.lc_max;
714 cnt->lc_sumsquare += t.lc_sumsquare;
717 cnt->lc_units = stats->ls_percpu[0]->lp_cntr[idx].lc_units;
721 * Append a space separated list of current set flags to str.
723 #define flag2str(flag) \
724 if (imp->imp_##flag && max - len > 0) \
725 len += snprintf(str + len, max - len, "%s" #flag, len ? ", " : "");
726 static int obd_import_flags2str(struct obd_import *imp, char *str, int max)
730 if (imp->imp_obd->obd_no_recov)
731 len += snprintf(str, max - len, "no_recov");
735 flag2str(replayable);
741 static const char *obd_connect_names[] = {
755 "join_file(obsolete)",
759 "remote_client_by_force",
768 "mds_mds_connection",
771 "alt_checksum_algorithm",
783 static int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
788 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
790 ret += snprintf(page + ret, count - ret, "%s%s",
791 ret ? sep : "", obd_connect_names[i]);
793 if (flags & ~(mask - 1))
794 ret += snprintf(page + ret, count - ret,
795 "%sunknown flags "LPX64,
796 ret ? sep : "", flags & ~(mask - 1));
800 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
801 int *eof, void *data)
803 struct lprocfs_counter ret;
804 struct obd_device *obd = (struct obd_device *)data;
805 struct obd_import *imp;
806 struct obd_import_conn *conn;
809 LASSERT(obd != NULL);
810 LPROCFS_CLIMP_CHECK(obd);
811 imp = obd->u.cli.cl_import;
814 i = snprintf(page, count,
822 ptlrpc_import_state_name(imp->imp_state));
823 i += obd_connect_flags2str(page + i, count - i,
824 imp->imp_connect_data.ocd_connect_flags,
826 i += snprintf(page + i, count - i,
829 i += obd_import_flags2str(imp, page + i, count - i);
831 i += snprintf(page + i, count - i,
834 " failover_nids: [");
835 cfs_spin_lock(&imp->imp_lock);
837 cfs_list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
838 i += snprintf(page + i, count - i, "%s%s", j ? ", " : "",
839 libcfs_nid2str(conn->oic_conn->c_peer.nid));
842 cfs_spin_unlock(&imp->imp_lock);
843 i += snprintf(page + i, count - i,
845 " current_connection: %s\n"
846 " connection_attempts: %u\n"
848 " in-progress_invalidations: %u\n",
849 libcfs_nid2str(imp->imp_connection->c_peer.nid),
852 cfs_atomic_read(&imp->imp_inval_count));
854 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
855 if (ret.lc_count != 0) {
856 /* first argument to do_div MUST be __u64 */
857 __u64 sum = ret.lc_sum;
858 do_div(sum, ret.lc_count);
862 i += snprintf(page + i, count - i,
865 " unregistering: %u\n"
867 " avg_waittime: "LPU64" %s\n",
868 cfs_atomic_read(&imp->imp_inflight),
869 cfs_atomic_read(&imp->imp_unregistering),
870 cfs_atomic_read(&imp->imp_timeouts),
871 ret.lc_sum, ret.lc_units);
874 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
875 if (imp->imp_at.iat_portal[j] == 0)
877 k = max_t(unsigned int, k,
878 at_get(&imp->imp_at.iat_service_estimate[j]));
880 i += snprintf(page + i, count - i,
881 " service_estimates:\n"
882 " services: %u sec\n"
883 " network: %u sec\n",
885 at_get(&imp->imp_at.iat_net_latency));
887 i += snprintf(page + i, count - i,
889 " last_replay: "LPU64"\n"
890 " peer_committed: "LPU64"\n"
891 " last_checked: "LPU64"\n",
892 imp->imp_last_replay_transno,
893 imp->imp_peer_committed_transno,
894 imp->imp_last_transno_checked);
897 for (rw = 0; rw <= 1; rw++) {
898 lprocfs_stats_collect(obd->obd_svc_stats,
899 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
901 if (ret.lc_sum > 0 && ret.lc_count > 0) {
902 /* first argument to do_div MUST be __u64 */
903 __u64 sum = ret.lc_sum;
904 do_div(sum, ret.lc_count);
906 i += snprintf(page + i, count - i,
907 " %s_data_averages:\n"
908 " bytes_per_rpc: "LPU64"\n",
909 rw ? "write" : "read",
913 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
914 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
915 if (ret.lc_sum > 0 && ret.lc_count != 0) {
916 /* first argument to do_div MUST be __u64 */
917 __u64 sum = ret.lc_sum;
918 do_div(sum, ret.lc_count);
920 i += snprintf(page + i, count - i,
921 " %s_per_rpc: "LPU64"\n",
922 ret.lc_units, ret.lc_sum);
925 i += snprintf(page + i, count - i,
926 " MB_per_sec: %u.%.02u\n",
927 k / j, (100 * k / j) % 100);
931 LPROCFS_CLIMP_EXIT(obd);
935 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
936 int *eof, void *data)
938 struct obd_device *obd = (struct obd_device *)data;
939 struct obd_import *imp;
942 LASSERT(obd != NULL);
943 LPROCFS_CLIMP_CHECK(obd);
944 imp = obd->u.cli.cl_import;
947 i = snprintf(page, count, "current_state: %s\n",
948 ptlrpc_import_state_name(imp->imp_state));
949 i += snprintf(page + i, count - i,
951 k = imp->imp_state_hist_idx;
952 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
953 struct import_state_hist *ish =
954 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
955 if (ish->ish_state == 0)
957 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
959 ptlrpc_import_state_name(ish->ish_state));
962 LPROCFS_CLIMP_EXIT(obd);
966 int lprocfs_at_hist_helper(char *page, int count, int rc,
967 struct adaptive_timeout *at)
970 for (i = 0; i < AT_BINS; i++)
971 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
972 rc += snprintf(page + rc, count - rc, "\n");
976 /* See also ptlrpc_lprocfs_rd_timeouts */
977 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
978 int *eof, void *data)
980 struct obd_device *obd = (struct obd_device *)data;
981 struct obd_import *imp;
982 unsigned int cur, worst;
987 LASSERT(obd != NULL);
988 LPROCFS_CLIMP_CHECK(obd);
989 imp = obd->u.cli.cl_import;
992 now = cfs_time_current_sec();
994 /* Some network health info for kicks */
995 s2dhms(&ts, now - imp->imp_last_reply_time);
996 rc += snprintf(page + rc, count - rc,
997 "%-10s : %ld, "DHMS_FMT" ago\n",
998 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
1000 cur = at_get(&imp->imp_at.iat_net_latency);
1001 worst = imp->imp_at.iat_net_latency.at_worst_ever;
1002 worstt = imp->imp_at.iat_net_latency.at_worst_time;
1003 s2dhms(&ts, now - worstt);
1004 rc += snprintf(page + rc, count - rc,
1005 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
1006 "network", cur, worst, worstt, DHMS_VARS(&ts));
1007 rc = lprocfs_at_hist_helper(page, count, rc,
1008 &imp->imp_at.iat_net_latency);
1010 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
1011 if (imp->imp_at.iat_portal[i] == 0)
1013 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
1014 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
1015 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
1016 s2dhms(&ts, now - worstt);
1017 rc += snprintf(page + rc, count - rc,
1018 "portal %-2d : cur %3u worst %3u (at %ld, "
1019 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
1020 cur, worst, worstt, DHMS_VARS(&ts));
1021 rc = lprocfs_at_hist_helper(page, count, rc,
1022 &imp->imp_at.iat_service_estimate[i]);
1025 LPROCFS_CLIMP_EXIT(obd);
1029 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1030 int count, int *eof, void *data)
1032 struct obd_device *obd = data;
1036 LPROCFS_CLIMP_CHECK(obd);
1037 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1038 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1039 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1040 ret += snprintf(page + ret, count - ret, "\n");
1041 LPROCFS_CLIMP_EXIT(obd);
1044 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1046 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1047 int *eof, void *data)
1049 struct obd_device *obd = data;
1051 LASSERT(obd != NULL);
1053 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1056 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1057 int *eof, void *data)
1059 struct obd_type *class = (struct obd_type*) data;
1061 LASSERT(class != NULL);
1063 return snprintf(page, count, "%d\n", class->typ_refcnt);
1066 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1070 LASSERT(obd != NULL);
1071 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1072 LASSERT(obd->obd_type->typ_procroot != NULL);
1074 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1075 obd->obd_type->typ_procroot,
1077 if (IS_ERR(obd->obd_proc_entry)) {
1078 rc = PTR_ERR(obd->obd_proc_entry);
1079 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1080 obd->obd_proc_entry = NULL;
1085 int lprocfs_obd_cleanup(struct obd_device *obd)
1089 if (obd->obd_proc_exports_entry) {
1090 /* Should be no exports left */
1091 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1092 lprocfs_remove(&obd->obd_proc_exports_entry);
1093 obd->obd_proc_exports_entry = NULL;
1095 if (obd->obd_proc_entry) {
1096 lprocfs_remove(&obd->obd_proc_entry);
1097 obd->obd_proc_entry = NULL;
1102 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1104 CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
1105 client_stat->nid_proc, client_stat->nid_stats,
1106 client_stat->nid_brw_stats);
1108 LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
1110 cfs_atomic_read(&client_stat->nid_exp_ref_count));
1112 cfs_hlist_del_init(&client_stat->nid_hash);
1114 if (client_stat->nid_proc)
1115 lprocfs_remove(&client_stat->nid_proc);
1117 if (client_stat->nid_stats)
1118 lprocfs_free_stats(&client_stat->nid_stats);
1120 if (client_stat->nid_brw_stats)
1121 OBD_FREE_PTR(client_stat->nid_brw_stats);
1123 if (client_stat->nid_ldlm_stats)
1124 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1126 OBD_FREE_PTR(client_stat);
1131 void lprocfs_free_per_client_stats(struct obd_device *obd)
1133 struct nid_stat *stat;
1136 /* we need extra list - because hash_exit called to early */
1137 /* not need locking because all clients is died */
1138 while(!cfs_list_empty(&obd->obd_nid_stats)) {
1139 stat = cfs_list_entry(obd->obd_nid_stats.next,
1140 struct nid_stat, nid_list);
1141 cfs_list_del_init(&stat->nid_list);
1142 lprocfs_free_client_stats(stat);
1148 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1149 enum lprocfs_stats_flags flags)
1151 struct lprocfs_stats *stats;
1152 unsigned int percpusize;
1154 unsigned int num_cpu;
1159 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1162 num_cpu = cfs_num_possible_cpus();
1164 OBD_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
1168 if (flags & LPROCFS_STATS_FLAG_NOPERCPU) {
1169 stats->ls_flags = flags;
1170 cfs_spin_lock_init(&stats->ls_lock);
1171 /* Use this lock only if there are no percpu areas */
1173 stats->ls_flags = 0;
1176 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
1178 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1180 for (i = 0; i < num_cpu; i++) {
1181 OBD_ALLOC(stats->ls_percpu[i], percpusize);
1182 if (stats->ls_percpu[i] == NULL) {
1183 for (j = 0; j < i; j++) {
1184 OBD_FREE(stats->ls_percpu[j], percpusize);
1185 stats->ls_percpu[j] = NULL;
1190 if (stats->ls_percpu[0] == NULL) {
1191 OBD_FREE(stats, offsetof(typeof(*stats),
1192 ls_percpu[num_cpu]));
1196 stats->ls_num = num;
1200 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1202 struct lprocfs_stats *stats = *statsh;
1203 unsigned int num_cpu;
1204 unsigned int percpusize;
1207 if (stats == NULL || stats->ls_num == 0)
1211 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1214 num_cpu = cfs_num_possible_cpus();
1216 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
1218 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1219 for (i = 0; i < num_cpu; i++)
1220 OBD_FREE(stats->ls_percpu[i], percpusize);
1221 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
1224 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1226 struct lprocfs_counter *percpu_cntr;
1228 unsigned int num_cpu;
1230 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1232 for (i = 0; i < num_cpu; i++) {
1233 for (j = 0; j < stats->ls_num; j++) {
1234 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
1235 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_entry);
1236 percpu_cntr->lc_count = 0;
1237 percpu_cntr->lc_sum = 0;
1238 percpu_cntr->lc_min = LC_MIN_INIT;
1239 percpu_cntr->lc_max = 0;
1240 percpu_cntr->lc_sumsquare = 0;
1241 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_exit);
1245 lprocfs_stats_unlock(stats);
1248 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1249 size_t len, loff_t *off)
1251 struct seq_file *seq = file->private_data;
1252 struct lprocfs_stats *stats = seq->private;
1254 lprocfs_clear_stats(stats);
1259 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1261 struct lprocfs_stats *stats = p->private;
1262 /* return 1st cpu location */
1263 return (*pos >= stats->ls_num) ? NULL :
1264 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1267 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1271 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1273 struct lprocfs_stats *stats = p->private;
1275 return (*pos >= stats->ls_num) ? NULL :
1276 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1279 /* seq file export of one lprocfs counter */
1280 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1282 struct lprocfs_stats *stats = p->private;
1283 struct lprocfs_counter *cntr = v;
1284 struct lprocfs_counter ret;
1287 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
1289 cfs_gettimeofday(&now);
1290 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1291 "snapshot_time", now.tv_sec, now.tv_usec);
1295 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
1297 lprocfs_stats_collect(stats, idx, &ret);
1299 if (ret.lc_count == 0)
1302 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", cntr->lc_name,
1303 ret.lc_count, cntr->lc_units);
1308 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
1309 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1310 ret.lc_min, ret.lc_max, ret.lc_sum);
1313 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
1314 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1318 rc = seq_printf(p, "\n");
1320 return (rc < 0) ? rc : 0;
1323 struct seq_operations lprocfs_stats_seq_sops = {
1324 start: lprocfs_stats_seq_start,
1325 stop: lprocfs_stats_seq_stop,
1326 next: lprocfs_stats_seq_next,
1327 show: lprocfs_stats_seq_show,
1330 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1332 struct proc_dir_entry *dp = PDE(inode);
1333 struct seq_file *seq;
1336 if (LPROCFS_ENTRY_AND_CHECK(dp))
1339 rc = seq_open(file, &lprocfs_stats_seq_sops);
1344 seq = file->private_data;
1345 seq->private = dp->data;
1349 struct file_operations lprocfs_stats_seq_fops = {
1350 .owner = THIS_MODULE,
1351 .open = lprocfs_stats_seq_open,
1353 .write = lprocfs_stats_seq_write,
1354 .llseek = seq_lseek,
1355 .release = lprocfs_seq_release,
1358 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1359 struct lprocfs_stats *stats)
1361 struct proc_dir_entry *entry;
1362 LASSERT(root != NULL);
1364 entry = create_proc_entry(name, 0644, root);
1367 entry->proc_fops = &lprocfs_stats_seq_fops;
1368 entry->data = stats;
1372 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1373 unsigned conf, const char *name, const char *units)
1375 struct lprocfs_counter *c;
1377 unsigned int num_cpu;
1379 LASSERT(stats != NULL);
1381 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1383 for (i = 0; i < num_cpu; i++) {
1384 c = &(stats->ls_percpu[i]->lp_cntr[index]);
1385 c->lc_config = conf;
1388 c->lc_min = LC_MIN_INIT;
1391 c->lc_units = units;
1394 lprocfs_stats_unlock(stats);
1396 EXPORT_SYMBOL(lprocfs_counter_init);
1398 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1400 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1401 LASSERT(coffset < stats->ls_num); \
1402 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1405 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1407 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1408 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1409 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1410 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1411 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1412 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1413 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1414 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1415 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1416 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1417 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1418 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1419 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1420 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1421 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1422 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1423 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1424 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1425 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
1426 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1427 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1428 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1429 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1430 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1431 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1432 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1433 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1434 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1435 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1436 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1437 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1438 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1439 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1440 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1441 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1442 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1443 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1444 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1445 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1446 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1447 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1448 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1449 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1450 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1451 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
1452 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1453 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1454 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1455 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1456 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1457 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1458 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1459 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1460 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1461 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1462 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1463 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1464 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1465 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1466 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1467 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1468 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quota_adjust_qunit);
1469 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1470 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1471 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1472 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1473 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1474 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1475 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1476 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync_fs);
1479 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1481 struct lprocfs_stats *stats;
1482 unsigned int num_stats;
1485 LASSERT(obd->obd_stats == NULL);
1486 LASSERT(obd->obd_proc_entry != NULL);
1487 LASSERT(obd->obd_cntr_base == 0);
1489 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1490 num_private_stats - 1 /* o_owner */;
1491 stats = lprocfs_alloc_stats(num_stats, 0);
1495 lprocfs_init_ops_stats(num_private_stats, stats);
1497 for (i = num_private_stats; i < num_stats; i++) {
1498 /* If this LBUGs, it is likely that an obd
1499 * operation was added to struct obd_ops in
1500 * <obd.h>, and that the corresponding line item
1501 * LPROCFS_OBD_OP_INIT(.., .., opname)
1502 * is missing from the list above. */
1503 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1504 "Missing obd_stat initializer obd_op "
1505 "operation at offset %d.\n", i - num_private_stats);
1507 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1509 lprocfs_free_stats(&stats);
1511 obd->obd_stats = stats;
1512 obd->obd_cntr_base = num_private_stats;
1517 void lprocfs_free_obd_stats(struct obd_device *obd)
1520 lprocfs_free_stats(&obd->obd_stats);
1523 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1525 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1526 LASSERT(coffset < stats->ls_num); \
1527 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1530 int lprocfs_alloc_md_stats(struct obd_device *obd,
1531 unsigned num_private_stats)
1533 struct lprocfs_stats *stats;
1534 unsigned int num_stats;
1537 LASSERT(obd->md_stats == NULL);
1538 LASSERT(obd->obd_proc_entry != NULL);
1539 LASSERT(obd->md_cntr_base == 0);
1541 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1543 stats = lprocfs_alloc_stats(num_stats, 0);
1547 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1548 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1549 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
1550 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1551 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1552 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1553 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1554 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1555 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1556 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1557 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1558 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1559 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1560 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1561 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1562 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1563 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1564 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1565 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1566 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1567 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1568 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1569 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1570 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1571 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1572 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1573 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1574 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1575 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1576 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1577 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1578 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1580 for (i = num_private_stats; i < num_stats; i++) {
1581 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1582 CERROR("Missing md_stat initializer md_op "
1583 "operation at offset %d. Aborting.\n",
1584 i - num_private_stats);
1588 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1590 lprocfs_free_stats(&stats);
1592 obd->md_stats = stats;
1593 obd->md_cntr_base = num_private_stats;
1598 void lprocfs_free_md_stats(struct obd_device *obd)
1600 struct lprocfs_stats *stats = obd->md_stats;
1602 if (stats != NULL) {
1603 obd->md_stats = NULL;
1604 obd->md_cntr_base = 0;
1605 lprocfs_free_stats(&stats);
1609 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1611 lprocfs_counter_init(ldlm_stats,
1612 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1613 0, "ldlm_enqueue", "reqs");
1614 lprocfs_counter_init(ldlm_stats,
1615 LDLM_CONVERT - LDLM_FIRST_OPC,
1616 0, "ldlm_convert", "reqs");
1617 lprocfs_counter_init(ldlm_stats,
1618 LDLM_CANCEL - LDLM_FIRST_OPC,
1619 0, "ldlm_cancel", "reqs");
1620 lprocfs_counter_init(ldlm_stats,
1621 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1622 0, "ldlm_bl_callback", "reqs");
1623 lprocfs_counter_init(ldlm_stats,
1624 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1625 0, "ldlm_cp_callback", "reqs");
1626 lprocfs_counter_init(ldlm_stats,
1627 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1628 0, "ldlm_gl_callback", "reqs");
1631 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1632 int *eof, void *data)
1634 struct obd_export *exp = data;
1635 LASSERT(exp != NULL);
1637 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1640 struct exp_uuid_cb_data {
1648 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1649 int count, int *eof, int *len)
1651 cb_data->page = page;
1652 cb_data->count = count;
1657 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1658 cfs_hlist_node_t *hnode, void *cb_data)
1661 struct obd_export *exp = cfs_hash_object(hs, hnode);
1662 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1664 if (exp->exp_nid_stats)
1665 *data->len += snprintf((data->page + *data->len),
1666 data->count, "%s\n",
1667 obd_uuid2str(&exp->exp_client_uuid));
1671 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1672 int *eof, void *data)
1674 struct nid_stat *stats = (struct nid_stat *)data;
1675 struct exp_uuid_cb_data cb_data;
1676 struct obd_device *obd = stats->nid_obd;
1681 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1682 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1683 lprocfs_exp_print_uuid, &cb_data);
1684 return (*cb_data.len);
1687 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1688 cfs_hlist_node_t *hnode, void *cb_data)
1691 struct exp_uuid_cb_data *data = cb_data;
1692 struct obd_export *exp = cfs_hash_object(hs, hnode);
1694 LASSERT(hs == exp->exp_lock_hash);
1696 *data->len += cfs_hash_debug_header(data->page,
1699 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1704 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1705 int *eof, void *data)
1707 struct nid_stat *stats = (struct nid_stat *)data;
1708 struct exp_uuid_cb_data cb_data;
1709 struct obd_device *obd = stats->nid_obd;
1714 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1716 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1717 lprocfs_exp_print_hash, &cb_data);
1718 return (*cb_data.len);
1721 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1722 int count, int *eof, void *data)
1725 return snprintf(page, count, "%s\n",
1726 "Write into this file to clear all nid stats and "
1727 "stale nid entries");
1729 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1731 int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1733 struct nid_stat *stat = obj;
1736 /* object has only hash + iterate_all references.
1737 * add/delete blocked by hash bucket lock */
1738 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
1739 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 2) {
1740 cfs_spin_lock(&stat->nid_obd->obd_nid_lock);
1741 cfs_list_move(&stat->nid_list, data);
1742 cfs_spin_unlock(&stat->nid_obd->obd_nid_lock);
1745 /* we has reference to object - only clear data*/
1746 if (stat->nid_stats)
1747 lprocfs_clear_stats(stat->nid_stats);
1749 if (stat->nid_brw_stats) {
1750 for (i = 0; i < BRW_LAST; i++)
1751 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
1756 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1757 unsigned long count, void *data)
1759 struct obd_device *obd = (struct obd_device *)data;
1760 struct nid_stat *client_stat;
1761 CFS_LIST_HEAD(free_list);
1763 cfs_hash_cond_del(obd->obd_nid_stats_hash,
1764 lprocfs_nid_stats_clear_write_cb, &free_list);
1766 while (!cfs_list_empty(&free_list)) {
1767 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
1769 cfs_list_del_init(&client_stat->nid_list);
1770 lprocfs_free_client_stats(client_stat);
1775 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1777 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int reconnect,
1780 struct nid_stat *new_stat, *old_stat;
1781 struct obd_device *obd = NULL;
1782 cfs_proc_dir_entry_t *entry;
1783 char *buffer = NULL;
1789 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1790 !exp->exp_obd->obd_nid_stats_hash)
1793 /* not test against zero because eric say:
1794 * You may only test nid against another nid, or LNET_NID_ANY.
1795 * Anything else is nonsense.*/
1796 if (!nid || *nid == LNET_NID_ANY)
1801 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
1803 OBD_ALLOC_PTR(new_stat);
1804 if (new_stat == NULL)
1807 new_stat->nid = *nid;
1808 new_stat->nid_obd = exp->exp_obd;
1809 /* we need set default refcount to 1 to balance obd_disconnect */
1810 cfs_atomic_set(&new_stat->nid_exp_ref_count, 1);
1812 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
1813 nid, &new_stat->nid_hash);
1814 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
1815 old_stat, libcfs_nid2str(*nid),
1816 cfs_atomic_read(&new_stat->nid_exp_ref_count));
1818 /* Return -EALREADY here so that we know that the /proc
1819 * entry already has been created */
1820 if (old_stat != new_stat) {
1821 /* if this connects to the existing export of same nid,
1822 * we need to release old stats for obd_disconnect won't
1823 * balance the reference gotten in "cfs_hash_findadd_uinque" */
1824 if (reconnect && exp->exp_nid_stats)
1825 nidstat_putref(old_stat);
1827 exp->exp_nid_stats = old_stat;
1828 GOTO(destroy_new, rc = -EALREADY);
1830 /* not found - create */
1831 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
1833 GOTO(destroy_new, rc = -ENOMEM);
1835 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
1836 new_stat->nid_proc = lprocfs_register(buffer,
1837 obd->obd_proc_exports_entry,
1839 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
1841 if (new_stat->nid_proc == NULL) {
1842 CERROR("Error making export directory for nid %s\n",
1843 libcfs_nid2str(*nid));
1844 GOTO(destroy_new_ns, rc = -ENOMEM);
1847 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
1848 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
1849 if (IS_ERR(entry)) {
1850 CWARN("Error adding the NID stats file\n");
1851 rc = PTR_ERR(entry);
1852 GOTO(destroy_new_ns, rc);
1855 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
1856 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
1857 if (IS_ERR(entry)) {
1858 CWARN("Error adding the hash file\n");
1859 rc = PTR_ERR(entry);
1860 GOTO(destroy_new_ns, rc);
1863 exp->exp_nid_stats = new_stat;
1865 /* protect competitive add to list, not need locking on destroy */
1866 cfs_spin_lock(&obd->obd_nid_lock);
1867 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
1868 cfs_spin_unlock(&obd->obd_nid_lock);
1873 if (new_stat->nid_proc != NULL)
1874 lprocfs_remove(&new_stat->nid_proc);
1875 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
1878 nidstat_putref(new_stat);
1879 OBD_FREE_PTR(new_stat);
1883 int lprocfs_exp_cleanup(struct obd_export *exp)
1885 struct nid_stat *stat = exp->exp_nid_stats;
1887 if(!stat || !exp->exp_obd)
1890 nidstat_putref(exp->exp_nid_stats);
1891 exp->exp_nid_stats = NULL;
1896 int lprocfs_write_helper(const char *buffer, unsigned long count,
1899 return lprocfs_write_frac_helper(buffer, count, val, 1);
1902 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
1905 char kernbuf[20], *end, *pbuf;
1907 if (count > (sizeof(kernbuf) - 1))
1910 if (cfs_copy_from_user(kernbuf, buffer, count))
1913 kernbuf[count] = '\0';
1920 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1924 if (end != NULL && *end == '.') {
1925 int temp_val, pow = 1;
1929 if (strlen(pbuf) > 5)
1930 pbuf[5] = '\0'; /*only allow 5bits fractional*/
1932 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1935 for (i = 0; i < (end - pbuf); i++)
1938 *val += temp_val / pow;
1944 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
1947 long decimal_val, frac_val;
1953 decimal_val = val / mult;
1954 prtn = snprintf(buffer, count, "%ld", decimal_val);
1955 frac_val = val % mult;
1957 if (prtn < (count - 4) && frac_val > 0) {
1959 int i, temp_mult = 1, frac_bits = 0;
1961 temp_frac = frac_val * 10;
1962 buffer[prtn++] = '.';
1963 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
1964 /* only reserved 2 bits fraction */
1965 buffer[prtn++] ='0';
1970 * Need to think these cases :
1971 * 1. #echo x.00 > /proc/xxx output result : x
1972 * 2. #echo x.0x > /proc/xxx output result : x.0x
1973 * 3. #echo x.x0 > /proc/xxx output result : x.x
1974 * 4. #echo x.xx > /proc/xxx output result : x.xx
1975 * Only reserved 2 bits fraction.
1977 for (i = 0; i < (5 - prtn); i++)
1980 frac_bits = min((int)count - prtn, 3 - frac_bits);
1981 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
1982 frac_val * temp_mult / mult);
1985 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
1987 if (buffer[prtn] == '.') {
1994 buffer[prtn++] ='\n';
1998 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
2000 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
2003 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
2004 __u64 *val, int mult)
2006 char kernbuf[22], *end, *pbuf;
2007 __u64 whole, frac = 0, units;
2008 unsigned frac_d = 1;
2010 if (count > (sizeof(kernbuf) - 1))
2013 if (cfs_copy_from_user(kernbuf, buffer, count))
2016 kernbuf[count] = '\0';
2023 whole = simple_strtoull(pbuf, &end, 10);
2027 if (end != NULL && *end == '.') {
2031 /* need to limit frac_d to a __u32 */
2032 if (strlen(pbuf) > 10)
2035 frac = simple_strtoull(pbuf, &end, 10);
2036 /* count decimal places */
2037 for (i = 0; i < (end - pbuf); i++)
2054 /* Specified units override the multiplier */
2056 mult = mult < 0 ? -units : units;
2059 do_div(frac, frac_d);
2060 *val = whole * mult + frac;
2064 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent, char *name, mode_t mode,
2065 struct file_operations *seq_fops, void *data)
2067 struct proc_dir_entry *entry;
2070 entry = create_proc_entry(name, mode, parent);
2073 entry->proc_fops = seq_fops;
2078 EXPORT_SYMBOL(lprocfs_seq_create);
2080 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
2082 struct file_operations *seq_fops,
2085 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2086 mode, seq_fops, data));
2088 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2090 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2092 if (value >= OBD_HIST_MAX)
2093 value = OBD_HIST_MAX - 1;
2095 cfs_spin_lock(&oh->oh_lock);
2096 oh->oh_buckets[value]++;
2097 cfs_spin_unlock(&oh->oh_lock);
2099 EXPORT_SYMBOL(lprocfs_oh_tally);
2101 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2105 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2108 lprocfs_oh_tally(oh, val);
2110 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2112 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2114 unsigned long ret = 0;
2117 for (i = 0; i < OBD_HIST_MAX; i++)
2118 ret += oh->oh_buckets[i];
2121 EXPORT_SYMBOL(lprocfs_oh_sum);
2123 void lprocfs_oh_clear(struct obd_histogram *oh)
2125 cfs_spin_lock(&oh->oh_lock);
2126 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2127 cfs_spin_unlock(&oh->oh_lock);
2129 EXPORT_SYMBOL(lprocfs_oh_clear);
2131 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2132 int count, int *eof, void *data)
2134 struct obd_device *obd = data;
2140 c += cfs_hash_debug_header(page, count);
2141 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2142 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2143 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2144 #ifdef HAVE_QUOTA_SUPPORT
2145 if (obd->u.obt.obt_qctxt.lqc_lqs_hash)
2146 c += cfs_hash_debug_str(obd->u.obt.obt_qctxt.lqc_lqs_hash,
2147 page + c, count - c);
2152 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2154 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2155 int count, int *eof, void *data)
2157 struct obd_device *obd = data;
2160 LASSERT(obd != NULL);
2161 LASSERT(count >= 0);
2163 /* Set start of user data returned to
2164 page + off since the user may have
2165 requested to read much smaller than
2166 what we need to read */
2167 *start = page + off;
2169 /* We know we are allocated a page here.
2170 Also we know that this function will
2171 not need to write more than a page
2172 so we can truncate at CFS_PAGE_SIZE. */
2173 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2175 /* Initialize the page */
2176 memset(page, 0, size);
2178 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2180 if (obd->obd_max_recoverable_clients == 0) {
2181 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2187 /* sampled unlocked, but really... */
2188 if (obd->obd_recovering == 0) {
2189 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2191 if (lprocfs_obd_snprintf(&page, size, &len,
2192 "recovery_start: %lu\n",
2193 obd->obd_recovery_start) <= 0)
2195 if (lprocfs_obd_snprintf(&page, size, &len,
2196 "recovery_duration: %lu\n",
2197 obd->obd_recovery_end -
2198 obd->obd_recovery_start) <= 0)
2200 /* Number of clients that have completed recovery */
2201 if (lprocfs_obd_snprintf(&page, size, &len,
2202 "completed_clients: %d/%d\n",
2203 obd->obd_max_recoverable_clients -
2204 obd->obd_stale_clients,
2205 obd->obd_max_recoverable_clients) <= 0)
2207 if (lprocfs_obd_snprintf(&page, size, &len,
2208 "replayed_requests: %d\n",
2209 obd->obd_replayed_requests) <= 0)
2211 if (lprocfs_obd_snprintf(&page, size, &len,
2212 "last_transno: "LPD64"\n",
2213 obd->obd_next_recovery_transno - 1)<=0)
2215 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2216 obd->obd_version_recov ? "ON" : "OFF")<=0)
2221 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2223 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2224 obd->obd_recovery_start) <= 0)
2226 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2227 cfs_time_current_sec() >= obd->obd_recovery_end ? 0 :
2228 obd->obd_recovery_end - cfs_time_current_sec()) <= 0)
2230 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2231 obd->obd_connected_clients,
2232 obd->obd_max_recoverable_clients) <= 0)
2234 /* Number of clients that have completed recovery */
2235 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2236 cfs_atomic_read(&obd->obd_req_replay_clients))
2239 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2240 cfs_atomic_read(&obd->obd_lock_replay_clients))
2243 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2244 obd->obd_connected_clients -
2245 cfs_atomic_read(&obd->obd_lock_replay_clients))
2248 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2249 obd->obd_stale_clients) <= 0)
2251 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2252 obd->obd_replayed_requests) <= 0)
2254 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2255 obd->obd_requests_queued_for_recovery) <= 0)
2258 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2259 obd->obd_next_recovery_transno) <= 0)
2265 return min(count, len - (int)off);
2267 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2269 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
2270 int count, int *eof, void *data)
2272 struct obd_device *obd = (struct obd_device *)data;
2273 LASSERT(obd != NULL);
2275 return snprintf(page, count, "%d\n",
2276 obd->obd_recovery_timeout);
2278 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
2280 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
2281 unsigned long count, void *data)
2283 struct obd_device *obd = (struct obd_device *)data;
2285 LASSERT(obd != NULL);
2287 rc = lprocfs_write_helper(buffer, count, &val);
2291 obd->obd_recovery_timeout = val;
2294 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
2296 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
2297 int count, int *eof, void *data)
2299 struct obd_device *obd = data;
2300 LASSERT(obd != NULL);
2302 return snprintf(page, count, "%lu\n", obd->obd_recovery_time_hard);
2304 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
2306 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
2307 unsigned long count, void *data)
2309 struct obd_device *obd = data;
2311 LASSERT(obd != NULL);
2313 rc = lprocfs_write_helper(buffer, count, &val);
2317 obd->obd_recovery_time_hard = val;
2320 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
2322 int lprocfs_obd_rd_mntdev(char *page, char **start, off_t off,
2323 int count, int *eof, void *data)
2325 struct obd_device *obd = (struct obd_device *)data;
2327 LASSERT(obd != NULL);
2328 LASSERT(obd->u.obt.obt_vfsmnt->mnt_devname);
2330 return snprintf(page, count, "%s\n",
2331 obd->u.obt.obt_vfsmnt->mnt_devname);
2333 EXPORT_SYMBOL(lprocfs_obd_rd_mntdev);
2335 EXPORT_SYMBOL(lprocfs_register);
2336 EXPORT_SYMBOL(lprocfs_srch);
2337 EXPORT_SYMBOL(lprocfs_remove);
2338 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
2339 EXPORT_SYMBOL(lprocfs_add_vars);
2340 EXPORT_SYMBOL(lprocfs_obd_setup);
2341 EXPORT_SYMBOL(lprocfs_obd_cleanup);
2342 EXPORT_SYMBOL(lprocfs_add_simple);
2343 EXPORT_SYMBOL(lprocfs_add_symlink);
2344 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
2345 EXPORT_SYMBOL(lprocfs_alloc_stats);
2346 EXPORT_SYMBOL(lprocfs_free_stats);
2347 EXPORT_SYMBOL(lprocfs_clear_stats);
2348 EXPORT_SYMBOL(lprocfs_register_stats);
2349 EXPORT_SYMBOL(lprocfs_init_ops_stats);
2350 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
2351 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
2352 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
2353 EXPORT_SYMBOL(lprocfs_free_obd_stats);
2354 EXPORT_SYMBOL(lprocfs_free_md_stats);
2355 EXPORT_SYMBOL(lprocfs_exp_setup);
2356 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2358 EXPORT_SYMBOL(lprocfs_rd_u64);
2359 EXPORT_SYMBOL(lprocfs_rd_atomic);
2360 EXPORT_SYMBOL(lprocfs_wr_atomic);
2361 EXPORT_SYMBOL(lprocfs_rd_uint);
2362 EXPORT_SYMBOL(lprocfs_wr_uint);
2363 EXPORT_SYMBOL(lprocfs_rd_uuid);
2364 EXPORT_SYMBOL(lprocfs_rd_name);
2365 EXPORT_SYMBOL(lprocfs_rd_fstype);
2366 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
2367 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
2368 EXPORT_SYMBOL(lprocfs_rd_num_exports);
2369 EXPORT_SYMBOL(lprocfs_rd_numrefs);
2370 EXPORT_SYMBOL(lprocfs_at_hist_helper);
2371 EXPORT_SYMBOL(lprocfs_rd_import);
2372 EXPORT_SYMBOL(lprocfs_rd_state);
2373 EXPORT_SYMBOL(lprocfs_rd_timeouts);
2374 EXPORT_SYMBOL(lprocfs_rd_blksize);
2375 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
2376 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
2377 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
2378 EXPORT_SYMBOL(lprocfs_rd_filestotal);
2379 EXPORT_SYMBOL(lprocfs_rd_filesfree);
2381 EXPORT_SYMBOL(lprocfs_write_helper);
2382 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2383 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2384 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2385 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2386 EXPORT_SYMBOL(lprocfs_stats_collect);