4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; If not, see
18 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21 * CA 95054 USA or visit www.sun.com if you need additional information or
27 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Use is subject to license terms.
30 * Copyright (c) 2011, Whamcloud, Inc.
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>
41 #define DEBUG_SUBSYSTEM S_CLASS
44 # include <liblustre.h>
47 #include <obd_class.h>
48 #include <lprocfs_status.h>
49 #include <lustre_fsfilt.h>
50 #include <lustre_log.h>
51 #include <lustre/lustre_idl.h>
55 static int lprocfs_no_percpu_stats = 0;
56 CFS_MODULE_PARM(lprocfs_no_percpu_stats, "i", int, 0644,
57 "Do not alloc percpu data for lprocfs stats");
59 #define MAX_STRING_SIZE 128
61 /* for bug 10866, global variable */
62 CFS_DECLARE_RWSEM(_lprocfs_lock);
63 EXPORT_SYMBOL(_lprocfs_lock);
65 int lprocfs_seq_release(struct inode *inode, struct file *file)
68 return seq_release(inode, file);
70 EXPORT_SYMBOL(lprocfs_seq_release);
72 static struct proc_dir_entry *__lprocfs_srch(struct proc_dir_entry *head,
75 struct proc_dir_entry *temp;
81 while (temp != NULL) {
82 if (strcmp(temp->name, name) == 0) {
91 struct proc_dir_entry *lprocfs_srch(struct proc_dir_entry *head,
94 struct proc_dir_entry *temp;
97 temp = __lprocfs_srch(head, name);
102 /* lprocfs API calls */
104 /* Function that emulates snprintf but also has the side effect of advancing
105 the page pointer for the next write into the buffer, incrementing the total
106 length written to the buffer, and decrementing the size left in the
108 static int lprocfs_obd_snprintf(char **page, int end, int *len,
109 const char *format, ...)
117 va_start(list, format);
118 n = vsnprintf(*page, end - *len, format, list);
121 *page += n; *len += n;
125 cfs_proc_dir_entry_t *lprocfs_add_simple(struct proc_dir_entry *root,
127 read_proc_t *read_proc,
128 write_proc_t *write_proc,
130 struct file_operations *fops)
132 cfs_proc_dir_entry_t *proc;
135 if (root == NULL || name == NULL)
136 return ERR_PTR(-EINVAL);
143 LPROCFS_WRITE_ENTRY();
144 proc = create_proc_entry(name, mode, root);
146 CERROR("LprocFS: No memory to create /proc entry %s", name);
147 LPROCFS_WRITE_EXIT();
148 return ERR_PTR(-ENOMEM);
150 proc->read_proc = read_proc;
151 proc->write_proc = write_proc;
154 proc->proc_fops = fops;
155 LPROCFS_WRITE_EXIT();
159 struct proc_dir_entry *lprocfs_add_symlink(const char *name,
160 struct proc_dir_entry *parent, const char *format, ...)
162 struct proc_dir_entry *entry;
166 if (parent == NULL || format == NULL)
169 OBD_ALLOC_WAIT(dest, MAX_STRING_SIZE + 1);
173 va_start(ap, format);
174 vsnprintf(dest, MAX_STRING_SIZE, format, ap);
177 entry = proc_symlink(name, parent, dest);
179 CERROR("LprocFS: Could not create symbolic link from %s to %s",
182 OBD_FREE(dest, MAX_STRING_SIZE + 1);
186 static ssize_t lprocfs_fops_read(struct file *f, char __user *buf,
187 size_t size, loff_t *ppos)
189 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
190 char *page, *start = NULL;
191 int rc = 0, eof = 1, count;
193 if (*ppos >= CFS_PAGE_SIZE)
196 page = (char *)__get_free_page(GFP_KERNEL);
200 if (LPROCFS_ENTRY_AND_CHECK(dp)) {
205 OBD_FAIL_TIMEOUT(OBD_FAIL_LPROC_REMOVE, 10);
207 rc = dp->read_proc(page, &start, *ppos, CFS_PAGE_SIZE,
213 /* for lustre proc read, the read count must be less than PAGE_SIZE */
222 start = page + *ppos;
223 } else if (start < page) {
227 count = (rc < size) ? rc : size;
228 if (cfs_copy_to_user(buf, start, count)) {
235 free_page((unsigned long)page);
239 static ssize_t lprocfs_fops_write(struct file *f, const char __user *buf,
240 size_t size, loff_t *ppos)
242 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
245 if (LPROCFS_ENTRY_AND_CHECK(dp))
248 rc = dp->write_proc(f, buf, size, dp->data);
253 static struct file_operations lprocfs_generic_fops = {
254 .owner = THIS_MODULE,
255 .read = lprocfs_fops_read,
256 .write = lprocfs_fops_write,
259 int lprocfs_evict_client_open(struct inode *inode, struct file *f)
261 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
262 struct obd_device *obd = dp->data;
264 cfs_atomic_inc(&obd->obd_evict_inprogress);
269 int lprocfs_evict_client_release(struct inode *inode, struct file *f)
271 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
272 struct obd_device *obd = dp->data;
274 cfs_atomic_dec(&obd->obd_evict_inprogress);
275 cfs_waitq_signal(&obd->obd_evict_inprogress_waitq);
280 struct file_operations lprocfs_evict_client_fops = {
281 .owner = THIS_MODULE,
282 .read = lprocfs_fops_read,
283 .write = lprocfs_fops_write,
284 .open = lprocfs_evict_client_open,
285 .release = lprocfs_evict_client_release,
287 EXPORT_SYMBOL(lprocfs_evict_client_fops);
292 * \param root [in] The parent proc entry on which new entry will be added.
293 * \param list [in] Array of proc entries to be added.
294 * \param data [in] The argument to be passed when entries read/write routines
295 * are called through /proc file.
297 * \retval 0 on success
300 int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list,
305 if (root == NULL || list == NULL)
308 LPROCFS_WRITE_ENTRY();
309 while (list->name != NULL) {
310 struct proc_dir_entry *cur_root, *proc;
311 char *pathcopy, *cur, *next, pathbuf[64];
312 int pathsize = strlen(list->name) + 1;
317 /* need copy of path for strsep */
318 if (strlen(list->name) > sizeof(pathbuf) - 1) {
319 OBD_ALLOC(pathcopy, pathsize);
320 if (pathcopy == NULL)
321 GOTO(out, rc = -ENOMEM);
327 strcpy(pathcopy, list->name);
329 while (cur_root != NULL && (cur = strsep(&next, "/"))) {
330 if (*cur =='\0') /* skip double/trailing "/" */
333 proc = __lprocfs_srch(cur_root, cur);
334 CDEBUG(D_OTHER, "cur_root=%s, cur=%s, next=%s, (%s)\n",
335 cur_root->name, cur, next,
336 (proc ? "exists" : "new"));
338 cur_root = (proc ? proc :
339 proc_mkdir(cur, cur_root));
340 } else if (proc == NULL) {
342 if (list->proc_mode != 0000) {
343 mode = list->proc_mode;
347 if (list->write_fptr)
350 proc = create_proc_entry(cur, mode, cur_root);
354 if (pathcopy != pathbuf)
355 OBD_FREE(pathcopy, pathsize);
357 if (cur_root == NULL || proc == NULL) {
358 CERROR("LprocFS: No memory to create /proc entry %s",
360 GOTO(out, rc = -ENOMEM);
364 proc->proc_fops = list->fops;
366 proc->proc_fops = &lprocfs_generic_fops;
367 proc->read_proc = list->read_fptr;
368 proc->write_proc = list->write_fptr;
369 proc->data = (list->data ? list->data : data);
373 LPROCFS_WRITE_EXIT();
377 void lprocfs_remove(struct proc_dir_entry **rooth)
379 struct proc_dir_entry *root = *rooth;
380 struct proc_dir_entry *temp = root;
381 struct proc_dir_entry *rm_entry;
382 struct proc_dir_entry *parent;
388 parent = root->parent;
389 LASSERT(parent != NULL);
390 LPROCFS_WRITE_ENTRY(); /* search vs remove race */
393 while (temp->subdir != NULL)
399 /* Memory corruption once caused this to fail, and
400 without this LASSERT we would loop here forever. */
401 LASSERTF(strlen(rm_entry->name) == rm_entry->namelen,
402 "0x%p %s/%s len %d\n", rm_entry, temp->name,
403 rm_entry->name, (int)strlen(rm_entry->name));
405 #ifdef HAVE_PROCFS_USERS
406 /* if procfs uses user count to synchronize deletion of
407 * proc entry, there is no protection for rm_entry->data,
408 * then lprocfs_fops_read and lprocfs_fops_write maybe
409 * call proc_dir_entry->read_proc (or write_proc) with
410 * proc_dir_entry->data == NULL, then cause kernel Oops.
411 * see bug19706 for detailed information */
413 /* procfs won't free rm_entry->data if it isn't a LINK,
414 * and Lustre won't use rm_entry->data if it is a LINK */
415 if (S_ISLNK(rm_entry->mode))
416 rm_entry->data = NULL;
418 /* Now, the rm_entry->deleted flags is protected
419 * by _lprocfs_lock. */
420 rm_entry->data = NULL;
422 remove_proc_entry(rm_entry->name, temp);
426 LPROCFS_WRITE_EXIT();
429 void lprocfs_remove_proc_entry(const char *name, struct proc_dir_entry *parent)
431 LASSERT(parent != NULL);
432 remove_proc_entry(name, parent);
435 struct proc_dir_entry *lprocfs_register(const char *name,
436 struct proc_dir_entry *parent,
437 struct lprocfs_vars *list, void *data)
439 struct proc_dir_entry *newchild;
441 newchild = lprocfs_srch(parent, name);
442 if (newchild != NULL) {
443 CERROR(" Lproc: Attempting to register %s more than once \n",
445 return ERR_PTR(-EALREADY);
448 newchild = proc_mkdir(name, parent);
449 if (newchild != NULL && list != NULL) {
450 int rc = lprocfs_add_vars(newchild, list, data);
452 lprocfs_remove(&newchild);
459 /* Generic callbacks */
460 int lprocfs_rd_uint(char *page, char **start, off_t off,
461 int count, int *eof, void *data)
463 unsigned int *temp = data;
464 return snprintf(page, count, "%u\n", *temp);
467 int lprocfs_wr_uint(struct file *file, const char *buffer,
468 unsigned long count, void *data)
471 char dummy[MAX_STRING_SIZE + 1], *end;
474 dummy[MAX_STRING_SIZE] = '\0';
475 if (cfs_copy_from_user(dummy, buffer, MAX_STRING_SIZE))
478 tmp = simple_strtoul(dummy, &end, 0);
482 *p = (unsigned int)tmp;
486 int lprocfs_rd_u64(char *page, char **start, off_t off,
487 int count, int *eof, void *data)
489 LASSERT(data != NULL);
491 return snprintf(page, count, LPU64"\n", *(__u64 *)data);
494 int lprocfs_rd_atomic(char *page, char **start, off_t off,
495 int count, int *eof, void *data)
497 cfs_atomic_t *atom = data;
498 LASSERT(atom != NULL);
500 return snprintf(page, count, "%d\n", cfs_atomic_read(atom));
503 int lprocfs_wr_atomic(struct file *file, const char *buffer,
504 unsigned long count, void *data)
506 cfs_atomic_t *atm = data;
510 rc = lprocfs_write_helper(buffer, count, &val);
517 cfs_atomic_set(atm, val);
521 int lprocfs_rd_uuid(char *page, char **start, off_t off, int count,
522 int *eof, void *data)
524 struct obd_device *obd = data;
526 LASSERT(obd != NULL);
528 return snprintf(page, count, "%s\n", obd->obd_uuid.uuid);
531 int lprocfs_rd_name(char *page, char **start, off_t off, int count,
532 int *eof, void *data)
534 struct obd_device *dev = data;
536 LASSERT(dev != NULL);
537 LASSERT(dev->obd_name != NULL);
539 return snprintf(page, count, "%s\n", dev->obd_name);
542 int lprocfs_rd_fstype(char *page, char **start, off_t off, int count, int *eof,
545 struct obd_device *obd = data;
547 LASSERT(obd != NULL);
548 LASSERT(obd->obd_fsops != NULL);
549 LASSERT(obd->obd_fsops->fs_type != NULL);
550 return snprintf(page, count, "%s\n", obd->obd_fsops->fs_type);
553 int lprocfs_rd_blksize(char *page, char **start, off_t off, int count,
554 int *eof, void *data)
556 struct obd_device *obd = data;
557 struct obd_statfs osfs;
558 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
559 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
563 rc = snprintf(page, count, "%u\n", osfs.os_bsize);
568 int lprocfs_rd_kbytestotal(char *page, char **start, off_t off, int count,
569 int *eof, void *data)
571 struct obd_device *obd = data;
572 struct obd_statfs osfs;
573 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
574 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
577 __u32 blk_size = osfs.os_bsize >> 10;
578 __u64 result = osfs.os_blocks;
580 while (blk_size >>= 1)
584 rc = snprintf(page, count, LPU64"\n", result);
589 int lprocfs_rd_kbytesfree(char *page, char **start, off_t off, int count,
590 int *eof, void *data)
592 struct obd_device *obd = data;
593 struct obd_statfs osfs;
594 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
595 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
598 __u32 blk_size = osfs.os_bsize >> 10;
599 __u64 result = osfs.os_bfree;
601 while (blk_size >>= 1)
605 rc = snprintf(page, count, LPU64"\n", result);
610 int lprocfs_rd_kbytesavail(char *page, char **start, off_t off, int count,
611 int *eof, void *data)
613 struct obd_device *obd = data;
614 struct obd_statfs osfs;
615 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
616 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
619 __u32 blk_size = osfs.os_bsize >> 10;
620 __u64 result = osfs.os_bavail;
622 while (blk_size >>= 1)
626 rc = snprintf(page, count, LPU64"\n", result);
631 int lprocfs_rd_filestotal(char *page, char **start, off_t off, int count,
632 int *eof, void *data)
634 struct obd_device *obd = data;
635 struct obd_statfs osfs;
636 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
637 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
641 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
647 int lprocfs_rd_filesfree(char *page, char **start, off_t off, int count,
648 int *eof, void *data)
650 struct obd_device *obd = data;
651 struct obd_statfs osfs;
652 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
653 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
657 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
662 int lprocfs_rd_server_uuid(char *page, char **start, off_t off, int count,
663 int *eof, void *data)
665 struct obd_device *obd = data;
666 struct obd_import *imp;
667 char *imp_state_name = NULL;
670 LASSERT(obd != NULL);
671 LPROCFS_CLIMP_CHECK(obd);
672 imp = obd->u.cli.cl_import;
673 imp_state_name = ptlrpc_import_state_name(imp->imp_state);
675 rc = snprintf(page, count, "%s\t%s%s\n",
676 obd2cli_tgt(obd), imp_state_name,
677 imp->imp_deactive ? "\tDEACTIVATED" : "");
679 LPROCFS_CLIMP_EXIT(obd);
683 int lprocfs_rd_conn_uuid(char *page, char **start, off_t off, int count,
684 int *eof, void *data)
686 struct obd_device *obd = data;
687 struct ptlrpc_connection *conn;
690 LASSERT(obd != NULL);
692 LPROCFS_CLIMP_CHECK(obd);
693 conn = obd->u.cli.cl_import->imp_connection;
695 if (conn && obd->u.cli.cl_import) {
696 rc = snprintf(page, count, "%s\n",
697 conn->c_remote_uuid.uuid);
699 rc = snprintf(page, count, "%s\n", "<none>");
702 LPROCFS_CLIMP_EXIT(obd);
706 /** add up per-cpu counters */
707 void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
708 struct lprocfs_counter *cnt)
710 unsigned int num_cpu;
711 struct lprocfs_counter t;
712 struct lprocfs_counter *percpu_cntr;
715 memset(cnt, 0, sizeof(*cnt));
718 /* set count to 1 to avoid divide-by-zero errs in callers */
723 cnt->lc_min = LC_MIN_INIT;
725 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
727 for (i = 0; i < num_cpu; i++) {
728 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[idx];
731 centry = cfs_atomic_read(&percpu_cntr-> \
733 t.lc_count = percpu_cntr->lc_count;
734 t.lc_sum = percpu_cntr->lc_sum;
735 t.lc_min = percpu_cntr->lc_min;
736 t.lc_max = percpu_cntr->lc_max;
737 t.lc_sumsquare = percpu_cntr->lc_sumsquare;
738 } while (centry != cfs_atomic_read(&percpu_cntr->lc_cntl. \
740 centry != cfs_atomic_read(&percpu_cntr->lc_cntl. \
742 cnt->lc_count += t.lc_count;
743 cnt->lc_sum += t.lc_sum;
744 if (t.lc_min < cnt->lc_min)
745 cnt->lc_min = t.lc_min;
746 if (t.lc_max > cnt->lc_max)
747 cnt->lc_max = t.lc_max;
748 cnt->lc_sumsquare += t.lc_sumsquare;
751 cnt->lc_units = stats->ls_percpu[0]->lp_cntr[idx].lc_units;
752 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU);
756 * Append a space separated list of current set flags to str.
758 #define flag2str(flag) \
759 if (imp->imp_##flag && max - len > 0) \
760 len += snprintf(str + len, max - len, "%s" #flag, len ? ", " : "");
761 static int obd_import_flags2str(struct obd_import *imp, char *str, int max)
765 if (imp->imp_obd->obd_no_recov)
766 len += snprintf(str, max - len, "no_recov");
770 flag2str(replayable);
776 static const char *obd_connect_names[] = {
790 "join_file(obsolete)",
794 "remote_client_by_force",
803 "mds_mds_connection",
806 "alt_checksum_algorithm",
825 int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
830 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
832 ret += snprintf(page + ret, count - ret, "%s%s",
833 ret ? sep : "", obd_connect_names[i]);
835 if (flags & ~(mask - 1))
836 ret += snprintf(page + ret, count - ret,
837 "%sunknown flags "LPX64,
838 ret ? sep : "", flags & ~(mask - 1));
841 EXPORT_SYMBOL(obd_connect_flags2str);
843 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
844 int *eof, void *data)
846 struct lprocfs_counter ret;
847 struct obd_device *obd = (struct obd_device *)data;
848 struct obd_import *imp;
849 struct obd_import_conn *conn;
852 LASSERT(obd != NULL);
853 LPROCFS_CLIMP_CHECK(obd);
854 imp = obd->u.cli.cl_import;
857 i = snprintf(page, count,
866 ptlrpc_import_state_name(imp->imp_state),
867 imp->imp_connect_data.ocd_instance);
868 i += obd_connect_flags2str(page + i, count - i,
869 imp->imp_connect_data.ocd_connect_flags,
871 i += snprintf(page + i, count - i,
874 i += obd_import_flags2str(imp, page + i, count - i);
876 i += snprintf(page + i, count - i,
879 " failover_nids: [");
880 cfs_spin_lock(&imp->imp_lock);
882 cfs_list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
883 i += snprintf(page + i, count - i, "%s%s", j ? ", " : "",
884 libcfs_nid2str(conn->oic_conn->c_peer.nid));
887 cfs_spin_unlock(&imp->imp_lock);
888 i += snprintf(page + i, count - i,
890 " current_connection: %s\n"
891 " connection_attempts: %u\n"
893 " in-progress_invalidations: %u\n",
894 libcfs_nid2str(imp->imp_connection->c_peer.nid),
897 cfs_atomic_read(&imp->imp_inval_count));
899 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
900 if (ret.lc_count != 0) {
901 /* first argument to do_div MUST be __u64 */
902 __u64 sum = ret.lc_sum;
903 do_div(sum, ret.lc_count);
907 i += snprintf(page + i, count - i,
910 " unregistering: %u\n"
912 " avg_waittime: "LPU64" %s\n",
913 cfs_atomic_read(&imp->imp_inflight),
914 cfs_atomic_read(&imp->imp_unregistering),
915 cfs_atomic_read(&imp->imp_timeouts),
916 ret.lc_sum, ret.lc_units);
919 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
920 if (imp->imp_at.iat_portal[j] == 0)
922 k = max_t(unsigned int, k,
923 at_get(&imp->imp_at.iat_service_estimate[j]));
925 i += snprintf(page + i, count - i,
926 " service_estimates:\n"
927 " services: %u sec\n"
928 " network: %u sec\n",
930 at_get(&imp->imp_at.iat_net_latency));
932 i += snprintf(page + i, count - i,
934 " last_replay: "LPU64"\n"
935 " peer_committed: "LPU64"\n"
936 " last_checked: "LPU64"\n",
937 imp->imp_last_replay_transno,
938 imp->imp_peer_committed_transno,
939 imp->imp_last_transno_checked);
942 for (rw = 0; rw <= 1; rw++) {
943 lprocfs_stats_collect(obd->obd_svc_stats,
944 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
946 if (ret.lc_sum > 0 && ret.lc_count > 0) {
947 /* first argument to do_div MUST be __u64 */
948 __u64 sum = ret.lc_sum;
949 do_div(sum, ret.lc_count);
951 i += snprintf(page + i, count - i,
952 " %s_data_averages:\n"
953 " bytes_per_rpc: "LPU64"\n",
954 rw ? "write" : "read",
958 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
959 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
960 if (ret.lc_sum > 0 && ret.lc_count != 0) {
961 /* first argument to do_div MUST be __u64 */
962 __u64 sum = ret.lc_sum;
963 do_div(sum, ret.lc_count);
965 i += snprintf(page + i, count - i,
966 " %s_per_rpc: "LPU64"\n",
967 ret.lc_units, ret.lc_sum);
970 i += snprintf(page + i, count - i,
971 " MB_per_sec: %u.%.02u\n",
972 k / j, (100 * k / j) % 100);
976 LPROCFS_CLIMP_EXIT(obd);
980 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
981 int *eof, void *data)
983 struct obd_device *obd = (struct obd_device *)data;
984 struct obd_import *imp;
987 LASSERT(obd != NULL);
988 LPROCFS_CLIMP_CHECK(obd);
989 imp = obd->u.cli.cl_import;
992 i = snprintf(page, count, "current_state: %s\n",
993 ptlrpc_import_state_name(imp->imp_state));
994 i += snprintf(page + i, count - i,
996 k = imp->imp_state_hist_idx;
997 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
998 struct import_state_hist *ish =
999 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
1000 if (ish->ish_state == 0)
1002 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
1004 ptlrpc_import_state_name(ish->ish_state));
1007 LPROCFS_CLIMP_EXIT(obd);
1011 int lprocfs_at_hist_helper(char *page, int count, int rc,
1012 struct adaptive_timeout *at)
1015 for (i = 0; i < AT_BINS; i++)
1016 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
1017 rc += snprintf(page + rc, count - rc, "\n");
1021 /* See also ptlrpc_lprocfs_rd_timeouts */
1022 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
1023 int *eof, void *data)
1025 struct obd_device *obd = (struct obd_device *)data;
1026 struct obd_import *imp;
1027 unsigned int cur, worst;
1032 LASSERT(obd != NULL);
1033 LPROCFS_CLIMP_CHECK(obd);
1034 imp = obd->u.cli.cl_import;
1037 now = cfs_time_current_sec();
1039 /* Some network health info for kicks */
1040 s2dhms(&ts, now - imp->imp_last_reply_time);
1041 rc += snprintf(page + rc, count - rc,
1042 "%-10s : %ld, "DHMS_FMT" ago\n",
1043 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
1045 cur = at_get(&imp->imp_at.iat_net_latency);
1046 worst = imp->imp_at.iat_net_latency.at_worst_ever;
1047 worstt = imp->imp_at.iat_net_latency.at_worst_time;
1048 s2dhms(&ts, now - worstt);
1049 rc += snprintf(page + rc, count - rc,
1050 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
1051 "network", cur, worst, worstt, DHMS_VARS(&ts));
1052 rc = lprocfs_at_hist_helper(page, count, rc,
1053 &imp->imp_at.iat_net_latency);
1055 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
1056 if (imp->imp_at.iat_portal[i] == 0)
1058 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
1059 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
1060 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
1061 s2dhms(&ts, now - worstt);
1062 rc += snprintf(page + rc, count - rc,
1063 "portal %-2d : cur %3u worst %3u (at %ld, "
1064 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
1065 cur, worst, worstt, DHMS_VARS(&ts));
1066 rc = lprocfs_at_hist_helper(page, count, rc,
1067 &imp->imp_at.iat_service_estimate[i]);
1070 LPROCFS_CLIMP_EXIT(obd);
1074 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1075 int count, int *eof, void *data)
1077 struct obd_device *obd = data;
1081 LPROCFS_CLIMP_CHECK(obd);
1082 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1083 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1084 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1085 ret += snprintf(page + ret, count - ret, "\n");
1086 LPROCFS_CLIMP_EXIT(obd);
1089 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1091 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1092 int *eof, void *data)
1094 struct obd_device *obd = data;
1096 LASSERT(obd != NULL);
1098 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1101 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1102 int *eof, void *data)
1104 struct obd_type *class = (struct obd_type*) data;
1106 LASSERT(class != NULL);
1108 return snprintf(page, count, "%d\n", class->typ_refcnt);
1111 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1115 LASSERT(obd != NULL);
1116 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1117 LASSERT(obd->obd_type->typ_procroot != NULL);
1119 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1120 obd->obd_type->typ_procroot,
1122 if (IS_ERR(obd->obd_proc_entry)) {
1123 rc = PTR_ERR(obd->obd_proc_entry);
1124 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1125 obd->obd_proc_entry = NULL;
1130 int lprocfs_obd_cleanup(struct obd_device *obd)
1134 if (obd->obd_proc_exports_entry) {
1135 /* Should be no exports left */
1136 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1137 lprocfs_remove(&obd->obd_proc_exports_entry);
1138 obd->obd_proc_exports_entry = NULL;
1140 if (obd->obd_proc_entry) {
1141 lprocfs_remove(&obd->obd_proc_entry);
1142 obd->obd_proc_entry = NULL;
1147 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1149 CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
1150 client_stat->nid_proc, client_stat->nid_stats,
1151 client_stat->nid_brw_stats);
1153 LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
1154 "nid %s:count %d\n", libcfs_nid2str(client_stat->nid),
1155 atomic_read(&client_stat->nid_exp_ref_count));
1157 if (client_stat->nid_proc)
1158 lprocfs_remove(&client_stat->nid_proc);
1160 if (client_stat->nid_stats)
1161 lprocfs_free_stats(&client_stat->nid_stats);
1163 if (client_stat->nid_brw_stats)
1164 OBD_FREE_PTR(client_stat->nid_brw_stats);
1166 if (client_stat->nid_ldlm_stats)
1167 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1169 OBD_FREE_PTR(client_stat);
1174 void lprocfs_free_per_client_stats(struct obd_device *obd)
1176 cfs_hash_t *hash = obd->obd_nid_stats_hash;
1177 struct nid_stat *stat;
1180 /* we need extra list - because hash_exit called to early */
1181 /* not need locking because all clients is died */
1182 while (!cfs_list_empty(&obd->obd_nid_stats)) {
1183 stat = cfs_list_entry(obd->obd_nid_stats.next,
1184 struct nid_stat, nid_list);
1185 cfs_list_del_init(&stat->nid_list);
1186 cfs_hash_del(hash, &stat->nid, &stat->nid_hash);
1187 lprocfs_free_client_stats(stat);
1192 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1193 enum lprocfs_stats_flags flags)
1195 struct lprocfs_stats *stats;
1196 unsigned int percpusize;
1198 unsigned int num_cpu;
1203 if (lprocfs_no_percpu_stats != 0)
1204 flags |= LPROCFS_STATS_FLAG_NOPERCPU;
1206 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1209 num_cpu = cfs_num_possible_cpus();
1211 OBD_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
1215 if (flags & LPROCFS_STATS_FLAG_NOPERCPU) {
1216 stats->ls_flags = flags;
1217 cfs_spin_lock_init(&stats->ls_lock);
1218 /* Use this lock only if there are no percpu areas */
1220 stats->ls_flags = 0;
1223 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
1225 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1227 for (i = 0; i < num_cpu; i++) {
1228 OBD_ALLOC(stats->ls_percpu[i], percpusize);
1229 if (stats->ls_percpu[i] == NULL) {
1230 for (j = 0; j < i; j++) {
1231 OBD_FREE(stats->ls_percpu[j], percpusize);
1232 stats->ls_percpu[j] = NULL;
1237 if (stats->ls_percpu[0] == NULL) {
1238 OBD_FREE(stats, offsetof(typeof(*stats),
1239 ls_percpu[num_cpu]));
1243 stats->ls_num = num;
1247 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1249 struct lprocfs_stats *stats = *statsh;
1250 unsigned int num_cpu;
1251 unsigned int percpusize;
1254 if (stats == NULL || stats->ls_num == 0)
1258 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1261 num_cpu = cfs_num_possible_cpus();
1263 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
1265 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1266 for (i = 0; i < num_cpu; i++)
1267 OBD_FREE(stats->ls_percpu[i], percpusize);
1268 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
1271 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1273 struct lprocfs_counter *percpu_cntr;
1275 unsigned int num_cpu;
1277 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1279 for (i = 0; i < num_cpu; i++) {
1280 for (j = 0; j < stats->ls_num; j++) {
1281 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
1282 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_entry);
1283 percpu_cntr->lc_count = 0;
1284 percpu_cntr->lc_sum = 0;
1285 percpu_cntr->lc_min = LC_MIN_INIT;
1286 percpu_cntr->lc_max = 0;
1287 percpu_cntr->lc_sumsquare = 0;
1288 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_exit);
1292 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU);
1295 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1296 size_t len, loff_t *off)
1298 struct seq_file *seq = file->private_data;
1299 struct lprocfs_stats *stats = seq->private;
1301 lprocfs_clear_stats(stats);
1306 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1308 struct lprocfs_stats *stats = p->private;
1309 /* return 1st cpu location */
1310 return (*pos >= stats->ls_num) ? NULL :
1311 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1314 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1318 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1320 struct lprocfs_stats *stats = p->private;
1322 return (*pos >= stats->ls_num) ? NULL :
1323 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1326 /* seq file export of one lprocfs counter */
1327 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1329 struct lprocfs_stats *stats = p->private;
1330 struct lprocfs_counter *cntr = v;
1331 struct lprocfs_counter ret;
1334 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
1336 cfs_gettimeofday(&now);
1337 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1338 "snapshot_time", now.tv_sec, now.tv_usec);
1342 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
1344 lprocfs_stats_collect(stats, idx, &ret);
1346 if (ret.lc_count == 0)
1349 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", cntr->lc_name,
1350 ret.lc_count, cntr->lc_units);
1355 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
1356 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1357 ret.lc_min, ret.lc_max, ret.lc_sum);
1360 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
1361 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1365 rc = seq_printf(p, "\n");
1367 return (rc < 0) ? rc : 0;
1370 struct seq_operations lprocfs_stats_seq_sops = {
1371 start: lprocfs_stats_seq_start,
1372 stop: lprocfs_stats_seq_stop,
1373 next: lprocfs_stats_seq_next,
1374 show: lprocfs_stats_seq_show,
1377 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1379 struct proc_dir_entry *dp = PDE(inode);
1380 struct seq_file *seq;
1383 if (LPROCFS_ENTRY_AND_CHECK(dp))
1386 rc = seq_open(file, &lprocfs_stats_seq_sops);
1391 seq = file->private_data;
1392 seq->private = dp->data;
1396 struct file_operations lprocfs_stats_seq_fops = {
1397 .owner = THIS_MODULE,
1398 .open = lprocfs_stats_seq_open,
1400 .write = lprocfs_stats_seq_write,
1401 .llseek = seq_lseek,
1402 .release = lprocfs_seq_release,
1405 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1406 struct lprocfs_stats *stats)
1408 struct proc_dir_entry *entry;
1409 LASSERT(root != NULL);
1411 LPROCFS_WRITE_ENTRY();
1412 entry = create_proc_entry(name, 0644, root);
1414 entry->proc_fops = &lprocfs_stats_seq_fops;
1415 entry->data = stats;
1418 LPROCFS_WRITE_EXIT();
1426 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1427 unsigned conf, const char *name, const char *units)
1429 struct lprocfs_counter *c;
1431 unsigned int num_cpu;
1433 LASSERT(stats != NULL);
1435 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1437 for (i = 0; i < num_cpu; i++) {
1438 c = &(stats->ls_percpu[i]->lp_cntr[index]);
1439 c->lc_config = conf;
1442 c->lc_min = LC_MIN_INIT;
1445 c->lc_units = units;
1448 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU);
1450 EXPORT_SYMBOL(lprocfs_counter_init);
1452 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1454 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1455 LASSERT(coffset < stats->ls_num); \
1456 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1459 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1461 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1462 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1463 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1464 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1465 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1466 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1467 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1468 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1469 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1470 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1471 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1472 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1473 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1474 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1475 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1476 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1477 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1478 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1479 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
1480 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1481 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1482 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1483 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1484 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1485 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1486 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1487 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1488 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1489 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1490 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1491 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1492 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1493 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1494 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1495 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1496 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1497 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1498 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1499 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1500 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1501 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1502 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1503 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1504 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1505 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
1506 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1507 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1508 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1509 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1510 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1511 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1512 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1513 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1514 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1515 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1516 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1517 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1518 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1519 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1520 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1521 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1522 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quota_adjust_qunit);
1523 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1524 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1525 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1526 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1527 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1528 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1529 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1532 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1534 struct lprocfs_stats *stats;
1535 unsigned int num_stats;
1538 LASSERT(obd->obd_stats == NULL);
1539 LASSERT(obd->obd_proc_entry != NULL);
1540 LASSERT(obd->obd_cntr_base == 0);
1542 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1543 num_private_stats - 1 /* o_owner */;
1544 stats = lprocfs_alloc_stats(num_stats, 0);
1548 lprocfs_init_ops_stats(num_private_stats, stats);
1550 for (i = num_private_stats; i < num_stats; i++) {
1551 /* If this LBUGs, it is likely that an obd
1552 * operation was added to struct obd_ops in
1553 * <obd.h>, and that the corresponding line item
1554 * LPROCFS_OBD_OP_INIT(.., .., opname)
1555 * is missing from the list above. */
1556 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1557 "Missing obd_stat initializer obd_op "
1558 "operation at offset %d.\n", i - num_private_stats);
1560 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1562 lprocfs_free_stats(&stats);
1564 obd->obd_stats = stats;
1565 obd->obd_cntr_base = num_private_stats;
1570 void lprocfs_free_obd_stats(struct obd_device *obd)
1573 lprocfs_free_stats(&obd->obd_stats);
1576 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1578 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1579 LASSERT(coffset < stats->ls_num); \
1580 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1583 void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats)
1585 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1586 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1587 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
1588 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1589 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1590 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1591 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1592 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1593 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1594 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1595 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1596 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1597 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1598 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1599 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1600 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1601 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1602 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1603 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1604 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1605 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1606 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1607 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1608 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1609 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1610 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1611 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1612 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1613 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1614 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1615 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1616 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1619 int lprocfs_alloc_md_stats(struct obd_device *obd,
1620 unsigned num_private_stats)
1622 struct lprocfs_stats *stats;
1623 unsigned int num_stats;
1626 LASSERT(obd->md_stats == NULL);
1627 LASSERT(obd->obd_proc_entry != NULL);
1628 LASSERT(obd->md_cntr_base == 0);
1630 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1632 stats = lprocfs_alloc_stats(num_stats, 0);
1636 lprocfs_init_mps_stats(num_private_stats, stats);
1638 for (i = num_private_stats; i < num_stats; i++) {
1639 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1640 CERROR("Missing md_stat initializer md_op "
1641 "operation at offset %d. Aborting.\n",
1642 i - num_private_stats);
1646 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1648 lprocfs_free_stats(&stats);
1650 obd->md_stats = stats;
1651 obd->md_cntr_base = num_private_stats;
1656 void lprocfs_free_md_stats(struct obd_device *obd)
1658 struct lprocfs_stats *stats = obd->md_stats;
1660 if (stats != NULL) {
1661 obd->md_stats = NULL;
1662 obd->md_cntr_base = 0;
1663 lprocfs_free_stats(&stats);
1667 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1669 lprocfs_counter_init(ldlm_stats,
1670 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1671 0, "ldlm_enqueue", "reqs");
1672 lprocfs_counter_init(ldlm_stats,
1673 LDLM_CONVERT - LDLM_FIRST_OPC,
1674 0, "ldlm_convert", "reqs");
1675 lprocfs_counter_init(ldlm_stats,
1676 LDLM_CANCEL - LDLM_FIRST_OPC,
1677 0, "ldlm_cancel", "reqs");
1678 lprocfs_counter_init(ldlm_stats,
1679 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1680 0, "ldlm_bl_callback", "reqs");
1681 lprocfs_counter_init(ldlm_stats,
1682 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1683 0, "ldlm_cp_callback", "reqs");
1684 lprocfs_counter_init(ldlm_stats,
1685 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1686 0, "ldlm_gl_callback", "reqs");
1689 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1690 int *eof, void *data)
1692 struct obd_export *exp = data;
1693 LASSERT(exp != NULL);
1695 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1698 struct exp_uuid_cb_data {
1706 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1707 int count, int *eof, int *len)
1709 cb_data->page = page;
1710 cb_data->count = count;
1715 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1716 cfs_hlist_node_t *hnode, void *cb_data)
1719 struct obd_export *exp = cfs_hash_object(hs, hnode);
1720 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1722 if (exp->exp_nid_stats)
1723 *data->len += snprintf((data->page + *data->len),
1724 data->count, "%s\n",
1725 obd_uuid2str(&exp->exp_client_uuid));
1729 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1730 int *eof, void *data)
1732 struct nid_stat *stats = (struct nid_stat *)data;
1733 struct exp_uuid_cb_data cb_data;
1734 struct obd_device *obd = stats->nid_obd;
1739 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1740 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1741 lprocfs_exp_print_uuid, &cb_data);
1742 return (*cb_data.len);
1745 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1746 cfs_hlist_node_t *hnode, void *cb_data)
1749 struct exp_uuid_cb_data *data = cb_data;
1750 struct obd_export *exp = cfs_hash_object(hs, hnode);
1752 if (exp->exp_lock_hash != NULL) {
1754 *data->len += cfs_hash_debug_header(data->page,
1757 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1764 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1765 int *eof, void *data)
1767 struct nid_stat *stats = (struct nid_stat *)data;
1768 struct exp_uuid_cb_data cb_data;
1769 struct obd_device *obd = stats->nid_obd;
1774 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1776 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1777 lprocfs_exp_print_hash, &cb_data);
1778 return (*cb_data.len);
1781 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1782 int count, int *eof, void *data)
1785 return snprintf(page, count, "%s\n",
1786 "Write into this file to clear all nid stats and "
1787 "stale nid entries");
1789 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1791 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1793 struct nid_stat *stat = obj;
1797 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
1798 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 1) {
1799 /* object has only hash references. */
1800 cfs_spin_lock(&stat->nid_obd->obd_nid_lock);
1801 cfs_list_move(&stat->nid_list, data);
1802 cfs_spin_unlock(&stat->nid_obd->obd_nid_lock);
1805 /* we has reference to object - only clear data*/
1806 if (stat->nid_stats)
1807 lprocfs_clear_stats(stat->nid_stats);
1809 if (stat->nid_brw_stats) {
1810 for (i = 0; i < BRW_LAST; i++)
1811 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
1816 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1817 unsigned long count, void *data)
1819 struct obd_device *obd = (struct obd_device *)data;
1820 struct nid_stat *client_stat;
1821 CFS_LIST_HEAD(free_list);
1823 cfs_hash_cond_del(obd->obd_nid_stats_hash,
1824 lprocfs_nid_stats_clear_write_cb, &free_list);
1826 while (!cfs_list_empty(&free_list)) {
1827 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
1829 cfs_list_del_init(&client_stat->nid_list);
1830 lprocfs_free_client_stats(client_stat);
1835 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1837 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1839 struct nid_stat *new_stat, *old_stat;
1840 struct obd_device *obd = NULL;
1841 cfs_proc_dir_entry_t *entry;
1842 char *buffer = NULL;
1848 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1849 !exp->exp_obd->obd_nid_stats_hash)
1852 /* not test against zero because eric say:
1853 * You may only test nid against another nid, or LNET_NID_ANY.
1854 * Anything else is nonsense.*/
1855 if (!nid || *nid == LNET_NID_ANY)
1860 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
1862 OBD_ALLOC_PTR(new_stat);
1863 if (new_stat == NULL)
1866 new_stat->nid = *nid;
1867 new_stat->nid_obd = exp->exp_obd;
1868 /* we need set default refcount to 1 to balance obd_disconnect */
1869 cfs_atomic_set(&new_stat->nid_exp_ref_count, 1);
1871 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
1872 nid, &new_stat->nid_hash);
1873 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
1874 old_stat, libcfs_nid2str(*nid),
1875 cfs_atomic_read(&new_stat->nid_exp_ref_count));
1877 /* We need to release old stats because lprocfs_exp_cleanup() hasn't
1878 * been and will never be called. */
1879 if (exp->exp_nid_stats) {
1880 nidstat_putref(exp->exp_nid_stats);
1881 exp->exp_nid_stats = NULL;
1884 /* Return -EALREADY here so that we know that the /proc
1885 * entry already has been created */
1886 if (old_stat != new_stat) {
1887 exp->exp_nid_stats = old_stat;
1888 GOTO(destroy_new, rc = -EALREADY);
1890 /* not found - create */
1891 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
1893 GOTO(destroy_new, rc = -ENOMEM);
1895 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
1896 new_stat->nid_proc = lprocfs_register(buffer,
1897 obd->obd_proc_exports_entry,
1899 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
1901 if (new_stat->nid_proc == NULL) {
1902 CERROR("Error making export directory for nid %s\n",
1903 libcfs_nid2str(*nid));
1904 GOTO(destroy_new_ns, rc = -ENOMEM);
1907 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
1908 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
1909 if (IS_ERR(entry)) {
1910 CWARN("Error adding the NID stats file\n");
1911 rc = PTR_ERR(entry);
1912 GOTO(destroy_new_ns, rc);
1915 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
1916 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
1917 if (IS_ERR(entry)) {
1918 CWARN("Error adding the hash file\n");
1919 rc = PTR_ERR(entry);
1920 GOTO(destroy_new_ns, rc);
1923 exp->exp_nid_stats = new_stat;
1925 /* protect competitive add to list, not need locking on destroy */
1926 cfs_spin_lock(&obd->obd_nid_lock);
1927 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
1928 cfs_spin_unlock(&obd->obd_nid_lock);
1933 if (new_stat->nid_proc != NULL)
1934 lprocfs_remove(&new_stat->nid_proc);
1935 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
1938 nidstat_putref(new_stat);
1939 OBD_FREE_PTR(new_stat);
1943 int lprocfs_exp_cleanup(struct obd_export *exp)
1945 struct nid_stat *stat = exp->exp_nid_stats;
1947 if(!stat || !exp->exp_obd)
1950 nidstat_putref(exp->exp_nid_stats);
1951 exp->exp_nid_stats = NULL;
1956 int lprocfs_write_helper(const char *buffer, unsigned long count,
1959 return lprocfs_write_frac_helper(buffer, count, val, 1);
1962 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
1965 char kernbuf[20], *end, *pbuf;
1967 if (count > (sizeof(kernbuf) - 1))
1970 if (cfs_copy_from_user(kernbuf, buffer, count))
1973 kernbuf[count] = '\0';
1980 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1984 if (end != NULL && *end == '.') {
1985 int temp_val, pow = 1;
1989 if (strlen(pbuf) > 5)
1990 pbuf[5] = '\0'; /*only allow 5bits fractional*/
1992 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1995 for (i = 0; i < (end - pbuf); i++)
1998 *val += temp_val / pow;
2004 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
2007 long decimal_val, frac_val;
2013 decimal_val = val / mult;
2014 prtn = snprintf(buffer, count, "%ld", decimal_val);
2015 frac_val = val % mult;
2017 if (prtn < (count - 4) && frac_val > 0) {
2019 int i, temp_mult = 1, frac_bits = 0;
2021 temp_frac = frac_val * 10;
2022 buffer[prtn++] = '.';
2023 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
2024 /* only reserved 2 bits fraction */
2025 buffer[prtn++] ='0';
2030 * Need to think these cases :
2031 * 1. #echo x.00 > /proc/xxx output result : x
2032 * 2. #echo x.0x > /proc/xxx output result : x.0x
2033 * 3. #echo x.x0 > /proc/xxx output result : x.x
2034 * 4. #echo x.xx > /proc/xxx output result : x.xx
2035 * Only reserved 2 bits fraction.
2037 for (i = 0; i < (5 - prtn); i++)
2040 frac_bits = min((int)count - prtn, 3 - frac_bits);
2041 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
2042 frac_val * temp_mult / mult);
2045 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
2047 if (buffer[prtn] == '.') {
2054 buffer[prtn++] ='\n';
2058 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
2060 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
2063 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
2064 __u64 *val, int mult)
2066 char kernbuf[22], *end, *pbuf;
2067 __u64 whole, frac = 0, units;
2068 unsigned frac_d = 1;
2070 if (count > (sizeof(kernbuf) - 1))
2073 if (cfs_copy_from_user(kernbuf, buffer, count))
2076 kernbuf[count] = '\0';
2083 whole = simple_strtoull(pbuf, &end, 10);
2087 if (end != NULL && *end == '.') {
2091 /* need to limit frac_d to a __u32 */
2092 if (strlen(pbuf) > 10)
2095 frac = simple_strtoull(pbuf, &end, 10);
2096 /* count decimal places */
2097 for (i = 0; i < (end - pbuf); i++)
2114 /* Specified units override the multiplier */
2116 mult = mult < 0 ? -units : units;
2119 do_div(frac, frac_d);
2120 *val = whole * mult + frac;
2124 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent, char *name, mode_t mode,
2125 struct file_operations *seq_fops, void *data)
2127 struct proc_dir_entry *entry;
2130 LPROCFS_WRITE_ENTRY();
2131 entry = create_proc_entry(name, mode, parent);
2133 entry->proc_fops = seq_fops;
2136 LPROCFS_WRITE_EXIT();
2143 EXPORT_SYMBOL(lprocfs_seq_create);
2145 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
2147 struct file_operations *seq_fops,
2150 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2151 mode, seq_fops, data));
2153 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2155 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2157 if (value >= OBD_HIST_MAX)
2158 value = OBD_HIST_MAX - 1;
2160 cfs_spin_lock(&oh->oh_lock);
2161 oh->oh_buckets[value]++;
2162 cfs_spin_unlock(&oh->oh_lock);
2164 EXPORT_SYMBOL(lprocfs_oh_tally);
2166 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2170 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2173 lprocfs_oh_tally(oh, val);
2175 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2177 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2179 unsigned long ret = 0;
2182 for (i = 0; i < OBD_HIST_MAX; i++)
2183 ret += oh->oh_buckets[i];
2186 EXPORT_SYMBOL(lprocfs_oh_sum);
2188 void lprocfs_oh_clear(struct obd_histogram *oh)
2190 cfs_spin_lock(&oh->oh_lock);
2191 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2192 cfs_spin_unlock(&oh->oh_lock);
2194 EXPORT_SYMBOL(lprocfs_oh_clear);
2196 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2197 int count, int *eof, void *data)
2199 struct obd_device *obd = data;
2205 c += cfs_hash_debug_header(page, count);
2206 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2207 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2208 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2209 #ifdef HAVE_QUOTA_SUPPORT
2210 if (obd->u.obt.obt_qctxt.lqc_lqs_hash)
2211 c += cfs_hash_debug_str(obd->u.obt.obt_qctxt.lqc_lqs_hash,
2212 page + c, count - c);
2217 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2219 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2220 int count, int *eof, void *data)
2222 struct obd_device *obd = data;
2225 LASSERT(obd != NULL);
2226 LASSERT(count >= 0);
2228 /* Set start of user data returned to
2229 page + off since the user may have
2230 requested to read much smaller than
2231 what we need to read */
2232 *start = page + off;
2234 /* We know we are allocated a page here.
2235 Also we know that this function will
2236 not need to write more than a page
2237 so we can truncate at CFS_PAGE_SIZE. */
2238 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2240 /* Initialize the page */
2241 memset(page, 0, size);
2243 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2245 if (obd->obd_max_recoverable_clients == 0) {
2246 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2252 /* sampled unlocked, but really... */
2253 if (obd->obd_recovering == 0) {
2254 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2256 if (lprocfs_obd_snprintf(&page, size, &len,
2257 "recovery_start: %lu\n",
2258 obd->obd_recovery_start) <= 0)
2260 if (lprocfs_obd_snprintf(&page, size, &len,
2261 "recovery_duration: %lu\n",
2262 obd->obd_recovery_end -
2263 obd->obd_recovery_start) <= 0)
2265 /* Number of clients that have completed recovery */
2266 if (lprocfs_obd_snprintf(&page, size, &len,
2267 "completed_clients: %d/%d\n",
2268 obd->obd_max_recoverable_clients -
2269 obd->obd_stale_clients,
2270 obd->obd_max_recoverable_clients) <= 0)
2272 if (lprocfs_obd_snprintf(&page, size, &len,
2273 "replayed_requests: %d\n",
2274 obd->obd_replayed_requests) <= 0)
2276 if (lprocfs_obd_snprintf(&page, size, &len,
2277 "last_transno: "LPD64"\n",
2278 obd->obd_next_recovery_transno - 1)<=0)
2280 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2281 obd->obd_version_recov ? "ON" : "OFF")<=0)
2283 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
2284 obd->obd_no_ir ? "OFF" : "ON") <= 0)
2289 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2291 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2292 obd->obd_recovery_start) <= 0)
2294 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2295 cfs_time_current_sec() >=
2296 obd->obd_recovery_start +
2297 obd->obd_recovery_timeout ? 0 :
2298 obd->obd_recovery_start +
2299 obd->obd_recovery_timeout -
2300 cfs_time_current_sec()) <= 0)
2302 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2303 cfs_atomic_read(&obd->obd_connected_clients),
2304 obd->obd_max_recoverable_clients) <= 0)
2306 /* Number of clients that have completed recovery */
2307 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2308 cfs_atomic_read(&obd->obd_req_replay_clients))
2311 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2312 cfs_atomic_read(&obd->obd_lock_replay_clients))
2315 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2316 cfs_atomic_read(&obd->obd_connected_clients) -
2317 cfs_atomic_read(&obd->obd_lock_replay_clients))
2320 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2321 obd->obd_stale_clients) <= 0)
2323 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2324 obd->obd_replayed_requests) <= 0)
2326 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2327 obd->obd_requests_queued_for_recovery) <= 0)
2330 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2331 obd->obd_next_recovery_transno) <= 0)
2337 return min(count, len - (int)off);
2339 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2341 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
2342 int count, int *eof, void *data)
2344 struct obd_device *obd = (struct obd_device *)data;
2345 LASSERT(obd != NULL);
2347 return snprintf(page, count, "%d\n",
2348 obd->obd_recovery_ir_factor);
2350 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
2352 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
2353 unsigned long count, void *data)
2355 struct obd_device *obd = (struct obd_device *)data;
2357 LASSERT(obd != NULL);
2359 rc = lprocfs_write_helper(buffer, count, &val);
2363 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
2366 obd->obd_recovery_ir_factor = val;
2369 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
2371 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
2372 int count, int *eof, void *data)
2374 struct obd_device *obd = (struct obd_device *)data;
2375 LASSERT(obd != NULL);
2377 return snprintf(page, count, "%d\n",
2378 obd->obd_recovery_timeout);
2380 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
2382 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
2383 unsigned long count, void *data)
2385 struct obd_device *obd = (struct obd_device *)data;
2387 LASSERT(obd != NULL);
2389 rc = lprocfs_write_helper(buffer, count, &val);
2393 obd->obd_recovery_timeout = val;
2396 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
2398 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
2399 int count, int *eof, void *data)
2401 struct obd_device *obd = data;
2402 LASSERT(obd != NULL);
2404 return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
2406 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
2408 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
2409 unsigned long count, void *data)
2411 struct obd_device *obd = data;
2413 LASSERT(obd != NULL);
2415 rc = lprocfs_write_helper(buffer, count, &val);
2419 obd->obd_recovery_time_hard = val;
2422 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
2424 int lprocfs_obd_rd_mntdev(char *page, char **start, off_t off,
2425 int count, int *eof, void *data)
2427 struct obd_device *obd = (struct obd_device *)data;
2429 LASSERT(obd != NULL);
2430 LASSERT(obd->u.obt.obt_vfsmnt->mnt_devname);
2432 return snprintf(page, count, "%s\n",
2433 obd->u.obt.obt_vfsmnt->mnt_devname);
2435 EXPORT_SYMBOL(lprocfs_obd_rd_mntdev);
2437 int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
2438 int count, int *eof, void *data)
2440 struct obd_device *dev = data;
2441 struct client_obd *cli = &dev->u.cli;
2444 client_obd_list_lock(&cli->cl_loi_list_lock);
2445 rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
2446 client_obd_list_unlock(&cli->cl_loi_list_lock);
2449 EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
2451 int lprocfs_obd_wr_max_pages_per_rpc(struct file *file, const char *buffer,
2452 unsigned long count, void *data)
2454 struct obd_device *dev = data;
2455 struct client_obd *cli = &dev->u.cli;
2456 struct obd_connect_data *ocd = &cli->cl_import->imp_connect_data;
2459 rc = lprocfs_write_helper(buffer, count, &val);
2463 LPROCFS_CLIMP_CHECK(dev);
2464 if (val < 1 || val > ocd->ocd_brw_size >> CFS_PAGE_SHIFT) {
2465 LPROCFS_CLIMP_EXIT(dev);
2468 client_obd_list_lock(&cli->cl_loi_list_lock);
2469 cli->cl_max_pages_per_rpc = val;
2470 client_obd_list_unlock(&cli->cl_loi_list_lock);
2472 LPROCFS_CLIMP_EXIT(dev);
2475 EXPORT_SYMBOL(lprocfs_obd_wr_max_pages_per_rpc);
2477 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
2478 int count, int *eof, void *data)
2480 struct obd_device *obd = (struct obd_device *)data;
2481 struct obd_device_target *target = &obd->u.obt;
2483 LASSERT(obd != NULL);
2484 LASSERT(target->obt_magic == OBT_MAGIC);
2486 return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
2488 EXPORT_SYMBOL(lprocfs_target_rd_instance);
2490 EXPORT_SYMBOL(lprocfs_register);
2491 EXPORT_SYMBOL(lprocfs_srch);
2492 EXPORT_SYMBOL(lprocfs_remove);
2493 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
2494 EXPORT_SYMBOL(lprocfs_add_vars);
2495 EXPORT_SYMBOL(lprocfs_obd_setup);
2496 EXPORT_SYMBOL(lprocfs_obd_cleanup);
2497 EXPORT_SYMBOL(lprocfs_add_simple);
2498 EXPORT_SYMBOL(lprocfs_add_symlink);
2499 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
2500 EXPORT_SYMBOL(lprocfs_alloc_stats);
2501 EXPORT_SYMBOL(lprocfs_free_stats);
2502 EXPORT_SYMBOL(lprocfs_clear_stats);
2503 EXPORT_SYMBOL(lprocfs_register_stats);
2504 EXPORT_SYMBOL(lprocfs_init_ops_stats);
2505 EXPORT_SYMBOL(lprocfs_init_mps_stats);
2506 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
2507 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
2508 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
2509 EXPORT_SYMBOL(lprocfs_free_obd_stats);
2510 EXPORT_SYMBOL(lprocfs_free_md_stats);
2511 EXPORT_SYMBOL(lprocfs_exp_setup);
2512 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2514 EXPORT_SYMBOL(lprocfs_rd_u64);
2515 EXPORT_SYMBOL(lprocfs_rd_atomic);
2516 EXPORT_SYMBOL(lprocfs_wr_atomic);
2517 EXPORT_SYMBOL(lprocfs_rd_uint);
2518 EXPORT_SYMBOL(lprocfs_wr_uint);
2519 EXPORT_SYMBOL(lprocfs_rd_uuid);
2520 EXPORT_SYMBOL(lprocfs_rd_name);
2521 EXPORT_SYMBOL(lprocfs_rd_fstype);
2522 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
2523 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
2524 EXPORT_SYMBOL(lprocfs_rd_num_exports);
2525 EXPORT_SYMBOL(lprocfs_rd_numrefs);
2526 EXPORT_SYMBOL(lprocfs_at_hist_helper);
2527 EXPORT_SYMBOL(lprocfs_rd_import);
2528 EXPORT_SYMBOL(lprocfs_rd_state);
2529 EXPORT_SYMBOL(lprocfs_rd_timeouts);
2530 EXPORT_SYMBOL(lprocfs_rd_blksize);
2531 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
2532 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
2533 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
2534 EXPORT_SYMBOL(lprocfs_rd_filestotal);
2535 EXPORT_SYMBOL(lprocfs_rd_filesfree);
2537 EXPORT_SYMBOL(lprocfs_write_helper);
2538 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2539 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2540 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2541 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2542 EXPORT_SYMBOL(lprocfs_stats_collect);