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)
65 return single_release(inode, file);
67 EXPORT_SYMBOL(lprocfs_single_release);
69 int lprocfs_seq_release(struct inode *inode, struct file *file)
71 return seq_release(inode, file);
73 EXPORT_SYMBOL(lprocfs_seq_release);
75 static struct proc_dir_entry *__lprocfs_srch(struct proc_dir_entry *head,
78 struct proc_dir_entry *temp;
84 while (temp != NULL) {
85 if (strcmp(temp->name, name) == 0) {
94 struct proc_dir_entry *lprocfs_srch(struct proc_dir_entry *head,
97 struct proc_dir_entry *temp;
100 temp = __lprocfs_srch(head, name);
104 EXPORT_SYMBOL(lprocfs_srch);
106 /* lprocfs API calls */
108 /* Function that emulates snprintf but also has the side effect of advancing
109 the page pointer for the next write into the buffer, incrementing the total
110 length written to the buffer, and decrementing the size left in the
112 static int lprocfs_obd_snprintf(char **page, int end, int *len,
113 const char *format, ...)
121 va_start(list, format);
122 n = vsnprintf(*page, end - *len, format, list);
125 *page += n; *len += n;
129 cfs_proc_dir_entry_t *lprocfs_add_simple(struct proc_dir_entry *root,
131 read_proc_t *read_proc,
132 write_proc_t *write_proc,
134 struct file_operations *fops)
136 cfs_proc_dir_entry_t *proc;
139 if (root == NULL || name == NULL)
140 return ERR_PTR(-EINVAL);
147 LPROCFS_WRITE_ENTRY();
148 proc = create_proc_entry(name, mode, root);
150 CERROR("LprocFS: No memory to create /proc entry %s", name);
151 LPROCFS_WRITE_EXIT();
152 return ERR_PTR(-ENOMEM);
154 proc->read_proc = read_proc;
155 proc->write_proc = write_proc;
158 proc->proc_fops = fops;
159 LPROCFS_WRITE_EXIT();
162 EXPORT_SYMBOL(lprocfs_add_simple);
164 struct proc_dir_entry *lprocfs_add_symlink(const char *name,
165 struct proc_dir_entry *parent, const char *format, ...)
167 struct proc_dir_entry *entry;
171 if (parent == NULL || format == NULL)
174 OBD_ALLOC_WAIT(dest, MAX_STRING_SIZE + 1);
178 va_start(ap, format);
179 vsnprintf(dest, MAX_STRING_SIZE, format, ap);
182 entry = proc_symlink(name, parent, dest);
184 CERROR("LprocFS: Could not create symbolic link from %s to %s",
187 OBD_FREE(dest, MAX_STRING_SIZE + 1);
190 EXPORT_SYMBOL(lprocfs_add_symlink);
192 static ssize_t lprocfs_fops_read(struct file *f, char __user *buf,
193 size_t size, loff_t *ppos)
195 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
196 char *page, *start = NULL;
197 int rc = 0, eof = 1, count;
199 if (*ppos >= PAGE_CACHE_SIZE)
202 page = (char *)__get_free_page(GFP_KERNEL);
206 if (LPROCFS_ENTRY_CHECK(dp)) {
211 OBD_FAIL_TIMEOUT(OBD_FAIL_LPROC_REMOVE, 10);
213 rc = dp->read_proc(page, &start, *ppos, PAGE_CACHE_SIZE,
218 /* for lustre proc read, the read count must be less than PAGE_SIZE */
227 start = page + *ppos;
228 } else if (start < page) {
232 count = (rc < size) ? rc : size;
233 if (copy_to_user(buf, start, count)) {
240 free_page((unsigned long)page);
244 static ssize_t lprocfs_fops_write(struct file *f, const char __user *buf,
245 size_t size, loff_t *ppos)
247 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
250 if (LPROCFS_ENTRY_CHECK(dp))
253 rc = dp->write_proc(f, buf, size, dp->data);
257 static struct file_operations lprocfs_generic_fops = {
258 .owner = THIS_MODULE,
259 .read = lprocfs_fops_read,
260 .write = lprocfs_fops_write,
263 int lprocfs_evict_client_open(struct inode *inode, struct file *f)
265 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
266 struct obd_device *obd = dp->data;
268 cfs_atomic_inc(&obd->obd_evict_inprogress);
273 int lprocfs_evict_client_release(struct inode *inode, struct file *f)
275 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
276 struct obd_device *obd = dp->data;
278 cfs_atomic_dec(&obd->obd_evict_inprogress);
279 cfs_waitq_signal(&obd->obd_evict_inprogress_waitq);
284 struct file_operations lprocfs_evict_client_fops = {
285 .owner = THIS_MODULE,
286 .read = lprocfs_fops_read,
287 .write = lprocfs_fops_write,
288 .open = lprocfs_evict_client_open,
289 .release = lprocfs_evict_client_release,
291 EXPORT_SYMBOL(lprocfs_evict_client_fops);
293 static int __lprocfs_add_vars(struct proc_dir_entry *root,
294 struct lprocfs_vars *list,
299 if (root == NULL || list == NULL)
302 while (list->name != NULL) {
303 struct proc_dir_entry *cur_root, *proc;
304 char *pathcopy, *cur, *next, pathbuf[64];
305 int pathsize = strlen(list->name) + 1;
310 /* need copy of path for strsep */
311 if (strlen(list->name) > sizeof(pathbuf) - 1) {
312 OBD_ALLOC(pathcopy, pathsize);
313 if (pathcopy == NULL)
314 GOTO(out, rc = -ENOMEM);
320 strcpy(pathcopy, list->name);
322 while (cur_root != NULL && (cur = strsep(&next, "/"))) {
323 if (*cur =='\0') /* skip double/trailing "/" */
326 proc = __lprocfs_srch(cur_root, cur);
327 CDEBUG(D_OTHER, "cur_root=%s, cur=%s, next=%s, (%s)\n",
328 cur_root->name, cur, next,
329 (proc ? "exists" : "new"));
331 cur_root = (proc ? proc :
332 proc_mkdir(cur, cur_root));
333 } else if (proc == NULL) {
335 if (list->proc_mode != 0000) {
336 mode = list->proc_mode;
340 if (list->write_fptr)
343 proc = create_proc_entry(cur, mode, cur_root);
347 if (pathcopy != pathbuf)
348 OBD_FREE(pathcopy, pathsize);
350 if (cur_root == NULL || proc == NULL) {
351 CERROR("LprocFS: No memory to create /proc entry %s",
353 GOTO(out, rc = -ENOMEM);
357 proc->proc_fops = list->fops;
359 proc->proc_fops = &lprocfs_generic_fops;
360 proc->read_proc = list->read_fptr;
361 proc->write_proc = list->write_fptr;
362 proc->data = (list->data ? list->data : data);
372 * \param root [in] The parent proc entry on which new entry will be added.
373 * \param list [in] Array of proc entries to be added.
374 * \param data [in] The argument to be passed when entries read/write routines
375 * are called through /proc file.
377 * \retval 0 on success
380 int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list,
385 LPROCFS_WRITE_ENTRY();
386 rc = __lprocfs_add_vars(root, list, data);
387 LPROCFS_WRITE_EXIT();
391 EXPORT_SYMBOL(lprocfs_add_vars);
393 void lprocfs_remove_nolock(struct proc_dir_entry **proot)
395 struct proc_dir_entry *root = *proot;
396 struct proc_dir_entry *temp = root;
397 struct proc_dir_entry *rm_entry;
398 struct proc_dir_entry *parent;
401 if (root == NULL || IS_ERR(root))
404 parent = root->parent;
405 LASSERT(parent != NULL);
408 while (temp->subdir != NULL)
414 /* Memory corruption once caused this to fail, and
415 without this LASSERT we would loop here forever. */
416 LASSERTF(strlen(rm_entry->name) == rm_entry->namelen,
417 "0x%p %s/%s len %d\n", rm_entry, temp->name,
418 rm_entry->name, (int)strlen(rm_entry->name));
420 remove_proc_entry(rm_entry->name, temp);
426 void lprocfs_remove(struct proc_dir_entry **rooth)
428 LPROCFS_WRITE_ENTRY(); /* search vs remove race */
429 lprocfs_remove_nolock(rooth);
430 LPROCFS_WRITE_EXIT();
432 EXPORT_SYMBOL(lprocfs_remove);
434 void lprocfs_remove_proc_entry(const char *name, struct proc_dir_entry *parent)
436 LASSERT(parent != NULL);
437 remove_proc_entry(name, parent);
439 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
441 void lprocfs_try_remove_proc_entry(const char *name,
442 struct proc_dir_entry *parent)
444 struct proc_dir_entry *t = NULL;
445 struct proc_dir_entry **p;
448 LASSERT(parent != NULL);
451 LPROCFS_WRITE_ENTRY();
453 /* lookup target name */
454 for (p = &parent->subdir; *p; p = &(*p)->next) {
455 if ((*p)->namelen != len)
457 if (memcmp(name, (*p)->name, len))
464 /* verify it's empty: do not count "num_refs" */
465 for (p = &t->subdir; *p; p = &(*p)->next) {
466 if ((*p)->namelen != strlen("num_refs")) {
470 if (memcmp("num_refs", (*p)->name,
471 strlen("num_refs"))) {
479 lprocfs_remove_nolock(&t);
481 LPROCFS_WRITE_EXIT();
485 EXPORT_SYMBOL(lprocfs_try_remove_proc_entry);
487 struct proc_dir_entry *lprocfs_register(const char *name,
488 struct proc_dir_entry *parent,
489 struct lprocfs_vars *list, void *data)
491 struct proc_dir_entry *entry;
494 LPROCFS_WRITE_ENTRY();
495 entry = __lprocfs_srch(parent, name);
497 CERROR("entry '%s' already registered\n", name);
498 GOTO(out, entry = ERR_PTR(-EALREADY));
501 entry = proc_mkdir(name, parent);
503 GOTO(out, entry = ERR_PTR(-ENOMEM));
506 rc = __lprocfs_add_vars(entry, list, data);
508 lprocfs_remove_nolock(&entry);
509 GOTO(out, entry = ERR_PTR(rc));
513 LPROCFS_WRITE_EXIT();
517 EXPORT_SYMBOL(lprocfs_register);
519 /* Generic callbacks */
520 int lprocfs_rd_uint(char *page, char **start, off_t off,
521 int count, int *eof, void *data)
523 unsigned int *temp = data;
524 return snprintf(page, count, "%u\n", *temp);
526 EXPORT_SYMBOL(lprocfs_rd_uint);
528 int lprocfs_wr_uint(struct file *file, const char *buffer,
529 unsigned long count, void *data)
532 char dummy[MAX_STRING_SIZE + 1], *end;
535 dummy[MAX_STRING_SIZE] = '\0';
536 if (copy_from_user(dummy, buffer, MAX_STRING_SIZE))
539 tmp = simple_strtoul(dummy, &end, 0);
543 *p = (unsigned int)tmp;
546 EXPORT_SYMBOL(lprocfs_wr_uint);
548 int lprocfs_rd_u64(char *page, char **start, off_t off,
549 int count, int *eof, void *data)
551 LASSERT(data != NULL);
553 return snprintf(page, count, LPU64"\n", *(__u64 *)data);
555 EXPORT_SYMBOL(lprocfs_rd_u64);
557 int lprocfs_rd_atomic(char *page, char **start, off_t off,
558 int count, int *eof, void *data)
560 cfs_atomic_t *atom = data;
561 LASSERT(atom != NULL);
563 return snprintf(page, count, "%d\n", cfs_atomic_read(atom));
565 EXPORT_SYMBOL(lprocfs_rd_atomic);
567 int lprocfs_wr_atomic(struct file *file, const char *buffer,
568 unsigned long count, void *data)
570 cfs_atomic_t *atm = data;
574 rc = lprocfs_write_helper(buffer, count, &val);
581 cfs_atomic_set(atm, val);
584 EXPORT_SYMBOL(lprocfs_wr_atomic);
586 int lprocfs_rd_uuid(char *page, char **start, off_t off, int count,
587 int *eof, void *data)
589 struct obd_device *obd = data;
591 LASSERT(obd != NULL);
593 return snprintf(page, count, "%s\n", obd->obd_uuid.uuid);
595 EXPORT_SYMBOL(lprocfs_rd_uuid);
597 int lprocfs_rd_name(char *page, char **start, off_t off, int count,
598 int *eof, void *data)
600 struct obd_device *dev = data;
602 LASSERT(dev != NULL);
604 return snprintf(page, count, "%s\n", dev->obd_name);
606 EXPORT_SYMBOL(lprocfs_rd_name);
608 int lprocfs_rd_blksize(char *page, char **start, off_t off, int count,
609 int *eof, void *data)
611 struct obd_device *obd = data;
612 struct obd_statfs osfs;
613 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
614 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
618 rc = snprintf(page, count, "%u\n", osfs.os_bsize);
622 EXPORT_SYMBOL(lprocfs_rd_blksize);
624 int lprocfs_rd_kbytestotal(char *page, char **start, off_t off, int count,
625 int *eof, void *data)
627 struct obd_device *obd = data;
628 struct obd_statfs osfs;
629 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
630 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
633 __u32 blk_size = osfs.os_bsize >> 10;
634 __u64 result = osfs.os_blocks;
636 while (blk_size >>= 1)
640 rc = snprintf(page, count, LPU64"\n", result);
644 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
646 int lprocfs_rd_kbytesfree(char *page, char **start, off_t off, int count,
647 int *eof, void *data)
649 struct obd_device *obd = data;
650 struct obd_statfs osfs;
651 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
652 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
655 __u32 blk_size = osfs.os_bsize >> 10;
656 __u64 result = osfs.os_bfree;
658 while (blk_size >>= 1)
662 rc = snprintf(page, count, LPU64"\n", result);
666 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
668 int lprocfs_rd_kbytesavail(char *page, char **start, off_t off, int count,
669 int *eof, void *data)
671 struct obd_device *obd = data;
672 struct obd_statfs osfs;
673 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
674 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
677 __u32 blk_size = osfs.os_bsize >> 10;
678 __u64 result = osfs.os_bavail;
680 while (blk_size >>= 1)
684 rc = snprintf(page, count, LPU64"\n", result);
688 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
690 int lprocfs_rd_filestotal(char *page, char **start, off_t off, int count,
691 int *eof, void *data)
693 struct obd_device *obd = data;
694 struct obd_statfs osfs;
695 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
696 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
700 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
705 EXPORT_SYMBOL(lprocfs_rd_filestotal);
707 int lprocfs_rd_filesfree(char *page, char **start, off_t off, int count,
708 int *eof, void *data)
710 struct obd_device *obd = data;
711 struct obd_statfs osfs;
712 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
713 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
717 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
721 EXPORT_SYMBOL(lprocfs_rd_filesfree);
723 int lprocfs_rd_server_uuid(char *page, char **start, off_t off, int count,
724 int *eof, void *data)
726 struct obd_device *obd = data;
727 struct obd_import *imp;
728 char *imp_state_name = NULL;
731 LASSERT(obd != NULL);
732 LPROCFS_CLIMP_CHECK(obd);
733 imp = obd->u.cli.cl_import;
734 imp_state_name = ptlrpc_import_state_name(imp->imp_state);
736 rc = snprintf(page, count, "%s\t%s%s\n",
737 obd2cli_tgt(obd), imp_state_name,
738 imp->imp_deactive ? "\tDEACTIVATED" : "");
740 LPROCFS_CLIMP_EXIT(obd);
743 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
745 int lprocfs_rd_conn_uuid(char *page, char **start, off_t off, int count,
746 int *eof, void *data)
748 struct obd_device *obd = data;
749 struct ptlrpc_connection *conn;
752 LASSERT(obd != NULL);
754 LPROCFS_CLIMP_CHECK(obd);
755 conn = obd->u.cli.cl_import->imp_connection;
757 if (conn && obd->u.cli.cl_import) {
758 rc = snprintf(page, count, "%s\n",
759 conn->c_remote_uuid.uuid);
761 rc = snprintf(page, count, "%s\n", "<none>");
764 LPROCFS_CLIMP_EXIT(obd);
767 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
769 /** add up per-cpu counters */
770 void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
771 struct lprocfs_counter *cnt)
773 unsigned int num_entry;
774 struct lprocfs_counter *percpu_cntr;
776 unsigned long flags = 0;
778 memset(cnt, 0, sizeof(*cnt));
781 /* set count to 1 to avoid divide-by-zero errs in callers */
786 cnt->lc_min = LC_MIN_INIT;
788 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
790 for (i = 0; i < num_entry; i++) {
791 if (stats->ls_percpu[i] == NULL)
793 percpu_cntr = lprocfs_stats_counter_get(stats, i, idx);
795 cnt->lc_count += percpu_cntr->lc_count;
796 cnt->lc_sum += percpu_cntr->lc_sum;
797 if (percpu_cntr->lc_min < cnt->lc_min)
798 cnt->lc_min = percpu_cntr->lc_min;
799 if (percpu_cntr->lc_max > cnt->lc_max)
800 cnt->lc_max = percpu_cntr->lc_max;
801 cnt->lc_sumsquare += percpu_cntr->lc_sumsquare;
804 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
806 EXPORT_SYMBOL(lprocfs_stats_collect);
809 * Append a space separated list of current set flags to str.
811 #define flag2str(flag) \
812 if (imp->imp_##flag && max - len > 0) \
813 len += snprintf(str + len, max - len, "%s" #flag, len ? ", " : "");
814 static int obd_import_flags2str(struct obd_import *imp, char *str, int max)
818 if (imp->imp_obd->obd_no_recov)
819 len += snprintf(str, max - len, "no_recov");
823 flag2str(replayable);
829 static const char *obd_connect_names[] = {
843 "join_file(obsolete)",
847 "remote_client_by_force",
856 "mds_mds_connection",
859 "alt_checksum_algorithm",
886 int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
891 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
893 ret += snprintf(page + ret, count - ret, "%s%s",
894 ret ? sep : "", obd_connect_names[i]);
896 if (flags & ~(mask - 1))
897 ret += snprintf(page + ret, count - ret,
898 "%sunknown flags "LPX64,
899 ret ? sep : "", flags & ~(mask - 1));
902 EXPORT_SYMBOL(obd_connect_flags2str);
904 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
905 int *eof, void *data)
907 struct lprocfs_counter ret;
908 struct lprocfs_counter_header *header;
909 struct obd_device *obd = (struct obd_device *)data;
910 struct obd_import *imp;
911 struct obd_import_conn *conn;
917 LASSERT(obd != NULL);
918 LPROCFS_CLIMP_CHECK(obd);
919 imp = obd->u.cli.cl_import;
922 i = snprintf(page, count,
931 ptlrpc_import_state_name(imp->imp_state),
932 imp->imp_connect_data.ocd_instance);
933 i += obd_connect_flags2str(page + i, count - i,
934 imp->imp_connect_data.ocd_connect_flags,
936 i += snprintf(page + i, count - i,
939 i += obd_import_flags2str(imp, page + i, count - i);
941 i += snprintf(page + i, count - i,
944 " failover_nids: [");
945 spin_lock(&imp->imp_lock);
947 cfs_list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
948 i += snprintf(page + i, count - i, "%s%s", j ? ", " : "",
949 libcfs_nid2str(conn->oic_conn->c_peer.nid));
952 i += snprintf(page + i, count - i,
954 " current_connection: %s\n"
955 " connection_attempts: %u\n"
957 " in-progress_invalidations: %u\n",
958 imp->imp_connection == NULL ? "<none>" :
959 libcfs_nid2str(imp->imp_connection->c_peer.nid),
962 cfs_atomic_read(&imp->imp_inval_count));
963 spin_unlock(&imp->imp_lock);
965 if (obd->obd_svc_stats == NULL)
968 header = &obd->obd_svc_stats->ls_cnt_header[PTLRPC_REQWAIT_CNTR];
969 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
970 if (ret.lc_count != 0) {
971 /* first argument to do_div MUST be __u64 */
972 __u64 sum = ret.lc_sum;
973 do_div(sum, ret.lc_count);
977 i += snprintf(page + i, count - i,
980 " unregistering: %u\n"
982 " avg_waittime: "LPU64" %s\n",
983 cfs_atomic_read(&imp->imp_inflight),
984 cfs_atomic_read(&imp->imp_unregistering),
985 cfs_atomic_read(&imp->imp_timeouts),
986 ret.lc_sum, header->lc_units);
989 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
990 if (imp->imp_at.iat_portal[j] == 0)
992 k = max_t(unsigned int, k,
993 at_get(&imp->imp_at.iat_service_estimate[j]));
995 i += snprintf(page + i, count - i,
996 " service_estimates:\n"
997 " services: %u sec\n"
998 " network: %u sec\n",
1000 at_get(&imp->imp_at.iat_net_latency));
1002 i += snprintf(page + i, count - i,
1004 " last_replay: "LPU64"\n"
1005 " peer_committed: "LPU64"\n"
1006 " last_checked: "LPU64"\n",
1007 imp->imp_last_replay_transno,
1008 imp->imp_peer_committed_transno,
1009 imp->imp_last_transno_checked);
1011 /* avg data rates */
1012 for (rw = 0; rw <= 1; rw++) {
1013 lprocfs_stats_collect(obd->obd_svc_stats,
1014 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
1016 if (ret.lc_sum > 0 && ret.lc_count > 0) {
1017 /* first argument to do_div MUST be __u64 */
1018 __u64 sum = ret.lc_sum;
1019 do_div(sum, ret.lc_count);
1021 i += snprintf(page + i, count - i,
1022 " %s_data_averages:\n"
1023 " bytes_per_rpc: "LPU64"\n",
1024 rw ? "write" : "read",
1027 k = (int)ret.lc_sum;
1028 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
1029 header = &obd->obd_svc_stats->ls_cnt_header[j];
1030 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
1031 if (ret.lc_sum > 0 && ret.lc_count != 0) {
1032 /* first argument to do_div MUST be __u64 */
1033 __u64 sum = ret.lc_sum;
1034 do_div(sum, ret.lc_count);
1036 i += snprintf(page + i, count - i,
1037 " %s_per_rpc: "LPU64"\n",
1038 header->lc_units, ret.lc_sum);
1039 j = (int)ret.lc_sum;
1041 i += snprintf(page + i, count - i,
1042 " MB_per_sec: %u.%.02u\n",
1043 k / j, (100 * k / j) % 100);
1048 LPROCFS_CLIMP_EXIT(obd);
1051 EXPORT_SYMBOL(lprocfs_rd_import);
1053 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
1054 int *eof, void *data)
1056 struct obd_device *obd = (struct obd_device *)data;
1057 struct obd_import *imp;
1060 LASSERT(obd != NULL);
1061 LPROCFS_CLIMP_CHECK(obd);
1062 imp = obd->u.cli.cl_import;
1065 i = snprintf(page, count, "current_state: %s\n",
1066 ptlrpc_import_state_name(imp->imp_state));
1067 i += snprintf(page + i, count - i,
1068 "state_history:\n");
1069 k = imp->imp_state_hist_idx;
1070 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
1071 struct import_state_hist *ish =
1072 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
1073 if (ish->ish_state == 0)
1075 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
1077 ptlrpc_import_state_name(ish->ish_state));
1080 LPROCFS_CLIMP_EXIT(obd);
1083 EXPORT_SYMBOL(lprocfs_rd_state);
1085 int lprocfs_at_hist_helper(char *page, int count, int rc,
1086 struct adaptive_timeout *at)
1089 for (i = 0; i < AT_BINS; i++)
1090 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
1091 rc += snprintf(page + rc, count - rc, "\n");
1094 EXPORT_SYMBOL(lprocfs_at_hist_helper);
1096 /* See also ptlrpc_lprocfs_rd_timeouts */
1097 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
1098 int *eof, void *data)
1100 struct obd_device *obd = (struct obd_device *)data;
1101 struct obd_import *imp;
1102 unsigned int cur, worst;
1107 LASSERT(obd != NULL);
1108 LPROCFS_CLIMP_CHECK(obd);
1109 imp = obd->u.cli.cl_import;
1112 now = cfs_time_current_sec();
1114 /* Some network health info for kicks */
1115 s2dhms(&ts, now - imp->imp_last_reply_time);
1116 rc += snprintf(page + rc, count - rc,
1117 "%-10s : %ld, "DHMS_FMT" ago\n",
1118 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
1120 cur = at_get(&imp->imp_at.iat_net_latency);
1121 worst = imp->imp_at.iat_net_latency.at_worst_ever;
1122 worstt = imp->imp_at.iat_net_latency.at_worst_time;
1123 s2dhms(&ts, now - worstt);
1124 rc += snprintf(page + rc, count - rc,
1125 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
1126 "network", cur, worst, worstt, DHMS_VARS(&ts));
1127 rc = lprocfs_at_hist_helper(page, count, rc,
1128 &imp->imp_at.iat_net_latency);
1130 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
1131 if (imp->imp_at.iat_portal[i] == 0)
1133 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
1134 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
1135 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
1136 s2dhms(&ts, now - worstt);
1137 rc += snprintf(page + rc, count - rc,
1138 "portal %-2d : cur %3u worst %3u (at %ld, "
1139 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
1140 cur, worst, worstt, DHMS_VARS(&ts));
1141 rc = lprocfs_at_hist_helper(page, count, rc,
1142 &imp->imp_at.iat_service_estimate[i]);
1145 LPROCFS_CLIMP_EXIT(obd);
1148 EXPORT_SYMBOL(lprocfs_rd_timeouts);
1150 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1151 int count, int *eof, void *data)
1153 struct obd_device *obd = data;
1157 LPROCFS_CLIMP_CHECK(obd);
1158 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1159 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1160 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1161 ret += snprintf(page + ret, count - ret, "\n");
1162 LPROCFS_CLIMP_EXIT(obd);
1165 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1167 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1168 int *eof, void *data)
1170 struct obd_device *obd = data;
1172 LASSERT(obd != NULL);
1174 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1176 EXPORT_SYMBOL(lprocfs_rd_num_exports);
1178 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1179 int *eof, void *data)
1181 struct obd_type *class = (struct obd_type*) data;
1183 LASSERT(class != NULL);
1185 return snprintf(page, count, "%d\n", class->typ_refcnt);
1187 EXPORT_SYMBOL(lprocfs_rd_numrefs);
1189 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1193 LASSERT(obd != NULL);
1194 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1195 LASSERT(obd->obd_type->typ_procroot != NULL);
1197 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1198 obd->obd_type->typ_procroot,
1200 if (IS_ERR(obd->obd_proc_entry)) {
1201 rc = PTR_ERR(obd->obd_proc_entry);
1202 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1203 obd->obd_proc_entry = NULL;
1207 EXPORT_SYMBOL(lprocfs_obd_setup);
1209 int lprocfs_obd_cleanup(struct obd_device *obd)
1213 if (obd->obd_proc_exports_entry) {
1214 /* Should be no exports left */
1215 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1216 lprocfs_remove(&obd->obd_proc_exports_entry);
1217 obd->obd_proc_exports_entry = NULL;
1219 if (obd->obd_proc_entry) {
1220 lprocfs_remove(&obd->obd_proc_entry);
1221 obd->obd_proc_entry = NULL;
1225 EXPORT_SYMBOL(lprocfs_obd_cleanup);
1227 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1229 CDEBUG(D_CONFIG, "stat %p - data %p/%p\n", client_stat,
1230 client_stat->nid_proc, client_stat->nid_stats);
1232 LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
1233 "nid %s:count %d\n", libcfs_nid2str(client_stat->nid),
1234 atomic_read(&client_stat->nid_exp_ref_count));
1236 if (client_stat->nid_proc)
1237 lprocfs_remove(&client_stat->nid_proc);
1239 if (client_stat->nid_stats)
1240 lprocfs_free_stats(&client_stat->nid_stats);
1242 if (client_stat->nid_ldlm_stats)
1243 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1245 OBD_FREE_PTR(client_stat);
1250 void lprocfs_free_per_client_stats(struct obd_device *obd)
1252 cfs_hash_t *hash = obd->obd_nid_stats_hash;
1253 struct nid_stat *stat;
1256 /* we need extra list - because hash_exit called to early */
1257 /* not need locking because all clients is died */
1258 while (!cfs_list_empty(&obd->obd_nid_stats)) {
1259 stat = cfs_list_entry(obd->obd_nid_stats.next,
1260 struct nid_stat, nid_list);
1261 cfs_list_del_init(&stat->nid_list);
1262 cfs_hash_del(hash, &stat->nid, &stat->nid_hash);
1263 lprocfs_free_client_stats(stat);
1267 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
1269 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1270 enum lprocfs_stats_flags flags)
1272 struct lprocfs_stats *stats;
1273 unsigned int num_entry;
1274 unsigned int percpusize = 0;
1280 if (lprocfs_no_percpu_stats != 0)
1281 flags |= LPROCFS_STATS_FLAG_NOPERCPU;
1283 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1286 num_entry = num_possible_cpus();
1288 /* alloc percpu pointers for all possible cpu slots */
1289 LIBCFS_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1293 stats->ls_num = num;
1294 stats->ls_flags = flags;
1295 spin_lock_init(&stats->ls_lock);
1297 /* alloc num of counter headers */
1298 LIBCFS_ALLOC(stats->ls_cnt_header,
1299 stats->ls_num * sizeof(struct lprocfs_counter_header));
1300 if (stats->ls_cnt_header == NULL)
1303 if ((flags & LPROCFS_STATS_FLAG_NOPERCPU) != 0) {
1304 /* contains only one set counters */
1305 percpusize = lprocfs_stats_counter_size(stats);
1306 LIBCFS_ALLOC_ATOMIC(stats->ls_percpu[0], percpusize);
1307 if (stats->ls_percpu[0] == NULL)
1309 stats->ls_biggest_alloc_num = 1;
1310 } else if ((flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0) {
1311 /* alloc all percpu data, currently only obd_memory use this */
1312 for (i = 0; i < num_entry; ++i)
1313 if (lprocfs_stats_alloc_one(stats, i) < 0)
1320 lprocfs_free_stats(&stats);
1323 EXPORT_SYMBOL(lprocfs_alloc_stats);
1325 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1327 struct lprocfs_stats *stats = *statsh;
1328 unsigned int num_entry;
1329 unsigned int percpusize;
1332 if (stats == NULL || stats->ls_num == 0)
1336 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1339 num_entry = num_possible_cpus();
1341 percpusize = lprocfs_stats_counter_size(stats);
1342 for (i = 0; i < num_entry; i++)
1343 if (stats->ls_percpu[i] != NULL)
1344 LIBCFS_FREE(stats->ls_percpu[i], percpusize);
1345 if (stats->ls_cnt_header != NULL)
1346 LIBCFS_FREE(stats->ls_cnt_header, stats->ls_num *
1347 sizeof(struct lprocfs_counter_header));
1348 LIBCFS_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1350 EXPORT_SYMBOL(lprocfs_free_stats);
1352 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1354 struct lprocfs_counter *percpu_cntr;
1357 unsigned int num_entry;
1358 unsigned long flags = 0;
1360 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1362 for (i = 0; i < num_entry; i++) {
1363 if (stats->ls_percpu[i] == NULL)
1365 for (j = 0; j < stats->ls_num; j++) {
1366 percpu_cntr = lprocfs_stats_counter_get(stats, i, j);
1367 percpu_cntr->lc_count = 0;
1368 percpu_cntr->lc_min = LC_MIN_INIT;
1369 percpu_cntr->lc_max = 0;
1370 percpu_cntr->lc_sumsquare = 0;
1371 percpu_cntr->lc_sum = 0;
1372 if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
1373 percpu_cntr->lc_sum_irq = 0;
1377 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1379 EXPORT_SYMBOL(lprocfs_clear_stats);
1381 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1382 size_t len, loff_t *off)
1384 struct seq_file *seq = file->private_data;
1385 struct lprocfs_stats *stats = seq->private;
1387 lprocfs_clear_stats(stats);
1392 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1394 struct lprocfs_stats *stats = p->private;
1396 return (*pos < stats->ls_num) ? pos : NULL;
1399 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1403 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1407 return lprocfs_stats_seq_start(p, pos);
1410 /* seq file export of one lprocfs counter */
1411 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1413 struct lprocfs_stats *stats = p->private;
1414 struct lprocfs_counter_header *hdr;
1415 struct lprocfs_counter ctr;
1416 int idx = *(loff_t *)v;
1422 do_gettimeofday(&now);
1423 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1424 "snapshot_time", now.tv_sec, now.tv_usec);
1429 hdr = &stats->ls_cnt_header[idx];
1430 lprocfs_stats_collect(stats, idx, &ctr);
1432 if (ctr.lc_count == 0)
1435 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", hdr->lc_name,
1436 ctr.lc_count, hdr->lc_units);
1440 if ((hdr->lc_config & LPROCFS_CNTR_AVGMINMAX) && ctr.lc_count > 0) {
1441 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1442 ctr.lc_min, ctr.lc_max, ctr.lc_sum);
1445 if (hdr->lc_config & LPROCFS_CNTR_STDDEV)
1446 rc = seq_printf(p, " "LPD64, ctr.lc_sumsquare);
1450 rc = seq_printf(p, "\n");
1452 return (rc < 0) ? rc : 0;
1455 struct seq_operations lprocfs_stats_seq_sops = {
1456 .start = lprocfs_stats_seq_start,
1457 .stop = lprocfs_stats_seq_stop,
1458 .next = lprocfs_stats_seq_next,
1459 .show = lprocfs_stats_seq_show,
1462 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1464 struct proc_dir_entry *dp = PDE(inode);
1465 struct seq_file *seq;
1468 if (LPROCFS_ENTRY_CHECK(dp))
1471 rc = seq_open(file, &lprocfs_stats_seq_sops);
1474 seq = file->private_data;
1475 seq->private = dp->data;
1479 struct file_operations lprocfs_stats_seq_fops = {
1480 .owner = THIS_MODULE,
1481 .open = lprocfs_stats_seq_open,
1483 .write = lprocfs_stats_seq_write,
1484 .llseek = seq_lseek,
1485 .release = lprocfs_seq_release,
1488 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1489 struct lprocfs_stats *stats)
1491 struct proc_dir_entry *entry;
1492 LASSERT(root != NULL);
1494 LPROCFS_WRITE_ENTRY();
1495 entry = create_proc_entry(name, 0644, root);
1497 entry->proc_fops = &lprocfs_stats_seq_fops;
1498 entry->data = stats;
1501 LPROCFS_WRITE_EXIT();
1508 EXPORT_SYMBOL(lprocfs_register_stats);
1510 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1511 unsigned conf, const char *name, const char *units)
1513 struct lprocfs_counter_header *header;
1514 struct lprocfs_counter *percpu_cntr;
1515 unsigned long flags = 0;
1517 unsigned int num_cpu;
1519 LASSERT(stats != NULL);
1521 header = &stats->ls_cnt_header[index];
1522 LASSERTF(header != NULL, "Failed to allocate stats header:[%d]%s/%s\n",
1523 index, name, units);
1525 header->lc_config = conf;
1526 header->lc_name = name;
1527 header->lc_units = units;
1529 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1530 for (i = 0; i < num_cpu; ++i) {
1531 if (stats->ls_percpu[i] == NULL)
1533 percpu_cntr = lprocfs_stats_counter_get(stats, i, index);
1534 percpu_cntr->lc_count = 0;
1535 percpu_cntr->lc_min = LC_MIN_INIT;
1536 percpu_cntr->lc_max = 0;
1537 percpu_cntr->lc_sumsquare = 0;
1538 percpu_cntr->lc_sum = 0;
1539 if ((stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
1540 percpu_cntr->lc_sum_irq = 0;
1542 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1544 EXPORT_SYMBOL(lprocfs_counter_init);
1546 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1548 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1549 LASSERT(coffset < stats->ls_num); \
1550 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1553 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1555 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1556 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1557 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1558 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1559 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1560 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1561 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1562 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1563 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1564 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1565 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1566 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1567 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1568 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1569 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1570 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1571 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1572 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1573 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1574 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1575 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1576 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1577 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1578 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1579 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1580 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1581 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1582 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1583 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1584 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1585 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1586 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1587 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1588 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1589 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1590 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1591 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1592 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1593 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1594 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1595 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1596 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1597 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1598 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
1599 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1600 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1601 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1602 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1603 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1604 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1605 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1606 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1607 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1608 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1609 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1610 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1611 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1612 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1613 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1614 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1615 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1616 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1617 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1618 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1619 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1620 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1621 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1623 EXPORT_SYMBOL(lprocfs_init_ops_stats);
1625 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1627 struct lprocfs_stats *stats;
1628 unsigned int num_stats;
1631 LASSERT(obd->obd_stats == NULL);
1632 LASSERT(obd->obd_proc_entry != NULL);
1633 LASSERT(obd->obd_cntr_base == 0);
1635 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1636 num_private_stats - 1 /* o_owner */;
1637 stats = lprocfs_alloc_stats(num_stats, 0);
1641 lprocfs_init_ops_stats(num_private_stats, stats);
1643 for (i = num_private_stats; i < num_stats; i++) {
1644 /* If this LBUGs, it is likely that an obd
1645 * operation was added to struct obd_ops in
1646 * <obd.h>, and that the corresponding line item
1647 * LPROCFS_OBD_OP_INIT(.., .., opname)
1648 * is missing from the list above. */
1649 LASSERTF(stats->ls_cnt_header[i].lc_name != NULL,
1650 "Missing obd_stat initializer obd_op "
1651 "operation at offset %d.\n", i - num_private_stats);
1653 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1655 lprocfs_free_stats(&stats);
1657 obd->obd_stats = stats;
1658 obd->obd_cntr_base = num_private_stats;
1662 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
1664 void lprocfs_free_obd_stats(struct obd_device *obd)
1667 lprocfs_free_stats(&obd->obd_stats);
1669 EXPORT_SYMBOL(lprocfs_free_obd_stats);
1671 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1673 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1674 LASSERT(coffset < stats->ls_num); \
1675 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1678 void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats)
1680 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1681 LPROCFS_MD_OP_INIT(num_private_stats, stats, null_inode);
1682 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
1683 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1684 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1685 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1686 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1687 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1688 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1689 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1690 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1691 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1692 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1693 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1694 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1695 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1696 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1697 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1698 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1699 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1700 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1701 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1702 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1703 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1704 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1705 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1706 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1707 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1708 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1709 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1710 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1711 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1713 EXPORT_SYMBOL(lprocfs_init_mps_stats);
1715 int lprocfs_alloc_md_stats(struct obd_device *obd,
1716 unsigned num_private_stats)
1718 struct lprocfs_stats *stats;
1719 unsigned int num_stats;
1722 LASSERT(obd->md_stats == NULL);
1723 LASSERT(obd->obd_proc_entry != NULL);
1724 LASSERT(obd->md_cntr_base == 0);
1726 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1728 stats = lprocfs_alloc_stats(num_stats, 0);
1732 lprocfs_init_mps_stats(num_private_stats, stats);
1734 for (i = num_private_stats; i < num_stats; i++) {
1735 if (stats->ls_cnt_header[i].lc_name == NULL) {
1736 CERROR("Missing md_stat initializer md_op "
1737 "operation at offset %d. Aborting.\n",
1738 i - num_private_stats);
1742 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1744 lprocfs_free_stats(&stats);
1746 obd->md_stats = stats;
1747 obd->md_cntr_base = num_private_stats;
1751 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
1753 void lprocfs_free_md_stats(struct obd_device *obd)
1755 struct lprocfs_stats *stats = obd->md_stats;
1757 if (stats != NULL) {
1758 obd->md_stats = NULL;
1759 obd->md_cntr_base = 0;
1760 lprocfs_free_stats(&stats);
1763 EXPORT_SYMBOL(lprocfs_free_md_stats);
1765 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1767 lprocfs_counter_init(ldlm_stats,
1768 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1769 0, "ldlm_enqueue", "reqs");
1770 lprocfs_counter_init(ldlm_stats,
1771 LDLM_CONVERT - LDLM_FIRST_OPC,
1772 0, "ldlm_convert", "reqs");
1773 lprocfs_counter_init(ldlm_stats,
1774 LDLM_CANCEL - LDLM_FIRST_OPC,
1775 0, "ldlm_cancel", "reqs");
1776 lprocfs_counter_init(ldlm_stats,
1777 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1778 0, "ldlm_bl_callback", "reqs");
1779 lprocfs_counter_init(ldlm_stats,
1780 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1781 0, "ldlm_cp_callback", "reqs");
1782 lprocfs_counter_init(ldlm_stats,
1783 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1784 0, "ldlm_gl_callback", "reqs");
1786 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
1788 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1789 int *eof, void *data)
1791 struct obd_export *exp = data;
1792 LASSERT(exp != NULL);
1794 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1797 struct exp_uuid_cb_data {
1805 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1806 int count, int *eof, int *len)
1808 cb_data->page = page;
1809 cb_data->count = count;
1814 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1815 cfs_hlist_node_t *hnode, void *cb_data)
1818 struct obd_export *exp = cfs_hash_object(hs, hnode);
1819 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1821 if (exp->exp_nid_stats)
1822 *data->len += snprintf((data->page + *data->len),
1823 data->count, "%s\n",
1824 obd_uuid2str(&exp->exp_client_uuid));
1828 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1829 int *eof, void *data)
1831 struct nid_stat *stats = (struct nid_stat *)data;
1832 struct exp_uuid_cb_data cb_data;
1833 struct obd_device *obd = stats->nid_obd;
1838 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1839 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1840 lprocfs_exp_print_uuid, &cb_data);
1841 return (*cb_data.len);
1844 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1845 cfs_hlist_node_t *hnode, void *cb_data)
1848 struct exp_uuid_cb_data *data = cb_data;
1849 struct obd_export *exp = cfs_hash_object(hs, hnode);
1851 if (exp->exp_lock_hash != NULL) {
1853 *data->len += cfs_hash_debug_header(data->page,
1856 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1863 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1864 int *eof, void *data)
1866 struct nid_stat *stats = (struct nid_stat *)data;
1867 struct exp_uuid_cb_data cb_data;
1868 struct obd_device *obd = stats->nid_obd;
1873 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1875 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1876 lprocfs_exp_print_hash, &cb_data);
1877 return (*cb_data.len);
1880 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1881 int count, int *eof, void *data)
1884 return snprintf(page, count, "%s\n",
1885 "Write into this file to clear all nid stats and "
1886 "stale nid entries");
1888 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1890 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1892 struct nid_stat *stat = obj;
1895 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
1896 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 1) {
1897 /* object has only hash references. */
1898 spin_lock(&stat->nid_obd->obd_nid_lock);
1899 cfs_list_move(&stat->nid_list, data);
1900 spin_unlock(&stat->nid_obd->obd_nid_lock);
1903 /* we has reference to object - only clear data*/
1904 if (stat->nid_stats)
1905 lprocfs_clear_stats(stat->nid_stats);
1910 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1911 unsigned long count, void *data)
1913 struct obd_device *obd = (struct obd_device *)data;
1914 struct nid_stat *client_stat;
1915 CFS_LIST_HEAD(free_list);
1917 cfs_hash_cond_del(obd->obd_nid_stats_hash,
1918 lprocfs_nid_stats_clear_write_cb, &free_list);
1920 while (!cfs_list_empty(&free_list)) {
1921 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
1923 cfs_list_del_init(&client_stat->nid_list);
1924 lprocfs_free_client_stats(client_stat);
1929 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1931 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1933 struct nid_stat *new_stat, *old_stat;
1934 struct obd_device *obd = NULL;
1935 cfs_proc_dir_entry_t *entry;
1936 char *buffer = NULL;
1942 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1943 !exp->exp_obd->obd_nid_stats_hash)
1946 /* not test against zero because eric say:
1947 * You may only test nid against another nid, or LNET_NID_ANY.
1948 * Anything else is nonsense.*/
1949 if (!nid || *nid == LNET_NID_ANY)
1954 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
1956 OBD_ALLOC_PTR(new_stat);
1957 if (new_stat == NULL)
1960 new_stat->nid = *nid;
1961 new_stat->nid_obd = exp->exp_obd;
1962 /* we need set default refcount to 1 to balance obd_disconnect */
1963 cfs_atomic_set(&new_stat->nid_exp_ref_count, 1);
1965 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
1966 nid, &new_stat->nid_hash);
1967 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
1968 old_stat, libcfs_nid2str(*nid),
1969 cfs_atomic_read(&new_stat->nid_exp_ref_count));
1971 /* We need to release old stats because lprocfs_exp_cleanup() hasn't
1972 * been and will never be called. */
1973 if (exp->exp_nid_stats) {
1974 nidstat_putref(exp->exp_nid_stats);
1975 exp->exp_nid_stats = NULL;
1978 /* Return -EALREADY here so that we know that the /proc
1979 * entry already has been created */
1980 if (old_stat != new_stat) {
1981 exp->exp_nid_stats = old_stat;
1982 GOTO(destroy_new, rc = -EALREADY);
1984 /* not found - create */
1985 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
1987 GOTO(destroy_new, rc = -ENOMEM);
1989 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
1990 new_stat->nid_proc = lprocfs_register(buffer,
1991 obd->obd_proc_exports_entry,
1993 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
1995 if (IS_ERR(new_stat->nid_proc)) {
1996 rc = PTR_ERR(new_stat->nid_proc);
1997 new_stat->nid_proc = NULL;
1998 CERROR("%s: cannot create proc entry for export %s: rc = %d\n",
1999 obd->obd_name, libcfs_nid2str(*nid), rc);
2000 GOTO(destroy_new_ns, rc);
2003 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
2004 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
2005 if (IS_ERR(entry)) {
2006 CWARN("Error adding the NID stats file\n");
2007 rc = PTR_ERR(entry);
2008 GOTO(destroy_new_ns, rc);
2011 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
2012 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
2013 if (IS_ERR(entry)) {
2014 CWARN("Error adding the hash file\n");
2015 rc = PTR_ERR(entry);
2016 GOTO(destroy_new_ns, rc);
2019 exp->exp_nid_stats = new_stat;
2021 /* protect competitive add to list, not need locking on destroy */
2022 spin_lock(&obd->obd_nid_lock);
2023 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
2024 spin_unlock(&obd->obd_nid_lock);
2029 if (new_stat->nid_proc != NULL)
2030 lprocfs_remove(&new_stat->nid_proc);
2031 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
2034 nidstat_putref(new_stat);
2035 OBD_FREE_PTR(new_stat);
2038 EXPORT_SYMBOL(lprocfs_exp_setup);
2040 int lprocfs_exp_cleanup(struct obd_export *exp)
2042 struct nid_stat *stat = exp->exp_nid_stats;
2044 if(!stat || !exp->exp_obd)
2047 nidstat_putref(exp->exp_nid_stats);
2048 exp->exp_nid_stats = NULL;
2052 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2054 int lprocfs_write_helper(const char *buffer, unsigned long count,
2057 return lprocfs_write_frac_helper(buffer, count, val, 1);
2059 EXPORT_SYMBOL(lprocfs_write_helper);
2061 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
2064 char kernbuf[20], *end, *pbuf;
2066 if (count > (sizeof(kernbuf) - 1))
2069 if (copy_from_user(kernbuf, buffer, count))
2072 kernbuf[count] = '\0';
2079 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2083 if (end != NULL && *end == '.') {
2084 int temp_val, pow = 1;
2088 if (strlen(pbuf) > 5)
2089 pbuf[5] = '\0'; /*only allow 5bits fractional*/
2091 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2094 for (i = 0; i < (end - pbuf); i++)
2097 *val += temp_val / pow;
2102 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2104 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
2107 long decimal_val, frac_val;
2113 decimal_val = val / mult;
2114 prtn = snprintf(buffer, count, "%ld", decimal_val);
2115 frac_val = val % mult;
2117 if (prtn < (count - 4) && frac_val > 0) {
2119 int i, temp_mult = 1, frac_bits = 0;
2121 temp_frac = frac_val * 10;
2122 buffer[prtn++] = '.';
2123 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
2124 /* only reserved 2 bits fraction */
2125 buffer[prtn++] ='0';
2130 * Need to think these cases :
2131 * 1. #echo x.00 > /proc/xxx output result : x
2132 * 2. #echo x.0x > /proc/xxx output result : x.0x
2133 * 3. #echo x.x0 > /proc/xxx output result : x.x
2134 * 4. #echo x.xx > /proc/xxx output result : x.xx
2135 * Only reserved 2 bits fraction.
2137 for (i = 0; i < (5 - prtn); i++)
2140 frac_bits = min((int)count - prtn, 3 - frac_bits);
2141 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
2142 frac_val * temp_mult / mult);
2145 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
2147 if (buffer[prtn] == '.') {
2154 buffer[prtn++] ='\n';
2157 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2159 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
2161 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
2163 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2165 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
2166 __u64 *val, int mult)
2168 char kernbuf[22], *end, *pbuf;
2169 __u64 whole, frac = 0, units;
2170 unsigned frac_d = 1;
2172 if (count > (sizeof(kernbuf) - 1))
2175 if (copy_from_user(kernbuf, buffer, count))
2178 kernbuf[count] = '\0';
2185 whole = simple_strtoull(pbuf, &end, 10);
2189 if (end != NULL && *end == '.') {
2193 /* need to limit frac_d to a __u32 */
2194 if (strlen(pbuf) > 10)
2197 frac = simple_strtoull(pbuf, &end, 10);
2198 /* count decimal places */
2199 for (i = 0; i < (end - pbuf); i++)
2216 /* Specified units override the multiplier */
2218 mult = mult < 0 ? -units : units;
2221 do_div(frac, frac_d);
2222 *val = whole * mult + frac;
2225 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2227 static char *lprocfs_strnstr(const char *s1, const char *s2, size_t len)
2236 if (!memcmp(s1, s2, l2))
2244 * Find the string \a name in the input \a buffer, and return a pointer to the
2245 * value immediately following \a name, reducing \a count appropriately.
2246 * If \a name is not found the original \a buffer is returned.
2248 char *lprocfs_find_named_value(const char *buffer, const char *name,
2249 unsigned long *count)
2252 size_t buflen = *count;
2254 /* there is no strnstr() in rhel5 and ubuntu kernels */
2255 val = lprocfs_strnstr(buffer, name, buflen);
2257 return (char *)buffer;
2259 val += strlen(name); /* skip prefix */
2260 while (val < buffer + buflen && isspace(*val)) /* skip separator */
2264 while (val < buffer + buflen && isalnum(*val)) {
2269 return val - *count;
2271 EXPORT_SYMBOL(lprocfs_find_named_value);
2273 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent,
2276 const struct file_operations *seq_fops,
2279 struct proc_dir_entry *entry;
2282 /* Disallow secretly (un)writable entries. */
2283 LASSERT((seq_fops->write == NULL) == ((mode & 0222) == 0));
2285 LPROCFS_WRITE_ENTRY();
2286 entry = create_proc_entry(name, mode, parent);
2288 entry->proc_fops = seq_fops;
2291 LPROCFS_WRITE_EXIT();
2298 EXPORT_SYMBOL(lprocfs_seq_create);
2300 int lprocfs_obd_seq_create(struct obd_device *dev,
2303 const struct file_operations *seq_fops,
2306 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2307 mode, seq_fops, data));
2309 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2311 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2313 if (value >= OBD_HIST_MAX)
2314 value = OBD_HIST_MAX - 1;
2316 spin_lock(&oh->oh_lock);
2317 oh->oh_buckets[value]++;
2318 spin_unlock(&oh->oh_lock);
2320 EXPORT_SYMBOL(lprocfs_oh_tally);
2322 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2326 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2329 lprocfs_oh_tally(oh, val);
2331 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2333 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2335 unsigned long ret = 0;
2338 for (i = 0; i < OBD_HIST_MAX; i++)
2339 ret += oh->oh_buckets[i];
2342 EXPORT_SYMBOL(lprocfs_oh_sum);
2344 void lprocfs_oh_clear(struct obd_histogram *oh)
2346 spin_lock(&oh->oh_lock);
2347 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2348 spin_unlock(&oh->oh_lock);
2350 EXPORT_SYMBOL(lprocfs_oh_clear);
2352 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2353 int count, int *eof, void *data)
2355 struct obd_device *obd = data;
2361 c += cfs_hash_debug_header(page, count);
2362 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2363 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2364 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2368 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2370 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2371 int count, int *eof, void *data)
2373 struct obd_device *obd = data;
2376 LASSERT(obd != NULL);
2377 LASSERT(count >= 0);
2379 /* Set start of user data returned to
2380 page + off since the user may have
2381 requested to read much smaller than
2382 what we need to read */
2383 *start = page + off;
2386 * We know we are allocated a page here.
2387 * Also we know that this function will
2388 * not need to write more than a page
2389 * so we can truncate at PAGE_CACHE_SIZE.
2391 size = min(count + (int)off + 1, (int)PAGE_CACHE_SIZE);
2393 /* Initialize the page */
2394 memset(page, 0, size);
2396 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2398 if (obd->obd_max_recoverable_clients == 0) {
2399 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2405 /* sampled unlocked, but really... */
2406 if (obd->obd_recovering == 0) {
2407 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2409 if (lprocfs_obd_snprintf(&page, size, &len,
2410 "recovery_start: %lu\n",
2411 obd->obd_recovery_start) <= 0)
2413 if (lprocfs_obd_snprintf(&page, size, &len,
2414 "recovery_duration: %lu\n",
2415 obd->obd_recovery_end -
2416 obd->obd_recovery_start) <= 0)
2418 /* Number of clients that have completed recovery */
2419 if (lprocfs_obd_snprintf(&page, size, &len,
2420 "completed_clients: %d/%d\n",
2421 obd->obd_max_recoverable_clients -
2422 obd->obd_stale_clients,
2423 obd->obd_max_recoverable_clients) <= 0)
2425 if (lprocfs_obd_snprintf(&page, size, &len,
2426 "replayed_requests: %d\n",
2427 obd->obd_replayed_requests) <= 0)
2429 if (lprocfs_obd_snprintf(&page, size, &len,
2430 "last_transno: "LPD64"\n",
2431 obd->obd_next_recovery_transno - 1)<=0)
2433 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2434 obd->obd_version_recov ?
2435 "ENABLED" : "DISABLED") <=0)
2437 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
2439 "DISABLED" : "ENABLED") <= 0)
2444 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2446 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2447 obd->obd_recovery_start) <= 0)
2449 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2450 cfs_time_current_sec() >=
2451 obd->obd_recovery_start +
2452 obd->obd_recovery_timeout ? 0 :
2453 obd->obd_recovery_start +
2454 obd->obd_recovery_timeout -
2455 cfs_time_current_sec()) <= 0)
2457 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2458 cfs_atomic_read(&obd->obd_connected_clients),
2459 obd->obd_max_recoverable_clients) <= 0)
2461 /* Number of clients that have completed recovery */
2462 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2463 cfs_atomic_read(&obd->obd_req_replay_clients))
2466 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2467 cfs_atomic_read(&obd->obd_lock_replay_clients))
2470 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2471 cfs_atomic_read(&obd->obd_connected_clients) -
2472 cfs_atomic_read(&obd->obd_lock_replay_clients))
2475 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2476 obd->obd_stale_clients) <= 0)
2478 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2479 obd->obd_replayed_requests) <= 0)
2481 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2482 obd->obd_requests_queued_for_recovery) <= 0)
2485 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2486 obd->obd_next_recovery_transno) <= 0)
2492 return min(count, len - (int)off);
2494 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2496 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
2497 int count, int *eof, void *data)
2499 struct obd_device *obd = (struct obd_device *)data;
2500 LASSERT(obd != NULL);
2502 return snprintf(page, count, "%d\n",
2503 obd->obd_recovery_ir_factor);
2505 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
2507 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
2508 unsigned long count, void *data)
2510 struct obd_device *obd = (struct obd_device *)data;
2512 LASSERT(obd != NULL);
2514 rc = lprocfs_write_helper(buffer, count, &val);
2518 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
2521 obd->obd_recovery_ir_factor = val;
2524 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
2526 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
2527 int count, int *eof, void *data)
2529 struct obd_device *obd = (struct obd_device *)data;
2530 LASSERT(obd != NULL);
2532 return snprintf(page, count, "%d\n",
2533 obd->obd_recovery_timeout);
2535 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
2537 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
2538 unsigned long count, void *data)
2540 struct obd_device *obd = (struct obd_device *)data;
2542 LASSERT(obd != NULL);
2544 rc = lprocfs_write_helper(buffer, count, &val);
2548 obd->obd_recovery_timeout = val;
2551 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
2553 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
2554 int count, int *eof, void *data)
2556 struct obd_device *obd = data;
2557 LASSERT(obd != NULL);
2559 return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
2561 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
2563 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
2564 unsigned long count, void *data)
2566 struct obd_device *obd = data;
2568 LASSERT(obd != NULL);
2570 rc = lprocfs_write_helper(buffer, count, &val);
2574 obd->obd_recovery_time_hard = val;
2577 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
2579 int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
2580 int count, int *eof, void *data)
2582 struct obd_device *dev = data;
2583 struct client_obd *cli = &dev->u.cli;
2586 client_obd_list_lock(&cli->cl_loi_list_lock);
2587 rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
2588 client_obd_list_unlock(&cli->cl_loi_list_lock);
2591 EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
2593 #ifdef HAVE_SERVER_SUPPORT
2594 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
2595 int count, int *eof, void *data)
2597 struct obd_device *obd = (struct obd_device *)data;
2598 struct obd_device_target *target = &obd->u.obt;
2600 LASSERT(obd != NULL);
2601 LASSERT(target->obt_magic == OBT_MAGIC);
2603 return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
2605 EXPORT_SYMBOL(lprocfs_target_rd_instance);