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 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 (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 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 atomic_dec(&obd->obd_evict_inprogress);
261 wake_up(&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 (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 atomic_t *atom = data;
465 LASSERT(atom != NULL);
467 return snprintf(page, count, "%d\n", atomic_read(atom));
470 int lprocfs_wr_atomic(struct file *file, const char *buffer,
471 unsigned long count, void *data)
473 atomic_t *atm = data;
477 rc = lprocfs_write_helper(buffer, count, &val);
484 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() - 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() - 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() - 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() - 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() - 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() - 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 = num_possible_cpus();
685 for (i = 0; i < num_cpu; i++) {
686 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[idx];
689 centry = atomic_read(&percpu_cntr->lc_cntl.la_entry);
690 t.lc_count = percpu_cntr->lc_count;
691 t.lc_sum = percpu_cntr->lc_sum;
692 t.lc_min = percpu_cntr->lc_min;
693 t.lc_max = percpu_cntr->lc_max;
694 t.lc_sumsquare = percpu_cntr->lc_sumsquare;
695 } while (centry != atomic_read(&percpu_cntr->lc_cntl.la_entry) &&
696 centry != atomic_read(&percpu_cntr->lc_cntl.la_exit));
697 cnt->lc_count += t.lc_count;
698 cnt->lc_sum += t.lc_sum;
699 if (t.lc_min < cnt->lc_min)
700 cnt->lc_min = t.lc_min;
701 if (t.lc_max > cnt->lc_max)
702 cnt->lc_max = t.lc_max;
703 cnt->lc_sumsquare += t.lc_sumsquare;
706 cnt->lc_units = stats->ls_percpu[0]->lp_cntr[idx].lc_units;
710 * Append a space separated list of current set flags to str.
712 #define flag2str(flag) \
713 if (imp->imp_##flag && max - len > 0) \
714 len += snprintf(str + len, max - len, "%s" #flag, len ? ", " : "");
715 static int obd_import_flags2str(struct obd_import *imp, char *str, int max)
719 if (imp->imp_obd->obd_no_recov)
720 len += snprintf(str, max - len, "no_recov");
724 flag2str(replayable);
727 flag2str(last_recon);
732 static const char *obd_connect_names[] = {
746 "join_file(obsolete)",
750 "remote_client_by_force",
759 "mds_mds_connection",
762 "alt_checksum_algorithm",
771 static int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
776 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
778 ret += snprintf(page + ret, count - ret, "%s%s",
779 ret ? sep : "", obd_connect_names[i]);
781 if (flags & ~(mask - 1))
782 ret += snprintf(page + ret, count - ret,
783 "%sunknown flags "LPX64,
784 ret ? sep : "", flags & ~(mask - 1));
788 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
789 int *eof, void *data)
791 struct lprocfs_counter ret;
792 struct obd_device *obd = (struct obd_device *)data;
793 struct obd_import *imp;
796 LASSERT(obd != NULL);
797 LPROCFS_CLIMP_CHECK(obd);
798 imp = obd->u.cli.cl_import;
801 i = snprintf(page, count,
805 " current_connection: %s\n"
810 imp->imp_connection->c_remote_uuid.uuid,
811 ptlrpc_import_state_name(imp->imp_state));
812 i += obd_connect_flags2str(page + i, count - i,
813 imp->imp_connect_data.ocd_connect_flags,
815 i += snprintf(page + i, count - i,
818 i += obd_import_flags2str(imp, page + i, count - i);
820 i += snprintf(page + i, count - i,
823 " connection_attempts: %u\n"
825 " in-progress_invalidations: %u\n",
828 atomic_read(&imp->imp_inval_count));
830 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
831 do_div(ret.lc_sum, ret.lc_count);
832 i += snprintf(page + i, count - i,
835 " unregistering: %u\n"
837 " avg_waittime: "LPU64" %s\n",
838 atomic_read(&imp->imp_inflight),
839 atomic_read(&imp->imp_unregistering),
840 atomic_read(&imp->imp_timeouts),
841 ret.lc_sum, ret.lc_units);
844 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
845 if (imp->imp_at.iat_portal[j] == 0)
847 k = max_t(unsigned int, k,
848 at_get(&imp->imp_at.iat_service_estimate[j]));
850 i += snprintf(page + i, count - i,
851 " service_estimates:\n"
852 " services: %u sec\n"
853 " network: %u sec\n",
855 at_get(&imp->imp_at.iat_net_latency));
857 i += snprintf(page + i, count - i,
859 " last_replay: "LPU64"\n"
860 " peer_committed: "LPU64"\n"
861 " last_checked: "LPU64"\n",
862 imp->imp_last_replay_transno,
863 imp->imp_peer_committed_transno,
864 imp->imp_last_transno_checked);
867 for (rw = 0; rw <= 1; rw++) {
868 lprocfs_stats_collect(obd->obd_svc_stats,
869 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
871 if (ret.lc_sum > 0) {
872 do_div(ret.lc_sum, ret.lc_count);
873 i += snprintf(page + i, count - i,
874 " %s_data_averages:\n"
875 " bytes_per_rpc: "LPU64"\n",
876 rw ? "write" : "read",
880 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
881 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
882 if (ret.lc_sum > 0) {
883 do_div(ret.lc_sum, ret.lc_count);
884 i += snprintf(page + i, count - i,
885 " %s_per_rpc: "LPU64"\n",
886 ret.lc_units, ret.lc_sum);
889 i += snprintf(page + i, count - i,
890 " MB_per_sec: %u.%.02u\n",
891 k / j, (100 * k / j) % 100);
895 LPROCFS_CLIMP_EXIT(obd);
899 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
900 int *eof, void *data)
902 struct obd_device *obd = (struct obd_device *)data;
903 struct obd_import *imp;
906 LASSERT(obd != NULL);
907 LPROCFS_CLIMP_CHECK(obd);
908 imp = obd->u.cli.cl_import;
911 i = snprintf(page, count, "current_state: %s\n",
912 ptlrpc_import_state_name(imp->imp_state));
913 i += snprintf(page + i, count - i,
915 k = imp->imp_state_hist_idx;
916 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
917 struct import_state_hist *ish =
918 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
919 if (ish->ish_state == 0)
921 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
923 ptlrpc_import_state_name(ish->ish_state));
926 LPROCFS_CLIMP_EXIT(obd);
930 int lprocfs_at_hist_helper(char *page, int count, int rc,
931 struct adaptive_timeout *at)
934 for (i = 0; i < AT_BINS; i++)
935 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
936 rc += snprintf(page + rc, count - rc, "\n");
940 int lprocfs_rd_quota_resend_count(char *page, char **start, off_t off,
941 int count, int *eof, void *data)
943 struct obd_device *obd = data;
945 return snprintf(page, count, "%d\n",
946 atomic_read(&obd->u.cli.cl_quota_resends));
949 int lprocfs_wr_quota_resend_count(struct file *file, const char *buffer,
950 unsigned long count, void *data)
952 struct obd_device *obd = data;
955 rc = lprocfs_write_helper(buffer, count, &val);
959 atomic_set(&obd->u.cli.cl_quota_resends, val);
964 /* See also ptlrpc_lprocfs_rd_timeouts */
965 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
966 int *eof, void *data)
968 struct obd_device *obd = (struct obd_device *)data;
969 struct obd_import *imp;
970 unsigned int cur, worst;
975 LASSERT(obd != NULL);
976 LPROCFS_CLIMP_CHECK(obd);
977 imp = obd->u.cli.cl_import;
980 now = cfs_time_current_sec();
982 /* Some network health info for kicks */
983 s2dhms(&ts, now - imp->imp_last_reply_time);
984 rc += snprintf(page + rc, count - rc,
985 "%-10s : %ld, "DHMS_FMT" ago\n",
986 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
988 cur = at_get(&imp->imp_at.iat_net_latency);
989 worst = imp->imp_at.iat_net_latency.at_worst_ever;
990 worstt = imp->imp_at.iat_net_latency.at_worst_time;
991 s2dhms(&ts, now - worstt);
992 rc += snprintf(page + rc, count - rc,
993 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
994 "network", cur, worst, worstt, DHMS_VARS(&ts));
995 rc = lprocfs_at_hist_helper(page, count, rc,
996 &imp->imp_at.iat_net_latency);
998 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
999 if (imp->imp_at.iat_portal[i] == 0)
1001 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
1002 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
1003 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
1004 s2dhms(&ts, now - worstt);
1005 rc += snprintf(page + rc, count - rc,
1006 "portal %-2d : cur %3u worst %3u (at %ld, "
1007 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
1008 cur, worst, worstt, DHMS_VARS(&ts));
1009 rc = lprocfs_at_hist_helper(page, count, rc,
1010 &imp->imp_at.iat_service_estimate[i]);
1013 LPROCFS_CLIMP_EXIT(obd);
1017 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1018 int count, int *eof, void *data)
1020 struct obd_device *obd = data;
1024 LPROCFS_CLIMP_CHECK(obd);
1025 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1026 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1027 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1028 ret += snprintf(page + ret, count - ret, "\n");
1029 LPROCFS_CLIMP_EXIT(obd);
1032 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1034 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1035 int *eof, void *data)
1037 struct obd_device *obd = data;
1039 LASSERT(obd != NULL);
1041 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1044 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1045 int *eof, void *data)
1047 struct obd_type *class = (struct obd_type*) data;
1049 LASSERT(class != NULL);
1051 return snprintf(page, count, "%d\n", class->typ_refcnt);
1054 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1058 LASSERT(obd != NULL);
1059 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1060 LASSERT(obd->obd_type->typ_procroot != NULL);
1062 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1063 obd->obd_type->typ_procroot,
1065 if (IS_ERR(obd->obd_proc_entry)) {
1066 rc = PTR_ERR(obd->obd_proc_entry);
1067 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1068 obd->obd_proc_entry = NULL;
1073 int lprocfs_obd_cleanup(struct obd_device *obd)
1077 if (obd->obd_proc_exports_entry) {
1078 /* Should be no exports left */
1079 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1080 lprocfs_remove(&obd->obd_proc_exports_entry);
1081 obd->obd_proc_exports_entry = NULL;
1083 if (obd->obd_proc_entry) {
1084 lprocfs_remove(&obd->obd_proc_entry);
1085 obd->obd_proc_entry = NULL;
1090 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1092 CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
1093 client_stat->nid_proc, client_stat->nid_stats,
1094 client_stat->nid_brw_stats);
1096 LASSERTF(atomic_read(&client_stat->nid_exp_ref_count) == 0,
1097 "count %d\n", atomic_read(&client_stat->nid_exp_ref_count));
1099 hlist_del_init(&client_stat->nid_hash);
1101 if (client_stat->nid_proc)
1102 lprocfs_remove(&client_stat->nid_proc);
1104 if (client_stat->nid_stats)
1105 lprocfs_free_stats(&client_stat->nid_stats);
1107 if (client_stat->nid_brw_stats)
1108 OBD_FREE_PTR(client_stat->nid_brw_stats);
1110 if (client_stat->nid_ldlm_stats)
1111 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1113 OBD_FREE_PTR(client_stat);
1118 void lprocfs_free_per_client_stats(struct obd_device *obd)
1120 struct nid_stat *stat;
1123 /* we need extra list - because hash_exit called to early */
1124 /* not need locking because all clients is died */
1125 while(!list_empty(&obd->obd_nid_stats)) {
1126 stat = list_entry(obd->obd_nid_stats.next,
1127 struct nid_stat, nid_list);
1128 list_del_init(&stat->nid_list);
1129 lprocfs_free_client_stats(stat);
1135 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1136 enum lprocfs_stats_flags flags)
1138 struct lprocfs_stats *stats;
1139 unsigned int percpusize;
1141 unsigned int num_cpu;
1146 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1149 num_cpu = num_possible_cpus();
1151 OBD_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
1155 if (flags & LPROCFS_STATS_FLAG_NOPERCPU) {
1156 stats->ls_flags = flags;
1157 spin_lock_init(&stats->ls_lock);
1158 /* Use this lock only if there are no percpu areas */
1160 stats->ls_flags = 0;
1163 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
1165 percpusize = L1_CACHE_ALIGN(percpusize);
1167 for (i = 0; i < num_cpu; i++) {
1168 OBD_ALLOC(stats->ls_percpu[i], percpusize);
1169 if (stats->ls_percpu[i] == NULL) {
1170 for (j = 0; j < i; j++) {
1171 OBD_FREE(stats->ls_percpu[j], percpusize);
1172 stats->ls_percpu[j] = NULL;
1177 if (stats->ls_percpu[0] == NULL) {
1178 OBD_FREE(stats, offsetof(typeof(*stats),
1179 ls_percpu[num_cpu]));
1183 stats->ls_num = num;
1187 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1189 struct lprocfs_stats *stats = *statsh;
1190 unsigned int num_cpu;
1191 unsigned int percpusize;
1194 if (stats == NULL || stats->ls_num == 0)
1198 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1201 num_cpu = num_possible_cpus();
1203 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
1205 percpusize = L1_CACHE_ALIGN(percpusize);
1206 for (i = 0; i < num_cpu; i++)
1207 OBD_FREE(stats->ls_percpu[i], percpusize);
1208 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
1211 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1213 struct lprocfs_counter *percpu_cntr;
1215 unsigned int num_cpu;
1217 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1219 for (i = 0; i < num_cpu; i++) {
1220 for (j = 0; j < stats->ls_num; j++) {
1221 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
1222 atomic_inc(&percpu_cntr->lc_cntl.la_entry);
1223 percpu_cntr->lc_count = 0;
1224 percpu_cntr->lc_sum = 0;
1225 percpu_cntr->lc_min = LC_MIN_INIT;
1226 percpu_cntr->lc_max = 0;
1227 percpu_cntr->lc_sumsquare = 0;
1228 atomic_inc(&percpu_cntr->lc_cntl.la_exit);
1232 lprocfs_stats_unlock(stats);
1235 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1236 size_t len, loff_t *off)
1238 struct seq_file *seq = file->private_data;
1239 struct lprocfs_stats *stats = seq->private;
1241 lprocfs_clear_stats(stats);
1246 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1248 struct lprocfs_stats *stats = p->private;
1249 /* return 1st cpu location */
1250 return (*pos >= stats->ls_num) ? NULL :
1251 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1254 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1258 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1260 struct lprocfs_stats *stats = p->private;
1262 return (*pos >= stats->ls_num) ? NULL :
1263 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1266 /* seq file export of one lprocfs counter */
1267 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1269 struct lprocfs_stats *stats = p->private;
1270 struct lprocfs_counter *cntr = v;
1271 struct lprocfs_counter ret;
1274 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
1276 do_gettimeofday(&now);
1277 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1278 "snapshot_time", now.tv_sec, now.tv_usec);
1282 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
1284 lprocfs_stats_collect(stats, idx, &ret);
1286 if (ret.lc_count == 0)
1289 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", cntr->lc_name,
1290 ret.lc_count, cntr->lc_units);
1295 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
1296 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1297 ret.lc_min, ret.lc_max, ret.lc_sum);
1300 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
1301 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1305 rc = seq_printf(p, "\n");
1307 return (rc < 0) ? rc : 0;
1310 struct seq_operations lprocfs_stats_seq_sops = {
1311 start: lprocfs_stats_seq_start,
1312 stop: lprocfs_stats_seq_stop,
1313 next: lprocfs_stats_seq_next,
1314 show: lprocfs_stats_seq_show,
1317 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1319 struct proc_dir_entry *dp = PDE(inode);
1320 struct seq_file *seq;
1323 if (LPROCFS_ENTRY_AND_CHECK(dp))
1326 rc = seq_open(file, &lprocfs_stats_seq_sops);
1331 seq = file->private_data;
1332 seq->private = dp->data;
1336 struct file_operations lprocfs_stats_seq_fops = {
1337 .owner = THIS_MODULE,
1338 .open = lprocfs_stats_seq_open,
1340 .write = lprocfs_stats_seq_write,
1341 .llseek = seq_lseek,
1342 .release = lprocfs_seq_release,
1345 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1346 struct lprocfs_stats *stats)
1348 struct proc_dir_entry *entry;
1349 LASSERT(root != NULL);
1351 entry = create_proc_entry(name, 0644, root);
1354 entry->proc_fops = &lprocfs_stats_seq_fops;
1355 entry->data = stats;
1359 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1360 unsigned conf, const char *name, const char *units)
1362 struct lprocfs_counter *c;
1364 unsigned int num_cpu;
1366 LASSERT(stats != NULL);
1368 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1370 for (i = 0; i < num_cpu; i++) {
1371 c = &(stats->ls_percpu[i]->lp_cntr[index]);
1372 c->lc_config = conf;
1375 c->lc_min = LC_MIN_INIT;
1378 c->lc_units = units;
1381 lprocfs_stats_unlock(stats);
1383 EXPORT_SYMBOL(lprocfs_counter_init);
1385 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1387 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1388 LASSERT(coffset < stats->ls_num); \
1389 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1392 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1394 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1395 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1396 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1397 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1398 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1399 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1400 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1401 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1402 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1403 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1404 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1405 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1406 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1407 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1408 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1409 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1410 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1411 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1412 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
1413 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1414 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1415 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1416 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1417 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1418 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1419 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1420 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1421 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1422 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1423 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1424 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1425 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1426 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1427 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1428 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1429 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1430 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1431 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1432 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1433 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1434 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1435 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1436 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1437 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1438 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1439 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1440 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1441 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1442 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1443 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1444 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1445 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1446 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1447 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1448 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1449 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1450 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1451 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1452 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1453 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1454 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quota_adjust_qunit);
1455 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1456 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1457 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1458 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1459 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1460 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1461 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1464 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1466 struct lprocfs_stats *stats;
1467 unsigned int num_stats;
1470 LASSERT(obd->obd_stats == NULL);
1471 LASSERT(obd->obd_proc_entry != NULL);
1472 LASSERT(obd->obd_cntr_base == 0);
1474 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1475 num_private_stats - 1 /* o_owner */;
1476 stats = lprocfs_alloc_stats(num_stats, 0);
1480 lprocfs_init_ops_stats(num_private_stats, stats);
1482 for (i = num_private_stats; i < num_stats; i++) {
1483 /* If this LBUGs, it is likely that an obd
1484 * operation was added to struct obd_ops in
1485 * <obd.h>, and that the corresponding line item
1486 * LPROCFS_OBD_OP_INIT(.., .., opname)
1487 * is missing from the list above. */
1488 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1489 "Missing obd_stat initializer obd_op "
1490 "operation at offset %d.\n", i - num_private_stats);
1492 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1494 lprocfs_free_stats(&stats);
1496 obd->obd_stats = stats;
1497 obd->obd_cntr_base = num_private_stats;
1502 void lprocfs_free_obd_stats(struct obd_device *obd)
1505 lprocfs_free_stats(&obd->obd_stats);
1508 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1510 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1511 LASSERT(coffset < stats->ls_num); \
1512 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1515 int lprocfs_alloc_md_stats(struct obd_device *obd,
1516 unsigned num_private_stats)
1518 struct lprocfs_stats *stats;
1519 unsigned int num_stats;
1522 LASSERT(obd->md_stats == NULL);
1523 LASSERT(obd->obd_proc_entry != NULL);
1524 LASSERT(obd->md_cntr_base == 0);
1526 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1528 stats = lprocfs_alloc_stats(num_stats, 0);
1532 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1533 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1534 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1535 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1536 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1537 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1538 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1539 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1540 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1541 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1542 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1543 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1544 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1545 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1546 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1547 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1548 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1549 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1550 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1551 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1552 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1553 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1554 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1555 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1556 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1557 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1558 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1559 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1560 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1561 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1562 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1564 for (i = num_private_stats; i < num_stats; i++) {
1565 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1566 CERROR("Missing md_stat initializer md_op "
1567 "operation at offset %d. Aborting.\n",
1568 i - num_private_stats);
1572 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1574 lprocfs_free_stats(&stats);
1576 obd->md_stats = stats;
1577 obd->md_cntr_base = num_private_stats;
1582 void lprocfs_free_md_stats(struct obd_device *obd)
1584 struct lprocfs_stats *stats = obd->md_stats;
1586 if (stats != NULL) {
1587 obd->md_stats = NULL;
1588 obd->md_cntr_base = 0;
1589 lprocfs_free_stats(&stats);
1593 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1595 lprocfs_counter_init(ldlm_stats,
1596 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1597 0, "ldlm_enqueue", "reqs");
1598 lprocfs_counter_init(ldlm_stats,
1599 LDLM_CONVERT - LDLM_FIRST_OPC,
1600 0, "ldlm_convert", "reqs");
1601 lprocfs_counter_init(ldlm_stats,
1602 LDLM_CANCEL - LDLM_FIRST_OPC,
1603 0, "ldlm_cancel", "reqs");
1604 lprocfs_counter_init(ldlm_stats,
1605 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1606 0, "ldlm_bl_callback", "reqs");
1607 lprocfs_counter_init(ldlm_stats,
1608 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1609 0, "ldlm_cp_callback", "reqs");
1610 lprocfs_counter_init(ldlm_stats,
1611 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1612 0, "ldlm_gl_callback", "reqs");
1615 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1616 int *eof, void *data)
1618 struct obd_export *exp = data;
1619 LASSERT(exp != NULL);
1621 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1624 struct exp_uuid_cb_data {
1632 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1633 int count, int *eof, int *len)
1635 cb_data->page = page;
1636 cb_data->count = count;
1641 void lprocfs_exp_print_uuid(void *obj, void *cb_data)
1643 struct obd_export *exp = (struct obd_export *)obj;
1644 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1646 if (exp->exp_nid_stats)
1647 *data->len += snprintf((data->page + *data->len),
1648 data->count, "%s\n",
1649 obd_uuid2str(&exp->exp_client_uuid));
1652 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1653 int *eof, void *data)
1655 struct nid_stat *stats = (struct nid_stat *)data;
1656 struct exp_uuid_cb_data cb_data;
1657 struct obd_device *obd = stats->nid_obd;
1662 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1663 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1664 lprocfs_exp_print_uuid, &cb_data);
1665 return (*cb_data.len);
1668 void lprocfs_exp_print_hash(void *obj, void *cb_data)
1670 struct exp_uuid_cb_data *data = cb_data;
1671 struct obd_export *exp = obj;
1674 hs = exp->exp_lock_hash;
1677 *data->len += cfs_hash_debug_header(data->page,
1680 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1685 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1686 int *eof, void *data)
1688 struct nid_stat *stats = (struct nid_stat *)data;
1689 struct exp_uuid_cb_data cb_data;
1690 struct obd_device *obd = stats->nid_obd;
1695 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1697 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1698 lprocfs_exp_print_hash, &cb_data);
1699 return (*cb_data.len);
1702 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1703 int count, int *eof, void *data)
1706 return snprintf(page, count, "%s\n",
1707 "Write into this file to clear all nid stats and "
1708 "stale nid entries");
1710 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1712 void lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1714 struct nid_stat *stat = obj;
1717 /* object has only hash + iterate_all references.
1718 * add/delete blocked by hash bucket lock */
1719 CDEBUG(D_INFO,"refcnt %d\n", atomic_read(&stat->nid_exp_ref_count));
1720 if (atomic_read(&stat->nid_exp_ref_count) == 2) {
1721 hlist_del_init(&stat->nid_hash);
1722 nidstat_putref(stat);
1723 spin_lock(&stat->nid_obd->obd_nid_lock);
1724 list_move(&stat->nid_list, data);
1725 spin_unlock(&stat->nid_obd->obd_nid_lock);
1729 /* we has reference to object - only clear data*/
1730 if (stat->nid_stats)
1731 lprocfs_clear_stats(stat->nid_stats);
1733 if (stat->nid_brw_stats) {
1734 for (i = 0; i < BRW_LAST; i++)
1735 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
1741 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1742 unsigned long count, void *data)
1744 struct obd_device *obd = (struct obd_device *)data;
1745 struct nid_stat *client_stat;
1746 CFS_LIST_HEAD(free_list);
1748 cfs_hash_for_each(obd->obd_nid_stats_hash,
1749 lprocfs_nid_stats_clear_write_cb, &free_list);
1751 while (!list_empty(&free_list)) {
1752 client_stat = list_entry(free_list.next, struct nid_stat,
1754 list_del_init(&client_stat->nid_list);
1755 lprocfs_free_client_stats(client_stat);
1760 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1762 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1764 struct nid_stat *new_stat, *old_stat;
1765 struct obd_device *obd = NULL;
1766 cfs_proc_dir_entry_t *entry;
1772 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1773 !exp->exp_obd->obd_nid_stats_hash)
1776 /* not test against zero because eric say:
1777 * You may only test nid against another nid, or LNET_NID_ANY.
1778 * Anything else is nonsense.*/
1779 if (!nid || *nid == LNET_NID_ANY)
1784 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
1786 OBD_ALLOC_PTR(new_stat);
1787 if (new_stat == NULL)
1790 new_stat->nid = *nid;
1791 new_stat->nid_obd = exp->exp_obd;
1792 atomic_set(&new_stat->nid_exp_ref_count, 0);
1794 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
1795 nid, &new_stat->nid_hash);
1796 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
1797 old_stat, libcfs_nid2str(*nid),
1798 atomic_read(&new_stat->nid_exp_ref_count));
1800 /* Return -EALREADY here so that we know that the /proc
1801 * entry already has been created */
1802 if (old_stat != new_stat) {
1803 spin_lock(&obd->obd_nid_lock);
1804 if (exp->exp_nid_stats != old_stat) {
1805 if (exp->exp_nid_stats)
1806 nidstat_putref(exp->exp_nid_stats);
1807 exp->exp_nid_stats = old_stat;
1809 /* cfs_hash_findadd_unique() has added
1810 * old_stat's refcount */
1811 nidstat_putref(old_stat);
1814 spin_unlock(&obd->obd_nid_lock);
1816 GOTO(destroy_new, rc = -EALREADY);
1818 /* not found - create */
1819 new_stat->nid_proc = lprocfs_register(libcfs_nid2str(*nid),
1820 obd->obd_proc_exports_entry,
1822 if (new_stat->nid_proc == NULL) {
1823 CERROR("Error making export directory for nid %s\n",
1824 libcfs_nid2str(*nid));
1825 GOTO(destroy_new_ns, rc = -ENOMEM);
1828 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
1829 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
1830 if (IS_ERR(entry)) {
1831 CWARN("Error adding the NID stats file\n");
1832 rc = PTR_ERR(entry);
1833 GOTO(destroy_new_ns, rc);
1836 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
1837 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
1838 if (IS_ERR(entry)) {
1839 CWARN("Error adding the hash file\n");
1840 rc = PTR_ERR(entry);
1841 GOTO(destroy_new_ns, rc);
1844 if (exp->exp_nid_stats)
1845 nidstat_putref(exp->exp_nid_stats);
1846 nidstat_getref(new_stat);
1847 exp->exp_nid_stats = new_stat;
1849 /* protect competitive add to list, not need locking on destroy */
1850 spin_lock(&obd->obd_nid_lock);
1851 list_add(&new_stat->nid_list, &obd->obd_nid_stats);
1852 spin_unlock(&obd->obd_nid_lock);
1857 if (new_stat->nid_proc != NULL)
1858 lprocfs_remove(&new_stat->nid_proc);
1859 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
1862 OBD_FREE_PTR(new_stat);
1866 int lprocfs_exp_cleanup(struct obd_export *exp)
1868 struct nid_stat *stat = exp->exp_nid_stats;
1870 if(!stat || !exp->exp_obd)
1873 nidstat_putref(exp->exp_nid_stats);
1874 exp->exp_nid_stats = NULL;
1879 int lprocfs_write_helper(const char *buffer, unsigned long count,
1882 return lprocfs_write_frac_helper(buffer, count, val, 1);
1885 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
1888 char kernbuf[20], *end, *pbuf;
1890 if (count > (sizeof(kernbuf) - 1))
1893 if (copy_from_user(kernbuf, buffer, count))
1896 kernbuf[count] = '\0';
1903 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1907 if (end != NULL && *end == '.') {
1908 int temp_val, pow = 1;
1912 if (strlen(pbuf) > 5)
1913 pbuf[5] = '\0'; /*only allow 5bits fractional*/
1915 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1918 for (i = 0; i < (end - pbuf); i++)
1921 *val += temp_val / pow;
1927 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
1930 long decimal_val, frac_val;
1936 decimal_val = val / mult;
1937 prtn = snprintf(buffer, count, "%ld", decimal_val);
1938 frac_val = val % mult;
1940 if (prtn < (count - 4) && frac_val > 0) {
1942 int i, temp_mult = 1, frac_bits = 0;
1944 temp_frac = frac_val * 10;
1945 buffer[prtn++] = '.';
1946 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
1947 /* only reserved 2 bits fraction */
1948 buffer[prtn++] ='0';
1953 * Need to think these cases :
1954 * 1. #echo x.00 > /proc/xxx output result : x
1955 * 2. #echo x.0x > /proc/xxx output result : x.0x
1956 * 3. #echo x.x0 > /proc/xxx output result : x.x
1957 * 4. #echo x.xx > /proc/xxx output result : x.xx
1958 * Only reserved 2 bits fraction.
1960 for (i = 0; i < (5 - prtn); i++)
1963 frac_bits = min((int)count - prtn, 3 - frac_bits);
1964 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
1965 frac_val * temp_mult / mult);
1968 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
1970 if (buffer[prtn] == '.') {
1977 buffer[prtn++] ='\n';
1981 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
1983 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
1986 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
1987 __u64 *val, int mult)
1989 char kernbuf[22], *end, *pbuf;
1990 __u64 whole, frac = 0, units;
1991 unsigned frac_d = 1;
1993 if (count > (sizeof(kernbuf) - 1))
1996 if (copy_from_user(kernbuf, buffer, count))
1999 kernbuf[count] = '\0';
2006 whole = simple_strtoull(pbuf, &end, 10);
2010 if (end != NULL && *end == '.') {
2014 /* need to limit frac_d to a __u32 */
2015 if (strlen(pbuf) > 10)
2018 frac = simple_strtoull(pbuf, &end, 10);
2019 /* count decimal places */
2020 for (i = 0; i < (end - pbuf); i++)
2037 /* Specified units override the multiplier */
2039 mult = mult < 0 ? -units : units;
2042 do_div(frac, frac_d);
2043 *val = whole * mult + frac;
2047 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent, char *name, mode_t mode,
2048 struct file_operations *seq_fops, void *data)
2050 struct proc_dir_entry *entry;
2053 entry = create_proc_entry(name, mode, parent);
2056 entry->proc_fops = seq_fops;
2061 EXPORT_SYMBOL(lprocfs_seq_create);
2063 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
2065 struct file_operations *seq_fops,
2068 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2069 mode, seq_fops, data));
2071 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2073 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2075 if (value >= OBD_HIST_MAX)
2076 value = OBD_HIST_MAX - 1;
2078 spin_lock(&oh->oh_lock);
2079 oh->oh_buckets[value]++;
2080 spin_unlock(&oh->oh_lock);
2082 EXPORT_SYMBOL(lprocfs_oh_tally);
2084 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2088 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2091 lprocfs_oh_tally(oh, val);
2093 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2095 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2097 unsigned long ret = 0;
2100 for (i = 0; i < OBD_HIST_MAX; i++)
2101 ret += oh->oh_buckets[i];
2104 EXPORT_SYMBOL(lprocfs_oh_sum);
2106 void lprocfs_oh_clear(struct obd_histogram *oh)
2108 spin_lock(&oh->oh_lock);
2109 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2110 spin_unlock(&oh->oh_lock);
2112 EXPORT_SYMBOL(lprocfs_oh_clear);
2114 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2115 int count, int *eof, void *data)
2117 struct obd_device *obd = data;
2123 c += cfs_hash_debug_header(page, count);
2124 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2125 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2126 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2130 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2132 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2133 int count, int *eof, void *data)
2135 struct obd_device *obd = data;
2138 LASSERT(obd != NULL);
2139 LASSERT(count >= 0);
2141 /* Set start of user data returned to
2142 page + off since the user may have
2143 requested to read much smaller than
2144 what we need to read */
2145 *start = page + off;
2147 /* We know we are allocated a page here.
2148 Also we know that this function will
2149 not need to write more than a page
2150 so we can truncate at CFS_PAGE_SIZE. */
2151 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2153 /* Initialize the page */
2154 memset(page, 0, size);
2156 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2158 if (obd->obd_max_recoverable_clients == 0) {
2159 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2165 /* sampled unlocked, but really... */
2166 if (obd->obd_recovering == 0) {
2167 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2169 if (lprocfs_obd_snprintf(&page, size, &len,
2170 "recovery_start: %lu\n",
2171 obd->obd_recovery_start) <= 0)
2173 if (lprocfs_obd_snprintf(&page, size, &len,
2174 "recovery_duration: %lu\n",
2175 obd->obd_recovery_end -
2176 obd->obd_recovery_start) <= 0)
2178 /* Number of clients that have completed recovery */
2179 if (lprocfs_obd_snprintf(&page, size, &len,
2180 "completed_clients: %d/%d\n",
2181 obd->obd_max_recoverable_clients -
2182 obd->obd_stale_clients,
2183 obd->obd_max_recoverable_clients) <= 0)
2185 if (lprocfs_obd_snprintf(&page, size, &len,
2186 "replayed_requests: %d\n",
2187 obd->obd_replayed_requests) <= 0)
2189 if (lprocfs_obd_snprintf(&page, size, &len,
2190 "last_transno: "LPD64"\n",
2191 obd->obd_next_recovery_transno - 1)<=0)
2193 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2194 obd->obd_version_recov ? "ON" : "OFF")<=0)
2199 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2201 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2202 obd->obd_recovery_start) <= 0)
2204 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2205 cfs_time_current_sec() >= obd->obd_recovery_end ? 0 :
2206 obd->obd_recovery_end - cfs_time_current_sec()) <= 0)
2208 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2209 obd->obd_connected_clients,
2210 obd->obd_max_recoverable_clients) <= 0)
2212 /* Number of clients that have completed recovery */
2213 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2214 atomic_read(&obd->obd_req_replay_clients))<= 0)
2216 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2217 atomic_read(&obd->obd_lock_replay_clients))<=0)
2219 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2220 obd->obd_connected_clients -
2221 atomic_read(&obd->obd_lock_replay_clients))<=0)
2223 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2224 obd->obd_stale_clients) <= 0)
2226 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2227 obd->obd_replayed_requests) <= 0)
2229 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2230 obd->obd_requests_queued_for_recovery) <= 0)
2233 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2234 obd->obd_next_recovery_transno) <= 0)
2240 return min(count, len - (int)off);
2242 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2244 int lprocfs_obd_rd_recovery_maxtime(char *page, char **start, off_t off,
2245 int count, int *eof, void *data)
2247 struct obd_device *obd = data;
2248 LASSERT(obd != NULL);
2250 return snprintf(page, count, "%lu\n", obd->obd_recovery_max_time);
2252 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_maxtime);
2254 int lprocfs_obd_wr_recovery_maxtime(struct file *file, const char *buffer,
2255 unsigned long count, void *data)
2257 struct obd_device *obd = data;
2259 LASSERT(obd != NULL);
2261 rc = lprocfs_write_helper(buffer, count, &val);
2265 obd->obd_recovery_max_time = val;
2268 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_maxtime);
2271 EXPORT_SYMBOL(lprocfs_register);
2272 EXPORT_SYMBOL(lprocfs_srch);
2273 EXPORT_SYMBOL(lprocfs_remove);
2274 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
2275 EXPORT_SYMBOL(lprocfs_add_vars);
2276 EXPORT_SYMBOL(lprocfs_obd_setup);
2277 EXPORT_SYMBOL(lprocfs_obd_cleanup);
2278 EXPORT_SYMBOL(lprocfs_add_simple);
2279 EXPORT_SYMBOL(lprocfs_add_symlink);
2280 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
2281 EXPORT_SYMBOL(lprocfs_alloc_stats);
2282 EXPORT_SYMBOL(lprocfs_free_stats);
2283 EXPORT_SYMBOL(lprocfs_clear_stats);
2284 EXPORT_SYMBOL(lprocfs_register_stats);
2285 EXPORT_SYMBOL(lprocfs_init_ops_stats);
2286 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
2287 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
2288 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
2289 EXPORT_SYMBOL(lprocfs_free_obd_stats);
2290 EXPORT_SYMBOL(lprocfs_free_md_stats);
2291 EXPORT_SYMBOL(lprocfs_exp_setup);
2292 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2294 EXPORT_SYMBOL(lprocfs_rd_u64);
2295 EXPORT_SYMBOL(lprocfs_rd_atomic);
2296 EXPORT_SYMBOL(lprocfs_wr_atomic);
2297 EXPORT_SYMBOL(lprocfs_rd_uint);
2298 EXPORT_SYMBOL(lprocfs_wr_uint);
2299 EXPORT_SYMBOL(lprocfs_rd_uuid);
2300 EXPORT_SYMBOL(lprocfs_rd_name);
2301 EXPORT_SYMBOL(lprocfs_rd_fstype);
2302 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
2303 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
2304 EXPORT_SYMBOL(lprocfs_rd_num_exports);
2305 EXPORT_SYMBOL(lprocfs_rd_numrefs);
2306 EXPORT_SYMBOL(lprocfs_at_hist_helper);
2307 EXPORT_SYMBOL(lprocfs_rd_import);
2308 EXPORT_SYMBOL(lprocfs_rd_state);
2309 EXPORT_SYMBOL(lprocfs_rd_timeouts);
2310 EXPORT_SYMBOL(lprocfs_rd_blksize);
2311 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
2312 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
2313 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
2314 EXPORT_SYMBOL(lprocfs_rd_filestotal);
2315 EXPORT_SYMBOL(lprocfs_rd_filesfree);
2316 EXPORT_SYMBOL(lprocfs_rd_quota_resend_count);
2317 EXPORT_SYMBOL(lprocfs_wr_quota_resend_count);
2319 EXPORT_SYMBOL(lprocfs_write_helper);
2320 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2321 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2322 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2323 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2324 EXPORT_SYMBOL(lprocfs_stats_collect);