1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 only,
10 * as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License version 2 for more details (a copy is included
16 * in the LICENSE file that accompanied this code).
18 * You should have received a copy of the GNU General Public License
19 * version 2 along with this program; If not, see
20 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
22 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23 * CA 95054 USA or visit www.sun.com if you need additional information or
29 * Copyright 2008 Sun Microsystems, Inc. All rights reserved
30 * Use is subject to license terms.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
36 * lustre/obdclass/lprocfs_status.c
38 * Author: Hariharan Thantry <thantry@users.sourceforge.net>
42 # define EXPORT_SYMTAB
44 #define DEBUG_SUBSYSTEM S_CLASS
47 # include <liblustre.h>
50 #include <obd_class.h>
51 #include <lprocfs_status.h>
52 #include <lustre_fsfilt.h>
53 #include <lustre_log.h>
54 #include <lustre/lustre_idl.h>
58 #define MAX_STRING_SIZE 128
60 /* for bug 10866, global variable */
61 CFS_DECLARE_RWSEM(_lprocfs_lock);
62 EXPORT_SYMBOL(_lprocfs_lock);
64 int lprocfs_seq_release(struct inode *inode, struct file *file)
67 return seq_release(inode, file);
69 EXPORT_SYMBOL(lprocfs_seq_release);
71 struct proc_dir_entry *lprocfs_srch(struct proc_dir_entry *head,
74 struct proc_dir_entry *temp;
81 while (temp != NULL) {
82 if (strcmp(temp->name, name) == 0) {
93 /* lprocfs API calls */
95 /* Function that emulates snprintf but also has the side effect of advancing
96 the page pointer for the next write into the buffer, incrementing the total
97 length written to the buffer, and decrementing the size left in the
99 static int lprocfs_obd_snprintf(char **page, int end, int *len,
100 const char *format, ...)
108 va_start(list, format);
109 n = vsnprintf(*page, end - *len, format, list);
112 *page += n; *len += n;
116 cfs_proc_dir_entry_t *lprocfs_add_simple(struct proc_dir_entry *root,
118 read_proc_t *read_proc,
119 write_proc_t *write_proc,
121 struct file_operations *fops)
123 cfs_proc_dir_entry_t *proc;
126 if (root == NULL || name == NULL)
127 return ERR_PTR(-EINVAL);
134 proc = create_proc_entry(name, mode, root);
136 CERROR("LprocFS: No memory to create /proc entry %s", name);
137 return ERR_PTR(-ENOMEM);
139 proc->read_proc = read_proc;
140 proc->write_proc = write_proc;
143 proc->proc_fops = fops;
147 struct proc_dir_entry *lprocfs_add_symlink(const char *name,
148 struct proc_dir_entry *parent, const char *format, ...)
150 struct proc_dir_entry *entry;
154 if (parent == NULL || format == NULL)
157 OBD_ALLOC_WAIT(dest, MAX_STRING_SIZE + 1);
161 va_start(ap, format);
162 vsnprintf(dest, MAX_STRING_SIZE, format, ap);
165 entry = proc_symlink(name, parent, dest);
167 CERROR("LprocFS: Could not create symbolic link from %s to %s",
170 OBD_FREE(dest, MAX_STRING_SIZE + 1);
174 static ssize_t lprocfs_fops_read(struct file *f, char __user *buf,
175 size_t size, loff_t *ppos)
177 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
178 char *page, *start = NULL;
179 int rc = 0, eof = 1, count;
181 if (*ppos >= CFS_PAGE_SIZE)
184 page = (char *)__get_free_page(GFP_KERNEL);
188 if (LPROCFS_ENTRY_AND_CHECK(dp))
191 OBD_FAIL_TIMEOUT(OBD_FAIL_LPROC_REMOVE, 10);
193 rc = dp->read_proc(page, &start, *ppos, CFS_PAGE_SIZE,
199 /* for lustre proc read, the read count must be less than PAGE_SIZE */
208 start = page + *ppos;
209 } else if (start < page) {
213 count = (rc < size) ? rc : size;
214 if (cfs_copy_to_user(buf, start, count)) {
221 free_page((unsigned long)page);
225 static ssize_t lprocfs_fops_write(struct file *f, const char __user *buf,
226 size_t size, loff_t *ppos)
228 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
231 if (LPROCFS_ENTRY_AND_CHECK(dp))
234 rc = dp->write_proc(f, buf, size, dp->data);
239 static struct file_operations lprocfs_generic_fops = {
240 .owner = THIS_MODULE,
241 .read = lprocfs_fops_read,
242 .write = lprocfs_fops_write,
245 int lprocfs_evict_client_open(struct inode *inode, struct file *f)
247 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
248 struct obd_device *obd = dp->data;
250 cfs_atomic_inc(&obd->obd_evict_inprogress);
255 int lprocfs_evict_client_release(struct inode *inode, struct file *f)
257 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
258 struct obd_device *obd = dp->data;
260 cfs_atomic_dec(&obd->obd_evict_inprogress);
261 cfs_waitq_signal(&obd->obd_evict_inprogress_waitq);
266 struct file_operations lprocfs_evict_client_fops = {
267 .owner = THIS_MODULE,
268 .read = lprocfs_fops_read,
269 .write = lprocfs_fops_write,
270 .open = lprocfs_evict_client_open,
271 .release = lprocfs_evict_client_release,
273 EXPORT_SYMBOL(lprocfs_evict_client_fops);
278 * \param root [in] The parent proc entry on which new entry will be added.
279 * \param list [in] Array of proc entries to be added.
280 * \param data [in] The argument to be passed when entries read/write routines
281 * are called through /proc file.
283 * \retval 0 on success
286 int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list,
289 if (root == NULL || list == NULL)
292 while (list->name != NULL) {
293 struct proc_dir_entry *cur_root, *proc;
294 char *pathcopy, *cur, *next, pathbuf[64];
295 int pathsize = strlen(list->name) + 1;
300 /* need copy of path for strsep */
301 if (strlen(list->name) > sizeof(pathbuf) - 1) {
302 OBD_ALLOC(pathcopy, pathsize);
303 if (pathcopy == NULL)
310 strcpy(pathcopy, list->name);
312 while (cur_root != NULL && (cur = strsep(&next, "/"))) {
313 if (*cur =='\0') /* skip double/trailing "/" */
316 proc = lprocfs_srch(cur_root, cur);
317 CDEBUG(D_OTHER, "cur_root=%s, cur=%s, next=%s, (%s)\n",
318 cur_root->name, cur, next,
319 (proc ? "exists" : "new"));
321 cur_root = (proc ? proc :
322 proc_mkdir(cur, cur_root));
323 } else if (proc == NULL) {
325 if (list->proc_mode != 0000) {
326 mode = list->proc_mode;
330 if (list->write_fptr)
333 proc = create_proc_entry(cur, mode, cur_root);
337 if (pathcopy != pathbuf)
338 OBD_FREE(pathcopy, pathsize);
340 if (cur_root == NULL || proc == NULL) {
341 CERROR("LprocFS: No memory to create /proc entry %s",
347 proc->proc_fops = list->fops;
349 proc->proc_fops = &lprocfs_generic_fops;
350 proc->read_proc = list->read_fptr;
351 proc->write_proc = list->write_fptr;
352 proc->data = (list->data ? list->data : data);
358 void lprocfs_remove(struct proc_dir_entry **rooth)
360 struct proc_dir_entry *root = *rooth;
361 struct proc_dir_entry *temp = root;
362 struct proc_dir_entry *rm_entry;
363 struct proc_dir_entry *parent;
369 parent = root->parent;
370 LASSERT(parent != NULL);
371 LPROCFS_WRITE_ENTRY(); /* search vs remove race */
374 while (temp->subdir != NULL)
380 /* Memory corruption once caused this to fail, and
381 without this LASSERT we would loop here forever. */
382 LASSERTF(strlen(rm_entry->name) == rm_entry->namelen,
383 "0x%p %s/%s len %d\n", rm_entry, temp->name,
384 rm_entry->name, (int)strlen(rm_entry->name));
386 /* Now, the rm_entry->deleted flags is protected
387 * by _lprocfs_lock. */
388 rm_entry->data = NULL;
389 remove_proc_entry(rm_entry->name, temp);
393 LPROCFS_WRITE_EXIT();
396 void lprocfs_remove_proc_entry(const char *name, struct proc_dir_entry *parent)
398 LASSERT(parent != NULL);
399 remove_proc_entry(name, parent);
402 struct proc_dir_entry *lprocfs_register(const char *name,
403 struct proc_dir_entry *parent,
404 struct lprocfs_vars *list, void *data)
406 struct proc_dir_entry *newchild;
408 newchild = lprocfs_srch(parent, name);
409 if (newchild != NULL) {
410 CERROR(" Lproc: Attempting to register %s more than once \n",
412 return ERR_PTR(-EALREADY);
415 newchild = proc_mkdir(name, parent);
416 if (newchild != NULL && list != NULL) {
417 int rc = lprocfs_add_vars(newchild, list, data);
419 lprocfs_remove(&newchild);
426 /* Generic callbacks */
427 int lprocfs_rd_uint(char *page, char **start, off_t off,
428 int count, int *eof, void *data)
430 unsigned int *temp = data;
431 return snprintf(page, count, "%u\n", *temp);
434 int lprocfs_wr_uint(struct file *file, const char *buffer,
435 unsigned long count, void *data)
438 char dummy[MAX_STRING_SIZE + 1], *end;
441 dummy[MAX_STRING_SIZE] = '\0';
442 if (cfs_copy_from_user(dummy, buffer, MAX_STRING_SIZE))
445 tmp = simple_strtoul(dummy, &end, 0);
449 *p = (unsigned int)tmp;
453 int lprocfs_rd_u64(char *page, char **start, off_t off,
454 int count, int *eof, void *data)
456 LASSERT(data != NULL);
458 return snprintf(page, count, LPU64"\n", *(__u64 *)data);
461 int lprocfs_rd_atomic(char *page, char **start, off_t off,
462 int count, int *eof, void *data)
464 cfs_atomic_t *atom = data;
465 LASSERT(atom != NULL);
467 return snprintf(page, count, "%d\n", cfs_atomic_read(atom));
470 int lprocfs_wr_atomic(struct file *file, const char *buffer,
471 unsigned long count, void *data)
473 cfs_atomic_t *atm = data;
477 rc = lprocfs_write_helper(buffer, count, &val);
484 cfs_atomic_set(atm, val);
488 int lprocfs_rd_uuid(char *page, char **start, off_t off, int count,
489 int *eof, void *data)
491 struct obd_device *obd = data;
493 LASSERT(obd != NULL);
495 return snprintf(page, count, "%s\n", obd->obd_uuid.uuid);
498 int lprocfs_rd_name(char *page, char **start, off_t off, int count,
499 int *eof, void *data)
501 struct obd_device *dev = data;
503 LASSERT(dev != NULL);
504 LASSERT(dev->obd_name != NULL);
506 return snprintf(page, count, "%s\n", dev->obd_name);
509 int lprocfs_rd_fstype(char *page, char **start, off_t off, int count, int *eof,
512 struct obd_device *obd = data;
514 LASSERT(obd != NULL);
515 LASSERT(obd->obd_fsops != NULL);
516 LASSERT(obd->obd_fsops->fs_type != NULL);
517 return snprintf(page, count, "%s\n", obd->obd_fsops->fs_type);
520 int lprocfs_rd_blksize(char *page, char **start, off_t off, int count,
521 int *eof, void *data)
523 struct obd_statfs osfs;
524 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - CFS_HZ,
528 rc = snprintf(page, count, "%u\n", osfs.os_bsize);
533 int lprocfs_rd_kbytestotal(char *page, char **start, off_t off, int count,
534 int *eof, void *data)
536 struct obd_statfs osfs;
537 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - CFS_HZ,
540 __u32 blk_size = osfs.os_bsize >> 10;
541 __u64 result = osfs.os_blocks;
543 while (blk_size >>= 1)
547 rc = snprintf(page, count, LPU64"\n", result);
552 int lprocfs_rd_kbytesfree(char *page, char **start, off_t off, int count,
553 int *eof, void *data)
555 struct obd_statfs osfs;
556 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - CFS_HZ,
559 __u32 blk_size = osfs.os_bsize >> 10;
560 __u64 result = osfs.os_bfree;
562 while (blk_size >>= 1)
566 rc = snprintf(page, count, LPU64"\n", result);
571 int lprocfs_rd_kbytesavail(char *page, char **start, off_t off, int count,
572 int *eof, void *data)
574 struct obd_statfs osfs;
575 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - CFS_HZ,
578 __u32 blk_size = osfs.os_bsize >> 10;
579 __u64 result = osfs.os_bavail;
581 while (blk_size >>= 1)
585 rc = snprintf(page, count, LPU64"\n", result);
590 int lprocfs_rd_filestotal(char *page, char **start, off_t off, int count,
591 int *eof, void *data)
593 struct obd_statfs osfs;
594 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - CFS_HZ,
598 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
604 int lprocfs_rd_filesfree(char *page, char **start, off_t off, int count,
605 int *eof, void *data)
607 struct obd_statfs osfs;
608 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - CFS_HZ,
612 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
617 int lprocfs_rd_server_uuid(char *page, char **start, off_t off, int count,
618 int *eof, void *data)
620 struct obd_device *obd = data;
621 struct obd_import *imp;
622 char *imp_state_name = NULL;
625 LASSERT(obd != NULL);
626 LPROCFS_CLIMP_CHECK(obd);
627 imp = obd->u.cli.cl_import;
628 imp_state_name = ptlrpc_import_state_name(imp->imp_state);
630 rc = snprintf(page, count, "%s\t%s%s\n",
631 obd2cli_tgt(obd), imp_state_name,
632 imp->imp_deactive ? "\tDEACTIVATED" : "");
634 LPROCFS_CLIMP_EXIT(obd);
638 int lprocfs_rd_conn_uuid(char *page, char **start, off_t off, int count,
639 int *eof, void *data)
641 struct obd_device *obd = data;
642 struct ptlrpc_connection *conn;
645 LASSERT(obd != NULL);
647 LPROCFS_CLIMP_CHECK(obd);
648 conn = obd->u.cli.cl_import->imp_connection;
650 if (conn && obd->u.cli.cl_import) {
651 rc = snprintf(page, count, "%s\n",
652 conn->c_remote_uuid.uuid);
654 rc = snprintf(page, count, "%s\n", "<none>");
657 LPROCFS_CLIMP_EXIT(obd);
661 /** add up per-cpu counters */
662 void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
663 struct lprocfs_counter *cnt)
665 unsigned int num_cpu;
666 struct lprocfs_counter t;
667 struct lprocfs_counter *percpu_cntr;
670 memset(cnt, 0, sizeof(*cnt));
673 /* set count to 1 to avoid divide-by-zero errs in callers */
678 cnt->lc_min = LC_MIN_INIT;
680 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
683 num_cpu = cfs_num_possible_cpus();
685 for (i = 0; i < num_cpu; i++) {
686 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[idx];
689 centry = cfs_atomic_read(&percpu_cntr-> \
691 t.lc_count = percpu_cntr->lc_count;
692 t.lc_sum = percpu_cntr->lc_sum;
693 t.lc_min = percpu_cntr->lc_min;
694 t.lc_max = percpu_cntr->lc_max;
695 t.lc_sumsquare = percpu_cntr->lc_sumsquare;
696 } while (centry != cfs_atomic_read(&percpu_cntr->lc_cntl. \
698 centry != cfs_atomic_read(&percpu_cntr->lc_cntl. \
700 cnt->lc_count += t.lc_count;
701 cnt->lc_sum += t.lc_sum;
702 if (t.lc_min < cnt->lc_min)
703 cnt->lc_min = t.lc_min;
704 if (t.lc_max > cnt->lc_max)
705 cnt->lc_max = t.lc_max;
706 cnt->lc_sumsquare += t.lc_sumsquare;
709 cnt->lc_units = stats->ls_percpu[0]->lp_cntr[idx].lc_units;
713 * Append a space separated list of current set flags to str.
715 #define flag2str(flag) \
716 if (imp->imp_##flag && max - len > 0) \
717 len += snprintf(str + len, max - len, "%s" #flag, len ? ", " : "");
718 static int obd_import_flags2str(struct obd_import *imp, char *str, int max)
722 if (imp->imp_obd->obd_no_recov)
723 len += snprintf(str, max - len, "no_recov");
727 flag2str(replayable);
733 static const char *obd_connect_names[] = {
747 "join_file(obsolete)",
751 "remote_client_by_force",
760 "mds_mds_connection",
763 "alt_checksum_algorithm",
773 static int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
778 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
780 ret += snprintf(page + ret, count - ret, "%s%s",
781 ret ? sep : "", obd_connect_names[i]);
783 if (flags & ~(mask - 1))
784 ret += snprintf(page + ret, count - ret,
785 "%sunknown flags "LPX64,
786 ret ? sep : "", flags & ~(mask - 1));
790 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
791 int *eof, void *data)
793 struct lprocfs_counter ret;
794 struct obd_device *obd = (struct obd_device *)data;
795 struct obd_import *imp;
798 LASSERT(obd != NULL);
799 LPROCFS_CLIMP_CHECK(obd);
800 imp = obd->u.cli.cl_import;
803 i = snprintf(page, count,
807 " current_connection: %s\n"
812 imp->imp_connection->c_remote_uuid.uuid,
813 ptlrpc_import_state_name(imp->imp_state));
814 i += obd_connect_flags2str(page + i, count - i,
815 imp->imp_connect_data.ocd_connect_flags,
817 i += snprintf(page + i, count - i,
820 i += obd_import_flags2str(imp, page + i, count - i);
822 i += snprintf(page + i, count - i,
825 " connection_attempts: %u\n"
827 " in-progress_invalidations: %u\n",
830 cfs_atomic_read(&imp->imp_inval_count));
832 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
833 if (ret.lc_count != 0)
834 do_div(ret.lc_sum, ret.lc_count);
837 i += snprintf(page + i, count - i,
840 " unregistering: %u\n"
842 " avg_waittime: "LPU64" %s\n",
843 cfs_atomic_read(&imp->imp_inflight),
844 cfs_atomic_read(&imp->imp_unregistering),
845 cfs_atomic_read(&imp->imp_timeouts),
846 ret.lc_sum, ret.lc_units);
849 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
850 if (imp->imp_at.iat_portal[j] == 0)
852 k = max_t(unsigned int, k,
853 at_get(&imp->imp_at.iat_service_estimate[j]));
855 i += snprintf(page + i, count - i,
856 " service_estimates:\n"
857 " services: %u sec\n"
858 " network: %u sec\n",
860 at_get(&imp->imp_at.iat_net_latency));
862 i += snprintf(page + i, count - i,
864 " last_replay: "LPU64"\n"
865 " peer_committed: "LPU64"\n"
866 " last_checked: "LPU64"\n",
867 imp->imp_last_replay_transno,
868 imp->imp_peer_committed_transno,
869 imp->imp_last_transno_checked);
872 for (rw = 0; rw <= 1; rw++) {
873 lprocfs_stats_collect(obd->obd_svc_stats,
874 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
876 if (ret.lc_sum > 0 && ret.lc_count > 0) {
877 do_div(ret.lc_sum, ret.lc_count);
878 i += snprintf(page + i, count - i,
879 " %s_data_averages:\n"
880 " bytes_per_rpc: "LPU64"\n",
881 rw ? "write" : "read",
885 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
886 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
887 if (ret.lc_sum > 0 && ret.lc_count != 0) {
888 do_div(ret.lc_sum, ret.lc_count);
889 i += snprintf(page + i, count - i,
890 " %s_per_rpc: "LPU64"\n",
891 ret.lc_units, ret.lc_sum);
894 i += snprintf(page + i, count - i,
895 " MB_per_sec: %u.%.02u\n",
896 k / j, (100 * k / j) % 100);
900 LPROCFS_CLIMP_EXIT(obd);
904 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
905 int *eof, void *data)
907 struct obd_device *obd = (struct obd_device *)data;
908 struct obd_import *imp;
911 LASSERT(obd != NULL);
912 LPROCFS_CLIMP_CHECK(obd);
913 imp = obd->u.cli.cl_import;
916 i = snprintf(page, count, "current_state: %s\n",
917 ptlrpc_import_state_name(imp->imp_state));
918 i += snprintf(page + i, count - i,
920 k = imp->imp_state_hist_idx;
921 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
922 struct import_state_hist *ish =
923 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
924 if (ish->ish_state == 0)
926 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
928 ptlrpc_import_state_name(ish->ish_state));
931 LPROCFS_CLIMP_EXIT(obd);
935 int lprocfs_at_hist_helper(char *page, int count, int rc,
936 struct adaptive_timeout *at)
939 for (i = 0; i < AT_BINS; i++)
940 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
941 rc += snprintf(page + rc, count - rc, "\n");
945 /* See also ptlrpc_lprocfs_rd_timeouts */
946 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
947 int *eof, void *data)
949 struct obd_device *obd = (struct obd_device *)data;
950 struct obd_import *imp;
951 unsigned int cur, worst;
956 LASSERT(obd != NULL);
957 LPROCFS_CLIMP_CHECK(obd);
958 imp = obd->u.cli.cl_import;
961 now = cfs_time_current_sec();
963 /* Some network health info for kicks */
964 s2dhms(&ts, now - imp->imp_last_reply_time);
965 rc += snprintf(page + rc, count - rc,
966 "%-10s : %ld, "DHMS_FMT" ago\n",
967 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
969 cur = at_get(&imp->imp_at.iat_net_latency);
970 worst = imp->imp_at.iat_net_latency.at_worst_ever;
971 worstt = imp->imp_at.iat_net_latency.at_worst_time;
972 s2dhms(&ts, now - worstt);
973 rc += snprintf(page + rc, count - rc,
974 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
975 "network", cur, worst, worstt, DHMS_VARS(&ts));
976 rc = lprocfs_at_hist_helper(page, count, rc,
977 &imp->imp_at.iat_net_latency);
979 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
980 if (imp->imp_at.iat_portal[i] == 0)
982 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
983 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
984 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
985 s2dhms(&ts, now - worstt);
986 rc += snprintf(page + rc, count - rc,
987 "portal %-2d : cur %3u worst %3u (at %ld, "
988 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
989 cur, worst, worstt, DHMS_VARS(&ts));
990 rc = lprocfs_at_hist_helper(page, count, rc,
991 &imp->imp_at.iat_service_estimate[i]);
994 LPROCFS_CLIMP_EXIT(obd);
998 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
999 int count, int *eof, void *data)
1001 struct obd_device *obd = data;
1005 LPROCFS_CLIMP_CHECK(obd);
1006 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1007 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1008 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1009 ret += snprintf(page + ret, count - ret, "\n");
1010 LPROCFS_CLIMP_EXIT(obd);
1013 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1015 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1016 int *eof, void *data)
1018 struct obd_device *obd = data;
1020 LASSERT(obd != NULL);
1022 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1025 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1026 int *eof, void *data)
1028 struct obd_type *class = (struct obd_type*) data;
1030 LASSERT(class != NULL);
1032 return snprintf(page, count, "%d\n", class->typ_refcnt);
1035 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1039 LASSERT(obd != NULL);
1040 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1041 LASSERT(obd->obd_type->typ_procroot != NULL);
1043 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1044 obd->obd_type->typ_procroot,
1046 if (IS_ERR(obd->obd_proc_entry)) {
1047 rc = PTR_ERR(obd->obd_proc_entry);
1048 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1049 obd->obd_proc_entry = NULL;
1054 int lprocfs_obd_cleanup(struct obd_device *obd)
1058 if (obd->obd_proc_exports_entry) {
1059 /* Should be no exports left */
1060 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1061 lprocfs_remove(&obd->obd_proc_exports_entry);
1062 obd->obd_proc_exports_entry = NULL;
1064 if (obd->obd_proc_entry) {
1065 lprocfs_remove(&obd->obd_proc_entry);
1066 obd->obd_proc_entry = NULL;
1071 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1073 CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
1074 client_stat->nid_proc, client_stat->nid_stats,
1075 client_stat->nid_brw_stats);
1077 LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
1079 cfs_atomic_read(&client_stat->nid_exp_ref_count));
1081 cfs_hlist_del_init(&client_stat->nid_hash);
1083 if (client_stat->nid_proc)
1084 lprocfs_remove(&client_stat->nid_proc);
1086 if (client_stat->nid_stats)
1087 lprocfs_free_stats(&client_stat->nid_stats);
1089 if (client_stat->nid_brw_stats)
1090 OBD_FREE_PTR(client_stat->nid_brw_stats);
1092 if (client_stat->nid_ldlm_stats)
1093 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1095 OBD_FREE_PTR(client_stat);
1100 void lprocfs_free_per_client_stats(struct obd_device *obd)
1102 struct nid_stat *stat;
1105 /* we need extra list - because hash_exit called to early */
1106 /* not need locking because all clients is died */
1107 while(!cfs_list_empty(&obd->obd_nid_stats)) {
1108 stat = cfs_list_entry(obd->obd_nid_stats.next,
1109 struct nid_stat, nid_list);
1110 cfs_list_del_init(&stat->nid_list);
1111 lprocfs_free_client_stats(stat);
1117 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1118 enum lprocfs_stats_flags flags)
1120 struct lprocfs_stats *stats;
1121 unsigned int percpusize;
1123 unsigned int num_cpu;
1128 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1131 num_cpu = cfs_num_possible_cpus();
1133 OBD_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
1137 if (flags & LPROCFS_STATS_FLAG_NOPERCPU) {
1138 stats->ls_flags = flags;
1139 cfs_spin_lock_init(&stats->ls_lock);
1140 /* Use this lock only if there are no percpu areas */
1142 stats->ls_flags = 0;
1145 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
1147 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1149 for (i = 0; i < num_cpu; i++) {
1150 OBD_ALLOC(stats->ls_percpu[i], percpusize);
1151 if (stats->ls_percpu[i] == NULL) {
1152 for (j = 0; j < i; j++) {
1153 OBD_FREE(stats->ls_percpu[j], percpusize);
1154 stats->ls_percpu[j] = NULL;
1159 if (stats->ls_percpu[0] == NULL) {
1160 OBD_FREE(stats, offsetof(typeof(*stats),
1161 ls_percpu[num_cpu]));
1165 stats->ls_num = num;
1169 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1171 struct lprocfs_stats *stats = *statsh;
1172 unsigned int num_cpu;
1173 unsigned int percpusize;
1176 if (stats == NULL || stats->ls_num == 0)
1180 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1183 num_cpu = cfs_num_possible_cpus();
1185 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
1187 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1188 for (i = 0; i < num_cpu; i++)
1189 OBD_FREE(stats->ls_percpu[i], percpusize);
1190 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
1193 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1195 struct lprocfs_counter *percpu_cntr;
1197 unsigned int num_cpu;
1199 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1201 for (i = 0; i < num_cpu; i++) {
1202 for (j = 0; j < stats->ls_num; j++) {
1203 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
1204 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_entry);
1205 percpu_cntr->lc_count = 0;
1206 percpu_cntr->lc_sum = 0;
1207 percpu_cntr->lc_min = LC_MIN_INIT;
1208 percpu_cntr->lc_max = 0;
1209 percpu_cntr->lc_sumsquare = 0;
1210 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_exit);
1214 lprocfs_stats_unlock(stats);
1217 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1218 size_t len, loff_t *off)
1220 struct seq_file *seq = file->private_data;
1221 struct lprocfs_stats *stats = seq->private;
1223 lprocfs_clear_stats(stats);
1228 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1230 struct lprocfs_stats *stats = p->private;
1231 /* return 1st cpu location */
1232 return (*pos >= stats->ls_num) ? NULL :
1233 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1236 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1240 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1242 struct lprocfs_stats *stats = p->private;
1244 return (*pos >= stats->ls_num) ? NULL :
1245 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1248 /* seq file export of one lprocfs counter */
1249 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1251 struct lprocfs_stats *stats = p->private;
1252 struct lprocfs_counter *cntr = v;
1253 struct lprocfs_counter ret;
1256 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
1258 cfs_gettimeofday(&now);
1259 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1260 "snapshot_time", now.tv_sec, now.tv_usec);
1264 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
1266 lprocfs_stats_collect(stats, idx, &ret);
1268 if (ret.lc_count == 0)
1271 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", cntr->lc_name,
1272 ret.lc_count, cntr->lc_units);
1277 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
1278 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1279 ret.lc_min, ret.lc_max, ret.lc_sum);
1282 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
1283 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1287 rc = seq_printf(p, "\n");
1289 return (rc < 0) ? rc : 0;
1292 struct seq_operations lprocfs_stats_seq_sops = {
1293 start: lprocfs_stats_seq_start,
1294 stop: lprocfs_stats_seq_stop,
1295 next: lprocfs_stats_seq_next,
1296 show: lprocfs_stats_seq_show,
1299 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1301 struct proc_dir_entry *dp = PDE(inode);
1302 struct seq_file *seq;
1305 if (LPROCFS_ENTRY_AND_CHECK(dp))
1308 rc = seq_open(file, &lprocfs_stats_seq_sops);
1313 seq = file->private_data;
1314 seq->private = dp->data;
1318 struct file_operations lprocfs_stats_seq_fops = {
1319 .owner = THIS_MODULE,
1320 .open = lprocfs_stats_seq_open,
1322 .write = lprocfs_stats_seq_write,
1323 .llseek = seq_lseek,
1324 .release = lprocfs_seq_release,
1327 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1328 struct lprocfs_stats *stats)
1330 struct proc_dir_entry *entry;
1331 LASSERT(root != NULL);
1333 entry = create_proc_entry(name, 0644, root);
1336 entry->proc_fops = &lprocfs_stats_seq_fops;
1337 entry->data = stats;
1341 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1342 unsigned conf, const char *name, const char *units)
1344 struct lprocfs_counter *c;
1346 unsigned int num_cpu;
1348 LASSERT(stats != NULL);
1350 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1352 for (i = 0; i < num_cpu; i++) {
1353 c = &(stats->ls_percpu[i]->lp_cntr[index]);
1354 c->lc_config = conf;
1357 c->lc_min = LC_MIN_INIT;
1360 c->lc_units = units;
1363 lprocfs_stats_unlock(stats);
1365 EXPORT_SYMBOL(lprocfs_counter_init);
1367 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1369 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1370 LASSERT(coffset < stats->ls_num); \
1371 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1374 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1376 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1377 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1378 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1379 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1380 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1381 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1382 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1383 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1384 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1385 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1386 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1387 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1388 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1389 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1390 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1391 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1392 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1393 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1394 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
1395 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1396 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1397 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1398 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1399 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1400 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1401 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1402 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1403 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1404 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1405 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1406 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1407 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1408 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1409 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1410 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1411 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1412 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1413 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1414 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1415 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1416 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1417 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1418 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1419 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1420 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
1421 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1422 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1423 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1424 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1425 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1426 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1427 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1428 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1429 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1430 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1431 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1432 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1433 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1434 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1435 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1436 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1437 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quota_adjust_qunit);
1438 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1439 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1440 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1441 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1442 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1443 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1444 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1447 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1449 struct lprocfs_stats *stats;
1450 unsigned int num_stats;
1453 LASSERT(obd->obd_stats == NULL);
1454 LASSERT(obd->obd_proc_entry != NULL);
1455 LASSERT(obd->obd_cntr_base == 0);
1457 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1458 num_private_stats - 1 /* o_owner */;
1459 stats = lprocfs_alloc_stats(num_stats, 0);
1463 lprocfs_init_ops_stats(num_private_stats, stats);
1465 for (i = num_private_stats; i < num_stats; i++) {
1466 /* If this LBUGs, it is likely that an obd
1467 * operation was added to struct obd_ops in
1468 * <obd.h>, and that the corresponding line item
1469 * LPROCFS_OBD_OP_INIT(.., .., opname)
1470 * is missing from the list above. */
1471 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1472 "Missing obd_stat initializer obd_op "
1473 "operation at offset %d.\n", i - num_private_stats);
1475 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1477 lprocfs_free_stats(&stats);
1479 obd->obd_stats = stats;
1480 obd->obd_cntr_base = num_private_stats;
1485 void lprocfs_free_obd_stats(struct obd_device *obd)
1488 lprocfs_free_stats(&obd->obd_stats);
1491 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1493 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1494 LASSERT(coffset < stats->ls_num); \
1495 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1498 int lprocfs_alloc_md_stats(struct obd_device *obd,
1499 unsigned num_private_stats)
1501 struct lprocfs_stats *stats;
1502 unsigned int num_stats;
1505 LASSERT(obd->md_stats == NULL);
1506 LASSERT(obd->obd_proc_entry != NULL);
1507 LASSERT(obd->md_cntr_base == 0);
1509 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1511 stats = lprocfs_alloc_stats(num_stats, 0);
1515 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1516 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1517 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
1518 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1519 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1520 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1521 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1522 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1523 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1524 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1525 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1526 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1527 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1528 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1529 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1530 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1531 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1532 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1533 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1534 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1535 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1536 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1537 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1538 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1539 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1540 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1541 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1542 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1543 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1544 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1545 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1546 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1548 for (i = num_private_stats; i < num_stats; i++) {
1549 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1550 CERROR("Missing md_stat initializer md_op "
1551 "operation at offset %d. Aborting.\n",
1552 i - num_private_stats);
1556 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1558 lprocfs_free_stats(&stats);
1560 obd->md_stats = stats;
1561 obd->md_cntr_base = num_private_stats;
1566 void lprocfs_free_md_stats(struct obd_device *obd)
1568 struct lprocfs_stats *stats = obd->md_stats;
1570 if (stats != NULL) {
1571 obd->md_stats = NULL;
1572 obd->md_cntr_base = 0;
1573 lprocfs_free_stats(&stats);
1577 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1579 lprocfs_counter_init(ldlm_stats,
1580 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1581 0, "ldlm_enqueue", "reqs");
1582 lprocfs_counter_init(ldlm_stats,
1583 LDLM_CONVERT - LDLM_FIRST_OPC,
1584 0, "ldlm_convert", "reqs");
1585 lprocfs_counter_init(ldlm_stats,
1586 LDLM_CANCEL - LDLM_FIRST_OPC,
1587 0, "ldlm_cancel", "reqs");
1588 lprocfs_counter_init(ldlm_stats,
1589 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1590 0, "ldlm_bl_callback", "reqs");
1591 lprocfs_counter_init(ldlm_stats,
1592 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1593 0, "ldlm_cp_callback", "reqs");
1594 lprocfs_counter_init(ldlm_stats,
1595 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1596 0, "ldlm_gl_callback", "reqs");
1599 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1600 int *eof, void *data)
1602 struct obd_export *exp = data;
1603 LASSERT(exp != NULL);
1605 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1608 struct exp_uuid_cb_data {
1616 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1617 int count, int *eof, int *len)
1619 cb_data->page = page;
1620 cb_data->count = count;
1625 void lprocfs_exp_print_uuid(void *obj, void *cb_data)
1627 struct obd_export *exp = (struct obd_export *)obj;
1628 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1630 if (exp->exp_nid_stats)
1631 *data->len += snprintf((data->page + *data->len),
1632 data->count, "%s\n",
1633 obd_uuid2str(&exp->exp_client_uuid));
1636 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1637 int *eof, void *data)
1639 struct nid_stat *stats = (struct nid_stat *)data;
1640 struct exp_uuid_cb_data cb_data;
1641 struct obd_device *obd = stats->nid_obd;
1646 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1647 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1648 lprocfs_exp_print_uuid, &cb_data);
1649 return (*cb_data.len);
1652 void lprocfs_exp_print_hash(void *obj, void *cb_data)
1654 struct exp_uuid_cb_data *data = cb_data;
1655 struct obd_export *exp = obj;
1658 hs = exp->exp_lock_hash;
1661 *data->len += cfs_hash_debug_header(data->page,
1664 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1669 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1670 int *eof, void *data)
1672 struct nid_stat *stats = (struct nid_stat *)data;
1673 struct exp_uuid_cb_data cb_data;
1674 struct obd_device *obd = stats->nid_obd;
1679 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1681 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1682 lprocfs_exp_print_hash, &cb_data);
1683 return (*cb_data.len);
1686 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1687 int count, int *eof, void *data)
1690 return snprintf(page, count, "%s\n",
1691 "Write into this file to clear all nid stats and "
1692 "stale nid entries");
1694 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1696 int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1698 struct nid_stat *stat = obj;
1701 /* object has only hash + iterate_all references.
1702 * add/delete blocked by hash bucket lock */
1703 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
1704 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 2) {
1705 cfs_spin_lock(&stat->nid_obd->obd_nid_lock);
1706 cfs_list_move(&stat->nid_list, data);
1707 cfs_spin_unlock(&stat->nid_obd->obd_nid_lock);
1710 /* we has reference to object - only clear data*/
1711 if (stat->nid_stats)
1712 lprocfs_clear_stats(stat->nid_stats);
1714 if (stat->nid_brw_stats) {
1715 for (i = 0; i < BRW_LAST; i++)
1716 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
1721 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1722 unsigned long count, void *data)
1724 struct obd_device *obd = (struct obd_device *)data;
1725 struct nid_stat *client_stat;
1726 CFS_LIST_HEAD(free_list);
1728 cfs_hash_cond_del(obd->obd_nid_stats_hash,
1729 lprocfs_nid_stats_clear_write_cb, &free_list);
1731 while (!cfs_list_empty(&free_list)) {
1732 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
1734 cfs_list_del_init(&client_stat->nid_list);
1735 lprocfs_free_client_stats(client_stat);
1740 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1742 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1744 struct nid_stat *new_stat, *old_stat;
1745 struct obd_device *obd = NULL;
1746 cfs_proc_dir_entry_t *entry;
1747 char *buffer = NULL;
1753 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1754 !exp->exp_obd->obd_nid_stats_hash)
1757 /* not test against zero because eric say:
1758 * You may only test nid against another nid, or LNET_NID_ANY.
1759 * Anything else is nonsense.*/
1760 if (!nid || *nid == LNET_NID_ANY)
1765 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
1767 OBD_ALLOC_PTR(new_stat);
1768 if (new_stat == NULL)
1771 new_stat->nid = *nid;
1772 new_stat->nid_obd = exp->exp_obd;
1773 cfs_atomic_set(&new_stat->nid_exp_ref_count, 0);
1775 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
1776 nid, &new_stat->nid_hash);
1777 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
1778 old_stat, libcfs_nid2str(*nid),
1779 cfs_atomic_read(&new_stat->nid_exp_ref_count));
1781 /* Return -EALREADY here so that we know that the /proc
1782 * entry already has been created */
1783 if (old_stat != new_stat) {
1784 cfs_spin_lock(&obd->obd_nid_lock);
1785 if (exp->exp_nid_stats != old_stat) {
1786 if (exp->exp_nid_stats)
1787 nidstat_putref(exp->exp_nid_stats);
1788 exp->exp_nid_stats = old_stat;
1790 /* cfs_hash_findadd_unique() has added
1791 * old_stat's refcount */
1792 nidstat_putref(old_stat);
1795 cfs_spin_unlock(&obd->obd_nid_lock);
1797 GOTO(destroy_new, rc = -EALREADY);
1799 /* not found - create */
1800 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
1802 GOTO(destroy_new, rc = -ENOMEM);
1804 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
1805 new_stat->nid_proc = lprocfs_register(buffer,
1806 obd->obd_proc_exports_entry,
1808 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
1810 if (new_stat->nid_proc == NULL) {
1811 CERROR("Error making export directory for nid %s\n",
1812 libcfs_nid2str(*nid));
1813 GOTO(destroy_new_ns, rc = -ENOMEM);
1816 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
1817 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
1818 if (IS_ERR(entry)) {
1819 CWARN("Error adding the NID stats file\n");
1820 rc = PTR_ERR(entry);
1821 GOTO(destroy_new_ns, rc);
1824 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
1825 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
1826 if (IS_ERR(entry)) {
1827 CWARN("Error adding the hash file\n");
1828 rc = PTR_ERR(entry);
1829 GOTO(destroy_new_ns, rc);
1832 if (exp->exp_nid_stats)
1833 nidstat_putref(exp->exp_nid_stats);
1834 nidstat_getref(new_stat);
1835 exp->exp_nid_stats = new_stat;
1837 /* protect competitive add to list, not need locking on destroy */
1838 cfs_spin_lock(&obd->obd_nid_lock);
1839 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
1840 cfs_spin_unlock(&obd->obd_nid_lock);
1845 if (new_stat->nid_proc != NULL)
1846 lprocfs_remove(&new_stat->nid_proc);
1847 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
1850 OBD_FREE_PTR(new_stat);
1854 int lprocfs_exp_cleanup(struct obd_export *exp)
1856 struct nid_stat *stat = exp->exp_nid_stats;
1858 if(!stat || !exp->exp_obd)
1861 nidstat_putref(exp->exp_nid_stats);
1862 exp->exp_nid_stats = NULL;
1867 int lprocfs_write_helper(const char *buffer, unsigned long count,
1870 return lprocfs_write_frac_helper(buffer, count, val, 1);
1873 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
1876 char kernbuf[20], *end, *pbuf;
1878 if (count > (sizeof(kernbuf) - 1))
1881 if (cfs_copy_from_user(kernbuf, buffer, count))
1884 kernbuf[count] = '\0';
1891 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1895 if (end != NULL && *end == '.') {
1896 int temp_val, pow = 1;
1900 if (strlen(pbuf) > 5)
1901 pbuf[5] = '\0'; /*only allow 5bits fractional*/
1903 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1906 for (i = 0; i < (end - pbuf); i++)
1909 *val += temp_val / pow;
1915 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
1918 long decimal_val, frac_val;
1924 decimal_val = val / mult;
1925 prtn = snprintf(buffer, count, "%ld", decimal_val);
1926 frac_val = val % mult;
1928 if (prtn < (count - 4) && frac_val > 0) {
1930 int i, temp_mult = 1, frac_bits = 0;
1932 temp_frac = frac_val * 10;
1933 buffer[prtn++] = '.';
1934 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
1935 /* only reserved 2 bits fraction */
1936 buffer[prtn++] ='0';
1941 * Need to think these cases :
1942 * 1. #echo x.00 > /proc/xxx output result : x
1943 * 2. #echo x.0x > /proc/xxx output result : x.0x
1944 * 3. #echo x.x0 > /proc/xxx output result : x.x
1945 * 4. #echo x.xx > /proc/xxx output result : x.xx
1946 * Only reserved 2 bits fraction.
1948 for (i = 0; i < (5 - prtn); i++)
1951 frac_bits = min((int)count - prtn, 3 - frac_bits);
1952 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
1953 frac_val * temp_mult / mult);
1956 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
1958 if (buffer[prtn] == '.') {
1965 buffer[prtn++] ='\n';
1969 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
1971 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
1974 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
1975 __u64 *val, int mult)
1977 char kernbuf[22], *end, *pbuf;
1978 __u64 whole, frac = 0, units;
1979 unsigned frac_d = 1;
1981 if (count > (sizeof(kernbuf) - 1))
1984 if (cfs_copy_from_user(kernbuf, buffer, count))
1987 kernbuf[count] = '\0';
1994 whole = simple_strtoull(pbuf, &end, 10);
1998 if (end != NULL && *end == '.') {
2002 /* need to limit frac_d to a __u32 */
2003 if (strlen(pbuf) > 10)
2006 frac = simple_strtoull(pbuf, &end, 10);
2007 /* count decimal places */
2008 for (i = 0; i < (end - pbuf); i++)
2025 /* Specified units override the multiplier */
2027 mult = mult < 0 ? -units : units;
2030 do_div(frac, frac_d);
2031 *val = whole * mult + frac;
2035 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent, char *name, mode_t mode,
2036 struct file_operations *seq_fops, void *data)
2038 struct proc_dir_entry *entry;
2041 entry = create_proc_entry(name, mode, parent);
2044 entry->proc_fops = seq_fops;
2049 EXPORT_SYMBOL(lprocfs_seq_create);
2051 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
2053 struct file_operations *seq_fops,
2056 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2057 mode, seq_fops, data));
2059 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2061 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2063 if (value >= OBD_HIST_MAX)
2064 value = OBD_HIST_MAX - 1;
2066 cfs_spin_lock(&oh->oh_lock);
2067 oh->oh_buckets[value]++;
2068 cfs_spin_unlock(&oh->oh_lock);
2070 EXPORT_SYMBOL(lprocfs_oh_tally);
2072 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2076 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2079 lprocfs_oh_tally(oh, val);
2081 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2083 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2085 unsigned long ret = 0;
2088 for (i = 0; i < OBD_HIST_MAX; i++)
2089 ret += oh->oh_buckets[i];
2092 EXPORT_SYMBOL(lprocfs_oh_sum);
2094 void lprocfs_oh_clear(struct obd_histogram *oh)
2096 cfs_spin_lock(&oh->oh_lock);
2097 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2098 cfs_spin_unlock(&oh->oh_lock);
2100 EXPORT_SYMBOL(lprocfs_oh_clear);
2102 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2103 int count, int *eof, void *data)
2105 struct obd_device *obd = data;
2111 c += cfs_hash_debug_header(page, count);
2112 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2113 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2114 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2118 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2120 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2121 int count, int *eof, void *data)
2123 struct obd_device *obd = data;
2126 LASSERT(obd != NULL);
2127 LASSERT(count >= 0);
2129 /* Set start of user data returned to
2130 page + off since the user may have
2131 requested to read much smaller than
2132 what we need to read */
2133 *start = page + off;
2135 /* We know we are allocated a page here.
2136 Also we know that this function will
2137 not need to write more than a page
2138 so we can truncate at CFS_PAGE_SIZE. */
2139 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2141 /* Initialize the page */
2142 memset(page, 0, size);
2144 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2146 if (obd->obd_max_recoverable_clients == 0) {
2147 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2153 /* sampled unlocked, but really... */
2154 if (obd->obd_recovering == 0) {
2155 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2157 if (lprocfs_obd_snprintf(&page, size, &len,
2158 "recovery_start: %lu\n",
2159 obd->obd_recovery_start) <= 0)
2161 if (lprocfs_obd_snprintf(&page, size, &len,
2162 "recovery_duration: %lu\n",
2163 obd->obd_recovery_end -
2164 obd->obd_recovery_start) <= 0)
2166 /* Number of clients that have completed recovery */
2167 if (lprocfs_obd_snprintf(&page, size, &len,
2168 "completed_clients: %d/%d\n",
2169 obd->obd_max_recoverable_clients -
2170 obd->obd_stale_clients,
2171 obd->obd_max_recoverable_clients) <= 0)
2173 if (lprocfs_obd_snprintf(&page, size, &len,
2174 "replayed_requests: %d\n",
2175 obd->obd_replayed_requests) <= 0)
2177 if (lprocfs_obd_snprintf(&page, size, &len,
2178 "last_transno: "LPD64"\n",
2179 obd->obd_next_recovery_transno - 1)<=0)
2181 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2182 obd->obd_version_recov ? "ON" : "OFF")<=0)
2187 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2189 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2190 obd->obd_recovery_start) <= 0)
2192 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2193 cfs_time_current_sec() >= obd->obd_recovery_end ? 0 :
2194 obd->obd_recovery_end - cfs_time_current_sec()) <= 0)
2196 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2197 obd->obd_connected_clients,
2198 obd->obd_max_recoverable_clients) <= 0)
2200 /* Number of clients that have completed recovery */
2201 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2202 cfs_atomic_read(&obd->obd_req_replay_clients))
2205 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2206 cfs_atomic_read(&obd->obd_lock_replay_clients))
2209 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2210 obd->obd_connected_clients -
2211 cfs_atomic_read(&obd->obd_lock_replay_clients))
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_time_soft(char *page, char **start, off_t off,
2236 int count, int *eof, void *data)
2238 struct obd_device *obd = (struct obd_device *)data;
2239 LASSERT(obd != NULL);
2241 return snprintf(page, count, "%d\n",
2242 obd->obd_recovery_timeout);
2244 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
2246 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
2247 unsigned long count, void *data)
2249 struct obd_device *obd = (struct obd_device *)data;
2251 LASSERT(obd != NULL);
2253 rc = lprocfs_write_helper(buffer, count, &val);
2257 obd->obd_recovery_timeout = val;
2260 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
2262 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
2263 int count, int *eof, void *data)
2265 struct obd_device *obd = data;
2266 LASSERT(obd != NULL);
2268 return snprintf(page, count, "%lu\n", obd->obd_recovery_time_hard);
2270 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
2272 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
2273 unsigned long count, void *data)
2275 struct obd_device *obd = data;
2277 LASSERT(obd != NULL);
2279 rc = lprocfs_write_helper(buffer, count, &val);
2283 obd->obd_recovery_time_hard = val;
2286 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
2288 EXPORT_SYMBOL(lprocfs_register);
2289 EXPORT_SYMBOL(lprocfs_srch);
2290 EXPORT_SYMBOL(lprocfs_remove);
2291 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
2292 EXPORT_SYMBOL(lprocfs_add_vars);
2293 EXPORT_SYMBOL(lprocfs_obd_setup);
2294 EXPORT_SYMBOL(lprocfs_obd_cleanup);
2295 EXPORT_SYMBOL(lprocfs_add_simple);
2296 EXPORT_SYMBOL(lprocfs_add_symlink);
2297 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
2298 EXPORT_SYMBOL(lprocfs_alloc_stats);
2299 EXPORT_SYMBOL(lprocfs_free_stats);
2300 EXPORT_SYMBOL(lprocfs_clear_stats);
2301 EXPORT_SYMBOL(lprocfs_register_stats);
2302 EXPORT_SYMBOL(lprocfs_init_ops_stats);
2303 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
2304 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
2305 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
2306 EXPORT_SYMBOL(lprocfs_free_obd_stats);
2307 EXPORT_SYMBOL(lprocfs_free_md_stats);
2308 EXPORT_SYMBOL(lprocfs_exp_setup);
2309 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2311 EXPORT_SYMBOL(lprocfs_rd_u64);
2312 EXPORT_SYMBOL(lprocfs_rd_atomic);
2313 EXPORT_SYMBOL(lprocfs_wr_atomic);
2314 EXPORT_SYMBOL(lprocfs_rd_uint);
2315 EXPORT_SYMBOL(lprocfs_wr_uint);
2316 EXPORT_SYMBOL(lprocfs_rd_uuid);
2317 EXPORT_SYMBOL(lprocfs_rd_name);
2318 EXPORT_SYMBOL(lprocfs_rd_fstype);
2319 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
2320 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
2321 EXPORT_SYMBOL(lprocfs_rd_num_exports);
2322 EXPORT_SYMBOL(lprocfs_rd_numrefs);
2323 EXPORT_SYMBOL(lprocfs_at_hist_helper);
2324 EXPORT_SYMBOL(lprocfs_rd_import);
2325 EXPORT_SYMBOL(lprocfs_rd_state);
2326 EXPORT_SYMBOL(lprocfs_rd_timeouts);
2327 EXPORT_SYMBOL(lprocfs_rd_blksize);
2328 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
2329 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
2330 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
2331 EXPORT_SYMBOL(lprocfs_rd_filestotal);
2332 EXPORT_SYMBOL(lprocfs_rd_filesfree);
2334 EXPORT_SYMBOL(lprocfs_write_helper);
2335 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2336 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2337 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2338 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2339 EXPORT_SYMBOL(lprocfs_stats_collect);