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",
890 int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
895 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
897 ret += snprintf(page + ret, count - ret, "%s%s",
898 ret ? sep : "", obd_connect_names[i]);
900 if (flags & ~(mask - 1))
901 ret += snprintf(page + ret, count - ret,
902 "%sunknown flags "LPX64,
903 ret ? sep : "", flags & ~(mask - 1));
906 EXPORT_SYMBOL(obd_connect_flags2str);
908 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
909 int *eof, void *data)
911 struct lprocfs_counter ret;
912 struct lprocfs_counter_header *header;
913 struct obd_device *obd = (struct obd_device *)data;
914 struct obd_import *imp;
915 struct obd_import_conn *conn;
921 LASSERT(obd != NULL);
922 LPROCFS_CLIMP_CHECK(obd);
923 imp = obd->u.cli.cl_import;
926 i = snprintf(page, count,
935 ptlrpc_import_state_name(imp->imp_state),
936 imp->imp_connect_data.ocd_instance);
937 i += obd_connect_flags2str(page + i, count - i,
938 imp->imp_connect_data.ocd_connect_flags,
940 i += snprintf(page + i, count - i,
943 i += obd_import_flags2str(imp, page + i, count - i);
945 i += snprintf(page + i, count - i,
948 " failover_nids: [");
949 spin_lock(&imp->imp_lock);
951 cfs_list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
952 i += snprintf(page + i, count - i, "%s%s", j ? ", " : "",
953 libcfs_nid2str(conn->oic_conn->c_peer.nid));
956 i += snprintf(page + i, count - i,
958 " current_connection: %s\n"
959 " connection_attempts: %u\n"
961 " in-progress_invalidations: %u\n",
962 imp->imp_connection == NULL ? "<none>" :
963 libcfs_nid2str(imp->imp_connection->c_peer.nid),
966 cfs_atomic_read(&imp->imp_inval_count));
967 spin_unlock(&imp->imp_lock);
969 if (obd->obd_svc_stats == NULL)
972 header = &obd->obd_svc_stats->ls_cnt_header[PTLRPC_REQWAIT_CNTR];
973 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
974 if (ret.lc_count != 0) {
975 /* first argument to do_div MUST be __u64 */
976 __u64 sum = ret.lc_sum;
977 do_div(sum, ret.lc_count);
981 i += snprintf(page + i, count - i,
984 " unregistering: %u\n"
986 " avg_waittime: "LPU64" %s\n",
987 cfs_atomic_read(&imp->imp_inflight),
988 cfs_atomic_read(&imp->imp_unregistering),
989 cfs_atomic_read(&imp->imp_timeouts),
990 ret.lc_sum, header->lc_units);
993 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
994 if (imp->imp_at.iat_portal[j] == 0)
996 k = max_t(unsigned int, k,
997 at_get(&imp->imp_at.iat_service_estimate[j]));
999 i += snprintf(page + i, count - i,
1000 " service_estimates:\n"
1001 " services: %u sec\n"
1002 " network: %u sec\n",
1004 at_get(&imp->imp_at.iat_net_latency));
1006 i += snprintf(page + i, count - i,
1008 " last_replay: "LPU64"\n"
1009 " peer_committed: "LPU64"\n"
1010 " last_checked: "LPU64"\n",
1011 imp->imp_last_replay_transno,
1012 imp->imp_peer_committed_transno,
1013 imp->imp_last_transno_checked);
1015 /* avg data rates */
1016 for (rw = 0; rw <= 1; rw++) {
1017 lprocfs_stats_collect(obd->obd_svc_stats,
1018 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
1020 if (ret.lc_sum > 0 && ret.lc_count > 0) {
1021 /* first argument to do_div MUST be __u64 */
1022 __u64 sum = ret.lc_sum;
1023 do_div(sum, ret.lc_count);
1025 i += snprintf(page + i, count - i,
1026 " %s_data_averages:\n"
1027 " bytes_per_rpc: "LPU64"\n",
1028 rw ? "write" : "read",
1031 k = (int)ret.lc_sum;
1032 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
1033 header = &obd->obd_svc_stats->ls_cnt_header[j];
1034 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
1035 if (ret.lc_sum > 0 && ret.lc_count != 0) {
1036 /* first argument to do_div MUST be __u64 */
1037 __u64 sum = ret.lc_sum;
1038 do_div(sum, ret.lc_count);
1040 i += snprintf(page + i, count - i,
1041 " %s_per_rpc: "LPU64"\n",
1042 header->lc_units, ret.lc_sum);
1043 j = (int)ret.lc_sum;
1045 i += snprintf(page + i, count - i,
1046 " MB_per_sec: %u.%.02u\n",
1047 k / j, (100 * k / j) % 100);
1052 LPROCFS_CLIMP_EXIT(obd);
1055 EXPORT_SYMBOL(lprocfs_rd_import);
1057 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
1058 int *eof, void *data)
1060 struct obd_device *obd = (struct obd_device *)data;
1061 struct obd_import *imp;
1064 LASSERT(obd != NULL);
1065 LPROCFS_CLIMP_CHECK(obd);
1066 imp = obd->u.cli.cl_import;
1069 i = snprintf(page, count, "current_state: %s\n",
1070 ptlrpc_import_state_name(imp->imp_state));
1071 i += snprintf(page + i, count - i,
1072 "state_history:\n");
1073 k = imp->imp_state_hist_idx;
1074 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
1075 struct import_state_hist *ish =
1076 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
1077 if (ish->ish_state == 0)
1079 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
1081 ptlrpc_import_state_name(ish->ish_state));
1084 LPROCFS_CLIMP_EXIT(obd);
1087 EXPORT_SYMBOL(lprocfs_rd_state);
1089 int lprocfs_at_hist_helper(char *page, int count, int rc,
1090 struct adaptive_timeout *at)
1093 for (i = 0; i < AT_BINS; i++)
1094 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
1095 rc += snprintf(page + rc, count - rc, "\n");
1098 EXPORT_SYMBOL(lprocfs_at_hist_helper);
1100 /* See also ptlrpc_lprocfs_rd_timeouts */
1101 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
1102 int *eof, void *data)
1104 struct obd_device *obd = (struct obd_device *)data;
1105 struct obd_import *imp;
1106 unsigned int cur, worst;
1111 LASSERT(obd != NULL);
1112 LPROCFS_CLIMP_CHECK(obd);
1113 imp = obd->u.cli.cl_import;
1116 now = cfs_time_current_sec();
1118 /* Some network health info for kicks */
1119 s2dhms(&ts, now - imp->imp_last_reply_time);
1120 rc += snprintf(page + rc, count - rc,
1121 "%-10s : %ld, "DHMS_FMT" ago\n",
1122 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
1124 cur = at_get(&imp->imp_at.iat_net_latency);
1125 worst = imp->imp_at.iat_net_latency.at_worst_ever;
1126 worstt = imp->imp_at.iat_net_latency.at_worst_time;
1127 s2dhms(&ts, now - worstt);
1128 rc += snprintf(page + rc, count - rc,
1129 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
1130 "network", cur, worst, worstt, DHMS_VARS(&ts));
1131 rc = lprocfs_at_hist_helper(page, count, rc,
1132 &imp->imp_at.iat_net_latency);
1134 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
1135 if (imp->imp_at.iat_portal[i] == 0)
1137 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
1138 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
1139 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
1140 s2dhms(&ts, now - worstt);
1141 rc += snprintf(page + rc, count - rc,
1142 "portal %-2d : cur %3u worst %3u (at %ld, "
1143 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
1144 cur, worst, worstt, DHMS_VARS(&ts));
1145 rc = lprocfs_at_hist_helper(page, count, rc,
1146 &imp->imp_at.iat_service_estimate[i]);
1149 LPROCFS_CLIMP_EXIT(obd);
1152 EXPORT_SYMBOL(lprocfs_rd_timeouts);
1154 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1155 int count, int *eof, void *data)
1157 struct obd_device *obd = data;
1161 LPROCFS_CLIMP_CHECK(obd);
1162 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1163 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1164 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1165 ret += snprintf(page + ret, count - ret, "\n");
1166 LPROCFS_CLIMP_EXIT(obd);
1169 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1171 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1172 int *eof, void *data)
1174 struct obd_device *obd = data;
1176 LASSERT(obd != NULL);
1178 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1180 EXPORT_SYMBOL(lprocfs_rd_num_exports);
1182 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1183 int *eof, void *data)
1185 struct obd_type *class = (struct obd_type*) data;
1187 LASSERT(class != NULL);
1189 return snprintf(page, count, "%d\n", class->typ_refcnt);
1191 EXPORT_SYMBOL(lprocfs_rd_numrefs);
1193 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1197 LASSERT(obd != NULL);
1198 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1199 LASSERT(obd->obd_type->typ_procroot != NULL);
1201 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1202 obd->obd_type->typ_procroot,
1204 if (IS_ERR(obd->obd_proc_entry)) {
1205 rc = PTR_ERR(obd->obd_proc_entry);
1206 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1207 obd->obd_proc_entry = NULL;
1211 EXPORT_SYMBOL(lprocfs_obd_setup);
1213 int lprocfs_obd_cleanup(struct obd_device *obd)
1217 if (obd->obd_proc_exports_entry) {
1218 /* Should be no exports left */
1219 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1220 lprocfs_remove(&obd->obd_proc_exports_entry);
1221 obd->obd_proc_exports_entry = NULL;
1223 if (obd->obd_proc_entry) {
1224 lprocfs_remove(&obd->obd_proc_entry);
1225 obd->obd_proc_entry = NULL;
1229 EXPORT_SYMBOL(lprocfs_obd_cleanup);
1231 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1233 CDEBUG(D_CONFIG, "stat %p - data %p/%p\n", client_stat,
1234 client_stat->nid_proc, client_stat->nid_stats);
1236 LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
1237 "nid %s:count %d\n", libcfs_nid2str(client_stat->nid),
1238 atomic_read(&client_stat->nid_exp_ref_count));
1240 if (client_stat->nid_proc)
1241 lprocfs_remove(&client_stat->nid_proc);
1243 if (client_stat->nid_stats)
1244 lprocfs_free_stats(&client_stat->nid_stats);
1246 if (client_stat->nid_ldlm_stats)
1247 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1249 OBD_FREE_PTR(client_stat);
1254 void lprocfs_free_per_client_stats(struct obd_device *obd)
1256 cfs_hash_t *hash = obd->obd_nid_stats_hash;
1257 struct nid_stat *stat;
1260 /* we need extra list - because hash_exit called to early */
1261 /* not need locking because all clients is died */
1262 while (!cfs_list_empty(&obd->obd_nid_stats)) {
1263 stat = cfs_list_entry(obd->obd_nid_stats.next,
1264 struct nid_stat, nid_list);
1265 cfs_list_del_init(&stat->nid_list);
1266 cfs_hash_del(hash, &stat->nid, &stat->nid_hash);
1267 lprocfs_free_client_stats(stat);
1271 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
1273 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1274 enum lprocfs_stats_flags flags)
1276 struct lprocfs_stats *stats;
1277 unsigned int num_entry;
1278 unsigned int percpusize = 0;
1284 if (lprocfs_no_percpu_stats != 0)
1285 flags |= LPROCFS_STATS_FLAG_NOPERCPU;
1287 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1290 num_entry = cfs_num_possible_cpus();
1292 /* alloc percpu pointers for all possible cpu slots */
1293 LIBCFS_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1297 stats->ls_num = num;
1298 stats->ls_flags = flags;
1299 spin_lock_init(&stats->ls_lock);
1301 /* alloc num of counter headers */
1302 LIBCFS_ALLOC(stats->ls_cnt_header,
1303 stats->ls_num * sizeof(struct lprocfs_counter_header));
1304 if (stats->ls_cnt_header == NULL)
1307 if ((flags & LPROCFS_STATS_FLAG_NOPERCPU) != 0) {
1308 /* contains only one set counters */
1309 percpusize = lprocfs_stats_counter_size(stats);
1310 LIBCFS_ALLOC_ATOMIC(stats->ls_percpu[0], percpusize);
1311 if (stats->ls_percpu[0] == NULL)
1313 stats->ls_biggest_alloc_num = 1;
1314 } else if ((flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0) {
1315 /* alloc all percpu data, currently only obd_memory use this */
1316 for (i = 0; i < num_entry; ++i)
1317 if (lprocfs_stats_alloc_one(stats, i) < 0)
1324 lprocfs_free_stats(&stats);
1327 EXPORT_SYMBOL(lprocfs_alloc_stats);
1329 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1331 struct lprocfs_stats *stats = *statsh;
1332 unsigned int num_entry;
1333 unsigned int percpusize;
1336 if (stats == NULL || stats->ls_num == 0)
1340 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1343 num_entry = cfs_num_possible_cpus();
1345 percpusize = lprocfs_stats_counter_size(stats);
1346 for (i = 0; i < num_entry; i++)
1347 if (stats->ls_percpu[i] != NULL)
1348 LIBCFS_FREE(stats->ls_percpu[i], percpusize);
1349 if (stats->ls_cnt_header != NULL)
1350 LIBCFS_FREE(stats->ls_cnt_header, stats->ls_num *
1351 sizeof(struct lprocfs_counter_header));
1352 LIBCFS_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1354 EXPORT_SYMBOL(lprocfs_free_stats);
1356 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1358 struct lprocfs_counter *percpu_cntr;
1361 unsigned int num_entry;
1362 unsigned long flags = 0;
1364 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1366 for (i = 0; i < num_entry; i++) {
1367 if (stats->ls_percpu[i] == NULL)
1369 for (j = 0; j < stats->ls_num; j++) {
1370 percpu_cntr = lprocfs_stats_counter_get(stats, i, j);
1371 percpu_cntr->lc_count = 0;
1372 percpu_cntr->lc_min = LC_MIN_INIT;
1373 percpu_cntr->lc_max = 0;
1374 percpu_cntr->lc_sumsquare = 0;
1375 percpu_cntr->lc_sum = 0;
1376 if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
1377 percpu_cntr->lc_sum_irq = 0;
1381 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1383 EXPORT_SYMBOL(lprocfs_clear_stats);
1385 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1386 size_t len, loff_t *off)
1388 struct seq_file *seq = file->private_data;
1389 struct lprocfs_stats *stats = seq->private;
1391 lprocfs_clear_stats(stats);
1396 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1398 struct lprocfs_stats *stats = p->private;
1400 return (*pos < stats->ls_num) ? pos : NULL;
1403 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1407 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1411 return lprocfs_stats_seq_start(p, pos);
1414 /* seq file export of one lprocfs counter */
1415 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1417 struct lprocfs_stats *stats = p->private;
1418 struct lprocfs_counter_header *hdr;
1419 struct lprocfs_counter ctr;
1420 int idx = *(loff_t *)v;
1426 cfs_gettimeofday(&now);
1427 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1428 "snapshot_time", now.tv_sec, now.tv_usec);
1433 hdr = &stats->ls_cnt_header[idx];
1434 lprocfs_stats_collect(stats, idx, &ctr);
1436 if (ctr.lc_count == 0)
1439 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", hdr->lc_name,
1440 ctr.lc_count, hdr->lc_units);
1444 if ((hdr->lc_config & LPROCFS_CNTR_AVGMINMAX) && ctr.lc_count > 0) {
1445 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1446 ctr.lc_min, ctr.lc_max, ctr.lc_sum);
1449 if (hdr->lc_config & LPROCFS_CNTR_STDDEV)
1450 rc = seq_printf(p, " "LPD64, ctr.lc_sumsquare);
1454 rc = seq_printf(p, "\n");
1456 return (rc < 0) ? rc : 0;
1459 struct seq_operations lprocfs_stats_seq_sops = {
1460 .start = lprocfs_stats_seq_start,
1461 .stop = lprocfs_stats_seq_stop,
1462 .next = lprocfs_stats_seq_next,
1463 .show = lprocfs_stats_seq_show,
1466 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1468 struct proc_dir_entry *dp = PDE(inode);
1469 struct seq_file *seq;
1472 if (LPROCFS_ENTRY_AND_CHECK(dp))
1475 rc = seq_open(file, &lprocfs_stats_seq_sops);
1480 seq = file->private_data;
1481 seq->private = dp->data;
1485 struct file_operations lprocfs_stats_seq_fops = {
1486 .owner = THIS_MODULE,
1487 .open = lprocfs_stats_seq_open,
1489 .write = lprocfs_stats_seq_write,
1490 .llseek = seq_lseek,
1491 .release = lprocfs_seq_release,
1494 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1495 struct lprocfs_stats *stats)
1497 struct proc_dir_entry *entry;
1498 LASSERT(root != NULL);
1500 LPROCFS_WRITE_ENTRY();
1501 entry = create_proc_entry(name, 0644, root);
1503 entry->proc_fops = &lprocfs_stats_seq_fops;
1504 entry->data = stats;
1507 LPROCFS_WRITE_EXIT();
1514 EXPORT_SYMBOL(lprocfs_register_stats);
1516 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1517 unsigned conf, const char *name, const char *units)
1519 struct lprocfs_counter_header *header;
1520 struct lprocfs_counter *percpu_cntr;
1521 unsigned long flags = 0;
1523 unsigned int num_cpu;
1525 LASSERT(stats != NULL);
1527 header = &stats->ls_cnt_header[index];
1528 LASSERTF(header != NULL, "Failed to allocate stats header:[%d]%s/%s\n",
1529 index, name, units);
1531 header->lc_config = conf;
1532 header->lc_name = name;
1533 header->lc_units = units;
1535 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1536 for (i = 0; i < num_cpu; ++i) {
1537 if (stats->ls_percpu[i] == NULL)
1539 percpu_cntr = lprocfs_stats_counter_get(stats, i, index);
1540 percpu_cntr->lc_count = 0;
1541 percpu_cntr->lc_min = LC_MIN_INIT;
1542 percpu_cntr->lc_max = 0;
1543 percpu_cntr->lc_sumsquare = 0;
1544 percpu_cntr->lc_sum = 0;
1545 if ((stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
1546 percpu_cntr->lc_sum_irq = 0;
1548 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1550 EXPORT_SYMBOL(lprocfs_counter_init);
1552 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1554 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1555 LASSERT(coffset < stats->ls_num); \
1556 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1559 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1561 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1562 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1563 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1564 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1565 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1566 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1567 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1568 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1569 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1570 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1571 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1572 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1573 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1574 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1575 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1576 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1577 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1578 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1579 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1580 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1581 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1582 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1583 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1584 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1585 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1586 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1587 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1588 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1589 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1590 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1591 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1592 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1593 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1594 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1595 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1596 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1597 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1598 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1599 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1600 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1601 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1602 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1603 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1604 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
1605 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1606 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1607 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1608 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1609 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1610 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1611 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1612 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1613 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1614 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1615 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1616 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1617 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1618 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1619 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1620 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1621 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1622 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1623 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1624 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1625 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1626 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1627 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1629 EXPORT_SYMBOL(lprocfs_init_ops_stats);
1631 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1633 struct lprocfs_stats *stats;
1634 unsigned int num_stats;
1637 LASSERT(obd->obd_stats == NULL);
1638 LASSERT(obd->obd_proc_entry != NULL);
1639 LASSERT(obd->obd_cntr_base == 0);
1641 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1642 num_private_stats - 1 /* o_owner */;
1643 stats = lprocfs_alloc_stats(num_stats, 0);
1647 lprocfs_init_ops_stats(num_private_stats, stats);
1649 for (i = num_private_stats; i < num_stats; i++) {
1650 /* If this LBUGs, it is likely that an obd
1651 * operation was added to struct obd_ops in
1652 * <obd.h>, and that the corresponding line item
1653 * LPROCFS_OBD_OP_INIT(.., .., opname)
1654 * is missing from the list above. */
1655 LASSERTF(stats->ls_cnt_header[i].lc_name != NULL,
1656 "Missing obd_stat initializer obd_op "
1657 "operation at offset %d.\n", i - num_private_stats);
1659 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1661 lprocfs_free_stats(&stats);
1663 obd->obd_stats = stats;
1664 obd->obd_cntr_base = num_private_stats;
1668 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
1670 void lprocfs_free_obd_stats(struct obd_device *obd)
1673 lprocfs_free_stats(&obd->obd_stats);
1675 EXPORT_SYMBOL(lprocfs_free_obd_stats);
1677 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1679 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1680 LASSERT(coffset < stats->ls_num); \
1681 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1684 void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats)
1686 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1687 LPROCFS_MD_OP_INIT(num_private_stats, stats, null_inode);
1688 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
1689 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1690 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1691 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1692 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1693 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1694 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1695 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1696 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1697 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1698 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1699 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1700 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1701 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1702 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1703 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1704 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1705 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1706 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1707 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1708 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1709 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1710 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1711 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1712 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1713 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1714 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1715 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1716 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1717 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1719 EXPORT_SYMBOL(lprocfs_init_mps_stats);
1721 int lprocfs_alloc_md_stats(struct obd_device *obd,
1722 unsigned num_private_stats)
1724 struct lprocfs_stats *stats;
1725 unsigned int num_stats;
1728 LASSERT(obd->md_stats == NULL);
1729 LASSERT(obd->obd_proc_entry != NULL);
1730 LASSERT(obd->md_cntr_base == 0);
1732 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1734 stats = lprocfs_alloc_stats(num_stats, 0);
1738 lprocfs_init_mps_stats(num_private_stats, stats);
1740 for (i = num_private_stats; i < num_stats; i++) {
1741 if (stats->ls_cnt_header[i].lc_name == NULL) {
1742 CERROR("Missing md_stat initializer md_op "
1743 "operation at offset %d. Aborting.\n",
1744 i - num_private_stats);
1748 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1750 lprocfs_free_stats(&stats);
1752 obd->md_stats = stats;
1753 obd->md_cntr_base = num_private_stats;
1757 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
1759 void lprocfs_free_md_stats(struct obd_device *obd)
1761 struct lprocfs_stats *stats = obd->md_stats;
1763 if (stats != NULL) {
1764 obd->md_stats = NULL;
1765 obd->md_cntr_base = 0;
1766 lprocfs_free_stats(&stats);
1769 EXPORT_SYMBOL(lprocfs_free_md_stats);
1771 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1773 lprocfs_counter_init(ldlm_stats,
1774 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1775 0, "ldlm_enqueue", "reqs");
1776 lprocfs_counter_init(ldlm_stats,
1777 LDLM_CONVERT - LDLM_FIRST_OPC,
1778 0, "ldlm_convert", "reqs");
1779 lprocfs_counter_init(ldlm_stats,
1780 LDLM_CANCEL - LDLM_FIRST_OPC,
1781 0, "ldlm_cancel", "reqs");
1782 lprocfs_counter_init(ldlm_stats,
1783 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1784 0, "ldlm_bl_callback", "reqs");
1785 lprocfs_counter_init(ldlm_stats,
1786 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1787 0, "ldlm_cp_callback", "reqs");
1788 lprocfs_counter_init(ldlm_stats,
1789 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1790 0, "ldlm_gl_callback", "reqs");
1792 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
1794 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1795 int *eof, void *data)
1797 struct obd_export *exp = data;
1798 LASSERT(exp != NULL);
1800 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1803 struct exp_uuid_cb_data {
1811 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1812 int count, int *eof, int *len)
1814 cb_data->page = page;
1815 cb_data->count = count;
1820 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1821 cfs_hlist_node_t *hnode, void *cb_data)
1824 struct obd_export *exp = cfs_hash_object(hs, hnode);
1825 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1827 if (exp->exp_nid_stats)
1828 *data->len += snprintf((data->page + *data->len),
1829 data->count, "%s\n",
1830 obd_uuid2str(&exp->exp_client_uuid));
1834 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1835 int *eof, void *data)
1837 struct nid_stat *stats = (struct nid_stat *)data;
1838 struct exp_uuid_cb_data cb_data;
1839 struct obd_device *obd = stats->nid_obd;
1844 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1845 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1846 lprocfs_exp_print_uuid, &cb_data);
1847 return (*cb_data.len);
1850 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1851 cfs_hlist_node_t *hnode, void *cb_data)
1854 struct exp_uuid_cb_data *data = cb_data;
1855 struct obd_export *exp = cfs_hash_object(hs, hnode);
1857 if (exp->exp_lock_hash != NULL) {
1859 *data->len += cfs_hash_debug_header(data->page,
1862 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1869 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1870 int *eof, void *data)
1872 struct nid_stat *stats = (struct nid_stat *)data;
1873 struct exp_uuid_cb_data cb_data;
1874 struct obd_device *obd = stats->nid_obd;
1879 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1881 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1882 lprocfs_exp_print_hash, &cb_data);
1883 return (*cb_data.len);
1886 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1887 int count, int *eof, void *data)
1890 return snprintf(page, count, "%s\n",
1891 "Write into this file to clear all nid stats and "
1892 "stale nid entries");
1894 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1896 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1898 struct nid_stat *stat = obj;
1901 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
1902 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 1) {
1903 /* object has only hash references. */
1904 spin_lock(&stat->nid_obd->obd_nid_lock);
1905 cfs_list_move(&stat->nid_list, data);
1906 spin_unlock(&stat->nid_obd->obd_nid_lock);
1909 /* we has reference to object - only clear data*/
1910 if (stat->nid_stats)
1911 lprocfs_clear_stats(stat->nid_stats);
1916 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1917 unsigned long count, void *data)
1919 struct obd_device *obd = (struct obd_device *)data;
1920 struct nid_stat *client_stat;
1921 CFS_LIST_HEAD(free_list);
1923 cfs_hash_cond_del(obd->obd_nid_stats_hash,
1924 lprocfs_nid_stats_clear_write_cb, &free_list);
1926 while (!cfs_list_empty(&free_list)) {
1927 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
1929 cfs_list_del_init(&client_stat->nid_list);
1930 lprocfs_free_client_stats(client_stat);
1935 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1937 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1939 struct nid_stat *new_stat, *old_stat;
1940 struct obd_device *obd = NULL;
1941 cfs_proc_dir_entry_t *entry;
1942 char *buffer = NULL;
1948 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1949 !exp->exp_obd->obd_nid_stats_hash)
1952 /* not test against zero because eric say:
1953 * You may only test nid against another nid, or LNET_NID_ANY.
1954 * Anything else is nonsense.*/
1955 if (!nid || *nid == LNET_NID_ANY)
1960 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
1962 OBD_ALLOC_PTR(new_stat);
1963 if (new_stat == NULL)
1966 new_stat->nid = *nid;
1967 new_stat->nid_obd = exp->exp_obd;
1968 /* we need set default refcount to 1 to balance obd_disconnect */
1969 cfs_atomic_set(&new_stat->nid_exp_ref_count, 1);
1971 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
1972 nid, &new_stat->nid_hash);
1973 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
1974 old_stat, libcfs_nid2str(*nid),
1975 cfs_atomic_read(&new_stat->nid_exp_ref_count));
1977 /* We need to release old stats because lprocfs_exp_cleanup() hasn't
1978 * been and will never be called. */
1979 if (exp->exp_nid_stats) {
1980 nidstat_putref(exp->exp_nid_stats);
1981 exp->exp_nid_stats = NULL;
1984 /* Return -EALREADY here so that we know that the /proc
1985 * entry already has been created */
1986 if (old_stat != new_stat) {
1987 exp->exp_nid_stats = old_stat;
1988 GOTO(destroy_new, rc = -EALREADY);
1990 /* not found - create */
1991 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
1993 GOTO(destroy_new, rc = -ENOMEM);
1995 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
1996 new_stat->nid_proc = lprocfs_register(buffer,
1997 obd->obd_proc_exports_entry,
1999 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
2001 if (IS_ERR(new_stat->nid_proc)) {
2002 rc = PTR_ERR(new_stat->nid_proc);
2003 new_stat->nid_proc = NULL;
2004 CERROR("%s: cannot create proc entry for export %s: rc = %d\n",
2005 obd->obd_name, libcfs_nid2str(*nid), rc);
2006 GOTO(destroy_new_ns, rc);
2009 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
2010 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
2011 if (IS_ERR(entry)) {
2012 CWARN("Error adding the NID stats file\n");
2013 rc = PTR_ERR(entry);
2014 GOTO(destroy_new_ns, rc);
2017 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
2018 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
2019 if (IS_ERR(entry)) {
2020 CWARN("Error adding the hash file\n");
2021 rc = PTR_ERR(entry);
2022 GOTO(destroy_new_ns, rc);
2025 exp->exp_nid_stats = new_stat;
2027 /* protect competitive add to list, not need locking on destroy */
2028 spin_lock(&obd->obd_nid_lock);
2029 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
2030 spin_unlock(&obd->obd_nid_lock);
2035 if (new_stat->nid_proc != NULL)
2036 lprocfs_remove(&new_stat->nid_proc);
2037 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
2040 nidstat_putref(new_stat);
2041 OBD_FREE_PTR(new_stat);
2044 EXPORT_SYMBOL(lprocfs_exp_setup);
2046 int lprocfs_exp_cleanup(struct obd_export *exp)
2048 struct nid_stat *stat = exp->exp_nid_stats;
2050 if(!stat || !exp->exp_obd)
2053 nidstat_putref(exp->exp_nid_stats);
2054 exp->exp_nid_stats = NULL;
2058 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2060 int lprocfs_write_helper(const char *buffer, unsigned long count,
2063 return lprocfs_write_frac_helper(buffer, count, val, 1);
2065 EXPORT_SYMBOL(lprocfs_write_helper);
2067 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
2070 char kernbuf[20], *end, *pbuf;
2072 if (count > (sizeof(kernbuf) - 1))
2075 if (copy_from_user(kernbuf, buffer, count))
2078 kernbuf[count] = '\0';
2085 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2089 if (end != NULL && *end == '.') {
2090 int temp_val, pow = 1;
2094 if (strlen(pbuf) > 5)
2095 pbuf[5] = '\0'; /*only allow 5bits fractional*/
2097 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2100 for (i = 0; i < (end - pbuf); i++)
2103 *val += temp_val / pow;
2108 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2110 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
2113 long decimal_val, frac_val;
2119 decimal_val = val / mult;
2120 prtn = snprintf(buffer, count, "%ld", decimal_val);
2121 frac_val = val % mult;
2123 if (prtn < (count - 4) && frac_val > 0) {
2125 int i, temp_mult = 1, frac_bits = 0;
2127 temp_frac = frac_val * 10;
2128 buffer[prtn++] = '.';
2129 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
2130 /* only reserved 2 bits fraction */
2131 buffer[prtn++] ='0';
2136 * Need to think these cases :
2137 * 1. #echo x.00 > /proc/xxx output result : x
2138 * 2. #echo x.0x > /proc/xxx output result : x.0x
2139 * 3. #echo x.x0 > /proc/xxx output result : x.x
2140 * 4. #echo x.xx > /proc/xxx output result : x.xx
2141 * Only reserved 2 bits fraction.
2143 for (i = 0; i < (5 - prtn); i++)
2146 frac_bits = min((int)count - prtn, 3 - frac_bits);
2147 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
2148 frac_val * temp_mult / mult);
2151 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
2153 if (buffer[prtn] == '.') {
2160 buffer[prtn++] ='\n';
2163 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2165 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
2167 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
2169 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2171 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
2172 __u64 *val, int mult)
2174 char kernbuf[22], *end, *pbuf;
2175 __u64 whole, frac = 0, units;
2176 unsigned frac_d = 1;
2178 if (count > (sizeof(kernbuf) - 1))
2181 if (copy_from_user(kernbuf, buffer, count))
2184 kernbuf[count] = '\0';
2191 whole = simple_strtoull(pbuf, &end, 10);
2195 if (end != NULL && *end == '.') {
2199 /* need to limit frac_d to a __u32 */
2200 if (strlen(pbuf) > 10)
2203 frac = simple_strtoull(pbuf, &end, 10);
2204 /* count decimal places */
2205 for (i = 0; i < (end - pbuf); i++)
2222 /* Specified units override the multiplier */
2224 mult = mult < 0 ? -units : units;
2227 do_div(frac, frac_d);
2228 *val = whole * mult + frac;
2231 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2233 static char *lprocfs_strnstr(const char *s1, const char *s2, size_t len)
2242 if (!memcmp(s1, s2, l2))
2250 * Find the string \a name in the input \a buffer, and return a pointer to the
2251 * value immediately following \a name, reducing \a count appropriately.
2252 * If \a name is not found the original \a buffer is returned.
2254 char *lprocfs_find_named_value(const char *buffer, const char *name,
2255 unsigned long *count)
2258 size_t buflen = *count;
2260 /* there is no strnstr() in rhel5 and ubuntu kernels */
2261 val = lprocfs_strnstr(buffer, name, buflen);
2263 return (char *)buffer;
2265 val += strlen(name); /* skip prefix */
2266 while (val < buffer + buflen && isspace(*val)) /* skip separator */
2270 while (val < buffer + buflen && isalnum(*val)) {
2275 return val - *count;
2277 EXPORT_SYMBOL(lprocfs_find_named_value);
2279 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent,
2282 const struct file_operations *seq_fops,
2285 struct proc_dir_entry *entry;
2288 /* Disallow secretly (un)writable entries. */
2289 LASSERT((seq_fops->write == NULL) == ((mode & 0222) == 0));
2291 LPROCFS_WRITE_ENTRY();
2292 entry = create_proc_entry(name, mode, parent);
2294 entry->proc_fops = seq_fops;
2297 LPROCFS_WRITE_EXIT();
2304 EXPORT_SYMBOL(lprocfs_seq_create);
2306 int lprocfs_obd_seq_create(struct obd_device *dev,
2309 const struct file_operations *seq_fops,
2312 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2313 mode, seq_fops, data));
2315 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2317 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2319 if (value >= OBD_HIST_MAX)
2320 value = OBD_HIST_MAX - 1;
2322 spin_lock(&oh->oh_lock);
2323 oh->oh_buckets[value]++;
2324 spin_unlock(&oh->oh_lock);
2326 EXPORT_SYMBOL(lprocfs_oh_tally);
2328 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2332 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2335 lprocfs_oh_tally(oh, val);
2337 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2339 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2341 unsigned long ret = 0;
2344 for (i = 0; i < OBD_HIST_MAX; i++)
2345 ret += oh->oh_buckets[i];
2348 EXPORT_SYMBOL(lprocfs_oh_sum);
2350 void lprocfs_oh_clear(struct obd_histogram *oh)
2352 spin_lock(&oh->oh_lock);
2353 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2354 spin_unlock(&oh->oh_lock);
2356 EXPORT_SYMBOL(lprocfs_oh_clear);
2358 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2359 int count, int *eof, void *data)
2361 struct obd_device *obd = data;
2367 c += cfs_hash_debug_header(page, count);
2368 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2369 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2370 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2374 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2376 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2377 int count, int *eof, void *data)
2379 struct obd_device *obd = data;
2382 LASSERT(obd != NULL);
2383 LASSERT(count >= 0);
2385 /* Set start of user data returned to
2386 page + off since the user may have
2387 requested to read much smaller than
2388 what we need to read */
2389 *start = page + off;
2392 * We know we are allocated a page here.
2393 * Also we know that this function will
2394 * not need to write more than a page
2395 * so we can truncate at PAGE_CACHE_SIZE.
2397 size = min(count + (int)off + 1, (int)PAGE_CACHE_SIZE);
2399 /* Initialize the page */
2400 memset(page, 0, size);
2402 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2404 if (obd->obd_max_recoverable_clients == 0) {
2405 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2411 /* sampled unlocked, but really... */
2412 if (obd->obd_recovering == 0) {
2413 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2415 if (lprocfs_obd_snprintf(&page, size, &len,
2416 "recovery_start: %lu\n",
2417 obd->obd_recovery_start) <= 0)
2419 if (lprocfs_obd_snprintf(&page, size, &len,
2420 "recovery_duration: %lu\n",
2421 obd->obd_recovery_end -
2422 obd->obd_recovery_start) <= 0)
2424 /* Number of clients that have completed recovery */
2425 if (lprocfs_obd_snprintf(&page, size, &len,
2426 "completed_clients: %d/%d\n",
2427 obd->obd_max_recoverable_clients -
2428 obd->obd_stale_clients,
2429 obd->obd_max_recoverable_clients) <= 0)
2431 if (lprocfs_obd_snprintf(&page, size, &len,
2432 "replayed_requests: %d\n",
2433 obd->obd_replayed_requests) <= 0)
2435 if (lprocfs_obd_snprintf(&page, size, &len,
2436 "last_transno: "LPD64"\n",
2437 obd->obd_next_recovery_transno - 1)<=0)
2439 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2440 obd->obd_version_recov ?
2441 "ENABLED" : "DISABLED") <=0)
2443 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
2445 "DISABLED" : "ENABLED") <= 0)
2450 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2452 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2453 obd->obd_recovery_start) <= 0)
2455 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2456 cfs_time_current_sec() >=
2457 obd->obd_recovery_start +
2458 obd->obd_recovery_timeout ? 0 :
2459 obd->obd_recovery_start +
2460 obd->obd_recovery_timeout -
2461 cfs_time_current_sec()) <= 0)
2463 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2464 cfs_atomic_read(&obd->obd_connected_clients),
2465 obd->obd_max_recoverable_clients) <= 0)
2467 /* Number of clients that have completed recovery */
2468 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2469 cfs_atomic_read(&obd->obd_req_replay_clients))
2472 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2473 cfs_atomic_read(&obd->obd_lock_replay_clients))
2476 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2477 cfs_atomic_read(&obd->obd_connected_clients) -
2478 cfs_atomic_read(&obd->obd_lock_replay_clients))
2481 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2482 obd->obd_stale_clients) <= 0)
2484 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2485 obd->obd_replayed_requests) <= 0)
2487 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2488 obd->obd_requests_queued_for_recovery) <= 0)
2491 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2492 obd->obd_next_recovery_transno) <= 0)
2498 return min(count, len - (int)off);
2500 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2502 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
2503 int count, int *eof, void *data)
2505 struct obd_device *obd = (struct obd_device *)data;
2506 LASSERT(obd != NULL);
2508 return snprintf(page, count, "%d\n",
2509 obd->obd_recovery_ir_factor);
2511 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
2513 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
2514 unsigned long count, void *data)
2516 struct obd_device *obd = (struct obd_device *)data;
2518 LASSERT(obd != NULL);
2520 rc = lprocfs_write_helper(buffer, count, &val);
2524 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
2527 obd->obd_recovery_ir_factor = val;
2530 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
2532 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
2533 int count, int *eof, void *data)
2535 struct obd_device *obd = (struct obd_device *)data;
2536 LASSERT(obd != NULL);
2538 return snprintf(page, count, "%d\n",
2539 obd->obd_recovery_timeout);
2541 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
2543 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
2544 unsigned long count, void *data)
2546 struct obd_device *obd = (struct obd_device *)data;
2548 LASSERT(obd != NULL);
2550 rc = lprocfs_write_helper(buffer, count, &val);
2554 obd->obd_recovery_timeout = val;
2557 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
2559 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
2560 int count, int *eof, void *data)
2562 struct obd_device *obd = data;
2563 LASSERT(obd != NULL);
2565 return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
2567 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
2569 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
2570 unsigned long count, void *data)
2572 struct obd_device *obd = data;
2574 LASSERT(obd != NULL);
2576 rc = lprocfs_write_helper(buffer, count, &val);
2580 obd->obd_recovery_time_hard = val;
2583 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
2585 int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
2586 int count, int *eof, void *data)
2588 struct obd_device *dev = data;
2589 struct client_obd *cli = &dev->u.cli;
2592 client_obd_list_lock(&cli->cl_loi_list_lock);
2593 rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
2594 client_obd_list_unlock(&cli->cl_loi_list_lock);
2597 EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
2599 #ifdef HAVE_SERVER_SUPPORT
2600 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
2601 int count, int *eof, void *data)
2603 struct obd_device *obd = (struct obd_device *)data;
2604 struct obd_device_target *target = &obd->u.obt;
2606 LASSERT(obd != NULL);
2607 LASSERT(target->obt_magic == OBT_MAGIC);
2609 return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
2611 EXPORT_SYMBOL(lprocfs_target_rd_instance);