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;
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 = num_possible_cpus();
673 for (i = 0; i < num_cpu; i++) {
674 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[idx];
677 centry = atomic_read(&percpu_cntr->lc_cntl.la_entry);
678 t.lc_count = percpu_cntr->lc_count;
679 t.lc_sum = percpu_cntr->lc_sum;
680 t.lc_min = percpu_cntr->lc_min;
681 t.lc_max = percpu_cntr->lc_max;
682 t.lc_sumsquare = percpu_cntr->lc_sumsquare;
683 } while (centry != atomic_read(&percpu_cntr->lc_cntl.la_entry) &&
684 centry != atomic_read(&percpu_cntr->lc_cntl.la_exit));
685 cnt->lc_count += t.lc_count;
686 cnt->lc_sum += t.lc_sum;
687 if (t.lc_min < cnt->lc_min)
688 cnt->lc_min = t.lc_min;
689 if (t.lc_max > cnt->lc_max)
690 cnt->lc_max = t.lc_max;
691 cnt->lc_sumsquare += t.lc_sumsquare;
694 cnt->lc_units = stats->ls_percpu[0]->lp_cntr[idx].lc_units;
698 * Append a space separated list of current set flags to str.
700 #define flag2str(flag) \
701 if (imp->imp_##flag && max - len > 0) \
702 len += snprintf(str + len, max - len, "%s" #flag, len ? ", " : "");
703 static int obd_import_flags2str(struct obd_import *imp, char *str, int max)
707 if (imp->imp_obd->obd_no_recov)
708 len += snprintf(str, max - len, "no_recov");
712 flag2str(replayable);
715 flag2str(last_recon);
720 static const char *obd_connect_names[] = {
747 "mds_mds_connection",
750 "alt_checksum_algorithm",
759 static int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
764 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
766 ret += snprintf(page + ret, count - ret, "%s%s",
767 ret ? sep : "", obd_connect_names[i]);
769 if (flags & ~(mask - 1))
770 ret += snprintf(page + ret, count - ret,
771 "%sunknown flags "LPX64,
772 ret ? sep : "", flags & ~(mask - 1));
776 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
777 int *eof, void *data)
779 struct lprocfs_counter ret;
780 struct obd_device *obd = (struct obd_device *)data;
781 struct obd_import *imp;
784 LASSERT(obd != NULL);
785 LPROCFS_CLIMP_CHECK(obd);
786 imp = obd->u.cli.cl_import;
789 i = snprintf(page, count,
793 " current_connection: %s\n"
798 imp->imp_connection->c_remote_uuid.uuid,
799 ptlrpc_import_state_name(imp->imp_state));
800 i += obd_connect_flags2str(page + i, count - i,
801 imp->imp_connect_data.ocd_connect_flags,
803 i += snprintf(page + i, count - i,
806 i += obd_import_flags2str(imp, page + i, count - i);
808 i += snprintf(page + i, count - i,
811 " connection_attempts: %u\n"
813 " in-progress_invalidations: %u\n",
816 atomic_read(&imp->imp_inval_count));
818 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
819 do_div(ret.lc_sum, ret.lc_count);
820 i += snprintf(page + i, count - i,
823 " unregistering: %u\n"
825 " avg_waittime: "LPU64" %s\n",
826 atomic_read(&imp->imp_inflight),
827 atomic_read(&imp->imp_unregistering),
828 atomic_read(&imp->imp_timeouts),
829 ret.lc_sum, ret.lc_units);
832 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
833 if (imp->imp_at.iat_portal[j] == 0)
835 k = max_t(unsigned int, k,
836 at_get(&imp->imp_at.iat_service_estimate[j]));
838 i += snprintf(page + i, count - i,
839 " service_estimates:\n"
840 " services: %u sec\n"
841 " network: %u sec\n",
843 at_get(&imp->imp_at.iat_net_latency));
845 i += snprintf(page + i, count - i,
847 " last_replay: "LPU64"\n"
848 " peer_committed: "LPU64"\n"
849 " last_checked: "LPU64"\n",
850 imp->imp_last_replay_transno,
851 imp->imp_peer_committed_transno,
852 imp->imp_last_transno_checked);
855 for (rw = 0; rw <= 1; rw++) {
856 lprocfs_stats_collect(obd->obd_svc_stats,
857 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
859 if (ret.lc_sum > 0) {
860 do_div(ret.lc_sum, ret.lc_count);
861 i += snprintf(page + i, count - i,
862 " %s_data_averages:\n"
863 " bytes_per_rpc: "LPU64"\n",
864 rw ? "write" : "read",
868 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
869 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
870 if (ret.lc_sum > 0) {
871 do_div(ret.lc_sum, ret.lc_count);
872 i += snprintf(page + i, count - i,
873 " %s_per_rpc: "LPU64"\n",
874 ret.lc_units, ret.lc_sum);
877 i += snprintf(page + i, count - i,
878 " MB_per_sec: %u.%.02u\n",
879 k / j, (100 * k / j) % 100);
883 LPROCFS_CLIMP_EXIT(obd);
887 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
888 int *eof, void *data)
890 struct obd_device *obd = (struct obd_device *)data;
891 struct obd_import *imp;
894 LASSERT(obd != NULL);
895 LPROCFS_CLIMP_CHECK(obd);
896 imp = obd->u.cli.cl_import;
899 i = snprintf(page, count, "current_state: %s\n",
900 ptlrpc_import_state_name(imp->imp_state));
901 i += snprintf(page + i, count - i,
903 k = imp->imp_state_hist_idx;
904 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
905 struct import_state_hist *ish =
906 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
907 if (ish->ish_state == 0)
909 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
911 ptlrpc_import_state_name(ish->ish_state));
914 LPROCFS_CLIMP_EXIT(obd);
918 int lprocfs_at_hist_helper(char *page, int count, int rc,
919 struct adaptive_timeout *at)
922 for (i = 0; i < AT_BINS; i++)
923 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
924 rc += snprintf(page + rc, count - rc, "\n");
928 int lprocfs_rd_quota_resend_count(char *page, char **start, off_t off,
929 int count, int *eof, void *data)
931 struct obd_device *obd = data;
933 return snprintf(page, count, "%d\n",
934 atomic_read(&obd->u.cli.cl_quota_resends));
937 int lprocfs_wr_quota_resend_count(struct file *file, const char *buffer,
938 unsigned long count, void *data)
940 struct obd_device *obd = data;
943 rc = lprocfs_write_helper(buffer, count, &val);
947 atomic_set(&obd->u.cli.cl_quota_resends, val);
952 /* See also ptlrpc_lprocfs_rd_timeouts */
953 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
954 int *eof, void *data)
956 struct obd_device *obd = (struct obd_device *)data;
957 struct obd_import *imp;
958 unsigned int cur, worst;
963 LASSERT(obd != NULL);
964 LPROCFS_CLIMP_CHECK(obd);
965 imp = obd->u.cli.cl_import;
968 now = cfs_time_current_sec();
970 /* Some network health info for kicks */
971 s2dhms(&ts, now - imp->imp_last_reply_time);
972 rc += snprintf(page + rc, count - rc,
973 "%-10s : %ld, "DHMS_FMT" ago\n",
974 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
976 cur = at_get(&imp->imp_at.iat_net_latency);
977 worst = imp->imp_at.iat_net_latency.at_worst_ever;
978 worstt = imp->imp_at.iat_net_latency.at_worst_time;
979 s2dhms(&ts, now - worstt);
980 rc += snprintf(page + rc, count - rc,
981 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
982 "network", cur, worst, worstt, DHMS_VARS(&ts));
983 rc = lprocfs_at_hist_helper(page, count, rc,
984 &imp->imp_at.iat_net_latency);
986 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
987 if (imp->imp_at.iat_portal[i] == 0)
989 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
990 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
991 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
992 s2dhms(&ts, now - worstt);
993 rc += snprintf(page + rc, count - rc,
994 "portal %-2d : cur %3u worst %3u (at %ld, "
995 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
996 cur, worst, worstt, DHMS_VARS(&ts));
997 rc = lprocfs_at_hist_helper(page, count, rc,
998 &imp->imp_at.iat_service_estimate[i]);
1001 LPROCFS_CLIMP_EXIT(obd);
1005 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1006 int count, int *eof, void *data)
1008 struct obd_device *obd = data;
1012 LPROCFS_CLIMP_CHECK(obd);
1013 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1014 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1015 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1016 ret += snprintf(page + ret, count - ret, "\n");
1017 LPROCFS_CLIMP_EXIT(obd);
1020 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1022 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1023 int *eof, void *data)
1025 struct obd_device *obd = data;
1027 LASSERT(obd != NULL);
1029 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1032 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1033 int *eof, void *data)
1035 struct obd_type *class = (struct obd_type*) data;
1037 LASSERT(class != NULL);
1039 return snprintf(page, count, "%d\n", class->typ_refcnt);
1042 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1046 LASSERT(obd != NULL);
1047 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1048 LASSERT(obd->obd_type->typ_procroot != NULL);
1050 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1051 obd->obd_type->typ_procroot,
1053 if (IS_ERR(obd->obd_proc_entry)) {
1054 rc = PTR_ERR(obd->obd_proc_entry);
1055 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1056 obd->obd_proc_entry = NULL;
1061 int lprocfs_obd_cleanup(struct obd_device *obd)
1065 if (obd->obd_proc_exports_entry) {
1066 /* Should be no exports left */
1067 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1068 lprocfs_remove(&obd->obd_proc_exports_entry);
1069 obd->obd_proc_exports_entry = NULL;
1071 if (obd->obd_proc_entry) {
1072 lprocfs_remove(&obd->obd_proc_entry);
1073 obd->obd_proc_entry = NULL;
1078 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1080 CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
1081 client_stat->nid_proc, client_stat->nid_stats,
1082 client_stat->nid_brw_stats);
1084 LASSERTF(atomic_read(&client_stat->nid_exp_ref_count) == 0,
1085 "count %d\n", atomic_read(&client_stat->nid_exp_ref_count));
1087 hlist_del_init(&client_stat->nid_hash);
1089 if (client_stat->nid_proc)
1090 lprocfs_remove(&client_stat->nid_proc);
1092 if (client_stat->nid_stats)
1093 lprocfs_free_stats(&client_stat->nid_stats);
1095 if (client_stat->nid_brw_stats)
1096 OBD_FREE_PTR(client_stat->nid_brw_stats);
1098 if (client_stat->nid_ldlm_stats)
1099 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1101 OBD_FREE_PTR(client_stat);
1106 void lprocfs_free_per_client_stats(struct obd_device *obd)
1108 struct nid_stat *stat;
1111 /* we need extra list - because hash_exit called to early */
1112 /* not need locking because all clients is died */
1113 while(!list_empty(&obd->obd_nid_stats)) {
1114 stat = list_entry(obd->obd_nid_stats.next,
1115 struct nid_stat, nid_list);
1116 list_del_init(&stat->nid_list);
1117 lprocfs_free_client_stats(stat);
1123 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1124 enum lprocfs_stats_flags flags)
1126 struct lprocfs_stats *stats;
1127 unsigned int percpusize;
1129 unsigned int num_cpu;
1134 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1137 num_cpu = num_possible_cpus();
1139 OBD_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
1143 if (flags & LPROCFS_STATS_FLAG_NOPERCPU) {
1144 stats->ls_flags = flags;
1145 spin_lock_init(&stats->ls_lock);
1146 /* Use this lock only if there are no percpu areas */
1148 stats->ls_flags = 0;
1151 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
1153 percpusize = L1_CACHE_ALIGN(percpusize);
1155 for (i = 0; i < num_cpu; i++) {
1156 OBD_ALLOC(stats->ls_percpu[i], percpusize);
1157 if (stats->ls_percpu[i] == NULL) {
1158 for (j = 0; j < i; j++) {
1159 OBD_FREE(stats->ls_percpu[j], percpusize);
1160 stats->ls_percpu[j] = NULL;
1165 if (stats->ls_percpu[0] == NULL) {
1166 OBD_FREE(stats, offsetof(typeof(*stats),
1167 ls_percpu[num_cpu]));
1171 stats->ls_num = num;
1175 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1177 struct lprocfs_stats *stats = *statsh;
1178 unsigned int num_cpu;
1179 unsigned int percpusize;
1182 if (stats == NULL || stats->ls_num == 0)
1186 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1189 num_cpu = num_possible_cpus();
1191 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
1193 percpusize = L1_CACHE_ALIGN(percpusize);
1194 for (i = 0; i < num_cpu; i++)
1195 OBD_FREE(stats->ls_percpu[i], percpusize);
1196 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
1199 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1201 struct lprocfs_counter *percpu_cntr;
1203 unsigned int num_cpu;
1205 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1207 for (i = 0; i < num_cpu; i++) {
1208 for (j = 0; j < stats->ls_num; j++) {
1209 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
1210 atomic_inc(&percpu_cntr->lc_cntl.la_entry);
1211 percpu_cntr->lc_count = 0;
1212 percpu_cntr->lc_sum = 0;
1213 percpu_cntr->lc_min = LC_MIN_INIT;
1214 percpu_cntr->lc_max = 0;
1215 percpu_cntr->lc_sumsquare = 0;
1216 atomic_inc(&percpu_cntr->lc_cntl.la_exit);
1220 lprocfs_stats_unlock(stats);
1223 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1224 size_t len, loff_t *off)
1226 struct seq_file *seq = file->private_data;
1227 struct lprocfs_stats *stats = seq->private;
1229 lprocfs_clear_stats(stats);
1234 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1236 struct lprocfs_stats *stats = p->private;
1237 /* return 1st cpu location */
1238 return (*pos >= stats->ls_num) ? NULL :
1239 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1242 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1246 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1248 struct lprocfs_stats *stats = p->private;
1250 return (*pos >= stats->ls_num) ? NULL :
1251 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1254 /* seq file export of one lprocfs counter */
1255 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1257 struct lprocfs_stats *stats = p->private;
1258 struct lprocfs_counter *cntr = v;
1259 struct lprocfs_counter ret;
1262 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
1264 do_gettimeofday(&now);
1265 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1266 "snapshot_time", now.tv_sec, now.tv_usec);
1270 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
1272 lprocfs_stats_collect(stats, idx, &ret);
1274 if (ret.lc_count == 0)
1277 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", cntr->lc_name,
1278 ret.lc_count, cntr->lc_units);
1283 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
1284 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1285 ret.lc_min, ret.lc_max, ret.lc_sum);
1288 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
1289 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1293 rc = seq_printf(p, "\n");
1295 return (rc < 0) ? rc : 0;
1298 struct seq_operations lprocfs_stats_seq_sops = {
1299 start: lprocfs_stats_seq_start,
1300 stop: lprocfs_stats_seq_stop,
1301 next: lprocfs_stats_seq_next,
1302 show: lprocfs_stats_seq_show,
1305 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1307 struct proc_dir_entry *dp = PDE(inode);
1308 struct seq_file *seq;
1311 if (LPROCFS_ENTRY_AND_CHECK(dp))
1314 rc = seq_open(file, &lprocfs_stats_seq_sops);
1319 seq = file->private_data;
1320 seq->private = dp->data;
1324 struct file_operations lprocfs_stats_seq_fops = {
1325 .owner = THIS_MODULE,
1326 .open = lprocfs_stats_seq_open,
1328 .write = lprocfs_stats_seq_write,
1329 .llseek = seq_lseek,
1330 .release = lprocfs_seq_release,
1333 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1334 struct lprocfs_stats *stats)
1336 struct proc_dir_entry *entry;
1337 LASSERT(root != NULL);
1339 entry = create_proc_entry(name, 0644, root);
1342 entry->proc_fops = &lprocfs_stats_seq_fops;
1343 entry->data = stats;
1347 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1348 unsigned conf, const char *name, const char *units)
1350 struct lprocfs_counter *c;
1352 unsigned int num_cpu;
1354 LASSERT(stats != NULL);
1356 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1358 for (i = 0; i < num_cpu; i++) {
1359 c = &(stats->ls_percpu[i]->lp_cntr[index]);
1360 c->lc_config = conf;
1363 c->lc_min = LC_MIN_INIT;
1366 c->lc_units = units;
1369 lprocfs_stats_unlock(stats);
1371 EXPORT_SYMBOL(lprocfs_counter_init);
1373 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1375 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1376 LASSERT(coffset < stats->ls_num); \
1377 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1380 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1382 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1383 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1384 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1385 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1386 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1387 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1388 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1389 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1390 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1391 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1392 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1393 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1394 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1395 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1396 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1397 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1398 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1399 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1400 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
1401 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1402 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1403 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1404 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1405 LPROCFS_OBD_OP_INIT(num_private_stats, stats, checkmd);
1406 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1407 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1408 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1409 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1410 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1411 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1412 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1413 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1414 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1415 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1416 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1417 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1418 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1419 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1420 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1421 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1422 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1423 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1424 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1425 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1426 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1427 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1428 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1429 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1430 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1431 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1432 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1433 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1434 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1435 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1436 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1437 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1438 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1439 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1440 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1441 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1442 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1443 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quota_adjust_qunit);
1444 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1445 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1446 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1447 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1448 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1449 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1450 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1453 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1455 struct lprocfs_stats *stats;
1456 unsigned int num_stats;
1459 LASSERT(obd->obd_stats == NULL);
1460 LASSERT(obd->obd_proc_entry != NULL);
1461 LASSERT(obd->obd_cntr_base == 0);
1463 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1464 num_private_stats - 1 /* o_owner */;
1465 stats = lprocfs_alloc_stats(num_stats, 0);
1469 lprocfs_init_ops_stats(num_private_stats, stats);
1471 for (i = num_private_stats; i < num_stats; i++) {
1472 /* If this LBUGs, it is likely that an obd
1473 * operation was added to struct obd_ops in
1474 * <obd.h>, and that the corresponding line item
1475 * LPROCFS_OBD_OP_INIT(.., .., opname)
1476 * is missing from the list above. */
1477 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1478 "Missing obd_stat initializer obd_op "
1479 "operation at offset %d.\n", i - num_private_stats);
1481 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1483 lprocfs_free_stats(&stats);
1485 obd->obd_stats = stats;
1486 obd->obd_cntr_base = num_private_stats;
1491 void lprocfs_free_obd_stats(struct obd_device *obd)
1494 lprocfs_free_stats(&obd->obd_stats);
1497 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1499 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1500 LASSERT(coffset < stats->ls_num); \
1501 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1504 int lprocfs_alloc_md_stats(struct obd_device *obd,
1505 unsigned num_private_stats)
1507 struct lprocfs_stats *stats;
1508 unsigned int num_stats;
1511 LASSERT(obd->md_stats == NULL);
1512 LASSERT(obd->obd_proc_entry != NULL);
1513 LASSERT(obd->md_cntr_base == 0);
1515 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1517 stats = lprocfs_alloc_stats(num_stats, 0);
1521 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1522 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1523 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1524 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1525 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1526 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1527 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1528 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1529 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1530 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1531 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1532 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1533 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1534 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1535 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1536 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1537 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1538 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1539 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1540 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1541 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1542 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1543 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1544 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1545 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1546 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1547 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1548 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1549 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1550 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1551 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1553 for (i = num_private_stats; i < num_stats; i++) {
1554 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1555 CERROR("Missing md_stat initializer md_op "
1556 "operation at offset %d. Aborting.\n",
1557 i - num_private_stats);
1561 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1563 lprocfs_free_stats(&stats);
1565 obd->md_stats = stats;
1566 obd->md_cntr_base = num_private_stats;
1571 void lprocfs_free_md_stats(struct obd_device *obd)
1573 struct lprocfs_stats *stats = obd->md_stats;
1575 if (stats != NULL) {
1576 obd->md_stats = NULL;
1577 obd->md_cntr_base = 0;
1578 lprocfs_free_stats(&stats);
1582 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1584 lprocfs_counter_init(ldlm_stats,
1585 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1586 0, "ldlm_enqueue", "reqs");
1587 lprocfs_counter_init(ldlm_stats,
1588 LDLM_CONVERT - LDLM_FIRST_OPC,
1589 0, "ldlm_convert", "reqs");
1590 lprocfs_counter_init(ldlm_stats,
1591 LDLM_CANCEL - LDLM_FIRST_OPC,
1592 0, "ldlm_cancel", "reqs");
1593 lprocfs_counter_init(ldlm_stats,
1594 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1595 0, "ldlm_bl_callback", "reqs");
1596 lprocfs_counter_init(ldlm_stats,
1597 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1598 0, "ldlm_cp_callback", "reqs");
1599 lprocfs_counter_init(ldlm_stats,
1600 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1601 0, "ldlm_gl_callback", "reqs");
1604 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1605 int *eof, void *data)
1607 struct obd_export *exp = data;
1608 LASSERT(exp != NULL);
1610 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1613 struct exp_uuid_cb_data {
1621 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1622 int count, int *eof, int *len)
1624 cb_data->page = page;
1625 cb_data->count = count;
1630 void lprocfs_exp_print_uuid(void *obj, void *cb_data)
1632 struct obd_export *exp = (struct obd_export *)obj;
1633 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1635 if (exp->exp_nid_stats)
1636 *data->len += snprintf((data->page + *data->len),
1637 data->count, "%s\n",
1638 obd_uuid2str(&exp->exp_client_uuid));
1641 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1642 int *eof, void *data)
1644 struct nid_stat *stats = (struct nid_stat *)data;
1645 struct exp_uuid_cb_data cb_data;
1646 struct obd_device *obd = stats->nid_obd;
1651 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1652 lustre_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1653 lprocfs_exp_print_uuid, &cb_data);
1654 return (*cb_data.len);
1657 void lprocfs_exp_print_hash(void *obj, void *cb_data)
1659 struct exp_uuid_cb_data *data = cb_data;
1660 struct obd_export *exp = obj;
1663 lh = exp->exp_lock_hash;
1666 *data->len += lustre_hash_debug_header(data->page,
1669 *data->len += lustre_hash_debug_str(lh, data->page + *data->len,
1674 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1675 int *eof, void *data)
1677 struct nid_stat *stats = (struct nid_stat *)data;
1678 struct exp_uuid_cb_data cb_data;
1679 struct obd_device *obd = stats->nid_obd;
1684 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1686 lustre_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1687 lprocfs_exp_print_hash, &cb_data);
1688 return (*cb_data.len);
1691 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1692 int count, int *eof, void *data)
1695 return snprintf(page, count, "%s\n",
1696 "Write into this file to clear all nid stats and "
1697 "stale nid entries");
1699 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1701 void lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1703 struct nid_stat *stat = obj;
1706 /* object has only hash + iterate_all references.
1707 * add/delete blocked by hash bucket lock */
1708 CDEBUG(D_INFO,"refcnt %d\n", atomic_read(&stat->nid_exp_ref_count));
1709 if (atomic_read(&stat->nid_exp_ref_count) == 2) {
1710 hlist_del_init(&stat->nid_hash);
1711 nidstat_putref(stat);
1712 spin_lock(&stat->nid_obd->obd_nid_lock);
1713 list_move(&stat->nid_list, data);
1714 spin_unlock(&stat->nid_obd->obd_nid_lock);
1718 /* we has reference to object - only clear data*/
1719 if (stat->nid_stats)
1720 lprocfs_clear_stats(stat->nid_stats);
1722 if (stat->nid_brw_stats) {
1723 for (i = 0; i < BRW_LAST; i++)
1724 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
1730 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1731 unsigned long count, void *data)
1733 struct obd_device *obd = (struct obd_device *)data;
1734 struct nid_stat *client_stat;
1735 CFS_LIST_HEAD(free_list);
1737 lustre_hash_for_each(obd->obd_nid_stats_hash,
1738 lprocfs_nid_stats_clear_write_cb, &free_list);
1740 while (!list_empty(&free_list)) {
1741 client_stat = list_entry(free_list.next, struct nid_stat,
1743 list_del_init(&client_stat->nid_list);
1744 lprocfs_free_client_stats(client_stat);
1749 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1751 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1753 struct nid_stat *new_stat, *old_stat;
1754 struct obd_device *obd = NULL;
1755 cfs_proc_dir_entry_t *entry;
1761 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1762 !exp->exp_obd->obd_nid_stats_hash)
1765 /* not test against zero because eric say:
1766 * You may only test nid against another nid, or LNET_NID_ANY.
1767 * Anything else is nonsense.*/
1768 if (!nid || *nid == LNET_NID_ANY)
1773 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
1775 OBD_ALLOC_PTR(new_stat);
1776 if (new_stat == NULL)
1779 new_stat->nid = *nid;
1780 new_stat->nid_obd = exp->exp_obd;
1781 atomic_set(&new_stat->nid_exp_ref_count, 0);
1783 old_stat = lustre_hash_findadd_unique(obd->obd_nid_stats_hash,
1784 nid, &new_stat->nid_hash);
1785 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
1786 old_stat, libcfs_nid2str(*nid),
1787 atomic_read(&new_stat->nid_exp_ref_count));
1789 /* Return -EALREADY here so that we know that the /proc
1790 * entry already has been created */
1791 if (old_stat != new_stat) {
1792 spin_lock(&obd->obd_nid_lock);
1793 if (exp->exp_nid_stats != old_stat) {
1794 if (exp->exp_nid_stats)
1795 nidstat_putref(exp->exp_nid_stats);
1796 exp->exp_nid_stats = old_stat;
1798 /* lustre_hash_findadd_unique() has added
1799 * old_stat's refcount */
1800 nidstat_putref(old_stat);
1803 spin_unlock(&obd->obd_nid_lock);
1805 GOTO(destroy_new, rc = -EALREADY);
1807 /* not found - create */
1808 new_stat->nid_proc = lprocfs_register(libcfs_nid2str(*nid),
1809 obd->obd_proc_exports_entry,
1811 if (new_stat->nid_proc == NULL) {
1812 CERROR("Error making export directory for nid %s\n",
1813 libcfs_nid2str(*nid));
1814 GOTO(destroy_new_ns, rc = -ENOMEM);
1817 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
1818 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
1819 if (IS_ERR(entry)) {
1820 CWARN("Error adding the NID stats file\n");
1821 rc = PTR_ERR(entry);
1822 GOTO(destroy_new_ns, rc);
1825 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
1826 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
1827 if (IS_ERR(entry)) {
1828 CWARN("Error adding the hash file\n");
1829 rc = PTR_ERR(entry);
1830 GOTO(destroy_new_ns, rc);
1833 if (exp->exp_nid_stats)
1834 nidstat_putref(exp->exp_nid_stats);
1835 nidstat_getref(new_stat);
1836 exp->exp_nid_stats = new_stat;
1838 /* protect competitive add to list, not need locking on destroy */
1839 spin_lock(&obd->obd_nid_lock);
1840 list_add(&new_stat->nid_list, &obd->obd_nid_stats);
1841 spin_unlock(&obd->obd_nid_lock);
1846 if (new_stat->nid_proc != NULL)
1847 lprocfs_remove(&new_stat->nid_proc);
1848 lustre_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
1851 OBD_FREE_PTR(new_stat);
1855 int lprocfs_exp_cleanup(struct obd_export *exp)
1857 struct nid_stat *stat = exp->exp_nid_stats;
1859 if(!stat || !exp->exp_obd)
1862 nidstat_putref(exp->exp_nid_stats);
1863 exp->exp_nid_stats = NULL;
1864 lprocfs_free_md_stats(exp->exp_obd);
1869 int lprocfs_write_helper(const char *buffer, unsigned long count,
1872 return lprocfs_write_frac_helper(buffer, count, val, 1);
1875 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
1878 char kernbuf[20], *end, *pbuf;
1880 if (count > (sizeof(kernbuf) - 1))
1883 if (copy_from_user(kernbuf, buffer, count))
1886 kernbuf[count] = '\0';
1893 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1897 if (end != NULL && *end == '.') {
1898 int temp_val, pow = 1;
1902 if (strlen(pbuf) > 5)
1903 pbuf[5] = '\0'; /*only allow 5bits fractional*/
1905 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1908 for (i = 0; i < (end - pbuf); i++)
1911 *val += temp_val / pow;
1917 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
1920 long decimal_val, frac_val;
1926 decimal_val = val / mult;
1927 prtn = snprintf(buffer, count, "%ld", decimal_val);
1928 frac_val = val % mult;
1930 if (prtn < (count - 4) && frac_val > 0) {
1932 int i, temp_mult = 1, frac_bits = 0;
1934 temp_frac = frac_val * 10;
1935 buffer[prtn++] = '.';
1936 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
1937 /* only reserved 2 bits fraction */
1938 buffer[prtn++] ='0';
1943 * Need to think these cases :
1944 * 1. #echo x.00 > /proc/xxx output result : x
1945 * 2. #echo x.0x > /proc/xxx output result : x.0x
1946 * 3. #echo x.x0 > /proc/xxx output result : x.x
1947 * 4. #echo x.xx > /proc/xxx output result : x.xx
1948 * Only reserved 2 bits fraction.
1950 for (i = 0; i < (5 - prtn); i++)
1953 frac_bits = min((int)count - prtn, 3 - frac_bits);
1954 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
1955 frac_val * temp_mult / mult);
1958 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
1960 if (buffer[prtn] == '.') {
1967 buffer[prtn++] ='\n';
1971 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
1973 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
1976 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
1977 __u64 *val, int mult)
1979 char kernbuf[22], *end, *pbuf;
1980 __u64 whole, frac = 0, units;
1981 unsigned frac_d = 1;
1983 if (count > (sizeof(kernbuf) - 1))
1986 if (copy_from_user(kernbuf, buffer, count))
1989 kernbuf[count] = '\0';
1996 whole = simple_strtoull(pbuf, &end, 10);
2000 if (end != NULL && *end == '.') {
2004 /* need to limit frac_d to a __u32 */
2005 if (strlen(pbuf) > 10)
2008 frac = simple_strtoull(pbuf, &end, 10);
2009 /* count decimal places */
2010 for (i = 0; i < (end - pbuf); i++)
2027 /* Specified units override the multiplier */
2029 mult = mult < 0 ? -units : units;
2032 do_div(frac, frac_d);
2033 *val = whole * mult + frac;
2037 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent, char *name, mode_t mode,
2038 struct file_operations *seq_fops, void *data)
2040 struct proc_dir_entry *entry;
2043 entry = create_proc_entry(name, mode, parent);
2046 entry->proc_fops = seq_fops;
2051 EXPORT_SYMBOL(lprocfs_seq_create);
2053 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
2055 struct file_operations *seq_fops,
2058 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2059 mode, seq_fops, data));
2061 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2063 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2065 if (value >= OBD_HIST_MAX)
2066 value = OBD_HIST_MAX - 1;
2068 spin_lock(&oh->oh_lock);
2069 oh->oh_buckets[value]++;
2070 spin_unlock(&oh->oh_lock);
2072 EXPORT_SYMBOL(lprocfs_oh_tally);
2074 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2078 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2081 lprocfs_oh_tally(oh, val);
2083 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2085 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2087 unsigned long ret = 0;
2090 for (i = 0; i < OBD_HIST_MAX; i++)
2091 ret += oh->oh_buckets[i];
2094 EXPORT_SYMBOL(lprocfs_oh_sum);
2096 void lprocfs_oh_clear(struct obd_histogram *oh)
2098 spin_lock(&oh->oh_lock);
2099 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2100 spin_unlock(&oh->oh_lock);
2102 EXPORT_SYMBOL(lprocfs_oh_clear);
2104 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2105 int count, int *eof, void *data)
2107 struct obd_device *obd = data;
2113 c += lustre_hash_debug_header(page, count);
2114 c += lustre_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2115 c += lustre_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2116 c += lustre_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2120 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2122 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2123 int count, int *eof, void *data)
2125 struct obd_device *obd = data;
2128 LASSERT(obd != NULL);
2129 LASSERT(count >= 0);
2131 /* Set start of user data returned to
2132 page + off since the user may have
2133 requested to read much smaller than
2134 what we need to read */
2135 *start = page + off;
2137 /* We know we are allocated a page here.
2138 Also we know that this function will
2139 not need to write more than a page
2140 so we can truncate at CFS_PAGE_SIZE. */
2141 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2143 /* Initialize the page */
2144 memset(page, 0, size);
2146 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2148 if (obd->obd_max_recoverable_clients == 0) {
2149 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2155 /* sampled unlocked, but really... */
2156 if (obd->obd_recovering == 0) {
2157 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2159 if (lprocfs_obd_snprintf(&page, size, &len,
2160 "recovery_start: %lu\n",
2161 obd->obd_recovery_start) <= 0)
2163 if (lprocfs_obd_snprintf(&page, size, &len,
2164 "recovery_duration: %lu\n",
2165 obd->obd_recovery_end -
2166 obd->obd_recovery_start) <= 0)
2168 /* Number of clients that have completed recovery */
2169 if (lprocfs_obd_snprintf(&page, size, &len,
2170 "completed_clients: %d/%d\n",
2171 obd->obd_max_recoverable_clients -
2172 obd->obd_stale_clients,
2173 obd->obd_max_recoverable_clients) <= 0)
2175 if (lprocfs_obd_snprintf(&page, size, &len,
2176 "replayed_requests: %d\n",
2177 obd->obd_replayed_requests) <= 0)
2179 if (lprocfs_obd_snprintf(&page, size, &len,
2180 "last_transno: "LPD64"\n",
2181 obd->obd_next_recovery_transno - 1)<=0)
2183 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2184 obd->obd_version_recov ? "ON" : "OFF")<=0)
2189 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2191 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2192 obd->obd_recovery_start) <= 0)
2194 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2195 cfs_time_current_sec() >= obd->obd_recovery_end ? 0 :
2196 obd->obd_recovery_end - cfs_time_current_sec()) <= 0)
2198 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2199 obd->obd_connected_clients,
2200 obd->obd_max_recoverable_clients) <= 0)
2202 /* Number of clients that have completed recovery */
2203 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2204 atomic_read(&obd->obd_req_replay_clients))<= 0)
2206 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2207 atomic_read(&obd->obd_lock_replay_clients))<=0)
2209 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2210 obd->obd_connected_clients -
2211 atomic_read(&obd->obd_lock_replay_clients))<=0)
2213 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2214 obd->obd_stale_clients) <= 0)
2216 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2217 obd->obd_replayed_requests) <= 0)
2219 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2220 obd->obd_requests_queued_for_recovery) <= 0)
2223 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2224 obd->obd_next_recovery_transno) <= 0)
2230 return min(count, len - (int)off);
2232 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2234 int lprocfs_obd_rd_recovery_maxtime(char *page, char **start, off_t off,
2235 int count, int *eof, void *data)
2237 struct obd_device *obd = data;
2238 LASSERT(obd != NULL);
2240 return snprintf(page, count, "%lu\n", obd->obd_recovery_max_time);
2242 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_maxtime);
2244 int lprocfs_obd_wr_recovery_maxtime(struct file *file, const char *buffer,
2245 unsigned long count, void *data)
2247 struct obd_device *obd = data;
2249 LASSERT(obd != NULL);
2251 rc = lprocfs_write_helper(buffer, count, &val);
2255 obd->obd_recovery_max_time = val;
2258 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_maxtime);
2261 EXPORT_SYMBOL(lprocfs_register);
2262 EXPORT_SYMBOL(lprocfs_srch);
2263 EXPORT_SYMBOL(lprocfs_remove);
2264 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
2265 EXPORT_SYMBOL(lprocfs_add_vars);
2266 EXPORT_SYMBOL(lprocfs_obd_setup);
2267 EXPORT_SYMBOL(lprocfs_obd_cleanup);
2268 EXPORT_SYMBOL(lprocfs_add_simple);
2269 EXPORT_SYMBOL(lprocfs_add_symlink);
2270 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
2271 EXPORT_SYMBOL(lprocfs_alloc_stats);
2272 EXPORT_SYMBOL(lprocfs_free_stats);
2273 EXPORT_SYMBOL(lprocfs_clear_stats);
2274 EXPORT_SYMBOL(lprocfs_register_stats);
2275 EXPORT_SYMBOL(lprocfs_init_ops_stats);
2276 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
2277 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
2278 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
2279 EXPORT_SYMBOL(lprocfs_free_obd_stats);
2280 EXPORT_SYMBOL(lprocfs_exp_setup);
2281 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2283 EXPORT_SYMBOL(lprocfs_rd_u64);
2284 EXPORT_SYMBOL(lprocfs_rd_atomic);
2285 EXPORT_SYMBOL(lprocfs_wr_atomic);
2286 EXPORT_SYMBOL(lprocfs_rd_uint);
2287 EXPORT_SYMBOL(lprocfs_wr_uint);
2288 EXPORT_SYMBOL(lprocfs_rd_uuid);
2289 EXPORT_SYMBOL(lprocfs_rd_name);
2290 EXPORT_SYMBOL(lprocfs_rd_fstype);
2291 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
2292 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
2293 EXPORT_SYMBOL(lprocfs_rd_num_exports);
2294 EXPORT_SYMBOL(lprocfs_rd_numrefs);
2295 EXPORT_SYMBOL(lprocfs_at_hist_helper);
2296 EXPORT_SYMBOL(lprocfs_rd_import);
2297 EXPORT_SYMBOL(lprocfs_rd_state);
2298 EXPORT_SYMBOL(lprocfs_rd_timeouts);
2299 EXPORT_SYMBOL(lprocfs_rd_blksize);
2300 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
2301 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
2302 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
2303 EXPORT_SYMBOL(lprocfs_rd_filestotal);
2304 EXPORT_SYMBOL(lprocfs_rd_filesfree);
2305 EXPORT_SYMBOL(lprocfs_rd_quota_resend_count);
2306 EXPORT_SYMBOL(lprocfs_wr_quota_resend_count);
2308 EXPORT_SYMBOL(lprocfs_write_helper);
2309 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2310 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2311 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2312 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2313 EXPORT_SYMBOL(lprocfs_stats_collect);