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;
779 struct lprocfs_counter_header *cntr_header;
781 unsigned long flags = 0;
783 memset(cnt, 0, sizeof(*cnt));
786 /* set count to 1 to avoid divide-by-zero errs in callers */
791 cnt->lc_min = LC_MIN_INIT;
793 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
795 for (i = 0; i < num_entry; i++) {
796 if (stats->ls_percpu[i] == NULL)
798 cntr_header = &stats->ls_cnt_header[idx];
799 percpu_cntr = lprocfs_stats_counter_get(stats, i, idx);
801 cnt->lc_count += percpu_cntr->lc_count;
802 cnt->lc_sum += percpu_cntr->lc_sum;
803 if (percpu_cntr->lc_min < cnt->lc_min)
804 cnt->lc_min = percpu_cntr->lc_min;
805 if (percpu_cntr->lc_max > cnt->lc_max)
806 cnt->lc_max = percpu_cntr->lc_max;
807 cnt->lc_sumsquare += percpu_cntr->lc_sumsquare;
810 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
812 EXPORT_SYMBOL(lprocfs_stats_collect);
815 * Append a space separated list of current set flags to str.
817 #define flag2str(flag) \
818 if (imp->imp_##flag && max - len > 0) \
819 len += snprintf(str + len, max - len, "%s" #flag, len ? ", " : "");
820 static int obd_import_flags2str(struct obd_import *imp, char *str, int max)
824 if (imp->imp_obd->obd_no_recov)
825 len += snprintf(str, max - len, "no_recov");
829 flag2str(replayable);
835 static const char *obd_connect_names[] = {
849 "join_file(obsolete)",
853 "remote_client_by_force",
862 "mds_mds_connection",
865 "alt_checksum_algorithm",
891 int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
896 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
898 ret += snprintf(page + ret, count - ret, "%s%s",
899 ret ? sep : "", obd_connect_names[i]);
901 if (flags & ~(mask - 1))
902 ret += snprintf(page + ret, count - ret,
903 "%sunknown flags "LPX64,
904 ret ? sep : "", flags & ~(mask - 1));
907 EXPORT_SYMBOL(obd_connect_flags2str);
909 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
910 int *eof, void *data)
912 struct lprocfs_counter ret;
913 struct lprocfs_counter_header *header;
914 struct obd_device *obd = (struct obd_device *)data;
915 struct obd_import *imp;
916 struct obd_import_conn *conn;
922 LASSERT(obd != NULL);
923 LPROCFS_CLIMP_CHECK(obd);
924 imp = obd->u.cli.cl_import;
927 i = snprintf(page, count,
936 ptlrpc_import_state_name(imp->imp_state),
937 imp->imp_connect_data.ocd_instance);
938 i += obd_connect_flags2str(page + i, count - i,
939 imp->imp_connect_data.ocd_connect_flags,
941 i += snprintf(page + i, count - i,
944 i += obd_import_flags2str(imp, page + i, count - i);
946 i += snprintf(page + i, count - i,
949 " failover_nids: [");
950 spin_lock(&imp->imp_lock);
952 cfs_list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
953 i += snprintf(page + i, count - i, "%s%s", j ? ", " : "",
954 libcfs_nid2str(conn->oic_conn->c_peer.nid));
957 i += snprintf(page + i, count - i,
959 " current_connection: %s\n"
960 " connection_attempts: %u\n"
962 " in-progress_invalidations: %u\n",
963 imp->imp_connection == NULL ? "<none>" :
964 libcfs_nid2str(imp->imp_connection->c_peer.nid),
967 cfs_atomic_read(&imp->imp_inval_count));
968 spin_unlock(&imp->imp_lock);
970 if (obd->obd_svc_stats == NULL)
973 header = &obd->obd_svc_stats->ls_cnt_header[PTLRPC_REQWAIT_CNTR];
974 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
975 if (ret.lc_count != 0) {
976 /* first argument to do_div MUST be __u64 */
977 __u64 sum = ret.lc_sum;
978 do_div(sum, ret.lc_count);
982 i += snprintf(page + i, count - i,
985 " unregistering: %u\n"
987 " avg_waittime: "LPU64" %s\n",
988 cfs_atomic_read(&imp->imp_inflight),
989 cfs_atomic_read(&imp->imp_unregistering),
990 cfs_atomic_read(&imp->imp_timeouts),
991 ret.lc_sum, header->lc_units);
994 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
995 if (imp->imp_at.iat_portal[j] == 0)
997 k = max_t(unsigned int, k,
998 at_get(&imp->imp_at.iat_service_estimate[j]));
1000 i += snprintf(page + i, count - i,
1001 " service_estimates:\n"
1002 " services: %u sec\n"
1003 " network: %u sec\n",
1005 at_get(&imp->imp_at.iat_net_latency));
1007 i += snprintf(page + i, count - i,
1009 " last_replay: "LPU64"\n"
1010 " peer_committed: "LPU64"\n"
1011 " last_checked: "LPU64"\n",
1012 imp->imp_last_replay_transno,
1013 imp->imp_peer_committed_transno,
1014 imp->imp_last_transno_checked);
1016 /* avg data rates */
1017 for (rw = 0; rw <= 1; rw++) {
1018 lprocfs_stats_collect(obd->obd_svc_stats,
1019 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
1021 if (ret.lc_sum > 0 && ret.lc_count > 0) {
1022 /* first argument to do_div MUST be __u64 */
1023 __u64 sum = ret.lc_sum;
1024 do_div(sum, ret.lc_count);
1026 i += snprintf(page + i, count - i,
1027 " %s_data_averages:\n"
1028 " bytes_per_rpc: "LPU64"\n",
1029 rw ? "write" : "read",
1032 k = (int)ret.lc_sum;
1033 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
1034 header = &obd->obd_svc_stats->ls_cnt_header[j];
1035 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
1036 if (ret.lc_sum > 0 && ret.lc_count != 0) {
1037 /* first argument to do_div MUST be __u64 */
1038 __u64 sum = ret.lc_sum;
1039 do_div(sum, ret.lc_count);
1041 i += snprintf(page + i, count - i,
1042 " %s_per_rpc: "LPU64"\n",
1043 header->lc_units, ret.lc_sum);
1044 j = (int)ret.lc_sum;
1046 i += snprintf(page + i, count - i,
1047 " MB_per_sec: %u.%.02u\n",
1048 k / j, (100 * k / j) % 100);
1053 LPROCFS_CLIMP_EXIT(obd);
1056 EXPORT_SYMBOL(lprocfs_rd_import);
1058 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
1059 int *eof, void *data)
1061 struct obd_device *obd = (struct obd_device *)data;
1062 struct obd_import *imp;
1065 LASSERT(obd != NULL);
1066 LPROCFS_CLIMP_CHECK(obd);
1067 imp = obd->u.cli.cl_import;
1070 i = snprintf(page, count, "current_state: %s\n",
1071 ptlrpc_import_state_name(imp->imp_state));
1072 i += snprintf(page + i, count - i,
1073 "state_history:\n");
1074 k = imp->imp_state_hist_idx;
1075 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
1076 struct import_state_hist *ish =
1077 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
1078 if (ish->ish_state == 0)
1080 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
1082 ptlrpc_import_state_name(ish->ish_state));
1085 LPROCFS_CLIMP_EXIT(obd);
1088 EXPORT_SYMBOL(lprocfs_rd_state);
1090 int lprocfs_at_hist_helper(char *page, int count, int rc,
1091 struct adaptive_timeout *at)
1094 for (i = 0; i < AT_BINS; i++)
1095 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
1096 rc += snprintf(page + rc, count - rc, "\n");
1099 EXPORT_SYMBOL(lprocfs_at_hist_helper);
1101 /* See also ptlrpc_lprocfs_rd_timeouts */
1102 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
1103 int *eof, void *data)
1105 struct obd_device *obd = (struct obd_device *)data;
1106 struct obd_import *imp;
1107 unsigned int cur, worst;
1112 LASSERT(obd != NULL);
1113 LPROCFS_CLIMP_CHECK(obd);
1114 imp = obd->u.cli.cl_import;
1117 now = cfs_time_current_sec();
1119 /* Some network health info for kicks */
1120 s2dhms(&ts, now - imp->imp_last_reply_time);
1121 rc += snprintf(page + rc, count - rc,
1122 "%-10s : %ld, "DHMS_FMT" ago\n",
1123 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
1125 cur = at_get(&imp->imp_at.iat_net_latency);
1126 worst = imp->imp_at.iat_net_latency.at_worst_ever;
1127 worstt = imp->imp_at.iat_net_latency.at_worst_time;
1128 s2dhms(&ts, now - worstt);
1129 rc += snprintf(page + rc, count - rc,
1130 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
1131 "network", cur, worst, worstt, DHMS_VARS(&ts));
1132 rc = lprocfs_at_hist_helper(page, count, rc,
1133 &imp->imp_at.iat_net_latency);
1135 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
1136 if (imp->imp_at.iat_portal[i] == 0)
1138 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
1139 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
1140 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
1141 s2dhms(&ts, now - worstt);
1142 rc += snprintf(page + rc, count - rc,
1143 "portal %-2d : cur %3u worst %3u (at %ld, "
1144 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
1145 cur, worst, worstt, DHMS_VARS(&ts));
1146 rc = lprocfs_at_hist_helper(page, count, rc,
1147 &imp->imp_at.iat_service_estimate[i]);
1150 LPROCFS_CLIMP_EXIT(obd);
1153 EXPORT_SYMBOL(lprocfs_rd_timeouts);
1155 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1156 int count, int *eof, void *data)
1158 struct obd_device *obd = data;
1162 LPROCFS_CLIMP_CHECK(obd);
1163 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1164 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1165 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1166 ret += snprintf(page + ret, count - ret, "\n");
1167 LPROCFS_CLIMP_EXIT(obd);
1170 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1172 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1173 int *eof, void *data)
1175 struct obd_device *obd = data;
1177 LASSERT(obd != NULL);
1179 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1181 EXPORT_SYMBOL(lprocfs_rd_num_exports);
1183 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1184 int *eof, void *data)
1186 struct obd_type *class = (struct obd_type*) data;
1188 LASSERT(class != NULL);
1190 return snprintf(page, count, "%d\n", class->typ_refcnt);
1192 EXPORT_SYMBOL(lprocfs_rd_numrefs);
1194 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1198 LASSERT(obd != NULL);
1199 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1200 LASSERT(obd->obd_type->typ_procroot != NULL);
1202 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1203 obd->obd_type->typ_procroot,
1205 if (IS_ERR(obd->obd_proc_entry)) {
1206 rc = PTR_ERR(obd->obd_proc_entry);
1207 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1208 obd->obd_proc_entry = NULL;
1212 EXPORT_SYMBOL(lprocfs_obd_setup);
1214 int lprocfs_obd_cleanup(struct obd_device *obd)
1218 if (obd->obd_proc_exports_entry) {
1219 /* Should be no exports left */
1220 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1221 lprocfs_remove(&obd->obd_proc_exports_entry);
1222 obd->obd_proc_exports_entry = NULL;
1224 if (obd->obd_proc_entry) {
1225 lprocfs_remove(&obd->obd_proc_entry);
1226 obd->obd_proc_entry = NULL;
1230 EXPORT_SYMBOL(lprocfs_obd_cleanup);
1232 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1234 CDEBUG(D_CONFIG, "stat %p - data %p/%p\n", client_stat,
1235 client_stat->nid_proc, client_stat->nid_stats);
1237 LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
1238 "nid %s:count %d\n", libcfs_nid2str(client_stat->nid),
1239 atomic_read(&client_stat->nid_exp_ref_count));
1241 if (client_stat->nid_proc)
1242 lprocfs_remove(&client_stat->nid_proc);
1244 if (client_stat->nid_stats)
1245 lprocfs_free_stats(&client_stat->nid_stats);
1247 if (client_stat->nid_ldlm_stats)
1248 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1250 OBD_FREE_PTR(client_stat);
1255 void lprocfs_free_per_client_stats(struct obd_device *obd)
1257 cfs_hash_t *hash = obd->obd_nid_stats_hash;
1258 struct nid_stat *stat;
1261 /* we need extra list - because hash_exit called to early */
1262 /* not need locking because all clients is died */
1263 while (!cfs_list_empty(&obd->obd_nid_stats)) {
1264 stat = cfs_list_entry(obd->obd_nid_stats.next,
1265 struct nid_stat, nid_list);
1266 cfs_list_del_init(&stat->nid_list);
1267 cfs_hash_del(hash, &stat->nid, &stat->nid_hash);
1268 lprocfs_free_client_stats(stat);
1272 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
1274 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1275 enum lprocfs_stats_flags flags)
1277 struct lprocfs_stats *stats;
1278 unsigned int num_entry;
1279 unsigned int percpusize = 0;
1285 if (lprocfs_no_percpu_stats != 0)
1286 flags |= LPROCFS_STATS_FLAG_NOPERCPU;
1288 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1291 num_entry = cfs_num_possible_cpus();
1293 /* alloc percpu pointers for all possible cpu slots */
1294 LIBCFS_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1298 stats->ls_num = num;
1299 stats->ls_flags = flags;
1300 spin_lock_init(&stats->ls_lock);
1302 /* alloc num of counter headers */
1303 LIBCFS_ALLOC(stats->ls_cnt_header,
1304 stats->ls_num * sizeof(struct lprocfs_counter_header));
1305 if (stats->ls_cnt_header == NULL)
1308 if ((flags & LPROCFS_STATS_FLAG_NOPERCPU) != 0) {
1309 /* contains only one set counters */
1310 percpusize = lprocfs_stats_counter_size(stats);
1311 LIBCFS_ALLOC_ATOMIC(stats->ls_percpu[0], percpusize);
1312 if (stats->ls_percpu[0] == NULL)
1314 stats->ls_biggest_alloc_num = 1;
1315 } else if ((flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0) {
1316 /* alloc all percpu data, currently only obd_memory use this */
1317 for (i = 0; i < num_entry; ++i)
1318 if (lprocfs_stats_alloc_one(stats, i) < 0)
1325 lprocfs_free_stats(&stats);
1328 EXPORT_SYMBOL(lprocfs_alloc_stats);
1330 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1332 struct lprocfs_stats *stats = *statsh;
1333 unsigned int num_entry;
1334 unsigned int percpusize;
1337 if (stats == NULL || stats->ls_num == 0)
1341 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1344 num_entry = cfs_num_possible_cpus();
1346 percpusize = lprocfs_stats_counter_size(stats);
1347 for (i = 0; i < num_entry; i++)
1348 if (stats->ls_percpu[i] != NULL)
1349 LIBCFS_FREE(stats->ls_percpu[i], percpusize);
1350 if (stats->ls_cnt_header != NULL)
1351 LIBCFS_FREE(stats->ls_cnt_header, stats->ls_num *
1352 sizeof(struct lprocfs_counter_header));
1353 LIBCFS_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1355 EXPORT_SYMBOL(lprocfs_free_stats);
1357 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1359 struct lprocfs_counter *percpu_cntr;
1360 struct lprocfs_counter_header *header;
1363 unsigned int num_entry;
1364 unsigned long flags = 0;
1366 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1368 for (i = 0; i < num_entry; i++) {
1369 if (stats->ls_percpu[i] == NULL)
1371 for (j = 0; j < stats->ls_num; j++) {
1372 header = &stats->ls_cnt_header[j];
1373 percpu_cntr = lprocfs_stats_counter_get(stats, i, j);
1374 percpu_cntr->lc_count = 0;
1375 percpu_cntr->lc_min = LC_MIN_INIT;
1376 percpu_cntr->lc_max = 0;
1377 percpu_cntr->lc_sumsquare = 0;
1378 percpu_cntr->lc_sum = 0;
1379 if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
1380 percpu_cntr->lc_sum_irq = 0;
1384 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1386 EXPORT_SYMBOL(lprocfs_clear_stats);
1388 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1389 size_t len, loff_t *off)
1391 struct seq_file *seq = file->private_data;
1392 struct lprocfs_stats *stats = seq->private;
1394 lprocfs_clear_stats(stats);
1399 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1401 struct lprocfs_stats *stats = p->private;
1403 return (*pos < stats->ls_num) ? pos : NULL;
1406 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1410 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1414 return lprocfs_stats_seq_start(p, pos);
1417 /* seq file export of one lprocfs counter */
1418 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1420 struct lprocfs_stats *stats = p->private;
1421 struct lprocfs_counter_header *hdr;
1422 struct lprocfs_counter ctr;
1423 int idx = *(loff_t *)v;
1429 cfs_gettimeofday(&now);
1430 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1431 "snapshot_time", now.tv_sec, now.tv_usec);
1436 hdr = &stats->ls_cnt_header[idx];
1437 lprocfs_stats_collect(stats, idx, &ctr);
1439 if (ctr.lc_count == 0)
1442 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", hdr->lc_name,
1443 ctr.lc_count, hdr->lc_units);
1447 if ((hdr->lc_config & LPROCFS_CNTR_AVGMINMAX) && ctr.lc_count > 0) {
1448 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1449 ctr.lc_min, ctr.lc_max, ctr.lc_sum);
1452 if (hdr->lc_config & LPROCFS_CNTR_STDDEV)
1453 rc = seq_printf(p, " "LPD64, ctr.lc_sumsquare);
1457 rc = seq_printf(p, "\n");
1459 return (rc < 0) ? rc : 0;
1462 struct seq_operations lprocfs_stats_seq_sops = {
1463 .start = lprocfs_stats_seq_start,
1464 .stop = lprocfs_stats_seq_stop,
1465 .next = lprocfs_stats_seq_next,
1466 .show = lprocfs_stats_seq_show,
1469 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1471 struct proc_dir_entry *dp = PDE(inode);
1472 struct seq_file *seq;
1475 if (LPROCFS_ENTRY_AND_CHECK(dp))
1478 rc = seq_open(file, &lprocfs_stats_seq_sops);
1483 seq = file->private_data;
1484 seq->private = dp->data;
1488 struct file_operations lprocfs_stats_seq_fops = {
1489 .owner = THIS_MODULE,
1490 .open = lprocfs_stats_seq_open,
1492 .write = lprocfs_stats_seq_write,
1493 .llseek = seq_lseek,
1494 .release = lprocfs_seq_release,
1497 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1498 struct lprocfs_stats *stats)
1500 struct proc_dir_entry *entry;
1501 LASSERT(root != NULL);
1503 LPROCFS_WRITE_ENTRY();
1504 entry = create_proc_entry(name, 0644, root);
1506 entry->proc_fops = &lprocfs_stats_seq_fops;
1507 entry->data = stats;
1510 LPROCFS_WRITE_EXIT();
1517 EXPORT_SYMBOL(lprocfs_register_stats);
1519 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1520 unsigned conf, const char *name, const char *units)
1522 struct lprocfs_counter_header *header;
1523 struct lprocfs_counter *percpu_cntr;
1524 unsigned long flags = 0;
1526 unsigned int num_cpu;
1528 LASSERT(stats != NULL);
1530 header = &stats->ls_cnt_header[index];
1531 LASSERTF(header != NULL, "Failed to allocate stats header:[%d]%s/%s\n",
1532 index, name, units);
1534 header->lc_config = conf;
1535 header->lc_name = name;
1536 header->lc_units = units;
1538 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1539 for (i = 0; i < num_cpu; ++i) {
1540 if (stats->ls_percpu[i] == NULL)
1542 percpu_cntr = lprocfs_stats_counter_get(stats, i, index);
1543 percpu_cntr->lc_count = 0;
1544 percpu_cntr->lc_min = LC_MIN_INIT;
1545 percpu_cntr->lc_max = 0;
1546 percpu_cntr->lc_sumsquare = 0;
1547 percpu_cntr->lc_sum = 0;
1548 if ((stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
1549 percpu_cntr->lc_sum_irq = 0;
1551 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1553 EXPORT_SYMBOL(lprocfs_counter_init);
1555 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1557 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1558 LASSERT(coffset < stats->ls_num); \
1559 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1562 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1564 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1565 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1566 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1567 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1568 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1569 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1570 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1571 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1572 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1573 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1574 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1575 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1576 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1577 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1578 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1579 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1580 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1581 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1582 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1583 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1584 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1585 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1586 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1587 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1588 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1589 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1590 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1591 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1592 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1593 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1594 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1595 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1596 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1597 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1598 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1599 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1600 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1601 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1602 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1603 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1604 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1605 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1606 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1607 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
1608 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1609 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1610 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1611 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1612 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1613 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1614 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1615 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1616 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1617 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1618 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1619 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1620 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1621 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1622 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1623 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1624 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1625 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1626 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1627 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1628 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1629 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1630 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1632 EXPORT_SYMBOL(lprocfs_init_ops_stats);
1634 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1636 struct lprocfs_stats *stats;
1637 unsigned int num_stats;
1640 LASSERT(obd->obd_stats == NULL);
1641 LASSERT(obd->obd_proc_entry != NULL);
1642 LASSERT(obd->obd_cntr_base == 0);
1644 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1645 num_private_stats - 1 /* o_owner */;
1646 stats = lprocfs_alloc_stats(num_stats, 0);
1650 lprocfs_init_ops_stats(num_private_stats, stats);
1652 for (i = num_private_stats; i < num_stats; i++) {
1653 /* If this LBUGs, it is likely that an obd
1654 * operation was added to struct obd_ops in
1655 * <obd.h>, and that the corresponding line item
1656 * LPROCFS_OBD_OP_INIT(.., .., opname)
1657 * is missing from the list above. */
1658 LASSERTF(stats->ls_cnt_header[i].lc_name != NULL,
1659 "Missing obd_stat initializer obd_op "
1660 "operation at offset %d.\n", i - num_private_stats);
1662 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1664 lprocfs_free_stats(&stats);
1666 obd->obd_stats = stats;
1667 obd->obd_cntr_base = num_private_stats;
1671 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
1673 void lprocfs_free_obd_stats(struct obd_device *obd)
1676 lprocfs_free_stats(&obd->obd_stats);
1678 EXPORT_SYMBOL(lprocfs_free_obd_stats);
1680 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1682 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1683 LASSERT(coffset < stats->ls_num); \
1684 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1687 void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats)
1689 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1690 LPROCFS_MD_OP_INIT(num_private_stats, stats, null_inode);
1691 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
1692 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1693 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1694 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1695 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1696 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1697 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1698 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1699 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1700 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1701 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1702 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1703 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1704 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1705 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1706 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1707 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1708 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1709 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1710 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1711 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1712 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1713 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1714 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1715 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1716 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1717 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1718 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1719 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1720 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1722 EXPORT_SYMBOL(lprocfs_init_mps_stats);
1724 int lprocfs_alloc_md_stats(struct obd_device *obd,
1725 unsigned num_private_stats)
1727 struct lprocfs_stats *stats;
1728 unsigned int num_stats;
1731 LASSERT(obd->md_stats == NULL);
1732 LASSERT(obd->obd_proc_entry != NULL);
1733 LASSERT(obd->md_cntr_base == 0);
1735 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1737 stats = lprocfs_alloc_stats(num_stats, 0);
1741 lprocfs_init_mps_stats(num_private_stats, stats);
1743 for (i = num_private_stats; i < num_stats; i++) {
1744 if (stats->ls_cnt_header[i].lc_name == NULL) {
1745 CERROR("Missing md_stat initializer md_op "
1746 "operation at offset %d. Aborting.\n",
1747 i - num_private_stats);
1751 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1753 lprocfs_free_stats(&stats);
1755 obd->md_stats = stats;
1756 obd->md_cntr_base = num_private_stats;
1760 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
1762 void lprocfs_free_md_stats(struct obd_device *obd)
1764 struct lprocfs_stats *stats = obd->md_stats;
1766 if (stats != NULL) {
1767 obd->md_stats = NULL;
1768 obd->md_cntr_base = 0;
1769 lprocfs_free_stats(&stats);
1772 EXPORT_SYMBOL(lprocfs_free_md_stats);
1774 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1776 lprocfs_counter_init(ldlm_stats,
1777 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1778 0, "ldlm_enqueue", "reqs");
1779 lprocfs_counter_init(ldlm_stats,
1780 LDLM_CONVERT - LDLM_FIRST_OPC,
1781 0, "ldlm_convert", "reqs");
1782 lprocfs_counter_init(ldlm_stats,
1783 LDLM_CANCEL - LDLM_FIRST_OPC,
1784 0, "ldlm_cancel", "reqs");
1785 lprocfs_counter_init(ldlm_stats,
1786 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1787 0, "ldlm_bl_callback", "reqs");
1788 lprocfs_counter_init(ldlm_stats,
1789 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1790 0, "ldlm_cp_callback", "reqs");
1791 lprocfs_counter_init(ldlm_stats,
1792 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1793 0, "ldlm_gl_callback", "reqs");
1795 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
1797 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1798 int *eof, void *data)
1800 struct obd_export *exp = data;
1801 LASSERT(exp != NULL);
1803 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1806 struct exp_uuid_cb_data {
1814 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1815 int count, int *eof, int *len)
1817 cb_data->page = page;
1818 cb_data->count = count;
1823 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1824 cfs_hlist_node_t *hnode, void *cb_data)
1827 struct obd_export *exp = cfs_hash_object(hs, hnode);
1828 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1830 if (exp->exp_nid_stats)
1831 *data->len += snprintf((data->page + *data->len),
1832 data->count, "%s\n",
1833 obd_uuid2str(&exp->exp_client_uuid));
1837 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1838 int *eof, void *data)
1840 struct nid_stat *stats = (struct nid_stat *)data;
1841 struct exp_uuid_cb_data cb_data;
1842 struct obd_device *obd = stats->nid_obd;
1847 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1848 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1849 lprocfs_exp_print_uuid, &cb_data);
1850 return (*cb_data.len);
1853 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1854 cfs_hlist_node_t *hnode, void *cb_data)
1857 struct exp_uuid_cb_data *data = cb_data;
1858 struct obd_export *exp = cfs_hash_object(hs, hnode);
1860 if (exp->exp_lock_hash != NULL) {
1862 *data->len += cfs_hash_debug_header(data->page,
1865 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1872 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1873 int *eof, void *data)
1875 struct nid_stat *stats = (struct nid_stat *)data;
1876 struct exp_uuid_cb_data cb_data;
1877 struct obd_device *obd = stats->nid_obd;
1882 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1884 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1885 lprocfs_exp_print_hash, &cb_data);
1886 return (*cb_data.len);
1889 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1890 int count, int *eof, void *data)
1893 return snprintf(page, count, "%s\n",
1894 "Write into this file to clear all nid stats and "
1895 "stale nid entries");
1897 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1899 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1901 struct nid_stat *stat = obj;
1904 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
1905 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 1) {
1906 /* object has only hash references. */
1907 spin_lock(&stat->nid_obd->obd_nid_lock);
1908 cfs_list_move(&stat->nid_list, data);
1909 spin_unlock(&stat->nid_obd->obd_nid_lock);
1912 /* we has reference to object - only clear data*/
1913 if (stat->nid_stats)
1914 lprocfs_clear_stats(stat->nid_stats);
1919 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1920 unsigned long count, void *data)
1922 struct obd_device *obd = (struct obd_device *)data;
1923 struct nid_stat *client_stat;
1924 CFS_LIST_HEAD(free_list);
1926 cfs_hash_cond_del(obd->obd_nid_stats_hash,
1927 lprocfs_nid_stats_clear_write_cb, &free_list);
1929 while (!cfs_list_empty(&free_list)) {
1930 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
1932 cfs_list_del_init(&client_stat->nid_list);
1933 lprocfs_free_client_stats(client_stat);
1938 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1940 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1942 struct nid_stat *new_stat, *old_stat;
1943 struct obd_device *obd = NULL;
1944 cfs_proc_dir_entry_t *entry;
1945 char *buffer = NULL;
1951 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1952 !exp->exp_obd->obd_nid_stats_hash)
1955 /* not test against zero because eric say:
1956 * You may only test nid against another nid, or LNET_NID_ANY.
1957 * Anything else is nonsense.*/
1958 if (!nid || *nid == LNET_NID_ANY)
1963 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
1965 OBD_ALLOC_PTR(new_stat);
1966 if (new_stat == NULL)
1969 new_stat->nid = *nid;
1970 new_stat->nid_obd = exp->exp_obd;
1971 /* we need set default refcount to 1 to balance obd_disconnect */
1972 cfs_atomic_set(&new_stat->nid_exp_ref_count, 1);
1974 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
1975 nid, &new_stat->nid_hash);
1976 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
1977 old_stat, libcfs_nid2str(*nid),
1978 cfs_atomic_read(&new_stat->nid_exp_ref_count));
1980 /* We need to release old stats because lprocfs_exp_cleanup() hasn't
1981 * been and will never be called. */
1982 if (exp->exp_nid_stats) {
1983 nidstat_putref(exp->exp_nid_stats);
1984 exp->exp_nid_stats = NULL;
1987 /* Return -EALREADY here so that we know that the /proc
1988 * entry already has been created */
1989 if (old_stat != new_stat) {
1990 exp->exp_nid_stats = old_stat;
1991 GOTO(destroy_new, rc = -EALREADY);
1993 /* not found - create */
1994 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
1996 GOTO(destroy_new, rc = -ENOMEM);
1998 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
1999 new_stat->nid_proc = lprocfs_register(buffer,
2000 obd->obd_proc_exports_entry,
2002 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
2004 if (IS_ERR(new_stat->nid_proc)) {
2005 rc = PTR_ERR(new_stat->nid_proc);
2006 new_stat->nid_proc = NULL;
2007 CERROR("%s: cannot create proc entry for export %s: rc = %d\n",
2008 obd->obd_name, libcfs_nid2str(*nid), rc);
2009 GOTO(destroy_new_ns, rc);
2012 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
2013 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
2014 if (IS_ERR(entry)) {
2015 CWARN("Error adding the NID stats file\n");
2016 rc = PTR_ERR(entry);
2017 GOTO(destroy_new_ns, rc);
2020 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
2021 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
2022 if (IS_ERR(entry)) {
2023 CWARN("Error adding the hash file\n");
2024 rc = PTR_ERR(entry);
2025 GOTO(destroy_new_ns, rc);
2028 exp->exp_nid_stats = new_stat;
2030 /* protect competitive add to list, not need locking on destroy */
2031 spin_lock(&obd->obd_nid_lock);
2032 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
2033 spin_unlock(&obd->obd_nid_lock);
2038 if (new_stat->nid_proc != NULL)
2039 lprocfs_remove(&new_stat->nid_proc);
2040 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
2043 nidstat_putref(new_stat);
2044 OBD_FREE_PTR(new_stat);
2047 EXPORT_SYMBOL(lprocfs_exp_setup);
2049 int lprocfs_exp_cleanup(struct obd_export *exp)
2051 struct nid_stat *stat = exp->exp_nid_stats;
2053 if(!stat || !exp->exp_obd)
2056 nidstat_putref(exp->exp_nid_stats);
2057 exp->exp_nid_stats = NULL;
2061 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2063 int lprocfs_write_helper(const char *buffer, unsigned long count,
2066 return lprocfs_write_frac_helper(buffer, count, val, 1);
2068 EXPORT_SYMBOL(lprocfs_write_helper);
2070 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
2073 char kernbuf[20], *end, *pbuf;
2075 if (count > (sizeof(kernbuf) - 1))
2078 if (copy_from_user(kernbuf, buffer, count))
2081 kernbuf[count] = '\0';
2088 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2092 if (end != NULL && *end == '.') {
2093 int temp_val, pow = 1;
2097 if (strlen(pbuf) > 5)
2098 pbuf[5] = '\0'; /*only allow 5bits fractional*/
2100 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2103 for (i = 0; i < (end - pbuf); i++)
2106 *val += temp_val / pow;
2111 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2113 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
2116 long decimal_val, frac_val;
2122 decimal_val = val / mult;
2123 prtn = snprintf(buffer, count, "%ld", decimal_val);
2124 frac_val = val % mult;
2126 if (prtn < (count - 4) && frac_val > 0) {
2128 int i, temp_mult = 1, frac_bits = 0;
2130 temp_frac = frac_val * 10;
2131 buffer[prtn++] = '.';
2132 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
2133 /* only reserved 2 bits fraction */
2134 buffer[prtn++] ='0';
2139 * Need to think these cases :
2140 * 1. #echo x.00 > /proc/xxx output result : x
2141 * 2. #echo x.0x > /proc/xxx output result : x.0x
2142 * 3. #echo x.x0 > /proc/xxx output result : x.x
2143 * 4. #echo x.xx > /proc/xxx output result : x.xx
2144 * Only reserved 2 bits fraction.
2146 for (i = 0; i < (5 - prtn); i++)
2149 frac_bits = min((int)count - prtn, 3 - frac_bits);
2150 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
2151 frac_val * temp_mult / mult);
2154 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
2156 if (buffer[prtn] == '.') {
2163 buffer[prtn++] ='\n';
2166 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2168 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
2170 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
2172 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2174 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
2175 __u64 *val, int mult)
2177 char kernbuf[22], *end, *pbuf;
2178 __u64 whole, frac = 0, units;
2179 unsigned frac_d = 1;
2181 if (count > (sizeof(kernbuf) - 1))
2184 if (copy_from_user(kernbuf, buffer, count))
2187 kernbuf[count] = '\0';
2194 whole = simple_strtoull(pbuf, &end, 10);
2198 if (end != NULL && *end == '.') {
2202 /* need to limit frac_d to a __u32 */
2203 if (strlen(pbuf) > 10)
2206 frac = simple_strtoull(pbuf, &end, 10);
2207 /* count decimal places */
2208 for (i = 0; i < (end - pbuf); i++)
2225 /* Specified units override the multiplier */
2227 mult = mult < 0 ? -units : units;
2230 do_div(frac, frac_d);
2231 *val = whole * mult + frac;
2234 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2236 static char *lprocfs_strnstr(const char *s1, const char *s2, size_t len)
2245 if (!memcmp(s1, s2, l2))
2253 * Find the string \a name in the input \a buffer, and return a pointer to the
2254 * value immediately following \a name, reducing \a count appropriately.
2255 * If \a name is not found the original \a buffer is returned.
2257 char *lprocfs_find_named_value(const char *buffer, const char *name,
2258 unsigned long *count)
2261 size_t buflen = *count;
2263 /* there is no strnstr() in rhel5 and ubuntu kernels */
2264 val = lprocfs_strnstr(buffer, name, buflen);
2266 return (char *)buffer;
2268 val += strlen(name); /* skip prefix */
2269 while (val < buffer + buflen && isspace(*val)) /* skip separator */
2273 while (val < buffer + buflen && isalnum(*val)) {
2278 return val - *count;
2280 EXPORT_SYMBOL(lprocfs_find_named_value);
2282 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent,
2285 const struct file_operations *seq_fops,
2288 struct proc_dir_entry *entry;
2291 /* Disallow secretly (un)writable entries. */
2292 LASSERT((seq_fops->write == NULL) == ((mode & 0222) == 0));
2294 LPROCFS_WRITE_ENTRY();
2295 entry = create_proc_entry(name, mode, parent);
2297 entry->proc_fops = seq_fops;
2300 LPROCFS_WRITE_EXIT();
2307 EXPORT_SYMBOL(lprocfs_seq_create);
2309 int lprocfs_obd_seq_create(struct obd_device *dev,
2312 const struct file_operations *seq_fops,
2315 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2316 mode, seq_fops, data));
2318 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2320 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2322 if (value >= OBD_HIST_MAX)
2323 value = OBD_HIST_MAX - 1;
2325 spin_lock(&oh->oh_lock);
2326 oh->oh_buckets[value]++;
2327 spin_unlock(&oh->oh_lock);
2329 EXPORT_SYMBOL(lprocfs_oh_tally);
2331 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2335 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2338 lprocfs_oh_tally(oh, val);
2340 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2342 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2344 unsigned long ret = 0;
2347 for (i = 0; i < OBD_HIST_MAX; i++)
2348 ret += oh->oh_buckets[i];
2351 EXPORT_SYMBOL(lprocfs_oh_sum);
2353 void lprocfs_oh_clear(struct obd_histogram *oh)
2355 spin_lock(&oh->oh_lock);
2356 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2357 spin_unlock(&oh->oh_lock);
2359 EXPORT_SYMBOL(lprocfs_oh_clear);
2361 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2362 int count, int *eof, void *data)
2364 struct obd_device *obd = data;
2370 c += cfs_hash_debug_header(page, count);
2371 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2372 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2373 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2377 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2379 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2380 int count, int *eof, void *data)
2382 struct obd_device *obd = data;
2385 LASSERT(obd != NULL);
2386 LASSERT(count >= 0);
2388 /* Set start of user data returned to
2389 page + off since the user may have
2390 requested to read much smaller than
2391 what we need to read */
2392 *start = page + off;
2395 * We know we are allocated a page here.
2396 * Also we know that this function will
2397 * not need to write more than a page
2398 * so we can truncate at PAGE_CACHE_SIZE.
2400 size = min(count + (int)off + 1, (int)PAGE_CACHE_SIZE);
2402 /* Initialize the page */
2403 memset(page, 0, size);
2405 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2407 if (obd->obd_max_recoverable_clients == 0) {
2408 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2414 /* sampled unlocked, but really... */
2415 if (obd->obd_recovering == 0) {
2416 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2418 if (lprocfs_obd_snprintf(&page, size, &len,
2419 "recovery_start: %lu\n",
2420 obd->obd_recovery_start) <= 0)
2422 if (lprocfs_obd_snprintf(&page, size, &len,
2423 "recovery_duration: %lu\n",
2424 obd->obd_recovery_end -
2425 obd->obd_recovery_start) <= 0)
2427 /* Number of clients that have completed recovery */
2428 if (lprocfs_obd_snprintf(&page, size, &len,
2429 "completed_clients: %d/%d\n",
2430 obd->obd_max_recoverable_clients -
2431 obd->obd_stale_clients,
2432 obd->obd_max_recoverable_clients) <= 0)
2434 if (lprocfs_obd_snprintf(&page, size, &len,
2435 "replayed_requests: %d\n",
2436 obd->obd_replayed_requests) <= 0)
2438 if (lprocfs_obd_snprintf(&page, size, &len,
2439 "last_transno: "LPD64"\n",
2440 obd->obd_next_recovery_transno - 1)<=0)
2442 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2443 obd->obd_version_recov ?
2444 "ENABLED" : "DISABLED") <=0)
2446 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
2448 "DISABLED" : "ENABLED") <= 0)
2453 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2455 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2456 obd->obd_recovery_start) <= 0)
2458 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2459 cfs_time_current_sec() >=
2460 obd->obd_recovery_start +
2461 obd->obd_recovery_timeout ? 0 :
2462 obd->obd_recovery_start +
2463 obd->obd_recovery_timeout -
2464 cfs_time_current_sec()) <= 0)
2466 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2467 cfs_atomic_read(&obd->obd_connected_clients),
2468 obd->obd_max_recoverable_clients) <= 0)
2470 /* Number of clients that have completed recovery */
2471 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2472 cfs_atomic_read(&obd->obd_req_replay_clients))
2475 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2476 cfs_atomic_read(&obd->obd_lock_replay_clients))
2479 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2480 cfs_atomic_read(&obd->obd_connected_clients) -
2481 cfs_atomic_read(&obd->obd_lock_replay_clients))
2484 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2485 obd->obd_stale_clients) <= 0)
2487 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2488 obd->obd_replayed_requests) <= 0)
2490 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2491 obd->obd_requests_queued_for_recovery) <= 0)
2494 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2495 obd->obd_next_recovery_transno) <= 0)
2501 return min(count, len - (int)off);
2503 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2505 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
2506 int count, int *eof, void *data)
2508 struct obd_device *obd = (struct obd_device *)data;
2509 LASSERT(obd != NULL);
2511 return snprintf(page, count, "%d\n",
2512 obd->obd_recovery_ir_factor);
2514 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
2516 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
2517 unsigned long count, void *data)
2519 struct obd_device *obd = (struct obd_device *)data;
2521 LASSERT(obd != NULL);
2523 rc = lprocfs_write_helper(buffer, count, &val);
2527 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
2530 obd->obd_recovery_ir_factor = val;
2533 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
2535 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
2536 int count, int *eof, void *data)
2538 struct obd_device *obd = (struct obd_device *)data;
2539 LASSERT(obd != NULL);
2541 return snprintf(page, count, "%d\n",
2542 obd->obd_recovery_timeout);
2544 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
2546 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
2547 unsigned long count, void *data)
2549 struct obd_device *obd = (struct obd_device *)data;
2551 LASSERT(obd != NULL);
2553 rc = lprocfs_write_helper(buffer, count, &val);
2557 obd->obd_recovery_timeout = val;
2560 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
2562 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
2563 int count, int *eof, void *data)
2565 struct obd_device *obd = data;
2566 LASSERT(obd != NULL);
2568 return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
2570 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
2572 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
2573 unsigned long count, void *data)
2575 struct obd_device *obd = data;
2577 LASSERT(obd != NULL);
2579 rc = lprocfs_write_helper(buffer, count, &val);
2583 obd->obd_recovery_time_hard = val;
2586 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
2588 int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
2589 int count, int *eof, void *data)
2591 struct obd_device *dev = data;
2592 struct client_obd *cli = &dev->u.cli;
2595 client_obd_list_lock(&cli->cl_loi_list_lock);
2596 rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
2597 client_obd_list_unlock(&cli->cl_loi_list_lock);
2600 EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
2602 #ifdef HAVE_SERVER_SUPPORT
2603 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
2604 int count, int *eof, void *data)
2606 struct obd_device *obd = (struct obd_device *)data;
2607 struct obd_device_target *target = &obd->u.obt;
2609 LASSERT(obd != NULL);
2610 LASSERT(target->obt_magic == OBT_MAGIC);
2612 return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
2614 EXPORT_SYMBOL(lprocfs_target_rd_instance);