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;
775 struct lprocfs_counter_header *cntr_header;
777 unsigned long flags = 0;
779 memset(cnt, 0, sizeof(*cnt));
782 /* set count to 1 to avoid divide-by-zero errs in callers */
787 cnt->lc_min = LC_MIN_INIT;
789 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
791 for (i = 0; i < num_entry; i++) {
792 if (stats->ls_percpu[i] == NULL)
794 cntr_header = &stats->ls_cnt_header[idx];
795 percpu_cntr = lprocfs_stats_counter_get(stats, i, idx);
797 cnt->lc_count += percpu_cntr->lc_count;
798 cnt->lc_sum += percpu_cntr->lc_sum;
799 if (percpu_cntr->lc_min < cnt->lc_min)
800 cnt->lc_min = percpu_cntr->lc_min;
801 if (percpu_cntr->lc_max > cnt->lc_max)
802 cnt->lc_max = percpu_cntr->lc_max;
803 cnt->lc_sumsquare += percpu_cntr->lc_sumsquare;
806 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
808 EXPORT_SYMBOL(lprocfs_stats_collect);
811 * Append a space separated list of current set flags to str.
813 #define flag2str(flag) \
814 if (imp->imp_##flag && max - len > 0) \
815 len += snprintf(str + len, max - len, "%s" #flag, len ? ", " : "");
816 static int obd_import_flags2str(struct obd_import *imp, char *str, int max)
820 if (imp->imp_obd->obd_no_recov)
821 len += snprintf(str, max - len, "no_recov");
825 flag2str(replayable);
831 static const char *obd_connect_names[] = {
845 "join_file(obsolete)",
849 "remote_client_by_force",
858 "mds_mds_connection",
861 "alt_checksum_algorithm",
887 int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
892 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
894 ret += snprintf(page + ret, count - ret, "%s%s",
895 ret ? sep : "", obd_connect_names[i]);
897 if (flags & ~(mask - 1))
898 ret += snprintf(page + ret, count - ret,
899 "%sunknown flags "LPX64,
900 ret ? sep : "", flags & ~(mask - 1));
903 EXPORT_SYMBOL(obd_connect_flags2str);
905 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
906 int *eof, void *data)
908 struct lprocfs_counter ret;
909 struct lprocfs_counter_header *header;
910 struct obd_device *obd = (struct obd_device *)data;
911 struct obd_import *imp;
912 struct obd_import_conn *conn;
918 LASSERT(obd != NULL);
919 LPROCFS_CLIMP_CHECK(obd);
920 imp = obd->u.cli.cl_import;
923 i = snprintf(page, count,
932 ptlrpc_import_state_name(imp->imp_state),
933 imp->imp_connect_data.ocd_instance);
934 i += obd_connect_flags2str(page + i, count - i,
935 imp->imp_connect_data.ocd_connect_flags,
937 i += snprintf(page + i, count - i,
940 i += obd_import_flags2str(imp, page + i, count - i);
942 i += snprintf(page + i, count - i,
945 " failover_nids: [");
946 spin_lock(&imp->imp_lock);
948 cfs_list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
949 i += snprintf(page + i, count - i, "%s%s", j ? ", " : "",
950 libcfs_nid2str(conn->oic_conn->c_peer.nid));
953 i += snprintf(page + i, count - i,
955 " current_connection: %s\n"
956 " connection_attempts: %u\n"
958 " in-progress_invalidations: %u\n",
959 imp->imp_connection == NULL ? "<none>" :
960 libcfs_nid2str(imp->imp_connection->c_peer.nid),
963 cfs_atomic_read(&imp->imp_inval_count));
964 spin_unlock(&imp->imp_lock);
966 if (obd->obd_svc_stats == NULL)
969 header = &obd->obd_svc_stats->ls_cnt_header[PTLRPC_REQWAIT_CNTR];
970 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
971 if (ret.lc_count != 0) {
972 /* first argument to do_div MUST be __u64 */
973 __u64 sum = ret.lc_sum;
974 do_div(sum, ret.lc_count);
978 i += snprintf(page + i, count - i,
981 " unregistering: %u\n"
983 " avg_waittime: "LPU64" %s\n",
984 cfs_atomic_read(&imp->imp_inflight),
985 cfs_atomic_read(&imp->imp_unregistering),
986 cfs_atomic_read(&imp->imp_timeouts),
987 ret.lc_sum, header->lc_units);
990 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
991 if (imp->imp_at.iat_portal[j] == 0)
993 k = max_t(unsigned int, k,
994 at_get(&imp->imp_at.iat_service_estimate[j]));
996 i += snprintf(page + i, count - i,
997 " service_estimates:\n"
998 " services: %u sec\n"
999 " network: %u sec\n",
1001 at_get(&imp->imp_at.iat_net_latency));
1003 i += snprintf(page + i, count - i,
1005 " last_replay: "LPU64"\n"
1006 " peer_committed: "LPU64"\n"
1007 " last_checked: "LPU64"\n",
1008 imp->imp_last_replay_transno,
1009 imp->imp_peer_committed_transno,
1010 imp->imp_last_transno_checked);
1012 /* avg data rates */
1013 for (rw = 0; rw <= 1; rw++) {
1014 lprocfs_stats_collect(obd->obd_svc_stats,
1015 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
1017 if (ret.lc_sum > 0 && ret.lc_count > 0) {
1018 /* first argument to do_div MUST be __u64 */
1019 __u64 sum = ret.lc_sum;
1020 do_div(sum, ret.lc_count);
1022 i += snprintf(page + i, count - i,
1023 " %s_data_averages:\n"
1024 " bytes_per_rpc: "LPU64"\n",
1025 rw ? "write" : "read",
1028 k = (int)ret.lc_sum;
1029 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
1030 header = &obd->obd_svc_stats->ls_cnt_header[j];
1031 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
1032 if (ret.lc_sum > 0 && ret.lc_count != 0) {
1033 /* first argument to do_div MUST be __u64 */
1034 __u64 sum = ret.lc_sum;
1035 do_div(sum, ret.lc_count);
1037 i += snprintf(page + i, count - i,
1038 " %s_per_rpc: "LPU64"\n",
1039 header->lc_units, ret.lc_sum);
1040 j = (int)ret.lc_sum;
1042 i += snprintf(page + i, count - i,
1043 " MB_per_sec: %u.%.02u\n",
1044 k / j, (100 * k / j) % 100);
1049 LPROCFS_CLIMP_EXIT(obd);
1052 EXPORT_SYMBOL(lprocfs_rd_import);
1054 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
1055 int *eof, void *data)
1057 struct obd_device *obd = (struct obd_device *)data;
1058 struct obd_import *imp;
1061 LASSERT(obd != NULL);
1062 LPROCFS_CLIMP_CHECK(obd);
1063 imp = obd->u.cli.cl_import;
1066 i = snprintf(page, count, "current_state: %s\n",
1067 ptlrpc_import_state_name(imp->imp_state));
1068 i += snprintf(page + i, count - i,
1069 "state_history:\n");
1070 k = imp->imp_state_hist_idx;
1071 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
1072 struct import_state_hist *ish =
1073 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
1074 if (ish->ish_state == 0)
1076 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
1078 ptlrpc_import_state_name(ish->ish_state));
1081 LPROCFS_CLIMP_EXIT(obd);
1084 EXPORT_SYMBOL(lprocfs_rd_state);
1086 int lprocfs_at_hist_helper(char *page, int count, int rc,
1087 struct adaptive_timeout *at)
1090 for (i = 0; i < AT_BINS; i++)
1091 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
1092 rc += snprintf(page + rc, count - rc, "\n");
1095 EXPORT_SYMBOL(lprocfs_at_hist_helper);
1097 /* See also ptlrpc_lprocfs_rd_timeouts */
1098 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
1099 int *eof, void *data)
1101 struct obd_device *obd = (struct obd_device *)data;
1102 struct obd_import *imp;
1103 unsigned int cur, worst;
1108 LASSERT(obd != NULL);
1109 LPROCFS_CLIMP_CHECK(obd);
1110 imp = obd->u.cli.cl_import;
1113 now = cfs_time_current_sec();
1115 /* Some network health info for kicks */
1116 s2dhms(&ts, now - imp->imp_last_reply_time);
1117 rc += snprintf(page + rc, count - rc,
1118 "%-10s : %ld, "DHMS_FMT" ago\n",
1119 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
1121 cur = at_get(&imp->imp_at.iat_net_latency);
1122 worst = imp->imp_at.iat_net_latency.at_worst_ever;
1123 worstt = imp->imp_at.iat_net_latency.at_worst_time;
1124 s2dhms(&ts, now - worstt);
1125 rc += snprintf(page + rc, count - rc,
1126 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
1127 "network", cur, worst, worstt, DHMS_VARS(&ts));
1128 rc = lprocfs_at_hist_helper(page, count, rc,
1129 &imp->imp_at.iat_net_latency);
1131 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
1132 if (imp->imp_at.iat_portal[i] == 0)
1134 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
1135 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
1136 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
1137 s2dhms(&ts, now - worstt);
1138 rc += snprintf(page + rc, count - rc,
1139 "portal %-2d : cur %3u worst %3u (at %ld, "
1140 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
1141 cur, worst, worstt, DHMS_VARS(&ts));
1142 rc = lprocfs_at_hist_helper(page, count, rc,
1143 &imp->imp_at.iat_service_estimate[i]);
1146 LPROCFS_CLIMP_EXIT(obd);
1149 EXPORT_SYMBOL(lprocfs_rd_timeouts);
1151 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1152 int count, int *eof, void *data)
1154 struct obd_device *obd = data;
1158 LPROCFS_CLIMP_CHECK(obd);
1159 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1160 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1161 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1162 ret += snprintf(page + ret, count - ret, "\n");
1163 LPROCFS_CLIMP_EXIT(obd);
1166 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1168 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1169 int *eof, void *data)
1171 struct obd_device *obd = data;
1173 LASSERT(obd != NULL);
1175 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1177 EXPORT_SYMBOL(lprocfs_rd_num_exports);
1179 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1180 int *eof, void *data)
1182 struct obd_type *class = (struct obd_type*) data;
1184 LASSERT(class != NULL);
1186 return snprintf(page, count, "%d\n", class->typ_refcnt);
1188 EXPORT_SYMBOL(lprocfs_rd_numrefs);
1190 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1194 LASSERT(obd != NULL);
1195 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1196 LASSERT(obd->obd_type->typ_procroot != NULL);
1198 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1199 obd->obd_type->typ_procroot,
1201 if (IS_ERR(obd->obd_proc_entry)) {
1202 rc = PTR_ERR(obd->obd_proc_entry);
1203 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1204 obd->obd_proc_entry = NULL;
1208 EXPORT_SYMBOL(lprocfs_obd_setup);
1210 int lprocfs_obd_cleanup(struct obd_device *obd)
1214 if (obd->obd_proc_exports_entry) {
1215 /* Should be no exports left */
1216 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1217 lprocfs_remove(&obd->obd_proc_exports_entry);
1218 obd->obd_proc_exports_entry = NULL;
1220 if (obd->obd_proc_entry) {
1221 lprocfs_remove(&obd->obd_proc_entry);
1222 obd->obd_proc_entry = NULL;
1226 EXPORT_SYMBOL(lprocfs_obd_cleanup);
1228 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1230 CDEBUG(D_CONFIG, "stat %p - data %p/%p\n", client_stat,
1231 client_stat->nid_proc, client_stat->nid_stats);
1233 LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
1234 "nid %s:count %d\n", libcfs_nid2str(client_stat->nid),
1235 atomic_read(&client_stat->nid_exp_ref_count));
1237 if (client_stat->nid_proc)
1238 lprocfs_remove(&client_stat->nid_proc);
1240 if (client_stat->nid_stats)
1241 lprocfs_free_stats(&client_stat->nid_stats);
1243 if (client_stat->nid_ldlm_stats)
1244 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1246 OBD_FREE_PTR(client_stat);
1251 void lprocfs_free_per_client_stats(struct obd_device *obd)
1253 cfs_hash_t *hash = obd->obd_nid_stats_hash;
1254 struct nid_stat *stat;
1257 /* we need extra list - because hash_exit called to early */
1258 /* not need locking because all clients is died */
1259 while (!cfs_list_empty(&obd->obd_nid_stats)) {
1260 stat = cfs_list_entry(obd->obd_nid_stats.next,
1261 struct nid_stat, nid_list);
1262 cfs_list_del_init(&stat->nid_list);
1263 cfs_hash_del(hash, &stat->nid, &stat->nid_hash);
1264 lprocfs_free_client_stats(stat);
1268 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
1270 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1271 enum lprocfs_stats_flags flags)
1273 struct lprocfs_stats *stats;
1274 unsigned int num_entry;
1275 unsigned int percpusize = 0;
1281 if (lprocfs_no_percpu_stats != 0)
1282 flags |= LPROCFS_STATS_FLAG_NOPERCPU;
1284 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1287 num_entry = cfs_num_possible_cpus();
1289 /* alloc percpu pointers for all possible cpu slots */
1290 LIBCFS_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1294 stats->ls_num = num;
1295 stats->ls_flags = flags;
1296 spin_lock_init(&stats->ls_lock);
1298 /* alloc num of counter headers */
1299 LIBCFS_ALLOC(stats->ls_cnt_header,
1300 stats->ls_num * sizeof(struct lprocfs_counter_header));
1301 if (stats->ls_cnt_header == NULL)
1304 if ((flags & LPROCFS_STATS_FLAG_NOPERCPU) != 0) {
1305 /* contains only one set counters */
1306 percpusize = lprocfs_stats_counter_size(stats);
1307 LIBCFS_ALLOC_ATOMIC(stats->ls_percpu[0], percpusize);
1308 if (stats->ls_percpu[0] == NULL)
1310 stats->ls_biggest_alloc_num = 1;
1311 } else if ((flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0) {
1312 /* alloc all percpu data, currently only obd_memory use this */
1313 for (i = 0; i < num_entry; ++i)
1314 if (lprocfs_stats_alloc_one(stats, i) < 0)
1321 lprocfs_free_stats(&stats);
1324 EXPORT_SYMBOL(lprocfs_alloc_stats);
1326 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1328 struct lprocfs_stats *stats = *statsh;
1329 unsigned int num_entry;
1330 unsigned int percpusize;
1333 if (stats == NULL || stats->ls_num == 0)
1337 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1340 num_entry = cfs_num_possible_cpus();
1342 percpusize = lprocfs_stats_counter_size(stats);
1343 for (i = 0; i < num_entry; i++)
1344 if (stats->ls_percpu[i] != NULL)
1345 LIBCFS_FREE(stats->ls_percpu[i], percpusize);
1346 if (stats->ls_cnt_header != NULL)
1347 LIBCFS_FREE(stats->ls_cnt_header, stats->ls_num *
1348 sizeof(struct lprocfs_counter_header));
1349 LIBCFS_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1351 EXPORT_SYMBOL(lprocfs_free_stats);
1353 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1355 struct lprocfs_counter *percpu_cntr;
1356 struct lprocfs_counter_header *header;
1359 unsigned int num_entry;
1360 unsigned long flags = 0;
1362 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1364 for (i = 0; i < num_entry; i++) {
1365 if (stats->ls_percpu[i] == NULL)
1367 for (j = 0; j < stats->ls_num; j++) {
1368 header = &stats->ls_cnt_header[j];
1369 percpu_cntr = lprocfs_stats_counter_get(stats, i, j);
1370 percpu_cntr->lc_count = 0;
1371 percpu_cntr->lc_min = LC_MIN_INIT;
1372 percpu_cntr->lc_max = 0;
1373 percpu_cntr->lc_sumsquare = 0;
1374 percpu_cntr->lc_sum = 0;
1375 if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
1376 percpu_cntr->lc_sum_irq = 0;
1380 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1382 EXPORT_SYMBOL(lprocfs_clear_stats);
1384 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1385 size_t len, loff_t *off)
1387 struct seq_file *seq = file->private_data;
1388 struct lprocfs_stats *stats = seq->private;
1390 lprocfs_clear_stats(stats);
1395 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1397 struct lprocfs_stats *stats = p->private;
1399 return (*pos < stats->ls_num) ? pos : NULL;
1402 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1406 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1410 return lprocfs_stats_seq_start(p, pos);
1413 /* seq file export of one lprocfs counter */
1414 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1416 struct lprocfs_stats *stats = p->private;
1417 struct lprocfs_counter_header *hdr;
1418 struct lprocfs_counter ctr;
1419 int idx = *(loff_t *)v;
1425 cfs_gettimeofday(&now);
1426 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1427 "snapshot_time", now.tv_sec, now.tv_usec);
1432 hdr = &stats->ls_cnt_header[idx];
1433 lprocfs_stats_collect(stats, idx, &ctr);
1435 if (ctr.lc_count == 0)
1438 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", hdr->lc_name,
1439 ctr.lc_count, hdr->lc_units);
1443 if ((hdr->lc_config & LPROCFS_CNTR_AVGMINMAX) && ctr.lc_count > 0) {
1444 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1445 ctr.lc_min, ctr.lc_max, ctr.lc_sum);
1448 if (hdr->lc_config & LPROCFS_CNTR_STDDEV)
1449 rc = seq_printf(p, " "LPD64, ctr.lc_sumsquare);
1453 rc = seq_printf(p, "\n");
1455 return (rc < 0) ? rc : 0;
1458 struct seq_operations lprocfs_stats_seq_sops = {
1459 .start = lprocfs_stats_seq_start,
1460 .stop = lprocfs_stats_seq_stop,
1461 .next = lprocfs_stats_seq_next,
1462 .show = lprocfs_stats_seq_show,
1465 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1467 struct proc_dir_entry *dp = PDE(inode);
1468 struct seq_file *seq;
1471 if (LPROCFS_ENTRY_CHECK(dp))
1474 rc = seq_open(file, &lprocfs_stats_seq_sops);
1477 seq = file->private_data;
1478 seq->private = dp->data;
1482 struct file_operations lprocfs_stats_seq_fops = {
1483 .owner = THIS_MODULE,
1484 .open = lprocfs_stats_seq_open,
1486 .write = lprocfs_stats_seq_write,
1487 .llseek = seq_lseek,
1488 .release = lprocfs_seq_release,
1491 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1492 struct lprocfs_stats *stats)
1494 struct proc_dir_entry *entry;
1495 LASSERT(root != NULL);
1497 LPROCFS_WRITE_ENTRY();
1498 entry = create_proc_entry(name, 0644, root);
1500 entry->proc_fops = &lprocfs_stats_seq_fops;
1501 entry->data = stats;
1504 LPROCFS_WRITE_EXIT();
1511 EXPORT_SYMBOL(lprocfs_register_stats);
1513 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1514 unsigned conf, const char *name, const char *units)
1516 struct lprocfs_counter_header *header;
1517 struct lprocfs_counter *percpu_cntr;
1518 unsigned long flags = 0;
1520 unsigned int num_cpu;
1522 LASSERT(stats != NULL);
1524 header = &stats->ls_cnt_header[index];
1525 LASSERTF(header != NULL, "Failed to allocate stats header:[%d]%s/%s\n",
1526 index, name, units);
1528 header->lc_config = conf;
1529 header->lc_name = name;
1530 header->lc_units = units;
1532 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1533 for (i = 0; i < num_cpu; ++i) {
1534 if (stats->ls_percpu[i] == NULL)
1536 percpu_cntr = lprocfs_stats_counter_get(stats, i, index);
1537 percpu_cntr->lc_count = 0;
1538 percpu_cntr->lc_min = LC_MIN_INIT;
1539 percpu_cntr->lc_max = 0;
1540 percpu_cntr->lc_sumsquare = 0;
1541 percpu_cntr->lc_sum = 0;
1542 if ((stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
1543 percpu_cntr->lc_sum_irq = 0;
1545 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1547 EXPORT_SYMBOL(lprocfs_counter_init);
1549 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1551 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1552 LASSERT(coffset < stats->ls_num); \
1553 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1556 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1558 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1559 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1560 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1561 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1562 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1563 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1564 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1565 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1566 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1567 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1568 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1569 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1570 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1571 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1572 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1573 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1574 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1575 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1576 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1577 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1578 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1579 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1580 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1581 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1582 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1583 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1584 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1585 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1586 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1587 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1588 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1589 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1590 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1591 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1592 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1593 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1594 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1595 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1596 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1597 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1598 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1599 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1600 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1601 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
1602 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1603 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1604 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1605 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1606 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1607 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1608 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1609 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1610 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1611 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1612 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1613 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1614 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1615 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1616 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1617 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1618 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1619 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1620 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1621 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1622 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1623 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1624 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1626 EXPORT_SYMBOL(lprocfs_init_ops_stats);
1628 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1630 struct lprocfs_stats *stats;
1631 unsigned int num_stats;
1634 LASSERT(obd->obd_stats == NULL);
1635 LASSERT(obd->obd_proc_entry != NULL);
1636 LASSERT(obd->obd_cntr_base == 0);
1638 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1639 num_private_stats - 1 /* o_owner */;
1640 stats = lprocfs_alloc_stats(num_stats, 0);
1644 lprocfs_init_ops_stats(num_private_stats, stats);
1646 for (i = num_private_stats; i < num_stats; i++) {
1647 /* If this LBUGs, it is likely that an obd
1648 * operation was added to struct obd_ops in
1649 * <obd.h>, and that the corresponding line item
1650 * LPROCFS_OBD_OP_INIT(.., .., opname)
1651 * is missing from the list above. */
1652 LASSERTF(stats->ls_cnt_header[i].lc_name != NULL,
1653 "Missing obd_stat initializer obd_op "
1654 "operation at offset %d.\n", i - num_private_stats);
1656 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1658 lprocfs_free_stats(&stats);
1660 obd->obd_stats = stats;
1661 obd->obd_cntr_base = num_private_stats;
1665 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
1667 void lprocfs_free_obd_stats(struct obd_device *obd)
1670 lprocfs_free_stats(&obd->obd_stats);
1672 EXPORT_SYMBOL(lprocfs_free_obd_stats);
1674 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1676 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1677 LASSERT(coffset < stats->ls_num); \
1678 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1681 void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats)
1683 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1684 LPROCFS_MD_OP_INIT(num_private_stats, stats, null_inode);
1685 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
1686 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1687 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1688 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1689 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1690 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1691 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1692 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1693 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1694 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1695 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1696 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1697 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1698 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1699 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1700 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1701 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1702 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1703 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1704 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1705 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1706 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1707 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1708 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1709 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1710 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1711 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1712 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1713 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1714 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1716 EXPORT_SYMBOL(lprocfs_init_mps_stats);
1718 int lprocfs_alloc_md_stats(struct obd_device *obd,
1719 unsigned num_private_stats)
1721 struct lprocfs_stats *stats;
1722 unsigned int num_stats;
1725 LASSERT(obd->md_stats == NULL);
1726 LASSERT(obd->obd_proc_entry != NULL);
1727 LASSERT(obd->md_cntr_base == 0);
1729 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1731 stats = lprocfs_alloc_stats(num_stats, 0);
1735 lprocfs_init_mps_stats(num_private_stats, stats);
1737 for (i = num_private_stats; i < num_stats; i++) {
1738 if (stats->ls_cnt_header[i].lc_name == NULL) {
1739 CERROR("Missing md_stat initializer md_op "
1740 "operation at offset %d. Aborting.\n",
1741 i - num_private_stats);
1745 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1747 lprocfs_free_stats(&stats);
1749 obd->md_stats = stats;
1750 obd->md_cntr_base = num_private_stats;
1754 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
1756 void lprocfs_free_md_stats(struct obd_device *obd)
1758 struct lprocfs_stats *stats = obd->md_stats;
1760 if (stats != NULL) {
1761 obd->md_stats = NULL;
1762 obd->md_cntr_base = 0;
1763 lprocfs_free_stats(&stats);
1766 EXPORT_SYMBOL(lprocfs_free_md_stats);
1768 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1770 lprocfs_counter_init(ldlm_stats,
1771 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1772 0, "ldlm_enqueue", "reqs");
1773 lprocfs_counter_init(ldlm_stats,
1774 LDLM_CONVERT - LDLM_FIRST_OPC,
1775 0, "ldlm_convert", "reqs");
1776 lprocfs_counter_init(ldlm_stats,
1777 LDLM_CANCEL - LDLM_FIRST_OPC,
1778 0, "ldlm_cancel", "reqs");
1779 lprocfs_counter_init(ldlm_stats,
1780 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1781 0, "ldlm_bl_callback", "reqs");
1782 lprocfs_counter_init(ldlm_stats,
1783 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1784 0, "ldlm_cp_callback", "reqs");
1785 lprocfs_counter_init(ldlm_stats,
1786 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1787 0, "ldlm_gl_callback", "reqs");
1789 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
1791 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1792 int *eof, void *data)
1794 struct obd_export *exp = data;
1795 LASSERT(exp != NULL);
1797 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1800 struct exp_uuid_cb_data {
1808 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1809 int count, int *eof, int *len)
1811 cb_data->page = page;
1812 cb_data->count = count;
1817 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1818 cfs_hlist_node_t *hnode, void *cb_data)
1821 struct obd_export *exp = cfs_hash_object(hs, hnode);
1822 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1824 if (exp->exp_nid_stats)
1825 *data->len += snprintf((data->page + *data->len),
1826 data->count, "%s\n",
1827 obd_uuid2str(&exp->exp_client_uuid));
1831 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1832 int *eof, void *data)
1834 struct nid_stat *stats = (struct nid_stat *)data;
1835 struct exp_uuid_cb_data cb_data;
1836 struct obd_device *obd = stats->nid_obd;
1841 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1842 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1843 lprocfs_exp_print_uuid, &cb_data);
1844 return (*cb_data.len);
1847 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1848 cfs_hlist_node_t *hnode, void *cb_data)
1851 struct exp_uuid_cb_data *data = cb_data;
1852 struct obd_export *exp = cfs_hash_object(hs, hnode);
1854 if (exp->exp_lock_hash != NULL) {
1856 *data->len += cfs_hash_debug_header(data->page,
1859 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1866 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1867 int *eof, void *data)
1869 struct nid_stat *stats = (struct nid_stat *)data;
1870 struct exp_uuid_cb_data cb_data;
1871 struct obd_device *obd = stats->nid_obd;
1876 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1878 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1879 lprocfs_exp_print_hash, &cb_data);
1880 return (*cb_data.len);
1883 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1884 int count, int *eof, void *data)
1887 return snprintf(page, count, "%s\n",
1888 "Write into this file to clear all nid stats and "
1889 "stale nid entries");
1891 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1893 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1895 struct nid_stat *stat = obj;
1898 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
1899 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 1) {
1900 /* object has only hash references. */
1901 spin_lock(&stat->nid_obd->obd_nid_lock);
1902 cfs_list_move(&stat->nid_list, data);
1903 spin_unlock(&stat->nid_obd->obd_nid_lock);
1906 /* we has reference to object - only clear data*/
1907 if (stat->nid_stats)
1908 lprocfs_clear_stats(stat->nid_stats);
1913 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1914 unsigned long count, void *data)
1916 struct obd_device *obd = (struct obd_device *)data;
1917 struct nid_stat *client_stat;
1918 CFS_LIST_HEAD(free_list);
1920 cfs_hash_cond_del(obd->obd_nid_stats_hash,
1921 lprocfs_nid_stats_clear_write_cb, &free_list);
1923 while (!cfs_list_empty(&free_list)) {
1924 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
1926 cfs_list_del_init(&client_stat->nid_list);
1927 lprocfs_free_client_stats(client_stat);
1932 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1934 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1936 struct nid_stat *new_stat, *old_stat;
1937 struct obd_device *obd = NULL;
1938 cfs_proc_dir_entry_t *entry;
1939 char *buffer = NULL;
1945 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1946 !exp->exp_obd->obd_nid_stats_hash)
1949 /* not test against zero because eric say:
1950 * You may only test nid against another nid, or LNET_NID_ANY.
1951 * Anything else is nonsense.*/
1952 if (!nid || *nid == LNET_NID_ANY)
1957 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
1959 OBD_ALLOC_PTR(new_stat);
1960 if (new_stat == NULL)
1963 new_stat->nid = *nid;
1964 new_stat->nid_obd = exp->exp_obd;
1965 /* we need set default refcount to 1 to balance obd_disconnect */
1966 cfs_atomic_set(&new_stat->nid_exp_ref_count, 1);
1968 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
1969 nid, &new_stat->nid_hash);
1970 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
1971 old_stat, libcfs_nid2str(*nid),
1972 cfs_atomic_read(&new_stat->nid_exp_ref_count));
1974 /* We need to release old stats because lprocfs_exp_cleanup() hasn't
1975 * been and will never be called. */
1976 if (exp->exp_nid_stats) {
1977 nidstat_putref(exp->exp_nid_stats);
1978 exp->exp_nid_stats = NULL;
1981 /* Return -EALREADY here so that we know that the /proc
1982 * entry already has been created */
1983 if (old_stat != new_stat) {
1984 exp->exp_nid_stats = old_stat;
1985 GOTO(destroy_new, rc = -EALREADY);
1987 /* not found - create */
1988 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
1990 GOTO(destroy_new, rc = -ENOMEM);
1992 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
1993 new_stat->nid_proc = lprocfs_register(buffer,
1994 obd->obd_proc_exports_entry,
1996 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
1998 if (IS_ERR(new_stat->nid_proc)) {
1999 rc = PTR_ERR(new_stat->nid_proc);
2000 new_stat->nid_proc = NULL;
2001 CERROR("%s: cannot create proc entry for export %s: rc = %d\n",
2002 obd->obd_name, libcfs_nid2str(*nid), rc);
2003 GOTO(destroy_new_ns, rc);
2006 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
2007 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
2008 if (IS_ERR(entry)) {
2009 CWARN("Error adding the NID stats file\n");
2010 rc = PTR_ERR(entry);
2011 GOTO(destroy_new_ns, rc);
2014 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
2015 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
2016 if (IS_ERR(entry)) {
2017 CWARN("Error adding the hash file\n");
2018 rc = PTR_ERR(entry);
2019 GOTO(destroy_new_ns, rc);
2022 exp->exp_nid_stats = new_stat;
2024 /* protect competitive add to list, not need locking on destroy */
2025 spin_lock(&obd->obd_nid_lock);
2026 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
2027 spin_unlock(&obd->obd_nid_lock);
2032 if (new_stat->nid_proc != NULL)
2033 lprocfs_remove(&new_stat->nid_proc);
2034 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
2037 nidstat_putref(new_stat);
2038 OBD_FREE_PTR(new_stat);
2041 EXPORT_SYMBOL(lprocfs_exp_setup);
2043 int lprocfs_exp_cleanup(struct obd_export *exp)
2045 struct nid_stat *stat = exp->exp_nid_stats;
2047 if(!stat || !exp->exp_obd)
2050 nidstat_putref(exp->exp_nid_stats);
2051 exp->exp_nid_stats = NULL;
2055 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2057 int lprocfs_write_helper(const char *buffer, unsigned long count,
2060 return lprocfs_write_frac_helper(buffer, count, val, 1);
2062 EXPORT_SYMBOL(lprocfs_write_helper);
2064 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
2067 char kernbuf[20], *end, *pbuf;
2069 if (count > (sizeof(kernbuf) - 1))
2072 if (copy_from_user(kernbuf, buffer, count))
2075 kernbuf[count] = '\0';
2082 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2086 if (end != NULL && *end == '.') {
2087 int temp_val, pow = 1;
2091 if (strlen(pbuf) > 5)
2092 pbuf[5] = '\0'; /*only allow 5bits fractional*/
2094 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2097 for (i = 0; i < (end - pbuf); i++)
2100 *val += temp_val / pow;
2105 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2107 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
2110 long decimal_val, frac_val;
2116 decimal_val = val / mult;
2117 prtn = snprintf(buffer, count, "%ld", decimal_val);
2118 frac_val = val % mult;
2120 if (prtn < (count - 4) && frac_val > 0) {
2122 int i, temp_mult = 1, frac_bits = 0;
2124 temp_frac = frac_val * 10;
2125 buffer[prtn++] = '.';
2126 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
2127 /* only reserved 2 bits fraction */
2128 buffer[prtn++] ='0';
2133 * Need to think these cases :
2134 * 1. #echo x.00 > /proc/xxx output result : x
2135 * 2. #echo x.0x > /proc/xxx output result : x.0x
2136 * 3. #echo x.x0 > /proc/xxx output result : x.x
2137 * 4. #echo x.xx > /proc/xxx output result : x.xx
2138 * Only reserved 2 bits fraction.
2140 for (i = 0; i < (5 - prtn); i++)
2143 frac_bits = min((int)count - prtn, 3 - frac_bits);
2144 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
2145 frac_val * temp_mult / mult);
2148 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
2150 if (buffer[prtn] == '.') {
2157 buffer[prtn++] ='\n';
2160 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2162 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
2164 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
2166 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2168 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
2169 __u64 *val, int mult)
2171 char kernbuf[22], *end, *pbuf;
2172 __u64 whole, frac = 0, units;
2173 unsigned frac_d = 1;
2175 if (count > (sizeof(kernbuf) - 1))
2178 if (copy_from_user(kernbuf, buffer, count))
2181 kernbuf[count] = '\0';
2188 whole = simple_strtoull(pbuf, &end, 10);
2192 if (end != NULL && *end == '.') {
2196 /* need to limit frac_d to a __u32 */
2197 if (strlen(pbuf) > 10)
2200 frac = simple_strtoull(pbuf, &end, 10);
2201 /* count decimal places */
2202 for (i = 0; i < (end - pbuf); i++)
2219 /* Specified units override the multiplier */
2221 mult = mult < 0 ? -units : units;
2224 do_div(frac, frac_d);
2225 *val = whole * mult + frac;
2228 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2230 static char *lprocfs_strnstr(const char *s1, const char *s2, size_t len)
2239 if (!memcmp(s1, s2, l2))
2247 * Find the string \a name in the input \a buffer, and return a pointer to the
2248 * value immediately following \a name, reducing \a count appropriately.
2249 * If \a name is not found the original \a buffer is returned.
2251 char *lprocfs_find_named_value(const char *buffer, const char *name,
2252 unsigned long *count)
2255 size_t buflen = *count;
2257 /* there is no strnstr() in rhel5 and ubuntu kernels */
2258 val = lprocfs_strnstr(buffer, name, buflen);
2260 return (char *)buffer;
2262 val += strlen(name); /* skip prefix */
2263 while (val < buffer + buflen && isspace(*val)) /* skip separator */
2267 while (val < buffer + buflen && isalnum(*val)) {
2272 return val - *count;
2274 EXPORT_SYMBOL(lprocfs_find_named_value);
2276 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent,
2279 const struct file_operations *seq_fops,
2282 struct proc_dir_entry *entry;
2285 /* Disallow secretly (un)writable entries. */
2286 LASSERT((seq_fops->write == NULL) == ((mode & 0222) == 0));
2288 LPROCFS_WRITE_ENTRY();
2289 entry = create_proc_entry(name, mode, parent);
2291 entry->proc_fops = seq_fops;
2294 LPROCFS_WRITE_EXIT();
2301 EXPORT_SYMBOL(lprocfs_seq_create);
2303 int lprocfs_obd_seq_create(struct obd_device *dev,
2306 const struct file_operations *seq_fops,
2309 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2310 mode, seq_fops, data));
2312 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2314 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2316 if (value >= OBD_HIST_MAX)
2317 value = OBD_HIST_MAX - 1;
2319 spin_lock(&oh->oh_lock);
2320 oh->oh_buckets[value]++;
2321 spin_unlock(&oh->oh_lock);
2323 EXPORT_SYMBOL(lprocfs_oh_tally);
2325 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2329 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2332 lprocfs_oh_tally(oh, val);
2334 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2336 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2338 unsigned long ret = 0;
2341 for (i = 0; i < OBD_HIST_MAX; i++)
2342 ret += oh->oh_buckets[i];
2345 EXPORT_SYMBOL(lprocfs_oh_sum);
2347 void lprocfs_oh_clear(struct obd_histogram *oh)
2349 spin_lock(&oh->oh_lock);
2350 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2351 spin_unlock(&oh->oh_lock);
2353 EXPORT_SYMBOL(lprocfs_oh_clear);
2355 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2356 int count, int *eof, void *data)
2358 struct obd_device *obd = data;
2364 c += cfs_hash_debug_header(page, count);
2365 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2366 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2367 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2371 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2373 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2374 int count, int *eof, void *data)
2376 struct obd_device *obd = data;
2379 LASSERT(obd != NULL);
2380 LASSERT(count >= 0);
2382 /* Set start of user data returned to
2383 page + off since the user may have
2384 requested to read much smaller than
2385 what we need to read */
2386 *start = page + off;
2389 * We know we are allocated a page here.
2390 * Also we know that this function will
2391 * not need to write more than a page
2392 * so we can truncate at PAGE_CACHE_SIZE.
2394 size = min(count + (int)off + 1, (int)PAGE_CACHE_SIZE);
2396 /* Initialize the page */
2397 memset(page, 0, size);
2399 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2401 if (obd->obd_max_recoverable_clients == 0) {
2402 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2408 /* sampled unlocked, but really... */
2409 if (obd->obd_recovering == 0) {
2410 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2412 if (lprocfs_obd_snprintf(&page, size, &len,
2413 "recovery_start: %lu\n",
2414 obd->obd_recovery_start) <= 0)
2416 if (lprocfs_obd_snprintf(&page, size, &len,
2417 "recovery_duration: %lu\n",
2418 obd->obd_recovery_end -
2419 obd->obd_recovery_start) <= 0)
2421 /* Number of clients that have completed recovery */
2422 if (lprocfs_obd_snprintf(&page, size, &len,
2423 "completed_clients: %d/%d\n",
2424 obd->obd_max_recoverable_clients -
2425 obd->obd_stale_clients,
2426 obd->obd_max_recoverable_clients) <= 0)
2428 if (lprocfs_obd_snprintf(&page, size, &len,
2429 "replayed_requests: %d\n",
2430 obd->obd_replayed_requests) <= 0)
2432 if (lprocfs_obd_snprintf(&page, size, &len,
2433 "last_transno: "LPD64"\n",
2434 obd->obd_next_recovery_transno - 1)<=0)
2436 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2437 obd->obd_version_recov ?
2438 "ENABLED" : "DISABLED") <=0)
2440 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
2442 "DISABLED" : "ENABLED") <= 0)
2447 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2449 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2450 obd->obd_recovery_start) <= 0)
2452 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2453 cfs_time_current_sec() >=
2454 obd->obd_recovery_start +
2455 obd->obd_recovery_timeout ? 0 :
2456 obd->obd_recovery_start +
2457 obd->obd_recovery_timeout -
2458 cfs_time_current_sec()) <= 0)
2460 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2461 cfs_atomic_read(&obd->obd_connected_clients),
2462 obd->obd_max_recoverable_clients) <= 0)
2464 /* Number of clients that have completed recovery */
2465 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2466 cfs_atomic_read(&obd->obd_req_replay_clients))
2469 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2470 cfs_atomic_read(&obd->obd_lock_replay_clients))
2473 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2474 cfs_atomic_read(&obd->obd_connected_clients) -
2475 cfs_atomic_read(&obd->obd_lock_replay_clients))
2478 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2479 obd->obd_stale_clients) <= 0)
2481 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2482 obd->obd_replayed_requests) <= 0)
2484 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2485 obd->obd_requests_queued_for_recovery) <= 0)
2488 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2489 obd->obd_next_recovery_transno) <= 0)
2495 return min(count, len - (int)off);
2497 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2499 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
2500 int count, int *eof, void *data)
2502 struct obd_device *obd = (struct obd_device *)data;
2503 LASSERT(obd != NULL);
2505 return snprintf(page, count, "%d\n",
2506 obd->obd_recovery_ir_factor);
2508 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
2510 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
2511 unsigned long count, void *data)
2513 struct obd_device *obd = (struct obd_device *)data;
2515 LASSERT(obd != NULL);
2517 rc = lprocfs_write_helper(buffer, count, &val);
2521 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
2524 obd->obd_recovery_ir_factor = val;
2527 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
2529 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
2530 int count, int *eof, void *data)
2532 struct obd_device *obd = (struct obd_device *)data;
2533 LASSERT(obd != NULL);
2535 return snprintf(page, count, "%d\n",
2536 obd->obd_recovery_timeout);
2538 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
2540 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
2541 unsigned long count, void *data)
2543 struct obd_device *obd = (struct obd_device *)data;
2545 LASSERT(obd != NULL);
2547 rc = lprocfs_write_helper(buffer, count, &val);
2551 obd->obd_recovery_timeout = val;
2554 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
2556 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
2557 int count, int *eof, void *data)
2559 struct obd_device *obd = data;
2560 LASSERT(obd != NULL);
2562 return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
2564 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
2566 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
2567 unsigned long count, void *data)
2569 struct obd_device *obd = data;
2571 LASSERT(obd != NULL);
2573 rc = lprocfs_write_helper(buffer, count, &val);
2577 obd->obd_recovery_time_hard = val;
2580 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
2582 int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
2583 int count, int *eof, void *data)
2585 struct obd_device *dev = data;
2586 struct client_obd *cli = &dev->u.cli;
2589 client_obd_list_lock(&cli->cl_loi_list_lock);
2590 rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
2591 client_obd_list_unlock(&cli->cl_loi_list_lock);
2594 EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
2596 #ifdef HAVE_SERVER_SUPPORT
2597 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
2598 int count, int *eof, void *data)
2600 struct obd_device *obd = (struct obd_device *)data;
2601 struct obd_device_target *target = &obd->u.obt;
2603 LASSERT(obd != NULL);
2604 LASSERT(target->obt_magic == OBT_MAGIC);
2606 return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
2608 EXPORT_SYMBOL(lprocfs_target_rd_instance);