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 >= PAGE_CACHE_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, PAGE_CACHE_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 (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);
297 static int __lprocfs_add_vars(struct proc_dir_entry *root,
298 struct lprocfs_vars *list,
303 if (root == NULL || list == NULL)
306 while (list->name != NULL) {
307 struct proc_dir_entry *cur_root, *proc;
308 char *pathcopy, *cur, *next, pathbuf[64];
309 int pathsize = strlen(list->name) + 1;
314 /* need copy of path for strsep */
315 if (strlen(list->name) > sizeof(pathbuf) - 1) {
316 OBD_ALLOC(pathcopy, pathsize);
317 if (pathcopy == NULL)
318 GOTO(out, rc = -ENOMEM);
324 strcpy(pathcopy, list->name);
326 while (cur_root != NULL && (cur = strsep(&next, "/"))) {
327 if (*cur =='\0') /* skip double/trailing "/" */
330 proc = __lprocfs_srch(cur_root, cur);
331 CDEBUG(D_OTHER, "cur_root=%s, cur=%s, next=%s, (%s)\n",
332 cur_root->name, cur, next,
333 (proc ? "exists" : "new"));
335 cur_root = (proc ? proc :
336 proc_mkdir(cur, cur_root));
337 } else if (proc == NULL) {
339 if (list->proc_mode != 0000) {
340 mode = list->proc_mode;
344 if (list->write_fptr)
347 proc = create_proc_entry(cur, mode, cur_root);
351 if (pathcopy != pathbuf)
352 OBD_FREE(pathcopy, pathsize);
354 if (cur_root == NULL || proc == NULL) {
355 CERROR("LprocFS: No memory to create /proc entry %s",
357 GOTO(out, rc = -ENOMEM);
361 proc->proc_fops = list->fops;
363 proc->proc_fops = &lprocfs_generic_fops;
364 proc->read_proc = list->read_fptr;
365 proc->write_proc = list->write_fptr;
366 proc->data = (list->data ? list->data : data);
376 * \param root [in] The parent proc entry on which new entry will be added.
377 * \param list [in] Array of proc entries to be added.
378 * \param data [in] The argument to be passed when entries read/write routines
379 * are called through /proc file.
381 * \retval 0 on success
384 int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list,
389 LPROCFS_WRITE_ENTRY();
390 rc = __lprocfs_add_vars(root, list, data);
391 LPROCFS_WRITE_EXIT();
395 EXPORT_SYMBOL(lprocfs_add_vars);
397 void lprocfs_remove_nolock(struct proc_dir_entry **proot)
399 struct proc_dir_entry *root = *proot;
400 struct proc_dir_entry *temp = root;
401 struct proc_dir_entry *rm_entry;
402 struct proc_dir_entry *parent;
405 if (root == NULL || IS_ERR(root))
408 parent = root->parent;
409 LASSERT(parent != NULL);
412 while (temp->subdir != NULL)
418 /* Memory corruption once caused this to fail, and
419 without this LASSERT we would loop here forever. */
420 LASSERTF(strlen(rm_entry->name) == rm_entry->namelen,
421 "0x%p %s/%s len %d\n", rm_entry, temp->name,
422 rm_entry->name, (int)strlen(rm_entry->name));
424 remove_proc_entry(rm_entry->name, temp);
430 void lprocfs_remove(struct proc_dir_entry **rooth)
432 LPROCFS_WRITE_ENTRY(); /* search vs remove race */
433 lprocfs_remove_nolock(rooth);
434 LPROCFS_WRITE_EXIT();
436 EXPORT_SYMBOL(lprocfs_remove);
438 void lprocfs_remove_proc_entry(const char *name, struct proc_dir_entry *parent)
440 LASSERT(parent != NULL);
441 remove_proc_entry(name, parent);
443 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
445 void lprocfs_try_remove_proc_entry(const char *name,
446 struct proc_dir_entry *parent)
448 struct proc_dir_entry *t = NULL;
449 struct proc_dir_entry **p;
452 LASSERT(parent != NULL);
455 LPROCFS_WRITE_ENTRY();
457 /* lookup target name */
458 for (p = &parent->subdir; *p; p = &(*p)->next) {
459 if ((*p)->namelen != len)
461 if (memcmp(name, (*p)->name, len))
468 /* verify it's empty: do not count "num_refs" */
469 for (p = &t->subdir; *p; p = &(*p)->next) {
470 if ((*p)->namelen != strlen("num_refs")) {
474 if (memcmp("num_refs", (*p)->name,
475 strlen("num_refs"))) {
483 lprocfs_remove_nolock(&t);
485 LPROCFS_WRITE_EXIT();
489 EXPORT_SYMBOL(lprocfs_try_remove_proc_entry);
491 struct proc_dir_entry *lprocfs_register(const char *name,
492 struct proc_dir_entry *parent,
493 struct lprocfs_vars *list, void *data)
495 struct proc_dir_entry *entry;
498 LPROCFS_WRITE_ENTRY();
499 entry = __lprocfs_srch(parent, name);
501 CERROR("entry '%s' already registered\n", name);
502 GOTO(out, entry = ERR_PTR(-EALREADY));
505 entry = proc_mkdir(name, parent);
507 GOTO(out, entry = ERR_PTR(-ENOMEM));
510 rc = __lprocfs_add_vars(entry, list, data);
512 lprocfs_remove_nolock(&entry);
513 GOTO(out, entry = ERR_PTR(rc));
517 LPROCFS_WRITE_EXIT();
521 EXPORT_SYMBOL(lprocfs_register);
523 /* Generic callbacks */
524 int lprocfs_rd_uint(char *page, char **start, off_t off,
525 int count, int *eof, void *data)
527 unsigned int *temp = data;
528 return snprintf(page, count, "%u\n", *temp);
530 EXPORT_SYMBOL(lprocfs_rd_uint);
532 int lprocfs_wr_uint(struct file *file, const char *buffer,
533 unsigned long count, void *data)
536 char dummy[MAX_STRING_SIZE + 1], *end;
539 dummy[MAX_STRING_SIZE] = '\0';
540 if (copy_from_user(dummy, buffer, MAX_STRING_SIZE))
543 tmp = simple_strtoul(dummy, &end, 0);
547 *p = (unsigned int)tmp;
550 EXPORT_SYMBOL(lprocfs_wr_uint);
552 int lprocfs_rd_u64(char *page, char **start, off_t off,
553 int count, int *eof, void *data)
555 LASSERT(data != NULL);
557 return snprintf(page, count, LPU64"\n", *(__u64 *)data);
559 EXPORT_SYMBOL(lprocfs_rd_u64);
561 int lprocfs_rd_atomic(char *page, char **start, off_t off,
562 int count, int *eof, void *data)
564 cfs_atomic_t *atom = data;
565 LASSERT(atom != NULL);
567 return snprintf(page, count, "%d\n", cfs_atomic_read(atom));
569 EXPORT_SYMBOL(lprocfs_rd_atomic);
571 int lprocfs_wr_atomic(struct file *file, const char *buffer,
572 unsigned long count, void *data)
574 cfs_atomic_t *atm = data;
578 rc = lprocfs_write_helper(buffer, count, &val);
585 cfs_atomic_set(atm, val);
588 EXPORT_SYMBOL(lprocfs_wr_atomic);
590 int lprocfs_rd_uuid(char *page, char **start, off_t off, int count,
591 int *eof, void *data)
593 struct obd_device *obd = data;
595 LASSERT(obd != NULL);
597 return snprintf(page, count, "%s\n", obd->obd_uuid.uuid);
599 EXPORT_SYMBOL(lprocfs_rd_uuid);
601 int lprocfs_rd_name(char *page, char **start, off_t off, int count,
602 int *eof, void *data)
604 struct obd_device *dev = data;
606 LASSERT(dev != NULL);
608 return snprintf(page, count, "%s\n", dev->obd_name);
610 EXPORT_SYMBOL(lprocfs_rd_name);
612 int lprocfs_rd_blksize(char *page, char **start, off_t off, int count,
613 int *eof, void *data)
615 struct obd_device *obd = data;
616 struct obd_statfs osfs;
617 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
618 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
622 rc = snprintf(page, count, "%u\n", osfs.os_bsize);
626 EXPORT_SYMBOL(lprocfs_rd_blksize);
628 int lprocfs_rd_kbytestotal(char *page, char **start, off_t off, int count,
629 int *eof, void *data)
631 struct obd_device *obd = data;
632 struct obd_statfs osfs;
633 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
634 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
637 __u32 blk_size = osfs.os_bsize >> 10;
638 __u64 result = osfs.os_blocks;
640 while (blk_size >>= 1)
644 rc = snprintf(page, count, LPU64"\n", result);
648 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
650 int lprocfs_rd_kbytesfree(char *page, char **start, off_t off, int count,
651 int *eof, void *data)
653 struct obd_device *obd = data;
654 struct obd_statfs osfs;
655 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
656 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
659 __u32 blk_size = osfs.os_bsize >> 10;
660 __u64 result = osfs.os_bfree;
662 while (blk_size >>= 1)
666 rc = snprintf(page, count, LPU64"\n", result);
670 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
672 int lprocfs_rd_kbytesavail(char *page, char **start, off_t off, int count,
673 int *eof, void *data)
675 struct obd_device *obd = data;
676 struct obd_statfs osfs;
677 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
678 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
681 __u32 blk_size = osfs.os_bsize >> 10;
682 __u64 result = osfs.os_bavail;
684 while (blk_size >>= 1)
688 rc = snprintf(page, count, LPU64"\n", result);
692 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
694 int lprocfs_rd_filestotal(char *page, char **start, off_t off, int count,
695 int *eof, void *data)
697 struct obd_device *obd = data;
698 struct obd_statfs osfs;
699 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
700 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
704 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
709 EXPORT_SYMBOL(lprocfs_rd_filestotal);
711 int lprocfs_rd_filesfree(char *page, char **start, off_t off, int count,
712 int *eof, void *data)
714 struct obd_device *obd = data;
715 struct obd_statfs osfs;
716 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
717 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
721 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
725 EXPORT_SYMBOL(lprocfs_rd_filesfree);
727 int lprocfs_rd_server_uuid(char *page, char **start, off_t off, int count,
728 int *eof, void *data)
730 struct obd_device *obd = data;
731 struct obd_import *imp;
732 char *imp_state_name = NULL;
735 LASSERT(obd != NULL);
736 LPROCFS_CLIMP_CHECK(obd);
737 imp = obd->u.cli.cl_import;
738 imp_state_name = ptlrpc_import_state_name(imp->imp_state);
740 rc = snprintf(page, count, "%s\t%s%s\n",
741 obd2cli_tgt(obd), imp_state_name,
742 imp->imp_deactive ? "\tDEACTIVATED" : "");
744 LPROCFS_CLIMP_EXIT(obd);
747 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
749 int lprocfs_rd_conn_uuid(char *page, char **start, off_t off, int count,
750 int *eof, void *data)
752 struct obd_device *obd = data;
753 struct ptlrpc_connection *conn;
756 LASSERT(obd != NULL);
758 LPROCFS_CLIMP_CHECK(obd);
759 conn = obd->u.cli.cl_import->imp_connection;
761 if (conn && obd->u.cli.cl_import) {
762 rc = snprintf(page, count, "%s\n",
763 conn->c_remote_uuid.uuid);
765 rc = snprintf(page, count, "%s\n", "<none>");
768 LPROCFS_CLIMP_EXIT(obd);
771 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
773 /** add up per-cpu counters */
774 void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
775 struct lprocfs_counter *cnt)
777 unsigned int num_entry;
778 struct lprocfs_counter *percpu_cntr;
780 unsigned long flags = 0;
782 memset(cnt, 0, sizeof(*cnt));
785 /* set count to 1 to avoid divide-by-zero errs in callers */
790 cnt->lc_min = LC_MIN_INIT;
792 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
794 for (i = 0; i < num_entry; i++) {
795 if (stats->ls_percpu[i] == NULL)
797 percpu_cntr = lprocfs_stats_counter_get(stats, i, idx);
799 cnt->lc_count += percpu_cntr->lc_count;
800 cnt->lc_sum += percpu_cntr->lc_sum;
801 if (percpu_cntr->lc_min < cnt->lc_min)
802 cnt->lc_min = percpu_cntr->lc_min;
803 if (percpu_cntr->lc_max > cnt->lc_max)
804 cnt->lc_max = percpu_cntr->lc_max;
805 cnt->lc_sumsquare += percpu_cntr->lc_sumsquare;
808 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
810 EXPORT_SYMBOL(lprocfs_stats_collect);
813 * Append a space separated list of current set flags to str.
815 #define flag2str(flag) \
816 if (imp->imp_##flag && max - len > 0) \
817 len += snprintf(str + len, max - len, "%s" #flag, len ? ", " : "");
818 static int obd_import_flags2str(struct obd_import *imp, char *str, int max)
822 if (imp->imp_obd->obd_no_recov)
823 len += snprintf(str, max - len, "no_recov");
827 flag2str(replayable);
833 static const char *obd_connect_names[] = {
847 "join_file(obsolete)",
851 "remote_client_by_force",
860 "mds_mds_connection",
863 "alt_checksum_algorithm",
889 int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
894 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
896 ret += snprintf(page + ret, count - ret, "%s%s",
897 ret ? sep : "", obd_connect_names[i]);
899 if (flags & ~(mask - 1))
900 ret += snprintf(page + ret, count - ret,
901 "%sunknown flags "LPX64,
902 ret ? sep : "", flags & ~(mask - 1));
905 EXPORT_SYMBOL(obd_connect_flags2str);
907 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
908 int *eof, void *data)
910 struct lprocfs_counter ret;
911 struct lprocfs_counter_header *header;
912 struct obd_device *obd = (struct obd_device *)data;
913 struct obd_import *imp;
914 struct obd_import_conn *conn;
920 LASSERT(obd != NULL);
921 LPROCFS_CLIMP_CHECK(obd);
922 imp = obd->u.cli.cl_import;
925 i = snprintf(page, count,
934 ptlrpc_import_state_name(imp->imp_state),
935 imp->imp_connect_data.ocd_instance);
936 i += obd_connect_flags2str(page + i, count - i,
937 imp->imp_connect_data.ocd_connect_flags,
939 i += snprintf(page + i, count - i,
942 i += obd_import_flags2str(imp, page + i, count - i);
944 i += snprintf(page + i, count - i,
947 " failover_nids: [");
948 spin_lock(&imp->imp_lock);
950 cfs_list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
951 i += snprintf(page + i, count - i, "%s%s", j ? ", " : "",
952 libcfs_nid2str(conn->oic_conn->c_peer.nid));
955 i += snprintf(page + i, count - i,
957 " current_connection: %s\n"
958 " connection_attempts: %u\n"
960 " in-progress_invalidations: %u\n",
961 imp->imp_connection == NULL ? "<none>" :
962 libcfs_nid2str(imp->imp_connection->c_peer.nid),
965 cfs_atomic_read(&imp->imp_inval_count));
966 spin_unlock(&imp->imp_lock);
968 if (obd->obd_svc_stats == NULL)
971 header = &obd->obd_svc_stats->ls_cnt_header[PTLRPC_REQWAIT_CNTR];
972 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
973 if (ret.lc_count != 0) {
974 /* first argument to do_div MUST be __u64 */
975 __u64 sum = ret.lc_sum;
976 do_div(sum, ret.lc_count);
980 i += snprintf(page + i, count - i,
983 " unregistering: %u\n"
985 " avg_waittime: "LPU64" %s\n",
986 cfs_atomic_read(&imp->imp_inflight),
987 cfs_atomic_read(&imp->imp_unregistering),
988 cfs_atomic_read(&imp->imp_timeouts),
989 ret.lc_sum, header->lc_units);
992 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
993 if (imp->imp_at.iat_portal[j] == 0)
995 k = max_t(unsigned int, k,
996 at_get(&imp->imp_at.iat_service_estimate[j]));
998 i += snprintf(page + i, count - i,
999 " service_estimates:\n"
1000 " services: %u sec\n"
1001 " network: %u sec\n",
1003 at_get(&imp->imp_at.iat_net_latency));
1005 i += snprintf(page + i, count - i,
1007 " last_replay: "LPU64"\n"
1008 " peer_committed: "LPU64"\n"
1009 " last_checked: "LPU64"\n",
1010 imp->imp_last_replay_transno,
1011 imp->imp_peer_committed_transno,
1012 imp->imp_last_transno_checked);
1014 /* avg data rates */
1015 for (rw = 0; rw <= 1; rw++) {
1016 lprocfs_stats_collect(obd->obd_svc_stats,
1017 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
1019 if (ret.lc_sum > 0 && ret.lc_count > 0) {
1020 /* first argument to do_div MUST be __u64 */
1021 __u64 sum = ret.lc_sum;
1022 do_div(sum, ret.lc_count);
1024 i += snprintf(page + i, count - i,
1025 " %s_data_averages:\n"
1026 " bytes_per_rpc: "LPU64"\n",
1027 rw ? "write" : "read",
1030 k = (int)ret.lc_sum;
1031 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
1032 header = &obd->obd_svc_stats->ls_cnt_header[j];
1033 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
1034 if (ret.lc_sum > 0 && ret.lc_count != 0) {
1035 /* first argument to do_div MUST be __u64 */
1036 __u64 sum = ret.lc_sum;
1037 do_div(sum, ret.lc_count);
1039 i += snprintf(page + i, count - i,
1040 " %s_per_rpc: "LPU64"\n",
1041 header->lc_units, ret.lc_sum);
1042 j = (int)ret.lc_sum;
1044 i += snprintf(page + i, count - i,
1045 " MB_per_sec: %u.%.02u\n",
1046 k / j, (100 * k / j) % 100);
1051 LPROCFS_CLIMP_EXIT(obd);
1054 EXPORT_SYMBOL(lprocfs_rd_import);
1056 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
1057 int *eof, void *data)
1059 struct obd_device *obd = (struct obd_device *)data;
1060 struct obd_import *imp;
1063 LASSERT(obd != NULL);
1064 LPROCFS_CLIMP_CHECK(obd);
1065 imp = obd->u.cli.cl_import;
1068 i = snprintf(page, count, "current_state: %s\n",
1069 ptlrpc_import_state_name(imp->imp_state));
1070 i += snprintf(page + i, count - i,
1071 "state_history:\n");
1072 k = imp->imp_state_hist_idx;
1073 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
1074 struct import_state_hist *ish =
1075 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
1076 if (ish->ish_state == 0)
1078 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
1080 ptlrpc_import_state_name(ish->ish_state));
1083 LPROCFS_CLIMP_EXIT(obd);
1086 EXPORT_SYMBOL(lprocfs_rd_state);
1088 int lprocfs_at_hist_helper(char *page, int count, int rc,
1089 struct adaptive_timeout *at)
1092 for (i = 0; i < AT_BINS; i++)
1093 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
1094 rc += snprintf(page + rc, count - rc, "\n");
1097 EXPORT_SYMBOL(lprocfs_at_hist_helper);
1099 /* See also ptlrpc_lprocfs_rd_timeouts */
1100 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
1101 int *eof, void *data)
1103 struct obd_device *obd = (struct obd_device *)data;
1104 struct obd_import *imp;
1105 unsigned int cur, worst;
1110 LASSERT(obd != NULL);
1111 LPROCFS_CLIMP_CHECK(obd);
1112 imp = obd->u.cli.cl_import;
1115 now = cfs_time_current_sec();
1117 /* Some network health info for kicks */
1118 s2dhms(&ts, now - imp->imp_last_reply_time);
1119 rc += snprintf(page + rc, count - rc,
1120 "%-10s : %ld, "DHMS_FMT" ago\n",
1121 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
1123 cur = at_get(&imp->imp_at.iat_net_latency);
1124 worst = imp->imp_at.iat_net_latency.at_worst_ever;
1125 worstt = imp->imp_at.iat_net_latency.at_worst_time;
1126 s2dhms(&ts, now - worstt);
1127 rc += snprintf(page + rc, count - rc,
1128 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
1129 "network", cur, worst, worstt, DHMS_VARS(&ts));
1130 rc = lprocfs_at_hist_helper(page, count, rc,
1131 &imp->imp_at.iat_net_latency);
1133 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
1134 if (imp->imp_at.iat_portal[i] == 0)
1136 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
1137 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
1138 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
1139 s2dhms(&ts, now - worstt);
1140 rc += snprintf(page + rc, count - rc,
1141 "portal %-2d : cur %3u worst %3u (at %ld, "
1142 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
1143 cur, worst, worstt, DHMS_VARS(&ts));
1144 rc = lprocfs_at_hist_helper(page, count, rc,
1145 &imp->imp_at.iat_service_estimate[i]);
1148 LPROCFS_CLIMP_EXIT(obd);
1151 EXPORT_SYMBOL(lprocfs_rd_timeouts);
1153 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1154 int count, int *eof, void *data)
1156 struct obd_device *obd = data;
1160 LPROCFS_CLIMP_CHECK(obd);
1161 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1162 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1163 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1164 ret += snprintf(page + ret, count - ret, "\n");
1165 LPROCFS_CLIMP_EXIT(obd);
1168 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1170 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1171 int *eof, void *data)
1173 struct obd_device *obd = data;
1175 LASSERT(obd != NULL);
1177 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1179 EXPORT_SYMBOL(lprocfs_rd_num_exports);
1181 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1182 int *eof, void *data)
1184 struct obd_type *class = (struct obd_type*) data;
1186 LASSERT(class != NULL);
1188 return snprintf(page, count, "%d\n", class->typ_refcnt);
1190 EXPORT_SYMBOL(lprocfs_rd_numrefs);
1192 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1196 LASSERT(obd != NULL);
1197 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1198 LASSERT(obd->obd_type->typ_procroot != NULL);
1200 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1201 obd->obd_type->typ_procroot,
1203 if (IS_ERR(obd->obd_proc_entry)) {
1204 rc = PTR_ERR(obd->obd_proc_entry);
1205 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1206 obd->obd_proc_entry = NULL;
1210 EXPORT_SYMBOL(lprocfs_obd_setup);
1212 int lprocfs_obd_cleanup(struct obd_device *obd)
1216 if (obd->obd_proc_exports_entry) {
1217 /* Should be no exports left */
1218 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1219 lprocfs_remove(&obd->obd_proc_exports_entry);
1220 obd->obd_proc_exports_entry = NULL;
1222 if (obd->obd_proc_entry) {
1223 lprocfs_remove(&obd->obd_proc_entry);
1224 obd->obd_proc_entry = NULL;
1228 EXPORT_SYMBOL(lprocfs_obd_cleanup);
1230 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1232 CDEBUG(D_CONFIG, "stat %p - data %p/%p\n", client_stat,
1233 client_stat->nid_proc, client_stat->nid_stats);
1235 LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
1236 "nid %s:count %d\n", libcfs_nid2str(client_stat->nid),
1237 atomic_read(&client_stat->nid_exp_ref_count));
1239 if (client_stat->nid_proc)
1240 lprocfs_remove(&client_stat->nid_proc);
1242 if (client_stat->nid_stats)
1243 lprocfs_free_stats(&client_stat->nid_stats);
1245 if (client_stat->nid_ldlm_stats)
1246 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1248 OBD_FREE_PTR(client_stat);
1253 void lprocfs_free_per_client_stats(struct obd_device *obd)
1255 cfs_hash_t *hash = obd->obd_nid_stats_hash;
1256 struct nid_stat *stat;
1259 /* we need extra list - because hash_exit called to early */
1260 /* not need locking because all clients is died */
1261 while (!cfs_list_empty(&obd->obd_nid_stats)) {
1262 stat = cfs_list_entry(obd->obd_nid_stats.next,
1263 struct nid_stat, nid_list);
1264 cfs_list_del_init(&stat->nid_list);
1265 cfs_hash_del(hash, &stat->nid, &stat->nid_hash);
1266 lprocfs_free_client_stats(stat);
1270 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
1272 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1273 enum lprocfs_stats_flags flags)
1275 struct lprocfs_stats *stats;
1276 unsigned int num_entry;
1277 unsigned int percpusize = 0;
1283 if (lprocfs_no_percpu_stats != 0)
1284 flags |= LPROCFS_STATS_FLAG_NOPERCPU;
1286 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1289 num_entry = cfs_num_possible_cpus();
1291 /* alloc percpu pointers for all possible cpu slots */
1292 LIBCFS_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1296 stats->ls_num = num;
1297 stats->ls_flags = flags;
1298 spin_lock_init(&stats->ls_lock);
1300 /* alloc num of counter headers */
1301 LIBCFS_ALLOC(stats->ls_cnt_header,
1302 stats->ls_num * sizeof(struct lprocfs_counter_header));
1303 if (stats->ls_cnt_header == NULL)
1306 if ((flags & LPROCFS_STATS_FLAG_NOPERCPU) != 0) {
1307 /* contains only one set counters */
1308 percpusize = lprocfs_stats_counter_size(stats);
1309 LIBCFS_ALLOC_ATOMIC(stats->ls_percpu[0], percpusize);
1310 if (stats->ls_percpu[0] == NULL)
1312 stats->ls_biggest_alloc_num = 1;
1313 } else if ((flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0) {
1314 /* alloc all percpu data, currently only obd_memory use this */
1315 for (i = 0; i < num_entry; ++i)
1316 if (lprocfs_stats_alloc_one(stats, i) < 0)
1323 lprocfs_free_stats(&stats);
1326 EXPORT_SYMBOL(lprocfs_alloc_stats);
1328 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1330 struct lprocfs_stats *stats = *statsh;
1331 unsigned int num_entry;
1332 unsigned int percpusize;
1335 if (stats == NULL || stats->ls_num == 0)
1339 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1342 num_entry = cfs_num_possible_cpus();
1344 percpusize = lprocfs_stats_counter_size(stats);
1345 for (i = 0; i < num_entry; i++)
1346 if (stats->ls_percpu[i] != NULL)
1347 LIBCFS_FREE(stats->ls_percpu[i], percpusize);
1348 if (stats->ls_cnt_header != NULL)
1349 LIBCFS_FREE(stats->ls_cnt_header, stats->ls_num *
1350 sizeof(struct lprocfs_counter_header));
1351 LIBCFS_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1353 EXPORT_SYMBOL(lprocfs_free_stats);
1355 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1357 struct lprocfs_counter *percpu_cntr;
1360 unsigned int num_entry;
1361 unsigned long flags = 0;
1363 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1365 for (i = 0; i < num_entry; i++) {
1366 if (stats->ls_percpu[i] == NULL)
1368 for (j = 0; j < stats->ls_num; j++) {
1369 percpu_cntr = lprocfs_stats_counter_get(stats, i, j);
1370 percpu_cntr->lc_count = 0;
1371 percpu_cntr->lc_min = LC_MIN_INIT;
1372 percpu_cntr->lc_max = 0;
1373 percpu_cntr->lc_sumsquare = 0;
1374 percpu_cntr->lc_sum = 0;
1375 if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
1376 percpu_cntr->lc_sum_irq = 0;
1380 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1382 EXPORT_SYMBOL(lprocfs_clear_stats);
1384 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1385 size_t len, loff_t *off)
1387 struct seq_file *seq = file->private_data;
1388 struct lprocfs_stats *stats = seq->private;
1390 lprocfs_clear_stats(stats);
1395 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1397 struct lprocfs_stats *stats = p->private;
1399 return (*pos < stats->ls_num) ? pos : NULL;
1402 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1406 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1410 return lprocfs_stats_seq_start(p, pos);
1413 /* seq file export of one lprocfs counter */
1414 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1416 struct lprocfs_stats *stats = p->private;
1417 struct lprocfs_counter_header *hdr;
1418 struct lprocfs_counter ctr;
1419 int idx = *(loff_t *)v;
1425 cfs_gettimeofday(&now);
1426 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1427 "snapshot_time", now.tv_sec, now.tv_usec);
1432 hdr = &stats->ls_cnt_header[idx];
1433 lprocfs_stats_collect(stats, idx, &ctr);
1435 if (ctr.lc_count == 0)
1438 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", hdr->lc_name,
1439 ctr.lc_count, hdr->lc_units);
1443 if ((hdr->lc_config & LPROCFS_CNTR_AVGMINMAX) && ctr.lc_count > 0) {
1444 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1445 ctr.lc_min, ctr.lc_max, ctr.lc_sum);
1448 if (hdr->lc_config & LPROCFS_CNTR_STDDEV)
1449 rc = seq_printf(p, " "LPD64, ctr.lc_sumsquare);
1453 rc = seq_printf(p, "\n");
1455 return (rc < 0) ? rc : 0;
1458 struct seq_operations lprocfs_stats_seq_sops = {
1459 .start = lprocfs_stats_seq_start,
1460 .stop = lprocfs_stats_seq_stop,
1461 .next = lprocfs_stats_seq_next,
1462 .show = lprocfs_stats_seq_show,
1465 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1467 struct proc_dir_entry *dp = PDE(inode);
1468 struct seq_file *seq;
1471 if (LPROCFS_ENTRY_AND_CHECK(dp))
1474 rc = seq_open(file, &lprocfs_stats_seq_sops);
1479 seq = file->private_data;
1480 seq->private = dp->data;
1484 struct file_operations lprocfs_stats_seq_fops = {
1485 .owner = THIS_MODULE,
1486 .open = lprocfs_stats_seq_open,
1488 .write = lprocfs_stats_seq_write,
1489 .llseek = seq_lseek,
1490 .release = lprocfs_seq_release,
1493 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1494 struct lprocfs_stats *stats)
1496 struct proc_dir_entry *entry;
1497 LASSERT(root != NULL);
1499 LPROCFS_WRITE_ENTRY();
1500 entry = create_proc_entry(name, 0644, root);
1502 entry->proc_fops = &lprocfs_stats_seq_fops;
1503 entry->data = stats;
1506 LPROCFS_WRITE_EXIT();
1513 EXPORT_SYMBOL(lprocfs_register_stats);
1515 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1516 unsigned conf, const char *name, const char *units)
1518 struct lprocfs_counter_header *header;
1519 struct lprocfs_counter *percpu_cntr;
1520 unsigned long flags = 0;
1522 unsigned int num_cpu;
1524 LASSERT(stats != NULL);
1526 header = &stats->ls_cnt_header[index];
1527 LASSERTF(header != NULL, "Failed to allocate stats header:[%d]%s/%s\n",
1528 index, name, units);
1530 header->lc_config = conf;
1531 header->lc_name = name;
1532 header->lc_units = units;
1534 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1535 for (i = 0; i < num_cpu; ++i) {
1536 if (stats->ls_percpu[i] == NULL)
1538 percpu_cntr = lprocfs_stats_counter_get(stats, i, index);
1539 percpu_cntr->lc_count = 0;
1540 percpu_cntr->lc_min = LC_MIN_INIT;
1541 percpu_cntr->lc_max = 0;
1542 percpu_cntr->lc_sumsquare = 0;
1543 percpu_cntr->lc_sum = 0;
1544 if ((stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
1545 percpu_cntr->lc_sum_irq = 0;
1547 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1549 EXPORT_SYMBOL(lprocfs_counter_init);
1551 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1553 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1554 LASSERT(coffset < stats->ls_num); \
1555 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1558 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1560 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1561 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1562 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1563 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1564 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1565 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1566 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1567 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1568 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1569 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1570 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1571 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1572 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1573 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1574 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1575 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1576 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1577 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1578 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1579 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1580 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1581 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1582 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1583 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1584 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1585 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1586 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1587 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1588 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1589 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1590 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1591 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1592 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1593 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1594 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1595 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1596 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1597 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1598 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1599 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1600 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1601 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1602 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1603 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
1604 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1605 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1606 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1607 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1608 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1609 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1610 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1611 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1612 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1613 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1614 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1615 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1616 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1617 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1618 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1619 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1620 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1621 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1622 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1623 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1624 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1625 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1626 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1628 EXPORT_SYMBOL(lprocfs_init_ops_stats);
1630 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1632 struct lprocfs_stats *stats;
1633 unsigned int num_stats;
1636 LASSERT(obd->obd_stats == NULL);
1637 LASSERT(obd->obd_proc_entry != NULL);
1638 LASSERT(obd->obd_cntr_base == 0);
1640 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1641 num_private_stats - 1 /* o_owner */;
1642 stats = lprocfs_alloc_stats(num_stats, 0);
1646 lprocfs_init_ops_stats(num_private_stats, stats);
1648 for (i = num_private_stats; i < num_stats; i++) {
1649 /* If this LBUGs, it is likely that an obd
1650 * operation was added to struct obd_ops in
1651 * <obd.h>, and that the corresponding line item
1652 * LPROCFS_OBD_OP_INIT(.., .., opname)
1653 * is missing from the list above. */
1654 LASSERTF(stats->ls_cnt_header[i].lc_name != NULL,
1655 "Missing obd_stat initializer obd_op "
1656 "operation at offset %d.\n", i - num_private_stats);
1658 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1660 lprocfs_free_stats(&stats);
1662 obd->obd_stats = stats;
1663 obd->obd_cntr_base = num_private_stats;
1667 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
1669 void lprocfs_free_obd_stats(struct obd_device *obd)
1672 lprocfs_free_stats(&obd->obd_stats);
1674 EXPORT_SYMBOL(lprocfs_free_obd_stats);
1676 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1678 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1679 LASSERT(coffset < stats->ls_num); \
1680 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1683 void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats)
1685 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1686 LPROCFS_MD_OP_INIT(num_private_stats, stats, null_inode);
1687 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
1688 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1689 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1690 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1691 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1692 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1693 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1694 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1695 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1696 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1697 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1698 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1699 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1700 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1701 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1702 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1703 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1704 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1705 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1706 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1707 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1708 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1709 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1710 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1711 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1712 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1713 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1714 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1715 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1716 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1718 EXPORT_SYMBOL(lprocfs_init_mps_stats);
1720 int lprocfs_alloc_md_stats(struct obd_device *obd,
1721 unsigned num_private_stats)
1723 struct lprocfs_stats *stats;
1724 unsigned int num_stats;
1727 LASSERT(obd->md_stats == NULL);
1728 LASSERT(obd->obd_proc_entry != NULL);
1729 LASSERT(obd->md_cntr_base == 0);
1731 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1733 stats = lprocfs_alloc_stats(num_stats, 0);
1737 lprocfs_init_mps_stats(num_private_stats, stats);
1739 for (i = num_private_stats; i < num_stats; i++) {
1740 if (stats->ls_cnt_header[i].lc_name == NULL) {
1741 CERROR("Missing md_stat initializer md_op "
1742 "operation at offset %d. Aborting.\n",
1743 i - num_private_stats);
1747 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1749 lprocfs_free_stats(&stats);
1751 obd->md_stats = stats;
1752 obd->md_cntr_base = num_private_stats;
1756 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
1758 void lprocfs_free_md_stats(struct obd_device *obd)
1760 struct lprocfs_stats *stats = obd->md_stats;
1762 if (stats != NULL) {
1763 obd->md_stats = NULL;
1764 obd->md_cntr_base = 0;
1765 lprocfs_free_stats(&stats);
1768 EXPORT_SYMBOL(lprocfs_free_md_stats);
1770 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1772 lprocfs_counter_init(ldlm_stats,
1773 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1774 0, "ldlm_enqueue", "reqs");
1775 lprocfs_counter_init(ldlm_stats,
1776 LDLM_CONVERT - LDLM_FIRST_OPC,
1777 0, "ldlm_convert", "reqs");
1778 lprocfs_counter_init(ldlm_stats,
1779 LDLM_CANCEL - LDLM_FIRST_OPC,
1780 0, "ldlm_cancel", "reqs");
1781 lprocfs_counter_init(ldlm_stats,
1782 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1783 0, "ldlm_bl_callback", "reqs");
1784 lprocfs_counter_init(ldlm_stats,
1785 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1786 0, "ldlm_cp_callback", "reqs");
1787 lprocfs_counter_init(ldlm_stats,
1788 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1789 0, "ldlm_gl_callback", "reqs");
1791 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
1793 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1794 int *eof, void *data)
1796 struct obd_export *exp = data;
1797 LASSERT(exp != NULL);
1799 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1802 struct exp_uuid_cb_data {
1810 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1811 int count, int *eof, int *len)
1813 cb_data->page = page;
1814 cb_data->count = count;
1819 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1820 cfs_hlist_node_t *hnode, void *cb_data)
1823 struct obd_export *exp = cfs_hash_object(hs, hnode);
1824 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1826 if (exp->exp_nid_stats)
1827 *data->len += snprintf((data->page + *data->len),
1828 data->count, "%s\n",
1829 obd_uuid2str(&exp->exp_client_uuid));
1833 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1834 int *eof, void *data)
1836 struct nid_stat *stats = (struct nid_stat *)data;
1837 struct exp_uuid_cb_data cb_data;
1838 struct obd_device *obd = stats->nid_obd;
1843 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1844 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1845 lprocfs_exp_print_uuid, &cb_data);
1846 return (*cb_data.len);
1849 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1850 cfs_hlist_node_t *hnode, void *cb_data)
1853 struct exp_uuid_cb_data *data = cb_data;
1854 struct obd_export *exp = cfs_hash_object(hs, hnode);
1856 if (exp->exp_lock_hash != NULL) {
1858 *data->len += cfs_hash_debug_header(data->page,
1861 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1868 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1869 int *eof, void *data)
1871 struct nid_stat *stats = (struct nid_stat *)data;
1872 struct exp_uuid_cb_data cb_data;
1873 struct obd_device *obd = stats->nid_obd;
1878 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1880 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1881 lprocfs_exp_print_hash, &cb_data);
1882 return (*cb_data.len);
1885 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1886 int count, int *eof, void *data)
1889 return snprintf(page, count, "%s\n",
1890 "Write into this file to clear all nid stats and "
1891 "stale nid entries");
1893 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1895 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1897 struct nid_stat *stat = obj;
1900 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
1901 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 1) {
1902 /* object has only hash references. */
1903 spin_lock(&stat->nid_obd->obd_nid_lock);
1904 cfs_list_move(&stat->nid_list, data);
1905 spin_unlock(&stat->nid_obd->obd_nid_lock);
1908 /* we has reference to object - only clear data*/
1909 if (stat->nid_stats)
1910 lprocfs_clear_stats(stat->nid_stats);
1915 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1916 unsigned long count, void *data)
1918 struct obd_device *obd = (struct obd_device *)data;
1919 struct nid_stat *client_stat;
1920 CFS_LIST_HEAD(free_list);
1922 cfs_hash_cond_del(obd->obd_nid_stats_hash,
1923 lprocfs_nid_stats_clear_write_cb, &free_list);
1925 while (!cfs_list_empty(&free_list)) {
1926 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
1928 cfs_list_del_init(&client_stat->nid_list);
1929 lprocfs_free_client_stats(client_stat);
1934 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1936 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1938 struct nid_stat *new_stat, *old_stat;
1939 struct obd_device *obd = NULL;
1940 cfs_proc_dir_entry_t *entry;
1941 char *buffer = NULL;
1947 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1948 !exp->exp_obd->obd_nid_stats_hash)
1951 /* not test against zero because eric say:
1952 * You may only test nid against another nid, or LNET_NID_ANY.
1953 * Anything else is nonsense.*/
1954 if (!nid || *nid == LNET_NID_ANY)
1959 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
1961 OBD_ALLOC_PTR(new_stat);
1962 if (new_stat == NULL)
1965 new_stat->nid = *nid;
1966 new_stat->nid_obd = exp->exp_obd;
1967 /* we need set default refcount to 1 to balance obd_disconnect */
1968 cfs_atomic_set(&new_stat->nid_exp_ref_count, 1);
1970 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
1971 nid, &new_stat->nid_hash);
1972 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
1973 old_stat, libcfs_nid2str(*nid),
1974 cfs_atomic_read(&new_stat->nid_exp_ref_count));
1976 /* We need to release old stats because lprocfs_exp_cleanup() hasn't
1977 * been and will never be called. */
1978 if (exp->exp_nid_stats) {
1979 nidstat_putref(exp->exp_nid_stats);
1980 exp->exp_nid_stats = NULL;
1983 /* Return -EALREADY here so that we know that the /proc
1984 * entry already has been created */
1985 if (old_stat != new_stat) {
1986 exp->exp_nid_stats = old_stat;
1987 GOTO(destroy_new, rc = -EALREADY);
1989 /* not found - create */
1990 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
1992 GOTO(destroy_new, rc = -ENOMEM);
1994 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
1995 new_stat->nid_proc = lprocfs_register(buffer,
1996 obd->obd_proc_exports_entry,
1998 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
2000 if (IS_ERR(new_stat->nid_proc)) {
2001 rc = PTR_ERR(new_stat->nid_proc);
2002 new_stat->nid_proc = NULL;
2003 CERROR("%s: cannot create proc entry for export %s: rc = %d\n",
2004 obd->obd_name, libcfs_nid2str(*nid), rc);
2005 GOTO(destroy_new_ns, rc);
2008 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
2009 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
2010 if (IS_ERR(entry)) {
2011 CWARN("Error adding the NID stats file\n");
2012 rc = PTR_ERR(entry);
2013 GOTO(destroy_new_ns, rc);
2016 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
2017 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
2018 if (IS_ERR(entry)) {
2019 CWARN("Error adding the hash file\n");
2020 rc = PTR_ERR(entry);
2021 GOTO(destroy_new_ns, rc);
2024 exp->exp_nid_stats = new_stat;
2026 /* protect competitive add to list, not need locking on destroy */
2027 spin_lock(&obd->obd_nid_lock);
2028 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
2029 spin_unlock(&obd->obd_nid_lock);
2034 if (new_stat->nid_proc != NULL)
2035 lprocfs_remove(&new_stat->nid_proc);
2036 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
2039 nidstat_putref(new_stat);
2040 OBD_FREE_PTR(new_stat);
2043 EXPORT_SYMBOL(lprocfs_exp_setup);
2045 int lprocfs_exp_cleanup(struct obd_export *exp)
2047 struct nid_stat *stat = exp->exp_nid_stats;
2049 if(!stat || !exp->exp_obd)
2052 nidstat_putref(exp->exp_nid_stats);
2053 exp->exp_nid_stats = NULL;
2057 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2059 int lprocfs_write_helper(const char *buffer, unsigned long count,
2062 return lprocfs_write_frac_helper(buffer, count, val, 1);
2064 EXPORT_SYMBOL(lprocfs_write_helper);
2066 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
2069 char kernbuf[20], *end, *pbuf;
2071 if (count > (sizeof(kernbuf) - 1))
2074 if (copy_from_user(kernbuf, buffer, count))
2077 kernbuf[count] = '\0';
2084 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2088 if (end != NULL && *end == '.') {
2089 int temp_val, pow = 1;
2093 if (strlen(pbuf) > 5)
2094 pbuf[5] = '\0'; /*only allow 5bits fractional*/
2096 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2099 for (i = 0; i < (end - pbuf); i++)
2102 *val += temp_val / pow;
2107 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2109 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
2112 long decimal_val, frac_val;
2118 decimal_val = val / mult;
2119 prtn = snprintf(buffer, count, "%ld", decimal_val);
2120 frac_val = val % mult;
2122 if (prtn < (count - 4) && frac_val > 0) {
2124 int i, temp_mult = 1, frac_bits = 0;
2126 temp_frac = frac_val * 10;
2127 buffer[prtn++] = '.';
2128 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
2129 /* only reserved 2 bits fraction */
2130 buffer[prtn++] ='0';
2135 * Need to think these cases :
2136 * 1. #echo x.00 > /proc/xxx output result : x
2137 * 2. #echo x.0x > /proc/xxx output result : x.0x
2138 * 3. #echo x.x0 > /proc/xxx output result : x.x
2139 * 4. #echo x.xx > /proc/xxx output result : x.xx
2140 * Only reserved 2 bits fraction.
2142 for (i = 0; i < (5 - prtn); i++)
2145 frac_bits = min((int)count - prtn, 3 - frac_bits);
2146 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
2147 frac_val * temp_mult / mult);
2150 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
2152 if (buffer[prtn] == '.') {
2159 buffer[prtn++] ='\n';
2162 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2164 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
2166 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
2168 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2170 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
2171 __u64 *val, int mult)
2173 char kernbuf[22], *end, *pbuf;
2174 __u64 whole, frac = 0, units;
2175 unsigned frac_d = 1;
2177 if (count > (sizeof(kernbuf) - 1))
2180 if (copy_from_user(kernbuf, buffer, count))
2183 kernbuf[count] = '\0';
2190 whole = simple_strtoull(pbuf, &end, 10);
2194 if (end != NULL && *end == '.') {
2198 /* need to limit frac_d to a __u32 */
2199 if (strlen(pbuf) > 10)
2202 frac = simple_strtoull(pbuf, &end, 10);
2203 /* count decimal places */
2204 for (i = 0; i < (end - pbuf); i++)
2221 /* Specified units override the multiplier */
2223 mult = mult < 0 ? -units : units;
2226 do_div(frac, frac_d);
2227 *val = whole * mult + frac;
2230 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2232 static char *lprocfs_strnstr(const char *s1, const char *s2, size_t len)
2241 if (!memcmp(s1, s2, l2))
2249 * Find the string \a name in the input \a buffer, and return a pointer to the
2250 * value immediately following \a name, reducing \a count appropriately.
2251 * If \a name is not found the original \a buffer is returned.
2253 char *lprocfs_find_named_value(const char *buffer, const char *name,
2254 unsigned long *count)
2257 size_t buflen = *count;
2259 /* there is no strnstr() in rhel5 and ubuntu kernels */
2260 val = lprocfs_strnstr(buffer, name, buflen);
2262 return (char *)buffer;
2264 val += strlen(name); /* skip prefix */
2265 while (val < buffer + buflen && isspace(*val)) /* skip separator */
2269 while (val < buffer + buflen && isalnum(*val)) {
2274 return val - *count;
2276 EXPORT_SYMBOL(lprocfs_find_named_value);
2278 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent,
2281 const struct file_operations *seq_fops,
2284 struct proc_dir_entry *entry;
2287 /* Disallow secretly (un)writable entries. */
2288 LASSERT((seq_fops->write == NULL) == ((mode & 0222) == 0));
2290 LPROCFS_WRITE_ENTRY();
2291 entry = create_proc_entry(name, mode, parent);
2293 entry->proc_fops = seq_fops;
2296 LPROCFS_WRITE_EXIT();
2303 EXPORT_SYMBOL(lprocfs_seq_create);
2305 int lprocfs_obd_seq_create(struct obd_device *dev,
2308 const struct file_operations *seq_fops,
2311 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2312 mode, seq_fops, data));
2314 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2316 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2318 if (value >= OBD_HIST_MAX)
2319 value = OBD_HIST_MAX - 1;
2321 spin_lock(&oh->oh_lock);
2322 oh->oh_buckets[value]++;
2323 spin_unlock(&oh->oh_lock);
2325 EXPORT_SYMBOL(lprocfs_oh_tally);
2327 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2331 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2334 lprocfs_oh_tally(oh, val);
2336 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2338 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2340 unsigned long ret = 0;
2343 for (i = 0; i < OBD_HIST_MAX; i++)
2344 ret += oh->oh_buckets[i];
2347 EXPORT_SYMBOL(lprocfs_oh_sum);
2349 void lprocfs_oh_clear(struct obd_histogram *oh)
2351 spin_lock(&oh->oh_lock);
2352 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2353 spin_unlock(&oh->oh_lock);
2355 EXPORT_SYMBOL(lprocfs_oh_clear);
2357 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2358 int count, int *eof, void *data)
2360 struct obd_device *obd = data;
2366 c += cfs_hash_debug_header(page, count);
2367 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2368 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2369 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2373 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2375 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2376 int count, int *eof, void *data)
2378 struct obd_device *obd = data;
2381 LASSERT(obd != NULL);
2382 LASSERT(count >= 0);
2384 /* Set start of user data returned to
2385 page + off since the user may have
2386 requested to read much smaller than
2387 what we need to read */
2388 *start = page + off;
2391 * We know we are allocated a page here.
2392 * Also we know that this function will
2393 * not need to write more than a page
2394 * so we can truncate at PAGE_CACHE_SIZE.
2396 size = min(count + (int)off + 1, (int)PAGE_CACHE_SIZE);
2398 /* Initialize the page */
2399 memset(page, 0, size);
2401 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2403 if (obd->obd_max_recoverable_clients == 0) {
2404 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2410 /* sampled unlocked, but really... */
2411 if (obd->obd_recovering == 0) {
2412 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2414 if (lprocfs_obd_snprintf(&page, size, &len,
2415 "recovery_start: %lu\n",
2416 obd->obd_recovery_start) <= 0)
2418 if (lprocfs_obd_snprintf(&page, size, &len,
2419 "recovery_duration: %lu\n",
2420 obd->obd_recovery_end -
2421 obd->obd_recovery_start) <= 0)
2423 /* Number of clients that have completed recovery */
2424 if (lprocfs_obd_snprintf(&page, size, &len,
2425 "completed_clients: %d/%d\n",
2426 obd->obd_max_recoverable_clients -
2427 obd->obd_stale_clients,
2428 obd->obd_max_recoverable_clients) <= 0)
2430 if (lprocfs_obd_snprintf(&page, size, &len,
2431 "replayed_requests: %d\n",
2432 obd->obd_replayed_requests) <= 0)
2434 if (lprocfs_obd_snprintf(&page, size, &len,
2435 "last_transno: "LPD64"\n",
2436 obd->obd_next_recovery_transno - 1)<=0)
2438 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2439 obd->obd_version_recov ?
2440 "ENABLED" : "DISABLED") <=0)
2442 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
2444 "DISABLED" : "ENABLED") <= 0)
2449 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2451 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2452 obd->obd_recovery_start) <= 0)
2454 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2455 cfs_time_current_sec() >=
2456 obd->obd_recovery_start +
2457 obd->obd_recovery_timeout ? 0 :
2458 obd->obd_recovery_start +
2459 obd->obd_recovery_timeout -
2460 cfs_time_current_sec()) <= 0)
2462 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2463 cfs_atomic_read(&obd->obd_connected_clients),
2464 obd->obd_max_recoverable_clients) <= 0)
2466 /* Number of clients that have completed recovery */
2467 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2468 cfs_atomic_read(&obd->obd_req_replay_clients))
2471 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2472 cfs_atomic_read(&obd->obd_lock_replay_clients))
2475 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2476 cfs_atomic_read(&obd->obd_connected_clients) -
2477 cfs_atomic_read(&obd->obd_lock_replay_clients))
2480 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2481 obd->obd_stale_clients) <= 0)
2483 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2484 obd->obd_replayed_requests) <= 0)
2486 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2487 obd->obd_requests_queued_for_recovery) <= 0)
2490 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2491 obd->obd_next_recovery_transno) <= 0)
2497 return min(count, len - (int)off);
2499 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2501 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
2502 int count, int *eof, void *data)
2504 struct obd_device *obd = (struct obd_device *)data;
2505 LASSERT(obd != NULL);
2507 return snprintf(page, count, "%d\n",
2508 obd->obd_recovery_ir_factor);
2510 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
2512 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
2513 unsigned long count, void *data)
2515 struct obd_device *obd = (struct obd_device *)data;
2517 LASSERT(obd != NULL);
2519 rc = lprocfs_write_helper(buffer, count, &val);
2523 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
2526 obd->obd_recovery_ir_factor = val;
2529 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
2531 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
2532 int count, int *eof, void *data)
2534 struct obd_device *obd = (struct obd_device *)data;
2535 LASSERT(obd != NULL);
2537 return snprintf(page, count, "%d\n",
2538 obd->obd_recovery_timeout);
2540 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
2542 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
2543 unsigned long count, void *data)
2545 struct obd_device *obd = (struct obd_device *)data;
2547 LASSERT(obd != NULL);
2549 rc = lprocfs_write_helper(buffer, count, &val);
2553 obd->obd_recovery_timeout = val;
2556 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
2558 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
2559 int count, int *eof, void *data)
2561 struct obd_device *obd = data;
2562 LASSERT(obd != NULL);
2564 return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
2566 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
2568 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
2569 unsigned long count, void *data)
2571 struct obd_device *obd = data;
2573 LASSERT(obd != NULL);
2575 rc = lprocfs_write_helper(buffer, count, &val);
2579 obd->obd_recovery_time_hard = val;
2582 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
2584 int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
2585 int count, int *eof, void *data)
2587 struct obd_device *dev = data;
2588 struct client_obd *cli = &dev->u.cli;
2591 client_obd_list_lock(&cli->cl_loi_list_lock);
2592 rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
2593 client_obd_list_unlock(&cli->cl_loi_list_lock);
2596 EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
2598 #ifdef HAVE_SERVER_SUPPORT
2599 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
2600 int count, int *eof, void *data)
2602 struct obd_device *obd = (struct obd_device *)data;
2603 struct obd_device_target *target = &obd->u.obt;
2605 LASSERT(obd != NULL);
2606 LASSERT(target->obt_magic == OBT_MAGIC);
2608 return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
2610 EXPORT_SYMBOL(lprocfs_target_rd_instance);