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 (c) 2002, 2010, Oracle and/or its affiliates. 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 static struct proc_dir_entry *__lprocfs_srch(struct proc_dir_entry *head,
74 struct proc_dir_entry *temp;
80 while (temp != NULL) {
81 if (strcmp(temp->name, name) == 0) {
90 struct proc_dir_entry *lprocfs_srch(struct proc_dir_entry *head,
93 struct proc_dir_entry *temp;
96 temp = __lprocfs_srch(head, name);
101 /* lprocfs API calls */
103 /* Function that emulates snprintf but also has the side effect of advancing
104 the page pointer for the next write into the buffer, incrementing the total
105 length written to the buffer, and decrementing the size left in the
107 static int lprocfs_obd_snprintf(char **page, int end, int *len,
108 const char *format, ...)
116 va_start(list, format);
117 n = vsnprintf(*page, end - *len, format, list);
120 *page += n; *len += n;
124 cfs_proc_dir_entry_t *lprocfs_add_simple(struct proc_dir_entry *root,
126 read_proc_t *read_proc,
127 write_proc_t *write_proc,
129 struct file_operations *fops)
131 cfs_proc_dir_entry_t *proc;
134 if (root == NULL || name == NULL)
135 return ERR_PTR(-EINVAL);
142 LPROCFS_WRITE_ENTRY();
143 proc = create_proc_entry(name, mode, root);
145 CERROR("LprocFS: No memory to create /proc entry %s", name);
146 LPROCFS_WRITE_EXIT();
147 return ERR_PTR(-ENOMEM);
149 proc->read_proc = read_proc;
150 proc->write_proc = write_proc;
153 proc->proc_fops = fops;
154 LPROCFS_WRITE_EXIT();
158 struct proc_dir_entry *lprocfs_add_symlink(const char *name,
159 struct proc_dir_entry *parent, const char *format, ...)
161 struct proc_dir_entry *entry;
165 if (parent == NULL || format == NULL)
168 OBD_ALLOC_WAIT(dest, MAX_STRING_SIZE + 1);
172 va_start(ap, format);
173 vsnprintf(dest, MAX_STRING_SIZE, format, ap);
176 entry = proc_symlink(name, parent, dest);
178 CERROR("LprocFS: Could not create symbolic link from %s to %s",
181 OBD_FREE(dest, MAX_STRING_SIZE + 1);
185 static ssize_t lprocfs_fops_read(struct file *f, char __user *buf,
186 size_t size, loff_t *ppos)
188 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
189 char *page, *start = NULL;
190 int rc = 0, eof = 1, count;
192 if (*ppos >= CFS_PAGE_SIZE)
195 page = (char *)__get_free_page(GFP_KERNEL);
199 if (LPROCFS_ENTRY_AND_CHECK(dp)) {
204 OBD_FAIL_TIMEOUT(OBD_FAIL_LPROC_REMOVE, 10);
206 rc = dp->read_proc(page, &start, *ppos, CFS_PAGE_SIZE,
212 /* for lustre proc read, the read count must be less than PAGE_SIZE */
221 start = page + *ppos;
222 } else if (start < page) {
226 count = (rc < size) ? rc : size;
227 if (cfs_copy_to_user(buf, start, count)) {
234 free_page((unsigned long)page);
238 static ssize_t lprocfs_fops_write(struct file *f, const char __user *buf,
239 size_t size, loff_t *ppos)
241 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
244 if (LPROCFS_ENTRY_AND_CHECK(dp))
247 rc = dp->write_proc(f, buf, size, dp->data);
252 static struct file_operations lprocfs_generic_fops = {
253 .owner = THIS_MODULE,
254 .read = lprocfs_fops_read,
255 .write = lprocfs_fops_write,
258 int lprocfs_evict_client_open(struct inode *inode, struct file *f)
260 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
261 struct obd_device *obd = dp->data;
263 cfs_atomic_inc(&obd->obd_evict_inprogress);
268 int lprocfs_evict_client_release(struct inode *inode, struct file *f)
270 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
271 struct obd_device *obd = dp->data;
273 cfs_atomic_dec(&obd->obd_evict_inprogress);
274 cfs_waitq_signal(&obd->obd_evict_inprogress_waitq);
279 struct file_operations lprocfs_evict_client_fops = {
280 .owner = THIS_MODULE,
281 .read = lprocfs_fops_read,
282 .write = lprocfs_fops_write,
283 .open = lprocfs_evict_client_open,
284 .release = lprocfs_evict_client_release,
286 EXPORT_SYMBOL(lprocfs_evict_client_fops);
291 * \param root [in] The parent proc entry on which new entry will be added.
292 * \param list [in] Array of proc entries to be added.
293 * \param data [in] The argument to be passed when entries read/write routines
294 * are called through /proc file.
296 * \retval 0 on success
299 int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list,
304 if (root == NULL || list == NULL)
307 LPROCFS_WRITE_ENTRY();
308 while (list->name != NULL) {
309 struct proc_dir_entry *cur_root, *proc;
310 char *pathcopy, *cur, *next, pathbuf[64];
311 int pathsize = strlen(list->name) + 1;
316 /* need copy of path for strsep */
317 if (strlen(list->name) > sizeof(pathbuf) - 1) {
318 OBD_ALLOC(pathcopy, pathsize);
319 if (pathcopy == NULL)
320 GOTO(out, rc = -ENOMEM);
326 strcpy(pathcopy, list->name);
328 while (cur_root != NULL && (cur = strsep(&next, "/"))) {
329 if (*cur =='\0') /* skip double/trailing "/" */
332 proc = __lprocfs_srch(cur_root, cur);
333 CDEBUG(D_OTHER, "cur_root=%s, cur=%s, next=%s, (%s)\n",
334 cur_root->name, cur, next,
335 (proc ? "exists" : "new"));
337 cur_root = (proc ? proc :
338 proc_mkdir(cur, cur_root));
339 } else if (proc == NULL) {
341 if (list->proc_mode != 0000) {
342 mode = list->proc_mode;
346 if (list->write_fptr)
349 proc = create_proc_entry(cur, mode, cur_root);
353 if (pathcopy != pathbuf)
354 OBD_FREE(pathcopy, pathsize);
356 if (cur_root == NULL || proc == NULL) {
357 CERROR("LprocFS: No memory to create /proc entry %s",
359 GOTO(out, rc = -ENOMEM);
363 proc->proc_fops = list->fops;
365 proc->proc_fops = &lprocfs_generic_fops;
366 proc->read_proc = list->read_fptr;
367 proc->write_proc = list->write_fptr;
368 proc->data = (list->data ? list->data : data);
372 LPROCFS_WRITE_EXIT();
376 void lprocfs_remove(struct proc_dir_entry **rooth)
378 struct proc_dir_entry *root = *rooth;
379 struct proc_dir_entry *temp = root;
380 struct proc_dir_entry *rm_entry;
381 struct proc_dir_entry *parent;
387 parent = root->parent;
388 LASSERT(parent != NULL);
389 LPROCFS_WRITE_ENTRY(); /* search vs remove race */
392 while (temp->subdir != NULL)
398 /* Memory corruption once caused this to fail, and
399 without this LASSERT we would loop here forever. */
400 LASSERTF(strlen(rm_entry->name) == rm_entry->namelen,
401 "0x%p %s/%s len %d\n", rm_entry, temp->name,
402 rm_entry->name, (int)strlen(rm_entry->name));
404 #ifdef HAVE_PROCFS_USERS
405 /* if procfs uses user count to synchronize deletion of
406 * proc entry, there is no protection for rm_entry->data,
407 * then lprocfs_fops_read and lprocfs_fops_write maybe
408 * call proc_dir_entry->read_proc (or write_proc) with
409 * proc_dir_entry->data == NULL, then cause kernel Oops.
410 * see bug19706 for detailed information */
412 /* procfs won't free rm_entry->data if it isn't a LINK,
413 * and Lustre won't use rm_entry->data if it is a LINK */
414 if (S_ISLNK(rm_entry->mode))
415 rm_entry->data = NULL;
417 /* Now, the rm_entry->deleted flags is protected
418 * by _lprocfs_lock. */
419 rm_entry->data = NULL;
421 remove_proc_entry(rm_entry->name, temp);
425 LPROCFS_WRITE_EXIT();
428 void lprocfs_remove_proc_entry(const char *name, struct proc_dir_entry *parent)
430 LASSERT(parent != NULL);
431 remove_proc_entry(name, parent);
434 struct proc_dir_entry *lprocfs_register(const char *name,
435 struct proc_dir_entry *parent,
436 struct lprocfs_vars *list, void *data)
438 struct proc_dir_entry *newchild;
440 newchild = lprocfs_srch(parent, name);
441 if (newchild != NULL) {
442 CERROR(" Lproc: Attempting to register %s more than once \n",
444 return ERR_PTR(-EALREADY);
447 newchild = proc_mkdir(name, parent);
448 if (newchild != NULL && list != NULL) {
449 int rc = lprocfs_add_vars(newchild, list, data);
451 lprocfs_remove(&newchild);
458 /* Generic callbacks */
459 int lprocfs_rd_uint(char *page, char **start, off_t off,
460 int count, int *eof, void *data)
462 unsigned int *temp = data;
463 return snprintf(page, count, "%u\n", *temp);
466 int lprocfs_wr_uint(struct file *file, const char *buffer,
467 unsigned long count, void *data)
470 char dummy[MAX_STRING_SIZE + 1], *end;
473 dummy[MAX_STRING_SIZE] = '\0';
474 if (cfs_copy_from_user(dummy, buffer, MAX_STRING_SIZE))
477 tmp = simple_strtoul(dummy, &end, 0);
481 *p = (unsigned int)tmp;
485 int lprocfs_rd_u64(char *page, char **start, off_t off,
486 int count, int *eof, void *data)
488 LASSERT(data != NULL);
490 return snprintf(page, count, LPU64"\n", *(__u64 *)data);
493 int lprocfs_rd_atomic(char *page, char **start, off_t off,
494 int count, int *eof, void *data)
496 cfs_atomic_t *atom = data;
497 LASSERT(atom != NULL);
499 return snprintf(page, count, "%d\n", cfs_atomic_read(atom));
502 int lprocfs_wr_atomic(struct file *file, const char *buffer,
503 unsigned long count, void *data)
505 cfs_atomic_t *atm = data;
509 rc = lprocfs_write_helper(buffer, count, &val);
516 cfs_atomic_set(atm, val);
520 int lprocfs_rd_uuid(char *page, char **start, off_t off, int count,
521 int *eof, void *data)
523 struct obd_device *obd = data;
525 LASSERT(obd != NULL);
527 return snprintf(page, count, "%s\n", obd->obd_uuid.uuid);
530 int lprocfs_rd_name(char *page, char **start, off_t off, int count,
531 int *eof, void *data)
533 struct obd_device *dev = data;
535 LASSERT(dev != NULL);
536 LASSERT(dev->obd_name != NULL);
538 return snprintf(page, count, "%s\n", dev->obd_name);
541 int lprocfs_rd_fstype(char *page, char **start, off_t off, int count, int *eof,
544 struct obd_device *obd = data;
546 LASSERT(obd != NULL);
547 LASSERT(obd->obd_fsops != NULL);
548 LASSERT(obd->obd_fsops->fs_type != NULL);
549 return snprintf(page, count, "%s\n", obd->obd_fsops->fs_type);
552 int lprocfs_rd_blksize(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,
557 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
561 rc = snprintf(page, count, "%u\n", osfs.os_bsize);
566 int lprocfs_rd_kbytestotal(char *page, char **start, off_t off, int count,
567 int *eof, void *data)
569 struct obd_statfs osfs;
570 int rc = obd_statfs(data, &osfs,
571 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
574 __u32 blk_size = osfs.os_bsize >> 10;
575 __u64 result = osfs.os_blocks;
577 while (blk_size >>= 1)
581 rc = snprintf(page, count, LPU64"\n", result);
586 int lprocfs_rd_kbytesfree(char *page, char **start, off_t off, int count,
587 int *eof, void *data)
589 struct obd_statfs osfs;
590 int rc = obd_statfs(data, &osfs,
591 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
594 __u32 blk_size = osfs.os_bsize >> 10;
595 __u64 result = osfs.os_bfree;
597 while (blk_size >>= 1)
601 rc = snprintf(page, count, LPU64"\n", result);
606 int lprocfs_rd_kbytesavail(char *page, char **start, off_t off, int count,
607 int *eof, void *data)
609 struct obd_statfs osfs;
610 int rc = obd_statfs(data, &osfs,
611 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
614 __u32 blk_size = osfs.os_bsize >> 10;
615 __u64 result = osfs.os_bavail;
617 while (blk_size >>= 1)
621 rc = snprintf(page, count, LPU64"\n", result);
626 int lprocfs_rd_filestotal(char *page, char **start, off_t off, int count,
627 int *eof, void *data)
629 struct obd_statfs osfs;
630 int rc = obd_statfs(data, &osfs,
631 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
635 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
641 int lprocfs_rd_filesfree(char *page, char **start, off_t off, int count,
642 int *eof, void *data)
644 struct obd_statfs osfs;
645 int rc = obd_statfs(data, &osfs,
646 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
650 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
655 int lprocfs_rd_server_uuid(char *page, char **start, off_t off, int count,
656 int *eof, void *data)
658 struct obd_device *obd = data;
659 struct obd_import *imp;
660 char *imp_state_name = NULL;
663 LASSERT(obd != NULL);
664 LPROCFS_CLIMP_CHECK(obd);
665 imp = obd->u.cli.cl_import;
666 imp_state_name = ptlrpc_import_state_name(imp->imp_state);
668 rc = snprintf(page, count, "%s\t%s%s\n",
669 obd2cli_tgt(obd), imp_state_name,
670 imp->imp_deactive ? "\tDEACTIVATED" : "");
672 LPROCFS_CLIMP_EXIT(obd);
676 int lprocfs_rd_conn_uuid(char *page, char **start, off_t off, int count,
677 int *eof, void *data)
679 struct obd_device *obd = data;
680 struct ptlrpc_connection *conn;
683 LASSERT(obd != NULL);
685 LPROCFS_CLIMP_CHECK(obd);
686 conn = obd->u.cli.cl_import->imp_connection;
688 if (conn && obd->u.cli.cl_import) {
689 rc = snprintf(page, count, "%s\n",
690 conn->c_remote_uuid.uuid);
692 rc = snprintf(page, count, "%s\n", "<none>");
695 LPROCFS_CLIMP_EXIT(obd);
699 /** add up per-cpu counters */
700 void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
701 struct lprocfs_counter *cnt)
703 unsigned int num_cpu;
704 struct lprocfs_counter t;
705 struct lprocfs_counter *percpu_cntr;
708 memset(cnt, 0, sizeof(*cnt));
711 /* set count to 1 to avoid divide-by-zero errs in callers */
716 cnt->lc_min = LC_MIN_INIT;
718 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
720 for (i = 0; i < num_cpu; i++) {
721 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[idx];
724 centry = cfs_atomic_read(&percpu_cntr-> \
726 t.lc_count = percpu_cntr->lc_count;
727 t.lc_sum = percpu_cntr->lc_sum;
728 t.lc_min = percpu_cntr->lc_min;
729 t.lc_max = percpu_cntr->lc_max;
730 t.lc_sumsquare = percpu_cntr->lc_sumsquare;
731 } while (centry != cfs_atomic_read(&percpu_cntr->lc_cntl. \
733 centry != cfs_atomic_read(&percpu_cntr->lc_cntl. \
735 cnt->lc_count += t.lc_count;
736 cnt->lc_sum += t.lc_sum;
737 if (t.lc_min < cnt->lc_min)
738 cnt->lc_min = t.lc_min;
739 if (t.lc_max > cnt->lc_max)
740 cnt->lc_max = t.lc_max;
741 cnt->lc_sumsquare += t.lc_sumsquare;
744 cnt->lc_units = stats->ls_percpu[0]->lp_cntr[idx].lc_units;
745 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU);
749 * Append a space separated list of current set flags to str.
751 #define flag2str(flag) \
752 if (imp->imp_##flag && max - len > 0) \
753 len += snprintf(str + len, max - len, "%s" #flag, len ? ", " : "");
754 static int obd_import_flags2str(struct obd_import *imp, char *str, int max)
758 if (imp->imp_obd->obd_no_recov)
759 len += snprintf(str, max - len, "no_recov");
763 flag2str(replayable);
769 static const char *obd_connect_names[] = {
783 "join_file(obsolete)",
787 "remote_client_by_force",
796 "mds_mds_connection",
799 "alt_checksum_algorithm",
811 static int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
816 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
818 ret += snprintf(page + ret, count - ret, "%s%s",
819 ret ? sep : "", obd_connect_names[i]);
821 if (flags & ~(mask - 1))
822 ret += snprintf(page + ret, count - ret,
823 "%sunknown flags "LPX64,
824 ret ? sep : "", flags & ~(mask - 1));
828 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
829 int *eof, void *data)
831 struct lprocfs_counter ret;
832 struct obd_device *obd = (struct obd_device *)data;
833 struct obd_import *imp;
834 struct obd_import_conn *conn;
837 LASSERT(obd != NULL);
838 LPROCFS_CLIMP_CHECK(obd);
839 imp = obd->u.cli.cl_import;
842 i = snprintf(page, count,
850 ptlrpc_import_state_name(imp->imp_state));
851 i += obd_connect_flags2str(page + i, count - i,
852 imp->imp_connect_data.ocd_connect_flags,
854 i += snprintf(page + i, count - i,
857 i += obd_import_flags2str(imp, page + i, count - i);
859 i += snprintf(page + i, count - i,
862 " failover_nids: [");
863 cfs_spin_lock(&imp->imp_lock);
865 cfs_list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
866 i += snprintf(page + i, count - i, "%s%s", j ? ", " : "",
867 libcfs_nid2str(conn->oic_conn->c_peer.nid));
870 cfs_spin_unlock(&imp->imp_lock);
871 i += snprintf(page + i, count - i,
873 " current_connection: %s\n"
874 " connection_attempts: %u\n"
876 " in-progress_invalidations: %u\n",
877 libcfs_nid2str(imp->imp_connection->c_peer.nid),
880 cfs_atomic_read(&imp->imp_inval_count));
882 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
883 if (ret.lc_count != 0) {
884 /* first argument to do_div MUST be __u64 */
885 __u64 sum = ret.lc_sum;
886 do_div(sum, ret.lc_count);
890 i += snprintf(page + i, count - i,
893 " unregistering: %u\n"
895 " avg_waittime: "LPU64" %s\n",
896 cfs_atomic_read(&imp->imp_inflight),
897 cfs_atomic_read(&imp->imp_unregistering),
898 cfs_atomic_read(&imp->imp_timeouts),
899 ret.lc_sum, ret.lc_units);
902 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
903 if (imp->imp_at.iat_portal[j] == 0)
905 k = max_t(unsigned int, k,
906 at_get(&imp->imp_at.iat_service_estimate[j]));
908 i += snprintf(page + i, count - i,
909 " service_estimates:\n"
910 " services: %u sec\n"
911 " network: %u sec\n",
913 at_get(&imp->imp_at.iat_net_latency));
915 i += snprintf(page + i, count - i,
917 " last_replay: "LPU64"\n"
918 " peer_committed: "LPU64"\n"
919 " last_checked: "LPU64"\n",
920 imp->imp_last_replay_transno,
921 imp->imp_peer_committed_transno,
922 imp->imp_last_transno_checked);
925 for (rw = 0; rw <= 1; rw++) {
926 lprocfs_stats_collect(obd->obd_svc_stats,
927 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
929 if (ret.lc_sum > 0 && ret.lc_count > 0) {
930 /* first argument to do_div MUST be __u64 */
931 __u64 sum = ret.lc_sum;
932 do_div(sum, ret.lc_count);
934 i += snprintf(page + i, count - i,
935 " %s_data_averages:\n"
936 " bytes_per_rpc: "LPU64"\n",
937 rw ? "write" : "read",
941 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
942 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
943 if (ret.lc_sum > 0 && ret.lc_count != 0) {
944 /* first argument to do_div MUST be __u64 */
945 __u64 sum = ret.lc_sum;
946 do_div(sum, ret.lc_count);
948 i += snprintf(page + i, count - i,
949 " %s_per_rpc: "LPU64"\n",
950 ret.lc_units, ret.lc_sum);
953 i += snprintf(page + i, count - i,
954 " MB_per_sec: %u.%.02u\n",
955 k / j, (100 * k / j) % 100);
959 LPROCFS_CLIMP_EXIT(obd);
963 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
964 int *eof, void *data)
966 struct obd_device *obd = (struct obd_device *)data;
967 struct obd_import *imp;
970 LASSERT(obd != NULL);
971 LPROCFS_CLIMP_CHECK(obd);
972 imp = obd->u.cli.cl_import;
975 i = snprintf(page, count, "current_state: %s\n",
976 ptlrpc_import_state_name(imp->imp_state));
977 i += snprintf(page + i, count - i,
979 k = imp->imp_state_hist_idx;
980 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
981 struct import_state_hist *ish =
982 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
983 if (ish->ish_state == 0)
985 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
987 ptlrpc_import_state_name(ish->ish_state));
990 LPROCFS_CLIMP_EXIT(obd);
994 int lprocfs_at_hist_helper(char *page, int count, int rc,
995 struct adaptive_timeout *at)
998 for (i = 0; i < AT_BINS; i++)
999 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
1000 rc += snprintf(page + rc, count - rc, "\n");
1004 /* See also ptlrpc_lprocfs_rd_timeouts */
1005 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
1006 int *eof, void *data)
1008 struct obd_device *obd = (struct obd_device *)data;
1009 struct obd_import *imp;
1010 unsigned int cur, worst;
1015 LASSERT(obd != NULL);
1016 LPROCFS_CLIMP_CHECK(obd);
1017 imp = obd->u.cli.cl_import;
1020 now = cfs_time_current_sec();
1022 /* Some network health info for kicks */
1023 s2dhms(&ts, now - imp->imp_last_reply_time);
1024 rc += snprintf(page + rc, count - rc,
1025 "%-10s : %ld, "DHMS_FMT" ago\n",
1026 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
1028 cur = at_get(&imp->imp_at.iat_net_latency);
1029 worst = imp->imp_at.iat_net_latency.at_worst_ever;
1030 worstt = imp->imp_at.iat_net_latency.at_worst_time;
1031 s2dhms(&ts, now - worstt);
1032 rc += snprintf(page + rc, count - rc,
1033 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
1034 "network", cur, worst, worstt, DHMS_VARS(&ts));
1035 rc = lprocfs_at_hist_helper(page, count, rc,
1036 &imp->imp_at.iat_net_latency);
1038 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
1039 if (imp->imp_at.iat_portal[i] == 0)
1041 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
1042 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
1043 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
1044 s2dhms(&ts, now - worstt);
1045 rc += snprintf(page + rc, count - rc,
1046 "portal %-2d : cur %3u worst %3u (at %ld, "
1047 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
1048 cur, worst, worstt, DHMS_VARS(&ts));
1049 rc = lprocfs_at_hist_helper(page, count, rc,
1050 &imp->imp_at.iat_service_estimate[i]);
1053 LPROCFS_CLIMP_EXIT(obd);
1057 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1058 int count, int *eof, void *data)
1060 struct obd_device *obd = data;
1064 LPROCFS_CLIMP_CHECK(obd);
1065 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1066 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1067 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1068 ret += snprintf(page + ret, count - ret, "\n");
1069 LPROCFS_CLIMP_EXIT(obd);
1072 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1074 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1075 int *eof, void *data)
1077 struct obd_device *obd = data;
1079 LASSERT(obd != NULL);
1081 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1084 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1085 int *eof, void *data)
1087 struct obd_type *class = (struct obd_type*) data;
1089 LASSERT(class != NULL);
1091 return snprintf(page, count, "%d\n", class->typ_refcnt);
1094 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1098 LASSERT(obd != NULL);
1099 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1100 LASSERT(obd->obd_type->typ_procroot != NULL);
1102 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1103 obd->obd_type->typ_procroot,
1105 if (IS_ERR(obd->obd_proc_entry)) {
1106 rc = PTR_ERR(obd->obd_proc_entry);
1107 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1108 obd->obd_proc_entry = NULL;
1113 int lprocfs_obd_cleanup(struct obd_device *obd)
1117 if (obd->obd_proc_exports_entry) {
1118 /* Should be no exports left */
1119 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1120 lprocfs_remove(&obd->obd_proc_exports_entry);
1121 obd->obd_proc_exports_entry = NULL;
1123 if (obd->obd_proc_entry) {
1124 lprocfs_remove(&obd->obd_proc_entry);
1125 obd->obd_proc_entry = NULL;
1130 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1132 CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
1133 client_stat->nid_proc, client_stat->nid_stats,
1134 client_stat->nid_brw_stats);
1136 LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
1137 "nid %s:count %d\n", libcfs_nid2str(client_stat->nid),
1138 atomic_read(&client_stat->nid_exp_ref_count));
1140 cfs_hlist_del_init(&client_stat->nid_hash);
1142 if (client_stat->nid_proc)
1143 lprocfs_remove(&client_stat->nid_proc);
1145 if (client_stat->nid_stats)
1146 lprocfs_free_stats(&client_stat->nid_stats);
1148 if (client_stat->nid_brw_stats)
1149 OBD_FREE_PTR(client_stat->nid_brw_stats);
1151 if (client_stat->nid_ldlm_stats)
1152 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1154 OBD_FREE_PTR(client_stat);
1159 void lprocfs_free_per_client_stats(struct obd_device *obd)
1161 struct nid_stat *stat;
1164 /* we need extra list - because hash_exit called to early */
1165 /* not need locking because all clients is died */
1166 while(!cfs_list_empty(&obd->obd_nid_stats)) {
1167 stat = cfs_list_entry(obd->obd_nid_stats.next,
1168 struct nid_stat, nid_list);
1169 cfs_list_del_init(&stat->nid_list);
1170 lprocfs_free_client_stats(stat);
1176 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1177 enum lprocfs_stats_flags flags)
1179 struct lprocfs_stats *stats;
1180 unsigned int percpusize;
1182 unsigned int num_cpu;
1187 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1190 num_cpu = cfs_num_possible_cpus();
1192 OBD_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
1196 if (flags & LPROCFS_STATS_FLAG_NOPERCPU) {
1197 stats->ls_flags = flags;
1198 cfs_spin_lock_init(&stats->ls_lock);
1199 /* Use this lock only if there are no percpu areas */
1201 stats->ls_flags = 0;
1204 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
1206 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1208 for (i = 0; i < num_cpu; i++) {
1209 OBD_ALLOC(stats->ls_percpu[i], percpusize);
1210 if (stats->ls_percpu[i] == NULL) {
1211 for (j = 0; j < i; j++) {
1212 OBD_FREE(stats->ls_percpu[j], percpusize);
1213 stats->ls_percpu[j] = NULL;
1218 if (stats->ls_percpu[0] == NULL) {
1219 OBD_FREE(stats, offsetof(typeof(*stats),
1220 ls_percpu[num_cpu]));
1224 stats->ls_num = num;
1228 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1230 struct lprocfs_stats *stats = *statsh;
1231 unsigned int num_cpu;
1232 unsigned int percpusize;
1235 if (stats == NULL || stats->ls_num == 0)
1239 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1242 num_cpu = cfs_num_possible_cpus();
1244 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
1246 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1247 for (i = 0; i < num_cpu; i++)
1248 OBD_FREE(stats->ls_percpu[i], percpusize);
1249 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
1252 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1254 struct lprocfs_counter *percpu_cntr;
1256 unsigned int num_cpu;
1258 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1260 for (i = 0; i < num_cpu; i++) {
1261 for (j = 0; j < stats->ls_num; j++) {
1262 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
1263 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_entry);
1264 percpu_cntr->lc_count = 0;
1265 percpu_cntr->lc_sum = 0;
1266 percpu_cntr->lc_min = LC_MIN_INIT;
1267 percpu_cntr->lc_max = 0;
1268 percpu_cntr->lc_sumsquare = 0;
1269 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_exit);
1273 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU);
1276 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1277 size_t len, loff_t *off)
1279 struct seq_file *seq = file->private_data;
1280 struct lprocfs_stats *stats = seq->private;
1282 lprocfs_clear_stats(stats);
1287 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1289 struct lprocfs_stats *stats = p->private;
1290 /* return 1st cpu location */
1291 return (*pos >= stats->ls_num) ? NULL :
1292 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1295 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1299 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1301 struct lprocfs_stats *stats = p->private;
1303 return (*pos >= stats->ls_num) ? NULL :
1304 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1307 /* seq file export of one lprocfs counter */
1308 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1310 struct lprocfs_stats *stats = p->private;
1311 struct lprocfs_counter *cntr = v;
1312 struct lprocfs_counter ret;
1315 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
1317 cfs_gettimeofday(&now);
1318 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1319 "snapshot_time", now.tv_sec, now.tv_usec);
1323 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
1325 lprocfs_stats_collect(stats, idx, &ret);
1327 if (ret.lc_count == 0)
1330 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", cntr->lc_name,
1331 ret.lc_count, cntr->lc_units);
1336 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
1337 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1338 ret.lc_min, ret.lc_max, ret.lc_sum);
1341 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
1342 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1346 rc = seq_printf(p, "\n");
1348 return (rc < 0) ? rc : 0;
1351 struct seq_operations lprocfs_stats_seq_sops = {
1352 start: lprocfs_stats_seq_start,
1353 stop: lprocfs_stats_seq_stop,
1354 next: lprocfs_stats_seq_next,
1355 show: lprocfs_stats_seq_show,
1358 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1360 struct proc_dir_entry *dp = PDE(inode);
1361 struct seq_file *seq;
1364 if (LPROCFS_ENTRY_AND_CHECK(dp))
1367 rc = seq_open(file, &lprocfs_stats_seq_sops);
1372 seq = file->private_data;
1373 seq->private = dp->data;
1377 struct file_operations lprocfs_stats_seq_fops = {
1378 .owner = THIS_MODULE,
1379 .open = lprocfs_stats_seq_open,
1381 .write = lprocfs_stats_seq_write,
1382 .llseek = seq_lseek,
1383 .release = lprocfs_seq_release,
1386 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1387 struct lprocfs_stats *stats)
1389 struct proc_dir_entry *entry;
1390 LASSERT(root != NULL);
1392 LPROCFS_WRITE_ENTRY();
1393 entry = create_proc_entry(name, 0644, root);
1395 entry->proc_fops = &lprocfs_stats_seq_fops;
1396 entry->data = stats;
1399 LPROCFS_WRITE_EXIT();
1407 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1408 unsigned conf, const char *name, const char *units)
1410 struct lprocfs_counter *c;
1412 unsigned int num_cpu;
1414 LASSERT(stats != NULL);
1416 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1418 for (i = 0; i < num_cpu; i++) {
1419 c = &(stats->ls_percpu[i]->lp_cntr[index]);
1420 c->lc_config = conf;
1423 c->lc_min = LC_MIN_INIT;
1426 c->lc_units = units;
1429 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU);
1431 EXPORT_SYMBOL(lprocfs_counter_init);
1433 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1435 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1436 LASSERT(coffset < stats->ls_num); \
1437 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1440 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1442 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1443 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1444 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1445 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1446 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1447 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1448 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1449 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1450 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1451 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1452 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1453 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1454 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1455 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1456 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1457 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1458 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1459 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1460 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
1461 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1462 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1463 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1464 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1465 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1466 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1467 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1468 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1469 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1470 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1471 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1472 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1473 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1474 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1475 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1476 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1477 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1478 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1479 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1480 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1481 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1482 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1483 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1484 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1485 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1486 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
1487 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1488 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1489 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1490 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1491 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1492 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1493 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1494 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1495 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1496 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1497 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1498 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1499 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1500 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1501 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1502 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1503 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quota_adjust_qunit);
1504 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1505 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1506 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1507 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1508 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1509 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1510 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1513 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1515 struct lprocfs_stats *stats;
1516 unsigned int num_stats;
1519 LASSERT(obd->obd_stats == NULL);
1520 LASSERT(obd->obd_proc_entry != NULL);
1521 LASSERT(obd->obd_cntr_base == 0);
1523 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1524 num_private_stats - 1 /* o_owner */;
1525 stats = lprocfs_alloc_stats(num_stats, 0);
1529 lprocfs_init_ops_stats(num_private_stats, stats);
1531 for (i = num_private_stats; i < num_stats; i++) {
1532 /* If this LBUGs, it is likely that an obd
1533 * operation was added to struct obd_ops in
1534 * <obd.h>, and that the corresponding line item
1535 * LPROCFS_OBD_OP_INIT(.., .., opname)
1536 * is missing from the list above. */
1537 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1538 "Missing obd_stat initializer obd_op "
1539 "operation at offset %d.\n", i - num_private_stats);
1541 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1543 lprocfs_free_stats(&stats);
1545 obd->obd_stats = stats;
1546 obd->obd_cntr_base = num_private_stats;
1551 void lprocfs_free_obd_stats(struct obd_device *obd)
1554 lprocfs_free_stats(&obd->obd_stats);
1557 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1559 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1560 LASSERT(coffset < stats->ls_num); \
1561 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1564 void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats)
1566 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1567 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1568 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
1569 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1570 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1571 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1572 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1573 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1574 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1575 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1576 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1577 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1578 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1579 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1580 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1581 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1582 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1583 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1584 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1585 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1586 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1587 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1588 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1589 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1590 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1591 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1592 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1593 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1594 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1595 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1596 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1597 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1600 int lprocfs_alloc_md_stats(struct obd_device *obd,
1601 unsigned num_private_stats)
1603 struct lprocfs_stats *stats;
1604 unsigned int num_stats;
1607 LASSERT(obd->md_stats == NULL);
1608 LASSERT(obd->obd_proc_entry != NULL);
1609 LASSERT(obd->md_cntr_base == 0);
1611 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1613 stats = lprocfs_alloc_stats(num_stats, 0);
1617 lprocfs_init_mps_stats(num_private_stats, stats);
1619 for (i = num_private_stats; i < num_stats; i++) {
1620 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1621 CERROR("Missing md_stat initializer md_op "
1622 "operation at offset %d. Aborting.\n",
1623 i - num_private_stats);
1627 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1629 lprocfs_free_stats(&stats);
1631 obd->md_stats = stats;
1632 obd->md_cntr_base = num_private_stats;
1637 void lprocfs_free_md_stats(struct obd_device *obd)
1639 struct lprocfs_stats *stats = obd->md_stats;
1641 if (stats != NULL) {
1642 obd->md_stats = NULL;
1643 obd->md_cntr_base = 0;
1644 lprocfs_free_stats(&stats);
1648 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1650 lprocfs_counter_init(ldlm_stats,
1651 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1652 0, "ldlm_enqueue", "reqs");
1653 lprocfs_counter_init(ldlm_stats,
1654 LDLM_CONVERT - LDLM_FIRST_OPC,
1655 0, "ldlm_convert", "reqs");
1656 lprocfs_counter_init(ldlm_stats,
1657 LDLM_CANCEL - LDLM_FIRST_OPC,
1658 0, "ldlm_cancel", "reqs");
1659 lprocfs_counter_init(ldlm_stats,
1660 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1661 0, "ldlm_bl_callback", "reqs");
1662 lprocfs_counter_init(ldlm_stats,
1663 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1664 0, "ldlm_cp_callback", "reqs");
1665 lprocfs_counter_init(ldlm_stats,
1666 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1667 0, "ldlm_gl_callback", "reqs");
1670 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1671 int *eof, void *data)
1673 struct obd_export *exp = data;
1674 LASSERT(exp != NULL);
1676 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1679 struct exp_uuid_cb_data {
1687 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1688 int count, int *eof, int *len)
1690 cb_data->page = page;
1691 cb_data->count = count;
1696 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1697 cfs_hlist_node_t *hnode, void *cb_data)
1700 struct obd_export *exp = cfs_hash_object(hs, hnode);
1701 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1703 if (exp->exp_nid_stats)
1704 *data->len += snprintf((data->page + *data->len),
1705 data->count, "%s\n",
1706 obd_uuid2str(&exp->exp_client_uuid));
1710 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1711 int *eof, void *data)
1713 struct nid_stat *stats = (struct nid_stat *)data;
1714 struct exp_uuid_cb_data cb_data;
1715 struct obd_device *obd = stats->nid_obd;
1720 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1721 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1722 lprocfs_exp_print_uuid, &cb_data);
1723 return (*cb_data.len);
1726 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1727 cfs_hlist_node_t *hnode, void *cb_data)
1730 struct exp_uuid_cb_data *data = cb_data;
1731 struct obd_export *exp = cfs_hash_object(hs, hnode);
1733 if (exp->exp_lock_hash != NULL) {
1735 *data->len += cfs_hash_debug_header(data->page,
1738 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1745 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1746 int *eof, void *data)
1748 struct nid_stat *stats = (struct nid_stat *)data;
1749 struct exp_uuid_cb_data cb_data;
1750 struct obd_device *obd = stats->nid_obd;
1755 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1757 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1758 lprocfs_exp_print_hash, &cb_data);
1759 return (*cb_data.len);
1762 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1763 int count, int *eof, void *data)
1766 return snprintf(page, count, "%s\n",
1767 "Write into this file to clear all nid stats and "
1768 "stale nid entries");
1770 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1772 int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1774 struct nid_stat *stat = obj;
1778 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
1779 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 1) {
1780 /* object has only hash references. */
1781 cfs_spin_lock(&stat->nid_obd->obd_nid_lock);
1782 cfs_list_move(&stat->nid_list, data);
1783 cfs_spin_unlock(&stat->nid_obd->obd_nid_lock);
1786 /* we has reference to object - only clear data*/
1787 if (stat->nid_stats)
1788 lprocfs_clear_stats(stat->nid_stats);
1790 if (stat->nid_brw_stats) {
1791 for (i = 0; i < BRW_LAST; i++)
1792 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
1797 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1798 unsigned long count, void *data)
1800 struct obd_device *obd = (struct obd_device *)data;
1801 struct nid_stat *client_stat;
1802 CFS_LIST_HEAD(free_list);
1804 cfs_hash_cond_del(obd->obd_nid_stats_hash,
1805 lprocfs_nid_stats_clear_write_cb, &free_list);
1807 while (!cfs_list_empty(&free_list)) {
1808 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
1810 cfs_list_del_init(&client_stat->nid_list);
1811 lprocfs_free_client_stats(client_stat);
1816 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1818 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1820 struct nid_stat *new_stat, *old_stat;
1821 struct obd_device *obd = NULL;
1822 cfs_proc_dir_entry_t *entry;
1823 char *buffer = NULL;
1829 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1830 !exp->exp_obd->obd_nid_stats_hash)
1833 /* not test against zero because eric say:
1834 * You may only test nid against another nid, or LNET_NID_ANY.
1835 * Anything else is nonsense.*/
1836 if (!nid || *nid == LNET_NID_ANY)
1841 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
1843 OBD_ALLOC_PTR(new_stat);
1844 if (new_stat == NULL)
1847 new_stat->nid = *nid;
1848 new_stat->nid_obd = exp->exp_obd;
1849 /* we need set default refcount to 1 to balance obd_disconnect */
1850 cfs_atomic_set(&new_stat->nid_exp_ref_count, 1);
1852 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
1853 nid, &new_stat->nid_hash);
1854 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
1855 old_stat, libcfs_nid2str(*nid),
1856 cfs_atomic_read(&new_stat->nid_exp_ref_count));
1858 /* We need to release old stats because lprocfs_exp_cleanup() hasn't
1859 * been and will never be called. */
1860 if (exp->exp_nid_stats) {
1861 nidstat_putref(exp->exp_nid_stats);
1862 exp->exp_nid_stats = NULL;
1865 /* Return -EALREADY here so that we know that the /proc
1866 * entry already has been created */
1867 if (old_stat != new_stat) {
1868 exp->exp_nid_stats = old_stat;
1869 GOTO(destroy_new, rc = -EALREADY);
1871 /* not found - create */
1872 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
1874 GOTO(destroy_new, rc = -ENOMEM);
1876 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
1877 new_stat->nid_proc = lprocfs_register(buffer,
1878 obd->obd_proc_exports_entry,
1880 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
1882 if (new_stat->nid_proc == NULL) {
1883 CERROR("Error making export directory for nid %s\n",
1884 libcfs_nid2str(*nid));
1885 GOTO(destroy_new_ns, rc = -ENOMEM);
1888 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
1889 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
1890 if (IS_ERR(entry)) {
1891 CWARN("Error adding the NID stats file\n");
1892 rc = PTR_ERR(entry);
1893 GOTO(destroy_new_ns, rc);
1896 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
1897 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
1898 if (IS_ERR(entry)) {
1899 CWARN("Error adding the hash file\n");
1900 rc = PTR_ERR(entry);
1901 GOTO(destroy_new_ns, rc);
1904 exp->exp_nid_stats = new_stat;
1906 /* protect competitive add to list, not need locking on destroy */
1907 cfs_spin_lock(&obd->obd_nid_lock);
1908 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
1909 cfs_spin_unlock(&obd->obd_nid_lock);
1914 if (new_stat->nid_proc != NULL)
1915 lprocfs_remove(&new_stat->nid_proc);
1916 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
1919 nidstat_putref(new_stat);
1920 OBD_FREE_PTR(new_stat);
1924 int lprocfs_exp_cleanup(struct obd_export *exp)
1926 struct nid_stat *stat = exp->exp_nid_stats;
1928 if(!stat || !exp->exp_obd)
1931 nidstat_putref(exp->exp_nid_stats);
1932 exp->exp_nid_stats = NULL;
1937 int lprocfs_write_helper(const char *buffer, unsigned long count,
1940 return lprocfs_write_frac_helper(buffer, count, val, 1);
1943 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
1946 char kernbuf[20], *end, *pbuf;
1948 if (count > (sizeof(kernbuf) - 1))
1951 if (cfs_copy_from_user(kernbuf, buffer, count))
1954 kernbuf[count] = '\0';
1961 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1965 if (end != NULL && *end == '.') {
1966 int temp_val, pow = 1;
1970 if (strlen(pbuf) > 5)
1971 pbuf[5] = '\0'; /*only allow 5bits fractional*/
1973 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1976 for (i = 0; i < (end - pbuf); i++)
1979 *val += temp_val / pow;
1985 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
1988 long decimal_val, frac_val;
1994 decimal_val = val / mult;
1995 prtn = snprintf(buffer, count, "%ld", decimal_val);
1996 frac_val = val % mult;
1998 if (prtn < (count - 4) && frac_val > 0) {
2000 int i, temp_mult = 1, frac_bits = 0;
2002 temp_frac = frac_val * 10;
2003 buffer[prtn++] = '.';
2004 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
2005 /* only reserved 2 bits fraction */
2006 buffer[prtn++] ='0';
2011 * Need to think these cases :
2012 * 1. #echo x.00 > /proc/xxx output result : x
2013 * 2. #echo x.0x > /proc/xxx output result : x.0x
2014 * 3. #echo x.x0 > /proc/xxx output result : x.x
2015 * 4. #echo x.xx > /proc/xxx output result : x.xx
2016 * Only reserved 2 bits fraction.
2018 for (i = 0; i < (5 - prtn); i++)
2021 frac_bits = min((int)count - prtn, 3 - frac_bits);
2022 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
2023 frac_val * temp_mult / mult);
2026 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
2028 if (buffer[prtn] == '.') {
2035 buffer[prtn++] ='\n';
2039 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
2041 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
2044 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
2045 __u64 *val, int mult)
2047 char kernbuf[22], *end, *pbuf;
2048 __u64 whole, frac = 0, units;
2049 unsigned frac_d = 1;
2051 if (count > (sizeof(kernbuf) - 1))
2054 if (cfs_copy_from_user(kernbuf, buffer, count))
2057 kernbuf[count] = '\0';
2064 whole = simple_strtoull(pbuf, &end, 10);
2068 if (end != NULL && *end == '.') {
2072 /* need to limit frac_d to a __u32 */
2073 if (strlen(pbuf) > 10)
2076 frac = simple_strtoull(pbuf, &end, 10);
2077 /* count decimal places */
2078 for (i = 0; i < (end - pbuf); i++)
2095 /* Specified units override the multiplier */
2097 mult = mult < 0 ? -units : units;
2100 do_div(frac, frac_d);
2101 *val = whole * mult + frac;
2105 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent, char *name, mode_t mode,
2106 struct file_operations *seq_fops, void *data)
2108 struct proc_dir_entry *entry;
2111 LPROCFS_WRITE_ENTRY();
2112 entry = create_proc_entry(name, mode, parent);
2114 entry->proc_fops = seq_fops;
2117 LPROCFS_WRITE_EXIT();
2124 EXPORT_SYMBOL(lprocfs_seq_create);
2126 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
2128 struct file_operations *seq_fops,
2131 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2132 mode, seq_fops, data));
2134 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2136 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2138 if (value >= OBD_HIST_MAX)
2139 value = OBD_HIST_MAX - 1;
2141 cfs_spin_lock(&oh->oh_lock);
2142 oh->oh_buckets[value]++;
2143 cfs_spin_unlock(&oh->oh_lock);
2145 EXPORT_SYMBOL(lprocfs_oh_tally);
2147 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2151 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2154 lprocfs_oh_tally(oh, val);
2156 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2158 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2160 unsigned long ret = 0;
2163 for (i = 0; i < OBD_HIST_MAX; i++)
2164 ret += oh->oh_buckets[i];
2167 EXPORT_SYMBOL(lprocfs_oh_sum);
2169 void lprocfs_oh_clear(struct obd_histogram *oh)
2171 cfs_spin_lock(&oh->oh_lock);
2172 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2173 cfs_spin_unlock(&oh->oh_lock);
2175 EXPORT_SYMBOL(lprocfs_oh_clear);
2177 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2178 int count, int *eof, void *data)
2180 struct obd_device *obd = data;
2186 c += cfs_hash_debug_header(page, count);
2187 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2188 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2189 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2190 #ifdef HAVE_QUOTA_SUPPORT
2191 if (obd->u.obt.obt_qctxt.lqc_lqs_hash)
2192 c += cfs_hash_debug_str(obd->u.obt.obt_qctxt.lqc_lqs_hash,
2193 page + c, count - c);
2198 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2200 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2201 int count, int *eof, void *data)
2203 struct obd_device *obd = data;
2206 LASSERT(obd != NULL);
2207 LASSERT(count >= 0);
2209 /* Set start of user data returned to
2210 page + off since the user may have
2211 requested to read much smaller than
2212 what we need to read */
2213 *start = page + off;
2215 /* We know we are allocated a page here.
2216 Also we know that this function will
2217 not need to write more than a page
2218 so we can truncate at CFS_PAGE_SIZE. */
2219 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2221 /* Initialize the page */
2222 memset(page, 0, size);
2224 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2226 if (obd->obd_max_recoverable_clients == 0) {
2227 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2233 /* sampled unlocked, but really... */
2234 if (obd->obd_recovering == 0) {
2235 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2237 if (lprocfs_obd_snprintf(&page, size, &len,
2238 "recovery_start: %lu\n",
2239 obd->obd_recovery_start) <= 0)
2241 if (lprocfs_obd_snprintf(&page, size, &len,
2242 "recovery_duration: %lu\n",
2243 obd->obd_recovery_end -
2244 obd->obd_recovery_start) <= 0)
2246 /* Number of clients that have completed recovery */
2247 if (lprocfs_obd_snprintf(&page, size, &len,
2248 "completed_clients: %d/%d\n",
2249 obd->obd_max_recoverable_clients -
2250 obd->obd_stale_clients,
2251 obd->obd_max_recoverable_clients) <= 0)
2253 if (lprocfs_obd_snprintf(&page, size, &len,
2254 "replayed_requests: %d\n",
2255 obd->obd_replayed_requests) <= 0)
2257 if (lprocfs_obd_snprintf(&page, size, &len,
2258 "last_transno: "LPD64"\n",
2259 obd->obd_next_recovery_transno - 1)<=0)
2261 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2262 obd->obd_version_recov ? "ON" : "OFF")<=0)
2267 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2269 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2270 obd->obd_recovery_start) <= 0)
2272 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2273 cfs_time_current_sec() >= obd->obd_recovery_end ? 0 :
2274 obd->obd_recovery_end - cfs_time_current_sec()) <= 0)
2276 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2277 obd->obd_connected_clients,
2278 obd->obd_max_recoverable_clients) <= 0)
2280 /* Number of clients that have completed recovery */
2281 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2282 cfs_atomic_read(&obd->obd_req_replay_clients))
2285 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2286 cfs_atomic_read(&obd->obd_lock_replay_clients))
2289 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2290 obd->obd_connected_clients -
2291 cfs_atomic_read(&obd->obd_lock_replay_clients))
2294 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2295 obd->obd_stale_clients) <= 0)
2297 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2298 obd->obd_replayed_requests) <= 0)
2300 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2301 obd->obd_requests_queued_for_recovery) <= 0)
2304 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2305 obd->obd_next_recovery_transno) <= 0)
2311 return min(count, len - (int)off);
2313 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2315 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
2316 int count, int *eof, void *data)
2318 struct obd_device *obd = (struct obd_device *)data;
2319 LASSERT(obd != NULL);
2321 return snprintf(page, count, "%d\n",
2322 obd->obd_recovery_timeout);
2324 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
2326 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
2327 unsigned long count, void *data)
2329 struct obd_device *obd = (struct obd_device *)data;
2331 LASSERT(obd != NULL);
2333 rc = lprocfs_write_helper(buffer, count, &val);
2337 obd->obd_recovery_timeout = val;
2340 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
2342 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
2343 int count, int *eof, void *data)
2345 struct obd_device *obd = data;
2346 LASSERT(obd != NULL);
2348 return snprintf(page, count, "%lu\n", obd->obd_recovery_time_hard);
2350 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
2352 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
2353 unsigned long count, void *data)
2355 struct obd_device *obd = data;
2357 LASSERT(obd != NULL);
2359 rc = lprocfs_write_helper(buffer, count, &val);
2363 obd->obd_recovery_time_hard = val;
2366 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
2368 int lprocfs_obd_rd_mntdev(char *page, char **start, off_t off,
2369 int count, int *eof, void *data)
2371 struct obd_device *obd = (struct obd_device *)data;
2373 LASSERT(obd != NULL);
2374 LASSERT(obd->u.obt.obt_vfsmnt->mnt_devname);
2376 return snprintf(page, count, "%s\n",
2377 obd->u.obt.obt_vfsmnt->mnt_devname);
2379 EXPORT_SYMBOL(lprocfs_obd_rd_mntdev);
2381 EXPORT_SYMBOL(lprocfs_register);
2382 EXPORT_SYMBOL(lprocfs_srch);
2383 EXPORT_SYMBOL(lprocfs_remove);
2384 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
2385 EXPORT_SYMBOL(lprocfs_add_vars);
2386 EXPORT_SYMBOL(lprocfs_obd_setup);
2387 EXPORT_SYMBOL(lprocfs_obd_cleanup);
2388 EXPORT_SYMBOL(lprocfs_add_simple);
2389 EXPORT_SYMBOL(lprocfs_add_symlink);
2390 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
2391 EXPORT_SYMBOL(lprocfs_alloc_stats);
2392 EXPORT_SYMBOL(lprocfs_free_stats);
2393 EXPORT_SYMBOL(lprocfs_clear_stats);
2394 EXPORT_SYMBOL(lprocfs_register_stats);
2395 EXPORT_SYMBOL(lprocfs_init_ops_stats);
2396 EXPORT_SYMBOL(lprocfs_init_mps_stats);
2397 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
2398 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
2399 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
2400 EXPORT_SYMBOL(lprocfs_free_obd_stats);
2401 EXPORT_SYMBOL(lprocfs_free_md_stats);
2402 EXPORT_SYMBOL(lprocfs_exp_setup);
2403 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2405 EXPORT_SYMBOL(lprocfs_rd_u64);
2406 EXPORT_SYMBOL(lprocfs_rd_atomic);
2407 EXPORT_SYMBOL(lprocfs_wr_atomic);
2408 EXPORT_SYMBOL(lprocfs_rd_uint);
2409 EXPORT_SYMBOL(lprocfs_wr_uint);
2410 EXPORT_SYMBOL(lprocfs_rd_uuid);
2411 EXPORT_SYMBOL(lprocfs_rd_name);
2412 EXPORT_SYMBOL(lprocfs_rd_fstype);
2413 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
2414 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
2415 EXPORT_SYMBOL(lprocfs_rd_num_exports);
2416 EXPORT_SYMBOL(lprocfs_rd_numrefs);
2417 EXPORT_SYMBOL(lprocfs_at_hist_helper);
2418 EXPORT_SYMBOL(lprocfs_rd_import);
2419 EXPORT_SYMBOL(lprocfs_rd_state);
2420 EXPORT_SYMBOL(lprocfs_rd_timeouts);
2421 EXPORT_SYMBOL(lprocfs_rd_blksize);
2422 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
2423 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
2424 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
2425 EXPORT_SYMBOL(lprocfs_rd_filestotal);
2426 EXPORT_SYMBOL(lprocfs_rd_filesfree);
2428 EXPORT_SYMBOL(lprocfs_write_helper);
2429 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2430 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2431 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2432 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2433 EXPORT_SYMBOL(lprocfs_stats_collect);