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",
774 static int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
779 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
781 ret += snprintf(page + ret, count - ret, "%s%s",
782 ret ? sep : "", obd_connect_names[i]);
784 if (flags & ~(mask - 1))
785 ret += snprintf(page + ret, count - ret,
786 "%sunknown flags "LPX64,
787 ret ? sep : "", flags & ~(mask - 1));
791 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
792 int *eof, void *data)
794 struct lprocfs_counter ret;
795 struct obd_device *obd = (struct obd_device *)data;
796 struct obd_import *imp;
799 LASSERT(obd != NULL);
800 LPROCFS_CLIMP_CHECK(obd);
801 imp = obd->u.cli.cl_import;
804 i = snprintf(page, count,
808 " current_connection: %s\n"
813 imp->imp_connection->c_remote_uuid.uuid,
814 ptlrpc_import_state_name(imp->imp_state));
815 i += obd_connect_flags2str(page + i, count - i,
816 imp->imp_connect_data.ocd_connect_flags,
818 i += snprintf(page + i, count - i,
821 i += obd_import_flags2str(imp, page + i, count - i);
823 i += snprintf(page + i, count - i,
826 " connection_attempts: %u\n"
828 " in-progress_invalidations: %u\n",
831 cfs_atomic_read(&imp->imp_inval_count));
833 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
834 if (ret.lc_count != 0)
835 do_div(ret.lc_sum, ret.lc_count);
838 i += snprintf(page + i, count - i,
841 " unregistering: %u\n"
843 " avg_waittime: "LPU64" %s\n",
844 cfs_atomic_read(&imp->imp_inflight),
845 cfs_atomic_read(&imp->imp_unregistering),
846 cfs_atomic_read(&imp->imp_timeouts),
847 ret.lc_sum, ret.lc_units);
850 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
851 if (imp->imp_at.iat_portal[j] == 0)
853 k = max_t(unsigned int, k,
854 at_get(&imp->imp_at.iat_service_estimate[j]));
856 i += snprintf(page + i, count - i,
857 " service_estimates:\n"
858 " services: %u sec\n"
859 " network: %u sec\n",
861 at_get(&imp->imp_at.iat_net_latency));
863 i += snprintf(page + i, count - i,
865 " last_replay: "LPU64"\n"
866 " peer_committed: "LPU64"\n"
867 " last_checked: "LPU64"\n",
868 imp->imp_last_replay_transno,
869 imp->imp_peer_committed_transno,
870 imp->imp_last_transno_checked);
873 for (rw = 0; rw <= 1; rw++) {
874 lprocfs_stats_collect(obd->obd_svc_stats,
875 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
877 if (ret.lc_sum > 0 && ret.lc_count > 0) {
878 do_div(ret.lc_sum, ret.lc_count);
879 i += snprintf(page + i, count - i,
880 " %s_data_averages:\n"
881 " bytes_per_rpc: "LPU64"\n",
882 rw ? "write" : "read",
886 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
887 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
888 if (ret.lc_sum > 0 && ret.lc_count != 0) {
889 do_div(ret.lc_sum, ret.lc_count);
890 i += snprintf(page + i, count - i,
891 " %s_per_rpc: "LPU64"\n",
892 ret.lc_units, ret.lc_sum);
895 i += snprintf(page + i, count - i,
896 " MB_per_sec: %u.%.02u\n",
897 k / j, (100 * k / j) % 100);
901 LPROCFS_CLIMP_EXIT(obd);
905 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
906 int *eof, void *data)
908 struct obd_device *obd = (struct obd_device *)data;
909 struct obd_import *imp;
912 LASSERT(obd != NULL);
913 LPROCFS_CLIMP_CHECK(obd);
914 imp = obd->u.cli.cl_import;
917 i = snprintf(page, count, "current_state: %s\n",
918 ptlrpc_import_state_name(imp->imp_state));
919 i += snprintf(page + i, count - i,
921 k = imp->imp_state_hist_idx;
922 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
923 struct import_state_hist *ish =
924 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
925 if (ish->ish_state == 0)
927 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
929 ptlrpc_import_state_name(ish->ish_state));
932 LPROCFS_CLIMP_EXIT(obd);
936 int lprocfs_at_hist_helper(char *page, int count, int rc,
937 struct adaptive_timeout *at)
940 for (i = 0; i < AT_BINS; i++)
941 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
942 rc += snprintf(page + rc, count - rc, "\n");
946 /* See also ptlrpc_lprocfs_rd_timeouts */
947 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
948 int *eof, void *data)
950 struct obd_device *obd = (struct obd_device *)data;
951 struct obd_import *imp;
952 unsigned int cur, worst;
957 LASSERT(obd != NULL);
958 LPROCFS_CLIMP_CHECK(obd);
959 imp = obd->u.cli.cl_import;
962 now = cfs_time_current_sec();
964 /* Some network health info for kicks */
965 s2dhms(&ts, now - imp->imp_last_reply_time);
966 rc += snprintf(page + rc, count - rc,
967 "%-10s : %ld, "DHMS_FMT" ago\n",
968 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
970 cur = at_get(&imp->imp_at.iat_net_latency);
971 worst = imp->imp_at.iat_net_latency.at_worst_ever;
972 worstt = imp->imp_at.iat_net_latency.at_worst_time;
973 s2dhms(&ts, now - worstt);
974 rc += snprintf(page + rc, count - rc,
975 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
976 "network", cur, worst, worstt, DHMS_VARS(&ts));
977 rc = lprocfs_at_hist_helper(page, count, rc,
978 &imp->imp_at.iat_net_latency);
980 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
981 if (imp->imp_at.iat_portal[i] == 0)
983 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
984 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
985 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
986 s2dhms(&ts, now - worstt);
987 rc += snprintf(page + rc, count - rc,
988 "portal %-2d : cur %3u worst %3u (at %ld, "
989 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
990 cur, worst, worstt, DHMS_VARS(&ts));
991 rc = lprocfs_at_hist_helper(page, count, rc,
992 &imp->imp_at.iat_service_estimate[i]);
995 LPROCFS_CLIMP_EXIT(obd);
999 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1000 int count, int *eof, void *data)
1002 struct obd_device *obd = data;
1006 LPROCFS_CLIMP_CHECK(obd);
1007 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1008 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1009 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1010 ret += snprintf(page + ret, count - ret, "\n");
1011 LPROCFS_CLIMP_EXIT(obd);
1014 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1016 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1017 int *eof, void *data)
1019 struct obd_device *obd = data;
1021 LASSERT(obd != NULL);
1023 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1026 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1027 int *eof, void *data)
1029 struct obd_type *class = (struct obd_type*) data;
1031 LASSERT(class != NULL);
1033 return snprintf(page, count, "%d\n", class->typ_refcnt);
1036 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1040 LASSERT(obd != NULL);
1041 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1042 LASSERT(obd->obd_type->typ_procroot != NULL);
1044 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1045 obd->obd_type->typ_procroot,
1047 if (IS_ERR(obd->obd_proc_entry)) {
1048 rc = PTR_ERR(obd->obd_proc_entry);
1049 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1050 obd->obd_proc_entry = NULL;
1055 int lprocfs_obd_cleanup(struct obd_device *obd)
1059 if (obd->obd_proc_exports_entry) {
1060 /* Should be no exports left */
1061 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1062 lprocfs_remove(&obd->obd_proc_exports_entry);
1063 obd->obd_proc_exports_entry = NULL;
1065 if (obd->obd_proc_entry) {
1066 lprocfs_remove(&obd->obd_proc_entry);
1067 obd->obd_proc_entry = NULL;
1072 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1074 CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
1075 client_stat->nid_proc, client_stat->nid_stats,
1076 client_stat->nid_brw_stats);
1078 LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
1080 cfs_atomic_read(&client_stat->nid_exp_ref_count));
1082 cfs_hlist_del_init(&client_stat->nid_hash);
1084 if (client_stat->nid_proc)
1085 lprocfs_remove(&client_stat->nid_proc);
1087 if (client_stat->nid_stats)
1088 lprocfs_free_stats(&client_stat->nid_stats);
1090 if (client_stat->nid_brw_stats)
1091 OBD_FREE_PTR(client_stat->nid_brw_stats);
1093 if (client_stat->nid_ldlm_stats)
1094 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1096 OBD_FREE_PTR(client_stat);
1101 void lprocfs_free_per_client_stats(struct obd_device *obd)
1103 struct nid_stat *stat;
1106 /* we need extra list - because hash_exit called to early */
1107 /* not need locking because all clients is died */
1108 while(!cfs_list_empty(&obd->obd_nid_stats)) {
1109 stat = cfs_list_entry(obd->obd_nid_stats.next,
1110 struct nid_stat, nid_list);
1111 cfs_list_del_init(&stat->nid_list);
1112 lprocfs_free_client_stats(stat);
1118 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1119 enum lprocfs_stats_flags flags)
1121 struct lprocfs_stats *stats;
1122 unsigned int percpusize;
1124 unsigned int num_cpu;
1129 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1132 num_cpu = cfs_num_possible_cpus();
1134 OBD_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
1138 if (flags & LPROCFS_STATS_FLAG_NOPERCPU) {
1139 stats->ls_flags = flags;
1140 cfs_spin_lock_init(&stats->ls_lock);
1141 /* Use this lock only if there are no percpu areas */
1143 stats->ls_flags = 0;
1146 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
1148 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1150 for (i = 0; i < num_cpu; i++) {
1151 OBD_ALLOC(stats->ls_percpu[i], percpusize);
1152 if (stats->ls_percpu[i] == NULL) {
1153 for (j = 0; j < i; j++) {
1154 OBD_FREE(stats->ls_percpu[j], percpusize);
1155 stats->ls_percpu[j] = NULL;
1160 if (stats->ls_percpu[0] == NULL) {
1161 OBD_FREE(stats, offsetof(typeof(*stats),
1162 ls_percpu[num_cpu]));
1166 stats->ls_num = num;
1170 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1172 struct lprocfs_stats *stats = *statsh;
1173 unsigned int num_cpu;
1174 unsigned int percpusize;
1177 if (stats == NULL || stats->ls_num == 0)
1181 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1184 num_cpu = cfs_num_possible_cpus();
1186 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
1188 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1189 for (i = 0; i < num_cpu; i++)
1190 OBD_FREE(stats->ls_percpu[i], percpusize);
1191 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
1194 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1196 struct lprocfs_counter *percpu_cntr;
1198 unsigned int num_cpu;
1200 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1202 for (i = 0; i < num_cpu; i++) {
1203 for (j = 0; j < stats->ls_num; j++) {
1204 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
1205 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_entry);
1206 percpu_cntr->lc_count = 0;
1207 percpu_cntr->lc_sum = 0;
1208 percpu_cntr->lc_min = LC_MIN_INIT;
1209 percpu_cntr->lc_max = 0;
1210 percpu_cntr->lc_sumsquare = 0;
1211 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_exit);
1215 lprocfs_stats_unlock(stats);
1218 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1219 size_t len, loff_t *off)
1221 struct seq_file *seq = file->private_data;
1222 struct lprocfs_stats *stats = seq->private;
1224 lprocfs_clear_stats(stats);
1229 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1231 struct lprocfs_stats *stats = p->private;
1232 /* return 1st cpu location */
1233 return (*pos >= stats->ls_num) ? NULL :
1234 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1237 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1241 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1243 struct lprocfs_stats *stats = p->private;
1245 return (*pos >= stats->ls_num) ? NULL :
1246 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1249 /* seq file export of one lprocfs counter */
1250 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1252 struct lprocfs_stats *stats = p->private;
1253 struct lprocfs_counter *cntr = v;
1254 struct lprocfs_counter ret;
1257 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
1259 cfs_gettimeofday(&now);
1260 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1261 "snapshot_time", now.tv_sec, now.tv_usec);
1265 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
1267 lprocfs_stats_collect(stats, idx, &ret);
1269 if (ret.lc_count == 0)
1272 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", cntr->lc_name,
1273 ret.lc_count, cntr->lc_units);
1278 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
1279 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1280 ret.lc_min, ret.lc_max, ret.lc_sum);
1283 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
1284 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1288 rc = seq_printf(p, "\n");
1290 return (rc < 0) ? rc : 0;
1293 struct seq_operations lprocfs_stats_seq_sops = {
1294 start: lprocfs_stats_seq_start,
1295 stop: lprocfs_stats_seq_stop,
1296 next: lprocfs_stats_seq_next,
1297 show: lprocfs_stats_seq_show,
1300 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1302 struct proc_dir_entry *dp = PDE(inode);
1303 struct seq_file *seq;
1306 if (LPROCFS_ENTRY_AND_CHECK(dp))
1309 rc = seq_open(file, &lprocfs_stats_seq_sops);
1314 seq = file->private_data;
1315 seq->private = dp->data;
1319 struct file_operations lprocfs_stats_seq_fops = {
1320 .owner = THIS_MODULE,
1321 .open = lprocfs_stats_seq_open,
1323 .write = lprocfs_stats_seq_write,
1324 .llseek = seq_lseek,
1325 .release = lprocfs_seq_release,
1328 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1329 struct lprocfs_stats *stats)
1331 struct proc_dir_entry *entry;
1332 LASSERT(root != NULL);
1334 entry = create_proc_entry(name, 0644, root);
1337 entry->proc_fops = &lprocfs_stats_seq_fops;
1338 entry->data = stats;
1342 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1343 unsigned conf, const char *name, const char *units)
1345 struct lprocfs_counter *c;
1347 unsigned int num_cpu;
1349 LASSERT(stats != NULL);
1351 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1353 for (i = 0; i < num_cpu; i++) {
1354 c = &(stats->ls_percpu[i]->lp_cntr[index]);
1355 c->lc_config = conf;
1358 c->lc_min = LC_MIN_INIT;
1361 c->lc_units = units;
1364 lprocfs_stats_unlock(stats);
1366 EXPORT_SYMBOL(lprocfs_counter_init);
1368 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1370 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1371 LASSERT(coffset < stats->ls_num); \
1372 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1375 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1377 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1378 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1379 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1380 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1381 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1382 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1383 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1384 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1385 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1386 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1387 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1388 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1389 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1390 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1391 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1392 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1393 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1394 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1395 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
1396 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1397 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1398 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1399 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1400 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1401 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1402 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1403 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1404 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1405 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1406 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1407 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1408 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1409 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1410 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1411 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1412 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1413 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1414 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1415 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1416 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1417 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1418 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1419 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1420 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1421 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
1422 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1423 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1424 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1425 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1426 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1427 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1428 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1429 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1430 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1431 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1432 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1433 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1434 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1435 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1436 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1437 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1438 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quota_adjust_qunit);
1439 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1440 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1441 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1442 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1443 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1444 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1445 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1448 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1450 struct lprocfs_stats *stats;
1451 unsigned int num_stats;
1454 LASSERT(obd->obd_stats == NULL);
1455 LASSERT(obd->obd_proc_entry != NULL);
1456 LASSERT(obd->obd_cntr_base == 0);
1458 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1459 num_private_stats - 1 /* o_owner */;
1460 stats = lprocfs_alloc_stats(num_stats, 0);
1464 lprocfs_init_ops_stats(num_private_stats, stats);
1466 for (i = num_private_stats; i < num_stats; i++) {
1467 /* If this LBUGs, it is likely that an obd
1468 * operation was added to struct obd_ops in
1469 * <obd.h>, and that the corresponding line item
1470 * LPROCFS_OBD_OP_INIT(.., .., opname)
1471 * is missing from the list above. */
1472 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1473 "Missing obd_stat initializer obd_op "
1474 "operation at offset %d.\n", i - num_private_stats);
1476 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1478 lprocfs_free_stats(&stats);
1480 obd->obd_stats = stats;
1481 obd->obd_cntr_base = num_private_stats;
1486 void lprocfs_free_obd_stats(struct obd_device *obd)
1489 lprocfs_free_stats(&obd->obd_stats);
1492 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1494 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1495 LASSERT(coffset < stats->ls_num); \
1496 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1499 int lprocfs_alloc_md_stats(struct obd_device *obd,
1500 unsigned num_private_stats)
1502 struct lprocfs_stats *stats;
1503 unsigned int num_stats;
1506 LASSERT(obd->md_stats == NULL);
1507 LASSERT(obd->obd_proc_entry != NULL);
1508 LASSERT(obd->md_cntr_base == 0);
1510 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1512 stats = lprocfs_alloc_stats(num_stats, 0);
1516 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1517 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1518 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
1519 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1520 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1521 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1522 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1523 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1524 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1525 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1526 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1527 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1528 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1529 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1530 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1531 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1532 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1533 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1534 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1535 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1536 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1537 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1538 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1539 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1540 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1541 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1542 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1543 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1544 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1545 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1546 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1547 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1549 for (i = num_private_stats; i < num_stats; i++) {
1550 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1551 CERROR("Missing md_stat initializer md_op "
1552 "operation at offset %d. Aborting.\n",
1553 i - num_private_stats);
1557 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1559 lprocfs_free_stats(&stats);
1561 obd->md_stats = stats;
1562 obd->md_cntr_base = num_private_stats;
1567 void lprocfs_free_md_stats(struct obd_device *obd)
1569 struct lprocfs_stats *stats = obd->md_stats;
1571 if (stats != NULL) {
1572 obd->md_stats = NULL;
1573 obd->md_cntr_base = 0;
1574 lprocfs_free_stats(&stats);
1578 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1580 lprocfs_counter_init(ldlm_stats,
1581 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1582 0, "ldlm_enqueue", "reqs");
1583 lprocfs_counter_init(ldlm_stats,
1584 LDLM_CONVERT - LDLM_FIRST_OPC,
1585 0, "ldlm_convert", "reqs");
1586 lprocfs_counter_init(ldlm_stats,
1587 LDLM_CANCEL - LDLM_FIRST_OPC,
1588 0, "ldlm_cancel", "reqs");
1589 lprocfs_counter_init(ldlm_stats,
1590 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1591 0, "ldlm_bl_callback", "reqs");
1592 lprocfs_counter_init(ldlm_stats,
1593 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1594 0, "ldlm_cp_callback", "reqs");
1595 lprocfs_counter_init(ldlm_stats,
1596 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1597 0, "ldlm_gl_callback", "reqs");
1600 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1601 int *eof, void *data)
1603 struct obd_export *exp = data;
1604 LASSERT(exp != NULL);
1606 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1609 struct exp_uuid_cb_data {
1617 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1618 int count, int *eof, int *len)
1620 cb_data->page = page;
1621 cb_data->count = count;
1626 void lprocfs_exp_print_uuid(void *obj, void *cb_data)
1628 struct obd_export *exp = (struct obd_export *)obj;
1629 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1631 if (exp->exp_nid_stats)
1632 *data->len += snprintf((data->page + *data->len),
1633 data->count, "%s\n",
1634 obd_uuid2str(&exp->exp_client_uuid));
1637 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1638 int *eof, void *data)
1640 struct nid_stat *stats = (struct nid_stat *)data;
1641 struct exp_uuid_cb_data cb_data;
1642 struct obd_device *obd = stats->nid_obd;
1647 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1648 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1649 lprocfs_exp_print_uuid, &cb_data);
1650 return (*cb_data.len);
1653 void lprocfs_exp_print_hash(void *obj, void *cb_data)
1655 struct exp_uuid_cb_data *data = cb_data;
1656 struct obd_export *exp = obj;
1659 hs = exp->exp_lock_hash;
1662 *data->len += cfs_hash_debug_header(data->page,
1665 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1670 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1671 int *eof, void *data)
1673 struct nid_stat *stats = (struct nid_stat *)data;
1674 struct exp_uuid_cb_data cb_data;
1675 struct obd_device *obd = stats->nid_obd;
1680 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1682 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1683 lprocfs_exp_print_hash, &cb_data);
1684 return (*cb_data.len);
1687 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1688 int count, int *eof, void *data)
1691 return snprintf(page, count, "%s\n",
1692 "Write into this file to clear all nid stats and "
1693 "stale nid entries");
1695 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1697 int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1699 struct nid_stat *stat = obj;
1702 /* object has only hash + iterate_all references.
1703 * add/delete blocked by hash bucket lock */
1704 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
1705 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 2) {
1706 cfs_spin_lock(&stat->nid_obd->obd_nid_lock);
1707 cfs_list_move(&stat->nid_list, data);
1708 cfs_spin_unlock(&stat->nid_obd->obd_nid_lock);
1711 /* we has reference to object - only clear data*/
1712 if (stat->nid_stats)
1713 lprocfs_clear_stats(stat->nid_stats);
1715 if (stat->nid_brw_stats) {
1716 for (i = 0; i < BRW_LAST; i++)
1717 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
1722 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1723 unsigned long count, void *data)
1725 struct obd_device *obd = (struct obd_device *)data;
1726 struct nid_stat *client_stat;
1727 CFS_LIST_HEAD(free_list);
1729 cfs_hash_cond_del(obd->obd_nid_stats_hash,
1730 lprocfs_nid_stats_clear_write_cb, &free_list);
1732 while (!cfs_list_empty(&free_list)) {
1733 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
1735 cfs_list_del_init(&client_stat->nid_list);
1736 lprocfs_free_client_stats(client_stat);
1741 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1743 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1745 struct nid_stat *new_stat, *old_stat;
1746 struct obd_device *obd = NULL;
1747 cfs_proc_dir_entry_t *entry;
1748 char *buffer = NULL;
1754 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1755 !exp->exp_obd->obd_nid_stats_hash)
1758 /* not test against zero because eric say:
1759 * You may only test nid against another nid, or LNET_NID_ANY.
1760 * Anything else is nonsense.*/
1761 if (!nid || *nid == LNET_NID_ANY)
1766 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
1768 OBD_ALLOC_PTR(new_stat);
1769 if (new_stat == NULL)
1772 new_stat->nid = *nid;
1773 new_stat->nid_obd = exp->exp_obd;
1774 cfs_atomic_set(&new_stat->nid_exp_ref_count, 0);
1776 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
1777 nid, &new_stat->nid_hash);
1778 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
1779 old_stat, libcfs_nid2str(*nid),
1780 cfs_atomic_read(&new_stat->nid_exp_ref_count));
1782 /* Return -EALREADY here so that we know that the /proc
1783 * entry already has been created */
1784 if (old_stat != new_stat) {
1785 cfs_spin_lock(&obd->obd_nid_lock);
1786 if (exp->exp_nid_stats != old_stat) {
1787 if (exp->exp_nid_stats)
1788 nidstat_putref(exp->exp_nid_stats);
1789 exp->exp_nid_stats = old_stat;
1791 /* cfs_hash_findadd_unique() has added
1792 * old_stat's refcount */
1793 nidstat_putref(old_stat);
1796 cfs_spin_unlock(&obd->obd_nid_lock);
1798 GOTO(destroy_new, rc = -EALREADY);
1800 /* not found - create */
1801 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
1803 GOTO(destroy_new, rc = -ENOMEM);
1805 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
1806 new_stat->nid_proc = lprocfs_register(buffer,
1807 obd->obd_proc_exports_entry,
1809 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
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 cfs_spin_lock(&obd->obd_nid_lock);
1840 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
1841 cfs_spin_unlock(&obd->obd_nid_lock);
1846 if (new_stat->nid_proc != NULL)
1847 lprocfs_remove(&new_stat->nid_proc);
1848 cfs_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;
1868 int lprocfs_write_helper(const char *buffer, unsigned long count,
1871 return lprocfs_write_frac_helper(buffer, count, val, 1);
1874 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
1877 char kernbuf[20], *end, *pbuf;
1879 if (count > (sizeof(kernbuf) - 1))
1882 if (cfs_copy_from_user(kernbuf, buffer, count))
1885 kernbuf[count] = '\0';
1892 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1896 if (end != NULL && *end == '.') {
1897 int temp_val, pow = 1;
1901 if (strlen(pbuf) > 5)
1902 pbuf[5] = '\0'; /*only allow 5bits fractional*/
1904 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1907 for (i = 0; i < (end - pbuf); i++)
1910 *val += temp_val / pow;
1916 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
1919 long decimal_val, frac_val;
1925 decimal_val = val / mult;
1926 prtn = snprintf(buffer, count, "%ld", decimal_val);
1927 frac_val = val % mult;
1929 if (prtn < (count - 4) && frac_val > 0) {
1931 int i, temp_mult = 1, frac_bits = 0;
1933 temp_frac = frac_val * 10;
1934 buffer[prtn++] = '.';
1935 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
1936 /* only reserved 2 bits fraction */
1937 buffer[prtn++] ='0';
1942 * Need to think these cases :
1943 * 1. #echo x.00 > /proc/xxx output result : x
1944 * 2. #echo x.0x > /proc/xxx output result : x.0x
1945 * 3. #echo x.x0 > /proc/xxx output result : x.x
1946 * 4. #echo x.xx > /proc/xxx output result : x.xx
1947 * Only reserved 2 bits fraction.
1949 for (i = 0; i < (5 - prtn); i++)
1952 frac_bits = min((int)count - prtn, 3 - frac_bits);
1953 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
1954 frac_val * temp_mult / mult);
1957 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
1959 if (buffer[prtn] == '.') {
1966 buffer[prtn++] ='\n';
1970 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
1972 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
1975 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
1976 __u64 *val, int mult)
1978 char kernbuf[22], *end, *pbuf;
1979 __u64 whole, frac = 0, units;
1980 unsigned frac_d = 1;
1982 if (count > (sizeof(kernbuf) - 1))
1985 if (cfs_copy_from_user(kernbuf, buffer, count))
1988 kernbuf[count] = '\0';
1995 whole = simple_strtoull(pbuf, &end, 10);
1999 if (end != NULL && *end == '.') {
2003 /* need to limit frac_d to a __u32 */
2004 if (strlen(pbuf) > 10)
2007 frac = simple_strtoull(pbuf, &end, 10);
2008 /* count decimal places */
2009 for (i = 0; i < (end - pbuf); i++)
2026 /* Specified units override the multiplier */
2028 mult = mult < 0 ? -units : units;
2031 do_div(frac, frac_d);
2032 *val = whole * mult + frac;
2036 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent, char *name, mode_t mode,
2037 struct file_operations *seq_fops, void *data)
2039 struct proc_dir_entry *entry;
2042 entry = create_proc_entry(name, mode, parent);
2045 entry->proc_fops = seq_fops;
2050 EXPORT_SYMBOL(lprocfs_seq_create);
2052 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
2054 struct file_operations *seq_fops,
2057 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2058 mode, seq_fops, data));
2060 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2062 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2064 if (value >= OBD_HIST_MAX)
2065 value = OBD_HIST_MAX - 1;
2067 cfs_spin_lock(&oh->oh_lock);
2068 oh->oh_buckets[value]++;
2069 cfs_spin_unlock(&oh->oh_lock);
2071 EXPORT_SYMBOL(lprocfs_oh_tally);
2073 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2077 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2080 lprocfs_oh_tally(oh, val);
2082 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2084 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2086 unsigned long ret = 0;
2089 for (i = 0; i < OBD_HIST_MAX; i++)
2090 ret += oh->oh_buckets[i];
2093 EXPORT_SYMBOL(lprocfs_oh_sum);
2095 void lprocfs_oh_clear(struct obd_histogram *oh)
2097 cfs_spin_lock(&oh->oh_lock);
2098 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2099 cfs_spin_unlock(&oh->oh_lock);
2101 EXPORT_SYMBOL(lprocfs_oh_clear);
2103 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2104 int count, int *eof, void *data)
2106 struct obd_device *obd = data;
2112 c += cfs_hash_debug_header(page, count);
2113 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2114 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2115 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2119 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2121 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2122 int count, int *eof, void *data)
2124 struct obd_device *obd = data;
2127 LASSERT(obd != NULL);
2128 LASSERT(count >= 0);
2130 /* Set start of user data returned to
2131 page + off since the user may have
2132 requested to read much smaller than
2133 what we need to read */
2134 *start = page + off;
2136 /* We know we are allocated a page here.
2137 Also we know that this function will
2138 not need to write more than a page
2139 so we can truncate at CFS_PAGE_SIZE. */
2140 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2142 /* Initialize the page */
2143 memset(page, 0, size);
2145 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2147 if (obd->obd_max_recoverable_clients == 0) {
2148 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2154 /* sampled unlocked, but really... */
2155 if (obd->obd_recovering == 0) {
2156 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2158 if (lprocfs_obd_snprintf(&page, size, &len,
2159 "recovery_start: %lu\n",
2160 obd->obd_recovery_start) <= 0)
2162 if (lprocfs_obd_snprintf(&page, size, &len,
2163 "recovery_duration: %lu\n",
2164 obd->obd_recovery_end -
2165 obd->obd_recovery_start) <= 0)
2167 /* Number of clients that have completed recovery */
2168 if (lprocfs_obd_snprintf(&page, size, &len,
2169 "completed_clients: %d/%d\n",
2170 obd->obd_max_recoverable_clients -
2171 obd->obd_stale_clients,
2172 obd->obd_max_recoverable_clients) <= 0)
2174 if (lprocfs_obd_snprintf(&page, size, &len,
2175 "replayed_requests: %d\n",
2176 obd->obd_replayed_requests) <= 0)
2178 if (lprocfs_obd_snprintf(&page, size, &len,
2179 "last_transno: "LPD64"\n",
2180 obd->obd_next_recovery_transno - 1)<=0)
2182 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2183 obd->obd_version_recov ? "ON" : "OFF")<=0)
2188 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2190 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2191 obd->obd_recovery_start) <= 0)
2193 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2194 cfs_time_current_sec() >= obd->obd_recovery_end ? 0 :
2195 obd->obd_recovery_end - cfs_time_current_sec()) <= 0)
2197 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2198 obd->obd_connected_clients,
2199 obd->obd_max_recoverable_clients) <= 0)
2201 /* Number of clients that have completed recovery */
2202 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2203 cfs_atomic_read(&obd->obd_req_replay_clients))
2206 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2207 cfs_atomic_read(&obd->obd_lock_replay_clients))
2210 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2211 obd->obd_connected_clients -
2212 cfs_atomic_read(&obd->obd_lock_replay_clients))
2215 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2216 obd->obd_stale_clients) <= 0)
2218 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2219 obd->obd_replayed_requests) <= 0)
2221 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2222 obd->obd_requests_queued_for_recovery) <= 0)
2225 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2226 obd->obd_next_recovery_transno) <= 0)
2232 return min(count, len - (int)off);
2234 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2236 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
2237 int count, int *eof, void *data)
2239 struct obd_device *obd = (struct obd_device *)data;
2240 LASSERT(obd != NULL);
2242 return snprintf(page, count, "%d\n",
2243 obd->obd_recovery_timeout);
2245 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
2247 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
2248 unsigned long count, void *data)
2250 struct obd_device *obd = (struct obd_device *)data;
2252 LASSERT(obd != NULL);
2254 rc = lprocfs_write_helper(buffer, count, &val);
2258 obd->obd_recovery_timeout = val;
2261 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
2263 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
2264 int count, int *eof, void *data)
2266 struct obd_device *obd = data;
2267 LASSERT(obd != NULL);
2269 return snprintf(page, count, "%lu\n", obd->obd_recovery_time_hard);
2271 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
2273 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
2274 unsigned long count, void *data)
2276 struct obd_device *obd = data;
2278 LASSERT(obd != NULL);
2280 rc = lprocfs_write_helper(buffer, count, &val);
2284 obd->obd_recovery_time_hard = val;
2287 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
2289 EXPORT_SYMBOL(lprocfs_register);
2290 EXPORT_SYMBOL(lprocfs_srch);
2291 EXPORT_SYMBOL(lprocfs_remove);
2292 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
2293 EXPORT_SYMBOL(lprocfs_add_vars);
2294 EXPORT_SYMBOL(lprocfs_obd_setup);
2295 EXPORT_SYMBOL(lprocfs_obd_cleanup);
2296 EXPORT_SYMBOL(lprocfs_add_simple);
2297 EXPORT_SYMBOL(lprocfs_add_symlink);
2298 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
2299 EXPORT_SYMBOL(lprocfs_alloc_stats);
2300 EXPORT_SYMBOL(lprocfs_free_stats);
2301 EXPORT_SYMBOL(lprocfs_clear_stats);
2302 EXPORT_SYMBOL(lprocfs_register_stats);
2303 EXPORT_SYMBOL(lprocfs_init_ops_stats);
2304 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
2305 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
2306 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
2307 EXPORT_SYMBOL(lprocfs_free_obd_stats);
2308 EXPORT_SYMBOL(lprocfs_free_md_stats);
2309 EXPORT_SYMBOL(lprocfs_exp_setup);
2310 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2312 EXPORT_SYMBOL(lprocfs_rd_u64);
2313 EXPORT_SYMBOL(lprocfs_rd_atomic);
2314 EXPORT_SYMBOL(lprocfs_wr_atomic);
2315 EXPORT_SYMBOL(lprocfs_rd_uint);
2316 EXPORT_SYMBOL(lprocfs_wr_uint);
2317 EXPORT_SYMBOL(lprocfs_rd_uuid);
2318 EXPORT_SYMBOL(lprocfs_rd_name);
2319 EXPORT_SYMBOL(lprocfs_rd_fstype);
2320 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
2321 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
2322 EXPORT_SYMBOL(lprocfs_rd_num_exports);
2323 EXPORT_SYMBOL(lprocfs_rd_numrefs);
2324 EXPORT_SYMBOL(lprocfs_at_hist_helper);
2325 EXPORT_SYMBOL(lprocfs_rd_import);
2326 EXPORT_SYMBOL(lprocfs_rd_state);
2327 EXPORT_SYMBOL(lprocfs_rd_timeouts);
2328 EXPORT_SYMBOL(lprocfs_rd_blksize);
2329 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
2330 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
2331 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
2332 EXPORT_SYMBOL(lprocfs_rd_filestotal);
2333 EXPORT_SYMBOL(lprocfs_rd_filesfree);
2335 EXPORT_SYMBOL(lprocfs_write_helper);
2336 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2337 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2338 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2339 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2340 EXPORT_SYMBOL(lprocfs_stats_collect);