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);
730 flag2str(last_recon);
735 static const char *obd_connect_names[] = {
749 "join_file(obsolete)",
753 "remote_client_by_force",
762 "mds_mds_connection",
765 "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;
799 LASSERT(obd != NULL);
800 LPROCFS_CLIMP_CHECK(obd);
801 imp = obd->u.cli.cl_import;
804 i = snprintf(page, count,
808 " current_connection: %s\n"
813 imp->imp_connection->c_remote_uuid.uuid,
814 ptlrpc_import_state_name(imp->imp_state));
815 i += obd_connect_flags2str(page + i, count - i,
816 imp->imp_connect_data.ocd_connect_flags,
818 i += snprintf(page + i, count - i,
821 i += obd_import_flags2str(imp, page + i, count - i);
823 i += snprintf(page + i, count - i,
826 " connection_attempts: %u\n"
828 " in-progress_invalidations: %u\n",
831 cfs_atomic_read(&imp->imp_inval_count));
833 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
834 do_div(ret.lc_sum, ret.lc_count);
835 i += snprintf(page + i, count - i,
838 " unregistering: %u\n"
840 " avg_waittime: "LPU64" %s\n",
841 cfs_atomic_read(&imp->imp_inflight),
842 cfs_atomic_read(&imp->imp_unregistering),
843 cfs_atomic_read(&imp->imp_timeouts),
844 ret.lc_sum, ret.lc_units);
847 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
848 if (imp->imp_at.iat_portal[j] == 0)
850 k = max_t(unsigned int, k,
851 at_get(&imp->imp_at.iat_service_estimate[j]));
853 i += snprintf(page + i, count - i,
854 " service_estimates:\n"
855 " services: %u sec\n"
856 " network: %u sec\n",
858 at_get(&imp->imp_at.iat_net_latency));
860 i += snprintf(page + i, count - i,
862 " last_replay: "LPU64"\n"
863 " peer_committed: "LPU64"\n"
864 " last_checked: "LPU64"\n",
865 imp->imp_last_replay_transno,
866 imp->imp_peer_committed_transno,
867 imp->imp_last_transno_checked);
870 for (rw = 0; rw <= 1; rw++) {
871 lprocfs_stats_collect(obd->obd_svc_stats,
872 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
874 if (ret.lc_sum > 0) {
875 do_div(ret.lc_sum, ret.lc_count);
876 i += snprintf(page + i, count - i,
877 " %s_data_averages:\n"
878 " bytes_per_rpc: "LPU64"\n",
879 rw ? "write" : "read",
883 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
884 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
885 if (ret.lc_sum > 0) {
886 do_div(ret.lc_sum, ret.lc_count);
887 i += snprintf(page + i, count - i,
888 " %s_per_rpc: "LPU64"\n",
889 ret.lc_units, ret.lc_sum);
892 i += snprintf(page + i, count - i,
893 " MB_per_sec: %u.%.02u\n",
894 k / j, (100 * k / j) % 100);
898 LPROCFS_CLIMP_EXIT(obd);
902 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
903 int *eof, void *data)
905 struct obd_device *obd = (struct obd_device *)data;
906 struct obd_import *imp;
909 LASSERT(obd != NULL);
910 LPROCFS_CLIMP_CHECK(obd);
911 imp = obd->u.cli.cl_import;
914 i = snprintf(page, count, "current_state: %s\n",
915 ptlrpc_import_state_name(imp->imp_state));
916 i += snprintf(page + i, count - i,
918 k = imp->imp_state_hist_idx;
919 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
920 struct import_state_hist *ish =
921 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
922 if (ish->ish_state == 0)
924 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
926 ptlrpc_import_state_name(ish->ish_state));
929 LPROCFS_CLIMP_EXIT(obd);
933 int lprocfs_at_hist_helper(char *page, int count, int rc,
934 struct adaptive_timeout *at)
937 for (i = 0; i < AT_BINS; i++)
938 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
939 rc += snprintf(page + rc, count - rc, "\n");
943 /* See also ptlrpc_lprocfs_rd_timeouts */
944 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
945 int *eof, void *data)
947 struct obd_device *obd = (struct obd_device *)data;
948 struct obd_import *imp;
949 unsigned int cur, worst;
954 LASSERT(obd != NULL);
955 LPROCFS_CLIMP_CHECK(obd);
956 imp = obd->u.cli.cl_import;
959 now = cfs_time_current_sec();
961 /* Some network health info for kicks */
962 s2dhms(&ts, now - imp->imp_last_reply_time);
963 rc += snprintf(page + rc, count - rc,
964 "%-10s : %ld, "DHMS_FMT" ago\n",
965 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
967 cur = at_get(&imp->imp_at.iat_net_latency);
968 worst = imp->imp_at.iat_net_latency.at_worst_ever;
969 worstt = imp->imp_at.iat_net_latency.at_worst_time;
970 s2dhms(&ts, now - worstt);
971 rc += snprintf(page + rc, count - rc,
972 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
973 "network", cur, worst, worstt, DHMS_VARS(&ts));
974 rc = lprocfs_at_hist_helper(page, count, rc,
975 &imp->imp_at.iat_net_latency);
977 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
978 if (imp->imp_at.iat_portal[i] == 0)
980 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
981 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
982 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
983 s2dhms(&ts, now - worstt);
984 rc += snprintf(page + rc, count - rc,
985 "portal %-2d : cur %3u worst %3u (at %ld, "
986 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
987 cur, worst, worstt, DHMS_VARS(&ts));
988 rc = lprocfs_at_hist_helper(page, count, rc,
989 &imp->imp_at.iat_service_estimate[i]);
992 LPROCFS_CLIMP_EXIT(obd);
996 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
997 int count, int *eof, void *data)
999 struct obd_device *obd = data;
1003 LPROCFS_CLIMP_CHECK(obd);
1004 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1005 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1006 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1007 ret += snprintf(page + ret, count - ret, "\n");
1008 LPROCFS_CLIMP_EXIT(obd);
1011 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1013 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1014 int *eof, void *data)
1016 struct obd_device *obd = data;
1018 LASSERT(obd != NULL);
1020 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1023 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1024 int *eof, void *data)
1026 struct obd_type *class = (struct obd_type*) data;
1028 LASSERT(class != NULL);
1030 return snprintf(page, count, "%d\n", class->typ_refcnt);
1033 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1037 LASSERT(obd != NULL);
1038 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1039 LASSERT(obd->obd_type->typ_procroot != NULL);
1041 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1042 obd->obd_type->typ_procroot,
1044 if (IS_ERR(obd->obd_proc_entry)) {
1045 rc = PTR_ERR(obd->obd_proc_entry);
1046 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1047 obd->obd_proc_entry = NULL;
1052 int lprocfs_obd_cleanup(struct obd_device *obd)
1056 if (obd->obd_proc_exports_entry) {
1057 /* Should be no exports left */
1058 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1059 lprocfs_remove(&obd->obd_proc_exports_entry);
1060 obd->obd_proc_exports_entry = NULL;
1062 if (obd->obd_proc_entry) {
1063 lprocfs_remove(&obd->obd_proc_entry);
1064 obd->obd_proc_entry = NULL;
1069 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1071 CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
1072 client_stat->nid_proc, client_stat->nid_stats,
1073 client_stat->nid_brw_stats);
1075 LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
1077 cfs_atomic_read(&client_stat->nid_exp_ref_count));
1079 cfs_hlist_del_init(&client_stat->nid_hash);
1081 if (client_stat->nid_proc)
1082 lprocfs_remove(&client_stat->nid_proc);
1084 if (client_stat->nid_stats)
1085 lprocfs_free_stats(&client_stat->nid_stats);
1087 if (client_stat->nid_brw_stats)
1088 OBD_FREE_PTR(client_stat->nid_brw_stats);
1090 if (client_stat->nid_ldlm_stats)
1091 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1093 OBD_FREE_PTR(client_stat);
1098 void lprocfs_free_per_client_stats(struct obd_device *obd)
1100 struct nid_stat *stat;
1103 /* we need extra list - because hash_exit called to early */
1104 /* not need locking because all clients is died */
1105 while(!cfs_list_empty(&obd->obd_nid_stats)) {
1106 stat = cfs_list_entry(obd->obd_nid_stats.next,
1107 struct nid_stat, nid_list);
1108 cfs_list_del_init(&stat->nid_list);
1109 lprocfs_free_client_stats(stat);
1115 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1116 enum lprocfs_stats_flags flags)
1118 struct lprocfs_stats *stats;
1119 unsigned int percpusize;
1121 unsigned int num_cpu;
1126 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1129 num_cpu = cfs_num_possible_cpus();
1131 OBD_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
1135 if (flags & LPROCFS_STATS_FLAG_NOPERCPU) {
1136 stats->ls_flags = flags;
1137 cfs_spin_lock_init(&stats->ls_lock);
1138 /* Use this lock only if there are no percpu areas */
1140 stats->ls_flags = 0;
1143 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
1145 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1147 for (i = 0; i < num_cpu; i++) {
1148 OBD_ALLOC(stats->ls_percpu[i], percpusize);
1149 if (stats->ls_percpu[i] == NULL) {
1150 for (j = 0; j < i; j++) {
1151 OBD_FREE(stats->ls_percpu[j], percpusize);
1152 stats->ls_percpu[j] = NULL;
1157 if (stats->ls_percpu[0] == NULL) {
1158 OBD_FREE(stats, offsetof(typeof(*stats),
1159 ls_percpu[num_cpu]));
1163 stats->ls_num = num;
1167 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1169 struct lprocfs_stats *stats = *statsh;
1170 unsigned int num_cpu;
1171 unsigned int percpusize;
1174 if (stats == NULL || stats->ls_num == 0)
1178 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1181 num_cpu = cfs_num_possible_cpus();
1183 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
1185 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1186 for (i = 0; i < num_cpu; i++)
1187 OBD_FREE(stats->ls_percpu[i], percpusize);
1188 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
1191 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1193 struct lprocfs_counter *percpu_cntr;
1195 unsigned int num_cpu;
1197 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1199 for (i = 0; i < num_cpu; i++) {
1200 for (j = 0; j < stats->ls_num; j++) {
1201 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
1202 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_entry);
1203 percpu_cntr->lc_count = 0;
1204 percpu_cntr->lc_sum = 0;
1205 percpu_cntr->lc_min = LC_MIN_INIT;
1206 percpu_cntr->lc_max = 0;
1207 percpu_cntr->lc_sumsquare = 0;
1208 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_exit);
1212 lprocfs_stats_unlock(stats);
1215 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1216 size_t len, loff_t *off)
1218 struct seq_file *seq = file->private_data;
1219 struct lprocfs_stats *stats = seq->private;
1221 lprocfs_clear_stats(stats);
1226 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1228 struct lprocfs_stats *stats = p->private;
1229 /* return 1st cpu location */
1230 return (*pos >= stats->ls_num) ? NULL :
1231 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1234 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1238 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1240 struct lprocfs_stats *stats = p->private;
1242 return (*pos >= stats->ls_num) ? NULL :
1243 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1246 /* seq file export of one lprocfs counter */
1247 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1249 struct lprocfs_stats *stats = p->private;
1250 struct lprocfs_counter *cntr = v;
1251 struct lprocfs_counter ret;
1254 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
1256 cfs_gettimeofday(&now);
1257 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1258 "snapshot_time", now.tv_sec, now.tv_usec);
1262 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
1264 lprocfs_stats_collect(stats, idx, &ret);
1266 if (ret.lc_count == 0)
1269 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", cntr->lc_name,
1270 ret.lc_count, cntr->lc_units);
1275 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
1276 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1277 ret.lc_min, ret.lc_max, ret.lc_sum);
1280 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
1281 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1285 rc = seq_printf(p, "\n");
1287 return (rc < 0) ? rc : 0;
1290 struct seq_operations lprocfs_stats_seq_sops = {
1291 start: lprocfs_stats_seq_start,
1292 stop: lprocfs_stats_seq_stop,
1293 next: lprocfs_stats_seq_next,
1294 show: lprocfs_stats_seq_show,
1297 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1299 struct proc_dir_entry *dp = PDE(inode);
1300 struct seq_file *seq;
1303 if (LPROCFS_ENTRY_AND_CHECK(dp))
1306 rc = seq_open(file, &lprocfs_stats_seq_sops);
1311 seq = file->private_data;
1312 seq->private = dp->data;
1316 struct file_operations lprocfs_stats_seq_fops = {
1317 .owner = THIS_MODULE,
1318 .open = lprocfs_stats_seq_open,
1320 .write = lprocfs_stats_seq_write,
1321 .llseek = seq_lseek,
1322 .release = lprocfs_seq_release,
1325 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1326 struct lprocfs_stats *stats)
1328 struct proc_dir_entry *entry;
1329 LASSERT(root != NULL);
1331 entry = create_proc_entry(name, 0644, root);
1334 entry->proc_fops = &lprocfs_stats_seq_fops;
1335 entry->data = stats;
1339 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1340 unsigned conf, const char *name, const char *units)
1342 struct lprocfs_counter *c;
1344 unsigned int num_cpu;
1346 LASSERT(stats != NULL);
1348 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1350 for (i = 0; i < num_cpu; i++) {
1351 c = &(stats->ls_percpu[i]->lp_cntr[index]);
1352 c->lc_config = conf;
1355 c->lc_min = LC_MIN_INIT;
1358 c->lc_units = units;
1361 lprocfs_stats_unlock(stats);
1363 EXPORT_SYMBOL(lprocfs_counter_init);
1365 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1367 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1368 LASSERT(coffset < stats->ls_num); \
1369 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1372 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1374 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1375 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1376 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1377 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1378 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1379 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1380 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1381 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1382 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1383 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1384 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1385 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1386 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1387 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1388 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1389 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1390 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1391 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1392 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
1393 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1394 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1395 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1396 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1397 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1398 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1399 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1400 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1401 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1402 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1403 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1404 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1405 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1406 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1407 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1408 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1409 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1410 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1411 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1412 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1413 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1414 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1415 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1416 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1417 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1418 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
1419 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1420 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1421 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1422 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1423 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1424 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1425 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1426 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1427 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1428 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1429 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1430 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1431 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1432 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1433 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1434 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1435 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quota_adjust_qunit);
1436 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1437 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1438 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1439 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1440 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1441 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1442 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1445 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1447 struct lprocfs_stats *stats;
1448 unsigned int num_stats;
1451 LASSERT(obd->obd_stats == NULL);
1452 LASSERT(obd->obd_proc_entry != NULL);
1453 LASSERT(obd->obd_cntr_base == 0);
1455 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1456 num_private_stats - 1 /* o_owner */;
1457 stats = lprocfs_alloc_stats(num_stats, 0);
1461 lprocfs_init_ops_stats(num_private_stats, stats);
1463 for (i = num_private_stats; i < num_stats; i++) {
1464 /* If this LBUGs, it is likely that an obd
1465 * operation was added to struct obd_ops in
1466 * <obd.h>, and that the corresponding line item
1467 * LPROCFS_OBD_OP_INIT(.., .., opname)
1468 * is missing from the list above. */
1469 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1470 "Missing obd_stat initializer obd_op "
1471 "operation at offset %d.\n", i - num_private_stats);
1473 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1475 lprocfs_free_stats(&stats);
1477 obd->obd_stats = stats;
1478 obd->obd_cntr_base = num_private_stats;
1483 void lprocfs_free_obd_stats(struct obd_device *obd)
1486 lprocfs_free_stats(&obd->obd_stats);
1489 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1491 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1492 LASSERT(coffset < stats->ls_num); \
1493 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1496 int lprocfs_alloc_md_stats(struct obd_device *obd,
1497 unsigned num_private_stats)
1499 struct lprocfs_stats *stats;
1500 unsigned int num_stats;
1503 LASSERT(obd->md_stats == NULL);
1504 LASSERT(obd->obd_proc_entry != NULL);
1505 LASSERT(obd->md_cntr_base == 0);
1507 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1509 stats = lprocfs_alloc_stats(num_stats, 0);
1513 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1514 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1515 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
1516 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1517 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1518 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1519 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1520 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1521 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1522 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1523 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1524 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1525 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1526 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1527 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1528 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1529 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1530 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1531 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1532 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1533 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1534 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1535 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1536 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1537 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1538 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1539 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1540 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1541 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1542 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1543 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1544 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1546 for (i = num_private_stats; i < num_stats; i++) {
1547 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1548 CERROR("Missing md_stat initializer md_op "
1549 "operation at offset %d. Aborting.\n",
1550 i - num_private_stats);
1554 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1556 lprocfs_free_stats(&stats);
1558 obd->md_stats = stats;
1559 obd->md_cntr_base = num_private_stats;
1564 void lprocfs_free_md_stats(struct obd_device *obd)
1566 struct lprocfs_stats *stats = obd->md_stats;
1568 if (stats != NULL) {
1569 obd->md_stats = NULL;
1570 obd->md_cntr_base = 0;
1571 lprocfs_free_stats(&stats);
1575 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1577 lprocfs_counter_init(ldlm_stats,
1578 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1579 0, "ldlm_enqueue", "reqs");
1580 lprocfs_counter_init(ldlm_stats,
1581 LDLM_CONVERT - LDLM_FIRST_OPC,
1582 0, "ldlm_convert", "reqs");
1583 lprocfs_counter_init(ldlm_stats,
1584 LDLM_CANCEL - LDLM_FIRST_OPC,
1585 0, "ldlm_cancel", "reqs");
1586 lprocfs_counter_init(ldlm_stats,
1587 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1588 0, "ldlm_bl_callback", "reqs");
1589 lprocfs_counter_init(ldlm_stats,
1590 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1591 0, "ldlm_cp_callback", "reqs");
1592 lprocfs_counter_init(ldlm_stats,
1593 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1594 0, "ldlm_gl_callback", "reqs");
1597 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1598 int *eof, void *data)
1600 struct obd_export *exp = data;
1601 LASSERT(exp != NULL);
1603 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1606 struct exp_uuid_cb_data {
1614 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1615 int count, int *eof, int *len)
1617 cb_data->page = page;
1618 cb_data->count = count;
1623 void lprocfs_exp_print_uuid(void *obj, void *cb_data)
1625 struct obd_export *exp = (struct obd_export *)obj;
1626 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1628 if (exp->exp_nid_stats)
1629 *data->len += snprintf((data->page + *data->len),
1630 data->count, "%s\n",
1631 obd_uuid2str(&exp->exp_client_uuid));
1634 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1635 int *eof, void *data)
1637 struct nid_stat *stats = (struct nid_stat *)data;
1638 struct exp_uuid_cb_data cb_data;
1639 struct obd_device *obd = stats->nid_obd;
1644 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1645 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1646 lprocfs_exp_print_uuid, &cb_data);
1647 return (*cb_data.len);
1650 void lprocfs_exp_print_hash(void *obj, void *cb_data)
1652 struct exp_uuid_cb_data *data = cb_data;
1653 struct obd_export *exp = obj;
1656 hs = exp->exp_lock_hash;
1659 *data->len += cfs_hash_debug_header(data->page,
1662 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1667 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1668 int *eof, void *data)
1670 struct nid_stat *stats = (struct nid_stat *)data;
1671 struct exp_uuid_cb_data cb_data;
1672 struct obd_device *obd = stats->nid_obd;
1677 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1679 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1680 lprocfs_exp_print_hash, &cb_data);
1681 return (*cb_data.len);
1684 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1685 int count, int *eof, void *data)
1688 return snprintf(page, count, "%s\n",
1689 "Write into this file to clear all nid stats and "
1690 "stale nid entries");
1692 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1694 void lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1696 struct nid_stat *stat = obj;
1699 /* object has only hash + iterate_all references.
1700 * add/delete blocked by hash bucket lock */
1701 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
1702 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 2) {
1703 cfs_hlist_del_init(&stat->nid_hash);
1704 nidstat_putref(stat);
1705 cfs_spin_lock(&stat->nid_obd->obd_nid_lock);
1706 cfs_list_move(&stat->nid_list, data);
1707 cfs_spin_unlock(&stat->nid_obd->obd_nid_lock);
1711 /* we has reference to object - only clear data*/
1712 if (stat->nid_stats)
1713 lprocfs_clear_stats(stat->nid_stats);
1715 if (stat->nid_brw_stats) {
1716 for (i = 0; i < BRW_LAST; i++)
1717 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
1723 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1724 unsigned long count, void *data)
1726 struct obd_device *obd = (struct obd_device *)data;
1727 struct nid_stat *client_stat;
1728 CFS_LIST_HEAD(free_list);
1730 cfs_hash_for_each(obd->obd_nid_stats_hash,
1731 lprocfs_nid_stats_clear_write_cb, &free_list);
1733 while (!cfs_list_empty(&free_list)) {
1734 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
1736 cfs_list_del_init(&client_stat->nid_list);
1737 lprocfs_free_client_stats(client_stat);
1742 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1744 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1746 struct nid_stat *new_stat, *old_stat;
1747 struct obd_device *obd = NULL;
1748 cfs_proc_dir_entry_t *entry;
1749 char *buffer = NULL;
1755 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1756 !exp->exp_obd->obd_nid_stats_hash)
1759 /* not test against zero because eric say:
1760 * You may only test nid against another nid, or LNET_NID_ANY.
1761 * Anything else is nonsense.*/
1762 if (!nid || *nid == LNET_NID_ANY)
1767 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
1769 OBD_ALLOC_PTR(new_stat);
1770 if (new_stat == NULL)
1773 new_stat->nid = *nid;
1774 new_stat->nid_obd = exp->exp_obd;
1775 cfs_atomic_set(&new_stat->nid_exp_ref_count, 0);
1777 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
1778 nid, &new_stat->nid_hash);
1779 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
1780 old_stat, libcfs_nid2str(*nid),
1781 cfs_atomic_read(&new_stat->nid_exp_ref_count));
1783 /* Return -EALREADY here so that we know that the /proc
1784 * entry already has been created */
1785 if (old_stat != new_stat) {
1786 cfs_spin_lock(&obd->obd_nid_lock);
1787 if (exp->exp_nid_stats != old_stat) {
1788 if (exp->exp_nid_stats)
1789 nidstat_putref(exp->exp_nid_stats);
1790 exp->exp_nid_stats = old_stat;
1792 /* cfs_hash_findadd_unique() has added
1793 * old_stat's refcount */
1794 nidstat_putref(old_stat);
1797 cfs_spin_unlock(&obd->obd_nid_lock);
1799 GOTO(destroy_new, rc = -EALREADY);
1801 /* not found - create */
1802 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
1804 GOTO(destroy_new, rc = -ENOMEM);
1806 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
1807 new_stat->nid_proc = lprocfs_register(buffer,
1808 obd->obd_proc_exports_entry,
1810 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
1812 if (new_stat->nid_proc == NULL) {
1813 CERROR("Error making export directory for nid %s\n",
1814 libcfs_nid2str(*nid));
1815 GOTO(destroy_new_ns, rc = -ENOMEM);
1818 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
1819 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
1820 if (IS_ERR(entry)) {
1821 CWARN("Error adding the NID stats file\n");
1822 rc = PTR_ERR(entry);
1823 GOTO(destroy_new_ns, rc);
1826 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
1827 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
1828 if (IS_ERR(entry)) {
1829 CWARN("Error adding the hash file\n");
1830 rc = PTR_ERR(entry);
1831 GOTO(destroy_new_ns, rc);
1834 if (exp->exp_nid_stats)
1835 nidstat_putref(exp->exp_nid_stats);
1836 nidstat_getref(new_stat);
1837 exp->exp_nid_stats = new_stat;
1839 /* protect competitive add to list, not need locking on destroy */
1840 cfs_spin_lock(&obd->obd_nid_lock);
1841 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
1842 cfs_spin_unlock(&obd->obd_nid_lock);
1847 if (new_stat->nid_proc != NULL)
1848 lprocfs_remove(&new_stat->nid_proc);
1849 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
1852 OBD_FREE_PTR(new_stat);
1856 int lprocfs_exp_cleanup(struct obd_export *exp)
1858 struct nid_stat *stat = exp->exp_nid_stats;
1860 if(!stat || !exp->exp_obd)
1863 nidstat_putref(exp->exp_nid_stats);
1864 exp->exp_nid_stats = NULL;
1869 int lprocfs_write_helper(const char *buffer, unsigned long count,
1872 return lprocfs_write_frac_helper(buffer, count, val, 1);
1875 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
1878 char kernbuf[20], *end, *pbuf;
1880 if (count > (sizeof(kernbuf) - 1))
1883 if (cfs_copy_from_user(kernbuf, buffer, count))
1886 kernbuf[count] = '\0';
1893 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1897 if (end != NULL && *end == '.') {
1898 int temp_val, pow = 1;
1902 if (strlen(pbuf) > 5)
1903 pbuf[5] = '\0'; /*only allow 5bits fractional*/
1905 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1908 for (i = 0; i < (end - pbuf); i++)
1911 *val += temp_val / pow;
1917 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
1920 long decimal_val, frac_val;
1926 decimal_val = val / mult;
1927 prtn = snprintf(buffer, count, "%ld", decimal_val);
1928 frac_val = val % mult;
1930 if (prtn < (count - 4) && frac_val > 0) {
1932 int i, temp_mult = 1, frac_bits = 0;
1934 temp_frac = frac_val * 10;
1935 buffer[prtn++] = '.';
1936 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
1937 /* only reserved 2 bits fraction */
1938 buffer[prtn++] ='0';
1943 * Need to think these cases :
1944 * 1. #echo x.00 > /proc/xxx output result : x
1945 * 2. #echo x.0x > /proc/xxx output result : x.0x
1946 * 3. #echo x.x0 > /proc/xxx output result : x.x
1947 * 4. #echo x.xx > /proc/xxx output result : x.xx
1948 * Only reserved 2 bits fraction.
1950 for (i = 0; i < (5 - prtn); i++)
1953 frac_bits = min((int)count - prtn, 3 - frac_bits);
1954 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
1955 frac_val * temp_mult / mult);
1958 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
1960 if (buffer[prtn] == '.') {
1967 buffer[prtn++] ='\n';
1971 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
1973 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
1976 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
1977 __u64 *val, int mult)
1979 char kernbuf[22], *end, *pbuf;
1980 __u64 whole, frac = 0, units;
1981 unsigned frac_d = 1;
1983 if (count > (sizeof(kernbuf) - 1))
1986 if (cfs_copy_from_user(kernbuf, buffer, count))
1989 kernbuf[count] = '\0';
1996 whole = simple_strtoull(pbuf, &end, 10);
2000 if (end != NULL && *end == '.') {
2004 /* need to limit frac_d to a __u32 */
2005 if (strlen(pbuf) > 10)
2008 frac = simple_strtoull(pbuf, &end, 10);
2009 /* count decimal places */
2010 for (i = 0; i < (end - pbuf); i++)
2027 /* Specified units override the multiplier */
2029 mult = mult < 0 ? -units : units;
2032 do_div(frac, frac_d);
2033 *val = whole * mult + frac;
2037 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent, char *name, mode_t mode,
2038 struct file_operations *seq_fops, void *data)
2040 struct proc_dir_entry *entry;
2043 entry = create_proc_entry(name, mode, parent);
2046 entry->proc_fops = seq_fops;
2051 EXPORT_SYMBOL(lprocfs_seq_create);
2053 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
2055 struct file_operations *seq_fops,
2058 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2059 mode, seq_fops, data));
2061 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2063 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2065 if (value >= OBD_HIST_MAX)
2066 value = OBD_HIST_MAX - 1;
2068 cfs_spin_lock(&oh->oh_lock);
2069 oh->oh_buckets[value]++;
2070 cfs_spin_unlock(&oh->oh_lock);
2072 EXPORT_SYMBOL(lprocfs_oh_tally);
2074 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2078 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2081 lprocfs_oh_tally(oh, val);
2083 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2085 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2087 unsigned long ret = 0;
2090 for (i = 0; i < OBD_HIST_MAX; i++)
2091 ret += oh->oh_buckets[i];
2094 EXPORT_SYMBOL(lprocfs_oh_sum);
2096 void lprocfs_oh_clear(struct obd_histogram *oh)
2098 cfs_spin_lock(&oh->oh_lock);
2099 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2100 cfs_spin_unlock(&oh->oh_lock);
2102 EXPORT_SYMBOL(lprocfs_oh_clear);
2104 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2105 int count, int *eof, void *data)
2107 struct obd_device *obd = data;
2113 c += cfs_hash_debug_header(page, count);
2114 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2115 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2116 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2120 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2122 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2123 int count, int *eof, void *data)
2125 struct obd_device *obd = data;
2128 LASSERT(obd != NULL);
2129 LASSERT(count >= 0);
2131 /* Set start of user data returned to
2132 page + off since the user may have
2133 requested to read much smaller than
2134 what we need to read */
2135 *start = page + off;
2137 /* We know we are allocated a page here.
2138 Also we know that this function will
2139 not need to write more than a page
2140 so we can truncate at CFS_PAGE_SIZE. */
2141 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2143 /* Initialize the page */
2144 memset(page, 0, size);
2146 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2148 if (obd->obd_max_recoverable_clients == 0) {
2149 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2155 /* sampled unlocked, but really... */
2156 if (obd->obd_recovering == 0) {
2157 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2159 if (lprocfs_obd_snprintf(&page, size, &len,
2160 "recovery_start: %lu\n",
2161 obd->obd_recovery_start) <= 0)
2163 if (lprocfs_obd_snprintf(&page, size, &len,
2164 "recovery_duration: %lu\n",
2165 obd->obd_recovery_end -
2166 obd->obd_recovery_start) <= 0)
2168 /* Number of clients that have completed recovery */
2169 if (lprocfs_obd_snprintf(&page, size, &len,
2170 "completed_clients: %d/%d\n",
2171 obd->obd_max_recoverable_clients -
2172 obd->obd_stale_clients,
2173 obd->obd_max_recoverable_clients) <= 0)
2175 if (lprocfs_obd_snprintf(&page, size, &len,
2176 "replayed_requests: %d\n",
2177 obd->obd_replayed_requests) <= 0)
2179 if (lprocfs_obd_snprintf(&page, size, &len,
2180 "last_transno: "LPD64"\n",
2181 obd->obd_next_recovery_transno - 1)<=0)
2183 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2184 obd->obd_version_recov ? "ON" : "OFF")<=0)
2189 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2191 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2192 obd->obd_recovery_start) <= 0)
2194 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2195 cfs_time_current_sec() >= obd->obd_recovery_end ? 0 :
2196 obd->obd_recovery_end - cfs_time_current_sec()) <= 0)
2198 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2199 obd->obd_connected_clients,
2200 obd->obd_max_recoverable_clients) <= 0)
2202 /* Number of clients that have completed recovery */
2203 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2204 cfs_atomic_read(&obd->obd_req_replay_clients))
2207 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2208 cfs_atomic_read(&obd->obd_lock_replay_clients))
2211 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2212 obd->obd_connected_clients -
2213 cfs_atomic_read(&obd->obd_lock_replay_clients))
2216 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2217 obd->obd_stale_clients) <= 0)
2219 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2220 obd->obd_replayed_requests) <= 0)
2222 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2223 obd->obd_requests_queued_for_recovery) <= 0)
2226 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2227 obd->obd_next_recovery_transno) <= 0)
2233 return min(count, len - (int)off);
2235 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2237 int lprocfs_obd_rd_recovery_maxtime(char *page, char **start, off_t off,
2238 int count, int *eof, void *data)
2240 struct obd_device *obd = data;
2241 LASSERT(obd != NULL);
2243 return snprintf(page, count, "%lu\n", obd->obd_recovery_max_time);
2245 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_maxtime);
2247 int lprocfs_obd_wr_recovery_maxtime(struct file *file, const char *buffer,
2248 unsigned long count, void *data)
2250 struct obd_device *obd = data;
2252 LASSERT(obd != NULL);
2254 rc = lprocfs_write_helper(buffer, count, &val);
2258 obd->obd_recovery_max_time = val;
2261 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_maxtime);
2264 EXPORT_SYMBOL(lprocfs_register);
2265 EXPORT_SYMBOL(lprocfs_srch);
2266 EXPORT_SYMBOL(lprocfs_remove);
2267 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
2268 EXPORT_SYMBOL(lprocfs_add_vars);
2269 EXPORT_SYMBOL(lprocfs_obd_setup);
2270 EXPORT_SYMBOL(lprocfs_obd_cleanup);
2271 EXPORT_SYMBOL(lprocfs_add_simple);
2272 EXPORT_SYMBOL(lprocfs_add_symlink);
2273 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
2274 EXPORT_SYMBOL(lprocfs_alloc_stats);
2275 EXPORT_SYMBOL(lprocfs_free_stats);
2276 EXPORT_SYMBOL(lprocfs_clear_stats);
2277 EXPORT_SYMBOL(lprocfs_register_stats);
2278 EXPORT_SYMBOL(lprocfs_init_ops_stats);
2279 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
2280 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
2281 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
2282 EXPORT_SYMBOL(lprocfs_free_obd_stats);
2283 EXPORT_SYMBOL(lprocfs_free_md_stats);
2284 EXPORT_SYMBOL(lprocfs_exp_setup);
2285 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2287 EXPORT_SYMBOL(lprocfs_rd_u64);
2288 EXPORT_SYMBOL(lprocfs_rd_atomic);
2289 EXPORT_SYMBOL(lprocfs_wr_atomic);
2290 EXPORT_SYMBOL(lprocfs_rd_uint);
2291 EXPORT_SYMBOL(lprocfs_wr_uint);
2292 EXPORT_SYMBOL(lprocfs_rd_uuid);
2293 EXPORT_SYMBOL(lprocfs_rd_name);
2294 EXPORT_SYMBOL(lprocfs_rd_fstype);
2295 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
2296 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
2297 EXPORT_SYMBOL(lprocfs_rd_num_exports);
2298 EXPORT_SYMBOL(lprocfs_rd_numrefs);
2299 EXPORT_SYMBOL(lprocfs_at_hist_helper);
2300 EXPORT_SYMBOL(lprocfs_rd_import);
2301 EXPORT_SYMBOL(lprocfs_rd_state);
2302 EXPORT_SYMBOL(lprocfs_rd_timeouts);
2303 EXPORT_SYMBOL(lprocfs_rd_blksize);
2304 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
2305 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
2306 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
2307 EXPORT_SYMBOL(lprocfs_rd_filestotal);
2308 EXPORT_SYMBOL(lprocfs_rd_filesfree);
2310 EXPORT_SYMBOL(lprocfs_write_helper);
2311 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2312 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2313 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2314 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2315 EXPORT_SYMBOL(lprocfs_stats_collect);