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, 2013, Intel Corporation.
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/lustre_idl.h>
53 static int lprocfs_no_percpu_stats = 0;
54 CFS_MODULE_PARM(lprocfs_no_percpu_stats, "i", int, 0644,
55 "Do not alloc percpu data for lprocfs stats");
57 #define MAX_STRING_SIZE 128
59 /* for bug 10866, global variable */
60 DECLARE_RWSEM(_lprocfs_lock);
61 EXPORT_SYMBOL(_lprocfs_lock);
63 int lprocfs_single_release(struct inode *inode, struct file *file)
66 return single_release(inode, file);
68 EXPORT_SYMBOL(lprocfs_single_release);
70 int lprocfs_seq_release(struct inode *inode, struct file *file)
73 return seq_release(inode, file);
75 EXPORT_SYMBOL(lprocfs_seq_release);
77 static struct proc_dir_entry *__lprocfs_srch(struct proc_dir_entry *head,
80 struct proc_dir_entry *temp;
86 while (temp != NULL) {
87 if (strcmp(temp->name, name) == 0) {
96 struct proc_dir_entry *lprocfs_srch(struct proc_dir_entry *head,
99 struct proc_dir_entry *temp;
101 LPROCFS_SRCH_ENTRY();
102 temp = __lprocfs_srch(head, name);
106 EXPORT_SYMBOL(lprocfs_srch);
108 /* lprocfs API calls */
110 /* Function that emulates snprintf but also has the side effect of advancing
111 the page pointer for the next write into the buffer, incrementing the total
112 length written to the buffer, and decrementing the size left in the
114 static int lprocfs_obd_snprintf(char **page, int end, int *len,
115 const char *format, ...)
123 va_start(list, format);
124 n = vsnprintf(*page, end - *len, format, list);
127 *page += n; *len += n;
131 cfs_proc_dir_entry_t *lprocfs_add_simple(struct proc_dir_entry *root,
133 read_proc_t *read_proc,
134 write_proc_t *write_proc,
136 struct file_operations *fops)
138 cfs_proc_dir_entry_t *proc;
141 if (root == NULL || name == NULL)
142 return ERR_PTR(-EINVAL);
149 LPROCFS_WRITE_ENTRY();
150 proc = create_proc_entry(name, mode, root);
152 CERROR("LprocFS: No memory to create /proc entry %s", name);
153 LPROCFS_WRITE_EXIT();
154 return ERR_PTR(-ENOMEM);
156 proc->read_proc = read_proc;
157 proc->write_proc = write_proc;
160 proc->proc_fops = fops;
161 LPROCFS_WRITE_EXIT();
164 EXPORT_SYMBOL(lprocfs_add_simple);
166 struct proc_dir_entry *lprocfs_add_symlink(const char *name,
167 struct proc_dir_entry *parent, const char *format, ...)
169 struct proc_dir_entry *entry;
173 if (parent == NULL || format == NULL)
176 OBD_ALLOC_WAIT(dest, MAX_STRING_SIZE + 1);
180 va_start(ap, format);
181 vsnprintf(dest, MAX_STRING_SIZE, format, ap);
184 entry = proc_symlink(name, parent, dest);
186 CERROR("LprocFS: Could not create symbolic link from %s to %s",
189 OBD_FREE(dest, MAX_STRING_SIZE + 1);
192 EXPORT_SYMBOL(lprocfs_add_symlink);
194 static ssize_t lprocfs_fops_read(struct file *f, char __user *buf,
195 size_t size, loff_t *ppos)
197 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
198 char *page, *start = NULL;
199 int rc = 0, eof = 1, count;
201 if (*ppos >= CFS_PAGE_SIZE)
204 page = (char *)__get_free_page(GFP_KERNEL);
208 if (LPROCFS_ENTRY_AND_CHECK(dp)) {
213 OBD_FAIL_TIMEOUT(OBD_FAIL_LPROC_REMOVE, 10);
215 rc = dp->read_proc(page, &start, *ppos, CFS_PAGE_SIZE,
221 /* for lustre proc read, the read count must be less than PAGE_SIZE */
230 start = page + *ppos;
231 } else if (start < page) {
235 count = (rc < size) ? rc : size;
236 if (cfs_copy_to_user(buf, start, count)) {
243 free_page((unsigned long)page);
247 static ssize_t lprocfs_fops_write(struct file *f, const char __user *buf,
248 size_t size, loff_t *ppos)
250 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
253 if (LPROCFS_ENTRY_AND_CHECK(dp))
256 rc = dp->write_proc(f, buf, size, dp->data);
261 static struct file_operations lprocfs_generic_fops = {
262 .owner = THIS_MODULE,
263 .read = lprocfs_fops_read,
264 .write = lprocfs_fops_write,
267 int lprocfs_evict_client_open(struct inode *inode, struct file *f)
269 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
270 struct obd_device *obd = dp->data;
272 cfs_atomic_inc(&obd->obd_evict_inprogress);
277 int lprocfs_evict_client_release(struct inode *inode, struct file *f)
279 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
280 struct obd_device *obd = dp->data;
282 cfs_atomic_dec(&obd->obd_evict_inprogress);
283 cfs_waitq_signal(&obd->obd_evict_inprogress_waitq);
288 struct file_operations lprocfs_evict_client_fops = {
289 .owner = THIS_MODULE,
290 .read = lprocfs_fops_read,
291 .write = lprocfs_fops_write,
292 .open = lprocfs_evict_client_open,
293 .release = lprocfs_evict_client_release,
295 EXPORT_SYMBOL(lprocfs_evict_client_fops);
300 * \param root [in] The parent proc entry on which new entry will be added.
301 * \param list [in] Array of proc entries to be added.
302 * \param data [in] The argument to be passed when entries read/write routines
303 * are called through /proc file.
305 * \retval 0 on success
308 int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list,
313 if (root == NULL || list == NULL)
316 LPROCFS_WRITE_ENTRY();
317 while (list->name != NULL) {
318 struct proc_dir_entry *cur_root, *proc;
319 char *pathcopy, *cur, *next, pathbuf[64];
320 int pathsize = strlen(list->name) + 1;
325 /* need copy of path for strsep */
326 if (strlen(list->name) > sizeof(pathbuf) - 1) {
327 OBD_ALLOC(pathcopy, pathsize);
328 if (pathcopy == NULL)
329 GOTO(out, rc = -ENOMEM);
335 strcpy(pathcopy, list->name);
337 while (cur_root != NULL && (cur = strsep(&next, "/"))) {
338 if (*cur =='\0') /* skip double/trailing "/" */
341 proc = __lprocfs_srch(cur_root, cur);
342 CDEBUG(D_OTHER, "cur_root=%s, cur=%s, next=%s, (%s)\n",
343 cur_root->name, cur, next,
344 (proc ? "exists" : "new"));
346 cur_root = (proc ? proc :
347 proc_mkdir(cur, cur_root));
348 } else if (proc == NULL) {
350 if (list->proc_mode != 0000) {
351 mode = list->proc_mode;
355 if (list->write_fptr)
358 proc = create_proc_entry(cur, mode, cur_root);
362 if (pathcopy != pathbuf)
363 OBD_FREE(pathcopy, pathsize);
365 if (cur_root == NULL || proc == NULL) {
366 CERROR("LprocFS: No memory to create /proc entry %s",
368 GOTO(out, rc = -ENOMEM);
372 proc->proc_fops = list->fops;
374 proc->proc_fops = &lprocfs_generic_fops;
375 proc->read_proc = list->read_fptr;
376 proc->write_proc = list->write_fptr;
377 proc->data = (list->data ? list->data : data);
381 LPROCFS_WRITE_EXIT();
384 EXPORT_SYMBOL(lprocfs_add_vars);
386 void lprocfs_remove_nolock(struct proc_dir_entry **rooth)
388 struct proc_dir_entry *root = *rooth;
389 struct proc_dir_entry *temp = root;
390 struct proc_dir_entry *rm_entry;
391 struct proc_dir_entry *parent;
397 parent = root->parent;
398 LASSERT(parent != NULL);
401 while (temp->subdir != NULL)
407 /* Memory corruption once caused this to fail, and
408 without this LASSERT we would loop here forever. */
409 LASSERTF(strlen(rm_entry->name) == rm_entry->namelen,
410 "0x%p %s/%s len %d\n", rm_entry, temp->name,
411 rm_entry->name, (int)strlen(rm_entry->name));
413 remove_proc_entry(rm_entry->name, temp);
419 void lprocfs_remove(struct proc_dir_entry **rooth)
421 LPROCFS_WRITE_ENTRY(); /* search vs remove race */
422 lprocfs_remove_nolock(rooth);
423 LPROCFS_WRITE_EXIT();
425 EXPORT_SYMBOL(lprocfs_remove);
427 void lprocfs_remove_proc_entry(const char *name, struct proc_dir_entry *parent)
429 LASSERT(parent != NULL);
430 remove_proc_entry(name, parent);
432 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
434 void lprocfs_try_remove_proc_entry(const char *name,
435 struct proc_dir_entry *parent)
437 struct proc_dir_entry *t = NULL;
438 struct proc_dir_entry **p;
441 LASSERT(parent != NULL);
444 LPROCFS_WRITE_ENTRY();
446 /* lookup target name */
447 for (p = &parent->subdir; *p; p = &(*p)->next) {
448 if ((*p)->namelen != len)
450 if (memcmp(name, (*p)->name, len))
457 /* verify it's empty: do not count "num_refs" */
458 for (p = &t->subdir; *p; p = &(*p)->next) {
459 if ((*p)->namelen != strlen("num_refs")) {
463 if (memcmp("num_refs", (*p)->name,
464 strlen("num_refs"))) {
472 lprocfs_remove_nolock(&t);
474 LPROCFS_WRITE_EXIT();
478 EXPORT_SYMBOL(lprocfs_try_remove_proc_entry);
480 struct proc_dir_entry *lprocfs_register(const char *name,
481 struct proc_dir_entry *parent,
482 struct lprocfs_vars *list, void *data)
484 struct proc_dir_entry *newchild;
486 newchild = lprocfs_srch(parent, name);
487 if (newchild != NULL) {
488 CERROR(" Lproc: Attempting to register %s more than once \n",
490 return ERR_PTR(-EALREADY);
493 newchild = proc_mkdir(name, parent);
494 if (newchild != NULL && list != NULL) {
495 int rc = lprocfs_add_vars(newchild, list, data);
497 lprocfs_remove(&newchild);
503 EXPORT_SYMBOL(lprocfs_register);
505 /* Generic callbacks */
506 int lprocfs_rd_uint(char *page, char **start, off_t off,
507 int count, int *eof, void *data)
509 unsigned int *temp = data;
510 return snprintf(page, count, "%u\n", *temp);
512 EXPORT_SYMBOL(lprocfs_rd_uint);
514 int lprocfs_wr_uint(struct file *file, const char *buffer,
515 unsigned long count, void *data)
518 char dummy[MAX_STRING_SIZE + 1], *end;
521 dummy[MAX_STRING_SIZE] = '\0';
522 if (cfs_copy_from_user(dummy, buffer, MAX_STRING_SIZE))
525 tmp = simple_strtoul(dummy, &end, 0);
529 *p = (unsigned int)tmp;
532 EXPORT_SYMBOL(lprocfs_wr_uint);
534 int lprocfs_rd_u64(char *page, char **start, off_t off,
535 int count, int *eof, void *data)
537 LASSERT(data != NULL);
539 return snprintf(page, count, LPU64"\n", *(__u64 *)data);
541 EXPORT_SYMBOL(lprocfs_rd_u64);
543 int lprocfs_rd_atomic(char *page, char **start, off_t off,
544 int count, int *eof, void *data)
546 cfs_atomic_t *atom = data;
547 LASSERT(atom != NULL);
549 return snprintf(page, count, "%d\n", cfs_atomic_read(atom));
551 EXPORT_SYMBOL(lprocfs_rd_atomic);
553 int lprocfs_wr_atomic(struct file *file, const char *buffer,
554 unsigned long count, void *data)
556 cfs_atomic_t *atm = data;
560 rc = lprocfs_write_helper(buffer, count, &val);
567 cfs_atomic_set(atm, val);
570 EXPORT_SYMBOL(lprocfs_wr_atomic);
572 int lprocfs_rd_uuid(char *page, char **start, off_t off, int count,
573 int *eof, void *data)
575 struct obd_device *obd = data;
577 LASSERT(obd != NULL);
579 return snprintf(page, count, "%s\n", obd->obd_uuid.uuid);
581 EXPORT_SYMBOL(lprocfs_rd_uuid);
583 int lprocfs_rd_name(char *page, char **start, off_t off, int count,
584 int *eof, void *data)
586 struct obd_device *dev = data;
588 LASSERT(dev != NULL);
590 return snprintf(page, count, "%s\n", dev->obd_name);
592 EXPORT_SYMBOL(lprocfs_rd_name);
594 int lprocfs_rd_blksize(char *page, char **start, off_t off, int count,
595 int *eof, void *data)
597 struct obd_device *obd = data;
598 struct obd_statfs osfs;
599 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
600 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
604 rc = snprintf(page, count, "%u\n", osfs.os_bsize);
608 EXPORT_SYMBOL(lprocfs_rd_blksize);
610 int lprocfs_rd_kbytestotal(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_blocks;
622 while (blk_size >>= 1)
626 rc = snprintf(page, count, LPU64"\n", result);
630 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
632 int lprocfs_rd_kbytesfree(char *page, char **start, off_t off, int count,
633 int *eof, void *data)
635 struct obd_device *obd = data;
636 struct obd_statfs osfs;
637 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
638 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
641 __u32 blk_size = osfs.os_bsize >> 10;
642 __u64 result = osfs.os_bfree;
644 while (blk_size >>= 1)
648 rc = snprintf(page, count, LPU64"\n", result);
652 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
654 int lprocfs_rd_kbytesavail(char *page, char **start, off_t off, int count,
655 int *eof, void *data)
657 struct obd_device *obd = data;
658 struct obd_statfs osfs;
659 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
660 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
663 __u32 blk_size = osfs.os_bsize >> 10;
664 __u64 result = osfs.os_bavail;
666 while (blk_size >>= 1)
670 rc = snprintf(page, count, LPU64"\n", result);
674 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
676 int lprocfs_rd_filestotal(char *page, char **start, off_t off, int count,
677 int *eof, void *data)
679 struct obd_device *obd = data;
680 struct obd_statfs osfs;
681 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
682 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
686 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
691 EXPORT_SYMBOL(lprocfs_rd_filestotal);
693 int lprocfs_rd_filesfree(char *page, char **start, off_t off, int count,
694 int *eof, void *data)
696 struct obd_device *obd = data;
697 struct obd_statfs osfs;
698 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
699 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
703 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
707 EXPORT_SYMBOL(lprocfs_rd_filesfree);
709 int lprocfs_rd_server_uuid(char *page, char **start, off_t off, int count,
710 int *eof, void *data)
712 struct obd_device *obd = data;
713 struct obd_import *imp;
714 char *imp_state_name = NULL;
717 LASSERT(obd != NULL);
718 LPROCFS_CLIMP_CHECK(obd);
719 imp = obd->u.cli.cl_import;
720 imp_state_name = ptlrpc_import_state_name(imp->imp_state);
722 rc = snprintf(page, count, "%s\t%s%s\n",
723 obd2cli_tgt(obd), imp_state_name,
724 imp->imp_deactive ? "\tDEACTIVATED" : "");
726 LPROCFS_CLIMP_EXIT(obd);
729 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
731 int lprocfs_rd_conn_uuid(char *page, char **start, off_t off, int count,
732 int *eof, void *data)
734 struct obd_device *obd = data;
735 struct ptlrpc_connection *conn;
738 LASSERT(obd != NULL);
740 LPROCFS_CLIMP_CHECK(obd);
741 conn = obd->u.cli.cl_import->imp_connection;
743 if (conn && obd->u.cli.cl_import) {
744 rc = snprintf(page, count, "%s\n",
745 conn->c_remote_uuid.uuid);
747 rc = snprintf(page, count, "%s\n", "<none>");
750 LPROCFS_CLIMP_EXIT(obd);
753 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
755 /** add up per-cpu counters */
756 void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
757 struct lprocfs_counter *cnt)
759 unsigned int num_entry;
760 struct lprocfs_counter *percpu_cntr;
761 struct lprocfs_counter_header *cntr_header;
763 unsigned long flags = 0;
765 memset(cnt, 0, sizeof(*cnt));
768 /* set count to 1 to avoid divide-by-zero errs in callers */
773 cnt->lc_min = LC_MIN_INIT;
775 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
777 for (i = 0; i < num_entry; i++) {
778 if (stats->ls_percpu[i] == NULL)
780 cntr_header = &stats->ls_cnt_header[idx];
781 percpu_cntr = lprocfs_stats_counter_get(stats, i, idx);
783 cnt->lc_count += percpu_cntr->lc_count;
784 cnt->lc_sum += percpu_cntr->lc_sum;
785 if (percpu_cntr->lc_min < cnt->lc_min)
786 cnt->lc_min = percpu_cntr->lc_min;
787 if (percpu_cntr->lc_max > cnt->lc_max)
788 cnt->lc_max = percpu_cntr->lc_max;
789 cnt->lc_sumsquare += percpu_cntr->lc_sumsquare;
792 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
794 EXPORT_SYMBOL(lprocfs_stats_collect);
797 * Append a space separated list of current set flags to str.
799 #define flag2str(flag) \
800 if (imp->imp_##flag && max - len > 0) \
801 len += snprintf(str + len, max - len, "%s" #flag, len ? ", " : "");
802 static int obd_import_flags2str(struct obd_import *imp, char *str, int max)
806 if (imp->imp_obd->obd_no_recov)
807 len += snprintf(str, max - len, "no_recov");
811 flag2str(replayable);
817 static const char *obd_connect_names[] = {
831 "join_file(obsolete)",
835 "remote_client_by_force",
844 "mds_mds_connection",
847 "alt_checksum_algorithm",
873 int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
878 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
880 ret += snprintf(page + ret, count - ret, "%s%s",
881 ret ? sep : "", obd_connect_names[i]);
883 if (flags & ~(mask - 1))
884 ret += snprintf(page + ret, count - ret,
885 "%sunknown flags "LPX64,
886 ret ? sep : "", flags & ~(mask - 1));
889 EXPORT_SYMBOL(obd_connect_flags2str);
891 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
892 int *eof, void *data)
894 struct lprocfs_counter ret;
895 struct lprocfs_counter_header *header;
896 struct obd_device *obd = (struct obd_device *)data;
897 struct obd_import *imp;
898 struct obd_import_conn *conn;
904 LASSERT(obd != NULL);
905 LPROCFS_CLIMP_CHECK(obd);
906 imp = obd->u.cli.cl_import;
909 i = snprintf(page, count,
918 ptlrpc_import_state_name(imp->imp_state),
919 imp->imp_connect_data.ocd_instance);
920 i += obd_connect_flags2str(page + i, count - i,
921 imp->imp_connect_data.ocd_connect_flags,
923 i += snprintf(page + i, count - i,
926 i += obd_import_flags2str(imp, page + i, count - i);
928 i += snprintf(page + i, count - i,
931 " failover_nids: [");
932 spin_lock(&imp->imp_lock);
934 cfs_list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
935 i += snprintf(page + i, count - i, "%s%s", j ? ", " : "",
936 libcfs_nid2str(conn->oic_conn->c_peer.nid));
939 i += snprintf(page + i, count - i,
941 " current_connection: %s\n"
942 " connection_attempts: %u\n"
944 " in-progress_invalidations: %u\n",
945 imp->imp_connection == NULL ? "<none>" :
946 libcfs_nid2str(imp->imp_connection->c_peer.nid),
949 cfs_atomic_read(&imp->imp_inval_count));
950 spin_unlock(&imp->imp_lock);
952 if (obd->obd_svc_stats == NULL)
955 header = &obd->obd_svc_stats->ls_cnt_header[PTLRPC_REQWAIT_CNTR];
956 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
957 if (ret.lc_count != 0) {
958 /* first argument to do_div MUST be __u64 */
959 __u64 sum = ret.lc_sum;
960 do_div(sum, ret.lc_count);
964 i += snprintf(page + i, count - i,
967 " unregistering: %u\n"
969 " avg_waittime: "LPU64" %s\n",
970 cfs_atomic_read(&imp->imp_inflight),
971 cfs_atomic_read(&imp->imp_unregistering),
972 cfs_atomic_read(&imp->imp_timeouts),
973 ret.lc_sum, header->lc_units);
976 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
977 if (imp->imp_at.iat_portal[j] == 0)
979 k = max_t(unsigned int, k,
980 at_get(&imp->imp_at.iat_service_estimate[j]));
982 i += snprintf(page + i, count - i,
983 " service_estimates:\n"
984 " services: %u sec\n"
985 " network: %u sec\n",
987 at_get(&imp->imp_at.iat_net_latency));
989 i += snprintf(page + i, count - i,
991 " last_replay: "LPU64"\n"
992 " peer_committed: "LPU64"\n"
993 " last_checked: "LPU64"\n",
994 imp->imp_last_replay_transno,
995 imp->imp_peer_committed_transno,
996 imp->imp_last_transno_checked);
999 for (rw = 0; rw <= 1; rw++) {
1000 lprocfs_stats_collect(obd->obd_svc_stats,
1001 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
1003 if (ret.lc_sum > 0 && ret.lc_count > 0) {
1004 /* first argument to do_div MUST be __u64 */
1005 __u64 sum = ret.lc_sum;
1006 do_div(sum, ret.lc_count);
1008 i += snprintf(page + i, count - i,
1009 " %s_data_averages:\n"
1010 " bytes_per_rpc: "LPU64"\n",
1011 rw ? "write" : "read",
1014 k = (int)ret.lc_sum;
1015 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
1016 header = &obd->obd_svc_stats->ls_cnt_header[j];
1017 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
1018 if (ret.lc_sum > 0 && ret.lc_count != 0) {
1019 /* first argument to do_div MUST be __u64 */
1020 __u64 sum = ret.lc_sum;
1021 do_div(sum, ret.lc_count);
1023 i += snprintf(page + i, count - i,
1024 " %s_per_rpc: "LPU64"\n",
1025 header->lc_units, ret.lc_sum);
1026 j = (int)ret.lc_sum;
1028 i += snprintf(page + i, count - i,
1029 " MB_per_sec: %u.%.02u\n",
1030 k / j, (100 * k / j) % 100);
1035 LPROCFS_CLIMP_EXIT(obd);
1038 EXPORT_SYMBOL(lprocfs_rd_import);
1040 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
1041 int *eof, void *data)
1043 struct obd_device *obd = (struct obd_device *)data;
1044 struct obd_import *imp;
1047 LASSERT(obd != NULL);
1048 LPROCFS_CLIMP_CHECK(obd);
1049 imp = obd->u.cli.cl_import;
1052 i = snprintf(page, count, "current_state: %s\n",
1053 ptlrpc_import_state_name(imp->imp_state));
1054 i += snprintf(page + i, count - i,
1055 "state_history:\n");
1056 k = imp->imp_state_hist_idx;
1057 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
1058 struct import_state_hist *ish =
1059 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
1060 if (ish->ish_state == 0)
1062 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
1064 ptlrpc_import_state_name(ish->ish_state));
1067 LPROCFS_CLIMP_EXIT(obd);
1070 EXPORT_SYMBOL(lprocfs_rd_state);
1072 int lprocfs_at_hist_helper(char *page, int count, int rc,
1073 struct adaptive_timeout *at)
1076 for (i = 0; i < AT_BINS; i++)
1077 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
1078 rc += snprintf(page + rc, count - rc, "\n");
1081 EXPORT_SYMBOL(lprocfs_at_hist_helper);
1083 /* See also ptlrpc_lprocfs_rd_timeouts */
1084 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
1085 int *eof, void *data)
1087 struct obd_device *obd = (struct obd_device *)data;
1088 struct obd_import *imp;
1089 unsigned int cur, worst;
1094 LASSERT(obd != NULL);
1095 LPROCFS_CLIMP_CHECK(obd);
1096 imp = obd->u.cli.cl_import;
1099 now = cfs_time_current_sec();
1101 /* Some network health info for kicks */
1102 s2dhms(&ts, now - imp->imp_last_reply_time);
1103 rc += snprintf(page + rc, count - rc,
1104 "%-10s : %ld, "DHMS_FMT" ago\n",
1105 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
1107 cur = at_get(&imp->imp_at.iat_net_latency);
1108 worst = imp->imp_at.iat_net_latency.at_worst_ever;
1109 worstt = imp->imp_at.iat_net_latency.at_worst_time;
1110 s2dhms(&ts, now - worstt);
1111 rc += snprintf(page + rc, count - rc,
1112 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
1113 "network", cur, worst, worstt, DHMS_VARS(&ts));
1114 rc = lprocfs_at_hist_helper(page, count, rc,
1115 &imp->imp_at.iat_net_latency);
1117 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
1118 if (imp->imp_at.iat_portal[i] == 0)
1120 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
1121 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
1122 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
1123 s2dhms(&ts, now - worstt);
1124 rc += snprintf(page + rc, count - rc,
1125 "portal %-2d : cur %3u worst %3u (at %ld, "
1126 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
1127 cur, worst, worstt, DHMS_VARS(&ts));
1128 rc = lprocfs_at_hist_helper(page, count, rc,
1129 &imp->imp_at.iat_service_estimate[i]);
1132 LPROCFS_CLIMP_EXIT(obd);
1135 EXPORT_SYMBOL(lprocfs_rd_timeouts);
1137 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1138 int count, int *eof, void *data)
1140 struct obd_device *obd = data;
1144 LPROCFS_CLIMP_CHECK(obd);
1145 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1146 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1147 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1148 ret += snprintf(page + ret, count - ret, "\n");
1149 LPROCFS_CLIMP_EXIT(obd);
1152 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1154 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1155 int *eof, void *data)
1157 struct obd_device *obd = data;
1159 LASSERT(obd != NULL);
1161 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1163 EXPORT_SYMBOL(lprocfs_rd_num_exports);
1165 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1166 int *eof, void *data)
1168 struct obd_type *class = (struct obd_type*) data;
1170 LASSERT(class != NULL);
1172 return snprintf(page, count, "%d\n", class->typ_refcnt);
1174 EXPORT_SYMBOL(lprocfs_rd_numrefs);
1176 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1180 LASSERT(obd != NULL);
1181 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1182 LASSERT(obd->obd_type->typ_procroot != NULL);
1184 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1185 obd->obd_type->typ_procroot,
1187 if (IS_ERR(obd->obd_proc_entry)) {
1188 rc = PTR_ERR(obd->obd_proc_entry);
1189 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1190 obd->obd_proc_entry = NULL;
1194 EXPORT_SYMBOL(lprocfs_obd_setup);
1196 int lprocfs_obd_cleanup(struct obd_device *obd)
1200 if (obd->obd_proc_exports_entry) {
1201 /* Should be no exports left */
1202 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1203 lprocfs_remove(&obd->obd_proc_exports_entry);
1204 obd->obd_proc_exports_entry = NULL;
1206 if (obd->obd_proc_entry) {
1207 lprocfs_remove(&obd->obd_proc_entry);
1208 obd->obd_proc_entry = NULL;
1212 EXPORT_SYMBOL(lprocfs_obd_cleanup);
1214 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1216 CDEBUG(D_CONFIG, "stat %p - data %p/%p\n", client_stat,
1217 client_stat->nid_proc, client_stat->nid_stats);
1219 LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
1220 "nid %s:count %d\n", libcfs_nid2str(client_stat->nid),
1221 atomic_read(&client_stat->nid_exp_ref_count));
1223 if (client_stat->nid_proc)
1224 lprocfs_remove(&client_stat->nid_proc);
1226 if (client_stat->nid_stats)
1227 lprocfs_free_stats(&client_stat->nid_stats);
1229 if (client_stat->nid_ldlm_stats)
1230 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1232 OBD_FREE_PTR(client_stat);
1237 void lprocfs_free_per_client_stats(struct obd_device *obd)
1239 cfs_hash_t *hash = obd->obd_nid_stats_hash;
1240 struct nid_stat *stat;
1243 /* we need extra list - because hash_exit called to early */
1244 /* not need locking because all clients is died */
1245 while (!cfs_list_empty(&obd->obd_nid_stats)) {
1246 stat = cfs_list_entry(obd->obd_nid_stats.next,
1247 struct nid_stat, nid_list);
1248 cfs_list_del_init(&stat->nid_list);
1249 cfs_hash_del(hash, &stat->nid, &stat->nid_hash);
1250 lprocfs_free_client_stats(stat);
1254 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
1256 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1257 enum lprocfs_stats_flags flags)
1259 struct lprocfs_stats *stats;
1260 unsigned int num_entry;
1261 unsigned int percpusize = 0;
1267 if (lprocfs_no_percpu_stats != 0)
1268 flags |= LPROCFS_STATS_FLAG_NOPERCPU;
1270 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1273 num_entry = cfs_num_possible_cpus();
1275 /* alloc percpu pointers for all possible cpu slots */
1276 LIBCFS_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1280 stats->ls_num = num;
1281 stats->ls_flags = flags;
1282 spin_lock_init(&stats->ls_lock);
1284 /* alloc num of counter headers */
1285 LIBCFS_ALLOC(stats->ls_cnt_header,
1286 stats->ls_num * sizeof(struct lprocfs_counter_header));
1287 if (stats->ls_cnt_header == NULL)
1290 if ((flags & LPROCFS_STATS_FLAG_NOPERCPU) != 0) {
1291 /* contains only one set counters */
1292 percpusize = lprocfs_stats_counter_size(stats);
1293 LIBCFS_ALLOC_ATOMIC(stats->ls_percpu[0], percpusize);
1294 if (stats->ls_percpu[0] == NULL)
1296 stats->ls_biggest_alloc_num = 1;
1297 } else if ((flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0) {
1298 /* alloc all percpu data, currently only obd_memory use this */
1299 for (i = 0; i < num_entry; ++i)
1300 if (lprocfs_stats_alloc_one(stats, i) < 0)
1307 lprocfs_free_stats(&stats);
1310 EXPORT_SYMBOL(lprocfs_alloc_stats);
1312 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1314 struct lprocfs_stats *stats = *statsh;
1315 unsigned int num_entry;
1316 unsigned int percpusize;
1319 if (stats == NULL || stats->ls_num == 0)
1323 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1326 num_entry = cfs_num_possible_cpus();
1328 percpusize = lprocfs_stats_counter_size(stats);
1329 for (i = 0; i < num_entry; i++)
1330 if (stats->ls_percpu[i] != NULL)
1331 LIBCFS_FREE(stats->ls_percpu[i], percpusize);
1332 if (stats->ls_cnt_header != NULL)
1333 LIBCFS_FREE(stats->ls_cnt_header, stats->ls_num *
1334 sizeof(struct lprocfs_counter_header));
1335 LIBCFS_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1337 EXPORT_SYMBOL(lprocfs_free_stats);
1339 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1341 struct lprocfs_counter *percpu_cntr;
1342 struct lprocfs_counter_header *header;
1345 unsigned int num_entry;
1346 unsigned long flags = 0;
1348 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1350 for (i = 0; i < num_entry; i++) {
1351 if (stats->ls_percpu[i] == NULL)
1353 for (j = 0; j < stats->ls_num; j++) {
1354 header = &stats->ls_cnt_header[j];
1355 percpu_cntr = lprocfs_stats_counter_get(stats, i, j);
1356 percpu_cntr->lc_count = 0;
1357 percpu_cntr->lc_min = LC_MIN_INIT;
1358 percpu_cntr->lc_max = 0;
1359 percpu_cntr->lc_sumsquare = 0;
1360 percpu_cntr->lc_sum = 0;
1361 if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
1362 percpu_cntr->lc_sum_irq = 0;
1366 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1368 EXPORT_SYMBOL(lprocfs_clear_stats);
1370 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1371 size_t len, loff_t *off)
1373 struct seq_file *seq = file->private_data;
1374 struct lprocfs_stats *stats = seq->private;
1376 lprocfs_clear_stats(stats);
1381 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1383 struct lprocfs_stats *stats = p->private;
1384 /* return 1st cpu location */
1385 return (*pos >= stats->ls_num) ? NULL :
1386 lprocfs_stats_counter_get(stats, 0, *pos);
1389 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1393 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1395 struct lprocfs_stats *stats = p->private;
1397 return (*pos >= stats->ls_num) ? NULL :
1398 lprocfs_stats_counter_get(stats, 0, *pos);
1401 /* seq file export of one lprocfs counter */
1402 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1404 struct lprocfs_stats *stats = p->private;
1405 struct lprocfs_counter *cntr = v;
1406 struct lprocfs_counter ret;
1407 struct lprocfs_counter_header *header;
1412 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
1414 cfs_gettimeofday(&now);
1415 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1416 "snapshot_time", now.tv_sec, now.tv_usec);
1420 entry_size = sizeof(*cntr);
1421 if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
1422 entry_size += sizeof(__s64);
1423 idx = ((void *)cntr - (void *)&(stats->ls_percpu[0])->lp_cntr[0]) /
1426 header = &stats->ls_cnt_header[idx];
1427 lprocfs_stats_collect(stats, idx, &ret);
1429 if (ret.lc_count == 0)
1432 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", header->lc_name,
1433 ret.lc_count, header->lc_units);
1438 if ((header->lc_config & LPROCFS_CNTR_AVGMINMAX) &&
1439 (ret.lc_count > 0)) {
1440 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1441 ret.lc_min, ret.lc_max, ret.lc_sum);
1444 if (header->lc_config & LPROCFS_CNTR_STDDEV)
1445 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1449 rc = seq_printf(p, "\n");
1451 return (rc < 0) ? rc : 0;
1454 struct seq_operations lprocfs_stats_seq_sops = {
1455 start: lprocfs_stats_seq_start,
1456 stop: lprocfs_stats_seq_stop,
1457 next: lprocfs_stats_seq_next,
1458 show: lprocfs_stats_seq_show,
1461 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1463 struct proc_dir_entry *dp = PDE(inode);
1464 struct seq_file *seq;
1467 if (LPROCFS_ENTRY_AND_CHECK(dp))
1470 rc = seq_open(file, &lprocfs_stats_seq_sops);
1475 seq = file->private_data;
1476 seq->private = dp->data;
1480 struct file_operations lprocfs_stats_seq_fops = {
1481 .owner = THIS_MODULE,
1482 .open = lprocfs_stats_seq_open,
1484 .write = lprocfs_stats_seq_write,
1485 .llseek = seq_lseek,
1486 .release = lprocfs_seq_release,
1489 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1490 struct lprocfs_stats *stats)
1492 struct proc_dir_entry *entry;
1493 LASSERT(root != NULL);
1495 LPROCFS_WRITE_ENTRY();
1496 entry = create_proc_entry(name, 0644, root);
1498 entry->proc_fops = &lprocfs_stats_seq_fops;
1499 entry->data = stats;
1502 LPROCFS_WRITE_EXIT();
1509 EXPORT_SYMBOL(lprocfs_register_stats);
1511 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1512 unsigned conf, const char *name, const char *units)
1514 struct lprocfs_counter_header *header;
1515 struct lprocfs_counter *percpu_cntr;
1516 unsigned long flags = 0;
1518 unsigned int num_cpu;
1520 LASSERT(stats != NULL);
1522 header = &stats->ls_cnt_header[index];
1523 LASSERTF(header != NULL, "Failed to allocate stats header:[%d]%s/%s\n",
1524 index, name, units);
1526 header->lc_config = conf;
1527 header->lc_name = name;
1528 header->lc_units = units;
1530 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1531 for (i = 0; i < num_cpu; ++i) {
1532 if (stats->ls_percpu[i] == NULL)
1534 percpu_cntr = lprocfs_stats_counter_get(stats, i, index);
1535 percpu_cntr->lc_count = 0;
1536 percpu_cntr->lc_min = LC_MIN_INIT;
1537 percpu_cntr->lc_max = 0;
1538 percpu_cntr->lc_sumsquare = 0;
1539 percpu_cntr->lc_sum = 0;
1540 if ((stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
1541 percpu_cntr->lc_sum_irq = 0;
1543 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1545 EXPORT_SYMBOL(lprocfs_counter_init);
1547 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1549 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1550 LASSERT(coffset < stats->ls_num); \
1551 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1554 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1556 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1557 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1558 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1559 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1560 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1561 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1562 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1563 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1564 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1565 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1566 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1567 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1568 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1569 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1570 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1571 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1572 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1573 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1574 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1575 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1576 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1577 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1578 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1579 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1580 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1581 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1582 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1583 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1584 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1585 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1586 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1587 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1588 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1589 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1590 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1591 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1592 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1593 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1594 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1595 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1596 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1597 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1598 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1599 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
1600 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1601 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1602 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1603 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1604 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1605 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1606 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1607 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1608 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1609 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1610 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1611 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1612 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1613 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1614 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1615 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1616 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1617 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1618 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1619 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1620 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1621 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1622 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1624 EXPORT_SYMBOL(lprocfs_init_ops_stats);
1626 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1628 struct lprocfs_stats *stats;
1629 unsigned int num_stats;
1632 LASSERT(obd->obd_stats == NULL);
1633 LASSERT(obd->obd_proc_entry != NULL);
1634 LASSERT(obd->obd_cntr_base == 0);
1636 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1637 num_private_stats - 1 /* o_owner */;
1638 stats = lprocfs_alloc_stats(num_stats, 0);
1642 lprocfs_init_ops_stats(num_private_stats, stats);
1644 for (i = num_private_stats; i < num_stats; i++) {
1645 /* If this LBUGs, it is likely that an obd
1646 * operation was added to struct obd_ops in
1647 * <obd.h>, and that the corresponding line item
1648 * LPROCFS_OBD_OP_INIT(.., .., opname)
1649 * is missing from the list above. */
1650 LASSERTF(stats->ls_cnt_header[i].lc_name != NULL,
1651 "Missing obd_stat initializer obd_op "
1652 "operation at offset %d.\n", i - num_private_stats);
1654 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1656 lprocfs_free_stats(&stats);
1658 obd->obd_stats = stats;
1659 obd->obd_cntr_base = num_private_stats;
1663 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
1665 void lprocfs_free_obd_stats(struct obd_device *obd)
1668 lprocfs_free_stats(&obd->obd_stats);
1670 EXPORT_SYMBOL(lprocfs_free_obd_stats);
1672 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1674 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1675 LASSERT(coffset < stats->ls_num); \
1676 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1679 void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats)
1681 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1682 LPROCFS_MD_OP_INIT(num_private_stats, stats, null_inode);
1683 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
1684 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1685 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1686 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1687 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1688 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1689 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1690 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1691 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1692 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1693 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1694 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1695 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1696 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1697 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1698 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1699 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1700 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1701 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1702 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1703 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1704 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1705 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1706 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1707 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1708 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1709 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1710 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1711 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1712 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1714 EXPORT_SYMBOL(lprocfs_init_mps_stats);
1716 int lprocfs_alloc_md_stats(struct obd_device *obd,
1717 unsigned num_private_stats)
1719 struct lprocfs_stats *stats;
1720 unsigned int num_stats;
1723 LASSERT(obd->md_stats == NULL);
1724 LASSERT(obd->obd_proc_entry != NULL);
1725 LASSERT(obd->md_cntr_base == 0);
1727 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1729 stats = lprocfs_alloc_stats(num_stats, 0);
1733 lprocfs_init_mps_stats(num_private_stats, stats);
1735 for (i = num_private_stats; i < num_stats; i++) {
1736 if (stats->ls_cnt_header[i].lc_name == NULL) {
1737 CERROR("Missing md_stat initializer md_op "
1738 "operation at offset %d. Aborting.\n",
1739 i - num_private_stats);
1743 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1745 lprocfs_free_stats(&stats);
1747 obd->md_stats = stats;
1748 obd->md_cntr_base = num_private_stats;
1752 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
1754 void lprocfs_free_md_stats(struct obd_device *obd)
1756 struct lprocfs_stats *stats = obd->md_stats;
1758 if (stats != NULL) {
1759 obd->md_stats = NULL;
1760 obd->md_cntr_base = 0;
1761 lprocfs_free_stats(&stats);
1764 EXPORT_SYMBOL(lprocfs_free_md_stats);
1766 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1768 lprocfs_counter_init(ldlm_stats,
1769 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1770 0, "ldlm_enqueue", "reqs");
1771 lprocfs_counter_init(ldlm_stats,
1772 LDLM_CONVERT - LDLM_FIRST_OPC,
1773 0, "ldlm_convert", "reqs");
1774 lprocfs_counter_init(ldlm_stats,
1775 LDLM_CANCEL - LDLM_FIRST_OPC,
1776 0, "ldlm_cancel", "reqs");
1777 lprocfs_counter_init(ldlm_stats,
1778 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1779 0, "ldlm_bl_callback", "reqs");
1780 lprocfs_counter_init(ldlm_stats,
1781 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1782 0, "ldlm_cp_callback", "reqs");
1783 lprocfs_counter_init(ldlm_stats,
1784 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1785 0, "ldlm_gl_callback", "reqs");
1787 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
1789 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1790 int *eof, void *data)
1792 struct obd_export *exp = data;
1793 LASSERT(exp != NULL);
1795 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1798 struct exp_uuid_cb_data {
1806 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1807 int count, int *eof, int *len)
1809 cb_data->page = page;
1810 cb_data->count = count;
1815 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1816 cfs_hlist_node_t *hnode, void *cb_data)
1819 struct obd_export *exp = cfs_hash_object(hs, hnode);
1820 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1822 if (exp->exp_nid_stats)
1823 *data->len += snprintf((data->page + *data->len),
1824 data->count, "%s\n",
1825 obd_uuid2str(&exp->exp_client_uuid));
1829 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1830 int *eof, void *data)
1832 struct nid_stat *stats = (struct nid_stat *)data;
1833 struct exp_uuid_cb_data cb_data;
1834 struct obd_device *obd = stats->nid_obd;
1839 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1840 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1841 lprocfs_exp_print_uuid, &cb_data);
1842 return (*cb_data.len);
1845 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1846 cfs_hlist_node_t *hnode, void *cb_data)
1849 struct exp_uuid_cb_data *data = cb_data;
1850 struct obd_export *exp = cfs_hash_object(hs, hnode);
1852 if (exp->exp_lock_hash != NULL) {
1854 *data->len += cfs_hash_debug_header(data->page,
1857 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1864 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1865 int *eof, void *data)
1867 struct nid_stat *stats = (struct nid_stat *)data;
1868 struct exp_uuid_cb_data cb_data;
1869 struct obd_device *obd = stats->nid_obd;
1874 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1876 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1877 lprocfs_exp_print_hash, &cb_data);
1878 return (*cb_data.len);
1881 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1882 int count, int *eof, void *data)
1885 return snprintf(page, count, "%s\n",
1886 "Write into this file to clear all nid stats and "
1887 "stale nid entries");
1889 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1891 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1893 struct nid_stat *stat = obj;
1896 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
1897 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 1) {
1898 /* object has only hash references. */
1899 spin_lock(&stat->nid_obd->obd_nid_lock);
1900 cfs_list_move(&stat->nid_list, data);
1901 spin_unlock(&stat->nid_obd->obd_nid_lock);
1904 /* we has reference to object - only clear data*/
1905 if (stat->nid_stats)
1906 lprocfs_clear_stats(stat->nid_stats);
1911 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1912 unsigned long count, void *data)
1914 struct obd_device *obd = (struct obd_device *)data;
1915 struct nid_stat *client_stat;
1916 CFS_LIST_HEAD(free_list);
1918 cfs_hash_cond_del(obd->obd_nid_stats_hash,
1919 lprocfs_nid_stats_clear_write_cb, &free_list);
1921 while (!cfs_list_empty(&free_list)) {
1922 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
1924 cfs_list_del_init(&client_stat->nid_list);
1925 lprocfs_free_client_stats(client_stat);
1930 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1932 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1934 struct nid_stat *new_stat, *old_stat;
1935 struct obd_device *obd = NULL;
1936 cfs_proc_dir_entry_t *entry;
1937 char *buffer = NULL;
1943 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1944 !exp->exp_obd->obd_nid_stats_hash)
1947 /* not test against zero because eric say:
1948 * You may only test nid against another nid, or LNET_NID_ANY.
1949 * Anything else is nonsense.*/
1950 if (!nid || *nid == LNET_NID_ANY)
1955 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
1957 OBD_ALLOC_PTR(new_stat);
1958 if (new_stat == NULL)
1961 new_stat->nid = *nid;
1962 new_stat->nid_obd = exp->exp_obd;
1963 /* we need set default refcount to 1 to balance obd_disconnect */
1964 cfs_atomic_set(&new_stat->nid_exp_ref_count, 1);
1966 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
1967 nid, &new_stat->nid_hash);
1968 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
1969 old_stat, libcfs_nid2str(*nid),
1970 cfs_atomic_read(&new_stat->nid_exp_ref_count));
1972 /* We need to release old stats because lprocfs_exp_cleanup() hasn't
1973 * been and will never be called. */
1974 if (exp->exp_nid_stats) {
1975 nidstat_putref(exp->exp_nid_stats);
1976 exp->exp_nid_stats = NULL;
1979 /* Return -EALREADY here so that we know that the /proc
1980 * entry already has been created */
1981 if (old_stat != new_stat) {
1982 exp->exp_nid_stats = old_stat;
1983 GOTO(destroy_new, rc = -EALREADY);
1985 /* not found - create */
1986 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
1988 GOTO(destroy_new, rc = -ENOMEM);
1990 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
1991 new_stat->nid_proc = lprocfs_register(buffer,
1992 obd->obd_proc_exports_entry,
1994 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
1996 if (new_stat->nid_proc == NULL) {
1997 CERROR("Error making export directory for nid %s\n",
1998 libcfs_nid2str(*nid));
1999 GOTO(destroy_new_ns, rc = -ENOMEM);
2002 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
2003 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
2004 if (IS_ERR(entry)) {
2005 CWARN("Error adding the NID stats file\n");
2006 rc = PTR_ERR(entry);
2007 GOTO(destroy_new_ns, rc);
2010 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
2011 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
2012 if (IS_ERR(entry)) {
2013 CWARN("Error adding the hash file\n");
2014 rc = PTR_ERR(entry);
2015 GOTO(destroy_new_ns, rc);
2018 exp->exp_nid_stats = new_stat;
2020 /* protect competitive add to list, not need locking on destroy */
2021 spin_lock(&obd->obd_nid_lock);
2022 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
2023 spin_unlock(&obd->obd_nid_lock);
2028 if (new_stat->nid_proc != NULL)
2029 lprocfs_remove(&new_stat->nid_proc);
2030 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
2033 nidstat_putref(new_stat);
2034 OBD_FREE_PTR(new_stat);
2037 EXPORT_SYMBOL(lprocfs_exp_setup);
2039 int lprocfs_exp_cleanup(struct obd_export *exp)
2041 struct nid_stat *stat = exp->exp_nid_stats;
2043 if(!stat || !exp->exp_obd)
2046 nidstat_putref(exp->exp_nid_stats);
2047 exp->exp_nid_stats = NULL;
2051 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2053 int lprocfs_write_helper(const char *buffer, unsigned long count,
2056 return lprocfs_write_frac_helper(buffer, count, val, 1);
2058 EXPORT_SYMBOL(lprocfs_write_helper);
2060 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
2063 char kernbuf[20], *end, *pbuf;
2065 if (count > (sizeof(kernbuf) - 1))
2068 if (cfs_copy_from_user(kernbuf, buffer, count))
2071 kernbuf[count] = '\0';
2078 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2082 if (end != NULL && *end == '.') {
2083 int temp_val, pow = 1;
2087 if (strlen(pbuf) > 5)
2088 pbuf[5] = '\0'; /*only allow 5bits fractional*/
2090 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2093 for (i = 0; i < (end - pbuf); i++)
2096 *val += temp_val / pow;
2101 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2103 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
2106 long decimal_val, frac_val;
2112 decimal_val = val / mult;
2113 prtn = snprintf(buffer, count, "%ld", decimal_val);
2114 frac_val = val % mult;
2116 if (prtn < (count - 4) && frac_val > 0) {
2118 int i, temp_mult = 1, frac_bits = 0;
2120 temp_frac = frac_val * 10;
2121 buffer[prtn++] = '.';
2122 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
2123 /* only reserved 2 bits fraction */
2124 buffer[prtn++] ='0';
2129 * Need to think these cases :
2130 * 1. #echo x.00 > /proc/xxx output result : x
2131 * 2. #echo x.0x > /proc/xxx output result : x.0x
2132 * 3. #echo x.x0 > /proc/xxx output result : x.x
2133 * 4. #echo x.xx > /proc/xxx output result : x.xx
2134 * Only reserved 2 bits fraction.
2136 for (i = 0; i < (5 - prtn); i++)
2139 frac_bits = min((int)count - prtn, 3 - frac_bits);
2140 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
2141 frac_val * temp_mult / mult);
2144 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
2146 if (buffer[prtn] == '.') {
2153 buffer[prtn++] ='\n';
2156 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2158 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
2160 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
2162 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2164 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
2165 __u64 *val, int mult)
2167 char kernbuf[22], *end, *pbuf;
2168 __u64 whole, frac = 0, units;
2169 unsigned frac_d = 1;
2171 if (count > (sizeof(kernbuf) - 1))
2174 if (cfs_copy_from_user(kernbuf, buffer, count))
2177 kernbuf[count] = '\0';
2184 whole = simple_strtoull(pbuf, &end, 10);
2188 if (end != NULL && *end == '.') {
2192 /* need to limit frac_d to a __u32 */
2193 if (strlen(pbuf) > 10)
2196 frac = simple_strtoull(pbuf, &end, 10);
2197 /* count decimal places */
2198 for (i = 0; i < (end - pbuf); i++)
2215 /* Specified units override the multiplier */
2217 mult = mult < 0 ? -units : units;
2220 do_div(frac, frac_d);
2221 *val = whole * mult + frac;
2224 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2226 static char *lprocfs_strnstr(const char *s1, const char *s2, size_t len)
2235 if (!memcmp(s1, s2, l2))
2243 * Find the string \a name in the input \a buffer, and return a pointer to the
2244 * value immediately following \a name, reducing \a count appropriately.
2245 * If \a name is not found the original \a buffer is returned.
2247 char *lprocfs_find_named_value(const char *buffer, const char *name,
2248 unsigned long *count)
2251 size_t buflen = *count;
2253 /* there is no strnstr() in rhel5 and ubuntu kernels */
2254 val = lprocfs_strnstr(buffer, name, buflen);
2256 return (char *)buffer;
2258 val += strlen(name); /* skip prefix */
2259 while (val < buffer + buflen && isspace(*val)) /* skip separator */
2263 while (val < buffer + buflen && isalnum(*val)) {
2268 return val - *count;
2270 EXPORT_SYMBOL(lprocfs_find_named_value);
2272 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent,
2275 const struct file_operations *seq_fops,
2278 struct proc_dir_entry *entry;
2281 /* Disallow secretly (un)writable entries. */
2282 LASSERT((seq_fops->write == NULL) == ((mode & 0222) == 0));
2284 LPROCFS_WRITE_ENTRY();
2285 entry = create_proc_entry(name, mode, parent);
2287 entry->proc_fops = seq_fops;
2290 LPROCFS_WRITE_EXIT();
2297 EXPORT_SYMBOL(lprocfs_seq_create);
2299 int lprocfs_obd_seq_create(struct obd_device *dev,
2302 const struct file_operations *seq_fops,
2305 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2306 mode, seq_fops, data));
2308 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2310 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2312 if (value >= OBD_HIST_MAX)
2313 value = OBD_HIST_MAX - 1;
2315 spin_lock(&oh->oh_lock);
2316 oh->oh_buckets[value]++;
2317 spin_unlock(&oh->oh_lock);
2319 EXPORT_SYMBOL(lprocfs_oh_tally);
2321 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2325 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2328 lprocfs_oh_tally(oh, val);
2330 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2332 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2334 unsigned long ret = 0;
2337 for (i = 0; i < OBD_HIST_MAX; i++)
2338 ret += oh->oh_buckets[i];
2341 EXPORT_SYMBOL(lprocfs_oh_sum);
2343 void lprocfs_oh_clear(struct obd_histogram *oh)
2345 spin_lock(&oh->oh_lock);
2346 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2347 spin_unlock(&oh->oh_lock);
2349 EXPORT_SYMBOL(lprocfs_oh_clear);
2351 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2352 int count, int *eof, void *data)
2354 struct obd_device *obd = data;
2360 c += cfs_hash_debug_header(page, count);
2361 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2362 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2363 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2367 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2369 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2370 int count, int *eof, void *data)
2372 struct obd_device *obd = data;
2375 LASSERT(obd != NULL);
2376 LASSERT(count >= 0);
2378 /* Set start of user data returned to
2379 page + off since the user may have
2380 requested to read much smaller than
2381 what we need to read */
2382 *start = page + off;
2384 /* We know we are allocated a page here.
2385 Also we know that this function will
2386 not need to write more than a page
2387 so we can truncate at CFS_PAGE_SIZE. */
2388 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2390 /* Initialize the page */
2391 memset(page, 0, size);
2393 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2395 if (obd->obd_max_recoverable_clients == 0) {
2396 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2402 /* sampled unlocked, but really... */
2403 if (obd->obd_recovering == 0) {
2404 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2406 if (lprocfs_obd_snprintf(&page, size, &len,
2407 "recovery_start: %lu\n",
2408 obd->obd_recovery_start) <= 0)
2410 if (lprocfs_obd_snprintf(&page, size, &len,
2411 "recovery_duration: %lu\n",
2412 obd->obd_recovery_end -
2413 obd->obd_recovery_start) <= 0)
2415 /* Number of clients that have completed recovery */
2416 if (lprocfs_obd_snprintf(&page, size, &len,
2417 "completed_clients: %d/%d\n",
2418 obd->obd_max_recoverable_clients -
2419 obd->obd_stale_clients,
2420 obd->obd_max_recoverable_clients) <= 0)
2422 if (lprocfs_obd_snprintf(&page, size, &len,
2423 "replayed_requests: %d\n",
2424 obd->obd_replayed_requests) <= 0)
2426 if (lprocfs_obd_snprintf(&page, size, &len,
2427 "last_transno: "LPD64"\n",
2428 obd->obd_next_recovery_transno - 1)<=0)
2430 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2431 obd->obd_version_recov ?
2432 "ENABLED" : "DISABLED") <=0)
2434 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
2436 "DISABLED" : "ENABLED") <= 0)
2441 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2443 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2444 obd->obd_recovery_start) <= 0)
2446 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2447 cfs_time_current_sec() >=
2448 obd->obd_recovery_start +
2449 obd->obd_recovery_timeout ? 0 :
2450 obd->obd_recovery_start +
2451 obd->obd_recovery_timeout -
2452 cfs_time_current_sec()) <= 0)
2454 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2455 cfs_atomic_read(&obd->obd_connected_clients),
2456 obd->obd_max_recoverable_clients) <= 0)
2458 /* Number of clients that have completed recovery */
2459 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2460 cfs_atomic_read(&obd->obd_req_replay_clients))
2463 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2464 cfs_atomic_read(&obd->obd_lock_replay_clients))
2467 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2468 cfs_atomic_read(&obd->obd_connected_clients) -
2469 cfs_atomic_read(&obd->obd_lock_replay_clients))
2472 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2473 obd->obd_stale_clients) <= 0)
2475 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2476 obd->obd_replayed_requests) <= 0)
2478 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2479 obd->obd_requests_queued_for_recovery) <= 0)
2482 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2483 obd->obd_next_recovery_transno) <= 0)
2489 return min(count, len - (int)off);
2491 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2493 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
2494 int count, int *eof, void *data)
2496 struct obd_device *obd = (struct obd_device *)data;
2497 LASSERT(obd != NULL);
2499 return snprintf(page, count, "%d\n",
2500 obd->obd_recovery_ir_factor);
2502 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
2504 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
2505 unsigned long count, void *data)
2507 struct obd_device *obd = (struct obd_device *)data;
2509 LASSERT(obd != NULL);
2511 rc = lprocfs_write_helper(buffer, count, &val);
2515 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
2518 obd->obd_recovery_ir_factor = val;
2521 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
2523 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
2524 int count, int *eof, void *data)
2526 struct obd_device *obd = (struct obd_device *)data;
2527 LASSERT(obd != NULL);
2529 return snprintf(page, count, "%d\n",
2530 obd->obd_recovery_timeout);
2532 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
2534 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
2535 unsigned long count, void *data)
2537 struct obd_device *obd = (struct obd_device *)data;
2539 LASSERT(obd != NULL);
2541 rc = lprocfs_write_helper(buffer, count, &val);
2545 obd->obd_recovery_timeout = val;
2548 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
2550 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
2551 int count, int *eof, void *data)
2553 struct obd_device *obd = data;
2554 LASSERT(obd != NULL);
2556 return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
2558 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
2560 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
2561 unsigned long count, void *data)
2563 struct obd_device *obd = data;
2565 LASSERT(obd != NULL);
2567 rc = lprocfs_write_helper(buffer, count, &val);
2571 obd->obd_recovery_time_hard = val;
2574 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
2576 int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
2577 int count, int *eof, void *data)
2579 struct obd_device *dev = data;
2580 struct client_obd *cli = &dev->u.cli;
2583 client_obd_list_lock(&cli->cl_loi_list_lock);
2584 rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
2585 client_obd_list_unlock(&cli->cl_loi_list_lock);
2588 EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
2590 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
2591 int count, int *eof, void *data)
2593 struct obd_device *obd = (struct obd_device *)data;
2594 struct obd_device_target *target = &obd->u.obt;
2596 LASSERT(obd != NULL);
2597 LASSERT(target->obt_magic == OBT_MAGIC);
2599 return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
2601 EXPORT_SYMBOL(lprocfs_target_rd_instance);