1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 only,
10 * as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License version 2 for more details (a copy is included
16 * in the LICENSE file that accompanied this code).
18 * You should have received a copy of the GNU General Public License
19 * version 2 along with this program; If not, see
20 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
22 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23 * CA 95054 USA or visit www.sun.com if you need additional information or
29 * Copyright 2008 Sun Microsystems, Inc. All rights reserved
30 * Use is subject to license terms.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
36 * lustre/obdclass/lprocfs_status.c
38 * Author: Hariharan Thantry <thantry@users.sourceforge.net>
42 # define EXPORT_SYMTAB
44 #define DEBUG_SUBSYSTEM S_CLASS
47 # include <liblustre.h>
50 #include <obd_class.h>
51 #include <lprocfs_status.h>
52 #include <lustre_fsfilt.h>
53 #include <lustre_log.h>
54 #include <lustre/lustre_idl.h>
58 #define MAX_STRING_SIZE 128
60 /* for bug 10866, global variable */
61 DECLARE_RWSEM(_lprocfs_lock);
62 EXPORT_SYMBOL(_lprocfs_lock);
64 int lprocfs_seq_release(struct inode *inode, struct file *file)
67 return seq_release(inode, file);
69 EXPORT_SYMBOL(lprocfs_seq_release);
71 struct proc_dir_entry *lprocfs_srch(struct proc_dir_entry *head,
74 struct proc_dir_entry *temp;
81 while (temp != NULL) {
82 if (strcmp(temp->name, name) == 0) {
93 /* lprocfs API calls */
95 /* Function that emulates snprintf but also has the side effect of advancing
96 the page pointer for the next write into the buffer, incrementing the total
97 length written to the buffer, and decrementing the size left in the
99 static int lprocfs_obd_snprintf(char **page, int end, int *len,
100 const char *format, ...)
108 va_start(list, format);
109 n = vsnprintf(*page, end - *len, format, list);
112 *page += n; *len += n;
116 cfs_proc_dir_entry_t *lprocfs_add_simple(struct proc_dir_entry *root,
118 read_proc_t *read_proc,
119 write_proc_t *write_proc,
121 struct file_operations *fops)
123 cfs_proc_dir_entry_t *proc;
126 if (root == NULL || name == NULL)
127 return ERR_PTR(-EINVAL);
134 proc = create_proc_entry(name, mode, root);
136 CERROR("LprocFS: No memory to create /proc entry %s", name);
137 return ERR_PTR(-ENOMEM);
139 proc->read_proc = read_proc;
140 proc->write_proc = write_proc;
143 proc->proc_fops = fops;
147 struct proc_dir_entry *lprocfs_add_symlink(const char *name,
148 struct proc_dir_entry *parent, const char *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 (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 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 atomic_dec(&obd->obd_evict_inprogress);
249 wake_up(&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 (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 atomic_t *atom = data;
453 LASSERT(atom != NULL);
455 return snprintf(page, count, "%d\n", atomic_read(atom));
458 int lprocfs_wr_atomic(struct file *file, const char *buffer,
459 unsigned long count, void *data)
461 atomic_t *atm = data;
465 rc = lprocfs_write_helper(buffer, count, &val);
472 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() - 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() - 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() - 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() - 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() - 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() - 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;
637 LASSERT(conn != NULL);
639 if (obd->u.cli.cl_import) {
640 rc = snprintf(page, count, "%s\n",
641 conn->c_remote_uuid.uuid);
643 rc = snprintf(page, count, "%s\n", "<none>");
646 LPROCFS_CLIMP_EXIT(obd);
650 /** add up per-cpu counters */
651 void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
652 struct lprocfs_counter *cnt)
654 unsigned int num_cpu;
655 struct lprocfs_counter t;
656 struct lprocfs_counter *percpu_cntr;
659 memset(cnt, 0, sizeof(*cnt));
662 /* set count to 1 to avoid divide-by-zero errs in callers */
667 cnt->lc_min = LC_MIN_INIT;
669 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
672 num_cpu = num_possible_cpus();
674 for (i = 0; i < num_cpu; i++) {
675 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[idx];
678 centry = atomic_read(&percpu_cntr->lc_cntl.la_entry);
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 != atomic_read(&percpu_cntr->lc_cntl.la_entry) &&
685 centry != atomic_read(&percpu_cntr->lc_cntl.la_exit));
686 cnt->lc_count += t.lc_count;
687 cnt->lc_sum += t.lc_sum;
688 if (t.lc_min < cnt->lc_min)
689 cnt->lc_min = t.lc_min;
690 if (t.lc_max > cnt->lc_max)
691 cnt->lc_max = t.lc_max;
692 cnt->lc_sumsquare += t.lc_sumsquare;
695 cnt->lc_units = stats->ls_percpu[0]->lp_cntr[idx].lc_units;
699 * Append a space separated list of current set flags to str.
701 #define flag2str(flag) \
702 if (imp->imp_##flag && max - len > 0) \
703 len += snprintf(str + len, max - len, "%s" #flag, len ? ", " : "");
704 static int obd_import_flags2str(struct obd_import *imp, char *str, int max)
708 if (imp->imp_obd->obd_no_recov)
709 len += snprintf(str, max - len, "no_recov");
713 flag2str(replayable);
716 flag2str(last_recon);
721 static const char *obd_connect_names[] = {
748 "mds_mds_connection",
751 "alt_checksum_algorithm",
760 static int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
765 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
767 ret += snprintf(page + ret, count - ret, "%s%s",
768 ret ? sep : "", obd_connect_names[i]);
770 if (flags & ~(mask - 1))
771 ret += snprintf(page + ret, count - ret,
772 "%sunknown flags "LPX64,
773 ret ? sep : "", flags & ~(mask - 1));
777 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
778 int *eof, void *data)
780 struct lprocfs_counter ret;
781 struct obd_device *obd = (struct obd_device *)data;
782 struct obd_import *imp;
785 LASSERT(obd != NULL);
786 LPROCFS_CLIMP_CHECK(obd);
787 imp = obd->u.cli.cl_import;
790 i = snprintf(page, count,
794 " current_connection: %s\n"
799 imp->imp_connection->c_remote_uuid.uuid,
800 ptlrpc_import_state_name(imp->imp_state));
801 i += obd_connect_flags2str(page + i, count - i,
802 imp->imp_connect_data.ocd_connect_flags,
804 i += snprintf(page + i, count - i,
807 i += obd_import_flags2str(imp, page + i, count - i);
809 i += snprintf(page + i, count - i,
812 " connection_attempts: %u\n"
814 " in-progress_invalidations: %u\n",
817 atomic_read(&imp->imp_inval_count));
819 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
820 do_div(ret.lc_sum, ret.lc_count);
821 i += snprintf(page + i, count - i,
824 " unregistering: %u\n"
826 " avg_waittime: "LPU64" %s\n",
827 atomic_read(&imp->imp_inflight),
828 atomic_read(&imp->imp_unregistering),
829 atomic_read(&imp->imp_timeouts),
830 ret.lc_sum, ret.lc_units);
833 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
834 if (imp->imp_at.iat_portal[j] == 0)
836 k = max_t(unsigned int, k,
837 at_get(&imp->imp_at.iat_service_estimate[j]));
839 i += snprintf(page + i, count - i,
840 " service_estimates:\n"
841 " services: %u sec\n"
842 " network: %u sec\n",
844 at_get(&imp->imp_at.iat_net_latency));
846 i += snprintf(page + i, count - i,
848 " last_replay: "LPU64"\n"
849 " peer_committed: "LPU64"\n"
850 " last_checked: "LPU64"\n",
851 imp->imp_last_replay_transno,
852 imp->imp_peer_committed_transno,
853 imp->imp_last_transno_checked);
856 for (rw = 0; rw <= 1; rw++) {
857 lprocfs_stats_collect(obd->obd_svc_stats,
858 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
860 if (ret.lc_sum > 0) {
861 do_div(ret.lc_sum, ret.lc_count);
862 i += snprintf(page + i, count - i,
863 " %s_data_averages:\n"
864 " bytes_per_rpc: "LPU64"\n",
865 rw ? "write" : "read",
869 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
870 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
871 if (ret.lc_sum > 0) {
872 do_div(ret.lc_sum, ret.lc_count);
873 i += snprintf(page + i, count - i,
874 " %s_per_rpc: "LPU64"\n",
875 ret.lc_units, ret.lc_sum);
878 i += snprintf(page + i, count - i,
879 " MB_per_sec: %u.%.02u\n",
880 k / j, (100 * k / j) % 100);
884 LPROCFS_CLIMP_EXIT(obd);
888 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
889 int *eof, void *data)
891 struct obd_device *obd = (struct obd_device *)data;
892 struct obd_import *imp;
895 LASSERT(obd != NULL);
896 LPROCFS_CLIMP_CHECK(obd);
897 imp = obd->u.cli.cl_import;
900 i = snprintf(page, count, "current_state: %s\n",
901 ptlrpc_import_state_name(imp->imp_state));
902 i += snprintf(page + i, count - i,
904 k = imp->imp_state_hist_idx;
905 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
906 struct import_state_hist *ish =
907 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
908 if (ish->ish_state == 0)
910 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
912 ptlrpc_import_state_name(ish->ish_state));
915 LPROCFS_CLIMP_EXIT(obd);
919 int lprocfs_at_hist_helper(char *page, int count, int rc,
920 struct adaptive_timeout *at)
923 for (i = 0; i < AT_BINS; i++)
924 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
925 rc += snprintf(page + rc, count - rc, "\n");
929 int lprocfs_rd_quota_resend_count(char *page, char **start, off_t off,
930 int count, int *eof, void *data)
932 struct obd_device *obd = data;
934 return snprintf(page, count, "%d\n",
935 atomic_read(&obd->u.cli.cl_quota_resends));
938 int lprocfs_wr_quota_resend_count(struct file *file, const char *buffer,
939 unsigned long count, void *data)
941 struct obd_device *obd = data;
944 rc = lprocfs_write_helper(buffer, count, &val);
948 atomic_set(&obd->u.cli.cl_quota_resends, val);
953 /* See also ptlrpc_lprocfs_rd_timeouts */
954 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
955 int *eof, void *data)
957 struct obd_device *obd = (struct obd_device *)data;
958 struct obd_import *imp;
959 unsigned int cur, worst;
964 LASSERT(obd != NULL);
965 LPROCFS_CLIMP_CHECK(obd);
966 imp = obd->u.cli.cl_import;
969 now = cfs_time_current_sec();
971 /* Some network health info for kicks */
972 s2dhms(&ts, now - imp->imp_last_reply_time);
973 rc += snprintf(page + rc, count - rc,
974 "%-10s : %ld, "DHMS_FMT" ago\n",
975 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
977 cur = at_get(&imp->imp_at.iat_net_latency);
978 worst = imp->imp_at.iat_net_latency.at_worst_ever;
979 worstt = imp->imp_at.iat_net_latency.at_worst_time;
980 s2dhms(&ts, now - worstt);
981 rc += snprintf(page + rc, count - rc,
982 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
983 "network", cur, worst, worstt, DHMS_VARS(&ts));
984 rc = lprocfs_at_hist_helper(page, count, rc,
985 &imp->imp_at.iat_net_latency);
987 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
988 if (imp->imp_at.iat_portal[i] == 0)
990 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
991 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
992 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
993 s2dhms(&ts, now - worstt);
994 rc += snprintf(page + rc, count - rc,
995 "portal %-2d : cur %3u worst %3u (at %ld, "
996 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
997 cur, worst, worstt, DHMS_VARS(&ts));
998 rc = lprocfs_at_hist_helper(page, count, rc,
999 &imp->imp_at.iat_service_estimate[i]);
1002 LPROCFS_CLIMP_EXIT(obd);
1006 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1007 int count, int *eof, void *data)
1009 struct obd_device *obd = data;
1013 LPROCFS_CLIMP_CHECK(obd);
1014 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1015 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1016 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1017 ret += snprintf(page + ret, count - ret, "\n");
1018 LPROCFS_CLIMP_EXIT(obd);
1021 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1023 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1024 int *eof, void *data)
1026 struct obd_device *obd = data;
1028 LASSERT(obd != NULL);
1030 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1033 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1034 int *eof, void *data)
1036 struct obd_type *class = (struct obd_type*) data;
1038 LASSERT(class != NULL);
1040 return snprintf(page, count, "%d\n", class->typ_refcnt);
1043 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1047 LASSERT(obd != NULL);
1048 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1049 LASSERT(obd->obd_type->typ_procroot != NULL);
1051 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1052 obd->obd_type->typ_procroot,
1054 if (IS_ERR(obd->obd_proc_entry)) {
1055 rc = PTR_ERR(obd->obd_proc_entry);
1056 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1057 obd->obd_proc_entry = NULL;
1062 int lprocfs_obd_cleanup(struct obd_device *obd)
1066 if (obd->obd_proc_exports_entry) {
1067 /* Should be no exports left */
1068 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1069 lprocfs_remove(&obd->obd_proc_exports_entry);
1070 obd->obd_proc_exports_entry = NULL;
1072 if (obd->obd_proc_entry) {
1073 lprocfs_remove(&obd->obd_proc_entry);
1074 obd->obd_proc_entry = NULL;
1079 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1081 CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
1082 client_stat->nid_proc, client_stat->nid_stats,
1083 client_stat->nid_brw_stats);
1085 LASSERTF(atomic_read(&client_stat->nid_exp_ref_count) == 0,
1086 "count %d\n", atomic_read(&client_stat->nid_exp_ref_count));
1088 hlist_del_init(&client_stat->nid_hash);
1090 if (client_stat->nid_proc)
1091 lprocfs_remove(&client_stat->nid_proc);
1093 if (client_stat->nid_stats)
1094 lprocfs_free_stats(&client_stat->nid_stats);
1096 if (client_stat->nid_brw_stats)
1097 OBD_FREE_PTR(client_stat->nid_brw_stats);
1099 if (client_stat->nid_ldlm_stats)
1100 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1102 OBD_FREE_PTR(client_stat);
1107 void lprocfs_free_per_client_stats(struct obd_device *obd)
1109 struct nid_stat *stat;
1112 /* we need extra list - because hash_exit called to early */
1113 /* not need locking because all clients is died */
1114 while(!list_empty(&obd->obd_nid_stats)) {
1115 stat = list_entry(obd->obd_nid_stats.next,
1116 struct nid_stat, nid_list);
1117 list_del_init(&stat->nid_list);
1118 lprocfs_free_client_stats(stat);
1124 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1125 enum lprocfs_stats_flags flags)
1127 struct lprocfs_stats *stats;
1128 unsigned int percpusize;
1130 unsigned int num_cpu;
1135 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1138 num_cpu = num_possible_cpus();
1140 OBD_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
1144 if (flags & LPROCFS_STATS_FLAG_NOPERCPU) {
1145 stats->ls_flags = flags;
1146 spin_lock_init(&stats->ls_lock);
1147 /* Use this lock only if there are no percpu areas */
1149 stats->ls_flags = 0;
1152 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
1154 percpusize = L1_CACHE_ALIGN(percpusize);
1156 for (i = 0; i < num_cpu; i++) {
1157 OBD_ALLOC(stats->ls_percpu[i], percpusize);
1158 if (stats->ls_percpu[i] == NULL) {
1159 for (j = 0; j < i; j++) {
1160 OBD_FREE(stats->ls_percpu[j], percpusize);
1161 stats->ls_percpu[j] = NULL;
1166 if (stats->ls_percpu[0] == NULL) {
1167 OBD_FREE(stats, offsetof(typeof(*stats),
1168 ls_percpu[num_cpu]));
1172 stats->ls_num = num;
1176 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1178 struct lprocfs_stats *stats = *statsh;
1179 unsigned int num_cpu;
1180 unsigned int percpusize;
1183 if (stats == NULL || stats->ls_num == 0)
1187 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1190 num_cpu = num_possible_cpus();
1192 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
1194 percpusize = L1_CACHE_ALIGN(percpusize);
1195 for (i = 0; i < num_cpu; i++)
1196 OBD_FREE(stats->ls_percpu[i], percpusize);
1197 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
1200 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1202 struct lprocfs_counter *percpu_cntr;
1204 unsigned int num_cpu;
1206 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1208 for (i = 0; i < num_cpu; i++) {
1209 for (j = 0; j < stats->ls_num; j++) {
1210 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
1211 atomic_inc(&percpu_cntr->lc_cntl.la_entry);
1212 percpu_cntr->lc_count = 0;
1213 percpu_cntr->lc_sum = 0;
1214 percpu_cntr->lc_min = LC_MIN_INIT;
1215 percpu_cntr->lc_max = 0;
1216 percpu_cntr->lc_sumsquare = 0;
1217 atomic_inc(&percpu_cntr->lc_cntl.la_exit);
1221 lprocfs_stats_unlock(stats);
1224 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1225 size_t len, loff_t *off)
1227 struct seq_file *seq = file->private_data;
1228 struct lprocfs_stats *stats = seq->private;
1230 lprocfs_clear_stats(stats);
1235 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1237 struct lprocfs_stats *stats = p->private;
1238 /* return 1st cpu location */
1239 return (*pos >= stats->ls_num) ? NULL :
1240 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1243 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1247 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1249 struct lprocfs_stats *stats = p->private;
1251 return (*pos >= stats->ls_num) ? NULL :
1252 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1255 /* seq file export of one lprocfs counter */
1256 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1258 struct lprocfs_stats *stats = p->private;
1259 struct lprocfs_counter *cntr = v;
1260 struct lprocfs_counter ret;
1263 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
1265 do_gettimeofday(&now);
1266 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1267 "snapshot_time", now.tv_sec, now.tv_usec);
1271 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
1273 lprocfs_stats_collect(stats, idx, &ret);
1275 if (ret.lc_count == 0)
1278 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", cntr->lc_name,
1279 ret.lc_count, cntr->lc_units);
1284 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
1285 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1286 ret.lc_min, ret.lc_max, ret.lc_sum);
1289 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
1290 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1294 rc = seq_printf(p, "\n");
1296 return (rc < 0) ? rc : 0;
1299 struct seq_operations lprocfs_stats_seq_sops = {
1300 start: lprocfs_stats_seq_start,
1301 stop: lprocfs_stats_seq_stop,
1302 next: lprocfs_stats_seq_next,
1303 show: lprocfs_stats_seq_show,
1306 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1308 struct proc_dir_entry *dp = PDE(inode);
1309 struct seq_file *seq;
1312 if (LPROCFS_ENTRY_AND_CHECK(dp))
1315 rc = seq_open(file, &lprocfs_stats_seq_sops);
1320 seq = file->private_data;
1321 seq->private = dp->data;
1325 struct file_operations lprocfs_stats_seq_fops = {
1326 .owner = THIS_MODULE,
1327 .open = lprocfs_stats_seq_open,
1329 .write = lprocfs_stats_seq_write,
1330 .llseek = seq_lseek,
1331 .release = lprocfs_seq_release,
1334 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1335 struct lprocfs_stats *stats)
1337 struct proc_dir_entry *entry;
1338 LASSERT(root != NULL);
1340 entry = create_proc_entry(name, 0644, root);
1343 entry->proc_fops = &lprocfs_stats_seq_fops;
1344 entry->data = stats;
1348 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1349 unsigned conf, const char *name, const char *units)
1351 struct lprocfs_counter *c;
1353 unsigned int num_cpu;
1355 LASSERT(stats != NULL);
1357 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1359 for (i = 0; i < num_cpu; i++) {
1360 c = &(stats->ls_percpu[i]->lp_cntr[index]);
1361 c->lc_config = conf;
1364 c->lc_min = LC_MIN_INIT;
1367 c->lc_units = units;
1370 lprocfs_stats_unlock(stats);
1372 EXPORT_SYMBOL(lprocfs_counter_init);
1374 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1376 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1377 LASSERT(coffset < stats->ls_num); \
1378 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1381 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1383 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1384 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1385 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1386 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1387 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1388 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1389 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1390 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1391 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1392 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1393 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1394 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1395 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1396 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1397 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1398 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1399 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1400 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1401 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
1402 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1403 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1404 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1405 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1406 LPROCFS_OBD_OP_INIT(num_private_stats, stats, checkmd);
1407 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1408 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1409 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1410 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1411 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1412 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1413 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1414 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1415 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1416 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1417 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1418 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1419 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1420 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1421 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1422 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1423 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1424 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1425 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1426 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1427 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1428 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1429 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1430 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1431 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1432 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1433 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1434 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1435 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1436 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1437 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1438 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1439 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1440 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1441 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1442 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1443 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1444 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quota_adjust_qunit);
1445 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1446 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1447 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1448 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1449 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1450 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1451 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1454 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1456 struct lprocfs_stats *stats;
1457 unsigned int num_stats;
1460 LASSERT(obd->obd_stats == NULL);
1461 LASSERT(obd->obd_proc_entry != NULL);
1462 LASSERT(obd->obd_cntr_base == 0);
1464 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1465 num_private_stats - 1 /* o_owner */;
1466 stats = lprocfs_alloc_stats(num_stats, 0);
1470 lprocfs_init_ops_stats(num_private_stats, stats);
1472 for (i = num_private_stats; i < num_stats; i++) {
1473 /* If this LBUGs, it is likely that an obd
1474 * operation was added to struct obd_ops in
1475 * <obd.h>, and that the corresponding line item
1476 * LPROCFS_OBD_OP_INIT(.., .., opname)
1477 * is missing from the list above. */
1478 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1479 "Missing obd_stat initializer obd_op "
1480 "operation at offset %d.\n", i - num_private_stats);
1482 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1484 lprocfs_free_stats(&stats);
1486 obd->obd_stats = stats;
1487 obd->obd_cntr_base = num_private_stats;
1492 void lprocfs_free_obd_stats(struct obd_device *obd)
1495 lprocfs_free_stats(&obd->obd_stats);
1498 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1500 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1501 LASSERT(coffset < stats->ls_num); \
1502 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1505 int lprocfs_alloc_md_stats(struct obd_device *obd,
1506 unsigned num_private_stats)
1508 struct lprocfs_stats *stats;
1509 unsigned int num_stats;
1512 LASSERT(obd->md_stats == NULL);
1513 LASSERT(obd->obd_proc_entry != NULL);
1514 LASSERT(obd->md_cntr_base == 0);
1516 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1518 stats = lprocfs_alloc_stats(num_stats, 0);
1522 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1523 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1524 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1525 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1526 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1527 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1528 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1529 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1530 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1531 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1532 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1533 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1534 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1535 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1536 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1537 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1538 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1539 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1540 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1541 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1542 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1543 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1544 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1545 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1546 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1547 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1548 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1549 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1550 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1551 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1552 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1554 for (i = num_private_stats; i < num_stats; i++) {
1555 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1556 CERROR("Missing md_stat initializer md_op "
1557 "operation at offset %d. Aborting.\n",
1558 i - num_private_stats);
1562 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1564 lprocfs_free_stats(&stats);
1566 obd->md_stats = stats;
1567 obd->md_cntr_base = num_private_stats;
1572 void lprocfs_free_md_stats(struct obd_device *obd)
1574 struct lprocfs_stats *stats = obd->md_stats;
1576 if (stats != NULL) {
1577 obd->md_stats = NULL;
1578 obd->md_cntr_base = 0;
1579 lprocfs_free_stats(&stats);
1583 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1585 lprocfs_counter_init(ldlm_stats,
1586 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1587 0, "ldlm_enqueue", "reqs");
1588 lprocfs_counter_init(ldlm_stats,
1589 LDLM_CONVERT - LDLM_FIRST_OPC,
1590 0, "ldlm_convert", "reqs");
1591 lprocfs_counter_init(ldlm_stats,
1592 LDLM_CANCEL - LDLM_FIRST_OPC,
1593 0, "ldlm_cancel", "reqs");
1594 lprocfs_counter_init(ldlm_stats,
1595 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1596 0, "ldlm_bl_callback", "reqs");
1597 lprocfs_counter_init(ldlm_stats,
1598 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1599 0, "ldlm_cp_callback", "reqs");
1600 lprocfs_counter_init(ldlm_stats,
1601 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1602 0, "ldlm_gl_callback", "reqs");
1605 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1606 int *eof, void *data)
1608 struct obd_export *exp = data;
1609 LASSERT(exp != NULL);
1611 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1614 struct exp_uuid_cb_data {
1622 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1623 int count, int *eof, int *len)
1625 cb_data->page = page;
1626 cb_data->count = count;
1631 void lprocfs_exp_print_uuid(void *obj, void *cb_data)
1633 struct obd_export *exp = (struct obd_export *)obj;
1634 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1636 if (exp->exp_nid_stats)
1637 *data->len += snprintf((data->page + *data->len),
1638 data->count, "%s\n",
1639 obd_uuid2str(&exp->exp_client_uuid));
1642 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1643 int *eof, void *data)
1645 struct nid_stat *stats = (struct nid_stat *)data;
1646 struct exp_uuid_cb_data cb_data;
1647 struct obd_device *obd = stats->nid_obd;
1652 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1653 lustre_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1654 lprocfs_exp_print_uuid, &cb_data);
1655 return (*cb_data.len);
1658 void lprocfs_exp_print_hash(void *obj, void *cb_data)
1660 struct exp_uuid_cb_data *data = cb_data;
1661 struct obd_export *exp = obj;
1664 lh = exp->exp_lock_hash;
1667 *data->len += lustre_hash_debug_header(data->page,
1670 *data->len += lustre_hash_debug_str(lh, data->page + *data->len,
1675 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1676 int *eof, void *data)
1678 struct nid_stat *stats = (struct nid_stat *)data;
1679 struct exp_uuid_cb_data cb_data;
1680 struct obd_device *obd = stats->nid_obd;
1685 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1687 lustre_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1688 lprocfs_exp_print_hash, &cb_data);
1689 return (*cb_data.len);
1692 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1693 int count, int *eof, void *data)
1696 return snprintf(page, count, "%s\n",
1697 "Write into this file to clear all nid stats and "
1698 "stale nid entries");
1700 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1702 void lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1704 struct nid_stat *stat = obj;
1707 /* object has only hash + iterate_all references.
1708 * add/delete blocked by hash bucket lock */
1709 CDEBUG(D_INFO,"refcnt %d\n", atomic_read(&stat->nid_exp_ref_count));
1710 if (atomic_read(&stat->nid_exp_ref_count) == 2) {
1711 hlist_del_init(&stat->nid_hash);
1712 nidstat_putref(stat);
1713 spin_lock(&stat->nid_obd->obd_nid_lock);
1714 list_move(&stat->nid_list, data);
1715 spin_unlock(&stat->nid_obd->obd_nid_lock);
1719 /* we has reference to object - only clear data*/
1720 if (stat->nid_stats)
1721 lprocfs_clear_stats(stat->nid_stats);
1723 if (stat->nid_brw_stats) {
1724 for (i = 0; i < BRW_LAST; i++)
1725 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
1731 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1732 unsigned long count, void *data)
1734 struct obd_device *obd = (struct obd_device *)data;
1735 struct nid_stat *client_stat;
1736 CFS_LIST_HEAD(free_list);
1738 lustre_hash_for_each(obd->obd_nid_stats_hash,
1739 lprocfs_nid_stats_clear_write_cb, &free_list);
1741 while (!list_empty(&free_list)) {
1742 client_stat = list_entry(free_list.next, struct nid_stat,
1744 list_del_init(&client_stat->nid_list);
1745 lprocfs_free_client_stats(client_stat);
1750 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1752 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1754 struct nid_stat *new_stat, *old_stat;
1755 struct obd_device *obd = NULL;
1756 cfs_proc_dir_entry_t *entry;
1762 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1763 !exp->exp_obd->obd_nid_stats_hash)
1766 /* not test against zero because eric say:
1767 * You may only test nid against another nid, or LNET_NID_ANY.
1768 * Anything else is nonsense.*/
1769 if (!nid || *nid == LNET_NID_ANY)
1774 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
1776 OBD_ALLOC_PTR(new_stat);
1777 if (new_stat == NULL)
1780 new_stat->nid = *nid;
1781 new_stat->nid_obd = exp->exp_obd;
1782 atomic_set(&new_stat->nid_exp_ref_count, 0);
1784 old_stat = lustre_hash_findadd_unique(obd->obd_nid_stats_hash,
1785 nid, &new_stat->nid_hash);
1786 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
1787 old_stat, libcfs_nid2str(*nid),
1788 atomic_read(&new_stat->nid_exp_ref_count));
1790 /* Return -EALREADY here so that we know that the /proc
1791 * entry already has been created */
1792 if (old_stat != new_stat) {
1793 spin_lock(&obd->obd_nid_lock);
1794 if (exp->exp_nid_stats != old_stat) {
1795 if (exp->exp_nid_stats)
1796 nidstat_putref(exp->exp_nid_stats);
1797 exp->exp_nid_stats = old_stat;
1799 /* lustre_hash_findadd_unique() has added
1800 * old_stat's refcount */
1801 nidstat_putref(old_stat);
1804 spin_unlock(&obd->obd_nid_lock);
1806 GOTO(destroy_new, rc = -EALREADY);
1808 /* not found - create */
1809 new_stat->nid_proc = lprocfs_register(libcfs_nid2str(*nid),
1810 obd->obd_proc_exports_entry,
1812 if (new_stat->nid_proc == NULL) {
1813 CERROR("Error making export directory for nid %s\n",
1814 libcfs_nid2str(*nid));
1815 GOTO(destroy_new_ns, rc = -ENOMEM);
1818 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
1819 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
1820 if (IS_ERR(entry)) {
1821 CWARN("Error adding the NID stats file\n");
1822 rc = PTR_ERR(entry);
1823 GOTO(destroy_new_ns, rc);
1826 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
1827 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
1828 if (IS_ERR(entry)) {
1829 CWARN("Error adding the hash file\n");
1830 rc = PTR_ERR(entry);
1831 GOTO(destroy_new_ns, rc);
1834 if (exp->exp_nid_stats)
1835 nidstat_putref(exp->exp_nid_stats);
1836 nidstat_getref(new_stat);
1837 exp->exp_nid_stats = new_stat;
1839 /* protect competitive add to list, not need locking on destroy */
1840 spin_lock(&obd->obd_nid_lock);
1841 list_add(&new_stat->nid_list, &obd->obd_nid_stats);
1842 spin_unlock(&obd->obd_nid_lock);
1847 if (new_stat->nid_proc != NULL)
1848 lprocfs_remove(&new_stat->nid_proc);
1849 lustre_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
1852 OBD_FREE_PTR(new_stat);
1856 int lprocfs_exp_cleanup(struct obd_export *exp)
1858 struct nid_stat *stat = exp->exp_nid_stats;
1860 if(!stat || !exp->exp_obd)
1863 nidstat_putref(exp->exp_nid_stats);
1864 exp->exp_nid_stats = NULL;
1865 lprocfs_free_md_stats(exp->exp_obd);
1870 int lprocfs_write_helper(const char *buffer, unsigned long count,
1873 return lprocfs_write_frac_helper(buffer, count, val, 1);
1876 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
1879 char kernbuf[20], *end, *pbuf;
1881 if (count > (sizeof(kernbuf) - 1))
1884 if (copy_from_user(kernbuf, buffer, count))
1887 kernbuf[count] = '\0';
1894 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1898 if (end != NULL && *end == '.') {
1899 int temp_val, pow = 1;
1903 if (strlen(pbuf) > 5)
1904 pbuf[5] = '\0'; /*only allow 5bits fractional*/
1906 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1909 for (i = 0; i < (end - pbuf); i++)
1912 *val += temp_val / pow;
1918 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
1921 long decimal_val, frac_val;
1927 decimal_val = val / mult;
1928 prtn = snprintf(buffer, count, "%ld", decimal_val);
1929 frac_val = val % mult;
1931 if (prtn < (count - 4) && frac_val > 0) {
1933 int i, temp_mult = 1, frac_bits = 0;
1935 temp_frac = frac_val * 10;
1936 buffer[prtn++] = '.';
1937 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
1938 /* only reserved 2 bits fraction */
1939 buffer[prtn++] ='0';
1944 * Need to think these cases :
1945 * 1. #echo x.00 > /proc/xxx output result : x
1946 * 2. #echo x.0x > /proc/xxx output result : x.0x
1947 * 3. #echo x.x0 > /proc/xxx output result : x.x
1948 * 4. #echo x.xx > /proc/xxx output result : x.xx
1949 * Only reserved 2 bits fraction.
1951 for (i = 0; i < (5 - prtn); i++)
1954 frac_bits = min((int)count - prtn, 3 - frac_bits);
1955 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
1956 frac_val * temp_mult / mult);
1959 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
1961 if (buffer[prtn] == '.') {
1968 buffer[prtn++] ='\n';
1972 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
1974 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
1977 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
1978 __u64 *val, int mult)
1980 char kernbuf[22], *end, *pbuf;
1981 __u64 whole, frac = 0, units;
1982 unsigned frac_d = 1;
1984 if (count > (sizeof(kernbuf) - 1))
1987 if (copy_from_user(kernbuf, buffer, count))
1990 kernbuf[count] = '\0';
1997 whole = simple_strtoull(pbuf, &end, 10);
2001 if (end != NULL && *end == '.') {
2005 /* need to limit frac_d to a __u32 */
2006 if (strlen(pbuf) > 10)
2009 frac = simple_strtoull(pbuf, &end, 10);
2010 /* count decimal places */
2011 for (i = 0; i < (end - pbuf); i++)
2028 /* Specified units override the multiplier */
2030 mult = mult < 0 ? -units : units;
2033 do_div(frac, frac_d);
2034 *val = whole * mult + frac;
2038 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent, char *name, mode_t mode,
2039 struct file_operations *seq_fops, void *data)
2041 struct proc_dir_entry *entry;
2044 entry = create_proc_entry(name, mode, parent);
2047 entry->proc_fops = seq_fops;
2052 EXPORT_SYMBOL(lprocfs_seq_create);
2054 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
2056 struct file_operations *seq_fops,
2059 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2060 mode, seq_fops, data));
2062 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2064 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2066 if (value >= OBD_HIST_MAX)
2067 value = OBD_HIST_MAX - 1;
2069 spin_lock(&oh->oh_lock);
2070 oh->oh_buckets[value]++;
2071 spin_unlock(&oh->oh_lock);
2073 EXPORT_SYMBOL(lprocfs_oh_tally);
2075 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2079 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2082 lprocfs_oh_tally(oh, val);
2084 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2086 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2088 unsigned long ret = 0;
2091 for (i = 0; i < OBD_HIST_MAX; i++)
2092 ret += oh->oh_buckets[i];
2095 EXPORT_SYMBOL(lprocfs_oh_sum);
2097 void lprocfs_oh_clear(struct obd_histogram *oh)
2099 spin_lock(&oh->oh_lock);
2100 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2101 spin_unlock(&oh->oh_lock);
2103 EXPORT_SYMBOL(lprocfs_oh_clear);
2105 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2106 int count, int *eof, void *data)
2108 struct obd_device *obd = data;
2114 c += lustre_hash_debug_header(page, count);
2115 c += lustre_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2116 c += lustre_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2117 c += lustre_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2121 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2123 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2124 int count, int *eof, void *data)
2126 struct obd_device *obd = data;
2129 LASSERT(obd != NULL);
2130 LASSERT(count >= 0);
2132 /* Set start of user data returned to
2133 page + off since the user may have
2134 requested to read much smaller than
2135 what we need to read */
2136 *start = page + off;
2138 /* We know we are allocated a page here.
2139 Also we know that this function will
2140 not need to write more than a page
2141 so we can truncate at CFS_PAGE_SIZE. */
2142 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2144 /* Initialize the page */
2145 memset(page, 0, size);
2147 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2149 if (obd->obd_max_recoverable_clients == 0) {
2150 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2156 /* sampled unlocked, but really... */
2157 if (obd->obd_recovering == 0) {
2158 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2160 if (lprocfs_obd_snprintf(&page, size, &len,
2161 "recovery_start: %lu\n",
2162 obd->obd_recovery_start) <= 0)
2164 if (lprocfs_obd_snprintf(&page, size, &len,
2165 "recovery_duration: %lu\n",
2166 obd->obd_recovery_end -
2167 obd->obd_recovery_start) <= 0)
2169 /* Number of clients that have completed recovery */
2170 if (lprocfs_obd_snprintf(&page, size, &len,
2171 "completed_clients: %d/%d\n",
2172 obd->obd_max_recoverable_clients -
2173 obd->obd_stale_clients,
2174 obd->obd_max_recoverable_clients) <= 0)
2176 if (lprocfs_obd_snprintf(&page, size, &len,
2177 "replayed_requests: %d\n",
2178 obd->obd_replayed_requests) <= 0)
2180 if (lprocfs_obd_snprintf(&page, size, &len,
2181 "last_transno: "LPD64"\n",
2182 obd->obd_next_recovery_transno - 1)<=0)
2184 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2185 obd->obd_version_recov ? "ON" : "OFF")<=0)
2190 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2192 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2193 obd->obd_recovery_start) <= 0)
2195 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2196 cfs_time_current_sec() >= obd->obd_recovery_end ? 0 :
2197 obd->obd_recovery_end - cfs_time_current_sec()) <= 0)
2199 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2200 obd->obd_connected_clients,
2201 obd->obd_max_recoverable_clients) <= 0)
2203 /* Number of clients that have completed recovery */
2204 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2205 atomic_read(&obd->obd_req_replay_clients))<= 0)
2207 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2208 atomic_read(&obd->obd_lock_replay_clients))<=0)
2210 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2211 obd->obd_connected_clients -
2212 atomic_read(&obd->obd_lock_replay_clients))<=0)
2214 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2215 obd->obd_stale_clients) <= 0)
2217 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2218 obd->obd_replayed_requests) <= 0)
2220 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2221 obd->obd_requests_queued_for_recovery) <= 0)
2224 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2225 obd->obd_next_recovery_transno) <= 0)
2231 return min(count, len - (int)off);
2233 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2235 int lprocfs_obd_rd_recovery_maxtime(char *page, char **start, off_t off,
2236 int count, int *eof, void *data)
2238 struct obd_device *obd = data;
2239 LASSERT(obd != NULL);
2241 return snprintf(page, count, "%lu\n", obd->obd_recovery_max_time);
2243 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_maxtime);
2245 int lprocfs_obd_wr_recovery_maxtime(struct file *file, const char *buffer,
2246 unsigned long count, void *data)
2248 struct obd_device *obd = data;
2250 LASSERT(obd != NULL);
2252 rc = lprocfs_write_helper(buffer, count, &val);
2256 obd->obd_recovery_max_time = val;
2259 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_maxtime);
2262 EXPORT_SYMBOL(lprocfs_register);
2263 EXPORT_SYMBOL(lprocfs_srch);
2264 EXPORT_SYMBOL(lprocfs_remove);
2265 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
2266 EXPORT_SYMBOL(lprocfs_add_vars);
2267 EXPORT_SYMBOL(lprocfs_obd_setup);
2268 EXPORT_SYMBOL(lprocfs_obd_cleanup);
2269 EXPORT_SYMBOL(lprocfs_add_simple);
2270 EXPORT_SYMBOL(lprocfs_add_symlink);
2271 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
2272 EXPORT_SYMBOL(lprocfs_alloc_stats);
2273 EXPORT_SYMBOL(lprocfs_free_stats);
2274 EXPORT_SYMBOL(lprocfs_clear_stats);
2275 EXPORT_SYMBOL(lprocfs_register_stats);
2276 EXPORT_SYMBOL(lprocfs_init_ops_stats);
2277 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
2278 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
2279 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
2280 EXPORT_SYMBOL(lprocfs_free_obd_stats);
2281 EXPORT_SYMBOL(lprocfs_exp_setup);
2282 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2284 EXPORT_SYMBOL(lprocfs_rd_u64);
2285 EXPORT_SYMBOL(lprocfs_rd_atomic);
2286 EXPORT_SYMBOL(lprocfs_wr_atomic);
2287 EXPORT_SYMBOL(lprocfs_rd_uint);
2288 EXPORT_SYMBOL(lprocfs_wr_uint);
2289 EXPORT_SYMBOL(lprocfs_rd_uuid);
2290 EXPORT_SYMBOL(lprocfs_rd_name);
2291 EXPORT_SYMBOL(lprocfs_rd_fstype);
2292 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
2293 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
2294 EXPORT_SYMBOL(lprocfs_rd_num_exports);
2295 EXPORT_SYMBOL(lprocfs_rd_numrefs);
2296 EXPORT_SYMBOL(lprocfs_at_hist_helper);
2297 EXPORT_SYMBOL(lprocfs_rd_import);
2298 EXPORT_SYMBOL(lprocfs_rd_state);
2299 EXPORT_SYMBOL(lprocfs_rd_timeouts);
2300 EXPORT_SYMBOL(lprocfs_rd_blksize);
2301 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
2302 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
2303 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
2304 EXPORT_SYMBOL(lprocfs_rd_filestotal);
2305 EXPORT_SYMBOL(lprocfs_rd_filesfree);
2306 EXPORT_SYMBOL(lprocfs_rd_quota_resend_count);
2307 EXPORT_SYMBOL(lprocfs_wr_quota_resend_count);
2309 EXPORT_SYMBOL(lprocfs_write_helper);
2310 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2311 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2312 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2313 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2314 EXPORT_SYMBOL(lprocfs_stats_collect);