4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; If not, see
18 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21 * CA 95054 USA or visit www.sun.com if you need additional information or
27 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Use is subject to license terms.
30 * Copyright (c) 2011, 2013, Intel Corporation.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
36 * lustre/obdclass/lprocfs_status.c
38 * Author: Hariharan Thantry <thantry@users.sourceforge.net>
41 #define DEBUG_SUBSYSTEM S_CLASS
44 # include <liblustre.h>
47 #include <obd_class.h>
48 #include <lprocfs_status.h>
49 #include <lustre/lustre_idl.h>
53 static int lprocfs_no_percpu_stats = 0;
54 CFS_MODULE_PARM(lprocfs_no_percpu_stats, "i", int, 0644,
55 "Do not alloc percpu data for lprocfs stats");
57 #define MAX_STRING_SIZE 128
59 /* for bug 10866, global variable */
60 DECLARE_RWSEM(_lprocfs_lock);
61 EXPORT_SYMBOL(_lprocfs_lock);
63 int lprocfs_single_release(struct inode *inode, struct file *file)
65 return single_release(inode, file);
67 EXPORT_SYMBOL(lprocfs_single_release);
69 int lprocfs_seq_release(struct inode *inode, struct file *file)
71 return seq_release(inode, file);
73 EXPORT_SYMBOL(lprocfs_seq_release);
75 static struct proc_dir_entry *__lprocfs_srch(struct proc_dir_entry *head,
78 struct proc_dir_entry *temp;
84 while (temp != NULL) {
85 if (strcmp(temp->name, name) == 0) {
94 struct proc_dir_entry *lprocfs_srch(struct proc_dir_entry *head,
97 struct proc_dir_entry *temp;
100 temp = __lprocfs_srch(head, name);
104 EXPORT_SYMBOL(lprocfs_srch);
106 /* lprocfs API calls */
108 /* Function that emulates snprintf but also has the side effect of advancing
109 the page pointer for the next write into the buffer, incrementing the total
110 length written to the buffer, and decrementing the size left in the
112 static int lprocfs_obd_snprintf(char **page, int end, int *len,
113 const char *format, ...)
121 va_start(list, format);
122 n = vsnprintf(*page, end - *len, format, list);
125 *page += n; *len += n;
129 cfs_proc_dir_entry_t *lprocfs_add_simple(struct proc_dir_entry *root,
131 read_proc_t *read_proc,
132 write_proc_t *write_proc,
134 struct file_operations *fops)
136 cfs_proc_dir_entry_t *proc;
139 if (root == NULL || name == NULL)
140 return ERR_PTR(-EINVAL);
147 LPROCFS_WRITE_ENTRY();
148 proc = create_proc_entry(name, mode, root);
150 CERROR("LprocFS: No memory to create /proc entry %s", name);
151 LPROCFS_WRITE_EXIT();
152 return ERR_PTR(-ENOMEM);
154 proc->read_proc = read_proc;
155 proc->write_proc = write_proc;
158 proc->proc_fops = fops;
159 LPROCFS_WRITE_EXIT();
162 EXPORT_SYMBOL(lprocfs_add_simple);
164 struct proc_dir_entry *lprocfs_add_symlink(const char *name,
165 struct proc_dir_entry *parent, const char *format, ...)
167 struct proc_dir_entry *entry;
171 if (parent == NULL || format == NULL)
174 OBD_ALLOC_WAIT(dest, MAX_STRING_SIZE + 1);
178 va_start(ap, format);
179 vsnprintf(dest, MAX_STRING_SIZE, format, ap);
182 entry = proc_symlink(name, parent, dest);
184 CERROR("LprocFS: Could not create symbolic link from %s to %s",
187 OBD_FREE(dest, MAX_STRING_SIZE + 1);
190 EXPORT_SYMBOL(lprocfs_add_symlink);
192 static ssize_t lprocfs_fops_read(struct file *f, char __user *buf,
193 size_t size, loff_t *ppos)
195 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
196 char *page, *start = NULL;
197 int rc = 0, eof = 1, count;
199 if (*ppos >= PAGE_CACHE_SIZE)
202 page = (char *)__get_free_page(GFP_KERNEL);
206 if (LPROCFS_ENTRY_CHECK(dp)) {
211 OBD_FAIL_TIMEOUT(OBD_FAIL_LPROC_REMOVE, 10);
213 rc = dp->read_proc(page, &start, *ppos, PAGE_CACHE_SIZE,
218 /* for lustre proc read, the read count must be less than PAGE_SIZE */
227 start = page + *ppos;
228 } else if (start < page) {
232 count = (rc < size) ? rc : size;
233 if (copy_to_user(buf, start, count)) {
240 free_page((unsigned long)page);
244 static ssize_t lprocfs_fops_write(struct file *f, const char __user *buf,
245 size_t size, loff_t *ppos)
247 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
250 if (LPROCFS_ENTRY_CHECK(dp))
253 rc = dp->write_proc(f, buf, size, dp->data);
257 static struct file_operations lprocfs_generic_fops = {
258 .owner = THIS_MODULE,
259 .read = lprocfs_fops_read,
260 .write = lprocfs_fops_write,
263 int lprocfs_evict_client_open(struct inode *inode, struct file *f)
265 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
266 struct obd_device *obd = dp->data;
268 cfs_atomic_inc(&obd->obd_evict_inprogress);
273 int lprocfs_evict_client_release(struct inode *inode, struct file *f)
275 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
276 struct obd_device *obd = dp->data;
278 cfs_atomic_dec(&obd->obd_evict_inprogress);
279 cfs_waitq_signal(&obd->obd_evict_inprogress_waitq);
284 struct file_operations lprocfs_evict_client_fops = {
285 .owner = THIS_MODULE,
286 .read = lprocfs_fops_read,
287 .write = lprocfs_fops_write,
288 .open = lprocfs_evict_client_open,
289 .release = lprocfs_evict_client_release,
291 EXPORT_SYMBOL(lprocfs_evict_client_fops);
293 static int __lprocfs_add_vars(struct proc_dir_entry *root,
294 struct lprocfs_vars *list,
299 if (root == NULL || list == NULL)
302 while (list->name != NULL) {
303 struct proc_dir_entry *cur_root, *proc;
304 char *pathcopy, *cur, *next, pathbuf[64];
305 int pathsize = strlen(list->name) + 1;
310 /* need copy of path for strsep */
311 if (strlen(list->name) > sizeof(pathbuf) - 1) {
312 OBD_ALLOC(pathcopy, pathsize);
313 if (pathcopy == NULL)
314 GOTO(out, rc = -ENOMEM);
320 strcpy(pathcopy, list->name);
322 while (cur_root != NULL && (cur = strsep(&next, "/"))) {
323 if (*cur =='\0') /* skip double/trailing "/" */
326 proc = __lprocfs_srch(cur_root, cur);
327 CDEBUG(D_OTHER, "cur_root=%s, cur=%s, next=%s, (%s)\n",
328 cur_root->name, cur, next,
329 (proc ? "exists" : "new"));
331 cur_root = (proc ? proc :
332 proc_mkdir(cur, cur_root));
333 } else if (proc == NULL) {
335 if (list->proc_mode != 0000) {
336 mode = list->proc_mode;
340 if (list->write_fptr)
343 proc = create_proc_entry(cur, mode, cur_root);
347 if (pathcopy != pathbuf)
348 OBD_FREE(pathcopy, pathsize);
350 if (cur_root == NULL || proc == NULL) {
351 CERROR("LprocFS: No memory to create /proc entry %s",
353 GOTO(out, rc = -ENOMEM);
357 proc->proc_fops = list->fops;
359 proc->proc_fops = &lprocfs_generic_fops;
360 proc->read_proc = list->read_fptr;
361 proc->write_proc = list->write_fptr;
362 proc->data = (list->data ? list->data : data);
372 * \param root [in] The parent proc entry on which new entry will be added.
373 * \param list [in] Array of proc entries to be added.
374 * \param data [in] The argument to be passed when entries read/write routines
375 * are called through /proc file.
377 * \retval 0 on success
380 int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list,
385 LPROCFS_WRITE_ENTRY();
386 rc = __lprocfs_add_vars(root, list, data);
387 LPROCFS_WRITE_EXIT();
391 EXPORT_SYMBOL(lprocfs_add_vars);
393 void lprocfs_remove_nolock(struct proc_dir_entry **proot)
395 struct proc_dir_entry *root = *proot;
396 struct proc_dir_entry *temp = root;
397 struct proc_dir_entry *rm_entry;
398 struct proc_dir_entry *parent;
401 if (root == NULL || IS_ERR(root))
404 parent = root->parent;
405 LASSERT(parent != NULL);
408 while (temp->subdir != NULL)
414 /* Memory corruption once caused this to fail, and
415 without this LASSERT we would loop here forever. */
416 LASSERTF(strlen(rm_entry->name) == rm_entry->namelen,
417 "0x%p %s/%s len %d\n", rm_entry, temp->name,
418 rm_entry->name, (int)strlen(rm_entry->name));
420 remove_proc_entry(rm_entry->name, temp);
426 void lprocfs_remove(struct proc_dir_entry **rooth)
428 LPROCFS_WRITE_ENTRY(); /* search vs remove race */
429 lprocfs_remove_nolock(rooth);
430 LPROCFS_WRITE_EXIT();
432 EXPORT_SYMBOL(lprocfs_remove);
434 void lprocfs_remove_proc_entry(const char *name, struct proc_dir_entry *parent)
436 LASSERT(parent != NULL);
437 remove_proc_entry(name, parent);
439 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
441 void lprocfs_try_remove_proc_entry(const char *name,
442 struct proc_dir_entry *parent)
444 struct proc_dir_entry *t = NULL;
445 struct proc_dir_entry **p;
448 LASSERT(parent != NULL);
451 LPROCFS_WRITE_ENTRY();
453 /* lookup target name */
454 for (p = &parent->subdir; *p; p = &(*p)->next) {
455 if ((*p)->namelen != len)
457 if (memcmp(name, (*p)->name, len))
464 /* verify it's empty: do not count "num_refs" */
465 for (p = &t->subdir; *p; p = &(*p)->next) {
466 if ((*p)->namelen != strlen("num_refs")) {
470 if (memcmp("num_refs", (*p)->name,
471 strlen("num_refs"))) {
479 lprocfs_remove_nolock(&t);
481 LPROCFS_WRITE_EXIT();
485 EXPORT_SYMBOL(lprocfs_try_remove_proc_entry);
487 struct proc_dir_entry *lprocfs_register(const char *name,
488 struct proc_dir_entry *parent,
489 struct lprocfs_vars *list, void *data)
491 struct proc_dir_entry *entry;
494 LPROCFS_WRITE_ENTRY();
495 entry = __lprocfs_srch(parent, name);
497 CERROR("entry '%s' already registered\n", name);
498 GOTO(out, entry = ERR_PTR(-EALREADY));
501 entry = proc_mkdir(name, parent);
503 GOTO(out, entry = ERR_PTR(-ENOMEM));
506 rc = __lprocfs_add_vars(entry, list, data);
508 lprocfs_remove_nolock(&entry);
509 GOTO(out, entry = ERR_PTR(rc));
513 LPROCFS_WRITE_EXIT();
517 EXPORT_SYMBOL(lprocfs_register);
519 /* Generic callbacks */
520 int lprocfs_rd_uint(char *page, char **start, off_t off,
521 int count, int *eof, void *data)
523 unsigned int *temp = data;
524 return snprintf(page, count, "%u\n", *temp);
526 EXPORT_SYMBOL(lprocfs_rd_uint);
528 int lprocfs_wr_uint(struct file *file, const char *buffer,
529 unsigned long count, void *data)
532 char dummy[MAX_STRING_SIZE + 1], *end;
535 dummy[MAX_STRING_SIZE] = '\0';
536 if (copy_from_user(dummy, buffer, MAX_STRING_SIZE))
539 tmp = simple_strtoul(dummy, &end, 0);
543 *p = (unsigned int)tmp;
546 EXPORT_SYMBOL(lprocfs_wr_uint);
548 int lprocfs_rd_u64(char *page, char **start, off_t off,
549 int count, int *eof, void *data)
551 LASSERT(data != NULL);
553 return snprintf(page, count, LPU64"\n", *(__u64 *)data);
555 EXPORT_SYMBOL(lprocfs_rd_u64);
557 int lprocfs_rd_atomic(char *page, char **start, off_t off,
558 int count, int *eof, void *data)
560 cfs_atomic_t *atom = data;
561 LASSERT(atom != NULL);
563 return snprintf(page, count, "%d\n", cfs_atomic_read(atom));
565 EXPORT_SYMBOL(lprocfs_rd_atomic);
567 int lprocfs_wr_atomic(struct file *file, const char *buffer,
568 unsigned long count, void *data)
570 cfs_atomic_t *atm = data;
574 rc = lprocfs_write_helper(buffer, count, &val);
581 cfs_atomic_set(atm, val);
584 EXPORT_SYMBOL(lprocfs_wr_atomic);
586 int lprocfs_rd_uuid(char *page, char **start, off_t off, int count,
587 int *eof, void *data)
589 struct obd_device *obd = data;
591 LASSERT(obd != NULL);
593 return snprintf(page, count, "%s\n", obd->obd_uuid.uuid);
595 EXPORT_SYMBOL(lprocfs_rd_uuid);
597 int lprocfs_rd_name(char *page, char **start, off_t off, int count,
598 int *eof, void *data)
600 struct obd_device *dev = data;
602 LASSERT(dev != NULL);
604 return snprintf(page, count, "%s\n", dev->obd_name);
606 EXPORT_SYMBOL(lprocfs_rd_name);
608 int lprocfs_rd_blksize(char *page, char **start, off_t off, int count,
609 int *eof, void *data)
611 struct obd_device *obd = data;
612 struct obd_statfs osfs;
613 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
614 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
618 rc = snprintf(page, count, "%u\n", osfs.os_bsize);
622 EXPORT_SYMBOL(lprocfs_rd_blksize);
624 int lprocfs_rd_kbytestotal(char *page, char **start, off_t off, int count,
625 int *eof, void *data)
627 struct obd_device *obd = data;
628 struct obd_statfs osfs;
629 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
630 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
633 __u32 blk_size = osfs.os_bsize >> 10;
634 __u64 result = osfs.os_blocks;
636 while (blk_size >>= 1)
640 rc = snprintf(page, count, LPU64"\n", result);
644 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
646 int lprocfs_rd_kbytesfree(char *page, char **start, off_t off, int count,
647 int *eof, void *data)
649 struct obd_device *obd = data;
650 struct obd_statfs osfs;
651 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
652 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
655 __u32 blk_size = osfs.os_bsize >> 10;
656 __u64 result = osfs.os_bfree;
658 while (blk_size >>= 1)
662 rc = snprintf(page, count, LPU64"\n", result);
666 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
668 int lprocfs_rd_kbytesavail(char *page, char **start, off_t off, int count,
669 int *eof, void *data)
671 struct obd_device *obd = data;
672 struct obd_statfs osfs;
673 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
674 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
677 __u32 blk_size = osfs.os_bsize >> 10;
678 __u64 result = osfs.os_bavail;
680 while (blk_size >>= 1)
684 rc = snprintf(page, count, LPU64"\n", result);
688 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
690 int lprocfs_rd_filestotal(char *page, char **start, off_t off, int count,
691 int *eof, void *data)
693 struct obd_device *obd = data;
694 struct obd_statfs osfs;
695 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
696 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
700 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
705 EXPORT_SYMBOL(lprocfs_rd_filestotal);
707 int lprocfs_rd_filesfree(char *page, char **start, off_t off, int count,
708 int *eof, void *data)
710 struct obd_device *obd = data;
711 struct obd_statfs osfs;
712 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
713 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
717 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
721 EXPORT_SYMBOL(lprocfs_rd_filesfree);
723 int lprocfs_rd_server_uuid(char *page, char **start, off_t off, int count,
724 int *eof, void *data)
726 struct obd_device *obd = data;
727 struct obd_import *imp;
728 char *imp_state_name = NULL;
731 LASSERT(obd != NULL);
732 LPROCFS_CLIMP_CHECK(obd);
733 imp = obd->u.cli.cl_import;
734 imp_state_name = ptlrpc_import_state_name(imp->imp_state);
736 rc = snprintf(page, count, "%s\t%s%s\n",
737 obd2cli_tgt(obd), imp_state_name,
738 imp->imp_deactive ? "\tDEACTIVATED" : "");
740 LPROCFS_CLIMP_EXIT(obd);
743 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
745 int lprocfs_rd_conn_uuid(char *page, char **start, off_t off, int count,
746 int *eof, void *data)
748 struct obd_device *obd = data;
749 struct ptlrpc_connection *conn;
752 LASSERT(obd != NULL);
754 LPROCFS_CLIMP_CHECK(obd);
755 conn = obd->u.cli.cl_import->imp_connection;
757 if (conn && obd->u.cli.cl_import) {
758 rc = snprintf(page, count, "%s\n",
759 conn->c_remote_uuid.uuid);
761 rc = snprintf(page, count, "%s\n", "<none>");
764 LPROCFS_CLIMP_EXIT(obd);
767 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
769 /** add up per-cpu counters */
770 void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
771 struct lprocfs_counter *cnt)
773 unsigned int num_entry;
774 struct lprocfs_counter *percpu_cntr;
776 unsigned long flags = 0;
778 memset(cnt, 0, sizeof(*cnt));
781 /* set count to 1 to avoid divide-by-zero errs in callers */
786 cnt->lc_min = LC_MIN_INIT;
788 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
790 for (i = 0; i < num_entry; i++) {
791 if (stats->ls_percpu[i] == NULL)
793 percpu_cntr = lprocfs_stats_counter_get(stats, i, idx);
795 cnt->lc_count += percpu_cntr->lc_count;
796 cnt->lc_sum += percpu_cntr->lc_sum;
797 if (percpu_cntr->lc_min < cnt->lc_min)
798 cnt->lc_min = percpu_cntr->lc_min;
799 if (percpu_cntr->lc_max > cnt->lc_max)
800 cnt->lc_max = percpu_cntr->lc_max;
801 cnt->lc_sumsquare += percpu_cntr->lc_sumsquare;
804 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
806 EXPORT_SYMBOL(lprocfs_stats_collect);
809 * Append a space separated list of current set flags to str.
811 #define flag2str(flag) \
812 if (imp->imp_##flag && max - len > 0) \
813 len += snprintf(str + len, max - len, "%s" #flag, len ? ", " : "");
814 static int obd_import_flags2str(struct obd_import *imp, char *str, int max)
818 if (imp->imp_obd->obd_no_recov)
819 len += snprintf(str, max - len, "no_recov");
823 flag2str(replayable);
829 static const char *obd_connect_names[] = {
843 "join_file(obsolete)",
847 "remote_client_by_force",
856 "mds_mds_connection",
859 "alt_checksum_algorithm",
886 int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
891 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
893 ret += snprintf(page + ret, count - ret, "%s%s",
894 ret ? sep : "", obd_connect_names[i]);
896 if (flags & ~(mask - 1))
897 ret += snprintf(page + ret, count - ret,
898 "%sunknown flags "LPX64,
899 ret ? sep : "", flags & ~(mask - 1));
902 EXPORT_SYMBOL(obd_connect_flags2str);
904 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
905 int *eof, void *data)
907 struct lprocfs_counter ret;
908 struct lprocfs_counter_header *header;
909 struct obd_device *obd = (struct obd_device *)data;
910 struct obd_import *imp;
911 struct obd_import_conn *conn;
917 LASSERT(obd != NULL);
918 LPROCFS_CLIMP_CHECK(obd);
919 imp = obd->u.cli.cl_import;
922 i = snprintf(page, count,
931 ptlrpc_import_state_name(imp->imp_state),
932 imp->imp_connect_data.ocd_instance);
933 i += obd_connect_flags2str(page + i, count - i,
934 imp->imp_connect_data.ocd_connect_flags,
936 i += snprintf(page + i, count - i,
939 i += obd_import_flags2str(imp, page + i, count - i);
941 i += snprintf(page + i, count - i,
944 " failover_nids: [");
945 spin_lock(&imp->imp_lock);
947 cfs_list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
948 i += snprintf(page + i, count - i, "%s%s", j ? ", " : "",
949 libcfs_nid2str(conn->oic_conn->c_peer.nid));
952 i += snprintf(page + i, count - i,
954 " current_connection: %s\n"
955 " connection_attempts: %u\n"
957 " in-progress_invalidations: %u\n",
958 imp->imp_connection == NULL ? "<none>" :
959 libcfs_nid2str(imp->imp_connection->c_peer.nid),
962 cfs_atomic_read(&imp->imp_inval_count));
963 spin_unlock(&imp->imp_lock);
965 if (obd->obd_svc_stats == NULL)
968 header = &obd->obd_svc_stats->ls_cnt_header[PTLRPC_REQWAIT_CNTR];
969 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
970 if (ret.lc_count != 0) {
971 /* first argument to do_div MUST be __u64 */
972 __u64 sum = ret.lc_sum;
973 do_div(sum, ret.lc_count);
977 i += snprintf(page + i, count - i,
980 " unregistering: %u\n"
982 " avg_waittime: "LPU64" %s\n",
983 cfs_atomic_read(&imp->imp_inflight),
984 cfs_atomic_read(&imp->imp_unregistering),
985 cfs_atomic_read(&imp->imp_timeouts),
986 ret.lc_sum, header->lc_units);
989 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
990 if (imp->imp_at.iat_portal[j] == 0)
992 k = max_t(unsigned int, k,
993 at_get(&imp->imp_at.iat_service_estimate[j]));
995 i += snprintf(page + i, count - i,
996 " service_estimates:\n"
997 " services: %u sec\n"
998 " network: %u sec\n",
1000 at_get(&imp->imp_at.iat_net_latency));
1002 i += snprintf(page + i, count - i,
1004 " last_replay: "LPU64"\n"
1005 " peer_committed: "LPU64"\n"
1006 " last_checked: "LPU64"\n",
1007 imp->imp_last_replay_transno,
1008 imp->imp_peer_committed_transno,
1009 imp->imp_last_transno_checked);
1011 /* avg data rates */
1012 for (rw = 0; rw <= 1; rw++) {
1013 lprocfs_stats_collect(obd->obd_svc_stats,
1014 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
1016 if (ret.lc_sum > 0 && ret.lc_count > 0) {
1017 /* first argument to do_div MUST be __u64 */
1018 __u64 sum = ret.lc_sum;
1019 do_div(sum, ret.lc_count);
1021 i += snprintf(page + i, count - i,
1022 " %s_data_averages:\n"
1023 " bytes_per_rpc: "LPU64"\n",
1024 rw ? "write" : "read",
1027 k = (int)ret.lc_sum;
1028 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
1029 header = &obd->obd_svc_stats->ls_cnt_header[j];
1030 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
1031 if (ret.lc_sum > 0 && ret.lc_count != 0) {
1032 /* first argument to do_div MUST be __u64 */
1033 __u64 sum = ret.lc_sum;
1034 do_div(sum, ret.lc_count);
1036 i += snprintf(page + i, count - i,
1037 " %s_per_rpc: "LPU64"\n",
1038 header->lc_units, ret.lc_sum);
1039 j = (int)ret.lc_sum;
1041 i += snprintf(page + i, count - i,
1042 " MB_per_sec: %u.%.02u\n",
1043 k / j, (100 * k / j) % 100);
1048 LPROCFS_CLIMP_EXIT(obd);
1051 EXPORT_SYMBOL(lprocfs_rd_import);
1053 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
1054 int *eof, void *data)
1056 struct obd_device *obd = (struct obd_device *)data;
1057 struct obd_import *imp;
1060 LASSERT(obd != NULL);
1061 LPROCFS_CLIMP_CHECK(obd);
1062 imp = obd->u.cli.cl_import;
1065 i = snprintf(page, count, "current_state: %s\n",
1066 ptlrpc_import_state_name(imp->imp_state));
1067 i += snprintf(page + i, count - i,
1068 "state_history:\n");
1069 k = imp->imp_state_hist_idx;
1070 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
1071 struct import_state_hist *ish =
1072 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
1073 if (ish->ish_state == 0)
1075 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
1077 ptlrpc_import_state_name(ish->ish_state));
1080 LPROCFS_CLIMP_EXIT(obd);
1083 EXPORT_SYMBOL(lprocfs_rd_state);
1085 int lprocfs_at_hist_helper(char *page, int count, int rc,
1086 struct adaptive_timeout *at)
1089 for (i = 0; i < AT_BINS; i++)
1090 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
1091 rc += snprintf(page + rc, count - rc, "\n");
1094 EXPORT_SYMBOL(lprocfs_at_hist_helper);
1096 /* See also ptlrpc_lprocfs_rd_timeouts */
1097 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
1098 int *eof, void *data)
1100 struct obd_device *obd = (struct obd_device *)data;
1101 struct obd_import *imp;
1102 unsigned int cur, worst;
1107 LASSERT(obd != NULL);
1108 LPROCFS_CLIMP_CHECK(obd);
1109 imp = obd->u.cli.cl_import;
1112 now = cfs_time_current_sec();
1114 /* Some network health info for kicks */
1115 s2dhms(&ts, now - imp->imp_last_reply_time);
1116 rc += snprintf(page + rc, count - rc,
1117 "%-10s : %ld, "DHMS_FMT" ago\n",
1118 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
1120 cur = at_get(&imp->imp_at.iat_net_latency);
1121 worst = imp->imp_at.iat_net_latency.at_worst_ever;
1122 worstt = imp->imp_at.iat_net_latency.at_worst_time;
1123 s2dhms(&ts, now - worstt);
1124 rc += snprintf(page + rc, count - rc,
1125 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
1126 "network", cur, worst, worstt, DHMS_VARS(&ts));
1127 rc = lprocfs_at_hist_helper(page, count, rc,
1128 &imp->imp_at.iat_net_latency);
1130 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
1131 if (imp->imp_at.iat_portal[i] == 0)
1133 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
1134 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
1135 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
1136 s2dhms(&ts, now - worstt);
1137 rc += snprintf(page + rc, count - rc,
1138 "portal %-2d : cur %3u worst %3u (at %ld, "
1139 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
1140 cur, worst, worstt, DHMS_VARS(&ts));
1141 rc = lprocfs_at_hist_helper(page, count, rc,
1142 &imp->imp_at.iat_service_estimate[i]);
1145 LPROCFS_CLIMP_EXIT(obd);
1148 EXPORT_SYMBOL(lprocfs_rd_timeouts);
1150 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1151 int count, int *eof, void *data)
1153 struct obd_device *obd = data;
1157 LPROCFS_CLIMP_CHECK(obd);
1158 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1159 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1160 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1161 ret += snprintf(page + ret, count - ret, "\n");
1162 LPROCFS_CLIMP_EXIT(obd);
1165 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1167 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1168 int *eof, void *data)
1170 struct obd_device *obd = data;
1172 LASSERT(obd != NULL);
1174 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1176 EXPORT_SYMBOL(lprocfs_rd_num_exports);
1178 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1179 int *eof, void *data)
1181 struct obd_type *class = (struct obd_type*) data;
1183 LASSERT(class != NULL);
1185 return snprintf(page, count, "%d\n", class->typ_refcnt);
1187 EXPORT_SYMBOL(lprocfs_rd_numrefs);
1189 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1193 LASSERT(obd != NULL);
1194 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1195 LASSERT(obd->obd_type->typ_procroot != NULL);
1197 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1198 obd->obd_type->typ_procroot,
1200 if (IS_ERR(obd->obd_proc_entry)) {
1201 rc = PTR_ERR(obd->obd_proc_entry);
1202 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1203 obd->obd_proc_entry = NULL;
1207 EXPORT_SYMBOL(lprocfs_obd_setup);
1209 int lprocfs_obd_cleanup(struct obd_device *obd)
1213 if (obd->obd_proc_exports_entry) {
1214 /* Should be no exports left */
1215 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1216 lprocfs_remove(&obd->obd_proc_exports_entry);
1217 obd->obd_proc_exports_entry = NULL;
1219 if (obd->obd_proc_entry) {
1220 lprocfs_remove(&obd->obd_proc_entry);
1221 obd->obd_proc_entry = NULL;
1225 EXPORT_SYMBOL(lprocfs_obd_cleanup);
1227 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1229 CDEBUG(D_CONFIG, "stat %p - data %p/%p\n", client_stat,
1230 client_stat->nid_proc, client_stat->nid_stats);
1232 LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
1233 "nid %s:count %d\n", libcfs_nid2str(client_stat->nid),
1234 atomic_read(&client_stat->nid_exp_ref_count));
1236 if (client_stat->nid_proc)
1237 lprocfs_remove(&client_stat->nid_proc);
1239 if (client_stat->nid_stats)
1240 lprocfs_free_stats(&client_stat->nid_stats);
1242 if (client_stat->nid_ldlm_stats)
1243 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1245 OBD_FREE_PTR(client_stat);
1250 void lprocfs_free_per_client_stats(struct obd_device *obd)
1252 cfs_hash_t *hash = obd->obd_nid_stats_hash;
1253 struct nid_stat *stat;
1256 /* we need extra list - because hash_exit called to early */
1257 /* not need locking because all clients is died */
1258 while (!cfs_list_empty(&obd->obd_nid_stats)) {
1259 stat = cfs_list_entry(obd->obd_nid_stats.next,
1260 struct nid_stat, nid_list);
1261 cfs_list_del_init(&stat->nid_list);
1262 cfs_hash_del(hash, &stat->nid, &stat->nid_hash);
1263 lprocfs_free_client_stats(stat);
1267 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
1269 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1270 enum lprocfs_stats_flags flags)
1272 struct lprocfs_stats *stats;
1273 unsigned int num_entry;
1274 unsigned int percpusize = 0;
1280 if (lprocfs_no_percpu_stats != 0)
1281 flags |= LPROCFS_STATS_FLAG_NOPERCPU;
1283 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1286 num_entry = num_possible_cpus();
1288 /* alloc percpu pointers for all possible cpu slots */
1289 LIBCFS_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1293 stats->ls_num = num;
1294 stats->ls_flags = flags;
1295 spin_lock_init(&stats->ls_lock);
1297 /* alloc num of counter headers */
1298 LIBCFS_ALLOC(stats->ls_cnt_header,
1299 stats->ls_num * sizeof(struct lprocfs_counter_header));
1300 if (stats->ls_cnt_header == NULL)
1303 if ((flags & LPROCFS_STATS_FLAG_NOPERCPU) != 0) {
1304 /* contains only one set counters */
1305 percpusize = lprocfs_stats_counter_size(stats);
1306 LIBCFS_ALLOC_ATOMIC(stats->ls_percpu[0], percpusize);
1307 if (stats->ls_percpu[0] == NULL)
1309 stats->ls_biggest_alloc_num = 1;
1310 } else if ((flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0) {
1311 /* alloc all percpu data, currently only obd_memory use this */
1312 for (i = 0; i < num_entry; ++i)
1313 if (lprocfs_stats_alloc_one(stats, i) < 0)
1320 lprocfs_free_stats(&stats);
1323 EXPORT_SYMBOL(lprocfs_alloc_stats);
1325 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1327 struct lprocfs_stats *stats = *statsh;
1328 unsigned int num_entry;
1329 unsigned int percpusize;
1332 if (stats == NULL || stats->ls_num == 0)
1336 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1339 num_entry = num_possible_cpus();
1341 percpusize = lprocfs_stats_counter_size(stats);
1342 for (i = 0; i < num_entry; i++)
1343 if (stats->ls_percpu[i] != NULL)
1344 LIBCFS_FREE(stats->ls_percpu[i], percpusize);
1345 if (stats->ls_cnt_header != NULL)
1346 LIBCFS_FREE(stats->ls_cnt_header, stats->ls_num *
1347 sizeof(struct lprocfs_counter_header));
1348 LIBCFS_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1350 EXPORT_SYMBOL(lprocfs_free_stats);
1352 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1354 struct lprocfs_counter *percpu_cntr;
1357 unsigned int num_entry;
1358 unsigned long flags = 0;
1360 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1362 for (i = 0; i < num_entry; i++) {
1363 if (stats->ls_percpu[i] == NULL)
1365 for (j = 0; j < stats->ls_num; j++) {
1366 percpu_cntr = lprocfs_stats_counter_get(stats, i, j);
1367 percpu_cntr->lc_count = 0;
1368 percpu_cntr->lc_min = LC_MIN_INIT;
1369 percpu_cntr->lc_max = 0;
1370 percpu_cntr->lc_sumsquare = 0;
1371 percpu_cntr->lc_sum = 0;
1372 if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
1373 percpu_cntr->lc_sum_irq = 0;
1377 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1379 EXPORT_SYMBOL(lprocfs_clear_stats);
1381 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1382 size_t len, loff_t *off)
1384 struct seq_file *seq = file->private_data;
1385 struct lprocfs_stats *stats = seq->private;
1387 lprocfs_clear_stats(stats);
1392 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1394 struct lprocfs_stats *stats = p->private;
1396 return (*pos < stats->ls_num) ? pos : NULL;
1399 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1403 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1407 return lprocfs_stats_seq_start(p, pos);
1410 /* seq file export of one lprocfs counter */
1411 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1413 struct lprocfs_stats *stats = p->private;
1414 struct lprocfs_counter_header *hdr;
1415 struct lprocfs_counter ctr;
1416 int idx = *(loff_t *)v;
1422 do_gettimeofday(&now);
1423 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1424 "snapshot_time", now.tv_sec, now.tv_usec);
1429 hdr = &stats->ls_cnt_header[idx];
1430 lprocfs_stats_collect(stats, idx, &ctr);
1432 if (ctr.lc_count == 0)
1435 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", hdr->lc_name,
1436 ctr.lc_count, hdr->lc_units);
1440 if ((hdr->lc_config & LPROCFS_CNTR_AVGMINMAX) && ctr.lc_count > 0) {
1441 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1442 ctr.lc_min, ctr.lc_max, ctr.lc_sum);
1445 if (hdr->lc_config & LPROCFS_CNTR_STDDEV)
1446 rc = seq_printf(p, " "LPD64, ctr.lc_sumsquare);
1450 rc = seq_printf(p, "\n");
1452 return (rc < 0) ? rc : 0;
1455 struct seq_operations lprocfs_stats_seq_sops = {
1456 .start = lprocfs_stats_seq_start,
1457 .stop = lprocfs_stats_seq_stop,
1458 .next = lprocfs_stats_seq_next,
1459 .show = lprocfs_stats_seq_show,
1462 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1464 struct proc_dir_entry *dp = PDE(inode);
1465 struct seq_file *seq;
1468 if (LPROCFS_ENTRY_CHECK(dp))
1471 rc = seq_open(file, &lprocfs_stats_seq_sops);
1474 seq = file->private_data;
1475 seq->private = dp->data;
1479 struct file_operations lprocfs_stats_seq_fops = {
1480 .owner = THIS_MODULE,
1481 .open = lprocfs_stats_seq_open,
1483 .write = lprocfs_stats_seq_write,
1484 .llseek = seq_lseek,
1485 .release = lprocfs_seq_release,
1488 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1489 struct lprocfs_stats *stats)
1491 struct proc_dir_entry *entry;
1492 LASSERT(root != NULL);
1494 LPROCFS_WRITE_ENTRY();
1495 entry = create_proc_entry(name, 0644, root);
1497 entry->proc_fops = &lprocfs_stats_seq_fops;
1498 entry->data = stats;
1501 LPROCFS_WRITE_EXIT();
1508 EXPORT_SYMBOL(lprocfs_register_stats);
1510 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1511 unsigned conf, const char *name, const char *units)
1513 struct lprocfs_counter_header *header;
1514 struct lprocfs_counter *percpu_cntr;
1515 unsigned long flags = 0;
1517 unsigned int num_cpu;
1519 LASSERT(stats != NULL);
1521 header = &stats->ls_cnt_header[index];
1522 LASSERTF(header != NULL, "Failed to allocate stats header:[%d]%s/%s\n",
1523 index, name, units);
1525 header->lc_config = conf;
1526 header->lc_name = name;
1527 header->lc_units = units;
1529 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1530 for (i = 0; i < num_cpu; ++i) {
1531 if (stats->ls_percpu[i] == NULL)
1533 percpu_cntr = lprocfs_stats_counter_get(stats, i, index);
1534 percpu_cntr->lc_count = 0;
1535 percpu_cntr->lc_min = LC_MIN_INIT;
1536 percpu_cntr->lc_max = 0;
1537 percpu_cntr->lc_sumsquare = 0;
1538 percpu_cntr->lc_sum = 0;
1539 if ((stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
1540 percpu_cntr->lc_sum_irq = 0;
1542 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1544 EXPORT_SYMBOL(lprocfs_counter_init);
1546 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1548 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1549 LASSERT(coffset < stats->ls_num); \
1550 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1553 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1555 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1556 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1557 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1558 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1559 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1560 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1561 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1562 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1563 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1564 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1565 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1566 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1567 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1568 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1569 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1570 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1571 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1572 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1573 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1574 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1575 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1576 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1577 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1578 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1579 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1580 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1581 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1582 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1583 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1584 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1585 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1586 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1587 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1588 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1589 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1590 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1591 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1592 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1593 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1594 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1595 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1596 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1597 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1598 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
1599 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1600 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1601 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1602 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1603 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1604 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1605 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1606 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1607 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1608 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1609 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1610 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1611 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1612 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1613 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1614 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1615 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1616 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1617 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1618 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1619 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1620 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1621 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1623 CLASSERT(NUM_OBD_STATS == OBD_COUNTER_OFFSET(putref) + 1);
1625 EXPORT_SYMBOL(lprocfs_init_ops_stats);
1627 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1629 struct lprocfs_stats *stats;
1630 unsigned int num_stats;
1633 LASSERT(obd->obd_stats == NULL);
1634 LASSERT(obd->obd_proc_entry != NULL);
1635 LASSERT(obd->obd_cntr_base == 0);
1637 num_stats = NUM_OBD_STATS + num_private_stats;
1638 stats = lprocfs_alloc_stats(num_stats, 0);
1642 lprocfs_init_ops_stats(num_private_stats, stats);
1644 for (i = num_private_stats; i < num_stats; i++) {
1645 /* If this LBUGs, it is likely that an obd
1646 * operation was added to struct obd_ops in
1647 * <obd.h>, and that the corresponding line item
1648 * LPROCFS_OBD_OP_INIT(.., .., opname)
1649 * is missing from the list above. */
1650 LASSERTF(stats->ls_cnt_header[i].lc_name != NULL,
1651 "Missing obd_stat initializer obd_op "
1652 "operation at offset %d.\n", i - num_private_stats);
1654 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1656 lprocfs_free_stats(&stats);
1658 obd->obd_stats = stats;
1659 obd->obd_cntr_base = num_private_stats;
1663 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
1665 void lprocfs_free_obd_stats(struct obd_device *obd)
1668 lprocfs_free_stats(&obd->obd_stats);
1670 EXPORT_SYMBOL(lprocfs_free_obd_stats);
1672 /* Note that we only init md counters for ops whose offset is less
1673 * than NUM_MD_STATS. This is explained in a comment in the definition
1674 * of struct md_ops. */
1675 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1677 unsigned int _idx = base + MD_COUNTER_OFFSET(op); \
1679 if (MD_COUNTER_OFFSET(op) < NUM_MD_STATS) { \
1680 LASSERT(_idx < stats->ls_num); \
1681 lprocfs_counter_init(stats, _idx, 0, #op, "reqs"); \
1685 void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats)
1687 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1688 LPROCFS_MD_OP_INIT(num_private_stats, stats, null_inode);
1689 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
1690 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1691 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1692 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1693 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1694 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1695 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1696 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1697 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1698 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1699 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1700 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1701 LPROCFS_MD_OP_INIT(num_private_stats, stats, fsync);
1702 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1703 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1704 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1705 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1706 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1707 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1708 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1709 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1710 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1711 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1712 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1713 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1714 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1715 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1716 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1717 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1718 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1720 EXPORT_SYMBOL(lprocfs_init_mps_stats);
1722 int lprocfs_alloc_md_stats(struct obd_device *obd,
1723 unsigned int num_private_stats)
1725 struct lprocfs_stats *stats;
1726 unsigned int num_stats;
1729 CLASSERT(offsetof(struct md_ops, MD_STATS_FIRST_OP) == 0);
1730 CLASSERT(_MD_COUNTER_OFFSET(MD_STATS_FIRST_OP) == 0);
1731 CLASSERT(_MD_COUNTER_OFFSET(MD_STATS_LAST_OP) > 0);
1733 /* TODO Ensure that this function is only used where
1734 * appropriate by adding an assertion to the effect that
1735 * obd->obd_type->typ_md_ops is not NULL. We can't do this now
1736 * because mdt_procfs_init() uses this function to allocate
1737 * the stats backing /proc/fs/lustre/mdt/.../md_stats but the
1738 * mdt layer does not use the md_ops interface. This is
1739 * confusing and a waste of memory. See LU-2484.
1741 LASSERT(obd->obd_proc_entry != NULL);
1742 LASSERT(obd->obd_md_stats == NULL);
1743 LASSERT(obd->obd_md_cntr_base == 0);
1745 num_stats = NUM_MD_STATS + num_private_stats;
1746 stats = lprocfs_alloc_stats(num_stats, 0);
1750 lprocfs_init_mps_stats(num_private_stats, stats);
1752 for (i = num_private_stats; i < num_stats; i++) {
1753 if (stats->ls_cnt_header[i].lc_name == NULL) {
1754 CERROR("Missing md_stat initializer md_op "
1755 "operation at offset %d. Aborting.\n",
1756 i - num_private_stats);
1761 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1763 lprocfs_free_stats(&stats);
1765 obd->obd_md_stats = stats;
1766 obd->obd_md_cntr_base = num_private_stats;
1771 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
1773 void lprocfs_free_md_stats(struct obd_device *obd)
1775 struct lprocfs_stats *stats = obd->obd_md_stats;
1777 if (stats != NULL) {
1778 obd->obd_md_stats = NULL;
1779 obd->obd_md_cntr_base = 0;
1780 lprocfs_free_stats(&stats);
1783 EXPORT_SYMBOL(lprocfs_free_md_stats);
1785 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1787 lprocfs_counter_init(ldlm_stats,
1788 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1789 0, "ldlm_enqueue", "reqs");
1790 lprocfs_counter_init(ldlm_stats,
1791 LDLM_CONVERT - LDLM_FIRST_OPC,
1792 0, "ldlm_convert", "reqs");
1793 lprocfs_counter_init(ldlm_stats,
1794 LDLM_CANCEL - LDLM_FIRST_OPC,
1795 0, "ldlm_cancel", "reqs");
1796 lprocfs_counter_init(ldlm_stats,
1797 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1798 0, "ldlm_bl_callback", "reqs");
1799 lprocfs_counter_init(ldlm_stats,
1800 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1801 0, "ldlm_cp_callback", "reqs");
1802 lprocfs_counter_init(ldlm_stats,
1803 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1804 0, "ldlm_gl_callback", "reqs");
1806 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
1808 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1809 int *eof, void *data)
1811 struct obd_export *exp = data;
1812 LASSERT(exp != NULL);
1814 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1817 struct exp_uuid_cb_data {
1825 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1826 int count, int *eof, int *len)
1828 cb_data->page = page;
1829 cb_data->count = count;
1834 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1835 cfs_hlist_node_t *hnode, void *cb_data)
1838 struct obd_export *exp = cfs_hash_object(hs, hnode);
1839 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1841 if (exp->exp_nid_stats)
1842 *data->len += snprintf((data->page + *data->len),
1843 data->count, "%s\n",
1844 obd_uuid2str(&exp->exp_client_uuid));
1848 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1849 int *eof, void *data)
1851 struct nid_stat *stats = (struct nid_stat *)data;
1852 struct exp_uuid_cb_data cb_data;
1853 struct obd_device *obd = stats->nid_obd;
1858 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1859 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1860 lprocfs_exp_print_uuid, &cb_data);
1861 return (*cb_data.len);
1864 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1865 cfs_hlist_node_t *hnode, void *cb_data)
1868 struct exp_uuid_cb_data *data = cb_data;
1869 struct obd_export *exp = cfs_hash_object(hs, hnode);
1871 if (exp->exp_lock_hash != NULL) {
1873 *data->len += cfs_hash_debug_header(data->page,
1876 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1883 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1884 int *eof, void *data)
1886 struct nid_stat *stats = (struct nid_stat *)data;
1887 struct exp_uuid_cb_data cb_data;
1888 struct obd_device *obd = stats->nid_obd;
1893 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1895 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1896 lprocfs_exp_print_hash, &cb_data);
1897 return (*cb_data.len);
1900 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1901 int count, int *eof, void *data)
1904 return snprintf(page, count, "%s\n",
1905 "Write into this file to clear all nid stats and "
1906 "stale nid entries");
1908 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1910 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1912 struct nid_stat *stat = obj;
1915 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
1916 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 1) {
1917 /* object has only hash references. */
1918 spin_lock(&stat->nid_obd->obd_nid_lock);
1919 cfs_list_move(&stat->nid_list, data);
1920 spin_unlock(&stat->nid_obd->obd_nid_lock);
1923 /* we has reference to object - only clear data*/
1924 if (stat->nid_stats)
1925 lprocfs_clear_stats(stat->nid_stats);
1930 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1931 unsigned long count, void *data)
1933 struct obd_device *obd = (struct obd_device *)data;
1934 struct nid_stat *client_stat;
1935 CFS_LIST_HEAD(free_list);
1937 cfs_hash_cond_del(obd->obd_nid_stats_hash,
1938 lprocfs_nid_stats_clear_write_cb, &free_list);
1940 while (!cfs_list_empty(&free_list)) {
1941 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
1943 cfs_list_del_init(&client_stat->nid_list);
1944 lprocfs_free_client_stats(client_stat);
1949 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1951 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1953 struct nid_stat *new_stat, *old_stat;
1954 struct obd_device *obd = NULL;
1955 cfs_proc_dir_entry_t *entry;
1956 char *buffer = NULL;
1962 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1963 !exp->exp_obd->obd_nid_stats_hash)
1966 /* not test against zero because eric say:
1967 * You may only test nid against another nid, or LNET_NID_ANY.
1968 * Anything else is nonsense.*/
1969 if (!nid || *nid == LNET_NID_ANY)
1974 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
1976 OBD_ALLOC_PTR(new_stat);
1977 if (new_stat == NULL)
1980 new_stat->nid = *nid;
1981 new_stat->nid_obd = exp->exp_obd;
1982 /* we need set default refcount to 1 to balance obd_disconnect */
1983 cfs_atomic_set(&new_stat->nid_exp_ref_count, 1);
1985 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
1986 nid, &new_stat->nid_hash);
1987 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
1988 old_stat, libcfs_nid2str(*nid),
1989 cfs_atomic_read(&new_stat->nid_exp_ref_count));
1991 /* We need to release old stats because lprocfs_exp_cleanup() hasn't
1992 * been and will never be called. */
1993 if (exp->exp_nid_stats) {
1994 nidstat_putref(exp->exp_nid_stats);
1995 exp->exp_nid_stats = NULL;
1998 /* Return -EALREADY here so that we know that the /proc
1999 * entry already has been created */
2000 if (old_stat != new_stat) {
2001 exp->exp_nid_stats = old_stat;
2002 GOTO(destroy_new, rc = -EALREADY);
2004 /* not found - create */
2005 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
2007 GOTO(destroy_new, rc = -ENOMEM);
2009 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
2010 new_stat->nid_proc = lprocfs_register(buffer,
2011 obd->obd_proc_exports_entry,
2013 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
2015 if (IS_ERR(new_stat->nid_proc)) {
2016 rc = PTR_ERR(new_stat->nid_proc);
2017 new_stat->nid_proc = NULL;
2018 CERROR("%s: cannot create proc entry for export %s: rc = %d\n",
2019 obd->obd_name, libcfs_nid2str(*nid), rc);
2020 GOTO(destroy_new_ns, rc);
2023 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
2024 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
2025 if (IS_ERR(entry)) {
2026 CWARN("Error adding the NID stats file\n");
2027 rc = PTR_ERR(entry);
2028 GOTO(destroy_new_ns, rc);
2031 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
2032 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
2033 if (IS_ERR(entry)) {
2034 CWARN("Error adding the hash file\n");
2035 rc = PTR_ERR(entry);
2036 GOTO(destroy_new_ns, rc);
2039 exp->exp_nid_stats = new_stat;
2041 /* protect competitive add to list, not need locking on destroy */
2042 spin_lock(&obd->obd_nid_lock);
2043 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
2044 spin_unlock(&obd->obd_nid_lock);
2049 if (new_stat->nid_proc != NULL)
2050 lprocfs_remove(&new_stat->nid_proc);
2051 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
2054 nidstat_putref(new_stat);
2055 OBD_FREE_PTR(new_stat);
2058 EXPORT_SYMBOL(lprocfs_exp_setup);
2060 int lprocfs_exp_cleanup(struct obd_export *exp)
2062 struct nid_stat *stat = exp->exp_nid_stats;
2064 if(!stat || !exp->exp_obd)
2067 nidstat_putref(exp->exp_nid_stats);
2068 exp->exp_nid_stats = NULL;
2072 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2074 int lprocfs_write_helper(const char *buffer, unsigned long count,
2077 return lprocfs_write_frac_helper(buffer, count, val, 1);
2079 EXPORT_SYMBOL(lprocfs_write_helper);
2081 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
2084 char kernbuf[20], *end, *pbuf;
2086 if (count > (sizeof(kernbuf) - 1))
2089 if (copy_from_user(kernbuf, buffer, count))
2092 kernbuf[count] = '\0';
2099 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2103 if (end != NULL && *end == '.') {
2104 int temp_val, pow = 1;
2108 if (strlen(pbuf) > 5)
2109 pbuf[5] = '\0'; /*only allow 5bits fractional*/
2111 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2114 for (i = 0; i < (end - pbuf); i++)
2117 *val += temp_val / pow;
2122 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2124 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
2127 long decimal_val, frac_val;
2133 decimal_val = val / mult;
2134 prtn = snprintf(buffer, count, "%ld", decimal_val);
2135 frac_val = val % mult;
2137 if (prtn < (count - 4) && frac_val > 0) {
2139 int i, temp_mult = 1, frac_bits = 0;
2141 temp_frac = frac_val * 10;
2142 buffer[prtn++] = '.';
2143 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
2144 /* only reserved 2 bits fraction */
2145 buffer[prtn++] ='0';
2150 * Need to think these cases :
2151 * 1. #echo x.00 > /proc/xxx output result : x
2152 * 2. #echo x.0x > /proc/xxx output result : x.0x
2153 * 3. #echo x.x0 > /proc/xxx output result : x.x
2154 * 4. #echo x.xx > /proc/xxx output result : x.xx
2155 * Only reserved 2 bits fraction.
2157 for (i = 0; i < (5 - prtn); i++)
2160 frac_bits = min((int)count - prtn, 3 - frac_bits);
2161 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
2162 frac_val * temp_mult / mult);
2165 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
2167 if (buffer[prtn] == '.') {
2174 buffer[prtn++] ='\n';
2177 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2179 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
2181 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
2183 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2185 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
2186 __u64 *val, int mult)
2188 char kernbuf[22], *end, *pbuf;
2189 __u64 whole, frac = 0, units;
2190 unsigned frac_d = 1;
2192 if (count > (sizeof(kernbuf) - 1))
2195 if (copy_from_user(kernbuf, buffer, count))
2198 kernbuf[count] = '\0';
2205 whole = simple_strtoull(pbuf, &end, 10);
2209 if (end != NULL && *end == '.') {
2213 /* need to limit frac_d to a __u32 */
2214 if (strlen(pbuf) > 10)
2217 frac = simple_strtoull(pbuf, &end, 10);
2218 /* count decimal places */
2219 for (i = 0; i < (end - pbuf); i++)
2236 /* Specified units override the multiplier */
2238 mult = mult < 0 ? -units : units;
2241 do_div(frac, frac_d);
2242 *val = whole * mult + frac;
2245 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2247 static char *lprocfs_strnstr(const char *s1, const char *s2, size_t len)
2256 if (!memcmp(s1, s2, l2))
2264 * Find the string \a name in the input \a buffer, and return a pointer to the
2265 * value immediately following \a name, reducing \a count appropriately.
2266 * If \a name is not found the original \a buffer is returned.
2268 char *lprocfs_find_named_value(const char *buffer, const char *name,
2269 unsigned long *count)
2272 size_t buflen = *count;
2274 /* there is no strnstr() in rhel5 and ubuntu kernels */
2275 val = lprocfs_strnstr(buffer, name, buflen);
2277 return (char *)buffer;
2279 val += strlen(name); /* skip prefix */
2280 while (val < buffer + buflen && isspace(*val)) /* skip separator */
2284 while (val < buffer + buflen && isalnum(*val)) {
2289 return val - *count;
2291 EXPORT_SYMBOL(lprocfs_find_named_value);
2293 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent,
2296 const struct file_operations *seq_fops,
2299 struct proc_dir_entry *entry;
2302 /* Disallow secretly (un)writable entries. */
2303 LASSERT((seq_fops->write == NULL) == ((mode & 0222) == 0));
2305 LPROCFS_WRITE_ENTRY();
2306 entry = create_proc_entry(name, mode, parent);
2308 entry->proc_fops = seq_fops;
2311 LPROCFS_WRITE_EXIT();
2318 EXPORT_SYMBOL(lprocfs_seq_create);
2320 int lprocfs_obd_seq_create(struct obd_device *dev,
2323 const struct file_operations *seq_fops,
2326 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2327 mode, seq_fops, data));
2329 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2331 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2333 if (value >= OBD_HIST_MAX)
2334 value = OBD_HIST_MAX - 1;
2336 spin_lock(&oh->oh_lock);
2337 oh->oh_buckets[value]++;
2338 spin_unlock(&oh->oh_lock);
2340 EXPORT_SYMBOL(lprocfs_oh_tally);
2342 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2346 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2349 lprocfs_oh_tally(oh, val);
2351 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2353 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2355 unsigned long ret = 0;
2358 for (i = 0; i < OBD_HIST_MAX; i++)
2359 ret += oh->oh_buckets[i];
2362 EXPORT_SYMBOL(lprocfs_oh_sum);
2364 void lprocfs_oh_clear(struct obd_histogram *oh)
2366 spin_lock(&oh->oh_lock);
2367 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2368 spin_unlock(&oh->oh_lock);
2370 EXPORT_SYMBOL(lprocfs_oh_clear);
2372 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2373 int count, int *eof, void *data)
2375 struct obd_device *obd = data;
2381 c += cfs_hash_debug_header(page, count);
2382 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2383 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2384 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2388 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2390 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2391 int count, int *eof, void *data)
2393 struct obd_device *obd = data;
2396 LASSERT(obd != NULL);
2397 LASSERT(count >= 0);
2399 /* Set start of user data returned to
2400 page + off since the user may have
2401 requested to read much smaller than
2402 what we need to read */
2403 *start = page + off;
2406 * We know we are allocated a page here.
2407 * Also we know that this function will
2408 * not need to write more than a page
2409 * so we can truncate at PAGE_CACHE_SIZE.
2411 size = min(count + (int)off + 1, (int)PAGE_CACHE_SIZE);
2413 /* Initialize the page */
2414 memset(page, 0, size);
2416 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2418 if (obd->obd_max_recoverable_clients == 0) {
2419 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2425 /* sampled unlocked, but really... */
2426 if (obd->obd_recovering == 0) {
2427 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2429 if (lprocfs_obd_snprintf(&page, size, &len,
2430 "recovery_start: %lu\n",
2431 obd->obd_recovery_start) <= 0)
2433 if (lprocfs_obd_snprintf(&page, size, &len,
2434 "recovery_duration: %lu\n",
2435 obd->obd_recovery_end -
2436 obd->obd_recovery_start) <= 0)
2438 /* Number of clients that have completed recovery */
2439 if (lprocfs_obd_snprintf(&page, size, &len,
2440 "completed_clients: %d/%d\n",
2441 obd->obd_max_recoverable_clients -
2442 obd->obd_stale_clients,
2443 obd->obd_max_recoverable_clients) <= 0)
2445 if (lprocfs_obd_snprintf(&page, size, &len,
2446 "replayed_requests: %d\n",
2447 obd->obd_replayed_requests) <= 0)
2449 if (lprocfs_obd_snprintf(&page, size, &len,
2450 "last_transno: "LPD64"\n",
2451 obd->obd_next_recovery_transno - 1)<=0)
2453 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2454 obd->obd_version_recov ?
2455 "ENABLED" : "DISABLED") <=0)
2457 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
2459 "DISABLED" : "ENABLED") <= 0)
2464 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2466 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2467 obd->obd_recovery_start) <= 0)
2469 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2470 cfs_time_current_sec() >=
2471 obd->obd_recovery_start +
2472 obd->obd_recovery_timeout ? 0 :
2473 obd->obd_recovery_start +
2474 obd->obd_recovery_timeout -
2475 cfs_time_current_sec()) <= 0)
2477 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2478 cfs_atomic_read(&obd->obd_connected_clients),
2479 obd->obd_max_recoverable_clients) <= 0)
2481 /* Number of clients that have completed recovery */
2482 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2483 cfs_atomic_read(&obd->obd_req_replay_clients))
2486 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2487 cfs_atomic_read(&obd->obd_lock_replay_clients))
2490 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2491 cfs_atomic_read(&obd->obd_connected_clients) -
2492 cfs_atomic_read(&obd->obd_lock_replay_clients))
2495 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2496 obd->obd_stale_clients) <= 0)
2498 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2499 obd->obd_replayed_requests) <= 0)
2501 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2502 obd->obd_requests_queued_for_recovery) <= 0)
2505 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2506 obd->obd_next_recovery_transno) <= 0)
2512 return min(count, len - (int)off);
2514 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2516 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
2517 int count, int *eof, void *data)
2519 struct obd_device *obd = (struct obd_device *)data;
2520 LASSERT(obd != NULL);
2522 return snprintf(page, count, "%d\n",
2523 obd->obd_recovery_ir_factor);
2525 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
2527 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
2528 unsigned long count, void *data)
2530 struct obd_device *obd = (struct obd_device *)data;
2532 LASSERT(obd != NULL);
2534 rc = lprocfs_write_helper(buffer, count, &val);
2538 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
2541 obd->obd_recovery_ir_factor = val;
2544 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
2546 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
2547 int count, int *eof, void *data)
2549 struct obd_device *obd = (struct obd_device *)data;
2550 LASSERT(obd != NULL);
2552 return snprintf(page, count, "%d\n",
2553 obd->obd_recovery_timeout);
2555 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
2557 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
2558 unsigned long count, void *data)
2560 struct obd_device *obd = (struct obd_device *)data;
2562 LASSERT(obd != NULL);
2564 rc = lprocfs_write_helper(buffer, count, &val);
2568 obd->obd_recovery_timeout = val;
2571 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
2573 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
2574 int count, int *eof, void *data)
2576 struct obd_device *obd = data;
2577 LASSERT(obd != NULL);
2579 return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
2581 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
2583 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
2584 unsigned long count, void *data)
2586 struct obd_device *obd = data;
2588 LASSERT(obd != NULL);
2590 rc = lprocfs_write_helper(buffer, count, &val);
2594 obd->obd_recovery_time_hard = val;
2597 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
2599 int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
2600 int count, int *eof, void *data)
2602 struct obd_device *dev = data;
2603 struct client_obd *cli = &dev->u.cli;
2606 client_obd_list_lock(&cli->cl_loi_list_lock);
2607 rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
2608 client_obd_list_unlock(&cli->cl_loi_list_lock);
2611 EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
2613 #ifdef HAVE_SERVER_SUPPORT
2614 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
2615 int count, int *eof, void *data)
2617 struct obd_device *obd = (struct obd_device *)data;
2618 struct obd_device_target *target = &obd->u.obt;
2620 LASSERT(obd != NULL);
2621 LASSERT(target->obt_magic == OBT_MAGIC);
2623 return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
2625 EXPORT_SYMBOL(lprocfs_target_rd_instance);