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 int lprocfs_rd_quota_resend_count(char *page, char **start, off_t off,
944 int count, int *eof, void *data)
946 struct obd_device *obd = data;
948 return snprintf(page, count, "%d\n",
949 cfs_atomic_read(&obd->u.cli.cl_quota_resends));
952 int lprocfs_wr_quota_resend_count(struct file *file, const char *buffer,
953 unsigned long count, void *data)
955 struct obd_device *obd = data;
958 rc = lprocfs_write_helper(buffer, count, &val);
962 cfs_atomic_set(&obd->u.cli.cl_quota_resends, val);
967 /* See also ptlrpc_lprocfs_rd_timeouts */
968 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
969 int *eof, void *data)
971 struct obd_device *obd = (struct obd_device *)data;
972 struct obd_import *imp;
973 unsigned int cur, worst;
978 LASSERT(obd != NULL);
979 LPROCFS_CLIMP_CHECK(obd);
980 imp = obd->u.cli.cl_import;
983 now = cfs_time_current_sec();
985 /* Some network health info for kicks */
986 s2dhms(&ts, now - imp->imp_last_reply_time);
987 rc += snprintf(page + rc, count - rc,
988 "%-10s : %ld, "DHMS_FMT" ago\n",
989 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
991 cur = at_get(&imp->imp_at.iat_net_latency);
992 worst = imp->imp_at.iat_net_latency.at_worst_ever;
993 worstt = imp->imp_at.iat_net_latency.at_worst_time;
994 s2dhms(&ts, now - worstt);
995 rc += snprintf(page + rc, count - rc,
996 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
997 "network", cur, worst, worstt, DHMS_VARS(&ts));
998 rc = lprocfs_at_hist_helper(page, count, rc,
999 &imp->imp_at.iat_net_latency);
1001 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
1002 if (imp->imp_at.iat_portal[i] == 0)
1004 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
1005 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
1006 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
1007 s2dhms(&ts, now - worstt);
1008 rc += snprintf(page + rc, count - rc,
1009 "portal %-2d : cur %3u worst %3u (at %ld, "
1010 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
1011 cur, worst, worstt, DHMS_VARS(&ts));
1012 rc = lprocfs_at_hist_helper(page, count, rc,
1013 &imp->imp_at.iat_service_estimate[i]);
1016 LPROCFS_CLIMP_EXIT(obd);
1020 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1021 int count, int *eof, void *data)
1023 struct obd_device *obd = data;
1027 LPROCFS_CLIMP_CHECK(obd);
1028 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1029 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1030 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1031 ret += snprintf(page + ret, count - ret, "\n");
1032 LPROCFS_CLIMP_EXIT(obd);
1035 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1037 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1038 int *eof, void *data)
1040 struct obd_device *obd = data;
1042 LASSERT(obd != NULL);
1044 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1047 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1048 int *eof, void *data)
1050 struct obd_type *class = (struct obd_type*) data;
1052 LASSERT(class != NULL);
1054 return snprintf(page, count, "%d\n", class->typ_refcnt);
1057 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1061 LASSERT(obd != NULL);
1062 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1063 LASSERT(obd->obd_type->typ_procroot != NULL);
1065 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1066 obd->obd_type->typ_procroot,
1068 if (IS_ERR(obd->obd_proc_entry)) {
1069 rc = PTR_ERR(obd->obd_proc_entry);
1070 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1071 obd->obd_proc_entry = NULL;
1076 int lprocfs_obd_cleanup(struct obd_device *obd)
1080 if (obd->obd_proc_exports_entry) {
1081 /* Should be no exports left */
1082 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1083 lprocfs_remove(&obd->obd_proc_exports_entry);
1084 obd->obd_proc_exports_entry = NULL;
1086 if (obd->obd_proc_entry) {
1087 lprocfs_remove(&obd->obd_proc_entry);
1088 obd->obd_proc_entry = NULL;
1093 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1095 CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
1096 client_stat->nid_proc, client_stat->nid_stats,
1097 client_stat->nid_brw_stats);
1099 LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
1101 cfs_atomic_read(&client_stat->nid_exp_ref_count));
1103 cfs_hlist_del_init(&client_stat->nid_hash);
1105 if (client_stat->nid_proc)
1106 lprocfs_remove(&client_stat->nid_proc);
1108 if (client_stat->nid_stats)
1109 lprocfs_free_stats(&client_stat->nid_stats);
1111 if (client_stat->nid_brw_stats)
1112 OBD_FREE_PTR(client_stat->nid_brw_stats);
1114 if (client_stat->nid_ldlm_stats)
1115 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1117 OBD_FREE_PTR(client_stat);
1122 void lprocfs_free_per_client_stats(struct obd_device *obd)
1124 struct nid_stat *stat;
1127 /* we need extra list - because hash_exit called to early */
1128 /* not need locking because all clients is died */
1129 while(!cfs_list_empty(&obd->obd_nid_stats)) {
1130 stat = cfs_list_entry(obd->obd_nid_stats.next,
1131 struct nid_stat, nid_list);
1132 cfs_list_del_init(&stat->nid_list);
1133 lprocfs_free_client_stats(stat);
1139 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1140 enum lprocfs_stats_flags flags)
1142 struct lprocfs_stats *stats;
1143 unsigned int percpusize;
1145 unsigned int num_cpu;
1150 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1153 num_cpu = cfs_num_possible_cpus();
1155 OBD_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
1159 if (flags & LPROCFS_STATS_FLAG_NOPERCPU) {
1160 stats->ls_flags = flags;
1161 cfs_spin_lock_init(&stats->ls_lock);
1162 /* Use this lock only if there are no percpu areas */
1164 stats->ls_flags = 0;
1167 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
1169 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1171 for (i = 0; i < num_cpu; i++) {
1172 OBD_ALLOC(stats->ls_percpu[i], percpusize);
1173 if (stats->ls_percpu[i] == NULL) {
1174 for (j = 0; j < i; j++) {
1175 OBD_FREE(stats->ls_percpu[j], percpusize);
1176 stats->ls_percpu[j] = NULL;
1181 if (stats->ls_percpu[0] == NULL) {
1182 OBD_FREE(stats, offsetof(typeof(*stats),
1183 ls_percpu[num_cpu]));
1187 stats->ls_num = num;
1191 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1193 struct lprocfs_stats *stats = *statsh;
1194 unsigned int num_cpu;
1195 unsigned int percpusize;
1198 if (stats == NULL || stats->ls_num == 0)
1202 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1205 num_cpu = cfs_num_possible_cpus();
1207 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
1209 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1210 for (i = 0; i < num_cpu; i++)
1211 OBD_FREE(stats->ls_percpu[i], percpusize);
1212 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
1215 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1217 struct lprocfs_counter *percpu_cntr;
1219 unsigned int num_cpu;
1221 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1223 for (i = 0; i < num_cpu; i++) {
1224 for (j = 0; j < stats->ls_num; j++) {
1225 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
1226 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_entry);
1227 percpu_cntr->lc_count = 0;
1228 percpu_cntr->lc_sum = 0;
1229 percpu_cntr->lc_min = LC_MIN_INIT;
1230 percpu_cntr->lc_max = 0;
1231 percpu_cntr->lc_sumsquare = 0;
1232 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_exit);
1236 lprocfs_stats_unlock(stats);
1239 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1240 size_t len, loff_t *off)
1242 struct seq_file *seq = file->private_data;
1243 struct lprocfs_stats *stats = seq->private;
1245 lprocfs_clear_stats(stats);
1250 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1252 struct lprocfs_stats *stats = p->private;
1253 /* return 1st cpu location */
1254 return (*pos >= stats->ls_num) ? NULL :
1255 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1258 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1262 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1264 struct lprocfs_stats *stats = p->private;
1266 return (*pos >= stats->ls_num) ? NULL :
1267 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1270 /* seq file export of one lprocfs counter */
1271 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1273 struct lprocfs_stats *stats = p->private;
1274 struct lprocfs_counter *cntr = v;
1275 struct lprocfs_counter ret;
1278 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
1280 cfs_gettimeofday(&now);
1281 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1282 "snapshot_time", now.tv_sec, now.tv_usec);
1286 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
1288 lprocfs_stats_collect(stats, idx, &ret);
1290 if (ret.lc_count == 0)
1293 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", cntr->lc_name,
1294 ret.lc_count, cntr->lc_units);
1299 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
1300 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1301 ret.lc_min, ret.lc_max, ret.lc_sum);
1304 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
1305 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1309 rc = seq_printf(p, "\n");
1311 return (rc < 0) ? rc : 0;
1314 struct seq_operations lprocfs_stats_seq_sops = {
1315 start: lprocfs_stats_seq_start,
1316 stop: lprocfs_stats_seq_stop,
1317 next: lprocfs_stats_seq_next,
1318 show: lprocfs_stats_seq_show,
1321 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1323 struct proc_dir_entry *dp = PDE(inode);
1324 struct seq_file *seq;
1327 if (LPROCFS_ENTRY_AND_CHECK(dp))
1330 rc = seq_open(file, &lprocfs_stats_seq_sops);
1335 seq = file->private_data;
1336 seq->private = dp->data;
1340 struct file_operations lprocfs_stats_seq_fops = {
1341 .owner = THIS_MODULE,
1342 .open = lprocfs_stats_seq_open,
1344 .write = lprocfs_stats_seq_write,
1345 .llseek = seq_lseek,
1346 .release = lprocfs_seq_release,
1349 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1350 struct lprocfs_stats *stats)
1352 struct proc_dir_entry *entry;
1353 LASSERT(root != NULL);
1355 entry = create_proc_entry(name, 0644, root);
1358 entry->proc_fops = &lprocfs_stats_seq_fops;
1359 entry->data = stats;
1363 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1364 unsigned conf, const char *name, const char *units)
1366 struct lprocfs_counter *c;
1368 unsigned int num_cpu;
1370 LASSERT(stats != NULL);
1372 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1374 for (i = 0; i < num_cpu; i++) {
1375 c = &(stats->ls_percpu[i]->lp_cntr[index]);
1376 c->lc_config = conf;
1379 c->lc_min = LC_MIN_INIT;
1382 c->lc_units = units;
1385 lprocfs_stats_unlock(stats);
1387 EXPORT_SYMBOL(lprocfs_counter_init);
1389 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1391 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1392 LASSERT(coffset < stats->ls_num); \
1393 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1396 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1398 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1399 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1400 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1401 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1402 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1403 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1404 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1405 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1406 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1407 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1408 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1409 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1410 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1411 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1412 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1413 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1414 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1415 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1416 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
1417 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1418 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1419 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1420 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1421 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1422 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1423 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1424 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1425 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1426 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1427 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1428 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1429 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1430 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1431 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1432 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1433 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1434 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1435 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1436 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1437 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1438 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1439 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1440 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1441 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1442 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1443 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1444 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1445 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1446 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1447 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1448 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1449 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1450 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1451 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1452 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1453 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1454 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1455 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1456 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1457 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1458 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quota_adjust_qunit);
1459 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1460 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1461 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1462 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1463 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1464 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1465 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1468 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1470 struct lprocfs_stats *stats;
1471 unsigned int num_stats;
1474 LASSERT(obd->obd_stats == NULL);
1475 LASSERT(obd->obd_proc_entry != NULL);
1476 LASSERT(obd->obd_cntr_base == 0);
1478 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1479 num_private_stats - 1 /* o_owner */;
1480 stats = lprocfs_alloc_stats(num_stats, 0);
1484 lprocfs_init_ops_stats(num_private_stats, stats);
1486 for (i = num_private_stats; i < num_stats; i++) {
1487 /* If this LBUGs, it is likely that an obd
1488 * operation was added to struct obd_ops in
1489 * <obd.h>, and that the corresponding line item
1490 * LPROCFS_OBD_OP_INIT(.., .., opname)
1491 * is missing from the list above. */
1492 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1493 "Missing obd_stat initializer obd_op "
1494 "operation at offset %d.\n", i - num_private_stats);
1496 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1498 lprocfs_free_stats(&stats);
1500 obd->obd_stats = stats;
1501 obd->obd_cntr_base = num_private_stats;
1506 void lprocfs_free_obd_stats(struct obd_device *obd)
1509 lprocfs_free_stats(&obd->obd_stats);
1512 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1514 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1515 LASSERT(coffset < stats->ls_num); \
1516 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1519 int lprocfs_alloc_md_stats(struct obd_device *obd,
1520 unsigned num_private_stats)
1522 struct lprocfs_stats *stats;
1523 unsigned int num_stats;
1526 LASSERT(obd->md_stats == NULL);
1527 LASSERT(obd->obd_proc_entry != NULL);
1528 LASSERT(obd->md_cntr_base == 0);
1530 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1532 stats = lprocfs_alloc_stats(num_stats, 0);
1536 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1537 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1538 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1539 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1540 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1541 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1542 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1543 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1544 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1545 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1546 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1547 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1548 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1549 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1550 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1551 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1552 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1553 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1554 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1555 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1556 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1557 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1558 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1559 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1560 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1561 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1562 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1563 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1564 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1565 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1566 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1568 for (i = num_private_stats; i < num_stats; i++) {
1569 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1570 CERROR("Missing md_stat initializer md_op "
1571 "operation at offset %d. Aborting.\n",
1572 i - num_private_stats);
1576 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1578 lprocfs_free_stats(&stats);
1580 obd->md_stats = stats;
1581 obd->md_cntr_base = num_private_stats;
1586 void lprocfs_free_md_stats(struct obd_device *obd)
1588 struct lprocfs_stats *stats = obd->md_stats;
1590 if (stats != NULL) {
1591 obd->md_stats = NULL;
1592 obd->md_cntr_base = 0;
1593 lprocfs_free_stats(&stats);
1597 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1599 lprocfs_counter_init(ldlm_stats,
1600 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1601 0, "ldlm_enqueue", "reqs");
1602 lprocfs_counter_init(ldlm_stats,
1603 LDLM_CONVERT - LDLM_FIRST_OPC,
1604 0, "ldlm_convert", "reqs");
1605 lprocfs_counter_init(ldlm_stats,
1606 LDLM_CANCEL - LDLM_FIRST_OPC,
1607 0, "ldlm_cancel", "reqs");
1608 lprocfs_counter_init(ldlm_stats,
1609 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1610 0, "ldlm_bl_callback", "reqs");
1611 lprocfs_counter_init(ldlm_stats,
1612 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1613 0, "ldlm_cp_callback", "reqs");
1614 lprocfs_counter_init(ldlm_stats,
1615 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1616 0, "ldlm_gl_callback", "reqs");
1619 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1620 int *eof, void *data)
1622 struct obd_export *exp = data;
1623 LASSERT(exp != NULL);
1625 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1628 struct exp_uuid_cb_data {
1636 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1637 int count, int *eof, int *len)
1639 cb_data->page = page;
1640 cb_data->count = count;
1645 void lprocfs_exp_print_uuid(void *obj, void *cb_data)
1647 struct obd_export *exp = (struct obd_export *)obj;
1648 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1650 if (exp->exp_nid_stats)
1651 *data->len += snprintf((data->page + *data->len),
1652 data->count, "%s\n",
1653 obd_uuid2str(&exp->exp_client_uuid));
1656 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1657 int *eof, void *data)
1659 struct nid_stat *stats = (struct nid_stat *)data;
1660 struct exp_uuid_cb_data cb_data;
1661 struct obd_device *obd = stats->nid_obd;
1666 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1667 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1668 lprocfs_exp_print_uuid, &cb_data);
1669 return (*cb_data.len);
1672 void lprocfs_exp_print_hash(void *obj, void *cb_data)
1674 struct exp_uuid_cb_data *data = cb_data;
1675 struct obd_export *exp = obj;
1678 hs = exp->exp_lock_hash;
1681 *data->len += cfs_hash_debug_header(data->page,
1684 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1689 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1690 int *eof, void *data)
1692 struct nid_stat *stats = (struct nid_stat *)data;
1693 struct exp_uuid_cb_data cb_data;
1694 struct obd_device *obd = stats->nid_obd;
1699 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1701 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1702 lprocfs_exp_print_hash, &cb_data);
1703 return (*cb_data.len);
1706 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1707 int count, int *eof, void *data)
1710 return snprintf(page, count, "%s\n",
1711 "Write into this file to clear all nid stats and "
1712 "stale nid entries");
1714 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1716 void lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1718 struct nid_stat *stat = obj;
1721 /* object has only hash + iterate_all references.
1722 * add/delete blocked by hash bucket lock */
1723 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
1724 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 2) {
1725 cfs_hlist_del_init(&stat->nid_hash);
1726 nidstat_putref(stat);
1727 cfs_spin_lock(&stat->nid_obd->obd_nid_lock);
1728 cfs_list_move(&stat->nid_list, data);
1729 cfs_spin_unlock(&stat->nid_obd->obd_nid_lock);
1733 /* we has reference to object - only clear data*/
1734 if (stat->nid_stats)
1735 lprocfs_clear_stats(stat->nid_stats);
1737 if (stat->nid_brw_stats) {
1738 for (i = 0; i < BRW_LAST; i++)
1739 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
1745 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1746 unsigned long count, void *data)
1748 struct obd_device *obd = (struct obd_device *)data;
1749 struct nid_stat *client_stat;
1750 CFS_LIST_HEAD(free_list);
1752 cfs_hash_for_each(obd->obd_nid_stats_hash,
1753 lprocfs_nid_stats_clear_write_cb, &free_list);
1755 while (!cfs_list_empty(&free_list)) {
1756 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
1758 cfs_list_del_init(&client_stat->nid_list);
1759 lprocfs_free_client_stats(client_stat);
1764 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1766 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1768 struct nid_stat *new_stat, *old_stat;
1769 struct obd_device *obd = NULL;
1770 cfs_proc_dir_entry_t *entry;
1776 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1777 !exp->exp_obd->obd_nid_stats_hash)
1780 /* not test against zero because eric say:
1781 * You may only test nid against another nid, or LNET_NID_ANY.
1782 * Anything else is nonsense.*/
1783 if (!nid || *nid == LNET_NID_ANY)
1788 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
1790 OBD_ALLOC_PTR(new_stat);
1791 if (new_stat == NULL)
1794 new_stat->nid = *nid;
1795 new_stat->nid_obd = exp->exp_obd;
1796 cfs_atomic_set(&new_stat->nid_exp_ref_count, 0);
1798 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
1799 nid, &new_stat->nid_hash);
1800 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
1801 old_stat, libcfs_nid2str(*nid),
1802 cfs_atomic_read(&new_stat->nid_exp_ref_count));
1804 /* Return -EALREADY here so that we know that the /proc
1805 * entry already has been created */
1806 if (old_stat != new_stat) {
1807 cfs_spin_lock(&obd->obd_nid_lock);
1808 if (exp->exp_nid_stats != old_stat) {
1809 if (exp->exp_nid_stats)
1810 nidstat_putref(exp->exp_nid_stats);
1811 exp->exp_nid_stats = old_stat;
1813 /* cfs_hash_findadd_unique() has added
1814 * old_stat's refcount */
1815 nidstat_putref(old_stat);
1818 cfs_spin_unlock(&obd->obd_nid_lock);
1820 GOTO(destroy_new, rc = -EALREADY);
1822 /* not found - create */
1823 new_stat->nid_proc = lprocfs_register(libcfs_nid2str(*nid),
1824 obd->obd_proc_exports_entry,
1826 if (new_stat->nid_proc == NULL) {
1827 CERROR("Error making export directory for nid %s\n",
1828 libcfs_nid2str(*nid));
1829 GOTO(destroy_new_ns, rc = -ENOMEM);
1832 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
1833 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
1834 if (IS_ERR(entry)) {
1835 CWARN("Error adding the NID stats file\n");
1836 rc = PTR_ERR(entry);
1837 GOTO(destroy_new_ns, rc);
1840 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
1841 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
1842 if (IS_ERR(entry)) {
1843 CWARN("Error adding the hash file\n");
1844 rc = PTR_ERR(entry);
1845 GOTO(destroy_new_ns, rc);
1848 if (exp->exp_nid_stats)
1849 nidstat_putref(exp->exp_nid_stats);
1850 nidstat_getref(new_stat);
1851 exp->exp_nid_stats = new_stat;
1853 /* protect competitive add to list, not need locking on destroy */
1854 cfs_spin_lock(&obd->obd_nid_lock);
1855 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
1856 cfs_spin_unlock(&obd->obd_nid_lock);
1861 if (new_stat->nid_proc != NULL)
1862 lprocfs_remove(&new_stat->nid_proc);
1863 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
1866 OBD_FREE_PTR(new_stat);
1870 int lprocfs_exp_cleanup(struct obd_export *exp)
1872 struct nid_stat *stat = exp->exp_nid_stats;
1874 if(!stat || !exp->exp_obd)
1877 nidstat_putref(exp->exp_nid_stats);
1878 exp->exp_nid_stats = NULL;
1883 int lprocfs_write_helper(const char *buffer, unsigned long count,
1886 return lprocfs_write_frac_helper(buffer, count, val, 1);
1889 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
1892 char kernbuf[20], *end, *pbuf;
1894 if (count > (sizeof(kernbuf) - 1))
1897 if (cfs_copy_from_user(kernbuf, buffer, count))
1900 kernbuf[count] = '\0';
1907 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1911 if (end != NULL && *end == '.') {
1912 int temp_val, pow = 1;
1916 if (strlen(pbuf) > 5)
1917 pbuf[5] = '\0'; /*only allow 5bits fractional*/
1919 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1922 for (i = 0; i < (end - pbuf); i++)
1925 *val += temp_val / pow;
1931 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
1934 long decimal_val, frac_val;
1940 decimal_val = val / mult;
1941 prtn = snprintf(buffer, count, "%ld", decimal_val);
1942 frac_val = val % mult;
1944 if (prtn < (count - 4) && frac_val > 0) {
1946 int i, temp_mult = 1, frac_bits = 0;
1948 temp_frac = frac_val * 10;
1949 buffer[prtn++] = '.';
1950 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
1951 /* only reserved 2 bits fraction */
1952 buffer[prtn++] ='0';
1957 * Need to think these cases :
1958 * 1. #echo x.00 > /proc/xxx output result : x
1959 * 2. #echo x.0x > /proc/xxx output result : x.0x
1960 * 3. #echo x.x0 > /proc/xxx output result : x.x
1961 * 4. #echo x.xx > /proc/xxx output result : x.xx
1962 * Only reserved 2 bits fraction.
1964 for (i = 0; i < (5 - prtn); i++)
1967 frac_bits = min((int)count - prtn, 3 - frac_bits);
1968 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
1969 frac_val * temp_mult / mult);
1972 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
1974 if (buffer[prtn] == '.') {
1981 buffer[prtn++] ='\n';
1985 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
1987 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
1990 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
1991 __u64 *val, int mult)
1993 char kernbuf[22], *end, *pbuf;
1994 __u64 whole, frac = 0, units;
1995 unsigned frac_d = 1;
1997 if (count > (sizeof(kernbuf) - 1))
2000 if (cfs_copy_from_user(kernbuf, buffer, count))
2003 kernbuf[count] = '\0';
2010 whole = simple_strtoull(pbuf, &end, 10);
2014 if (end != NULL && *end == '.') {
2018 /* need to limit frac_d to a __u32 */
2019 if (strlen(pbuf) > 10)
2022 frac = simple_strtoull(pbuf, &end, 10);
2023 /* count decimal places */
2024 for (i = 0; i < (end - pbuf); i++)
2041 /* Specified units override the multiplier */
2043 mult = mult < 0 ? -units : units;
2046 do_div(frac, frac_d);
2047 *val = whole * mult + frac;
2051 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent, char *name, mode_t mode,
2052 struct file_operations *seq_fops, void *data)
2054 struct proc_dir_entry *entry;
2057 entry = create_proc_entry(name, mode, parent);
2060 entry->proc_fops = seq_fops;
2065 EXPORT_SYMBOL(lprocfs_seq_create);
2067 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
2069 struct file_operations *seq_fops,
2072 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2073 mode, seq_fops, data));
2075 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2077 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2079 if (value >= OBD_HIST_MAX)
2080 value = OBD_HIST_MAX - 1;
2082 cfs_spin_lock(&oh->oh_lock);
2083 oh->oh_buckets[value]++;
2084 cfs_spin_unlock(&oh->oh_lock);
2086 EXPORT_SYMBOL(lprocfs_oh_tally);
2088 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2092 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2095 lprocfs_oh_tally(oh, val);
2097 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2099 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2101 unsigned long ret = 0;
2104 for (i = 0; i < OBD_HIST_MAX; i++)
2105 ret += oh->oh_buckets[i];
2108 EXPORT_SYMBOL(lprocfs_oh_sum);
2110 void lprocfs_oh_clear(struct obd_histogram *oh)
2112 cfs_spin_lock(&oh->oh_lock);
2113 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2114 cfs_spin_unlock(&oh->oh_lock);
2116 EXPORT_SYMBOL(lprocfs_oh_clear);
2118 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2119 int count, int *eof, void *data)
2121 struct obd_device *obd = data;
2127 c += cfs_hash_debug_header(page, count);
2128 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2129 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2130 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2134 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2136 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2137 int count, int *eof, void *data)
2139 struct obd_device *obd = data;
2142 LASSERT(obd != NULL);
2143 LASSERT(count >= 0);
2145 /* Set start of user data returned to
2146 page + off since the user may have
2147 requested to read much smaller than
2148 what we need to read */
2149 *start = page + off;
2151 /* We know we are allocated a page here.
2152 Also we know that this function will
2153 not need to write more than a page
2154 so we can truncate at CFS_PAGE_SIZE. */
2155 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2157 /* Initialize the page */
2158 memset(page, 0, size);
2160 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2162 if (obd->obd_max_recoverable_clients == 0) {
2163 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2169 /* sampled unlocked, but really... */
2170 if (obd->obd_recovering == 0) {
2171 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2173 if (lprocfs_obd_snprintf(&page, size, &len,
2174 "recovery_start: %lu\n",
2175 obd->obd_recovery_start) <= 0)
2177 if (lprocfs_obd_snprintf(&page, size, &len,
2178 "recovery_duration: %lu\n",
2179 obd->obd_recovery_end -
2180 obd->obd_recovery_start) <= 0)
2182 /* Number of clients that have completed recovery */
2183 if (lprocfs_obd_snprintf(&page, size, &len,
2184 "completed_clients: %d/%d\n",
2185 obd->obd_max_recoverable_clients -
2186 obd->obd_stale_clients,
2187 obd->obd_max_recoverable_clients) <= 0)
2189 if (lprocfs_obd_snprintf(&page, size, &len,
2190 "replayed_requests: %d\n",
2191 obd->obd_replayed_requests) <= 0)
2193 if (lprocfs_obd_snprintf(&page, size, &len,
2194 "last_transno: "LPD64"\n",
2195 obd->obd_next_recovery_transno - 1)<=0)
2197 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2198 obd->obd_version_recov ? "ON" : "OFF")<=0)
2203 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2205 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2206 obd->obd_recovery_start) <= 0)
2208 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2209 cfs_time_current_sec() >= obd->obd_recovery_end ? 0 :
2210 obd->obd_recovery_end - cfs_time_current_sec()) <= 0)
2212 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2213 obd->obd_connected_clients,
2214 obd->obd_max_recoverable_clients) <= 0)
2216 /* Number of clients that have completed recovery */
2217 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2218 cfs_atomic_read(&obd->obd_req_replay_clients))
2221 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2222 cfs_atomic_read(&obd->obd_lock_replay_clients))
2225 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2226 obd->obd_connected_clients -
2227 cfs_atomic_read(&obd->obd_lock_replay_clients))
2230 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2231 obd->obd_stale_clients) <= 0)
2233 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2234 obd->obd_replayed_requests) <= 0)
2236 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2237 obd->obd_requests_queued_for_recovery) <= 0)
2240 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2241 obd->obd_next_recovery_transno) <= 0)
2247 return min(count, len - (int)off);
2249 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2251 int lprocfs_obd_rd_recovery_maxtime(char *page, char **start, off_t off,
2252 int count, int *eof, void *data)
2254 struct obd_device *obd = data;
2255 LASSERT(obd != NULL);
2257 return snprintf(page, count, "%lu\n", obd->obd_recovery_max_time);
2259 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_maxtime);
2261 int lprocfs_obd_wr_recovery_maxtime(struct file *file, const char *buffer,
2262 unsigned long count, void *data)
2264 struct obd_device *obd = data;
2266 LASSERT(obd != NULL);
2268 rc = lprocfs_write_helper(buffer, count, &val);
2272 obd->obd_recovery_max_time = val;
2275 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_maxtime);
2278 EXPORT_SYMBOL(lprocfs_register);
2279 EXPORT_SYMBOL(lprocfs_srch);
2280 EXPORT_SYMBOL(lprocfs_remove);
2281 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
2282 EXPORT_SYMBOL(lprocfs_add_vars);
2283 EXPORT_SYMBOL(lprocfs_obd_setup);
2284 EXPORT_SYMBOL(lprocfs_obd_cleanup);
2285 EXPORT_SYMBOL(lprocfs_add_simple);
2286 EXPORT_SYMBOL(lprocfs_add_symlink);
2287 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
2288 EXPORT_SYMBOL(lprocfs_alloc_stats);
2289 EXPORT_SYMBOL(lprocfs_free_stats);
2290 EXPORT_SYMBOL(lprocfs_clear_stats);
2291 EXPORT_SYMBOL(lprocfs_register_stats);
2292 EXPORT_SYMBOL(lprocfs_init_ops_stats);
2293 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
2294 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
2295 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
2296 EXPORT_SYMBOL(lprocfs_free_obd_stats);
2297 EXPORT_SYMBOL(lprocfs_free_md_stats);
2298 EXPORT_SYMBOL(lprocfs_exp_setup);
2299 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2301 EXPORT_SYMBOL(lprocfs_rd_u64);
2302 EXPORT_SYMBOL(lprocfs_rd_atomic);
2303 EXPORT_SYMBOL(lprocfs_wr_atomic);
2304 EXPORT_SYMBOL(lprocfs_rd_uint);
2305 EXPORT_SYMBOL(lprocfs_wr_uint);
2306 EXPORT_SYMBOL(lprocfs_rd_uuid);
2307 EXPORT_SYMBOL(lprocfs_rd_name);
2308 EXPORT_SYMBOL(lprocfs_rd_fstype);
2309 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
2310 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
2311 EXPORT_SYMBOL(lprocfs_rd_num_exports);
2312 EXPORT_SYMBOL(lprocfs_rd_numrefs);
2313 EXPORT_SYMBOL(lprocfs_at_hist_helper);
2314 EXPORT_SYMBOL(lprocfs_rd_import);
2315 EXPORT_SYMBOL(lprocfs_rd_state);
2316 EXPORT_SYMBOL(lprocfs_rd_timeouts);
2317 EXPORT_SYMBOL(lprocfs_rd_blksize);
2318 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
2319 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
2320 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
2321 EXPORT_SYMBOL(lprocfs_rd_filestotal);
2322 EXPORT_SYMBOL(lprocfs_rd_filesfree);
2323 EXPORT_SYMBOL(lprocfs_rd_quota_resend_count);
2324 EXPORT_SYMBOL(lprocfs_wr_quota_resend_count);
2326 EXPORT_SYMBOL(lprocfs_write_helper);
2327 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2328 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2329 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2330 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2331 EXPORT_SYMBOL(lprocfs_stats_collect);