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_entry;
711 struct lprocfs_counter t;
712 struct lprocfs_counter *percpu_cntr;
715 unsigned long flags = 0;
717 memset(cnt, 0, sizeof(*cnt));
720 /* set count to 1 to avoid divide-by-zero errs in callers */
725 cnt->lc_min = LC_MIN_INIT;
727 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
729 for (i = 0; i < num_entry; i++) {
730 if (stats->ls_percpu[i] == NULL)
732 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[idx];
735 centry = cfs_atomic_read(&percpu_cntr-> \
737 t.lc_count = percpu_cntr->lc_count;
738 t.lc_sum = percpu_cntr->lc_sum;
739 t.lc_min = percpu_cntr->lc_min;
740 t.lc_max = percpu_cntr->lc_max;
741 t.lc_sumsquare = percpu_cntr->lc_sumsquare;
742 } while (centry != cfs_atomic_read(&percpu_cntr->lc_cntl. \
744 centry != cfs_atomic_read(&percpu_cntr->lc_cntl. \
746 cnt->lc_count += t.lc_count;
747 cnt->lc_sum += t.lc_sum;
748 if (t.lc_min < cnt->lc_min)
749 cnt->lc_min = t.lc_min;
750 if (t.lc_max > cnt->lc_max)
751 cnt->lc_max = t.lc_max;
752 cnt->lc_sumsquare += t.lc_sumsquare;
755 cnt->lc_units = stats->ls_percpu[0]->lp_cntr[idx].lc_units;
756 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
760 * Append a space separated list of current set flags to str.
762 #define flag2str(flag) \
763 if (imp->imp_##flag && max - len > 0) \
764 len += snprintf(str + len, max - len, "%s" #flag, len ? ", " : "");
765 static int obd_import_flags2str(struct obd_import *imp, char *str, int max)
769 if (imp->imp_obd->obd_no_recov)
770 len += snprintf(str, max - len, "no_recov");
774 flag2str(replayable);
780 static const char *obd_connect_names[] = {
794 "join_file(obsolete)",
798 "remote_client_by_force",
807 "mds_mds_connection",
810 "alt_checksum_algorithm",
829 int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
834 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
836 ret += snprintf(page + ret, count - ret, "%s%s",
837 ret ? sep : "", obd_connect_names[i]);
839 if (flags & ~(mask - 1))
840 ret += snprintf(page + ret, count - ret,
841 "%sunknown flags "LPX64,
842 ret ? sep : "", flags & ~(mask - 1));
845 EXPORT_SYMBOL(obd_connect_flags2str);
847 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
848 int *eof, void *data)
850 struct lprocfs_counter ret;
851 struct obd_device *obd = (struct obd_device *)data;
852 struct obd_import *imp;
853 struct obd_import_conn *conn;
856 LASSERT(obd != NULL);
857 LPROCFS_CLIMP_CHECK(obd);
858 imp = obd->u.cli.cl_import;
861 i = snprintf(page, count,
870 ptlrpc_import_state_name(imp->imp_state),
871 imp->imp_connect_data.ocd_instance);
872 i += obd_connect_flags2str(page + i, count - i,
873 imp->imp_connect_data.ocd_connect_flags,
875 i += snprintf(page + i, count - i,
878 i += obd_import_flags2str(imp, page + i, count - i);
880 i += snprintf(page + i, count - i,
883 " failover_nids: [");
884 cfs_spin_lock(&imp->imp_lock);
886 cfs_list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
887 i += snprintf(page + i, count - i, "%s%s", j ? ", " : "",
888 libcfs_nid2str(conn->oic_conn->c_peer.nid));
891 cfs_spin_unlock(&imp->imp_lock);
892 i += snprintf(page + i, count - i,
894 " current_connection: %s\n"
895 " connection_attempts: %u\n"
897 " in-progress_invalidations: %u\n",
898 libcfs_nid2str(imp->imp_connection->c_peer.nid),
901 cfs_atomic_read(&imp->imp_inval_count));
903 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
904 if (ret.lc_count != 0) {
905 /* first argument to do_div MUST be __u64 */
906 __u64 sum = ret.lc_sum;
907 do_div(sum, ret.lc_count);
911 i += snprintf(page + i, count - i,
914 " unregistering: %u\n"
916 " avg_waittime: "LPU64" %s\n",
917 cfs_atomic_read(&imp->imp_inflight),
918 cfs_atomic_read(&imp->imp_unregistering),
919 cfs_atomic_read(&imp->imp_timeouts),
920 ret.lc_sum, ret.lc_units);
923 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
924 if (imp->imp_at.iat_portal[j] == 0)
926 k = max_t(unsigned int, k,
927 at_get(&imp->imp_at.iat_service_estimate[j]));
929 i += snprintf(page + i, count - i,
930 " service_estimates:\n"
931 " services: %u sec\n"
932 " network: %u sec\n",
934 at_get(&imp->imp_at.iat_net_latency));
936 i += snprintf(page + i, count - i,
938 " last_replay: "LPU64"\n"
939 " peer_committed: "LPU64"\n"
940 " last_checked: "LPU64"\n",
941 imp->imp_last_replay_transno,
942 imp->imp_peer_committed_transno,
943 imp->imp_last_transno_checked);
946 for (rw = 0; rw <= 1; rw++) {
947 lprocfs_stats_collect(obd->obd_svc_stats,
948 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
950 if (ret.lc_sum > 0 && ret.lc_count > 0) {
951 /* first argument to do_div MUST be __u64 */
952 __u64 sum = ret.lc_sum;
953 do_div(sum, ret.lc_count);
955 i += snprintf(page + i, count - i,
956 " %s_data_averages:\n"
957 " bytes_per_rpc: "LPU64"\n",
958 rw ? "write" : "read",
962 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
963 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
964 if (ret.lc_sum > 0 && ret.lc_count != 0) {
965 /* first argument to do_div MUST be __u64 */
966 __u64 sum = ret.lc_sum;
967 do_div(sum, ret.lc_count);
969 i += snprintf(page + i, count - i,
970 " %s_per_rpc: "LPU64"\n",
971 ret.lc_units, ret.lc_sum);
974 i += snprintf(page + i, count - i,
975 " MB_per_sec: %u.%.02u\n",
976 k / j, (100 * k / j) % 100);
980 LPROCFS_CLIMP_EXIT(obd);
984 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
985 int *eof, void *data)
987 struct obd_device *obd = (struct obd_device *)data;
988 struct obd_import *imp;
991 LASSERT(obd != NULL);
992 LPROCFS_CLIMP_CHECK(obd);
993 imp = obd->u.cli.cl_import;
996 i = snprintf(page, count, "current_state: %s\n",
997 ptlrpc_import_state_name(imp->imp_state));
998 i += snprintf(page + i, count - i,
1000 k = imp->imp_state_hist_idx;
1001 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
1002 struct import_state_hist *ish =
1003 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
1004 if (ish->ish_state == 0)
1006 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
1008 ptlrpc_import_state_name(ish->ish_state));
1011 LPROCFS_CLIMP_EXIT(obd);
1015 int lprocfs_at_hist_helper(char *page, int count, int rc,
1016 struct adaptive_timeout *at)
1019 for (i = 0; i < AT_BINS; i++)
1020 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
1021 rc += snprintf(page + rc, count - rc, "\n");
1025 /* See also ptlrpc_lprocfs_rd_timeouts */
1026 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
1027 int *eof, void *data)
1029 struct obd_device *obd = (struct obd_device *)data;
1030 struct obd_import *imp;
1031 unsigned int cur, worst;
1036 LASSERT(obd != NULL);
1037 LPROCFS_CLIMP_CHECK(obd);
1038 imp = obd->u.cli.cl_import;
1041 now = cfs_time_current_sec();
1043 /* Some network health info for kicks */
1044 s2dhms(&ts, now - imp->imp_last_reply_time);
1045 rc += snprintf(page + rc, count - rc,
1046 "%-10s : %ld, "DHMS_FMT" ago\n",
1047 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
1049 cur = at_get(&imp->imp_at.iat_net_latency);
1050 worst = imp->imp_at.iat_net_latency.at_worst_ever;
1051 worstt = imp->imp_at.iat_net_latency.at_worst_time;
1052 s2dhms(&ts, now - worstt);
1053 rc += snprintf(page + rc, count - rc,
1054 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
1055 "network", cur, worst, worstt, DHMS_VARS(&ts));
1056 rc = lprocfs_at_hist_helper(page, count, rc,
1057 &imp->imp_at.iat_net_latency);
1059 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
1060 if (imp->imp_at.iat_portal[i] == 0)
1062 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
1063 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
1064 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
1065 s2dhms(&ts, now - worstt);
1066 rc += snprintf(page + rc, count - rc,
1067 "portal %-2d : cur %3u worst %3u (at %ld, "
1068 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
1069 cur, worst, worstt, DHMS_VARS(&ts));
1070 rc = lprocfs_at_hist_helper(page, count, rc,
1071 &imp->imp_at.iat_service_estimate[i]);
1074 LPROCFS_CLIMP_EXIT(obd);
1078 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1079 int count, int *eof, void *data)
1081 struct obd_device *obd = data;
1085 LPROCFS_CLIMP_CHECK(obd);
1086 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1087 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1088 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1089 ret += snprintf(page + ret, count - ret, "\n");
1090 LPROCFS_CLIMP_EXIT(obd);
1093 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1095 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1096 int *eof, void *data)
1098 struct obd_device *obd = data;
1100 LASSERT(obd != NULL);
1102 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1105 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1106 int *eof, void *data)
1108 struct obd_type *class = (struct obd_type*) data;
1110 LASSERT(class != NULL);
1112 return snprintf(page, count, "%d\n", class->typ_refcnt);
1115 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1119 LASSERT(obd != NULL);
1120 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1121 LASSERT(obd->obd_type->typ_procroot != NULL);
1123 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1124 obd->obd_type->typ_procroot,
1126 if (IS_ERR(obd->obd_proc_entry)) {
1127 rc = PTR_ERR(obd->obd_proc_entry);
1128 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1129 obd->obd_proc_entry = NULL;
1134 int lprocfs_obd_cleanup(struct obd_device *obd)
1138 if (obd->obd_proc_exports_entry) {
1139 /* Should be no exports left */
1140 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1141 lprocfs_remove(&obd->obd_proc_exports_entry);
1142 obd->obd_proc_exports_entry = NULL;
1144 if (obd->obd_proc_entry) {
1145 lprocfs_remove(&obd->obd_proc_entry);
1146 obd->obd_proc_entry = NULL;
1151 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1153 CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
1154 client_stat->nid_proc, client_stat->nid_stats,
1155 client_stat->nid_brw_stats);
1157 LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
1158 "nid %s:count %d\n", libcfs_nid2str(client_stat->nid),
1159 atomic_read(&client_stat->nid_exp_ref_count));
1161 if (client_stat->nid_proc)
1162 lprocfs_remove(&client_stat->nid_proc);
1164 if (client_stat->nid_stats)
1165 lprocfs_free_stats(&client_stat->nid_stats);
1167 if (client_stat->nid_brw_stats)
1168 OBD_FREE_PTR(client_stat->nid_brw_stats);
1170 if (client_stat->nid_ldlm_stats)
1171 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1173 OBD_FREE_PTR(client_stat);
1178 void lprocfs_free_per_client_stats(struct obd_device *obd)
1180 cfs_hash_t *hash = obd->obd_nid_stats_hash;
1181 struct nid_stat *stat;
1184 /* we need extra list - because hash_exit called to early */
1185 /* not need locking because all clients is died */
1186 while (!cfs_list_empty(&obd->obd_nid_stats)) {
1187 stat = cfs_list_entry(obd->obd_nid_stats.next,
1188 struct nid_stat, nid_list);
1189 cfs_list_del_init(&stat->nid_list);
1190 cfs_hash_del(hash, &stat->nid, &stat->nid_hash);
1191 lprocfs_free_client_stats(stat);
1196 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1197 enum lprocfs_stats_flags flags)
1199 struct lprocfs_stats *stats;
1200 unsigned int percpusize;
1201 unsigned int num_entry;
1206 if (lprocfs_no_percpu_stats != 0)
1207 flags |= LPROCFS_STATS_FLAG_NOPERCPU;
1209 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1212 num_entry = cfs_num_possible_cpus() + 1;
1214 /* alloc percpu pointers for all possible cpu slots */
1215 OBD_ALLOC(stats, offsetof(struct lprocfs_stats, ls_percpu[num_entry]));
1219 stats->ls_num = num;
1220 stats->ls_biggest_alloc_num = 1;
1221 if (flags & LPROCFS_STATS_FLAG_NOPERCPU) {
1222 stats->ls_flags = flags;
1223 cfs_spin_lock_init(&stats->ls_lock);
1224 /* Use this lock only if there are no percpu areas */
1226 stats->ls_flags = 0;
1229 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
1231 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1233 /* for no percpu area, the 0th entry is for real use,
1234 * for percpu area, the 0th entry is for intialized entry template */
1235 OBD_ALLOC(stats->ls_percpu[0], percpusize);
1236 if (stats->ls_percpu[0] == NULL) {
1238 offsetof(struct lprocfs_stats, ls_percpu[num_entry]));
1244 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1246 struct lprocfs_stats *stats = *statsh;
1247 unsigned int num_entry;
1248 unsigned int percpusize;
1251 if (stats == NULL || stats->ls_num == 0)
1255 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1258 num_entry = cfs_num_possible_cpus() + 1;
1260 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
1262 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1263 for (i = 0; i < num_entry; i++)
1264 if (stats->ls_percpu[i] != NULL)
1265 OBD_FREE(stats->ls_percpu[i], percpusize);
1266 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1269 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1271 struct lprocfs_counter *percpu_cntr;
1274 unsigned int num_entry;
1275 unsigned int percpusize;
1276 unsigned long flags = 0;
1278 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1280 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
1282 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1284 for (i = 0; i < num_entry; i++) {
1285 if (stats->ls_percpu[i] == NULL)
1287 /* the 1st percpu entry was statically allocated in
1288 * lprocfs_alloc_stats() */
1290 OBD_FREE(stats->ls_percpu[i], percpusize);
1291 stats->ls_percpu[i] = NULL;
1294 for (j = 0; j < stats->ls_num; j++) {
1295 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
1296 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_entry);
1297 percpu_cntr->lc_count = 0;
1298 percpu_cntr->lc_sum = 0;
1299 percpu_cntr->lc_min = LC_MIN_INIT;
1300 percpu_cntr->lc_max = 0;
1301 percpu_cntr->lc_sumsquare = 0;
1302 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_exit);
1306 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1309 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1310 size_t len, loff_t *off)
1312 struct seq_file *seq = file->private_data;
1313 struct lprocfs_stats *stats = seq->private;
1315 lprocfs_clear_stats(stats);
1320 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1322 struct lprocfs_stats *stats = p->private;
1323 /* return 1st cpu location */
1324 return (*pos >= stats->ls_num) ? NULL :
1325 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1328 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1332 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1334 struct lprocfs_stats *stats = p->private;
1336 return (*pos >= stats->ls_num) ? NULL :
1337 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1340 /* seq file export of one lprocfs counter */
1341 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1343 struct lprocfs_stats *stats = p->private;
1344 struct lprocfs_counter *cntr = v;
1345 struct lprocfs_counter ret;
1348 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
1350 cfs_gettimeofday(&now);
1351 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1352 "snapshot_time", now.tv_sec, now.tv_usec);
1356 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
1358 lprocfs_stats_collect(stats, idx, &ret);
1360 if (ret.lc_count == 0)
1363 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", cntr->lc_name,
1364 ret.lc_count, cntr->lc_units);
1369 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
1370 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1371 ret.lc_min, ret.lc_max, ret.lc_sum);
1374 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
1375 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1379 rc = seq_printf(p, "\n");
1381 return (rc < 0) ? rc : 0;
1384 struct seq_operations lprocfs_stats_seq_sops = {
1385 start: lprocfs_stats_seq_start,
1386 stop: lprocfs_stats_seq_stop,
1387 next: lprocfs_stats_seq_next,
1388 show: lprocfs_stats_seq_show,
1391 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1393 struct proc_dir_entry *dp = PDE(inode);
1394 struct seq_file *seq;
1397 if (LPROCFS_ENTRY_AND_CHECK(dp))
1400 rc = seq_open(file, &lprocfs_stats_seq_sops);
1405 seq = file->private_data;
1406 seq->private = dp->data;
1410 struct file_operations lprocfs_stats_seq_fops = {
1411 .owner = THIS_MODULE,
1412 .open = lprocfs_stats_seq_open,
1414 .write = lprocfs_stats_seq_write,
1415 .llseek = seq_lseek,
1416 .release = lprocfs_seq_release,
1419 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1420 struct lprocfs_stats *stats)
1422 struct proc_dir_entry *entry;
1423 LASSERT(root != NULL);
1425 LPROCFS_WRITE_ENTRY();
1426 entry = create_proc_entry(name, 0644, root);
1428 entry->proc_fops = &lprocfs_stats_seq_fops;
1429 entry->data = stats;
1432 LPROCFS_WRITE_EXIT();
1440 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1441 unsigned conf, const char *name, const char *units)
1443 struct lprocfs_counter *c = &(stats->ls_percpu[0]->lp_cntr[index]);
1444 unsigned long flags = 0;
1446 LASSERT(stats != NULL);
1447 LASSERT(stats->ls_percpu[0] != NULL);
1449 lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1450 c->lc_config = conf;
1453 c->lc_min = LC_MIN_INIT;
1456 c->lc_units = units;
1457 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1459 EXPORT_SYMBOL(lprocfs_counter_init);
1461 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1463 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1464 LASSERT(coffset < stats->ls_num); \
1465 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1468 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1470 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1471 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1472 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1473 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1474 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1475 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1476 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1477 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1478 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1479 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1480 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1481 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1482 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1483 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1484 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1485 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1486 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1487 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1488 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
1489 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1490 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1491 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1492 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1493 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1494 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1495 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1496 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1497 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1498 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1499 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1500 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1501 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1502 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1503 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1504 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1505 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1506 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1507 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1508 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1509 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1510 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1511 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1512 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1513 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1514 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
1515 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1516 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1517 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1518 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1519 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1520 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1521 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1522 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1523 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1524 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1525 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1526 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1527 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1528 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1529 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1530 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1531 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quota_adjust_qunit);
1532 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1533 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1534 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1535 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1536 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1537 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1538 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1541 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1543 struct lprocfs_stats *stats;
1544 unsigned int num_stats;
1547 LASSERT(obd->obd_stats == NULL);
1548 LASSERT(obd->obd_proc_entry != NULL);
1549 LASSERT(obd->obd_cntr_base == 0);
1551 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1552 num_private_stats - 1 /* o_owner */;
1553 stats = lprocfs_alloc_stats(num_stats, 0);
1557 lprocfs_init_ops_stats(num_private_stats, stats);
1559 for (i = num_private_stats; i < num_stats; i++) {
1560 /* If this LBUGs, it is likely that an obd
1561 * operation was added to struct obd_ops in
1562 * <obd.h>, and that the corresponding line item
1563 * LPROCFS_OBD_OP_INIT(.., .., opname)
1564 * is missing from the list above. */
1565 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1566 "Missing obd_stat initializer obd_op "
1567 "operation at offset %d.\n", i - num_private_stats);
1569 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1571 lprocfs_free_stats(&stats);
1573 obd->obd_stats = stats;
1574 obd->obd_cntr_base = num_private_stats;
1579 void lprocfs_free_obd_stats(struct obd_device *obd)
1582 lprocfs_free_stats(&obd->obd_stats);
1585 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1587 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1588 LASSERT(coffset < stats->ls_num); \
1589 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1592 void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats)
1594 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1595 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1596 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
1597 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1598 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1599 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1600 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1601 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1602 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1603 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1604 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1605 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1606 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1607 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1608 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1609 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1610 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1611 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1612 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1613 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1614 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1615 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1616 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1617 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1618 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1619 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1620 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1621 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1622 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1623 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1624 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1625 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1628 int lprocfs_alloc_md_stats(struct obd_device *obd,
1629 unsigned num_private_stats)
1631 struct lprocfs_stats *stats;
1632 unsigned int num_stats;
1635 LASSERT(obd->md_stats == NULL);
1636 LASSERT(obd->obd_proc_entry != NULL);
1637 LASSERT(obd->md_cntr_base == 0);
1639 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1641 stats = lprocfs_alloc_stats(num_stats, 0);
1645 lprocfs_init_mps_stats(num_private_stats, stats);
1647 for (i = num_private_stats; i < num_stats; i++) {
1648 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1649 CERROR("Missing md_stat initializer md_op "
1650 "operation at offset %d. Aborting.\n",
1651 i - num_private_stats);
1655 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1657 lprocfs_free_stats(&stats);
1659 obd->md_stats = stats;
1660 obd->md_cntr_base = num_private_stats;
1665 void lprocfs_free_md_stats(struct obd_device *obd)
1667 struct lprocfs_stats *stats = obd->md_stats;
1669 if (stats != NULL) {
1670 obd->md_stats = NULL;
1671 obd->md_cntr_base = 0;
1672 lprocfs_free_stats(&stats);
1676 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1678 lprocfs_counter_init(ldlm_stats,
1679 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1680 0, "ldlm_enqueue", "reqs");
1681 lprocfs_counter_init(ldlm_stats,
1682 LDLM_CONVERT - LDLM_FIRST_OPC,
1683 0, "ldlm_convert", "reqs");
1684 lprocfs_counter_init(ldlm_stats,
1685 LDLM_CANCEL - LDLM_FIRST_OPC,
1686 0, "ldlm_cancel", "reqs");
1687 lprocfs_counter_init(ldlm_stats,
1688 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1689 0, "ldlm_bl_callback", "reqs");
1690 lprocfs_counter_init(ldlm_stats,
1691 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1692 0, "ldlm_cp_callback", "reqs");
1693 lprocfs_counter_init(ldlm_stats,
1694 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1695 0, "ldlm_gl_callback", "reqs");
1698 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1699 int *eof, void *data)
1701 struct obd_export *exp = data;
1702 LASSERT(exp != NULL);
1704 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1707 struct exp_uuid_cb_data {
1715 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1716 int count, int *eof, int *len)
1718 cb_data->page = page;
1719 cb_data->count = count;
1724 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1725 cfs_hlist_node_t *hnode, void *cb_data)
1728 struct obd_export *exp = cfs_hash_object(hs, hnode);
1729 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1731 if (exp->exp_nid_stats)
1732 *data->len += snprintf((data->page + *data->len),
1733 data->count, "%s\n",
1734 obd_uuid2str(&exp->exp_client_uuid));
1738 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1739 int *eof, void *data)
1741 struct nid_stat *stats = (struct nid_stat *)data;
1742 struct exp_uuid_cb_data cb_data;
1743 struct obd_device *obd = stats->nid_obd;
1748 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1749 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1750 lprocfs_exp_print_uuid, &cb_data);
1751 return (*cb_data.len);
1754 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1755 cfs_hlist_node_t *hnode, void *cb_data)
1758 struct exp_uuid_cb_data *data = cb_data;
1759 struct obd_export *exp = cfs_hash_object(hs, hnode);
1761 if (exp->exp_lock_hash != NULL) {
1763 *data->len += cfs_hash_debug_header(data->page,
1766 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1773 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1774 int *eof, void *data)
1776 struct nid_stat *stats = (struct nid_stat *)data;
1777 struct exp_uuid_cb_data cb_data;
1778 struct obd_device *obd = stats->nid_obd;
1783 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1785 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1786 lprocfs_exp_print_hash, &cb_data);
1787 return (*cb_data.len);
1790 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1791 int count, int *eof, void *data)
1794 return snprintf(page, count, "%s\n",
1795 "Write into this file to clear all nid stats and "
1796 "stale nid entries");
1798 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1800 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1802 struct nid_stat *stat = obj;
1806 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
1807 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 1) {
1808 /* object has only hash references. */
1809 cfs_spin_lock(&stat->nid_obd->obd_nid_lock);
1810 cfs_list_move(&stat->nid_list, data);
1811 cfs_spin_unlock(&stat->nid_obd->obd_nid_lock);
1814 /* we has reference to object - only clear data*/
1815 if (stat->nid_stats)
1816 lprocfs_clear_stats(stat->nid_stats);
1818 if (stat->nid_brw_stats) {
1819 for (i = 0; i < BRW_LAST; i++)
1820 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
1825 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1826 unsigned long count, void *data)
1828 struct obd_device *obd = (struct obd_device *)data;
1829 struct nid_stat *client_stat;
1830 CFS_LIST_HEAD(free_list);
1832 cfs_hash_cond_del(obd->obd_nid_stats_hash,
1833 lprocfs_nid_stats_clear_write_cb, &free_list);
1835 while (!cfs_list_empty(&free_list)) {
1836 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
1838 cfs_list_del_init(&client_stat->nid_list);
1839 lprocfs_free_client_stats(client_stat);
1844 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1846 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1848 struct nid_stat *new_stat, *old_stat;
1849 struct obd_device *obd = NULL;
1850 cfs_proc_dir_entry_t *entry;
1851 char *buffer = NULL;
1857 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1858 !exp->exp_obd->obd_nid_stats_hash)
1861 /* not test against zero because eric say:
1862 * You may only test nid against another nid, or LNET_NID_ANY.
1863 * Anything else is nonsense.*/
1864 if (!nid || *nid == LNET_NID_ANY)
1869 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
1871 OBD_ALLOC_PTR(new_stat);
1872 if (new_stat == NULL)
1875 new_stat->nid = *nid;
1876 new_stat->nid_obd = exp->exp_obd;
1877 /* we need set default refcount to 1 to balance obd_disconnect */
1878 cfs_atomic_set(&new_stat->nid_exp_ref_count, 1);
1880 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
1881 nid, &new_stat->nid_hash);
1882 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
1883 old_stat, libcfs_nid2str(*nid),
1884 cfs_atomic_read(&new_stat->nid_exp_ref_count));
1886 /* We need to release old stats because lprocfs_exp_cleanup() hasn't
1887 * been and will never be called. */
1888 if (exp->exp_nid_stats) {
1889 nidstat_putref(exp->exp_nid_stats);
1890 exp->exp_nid_stats = NULL;
1893 /* Return -EALREADY here so that we know that the /proc
1894 * entry already has been created */
1895 if (old_stat != new_stat) {
1896 exp->exp_nid_stats = old_stat;
1897 GOTO(destroy_new, rc = -EALREADY);
1899 /* not found - create */
1900 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
1902 GOTO(destroy_new, rc = -ENOMEM);
1904 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
1905 new_stat->nid_proc = lprocfs_register(buffer,
1906 obd->obd_proc_exports_entry,
1908 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
1910 if (new_stat->nid_proc == NULL) {
1911 CERROR("Error making export directory for nid %s\n",
1912 libcfs_nid2str(*nid));
1913 GOTO(destroy_new_ns, rc = -ENOMEM);
1916 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
1917 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
1918 if (IS_ERR(entry)) {
1919 CWARN("Error adding the NID stats file\n");
1920 rc = PTR_ERR(entry);
1921 GOTO(destroy_new_ns, rc);
1924 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
1925 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
1926 if (IS_ERR(entry)) {
1927 CWARN("Error adding the hash file\n");
1928 rc = PTR_ERR(entry);
1929 GOTO(destroy_new_ns, rc);
1932 exp->exp_nid_stats = new_stat;
1934 /* protect competitive add to list, not need locking on destroy */
1935 cfs_spin_lock(&obd->obd_nid_lock);
1936 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
1937 cfs_spin_unlock(&obd->obd_nid_lock);
1942 if (new_stat->nid_proc != NULL)
1943 lprocfs_remove(&new_stat->nid_proc);
1944 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
1947 nidstat_putref(new_stat);
1948 OBD_FREE_PTR(new_stat);
1952 int lprocfs_exp_cleanup(struct obd_export *exp)
1954 struct nid_stat *stat = exp->exp_nid_stats;
1956 if(!stat || !exp->exp_obd)
1959 nidstat_putref(exp->exp_nid_stats);
1960 exp->exp_nid_stats = NULL;
1965 int lprocfs_write_helper(const char *buffer, unsigned long count,
1968 return lprocfs_write_frac_helper(buffer, count, val, 1);
1971 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
1974 char kernbuf[20], *end, *pbuf;
1976 if (count > (sizeof(kernbuf) - 1))
1979 if (cfs_copy_from_user(kernbuf, buffer, count))
1982 kernbuf[count] = '\0';
1989 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1993 if (end != NULL && *end == '.') {
1994 int temp_val, pow = 1;
1998 if (strlen(pbuf) > 5)
1999 pbuf[5] = '\0'; /*only allow 5bits fractional*/
2001 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2004 for (i = 0; i < (end - pbuf); i++)
2007 *val += temp_val / pow;
2013 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
2016 long decimal_val, frac_val;
2022 decimal_val = val / mult;
2023 prtn = snprintf(buffer, count, "%ld", decimal_val);
2024 frac_val = val % mult;
2026 if (prtn < (count - 4) && frac_val > 0) {
2028 int i, temp_mult = 1, frac_bits = 0;
2030 temp_frac = frac_val * 10;
2031 buffer[prtn++] = '.';
2032 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
2033 /* only reserved 2 bits fraction */
2034 buffer[prtn++] ='0';
2039 * Need to think these cases :
2040 * 1. #echo x.00 > /proc/xxx output result : x
2041 * 2. #echo x.0x > /proc/xxx output result : x.0x
2042 * 3. #echo x.x0 > /proc/xxx output result : x.x
2043 * 4. #echo x.xx > /proc/xxx output result : x.xx
2044 * Only reserved 2 bits fraction.
2046 for (i = 0; i < (5 - prtn); i++)
2049 frac_bits = min((int)count - prtn, 3 - frac_bits);
2050 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
2051 frac_val * temp_mult / mult);
2054 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
2056 if (buffer[prtn] == '.') {
2063 buffer[prtn++] ='\n';
2067 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
2069 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
2072 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
2073 __u64 *val, int mult)
2075 char kernbuf[22], *end, *pbuf;
2076 __u64 whole, frac = 0, units;
2077 unsigned frac_d = 1;
2079 if (count > (sizeof(kernbuf) - 1))
2082 if (cfs_copy_from_user(kernbuf, buffer, count))
2085 kernbuf[count] = '\0';
2092 whole = simple_strtoull(pbuf, &end, 10);
2096 if (end != NULL && *end == '.') {
2100 /* need to limit frac_d to a __u32 */
2101 if (strlen(pbuf) > 10)
2104 frac = simple_strtoull(pbuf, &end, 10);
2105 /* count decimal places */
2106 for (i = 0; i < (end - pbuf); i++)
2123 /* Specified units override the multiplier */
2125 mult = mult < 0 ? -units : units;
2128 do_div(frac, frac_d);
2129 *val = whole * mult + frac;
2133 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent, char *name, mode_t mode,
2134 struct file_operations *seq_fops, void *data)
2136 struct proc_dir_entry *entry;
2139 LPROCFS_WRITE_ENTRY();
2140 entry = create_proc_entry(name, mode, parent);
2142 entry->proc_fops = seq_fops;
2145 LPROCFS_WRITE_EXIT();
2152 EXPORT_SYMBOL(lprocfs_seq_create);
2154 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
2156 struct file_operations *seq_fops,
2159 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2160 mode, seq_fops, data));
2162 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2164 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2166 if (value >= OBD_HIST_MAX)
2167 value = OBD_HIST_MAX - 1;
2169 cfs_spin_lock(&oh->oh_lock);
2170 oh->oh_buckets[value]++;
2171 cfs_spin_unlock(&oh->oh_lock);
2173 EXPORT_SYMBOL(lprocfs_oh_tally);
2175 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2179 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2182 lprocfs_oh_tally(oh, val);
2184 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2186 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2188 unsigned long ret = 0;
2191 for (i = 0; i < OBD_HIST_MAX; i++)
2192 ret += oh->oh_buckets[i];
2195 EXPORT_SYMBOL(lprocfs_oh_sum);
2197 void lprocfs_oh_clear(struct obd_histogram *oh)
2199 cfs_spin_lock(&oh->oh_lock);
2200 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2201 cfs_spin_unlock(&oh->oh_lock);
2203 EXPORT_SYMBOL(lprocfs_oh_clear);
2205 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2206 int count, int *eof, void *data)
2208 struct obd_device *obd = data;
2214 c += cfs_hash_debug_header(page, count);
2215 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2216 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2217 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2218 #ifdef HAVE_QUOTA_SUPPORT
2219 if (obd->u.obt.obt_qctxt.lqc_lqs_hash)
2220 c += cfs_hash_debug_str(obd->u.obt.obt_qctxt.lqc_lqs_hash,
2221 page + c, count - c);
2226 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2228 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2229 int count, int *eof, void *data)
2231 struct obd_device *obd = data;
2234 LASSERT(obd != NULL);
2235 LASSERT(count >= 0);
2237 /* Set start of user data returned to
2238 page + off since the user may have
2239 requested to read much smaller than
2240 what we need to read */
2241 *start = page + off;
2243 /* We know we are allocated a page here.
2244 Also we know that this function will
2245 not need to write more than a page
2246 so we can truncate at CFS_PAGE_SIZE. */
2247 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2249 /* Initialize the page */
2250 memset(page, 0, size);
2252 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2254 if (obd->obd_max_recoverable_clients == 0) {
2255 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2261 /* sampled unlocked, but really... */
2262 if (obd->obd_recovering == 0) {
2263 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2265 if (lprocfs_obd_snprintf(&page, size, &len,
2266 "recovery_start: %lu\n",
2267 obd->obd_recovery_start) <= 0)
2269 if (lprocfs_obd_snprintf(&page, size, &len,
2270 "recovery_duration: %lu\n",
2271 obd->obd_recovery_end -
2272 obd->obd_recovery_start) <= 0)
2274 /* Number of clients that have completed recovery */
2275 if (lprocfs_obd_snprintf(&page, size, &len,
2276 "completed_clients: %d/%d\n",
2277 obd->obd_max_recoverable_clients -
2278 obd->obd_stale_clients,
2279 obd->obd_max_recoverable_clients) <= 0)
2281 if (lprocfs_obd_snprintf(&page, size, &len,
2282 "replayed_requests: %d\n",
2283 obd->obd_replayed_requests) <= 0)
2285 if (lprocfs_obd_snprintf(&page, size, &len,
2286 "last_transno: "LPD64"\n",
2287 obd->obd_next_recovery_transno - 1)<=0)
2289 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2290 obd->obd_version_recov ? "ON" : "OFF")<=0)
2292 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
2293 obd->obd_no_ir ? "OFF" : "ON") <= 0)
2298 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2300 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2301 obd->obd_recovery_start) <= 0)
2303 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2304 cfs_time_current_sec() >=
2305 obd->obd_recovery_start +
2306 obd->obd_recovery_timeout ? 0 :
2307 obd->obd_recovery_start +
2308 obd->obd_recovery_timeout -
2309 cfs_time_current_sec()) <= 0)
2311 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2312 cfs_atomic_read(&obd->obd_connected_clients),
2313 obd->obd_max_recoverable_clients) <= 0)
2315 /* Number of clients that have completed recovery */
2316 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2317 cfs_atomic_read(&obd->obd_req_replay_clients))
2320 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2321 cfs_atomic_read(&obd->obd_lock_replay_clients))
2324 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2325 cfs_atomic_read(&obd->obd_connected_clients) -
2326 cfs_atomic_read(&obd->obd_lock_replay_clients))
2329 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2330 obd->obd_stale_clients) <= 0)
2332 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2333 obd->obd_replayed_requests) <= 0)
2335 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2336 obd->obd_requests_queued_for_recovery) <= 0)
2339 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2340 obd->obd_next_recovery_transno) <= 0)
2346 return min(count, len - (int)off);
2348 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2350 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
2351 int count, int *eof, void *data)
2353 struct obd_device *obd = (struct obd_device *)data;
2354 LASSERT(obd != NULL);
2356 return snprintf(page, count, "%d\n",
2357 obd->obd_recovery_ir_factor);
2359 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
2361 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
2362 unsigned long count, void *data)
2364 struct obd_device *obd = (struct obd_device *)data;
2366 LASSERT(obd != NULL);
2368 rc = lprocfs_write_helper(buffer, count, &val);
2372 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
2375 obd->obd_recovery_ir_factor = val;
2378 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
2380 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
2381 int count, int *eof, void *data)
2383 struct obd_device *obd = (struct obd_device *)data;
2384 LASSERT(obd != NULL);
2386 return snprintf(page, count, "%d\n",
2387 obd->obd_recovery_timeout);
2389 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
2391 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
2392 unsigned long count, void *data)
2394 struct obd_device *obd = (struct obd_device *)data;
2396 LASSERT(obd != NULL);
2398 rc = lprocfs_write_helper(buffer, count, &val);
2402 obd->obd_recovery_timeout = val;
2405 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
2407 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
2408 int count, int *eof, void *data)
2410 struct obd_device *obd = data;
2411 LASSERT(obd != NULL);
2413 return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
2415 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
2417 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
2418 unsigned long count, void *data)
2420 struct obd_device *obd = data;
2422 LASSERT(obd != NULL);
2424 rc = lprocfs_write_helper(buffer, count, &val);
2428 obd->obd_recovery_time_hard = val;
2431 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
2433 int lprocfs_obd_rd_mntdev(char *page, char **start, off_t off,
2434 int count, int *eof, void *data)
2436 struct obd_device *obd = (struct obd_device *)data;
2438 LASSERT(obd != NULL);
2439 LASSERT(obd->u.obt.obt_vfsmnt->mnt_devname);
2441 return snprintf(page, count, "%s\n",
2442 obd->u.obt.obt_vfsmnt->mnt_devname);
2444 EXPORT_SYMBOL(lprocfs_obd_rd_mntdev);
2446 int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
2447 int count, int *eof, void *data)
2449 struct obd_device *dev = data;
2450 struct client_obd *cli = &dev->u.cli;
2453 client_obd_list_lock(&cli->cl_loi_list_lock);
2454 rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
2455 client_obd_list_unlock(&cli->cl_loi_list_lock);
2458 EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
2460 int lprocfs_obd_wr_max_pages_per_rpc(struct file *file, const char *buffer,
2461 unsigned long count, void *data)
2463 struct obd_device *dev = data;
2464 struct client_obd *cli = &dev->u.cli;
2465 struct obd_connect_data *ocd = &cli->cl_import->imp_connect_data;
2468 rc = lprocfs_write_helper(buffer, count, &val);
2472 LPROCFS_CLIMP_CHECK(dev);
2473 if (val < 1 || val > ocd->ocd_brw_size >> CFS_PAGE_SHIFT) {
2474 LPROCFS_CLIMP_EXIT(dev);
2477 client_obd_list_lock(&cli->cl_loi_list_lock);
2478 cli->cl_max_pages_per_rpc = val;
2479 client_obd_list_unlock(&cli->cl_loi_list_lock);
2481 LPROCFS_CLIMP_EXIT(dev);
2484 EXPORT_SYMBOL(lprocfs_obd_wr_max_pages_per_rpc);
2486 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
2487 int count, int *eof, void *data)
2489 struct obd_device *obd = (struct obd_device *)data;
2490 struct obd_device_target *target = &obd->u.obt;
2492 LASSERT(obd != NULL);
2493 LASSERT(target->obt_magic == OBT_MAGIC);
2495 return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
2497 EXPORT_SYMBOL(lprocfs_target_rd_instance);
2499 EXPORT_SYMBOL(lprocfs_register);
2500 EXPORT_SYMBOL(lprocfs_srch);
2501 EXPORT_SYMBOL(lprocfs_remove);
2502 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
2503 EXPORT_SYMBOL(lprocfs_add_vars);
2504 EXPORT_SYMBOL(lprocfs_obd_setup);
2505 EXPORT_SYMBOL(lprocfs_obd_cleanup);
2506 EXPORT_SYMBOL(lprocfs_add_simple);
2507 EXPORT_SYMBOL(lprocfs_add_symlink);
2508 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
2509 EXPORT_SYMBOL(lprocfs_alloc_stats);
2510 EXPORT_SYMBOL(lprocfs_free_stats);
2511 EXPORT_SYMBOL(lprocfs_clear_stats);
2512 EXPORT_SYMBOL(lprocfs_register_stats);
2513 EXPORT_SYMBOL(lprocfs_init_ops_stats);
2514 EXPORT_SYMBOL(lprocfs_init_mps_stats);
2515 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
2516 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
2517 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
2518 EXPORT_SYMBOL(lprocfs_free_obd_stats);
2519 EXPORT_SYMBOL(lprocfs_free_md_stats);
2520 EXPORT_SYMBOL(lprocfs_exp_setup);
2521 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2523 EXPORT_SYMBOL(lprocfs_rd_u64);
2524 EXPORT_SYMBOL(lprocfs_rd_atomic);
2525 EXPORT_SYMBOL(lprocfs_wr_atomic);
2526 EXPORT_SYMBOL(lprocfs_rd_uint);
2527 EXPORT_SYMBOL(lprocfs_wr_uint);
2528 EXPORT_SYMBOL(lprocfs_rd_uuid);
2529 EXPORT_SYMBOL(lprocfs_rd_name);
2530 EXPORT_SYMBOL(lprocfs_rd_fstype);
2531 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
2532 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
2533 EXPORT_SYMBOL(lprocfs_rd_num_exports);
2534 EXPORT_SYMBOL(lprocfs_rd_numrefs);
2535 EXPORT_SYMBOL(lprocfs_at_hist_helper);
2536 EXPORT_SYMBOL(lprocfs_rd_import);
2537 EXPORT_SYMBOL(lprocfs_rd_state);
2538 EXPORT_SYMBOL(lprocfs_rd_timeouts);
2539 EXPORT_SYMBOL(lprocfs_rd_blksize);
2540 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
2541 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
2542 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
2543 EXPORT_SYMBOL(lprocfs_rd_filestotal);
2544 EXPORT_SYMBOL(lprocfs_rd_filesfree);
2546 EXPORT_SYMBOL(lprocfs_write_helper);
2547 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2548 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2549 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2550 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2551 EXPORT_SYMBOL(lprocfs_stats_collect);