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 wake_up(&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",
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 = 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 = 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;
1358 unsigned int num_entry;
1359 unsigned long flags = 0;
1361 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1363 for (i = 0; i < num_entry; i++) {
1364 if (stats->ls_percpu[i] == NULL)
1366 for (j = 0; j < stats->ls_num; j++) {
1367 percpu_cntr = lprocfs_stats_counter_get(stats, i, j);
1368 percpu_cntr->lc_count = 0;
1369 percpu_cntr->lc_min = LC_MIN_INIT;
1370 percpu_cntr->lc_max = 0;
1371 percpu_cntr->lc_sumsquare = 0;
1372 percpu_cntr->lc_sum = 0;
1373 if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
1374 percpu_cntr->lc_sum_irq = 0;
1378 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1380 EXPORT_SYMBOL(lprocfs_clear_stats);
1382 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1383 size_t len, loff_t *off)
1385 struct seq_file *seq = file->private_data;
1386 struct lprocfs_stats *stats = seq->private;
1388 lprocfs_clear_stats(stats);
1393 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1395 struct lprocfs_stats *stats = p->private;
1397 return (*pos < stats->ls_num) ? pos : NULL;
1400 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1404 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1408 return lprocfs_stats_seq_start(p, pos);
1411 /* seq file export of one lprocfs counter */
1412 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1414 struct lprocfs_stats *stats = p->private;
1415 struct lprocfs_counter_header *hdr;
1416 struct lprocfs_counter ctr;
1417 int idx = *(loff_t *)v;
1423 do_gettimeofday(&now);
1424 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1425 "snapshot_time", now.tv_sec, now.tv_usec);
1430 hdr = &stats->ls_cnt_header[idx];
1431 lprocfs_stats_collect(stats, idx, &ctr);
1433 if (ctr.lc_count == 0)
1436 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", hdr->lc_name,
1437 ctr.lc_count, hdr->lc_units);
1441 if ((hdr->lc_config & LPROCFS_CNTR_AVGMINMAX) && ctr.lc_count > 0) {
1442 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1443 ctr.lc_min, ctr.lc_max, ctr.lc_sum);
1446 if (hdr->lc_config & LPROCFS_CNTR_STDDEV)
1447 rc = seq_printf(p, " "LPD64, ctr.lc_sumsquare);
1451 rc = seq_printf(p, "\n");
1453 return (rc < 0) ? rc : 0;
1456 struct seq_operations lprocfs_stats_seq_sops = {
1457 .start = lprocfs_stats_seq_start,
1458 .stop = lprocfs_stats_seq_stop,
1459 .next = lprocfs_stats_seq_next,
1460 .show = lprocfs_stats_seq_show,
1463 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1465 struct proc_dir_entry *dp = PDE(inode);
1466 struct seq_file *seq;
1469 if (LPROCFS_ENTRY_CHECK(dp))
1472 rc = seq_open(file, &lprocfs_stats_seq_sops);
1475 seq = file->private_data;
1476 seq->private = dp->data;
1480 struct file_operations lprocfs_stats_seq_fops = {
1481 .owner = THIS_MODULE,
1482 .open = lprocfs_stats_seq_open,
1484 .write = lprocfs_stats_seq_write,
1485 .llseek = seq_lseek,
1486 .release = lprocfs_seq_release,
1489 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1490 struct lprocfs_stats *stats)
1492 struct proc_dir_entry *entry;
1493 LASSERT(root != NULL);
1495 LPROCFS_WRITE_ENTRY();
1496 entry = create_proc_entry(name, 0644, root);
1498 entry->proc_fops = &lprocfs_stats_seq_fops;
1499 entry->data = stats;
1502 LPROCFS_WRITE_EXIT();
1509 EXPORT_SYMBOL(lprocfs_register_stats);
1511 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1512 unsigned conf, const char *name, const char *units)
1514 struct lprocfs_counter_header *header;
1515 struct lprocfs_counter *percpu_cntr;
1516 unsigned long flags = 0;
1518 unsigned int num_cpu;
1520 LASSERT(stats != NULL);
1522 header = &stats->ls_cnt_header[index];
1523 LASSERTF(header != NULL, "Failed to allocate stats header:[%d]%s/%s\n",
1524 index, name, units);
1526 header->lc_config = conf;
1527 header->lc_name = name;
1528 header->lc_units = units;
1530 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1531 for (i = 0; i < num_cpu; ++i) {
1532 if (stats->ls_percpu[i] == NULL)
1534 percpu_cntr = lprocfs_stats_counter_get(stats, i, index);
1535 percpu_cntr->lc_count = 0;
1536 percpu_cntr->lc_min = LC_MIN_INIT;
1537 percpu_cntr->lc_max = 0;
1538 percpu_cntr->lc_sumsquare = 0;
1539 percpu_cntr->lc_sum = 0;
1540 if ((stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
1541 percpu_cntr->lc_sum_irq = 0;
1543 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1545 EXPORT_SYMBOL(lprocfs_counter_init);
1547 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1549 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1550 LASSERT(coffset < stats->ls_num); \
1551 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1554 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1556 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1557 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1558 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1559 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1560 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1561 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1562 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1563 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1564 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1565 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1566 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1567 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1568 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1569 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1570 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1571 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1572 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1573 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1574 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1575 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1576 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1577 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1578 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1579 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1580 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1581 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1582 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1583 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1584 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1585 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1586 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1587 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1588 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1589 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1590 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1591 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1592 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1593 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1594 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1595 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1596 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1597 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1598 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1599 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
1600 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1601 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1602 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1603 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1604 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1605 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1606 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1607 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1608 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1609 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1610 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1611 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1612 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1613 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1614 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1615 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1616 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1617 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1618 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1619 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1620 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1621 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1622 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1624 CLASSERT(NUM_OBD_STATS == OBD_COUNTER_OFFSET(putref) + 1);
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 = NUM_OBD_STATS + num_private_stats;
1639 stats = lprocfs_alloc_stats(num_stats, 0);
1643 lprocfs_init_ops_stats(num_private_stats, stats);
1645 for (i = num_private_stats; i < num_stats; i++) {
1646 /* If this LBUGs, it is likely that an obd
1647 * operation was added to struct obd_ops in
1648 * <obd.h>, and that the corresponding line item
1649 * LPROCFS_OBD_OP_INIT(.., .., opname)
1650 * is missing from the list above. */
1651 LASSERTF(stats->ls_cnt_header[i].lc_name != NULL,
1652 "Missing obd_stat initializer obd_op "
1653 "operation at offset %d.\n", i - num_private_stats);
1655 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1657 lprocfs_free_stats(&stats);
1659 obd->obd_stats = stats;
1660 obd->obd_cntr_base = num_private_stats;
1664 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
1666 void lprocfs_free_obd_stats(struct obd_device *obd)
1669 lprocfs_free_stats(&obd->obd_stats);
1671 EXPORT_SYMBOL(lprocfs_free_obd_stats);
1673 /* Note that we only init md counters for ops whose offset is less
1674 * than NUM_MD_STATS. This is explained in a comment in the definition
1675 * of struct md_ops. */
1676 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1678 unsigned int _idx = base + MD_COUNTER_OFFSET(op); \
1680 if (MD_COUNTER_OFFSET(op) < NUM_MD_STATS) { \
1681 LASSERT(_idx < stats->ls_num); \
1682 lprocfs_counter_init(stats, _idx, 0, #op, "reqs"); \
1686 void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats)
1688 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1689 LPROCFS_MD_OP_INIT(num_private_stats, stats, null_inode);
1690 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
1691 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1692 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1693 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1694 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1695 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1696 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1697 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1698 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1699 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1700 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1701 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1702 LPROCFS_MD_OP_INIT(num_private_stats, stats, fsync);
1703 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1704 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1705 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1706 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1707 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1708 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1709 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1710 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1711 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1712 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1713 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1714 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1715 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1716 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1717 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1718 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1719 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1721 EXPORT_SYMBOL(lprocfs_init_mps_stats);
1723 int lprocfs_alloc_md_stats(struct obd_device *obd,
1724 unsigned int num_private_stats)
1726 struct lprocfs_stats *stats;
1727 unsigned int num_stats;
1730 CLASSERT(offsetof(struct md_ops, MD_STATS_FIRST_OP) == 0);
1731 CLASSERT(_MD_COUNTER_OFFSET(MD_STATS_FIRST_OP) == 0);
1732 CLASSERT(_MD_COUNTER_OFFSET(MD_STATS_LAST_OP) > 0);
1734 /* TODO Ensure that this function is only used where
1735 * appropriate by adding an assertion to the effect that
1736 * obd->obd_type->typ_md_ops is not NULL. We can't do this now
1737 * because mdt_procfs_init() uses this function to allocate
1738 * the stats backing /proc/fs/lustre/mdt/.../md_stats but the
1739 * mdt layer does not use the md_ops interface. This is
1740 * confusing and a waste of memory. See LU-2484.
1742 LASSERT(obd->obd_proc_entry != NULL);
1743 LASSERT(obd->obd_md_stats == NULL);
1744 LASSERT(obd->obd_md_cntr_base == 0);
1746 num_stats = NUM_MD_STATS + num_private_stats;
1747 stats = lprocfs_alloc_stats(num_stats, 0);
1751 lprocfs_init_mps_stats(num_private_stats, stats);
1753 for (i = num_private_stats; i < num_stats; i++) {
1754 if (stats->ls_cnt_header[i].lc_name == NULL) {
1755 CERROR("Missing md_stat initializer md_op "
1756 "operation at offset %d. Aborting.\n",
1757 i - num_private_stats);
1762 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1764 lprocfs_free_stats(&stats);
1766 obd->obd_md_stats = stats;
1767 obd->obd_md_cntr_base = num_private_stats;
1772 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
1774 void lprocfs_free_md_stats(struct obd_device *obd)
1776 struct lprocfs_stats *stats = obd->obd_md_stats;
1778 if (stats != NULL) {
1779 obd->obd_md_stats = NULL;
1780 obd->obd_md_cntr_base = 0;
1781 lprocfs_free_stats(&stats);
1784 EXPORT_SYMBOL(lprocfs_free_md_stats);
1786 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1788 lprocfs_counter_init(ldlm_stats,
1789 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1790 0, "ldlm_enqueue", "reqs");
1791 lprocfs_counter_init(ldlm_stats,
1792 LDLM_CONVERT - LDLM_FIRST_OPC,
1793 0, "ldlm_convert", "reqs");
1794 lprocfs_counter_init(ldlm_stats,
1795 LDLM_CANCEL - LDLM_FIRST_OPC,
1796 0, "ldlm_cancel", "reqs");
1797 lprocfs_counter_init(ldlm_stats,
1798 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1799 0, "ldlm_bl_callback", "reqs");
1800 lprocfs_counter_init(ldlm_stats,
1801 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1802 0, "ldlm_cp_callback", "reqs");
1803 lprocfs_counter_init(ldlm_stats,
1804 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1805 0, "ldlm_gl_callback", "reqs");
1807 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
1809 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1810 int *eof, void *data)
1812 struct obd_export *exp = data;
1813 LASSERT(exp != NULL);
1815 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1818 struct exp_uuid_cb_data {
1826 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1827 int count, int *eof, int *len)
1829 cb_data->page = page;
1830 cb_data->count = count;
1835 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1836 cfs_hlist_node_t *hnode, void *cb_data)
1839 struct obd_export *exp = cfs_hash_object(hs, hnode);
1840 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1842 if (exp->exp_nid_stats)
1843 *data->len += snprintf((data->page + *data->len),
1844 data->count, "%s\n",
1845 obd_uuid2str(&exp->exp_client_uuid));
1849 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1850 int *eof, void *data)
1852 struct nid_stat *stats = (struct nid_stat *)data;
1853 struct exp_uuid_cb_data cb_data;
1854 struct obd_device *obd = stats->nid_obd;
1859 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1860 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1861 lprocfs_exp_print_uuid, &cb_data);
1862 return (*cb_data.len);
1865 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1866 cfs_hlist_node_t *hnode, void *cb_data)
1869 struct exp_uuid_cb_data *data = cb_data;
1870 struct obd_export *exp = cfs_hash_object(hs, hnode);
1872 if (exp->exp_lock_hash != NULL) {
1874 *data->len += cfs_hash_debug_header(data->page,
1877 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1884 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1885 int *eof, void *data)
1887 struct nid_stat *stats = (struct nid_stat *)data;
1888 struct exp_uuid_cb_data cb_data;
1889 struct obd_device *obd = stats->nid_obd;
1894 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1896 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1897 lprocfs_exp_print_hash, &cb_data);
1898 return (*cb_data.len);
1901 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1902 int count, int *eof, void *data)
1905 return snprintf(page, count, "%s\n",
1906 "Write into this file to clear all nid stats and "
1907 "stale nid entries");
1909 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1911 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1913 struct nid_stat *stat = obj;
1916 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
1917 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 1) {
1918 /* object has only hash references. */
1919 spin_lock(&stat->nid_obd->obd_nid_lock);
1920 cfs_list_move(&stat->nid_list, data);
1921 spin_unlock(&stat->nid_obd->obd_nid_lock);
1924 /* we has reference to object - only clear data*/
1925 if (stat->nid_stats)
1926 lprocfs_clear_stats(stat->nid_stats);
1931 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1932 unsigned long count, void *data)
1934 struct obd_device *obd = (struct obd_device *)data;
1935 struct nid_stat *client_stat;
1936 CFS_LIST_HEAD(free_list);
1938 cfs_hash_cond_del(obd->obd_nid_stats_hash,
1939 lprocfs_nid_stats_clear_write_cb, &free_list);
1941 while (!cfs_list_empty(&free_list)) {
1942 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
1944 cfs_list_del_init(&client_stat->nid_list);
1945 lprocfs_free_client_stats(client_stat);
1950 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1952 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1954 struct nid_stat *new_stat, *old_stat;
1955 struct obd_device *obd = NULL;
1956 cfs_proc_dir_entry_t *entry;
1957 char *buffer = NULL;
1963 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1964 !exp->exp_obd->obd_nid_stats_hash)
1967 /* not test against zero because eric say:
1968 * You may only test nid against another nid, or LNET_NID_ANY.
1969 * Anything else is nonsense.*/
1970 if (!nid || *nid == LNET_NID_ANY)
1973 spin_lock(&exp->exp_lock);
1974 if (exp->exp_nid_stats != NULL) {
1975 spin_unlock(&exp->exp_lock);
1978 spin_unlock(&exp->exp_lock);
1982 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
1984 OBD_ALLOC_PTR(new_stat);
1985 if (new_stat == NULL)
1988 new_stat->nid = *nid;
1989 new_stat->nid_obd = exp->exp_obd;
1990 /* we need set default refcount to 1 to balance obd_disconnect */
1991 cfs_atomic_set(&new_stat->nid_exp_ref_count, 1);
1993 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
1994 nid, &new_stat->nid_hash);
1995 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
1996 old_stat, libcfs_nid2str(*nid),
1997 cfs_atomic_read(&new_stat->nid_exp_ref_count));
1999 /* Return -EALREADY here so that we know that the /proc
2000 * entry already has been created */
2001 if (old_stat != new_stat) {
2002 nidstat_putref(old_stat);
2003 GOTO(destroy_new, rc = -EALREADY);
2005 /* not found - create */
2006 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
2008 GOTO(destroy_new, rc = -ENOMEM);
2010 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
2011 new_stat->nid_proc = lprocfs_register(buffer,
2012 obd->obd_proc_exports_entry,
2014 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
2016 if (IS_ERR(new_stat->nid_proc)) {
2017 rc = PTR_ERR(new_stat->nid_proc);
2018 new_stat->nid_proc = NULL;
2019 CERROR("%s: cannot create proc entry for export %s: rc = %d\n",
2020 obd->obd_name, libcfs_nid2str(*nid), rc);
2021 GOTO(destroy_new_ns, rc);
2024 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
2025 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
2026 if (IS_ERR(entry)) {
2027 CWARN("Error adding the NID stats file\n");
2028 rc = PTR_ERR(entry);
2029 GOTO(destroy_new_ns, rc);
2032 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
2033 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
2034 if (IS_ERR(entry)) {
2035 CWARN("Error adding the hash file\n");
2036 rc = PTR_ERR(entry);
2037 GOTO(destroy_new_ns, rc);
2040 spin_lock(&exp->exp_lock);
2041 exp->exp_nid_stats = new_stat;
2042 spin_unlock(&exp->exp_lock);
2044 /* protect competitive add to list, not need locking on destroy */
2045 spin_lock(&obd->obd_nid_lock);
2046 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
2047 spin_unlock(&obd->obd_nid_lock);
2052 if (new_stat->nid_proc != NULL)
2053 lprocfs_remove(&new_stat->nid_proc);
2054 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
2057 nidstat_putref(new_stat);
2058 OBD_FREE_PTR(new_stat);
2061 EXPORT_SYMBOL(lprocfs_exp_setup);
2063 int lprocfs_exp_cleanup(struct obd_export *exp)
2065 struct nid_stat *stat = exp->exp_nid_stats;
2067 if(!stat || !exp->exp_obd)
2070 nidstat_putref(exp->exp_nid_stats);
2071 exp->exp_nid_stats = NULL;
2075 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2077 int lprocfs_write_helper(const char *buffer, unsigned long count,
2080 return lprocfs_write_frac_helper(buffer, count, val, 1);
2082 EXPORT_SYMBOL(lprocfs_write_helper);
2084 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
2087 char kernbuf[20], *end, *pbuf;
2089 if (count > (sizeof(kernbuf) - 1))
2092 if (copy_from_user(kernbuf, buffer, count))
2095 kernbuf[count] = '\0';
2102 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2106 if (end != NULL && *end == '.') {
2107 int temp_val, pow = 1;
2111 if (strlen(pbuf) > 5)
2112 pbuf[5] = '\0'; /*only allow 5bits fractional*/
2114 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2117 for (i = 0; i < (end - pbuf); i++)
2120 *val += temp_val / pow;
2125 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2127 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
2130 long decimal_val, frac_val;
2136 decimal_val = val / mult;
2137 prtn = snprintf(buffer, count, "%ld", decimal_val);
2138 frac_val = val % mult;
2140 if (prtn < (count - 4) && frac_val > 0) {
2142 int i, temp_mult = 1, frac_bits = 0;
2144 temp_frac = frac_val * 10;
2145 buffer[prtn++] = '.';
2146 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
2147 /* only reserved 2 bits fraction */
2148 buffer[prtn++] ='0';
2153 * Need to think these cases :
2154 * 1. #echo x.00 > /proc/xxx output result : x
2155 * 2. #echo x.0x > /proc/xxx output result : x.0x
2156 * 3. #echo x.x0 > /proc/xxx output result : x.x
2157 * 4. #echo x.xx > /proc/xxx output result : x.xx
2158 * Only reserved 2 bits fraction.
2160 for (i = 0; i < (5 - prtn); i++)
2163 frac_bits = min((int)count - prtn, 3 - frac_bits);
2164 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
2165 frac_val * temp_mult / mult);
2168 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
2170 if (buffer[prtn] == '.') {
2177 buffer[prtn++] ='\n';
2180 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2182 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
2184 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
2186 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2188 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
2189 __u64 *val, int mult)
2191 char kernbuf[22], *end, *pbuf;
2192 __u64 whole, frac = 0, units;
2193 unsigned frac_d = 1;
2195 if (count > (sizeof(kernbuf) - 1))
2198 if (copy_from_user(kernbuf, buffer, count))
2201 kernbuf[count] = '\0';
2208 whole = simple_strtoull(pbuf, &end, 10);
2212 if (end != NULL && *end == '.') {
2216 /* need to limit frac_d to a __u32 */
2217 if (strlen(pbuf) > 10)
2220 frac = simple_strtoull(pbuf, &end, 10);
2221 /* count decimal places */
2222 for (i = 0; i < (end - pbuf); i++)
2241 /* Specified units override the multiplier */
2243 mult = mult < 0 ? -units : units;
2246 do_div(frac, frac_d);
2247 *val = whole * mult + frac;
2250 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2252 static char *lprocfs_strnstr(const char *s1, const char *s2, size_t len)
2261 if (!memcmp(s1, s2, l2))
2269 * Find the string \a name in the input \a buffer, and return a pointer to the
2270 * value immediately following \a name, reducing \a count appropriately.
2271 * If \a name is not found the original \a buffer is returned.
2273 char *lprocfs_find_named_value(const char *buffer, const char *name,
2274 unsigned long *count)
2277 size_t buflen = *count;
2279 /* there is no strnstr() in rhel5 and ubuntu kernels */
2280 val = lprocfs_strnstr(buffer, name, buflen);
2282 return (char *)buffer;
2284 val += strlen(name); /* skip prefix */
2285 while (val < buffer + buflen && isspace(*val)) /* skip separator */
2289 while (val < buffer + buflen && isalnum(*val)) {
2294 return val - *count;
2296 EXPORT_SYMBOL(lprocfs_find_named_value);
2298 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent,
2301 const struct file_operations *seq_fops,
2304 struct proc_dir_entry *entry;
2307 /* Disallow secretly (un)writable entries. */
2308 LASSERT((seq_fops->write == NULL) == ((mode & 0222) == 0));
2310 LPROCFS_WRITE_ENTRY();
2311 entry = create_proc_entry(name, mode, parent);
2313 entry->proc_fops = seq_fops;
2316 LPROCFS_WRITE_EXIT();
2323 EXPORT_SYMBOL(lprocfs_seq_create);
2325 int lprocfs_obd_seq_create(struct obd_device *dev,
2328 const struct file_operations *seq_fops,
2331 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2332 mode, seq_fops, data));
2334 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2336 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2338 if (value >= OBD_HIST_MAX)
2339 value = OBD_HIST_MAX - 1;
2341 spin_lock(&oh->oh_lock);
2342 oh->oh_buckets[value]++;
2343 spin_unlock(&oh->oh_lock);
2345 EXPORT_SYMBOL(lprocfs_oh_tally);
2347 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2349 unsigned int val = 0;
2351 if (likely(value != 0))
2352 val = min(fls(value - 1), OBD_HIST_MAX);
2354 lprocfs_oh_tally(oh, val);
2356 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2358 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2360 unsigned long ret = 0;
2363 for (i = 0; i < OBD_HIST_MAX; i++)
2364 ret += oh->oh_buckets[i];
2367 EXPORT_SYMBOL(lprocfs_oh_sum);
2369 void lprocfs_oh_clear(struct obd_histogram *oh)
2371 spin_lock(&oh->oh_lock);
2372 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2373 spin_unlock(&oh->oh_lock);
2375 EXPORT_SYMBOL(lprocfs_oh_clear);
2377 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2378 int count, int *eof, void *data)
2380 struct obd_device *obd = data;
2386 c += cfs_hash_debug_header(page, count);
2387 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2388 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2389 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2393 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2395 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2396 int count, int *eof, void *data)
2398 struct obd_device *obd = data;
2401 LASSERT(obd != NULL);
2402 LASSERT(count >= 0);
2404 /* Set start of user data returned to
2405 page + off since the user may have
2406 requested to read much smaller than
2407 what we need to read */
2408 *start = page + off;
2411 * We know we are allocated a page here.
2412 * Also we know that this function will
2413 * not need to write more than a page
2414 * so we can truncate at PAGE_CACHE_SIZE.
2416 size = min(count + (int)off + 1, (int)PAGE_CACHE_SIZE);
2418 /* Initialize the page */
2419 memset(page, 0, size);
2421 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2423 if (obd->obd_max_recoverable_clients == 0) {
2424 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2430 /* sampled unlocked, but really... */
2431 if (obd->obd_recovering == 0) {
2432 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2434 if (lprocfs_obd_snprintf(&page, size, &len,
2435 "recovery_start: %lu\n",
2436 obd->obd_recovery_start) <= 0)
2438 if (lprocfs_obd_snprintf(&page, size, &len,
2439 "recovery_duration: %lu\n",
2440 obd->obd_recovery_end -
2441 obd->obd_recovery_start) <= 0)
2443 /* Number of clients that have completed recovery */
2444 if (lprocfs_obd_snprintf(&page, size, &len,
2445 "completed_clients: %d/%d\n",
2446 obd->obd_max_recoverable_clients -
2447 obd->obd_stale_clients,
2448 obd->obd_max_recoverable_clients) <= 0)
2450 if (lprocfs_obd_snprintf(&page, size, &len,
2451 "replayed_requests: %d\n",
2452 obd->obd_replayed_requests) <= 0)
2454 if (lprocfs_obd_snprintf(&page, size, &len,
2455 "last_transno: "LPD64"\n",
2456 obd->obd_next_recovery_transno - 1)<=0)
2458 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2459 obd->obd_version_recov ?
2460 "ENABLED" : "DISABLED") <=0)
2462 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
2464 "DISABLED" : "ENABLED") <= 0)
2469 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2471 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2472 obd->obd_recovery_start) <= 0)
2474 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2475 cfs_time_current_sec() >=
2476 obd->obd_recovery_start +
2477 obd->obd_recovery_timeout ? 0 :
2478 obd->obd_recovery_start +
2479 obd->obd_recovery_timeout -
2480 cfs_time_current_sec()) <= 0)
2482 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2483 cfs_atomic_read(&obd->obd_connected_clients),
2484 obd->obd_max_recoverable_clients) <= 0)
2486 /* Number of clients that have completed recovery */
2487 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2488 cfs_atomic_read(&obd->obd_req_replay_clients))
2491 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2492 cfs_atomic_read(&obd->obd_lock_replay_clients))
2495 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2496 cfs_atomic_read(&obd->obd_connected_clients) -
2497 cfs_atomic_read(&obd->obd_lock_replay_clients))
2500 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2501 obd->obd_stale_clients) <= 0)
2503 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2504 obd->obd_replayed_requests) <= 0)
2506 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2507 obd->obd_requests_queued_for_recovery) <= 0)
2510 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2511 obd->obd_next_recovery_transno) <= 0)
2517 return min(count, len - (int)off);
2519 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2521 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
2522 int count, int *eof, void *data)
2524 struct obd_device *obd = (struct obd_device *)data;
2525 LASSERT(obd != NULL);
2527 return snprintf(page, count, "%d\n",
2528 obd->obd_recovery_ir_factor);
2530 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
2532 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
2533 unsigned long count, void *data)
2535 struct obd_device *obd = (struct obd_device *)data;
2537 LASSERT(obd != NULL);
2539 rc = lprocfs_write_helper(buffer, count, &val);
2543 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
2546 obd->obd_recovery_ir_factor = val;
2549 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
2551 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
2552 int count, int *eof, void *data)
2554 struct obd_device *obd = (struct obd_device *)data;
2555 LASSERT(obd != NULL);
2557 return snprintf(page, count, "%d\n",
2558 obd->obd_recovery_timeout);
2560 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
2562 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
2563 unsigned long count, void *data)
2565 struct obd_device *obd = (struct obd_device *)data;
2567 LASSERT(obd != NULL);
2569 rc = lprocfs_write_helper(buffer, count, &val);
2573 obd->obd_recovery_timeout = val;
2576 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
2578 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
2579 int count, int *eof, void *data)
2581 struct obd_device *obd = data;
2582 LASSERT(obd != NULL);
2584 return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
2586 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
2588 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
2589 unsigned long count, void *data)
2591 struct obd_device *obd = data;
2593 LASSERT(obd != NULL);
2595 rc = lprocfs_write_helper(buffer, count, &val);
2599 obd->obd_recovery_time_hard = val;
2602 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
2604 int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
2605 int count, int *eof, void *data)
2607 struct obd_device *dev = data;
2608 struct client_obd *cli = &dev->u.cli;
2611 client_obd_list_lock(&cli->cl_loi_list_lock);
2612 rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
2613 client_obd_list_unlock(&cli->cl_loi_list_lock);
2616 EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
2618 #ifdef HAVE_SERVER_SUPPORT
2619 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
2620 int count, int *eof, void *data)
2622 struct obd_device *obd = (struct obd_device *)data;
2623 struct obd_device_target *target = &obd->u.obt;
2625 LASSERT(obd != NULL);
2626 LASSERT(target->obt_magic == OBT_MAGIC);
2628 return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
2630 EXPORT_SYMBOL(lprocfs_target_rd_instance);