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 *dest)
150 struct proc_dir_entry *entry;
152 if (parent == NULL || dest == NULL)
155 entry = proc_symlink(name, parent, dest);
157 CERROR("LprocFS: Could not create symbolic link from %s to %s",
162 static ssize_t lprocfs_fops_read(struct file *f, char __user *buf,
163 size_t size, loff_t *ppos)
165 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
166 char *page, *start = NULL;
167 int rc = 0, eof = 1, count;
169 if (*ppos >= CFS_PAGE_SIZE)
172 page = (char *)__get_free_page(GFP_KERNEL);
176 if (LPROCFS_ENTRY_AND_CHECK(dp))
179 OBD_FAIL_TIMEOUT(OBD_FAIL_LPROC_REMOVE, 10);
181 rc = dp->read_proc(page, &start, *ppos, CFS_PAGE_SIZE,
187 /* for lustre proc read, the read count must be less than PAGE_SIZE */
196 start = page + *ppos;
197 } else if (start < page) {
201 count = (rc < size) ? rc : size;
202 if (cfs_copy_to_user(buf, start, count)) {
209 free_page((unsigned long)page);
213 static ssize_t lprocfs_fops_write(struct file *f, const char __user *buf,
214 size_t size, loff_t *ppos)
216 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
219 if (LPROCFS_ENTRY_AND_CHECK(dp))
222 rc = dp->write_proc(f, buf, size, dp->data);
227 static struct file_operations lprocfs_generic_fops = {
228 .owner = THIS_MODULE,
229 .read = lprocfs_fops_read,
230 .write = lprocfs_fops_write,
233 int lprocfs_evict_client_open(struct inode *inode, struct file *f)
235 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
236 struct obd_device *obd = dp->data;
238 cfs_atomic_inc(&obd->obd_evict_inprogress);
243 int lprocfs_evict_client_release(struct inode *inode, struct file *f)
245 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
246 struct obd_device *obd = dp->data;
248 cfs_atomic_dec(&obd->obd_evict_inprogress);
249 cfs_waitq_signal(&obd->obd_evict_inprogress_waitq);
254 struct file_operations lprocfs_evict_client_fops = {
255 .owner = THIS_MODULE,
256 .read = lprocfs_fops_read,
257 .write = lprocfs_fops_write,
258 .open = lprocfs_evict_client_open,
259 .release = lprocfs_evict_client_release,
261 EXPORT_SYMBOL(lprocfs_evict_client_fops);
266 * \param root [in] The parent proc entry on which new entry will be added.
267 * \param list [in] Array of proc entries to be added.
268 * \param data [in] The argument to be passed when entries read/write routines
269 * are called through /proc file.
271 * \retval 0 on success
274 int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list,
277 if (root == NULL || list == NULL)
280 while (list->name != NULL) {
281 struct proc_dir_entry *cur_root, *proc;
282 char *pathcopy, *cur, *next, pathbuf[64];
283 int pathsize = strlen(list->name) + 1;
288 /* need copy of path for strsep */
289 if (strlen(list->name) > sizeof(pathbuf) - 1) {
290 OBD_ALLOC(pathcopy, pathsize);
291 if (pathcopy == NULL)
298 strcpy(pathcopy, list->name);
300 while (cur_root != NULL && (cur = strsep(&next, "/"))) {
301 if (*cur =='\0') /* skip double/trailing "/" */
304 proc = lprocfs_srch(cur_root, cur);
305 CDEBUG(D_OTHER, "cur_root=%s, cur=%s, next=%s, (%s)\n",
306 cur_root->name, cur, next,
307 (proc ? "exists" : "new"));
309 cur_root = (proc ? proc :
310 proc_mkdir(cur, cur_root));
311 } else if (proc == NULL) {
313 if (list->proc_mode != 0000) {
314 mode = list->proc_mode;
318 if (list->write_fptr)
321 proc = create_proc_entry(cur, mode, cur_root);
325 if (pathcopy != pathbuf)
326 OBD_FREE(pathcopy, pathsize);
328 if (cur_root == NULL || proc == NULL) {
329 CERROR("LprocFS: No memory to create /proc entry %s",
335 proc->proc_fops = list->fops;
337 proc->proc_fops = &lprocfs_generic_fops;
338 proc->read_proc = list->read_fptr;
339 proc->write_proc = list->write_fptr;
340 proc->data = (list->data ? list->data : data);
346 void lprocfs_remove(struct proc_dir_entry **rooth)
348 struct proc_dir_entry *root = *rooth;
349 struct proc_dir_entry *temp = root;
350 struct proc_dir_entry *rm_entry;
351 struct proc_dir_entry *parent;
357 parent = root->parent;
358 LASSERT(parent != NULL);
359 LPROCFS_WRITE_ENTRY(); /* search vs remove race */
362 while (temp->subdir != NULL)
368 /* Memory corruption once caused this to fail, and
369 without this LASSERT we would loop here forever. */
370 LASSERTF(strlen(rm_entry->name) == rm_entry->namelen,
371 "0x%p %s/%s len %d\n", rm_entry, temp->name,
372 rm_entry->name, (int)strlen(rm_entry->name));
374 /* Now, the rm_entry->deleted flags is protected
375 * by _lprocfs_lock. */
376 rm_entry->data = NULL;
377 remove_proc_entry(rm_entry->name, temp);
381 LPROCFS_WRITE_EXIT();
384 void lprocfs_remove_proc_entry(const char *name, struct proc_dir_entry *parent)
386 LASSERT(parent != NULL);
387 remove_proc_entry(name, parent);
390 struct proc_dir_entry *lprocfs_register(const char *name,
391 struct proc_dir_entry *parent,
392 struct lprocfs_vars *list, void *data)
394 struct proc_dir_entry *newchild;
396 newchild = lprocfs_srch(parent, name);
397 if (newchild != NULL) {
398 CERROR(" Lproc: Attempting to register %s more than once \n",
400 return ERR_PTR(-EALREADY);
403 newchild = proc_mkdir(name, parent);
404 if (newchild != NULL && list != NULL) {
405 int rc = lprocfs_add_vars(newchild, list, data);
407 lprocfs_remove(&newchild);
414 /* Generic callbacks */
415 int lprocfs_rd_uint(char *page, char **start, off_t off,
416 int count, int *eof, void *data)
418 unsigned int *temp = data;
419 return snprintf(page, count, "%u\n", *temp);
422 int lprocfs_wr_uint(struct file *file, const char *buffer,
423 unsigned long count, void *data)
426 char dummy[MAX_STRING_SIZE + 1], *end;
429 dummy[MAX_STRING_SIZE] = '\0';
430 if (cfs_copy_from_user(dummy, buffer, MAX_STRING_SIZE))
433 tmp = simple_strtoul(dummy, &end, 0);
437 *p = (unsigned int)tmp;
441 int lprocfs_rd_u64(char *page, char **start, off_t off,
442 int count, int *eof, void *data)
444 LASSERT(data != NULL);
446 return snprintf(page, count, LPU64"\n", *(__u64 *)data);
449 int lprocfs_rd_atomic(char *page, char **start, off_t off,
450 int count, int *eof, void *data)
452 cfs_atomic_t *atom = data;
453 LASSERT(atom != NULL);
455 return snprintf(page, count, "%d\n", cfs_atomic_read(atom));
458 int lprocfs_wr_atomic(struct file *file, const char *buffer,
459 unsigned long count, void *data)
461 cfs_atomic_t *atm = data;
465 rc = lprocfs_write_helper(buffer, count, &val);
472 cfs_atomic_set(atm, val);
476 int lprocfs_rd_uuid(char *page, char **start, off_t off, int count,
477 int *eof, void *data)
479 struct obd_device *obd = data;
481 LASSERT(obd != NULL);
483 return snprintf(page, count, "%s\n", obd->obd_uuid.uuid);
486 int lprocfs_rd_name(char *page, char **start, off_t off, int count,
487 int *eof, void *data)
489 struct obd_device *dev = data;
491 LASSERT(dev != NULL);
492 LASSERT(dev->obd_name != NULL);
494 return snprintf(page, count, "%s\n", dev->obd_name);
497 int lprocfs_rd_fstype(char *page, char **start, off_t off, int count, int *eof,
500 struct obd_device *obd = data;
502 LASSERT(obd != NULL);
503 LASSERT(obd->obd_fsops != NULL);
504 LASSERT(obd->obd_fsops->fs_type != NULL);
505 return snprintf(page, count, "%s\n", obd->obd_fsops->fs_type);
508 int lprocfs_rd_blksize(char *page, char **start, off_t off, int count,
509 int *eof, void *data)
511 struct obd_statfs osfs;
512 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - CFS_HZ,
516 rc = snprintf(page, count, "%u\n", osfs.os_bsize);
521 int lprocfs_rd_kbytestotal(char *page, char **start, off_t off, int count,
522 int *eof, void *data)
524 struct obd_statfs osfs;
525 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - CFS_HZ,
528 __u32 blk_size = osfs.os_bsize >> 10;
529 __u64 result = osfs.os_blocks;
531 while (blk_size >>= 1)
535 rc = snprintf(page, count, LPU64"\n", result);
540 int lprocfs_rd_kbytesfree(char *page, char **start, off_t off, int count,
541 int *eof, void *data)
543 struct obd_statfs osfs;
544 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - CFS_HZ,
547 __u32 blk_size = osfs.os_bsize >> 10;
548 __u64 result = osfs.os_bfree;
550 while (blk_size >>= 1)
554 rc = snprintf(page, count, LPU64"\n", result);
559 int lprocfs_rd_kbytesavail(char *page, char **start, off_t off, int count,
560 int *eof, void *data)
562 struct obd_statfs osfs;
563 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - CFS_HZ,
566 __u32 blk_size = osfs.os_bsize >> 10;
567 __u64 result = osfs.os_bavail;
569 while (blk_size >>= 1)
573 rc = snprintf(page, count, LPU64"\n", result);
578 int lprocfs_rd_filestotal(char *page, char **start, off_t off, int count,
579 int *eof, void *data)
581 struct obd_statfs osfs;
582 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - CFS_HZ,
586 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
592 int lprocfs_rd_filesfree(char *page, char **start, off_t off, int count,
593 int *eof, void *data)
595 struct obd_statfs osfs;
596 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - CFS_HZ,
600 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
605 int lprocfs_rd_server_uuid(char *page, char **start, off_t off, int count,
606 int *eof, void *data)
608 struct obd_device *obd = data;
609 struct obd_import *imp;
610 char *imp_state_name = NULL;
613 LASSERT(obd != NULL);
614 LPROCFS_CLIMP_CHECK(obd);
615 imp = obd->u.cli.cl_import;
616 imp_state_name = ptlrpc_import_state_name(imp->imp_state);
618 rc = snprintf(page, count, "%s\t%s%s\n",
619 obd2cli_tgt(obd), imp_state_name,
620 imp->imp_deactive ? "\tDEACTIVATED" : "");
622 LPROCFS_CLIMP_EXIT(obd);
626 int lprocfs_rd_conn_uuid(char *page, char **start, off_t off, int count,
627 int *eof, void *data)
629 struct obd_device *obd = data;
630 struct ptlrpc_connection *conn;
633 LASSERT(obd != NULL);
635 LPROCFS_CLIMP_CHECK(obd);
636 conn = obd->u.cli.cl_import->imp_connection;
638 if (conn && obd->u.cli.cl_import) {
639 rc = snprintf(page, count, "%s\n",
640 conn->c_remote_uuid.uuid);
642 rc = snprintf(page, count, "%s\n", "<none>");
645 LPROCFS_CLIMP_EXIT(obd);
649 /** add up per-cpu counters */
650 void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
651 struct lprocfs_counter *cnt)
653 unsigned int num_cpu;
654 struct lprocfs_counter t;
655 struct lprocfs_counter *percpu_cntr;
658 memset(cnt, 0, sizeof(*cnt));
661 /* set count to 1 to avoid divide-by-zero errs in callers */
666 cnt->lc_min = LC_MIN_INIT;
668 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
671 num_cpu = cfs_num_possible_cpus();
673 for (i = 0; i < num_cpu; i++) {
674 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[idx];
677 centry = cfs_atomic_read(&percpu_cntr-> \
679 t.lc_count = percpu_cntr->lc_count;
680 t.lc_sum = percpu_cntr->lc_sum;
681 t.lc_min = percpu_cntr->lc_min;
682 t.lc_max = percpu_cntr->lc_max;
683 t.lc_sumsquare = percpu_cntr->lc_sumsquare;
684 } while (centry != cfs_atomic_read(&percpu_cntr->lc_cntl. \
686 centry != cfs_atomic_read(&percpu_cntr->lc_cntl. \
688 cnt->lc_count += t.lc_count;
689 cnt->lc_sum += t.lc_sum;
690 if (t.lc_min < cnt->lc_min)
691 cnt->lc_min = t.lc_min;
692 if (t.lc_max > cnt->lc_max)
693 cnt->lc_max = t.lc_max;
694 cnt->lc_sumsquare += t.lc_sumsquare;
697 cnt->lc_units = stats->ls_percpu[0]->lp_cntr[idx].lc_units;
701 * Append a space separated list of current set flags to str.
703 #define flag2str(flag) \
704 if (imp->imp_##flag && max - len > 0) \
705 len += snprintf(str + len, max - len, "%s" #flag, len ? ", " : "");
706 static int obd_import_flags2str(struct obd_import *imp, char *str, int max)
710 if (imp->imp_obd->obd_no_recov)
711 len += snprintf(str, max - len, "no_recov");
715 flag2str(replayable);
718 flag2str(last_recon);
723 static const char *obd_connect_names[] = {
737 "join_file(obsolete)",
741 "remote_client_by_force",
750 "mds_mds_connection",
753 "alt_checksum_algorithm",
762 static int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
767 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
769 ret += snprintf(page + ret, count - ret, "%s%s",
770 ret ? sep : "", obd_connect_names[i]);
772 if (flags & ~(mask - 1))
773 ret += snprintf(page + ret, count - ret,
774 "%sunknown flags "LPX64,
775 ret ? sep : "", flags & ~(mask - 1));
779 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
780 int *eof, void *data)
782 struct lprocfs_counter ret;
783 struct obd_device *obd = (struct obd_device *)data;
784 struct obd_import *imp;
787 LASSERT(obd != NULL);
788 LPROCFS_CLIMP_CHECK(obd);
789 imp = obd->u.cli.cl_import;
792 i = snprintf(page, count,
796 " current_connection: %s\n"
801 imp->imp_connection->c_remote_uuid.uuid,
802 ptlrpc_import_state_name(imp->imp_state));
803 i += obd_connect_flags2str(page + i, count - i,
804 imp->imp_connect_data.ocd_connect_flags,
806 i += snprintf(page + i, count - i,
809 i += obd_import_flags2str(imp, page + i, count - i);
811 i += snprintf(page + i, count - i,
814 " connection_attempts: %u\n"
816 " in-progress_invalidations: %u\n",
819 cfs_atomic_read(&imp->imp_inval_count));
821 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
822 do_div(ret.lc_sum, ret.lc_count);
823 i += snprintf(page + i, count - i,
826 " unregistering: %u\n"
828 " avg_waittime: "LPU64" %s\n",
829 cfs_atomic_read(&imp->imp_inflight),
830 cfs_atomic_read(&imp->imp_unregistering),
831 cfs_atomic_read(&imp->imp_timeouts),
832 ret.lc_sum, ret.lc_units);
835 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
836 if (imp->imp_at.iat_portal[j] == 0)
838 k = max_t(unsigned int, k,
839 at_get(&imp->imp_at.iat_service_estimate[j]));
841 i += snprintf(page + i, count - i,
842 " service_estimates:\n"
843 " services: %u sec\n"
844 " network: %u sec\n",
846 at_get(&imp->imp_at.iat_net_latency));
848 i += snprintf(page + i, count - i,
850 " last_replay: "LPU64"\n"
851 " peer_committed: "LPU64"\n"
852 " last_checked: "LPU64"\n",
853 imp->imp_last_replay_transno,
854 imp->imp_peer_committed_transno,
855 imp->imp_last_transno_checked);
858 for (rw = 0; rw <= 1; rw++) {
859 lprocfs_stats_collect(obd->obd_svc_stats,
860 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
862 if (ret.lc_sum > 0) {
863 do_div(ret.lc_sum, ret.lc_count);
864 i += snprintf(page + i, count - i,
865 " %s_data_averages:\n"
866 " bytes_per_rpc: "LPU64"\n",
867 rw ? "write" : "read",
871 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
872 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
873 if (ret.lc_sum > 0) {
874 do_div(ret.lc_sum, ret.lc_count);
875 i += snprintf(page + i, count - i,
876 " %s_per_rpc: "LPU64"\n",
877 ret.lc_units, ret.lc_sum);
880 i += snprintf(page + i, count - i,
881 " MB_per_sec: %u.%.02u\n",
882 k / j, (100 * k / j) % 100);
886 LPROCFS_CLIMP_EXIT(obd);
890 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
891 int *eof, void *data)
893 struct obd_device *obd = (struct obd_device *)data;
894 struct obd_import *imp;
897 LASSERT(obd != NULL);
898 LPROCFS_CLIMP_CHECK(obd);
899 imp = obd->u.cli.cl_import;
902 i = snprintf(page, count, "current_state: %s\n",
903 ptlrpc_import_state_name(imp->imp_state));
904 i += snprintf(page + i, count - i,
906 k = imp->imp_state_hist_idx;
907 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
908 struct import_state_hist *ish =
909 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
910 if (ish->ish_state == 0)
912 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
914 ptlrpc_import_state_name(ish->ish_state));
917 LPROCFS_CLIMP_EXIT(obd);
921 int lprocfs_at_hist_helper(char *page, int count, int rc,
922 struct adaptive_timeout *at)
925 for (i = 0; i < AT_BINS; i++)
926 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
927 rc += snprintf(page + rc, count - rc, "\n");
931 int lprocfs_rd_quota_resend_count(char *page, char **start, off_t off,
932 int count, int *eof, void *data)
934 struct obd_device *obd = data;
936 return snprintf(page, count, "%d\n",
937 cfs_atomic_read(&obd->u.cli.cl_quota_resends));
940 int lprocfs_wr_quota_resend_count(struct file *file, const char *buffer,
941 unsigned long count, void *data)
943 struct obd_device *obd = data;
946 rc = lprocfs_write_helper(buffer, count, &val);
950 cfs_atomic_set(&obd->u.cli.cl_quota_resends, val);
955 /* See also ptlrpc_lprocfs_rd_timeouts */
956 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
957 int *eof, void *data)
959 struct obd_device *obd = (struct obd_device *)data;
960 struct obd_import *imp;
961 unsigned int cur, worst;
966 LASSERT(obd != NULL);
967 LPROCFS_CLIMP_CHECK(obd);
968 imp = obd->u.cli.cl_import;
971 now = cfs_time_current_sec();
973 /* Some network health info for kicks */
974 s2dhms(&ts, now - imp->imp_last_reply_time);
975 rc += snprintf(page + rc, count - rc,
976 "%-10s : %ld, "DHMS_FMT" ago\n",
977 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
979 cur = at_get(&imp->imp_at.iat_net_latency);
980 worst = imp->imp_at.iat_net_latency.at_worst_ever;
981 worstt = imp->imp_at.iat_net_latency.at_worst_time;
982 s2dhms(&ts, now - worstt);
983 rc += snprintf(page + rc, count - rc,
984 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
985 "network", cur, worst, worstt, DHMS_VARS(&ts));
986 rc = lprocfs_at_hist_helper(page, count, rc,
987 &imp->imp_at.iat_net_latency);
989 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
990 if (imp->imp_at.iat_portal[i] == 0)
992 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
993 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
994 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
995 s2dhms(&ts, now - worstt);
996 rc += snprintf(page + rc, count - rc,
997 "portal %-2d : cur %3u worst %3u (at %ld, "
998 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
999 cur, worst, worstt, DHMS_VARS(&ts));
1000 rc = lprocfs_at_hist_helper(page, count, rc,
1001 &imp->imp_at.iat_service_estimate[i]);
1004 LPROCFS_CLIMP_EXIT(obd);
1008 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1009 int count, int *eof, void *data)
1011 struct obd_device *obd = data;
1015 LPROCFS_CLIMP_CHECK(obd);
1016 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1017 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1018 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1019 ret += snprintf(page + ret, count - ret, "\n");
1020 LPROCFS_CLIMP_EXIT(obd);
1023 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1025 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1026 int *eof, void *data)
1028 struct obd_device *obd = data;
1030 LASSERT(obd != NULL);
1032 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1035 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1036 int *eof, void *data)
1038 struct obd_type *class = (struct obd_type*) data;
1040 LASSERT(class != NULL);
1042 return snprintf(page, count, "%d\n", class->typ_refcnt);
1045 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1049 LASSERT(obd != NULL);
1050 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1051 LASSERT(obd->obd_type->typ_procroot != NULL);
1053 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1054 obd->obd_type->typ_procroot,
1056 if (IS_ERR(obd->obd_proc_entry)) {
1057 rc = PTR_ERR(obd->obd_proc_entry);
1058 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1059 obd->obd_proc_entry = NULL;
1064 int lprocfs_obd_cleanup(struct obd_device *obd)
1068 if (obd->obd_proc_exports_entry) {
1069 /* Should be no exports left */
1070 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1071 lprocfs_remove(&obd->obd_proc_exports_entry);
1072 obd->obd_proc_exports_entry = NULL;
1074 if (obd->obd_proc_entry) {
1075 lprocfs_remove(&obd->obd_proc_entry);
1076 obd->obd_proc_entry = NULL;
1081 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1083 CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
1084 client_stat->nid_proc, client_stat->nid_stats,
1085 client_stat->nid_brw_stats);
1087 LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
1089 cfs_atomic_read(&client_stat->nid_exp_ref_count));
1091 cfs_hlist_del_init(&client_stat->nid_hash);
1093 if (client_stat->nid_proc)
1094 lprocfs_remove(&client_stat->nid_proc);
1096 if (client_stat->nid_stats)
1097 lprocfs_free_stats(&client_stat->nid_stats);
1099 if (client_stat->nid_brw_stats)
1100 OBD_FREE_PTR(client_stat->nid_brw_stats);
1102 if (client_stat->nid_ldlm_stats)
1103 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1105 OBD_FREE_PTR(client_stat);
1110 void lprocfs_free_per_client_stats(struct obd_device *obd)
1112 struct nid_stat *stat;
1115 /* we need extra list - because hash_exit called to early */
1116 /* not need locking because all clients is died */
1117 while(!cfs_list_empty(&obd->obd_nid_stats)) {
1118 stat = cfs_list_entry(obd->obd_nid_stats.next,
1119 struct nid_stat, nid_list);
1120 cfs_list_del_init(&stat->nid_list);
1121 lprocfs_free_client_stats(stat);
1127 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1128 enum lprocfs_stats_flags flags)
1130 struct lprocfs_stats *stats;
1131 unsigned int percpusize;
1133 unsigned int num_cpu;
1138 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1141 num_cpu = cfs_num_possible_cpus();
1143 OBD_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
1147 if (flags & LPROCFS_STATS_FLAG_NOPERCPU) {
1148 stats->ls_flags = flags;
1149 cfs_spin_lock_init(&stats->ls_lock);
1150 /* Use this lock only if there are no percpu areas */
1152 stats->ls_flags = 0;
1155 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
1157 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1159 for (i = 0; i < num_cpu; i++) {
1160 OBD_ALLOC(stats->ls_percpu[i], percpusize);
1161 if (stats->ls_percpu[i] == NULL) {
1162 for (j = 0; j < i; j++) {
1163 OBD_FREE(stats->ls_percpu[j], percpusize);
1164 stats->ls_percpu[j] = NULL;
1169 if (stats->ls_percpu[0] == NULL) {
1170 OBD_FREE(stats, offsetof(typeof(*stats),
1171 ls_percpu[num_cpu]));
1175 stats->ls_num = num;
1179 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1181 struct lprocfs_stats *stats = *statsh;
1182 unsigned int num_cpu;
1183 unsigned int percpusize;
1186 if (stats == NULL || stats->ls_num == 0)
1190 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1193 num_cpu = cfs_num_possible_cpus();
1195 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
1197 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1198 for (i = 0; i < num_cpu; i++)
1199 OBD_FREE(stats->ls_percpu[i], percpusize);
1200 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
1203 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1205 struct lprocfs_counter *percpu_cntr;
1207 unsigned int num_cpu;
1209 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1211 for (i = 0; i < num_cpu; i++) {
1212 for (j = 0; j < stats->ls_num; j++) {
1213 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
1214 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_entry);
1215 percpu_cntr->lc_count = 0;
1216 percpu_cntr->lc_sum = 0;
1217 percpu_cntr->lc_min = LC_MIN_INIT;
1218 percpu_cntr->lc_max = 0;
1219 percpu_cntr->lc_sumsquare = 0;
1220 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_exit);
1224 lprocfs_stats_unlock(stats);
1227 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1228 size_t len, loff_t *off)
1230 struct seq_file *seq = file->private_data;
1231 struct lprocfs_stats *stats = seq->private;
1233 lprocfs_clear_stats(stats);
1238 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1240 struct lprocfs_stats *stats = p->private;
1241 /* return 1st cpu location */
1242 return (*pos >= stats->ls_num) ? NULL :
1243 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1246 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1250 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1252 struct lprocfs_stats *stats = p->private;
1254 return (*pos >= stats->ls_num) ? NULL :
1255 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1258 /* seq file export of one lprocfs counter */
1259 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1261 struct lprocfs_stats *stats = p->private;
1262 struct lprocfs_counter *cntr = v;
1263 struct lprocfs_counter ret;
1266 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
1268 cfs_gettimeofday(&now);
1269 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1270 "snapshot_time", now.tv_sec, now.tv_usec);
1274 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
1276 lprocfs_stats_collect(stats, idx, &ret);
1278 if (ret.lc_count == 0)
1281 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", cntr->lc_name,
1282 ret.lc_count, cntr->lc_units);
1287 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
1288 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1289 ret.lc_min, ret.lc_max, ret.lc_sum);
1292 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
1293 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1297 rc = seq_printf(p, "\n");
1299 return (rc < 0) ? rc : 0;
1302 struct seq_operations lprocfs_stats_seq_sops = {
1303 start: lprocfs_stats_seq_start,
1304 stop: lprocfs_stats_seq_stop,
1305 next: lprocfs_stats_seq_next,
1306 show: lprocfs_stats_seq_show,
1309 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1311 struct proc_dir_entry *dp = PDE(inode);
1312 struct seq_file *seq;
1315 if (LPROCFS_ENTRY_AND_CHECK(dp))
1318 rc = seq_open(file, &lprocfs_stats_seq_sops);
1323 seq = file->private_data;
1324 seq->private = dp->data;
1328 struct file_operations lprocfs_stats_seq_fops = {
1329 .owner = THIS_MODULE,
1330 .open = lprocfs_stats_seq_open,
1332 .write = lprocfs_stats_seq_write,
1333 .llseek = seq_lseek,
1334 .release = lprocfs_seq_release,
1337 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1338 struct lprocfs_stats *stats)
1340 struct proc_dir_entry *entry;
1341 LASSERT(root != NULL);
1343 entry = create_proc_entry(name, 0644, root);
1346 entry->proc_fops = &lprocfs_stats_seq_fops;
1347 entry->data = stats;
1351 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1352 unsigned conf, const char *name, const char *units)
1354 struct lprocfs_counter *c;
1356 unsigned int num_cpu;
1358 LASSERT(stats != NULL);
1360 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1362 for (i = 0; i < num_cpu; i++) {
1363 c = &(stats->ls_percpu[i]->lp_cntr[index]);
1364 c->lc_config = conf;
1367 c->lc_min = LC_MIN_INIT;
1370 c->lc_units = units;
1373 lprocfs_stats_unlock(stats);
1375 EXPORT_SYMBOL(lprocfs_counter_init);
1377 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1379 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1380 LASSERT(coffset < stats->ls_num); \
1381 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1384 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1386 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1387 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1388 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1389 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1390 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1391 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1392 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1393 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1394 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1395 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1396 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1397 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1398 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1399 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1400 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1401 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1402 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1403 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1404 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
1405 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1406 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1407 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1408 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1409 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1410 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1411 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1412 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1413 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1414 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1415 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1416 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1417 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1418 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1419 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1420 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1421 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1422 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1423 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1424 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1425 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1426 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1427 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1428 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1429 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1430 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1431 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1432 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1433 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1434 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1435 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1436 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1437 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1438 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1439 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1440 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1441 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1442 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1443 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1444 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1445 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1446 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quota_adjust_qunit);
1447 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1448 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1449 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1450 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1451 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1452 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1453 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1456 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1458 struct lprocfs_stats *stats;
1459 unsigned int num_stats;
1462 LASSERT(obd->obd_stats == NULL);
1463 LASSERT(obd->obd_proc_entry != NULL);
1464 LASSERT(obd->obd_cntr_base == 0);
1466 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1467 num_private_stats - 1 /* o_owner */;
1468 stats = lprocfs_alloc_stats(num_stats, 0);
1472 lprocfs_init_ops_stats(num_private_stats, stats);
1474 for (i = num_private_stats; i < num_stats; i++) {
1475 /* If this LBUGs, it is likely that an obd
1476 * operation was added to struct obd_ops in
1477 * <obd.h>, and that the corresponding line item
1478 * LPROCFS_OBD_OP_INIT(.., .., opname)
1479 * is missing from the list above. */
1480 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1481 "Missing obd_stat initializer obd_op "
1482 "operation at offset %d.\n", i - num_private_stats);
1484 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1486 lprocfs_free_stats(&stats);
1488 obd->obd_stats = stats;
1489 obd->obd_cntr_base = num_private_stats;
1494 void lprocfs_free_obd_stats(struct obd_device *obd)
1497 lprocfs_free_stats(&obd->obd_stats);
1500 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1502 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1503 LASSERT(coffset < stats->ls_num); \
1504 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1507 int lprocfs_alloc_md_stats(struct obd_device *obd,
1508 unsigned num_private_stats)
1510 struct lprocfs_stats *stats;
1511 unsigned int num_stats;
1514 LASSERT(obd->md_stats == NULL);
1515 LASSERT(obd->obd_proc_entry != NULL);
1516 LASSERT(obd->md_cntr_base == 0);
1518 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1520 stats = lprocfs_alloc_stats(num_stats, 0);
1524 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1525 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1526 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1527 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1528 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1529 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1530 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1531 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1532 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1533 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1534 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1535 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1536 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1537 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1538 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1539 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1540 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1541 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1542 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1543 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1544 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1545 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1546 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1547 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1548 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1549 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1550 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1551 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1552 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1553 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1554 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1556 for (i = num_private_stats; i < num_stats; i++) {
1557 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1558 CERROR("Missing md_stat initializer md_op "
1559 "operation at offset %d. Aborting.\n",
1560 i - num_private_stats);
1564 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1566 lprocfs_free_stats(&stats);
1568 obd->md_stats = stats;
1569 obd->md_cntr_base = num_private_stats;
1574 void lprocfs_free_md_stats(struct obd_device *obd)
1576 struct lprocfs_stats *stats = obd->md_stats;
1578 if (stats != NULL) {
1579 obd->md_stats = NULL;
1580 obd->md_cntr_base = 0;
1581 lprocfs_free_stats(&stats);
1585 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1587 lprocfs_counter_init(ldlm_stats,
1588 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1589 0, "ldlm_enqueue", "reqs");
1590 lprocfs_counter_init(ldlm_stats,
1591 LDLM_CONVERT - LDLM_FIRST_OPC,
1592 0, "ldlm_convert", "reqs");
1593 lprocfs_counter_init(ldlm_stats,
1594 LDLM_CANCEL - LDLM_FIRST_OPC,
1595 0, "ldlm_cancel", "reqs");
1596 lprocfs_counter_init(ldlm_stats,
1597 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1598 0, "ldlm_bl_callback", "reqs");
1599 lprocfs_counter_init(ldlm_stats,
1600 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1601 0, "ldlm_cp_callback", "reqs");
1602 lprocfs_counter_init(ldlm_stats,
1603 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1604 0, "ldlm_gl_callback", "reqs");
1607 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1608 int *eof, void *data)
1610 struct obd_export *exp = data;
1611 LASSERT(exp != NULL);
1613 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1616 struct exp_uuid_cb_data {
1624 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1625 int count, int *eof, int *len)
1627 cb_data->page = page;
1628 cb_data->count = count;
1633 void lprocfs_exp_print_uuid(void *obj, void *cb_data)
1635 struct obd_export *exp = (struct obd_export *)obj;
1636 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1638 if (exp->exp_nid_stats)
1639 *data->len += snprintf((data->page + *data->len),
1640 data->count, "%s\n",
1641 obd_uuid2str(&exp->exp_client_uuid));
1644 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1645 int *eof, void *data)
1647 struct nid_stat *stats = (struct nid_stat *)data;
1648 struct exp_uuid_cb_data cb_data;
1649 struct obd_device *obd = stats->nid_obd;
1654 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1655 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1656 lprocfs_exp_print_uuid, &cb_data);
1657 return (*cb_data.len);
1660 void lprocfs_exp_print_hash(void *obj, void *cb_data)
1662 struct exp_uuid_cb_data *data = cb_data;
1663 struct obd_export *exp = obj;
1666 hs = exp->exp_lock_hash;
1669 *data->len += cfs_hash_debug_header(data->page,
1672 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1677 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1678 int *eof, void *data)
1680 struct nid_stat *stats = (struct nid_stat *)data;
1681 struct exp_uuid_cb_data cb_data;
1682 struct obd_device *obd = stats->nid_obd;
1687 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1689 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1690 lprocfs_exp_print_hash, &cb_data);
1691 return (*cb_data.len);
1694 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1695 int count, int *eof, void *data)
1698 return snprintf(page, count, "%s\n",
1699 "Write into this file to clear all nid stats and "
1700 "stale nid entries");
1702 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1704 void lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1706 struct nid_stat *stat = obj;
1709 /* object has only hash + iterate_all references.
1710 * add/delete blocked by hash bucket lock */
1711 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
1712 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 2) {
1713 cfs_hlist_del_init(&stat->nid_hash);
1714 nidstat_putref(stat);
1715 cfs_spin_lock(&stat->nid_obd->obd_nid_lock);
1716 cfs_list_move(&stat->nid_list, data);
1717 cfs_spin_unlock(&stat->nid_obd->obd_nid_lock);
1721 /* we has reference to object - only clear data*/
1722 if (stat->nid_stats)
1723 lprocfs_clear_stats(stat->nid_stats);
1725 if (stat->nid_brw_stats) {
1726 for (i = 0; i < BRW_LAST; i++)
1727 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
1733 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1734 unsigned long count, void *data)
1736 struct obd_device *obd = (struct obd_device *)data;
1737 struct nid_stat *client_stat;
1738 CFS_LIST_HEAD(free_list);
1740 cfs_hash_for_each(obd->obd_nid_stats_hash,
1741 lprocfs_nid_stats_clear_write_cb, &free_list);
1743 while (!cfs_list_empty(&free_list)) {
1744 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
1746 cfs_list_del_init(&client_stat->nid_list);
1747 lprocfs_free_client_stats(client_stat);
1752 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1754 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1756 struct nid_stat *new_stat, *old_stat;
1757 struct obd_device *obd = NULL;
1758 cfs_proc_dir_entry_t *entry;
1764 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1765 !exp->exp_obd->obd_nid_stats_hash)
1768 /* not test against zero because eric say:
1769 * You may only test nid against another nid, or LNET_NID_ANY.
1770 * Anything else is nonsense.*/
1771 if (!nid || *nid == LNET_NID_ANY)
1776 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
1778 OBD_ALLOC_PTR(new_stat);
1779 if (new_stat == NULL)
1782 new_stat->nid = *nid;
1783 new_stat->nid_obd = exp->exp_obd;
1784 cfs_atomic_set(&new_stat->nid_exp_ref_count, 0);
1786 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
1787 nid, &new_stat->nid_hash);
1788 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
1789 old_stat, libcfs_nid2str(*nid),
1790 cfs_atomic_read(&new_stat->nid_exp_ref_count));
1792 /* Return -EALREADY here so that we know that the /proc
1793 * entry already has been created */
1794 if (old_stat != new_stat) {
1795 cfs_spin_lock(&obd->obd_nid_lock);
1796 if (exp->exp_nid_stats != old_stat) {
1797 if (exp->exp_nid_stats)
1798 nidstat_putref(exp->exp_nid_stats);
1799 exp->exp_nid_stats = old_stat;
1801 /* cfs_hash_findadd_unique() has added
1802 * old_stat's refcount */
1803 nidstat_putref(old_stat);
1806 cfs_spin_unlock(&obd->obd_nid_lock);
1808 GOTO(destroy_new, rc = -EALREADY);
1810 /* not found - create */
1811 new_stat->nid_proc = lprocfs_register(libcfs_nid2str(*nid),
1812 obd->obd_proc_exports_entry,
1814 if (new_stat->nid_proc == NULL) {
1815 CERROR("Error making export directory for nid %s\n",
1816 libcfs_nid2str(*nid));
1817 GOTO(destroy_new_ns, rc = -ENOMEM);
1820 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
1821 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
1822 if (IS_ERR(entry)) {
1823 CWARN("Error adding the NID stats file\n");
1824 rc = PTR_ERR(entry);
1825 GOTO(destroy_new_ns, rc);
1828 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
1829 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
1830 if (IS_ERR(entry)) {
1831 CWARN("Error adding the hash file\n");
1832 rc = PTR_ERR(entry);
1833 GOTO(destroy_new_ns, rc);
1836 if (exp->exp_nid_stats)
1837 nidstat_putref(exp->exp_nid_stats);
1838 nidstat_getref(new_stat);
1839 exp->exp_nid_stats = new_stat;
1841 /* protect competitive add to list, not need locking on destroy */
1842 cfs_spin_lock(&obd->obd_nid_lock);
1843 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
1844 cfs_spin_unlock(&obd->obd_nid_lock);
1849 if (new_stat->nid_proc != NULL)
1850 lprocfs_remove(&new_stat->nid_proc);
1851 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
1854 OBD_FREE_PTR(new_stat);
1858 int lprocfs_exp_cleanup(struct obd_export *exp)
1860 struct nid_stat *stat = exp->exp_nid_stats;
1862 if(!stat || !exp->exp_obd)
1865 nidstat_putref(exp->exp_nid_stats);
1866 exp->exp_nid_stats = NULL;
1871 int lprocfs_write_helper(const char *buffer, unsigned long count,
1874 return lprocfs_write_frac_helper(buffer, count, val, 1);
1877 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
1880 char kernbuf[20], *end, *pbuf;
1882 if (count > (sizeof(kernbuf) - 1))
1885 if (cfs_copy_from_user(kernbuf, buffer, count))
1888 kernbuf[count] = '\0';
1895 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1899 if (end != NULL && *end == '.') {
1900 int temp_val, pow = 1;
1904 if (strlen(pbuf) > 5)
1905 pbuf[5] = '\0'; /*only allow 5bits fractional*/
1907 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1910 for (i = 0; i < (end - pbuf); i++)
1913 *val += temp_val / pow;
1919 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
1922 long decimal_val, frac_val;
1928 decimal_val = val / mult;
1929 prtn = snprintf(buffer, count, "%ld", decimal_val);
1930 frac_val = val % mult;
1932 if (prtn < (count - 4) && frac_val > 0) {
1934 int i, temp_mult = 1, frac_bits = 0;
1936 temp_frac = frac_val * 10;
1937 buffer[prtn++] = '.';
1938 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
1939 /* only reserved 2 bits fraction */
1940 buffer[prtn++] ='0';
1945 * Need to think these cases :
1946 * 1. #echo x.00 > /proc/xxx output result : x
1947 * 2. #echo x.0x > /proc/xxx output result : x.0x
1948 * 3. #echo x.x0 > /proc/xxx output result : x.x
1949 * 4. #echo x.xx > /proc/xxx output result : x.xx
1950 * Only reserved 2 bits fraction.
1952 for (i = 0; i < (5 - prtn); i++)
1955 frac_bits = min((int)count - prtn, 3 - frac_bits);
1956 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
1957 frac_val * temp_mult / mult);
1960 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
1962 if (buffer[prtn] == '.') {
1969 buffer[prtn++] ='\n';
1973 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
1975 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
1978 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
1979 __u64 *val, int mult)
1981 char kernbuf[22], *end, *pbuf;
1982 __u64 whole, frac = 0, units;
1983 unsigned frac_d = 1;
1985 if (count > (sizeof(kernbuf) - 1))
1988 if (cfs_copy_from_user(kernbuf, buffer, count))
1991 kernbuf[count] = '\0';
1998 whole = simple_strtoull(pbuf, &end, 10);
2002 if (end != NULL && *end == '.') {
2006 /* need to limit frac_d to a __u32 */
2007 if (strlen(pbuf) > 10)
2010 frac = simple_strtoull(pbuf, &end, 10);
2011 /* count decimal places */
2012 for (i = 0; i < (end - pbuf); i++)
2029 /* Specified units override the multiplier */
2031 mult = mult < 0 ? -units : units;
2034 do_div(frac, frac_d);
2035 *val = whole * mult + frac;
2039 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent, char *name, mode_t mode,
2040 struct file_operations *seq_fops, void *data)
2042 struct proc_dir_entry *entry;
2045 entry = create_proc_entry(name, mode, parent);
2048 entry->proc_fops = seq_fops;
2053 EXPORT_SYMBOL(lprocfs_seq_create);
2055 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
2057 struct file_operations *seq_fops,
2060 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2061 mode, seq_fops, data));
2063 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2065 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2067 if (value >= OBD_HIST_MAX)
2068 value = OBD_HIST_MAX - 1;
2070 cfs_spin_lock(&oh->oh_lock);
2071 oh->oh_buckets[value]++;
2072 cfs_spin_unlock(&oh->oh_lock);
2074 EXPORT_SYMBOL(lprocfs_oh_tally);
2076 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2080 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2083 lprocfs_oh_tally(oh, val);
2085 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2087 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2089 unsigned long ret = 0;
2092 for (i = 0; i < OBD_HIST_MAX; i++)
2093 ret += oh->oh_buckets[i];
2096 EXPORT_SYMBOL(lprocfs_oh_sum);
2098 void lprocfs_oh_clear(struct obd_histogram *oh)
2100 cfs_spin_lock(&oh->oh_lock);
2101 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2102 cfs_spin_unlock(&oh->oh_lock);
2104 EXPORT_SYMBOL(lprocfs_oh_clear);
2106 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2107 int count, int *eof, void *data)
2109 struct obd_device *obd = data;
2115 c += cfs_hash_debug_header(page, count);
2116 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2117 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2118 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2122 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2124 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2125 int count, int *eof, void *data)
2127 struct obd_device *obd = data;
2130 LASSERT(obd != NULL);
2131 LASSERT(count >= 0);
2133 /* Set start of user data returned to
2134 page + off since the user may have
2135 requested to read much smaller than
2136 what we need to read */
2137 *start = page + off;
2139 /* We know we are allocated a page here.
2140 Also we know that this function will
2141 not need to write more than a page
2142 so we can truncate at CFS_PAGE_SIZE. */
2143 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2145 /* Initialize the page */
2146 memset(page, 0, size);
2148 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2150 if (obd->obd_max_recoverable_clients == 0) {
2151 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2157 /* sampled unlocked, but really... */
2158 if (obd->obd_recovering == 0) {
2159 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2161 if (lprocfs_obd_snprintf(&page, size, &len,
2162 "recovery_start: %lu\n",
2163 obd->obd_recovery_start) <= 0)
2165 if (lprocfs_obd_snprintf(&page, size, &len,
2166 "recovery_duration: %lu\n",
2167 obd->obd_recovery_end -
2168 obd->obd_recovery_start) <= 0)
2170 /* Number of clients that have completed recovery */
2171 if (lprocfs_obd_snprintf(&page, size, &len,
2172 "completed_clients: %d/%d\n",
2173 obd->obd_max_recoverable_clients -
2174 obd->obd_stale_clients,
2175 obd->obd_max_recoverable_clients) <= 0)
2177 if (lprocfs_obd_snprintf(&page, size, &len,
2178 "replayed_requests: %d\n",
2179 obd->obd_replayed_requests) <= 0)
2181 if (lprocfs_obd_snprintf(&page, size, &len,
2182 "last_transno: "LPD64"\n",
2183 obd->obd_next_recovery_transno - 1)<=0)
2185 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2186 obd->obd_version_recov ? "ON" : "OFF")<=0)
2191 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2193 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2194 obd->obd_recovery_start) <= 0)
2196 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2197 cfs_time_current_sec() >= obd->obd_recovery_end ? 0 :
2198 obd->obd_recovery_end - cfs_time_current_sec()) <= 0)
2200 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2201 obd->obd_connected_clients,
2202 obd->obd_max_recoverable_clients) <= 0)
2204 /* Number of clients that have completed recovery */
2205 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2206 cfs_atomic_read(&obd->obd_req_replay_clients))
2209 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2210 cfs_atomic_read(&obd->obd_lock_replay_clients))
2213 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2214 obd->obd_connected_clients -
2215 cfs_atomic_read(&obd->obd_lock_replay_clients))
2218 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2219 obd->obd_stale_clients) <= 0)
2221 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2222 obd->obd_replayed_requests) <= 0)
2224 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2225 obd->obd_requests_queued_for_recovery) <= 0)
2228 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2229 obd->obd_next_recovery_transno) <= 0)
2235 return min(count, len - (int)off);
2237 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2239 int lprocfs_obd_rd_recovery_maxtime(char *page, char **start, off_t off,
2240 int count, int *eof, void *data)
2242 struct obd_device *obd = data;
2243 LASSERT(obd != NULL);
2245 return snprintf(page, count, "%lu\n", obd->obd_recovery_max_time);
2247 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_maxtime);
2249 int lprocfs_obd_wr_recovery_maxtime(struct file *file, const char *buffer,
2250 unsigned long count, void *data)
2252 struct obd_device *obd = data;
2254 LASSERT(obd != NULL);
2256 rc = lprocfs_write_helper(buffer, count, &val);
2260 obd->obd_recovery_max_time = val;
2263 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_maxtime);
2266 EXPORT_SYMBOL(lprocfs_register);
2267 EXPORT_SYMBOL(lprocfs_srch);
2268 EXPORT_SYMBOL(lprocfs_remove);
2269 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
2270 EXPORT_SYMBOL(lprocfs_add_vars);
2271 EXPORT_SYMBOL(lprocfs_obd_setup);
2272 EXPORT_SYMBOL(lprocfs_obd_cleanup);
2273 EXPORT_SYMBOL(lprocfs_add_simple);
2274 EXPORT_SYMBOL(lprocfs_add_symlink);
2275 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
2276 EXPORT_SYMBOL(lprocfs_alloc_stats);
2277 EXPORT_SYMBOL(lprocfs_free_stats);
2278 EXPORT_SYMBOL(lprocfs_clear_stats);
2279 EXPORT_SYMBOL(lprocfs_register_stats);
2280 EXPORT_SYMBOL(lprocfs_init_ops_stats);
2281 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
2282 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
2283 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
2284 EXPORT_SYMBOL(lprocfs_free_obd_stats);
2285 EXPORT_SYMBOL(lprocfs_free_md_stats);
2286 EXPORT_SYMBOL(lprocfs_exp_setup);
2287 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2289 EXPORT_SYMBOL(lprocfs_rd_u64);
2290 EXPORT_SYMBOL(lprocfs_rd_atomic);
2291 EXPORT_SYMBOL(lprocfs_wr_atomic);
2292 EXPORT_SYMBOL(lprocfs_rd_uint);
2293 EXPORT_SYMBOL(lprocfs_wr_uint);
2294 EXPORT_SYMBOL(lprocfs_rd_uuid);
2295 EXPORT_SYMBOL(lprocfs_rd_name);
2296 EXPORT_SYMBOL(lprocfs_rd_fstype);
2297 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
2298 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
2299 EXPORT_SYMBOL(lprocfs_rd_num_exports);
2300 EXPORT_SYMBOL(lprocfs_rd_numrefs);
2301 EXPORT_SYMBOL(lprocfs_at_hist_helper);
2302 EXPORT_SYMBOL(lprocfs_rd_import);
2303 EXPORT_SYMBOL(lprocfs_rd_state);
2304 EXPORT_SYMBOL(lprocfs_rd_timeouts);
2305 EXPORT_SYMBOL(lprocfs_rd_blksize);
2306 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
2307 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
2308 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
2309 EXPORT_SYMBOL(lprocfs_rd_filestotal);
2310 EXPORT_SYMBOL(lprocfs_rd_filesfree);
2311 EXPORT_SYMBOL(lprocfs_rd_quota_resend_count);
2312 EXPORT_SYMBOL(lprocfs_wr_quota_resend_count);
2314 EXPORT_SYMBOL(lprocfs_write_helper);
2315 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2316 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2317 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2318 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2319 EXPORT_SYMBOL(lprocfs_stats_collect);