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",
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 int lprocfs_stats_alloc_one(struct lprocfs_stats *stats, unsigned int cpuid)
1271 struct lprocfs_counter *cntr;
1272 unsigned int percpusize;
1274 unsigned long flags = 0;
1277 LASSERT(stats->ls_percpu[cpuid] == NULL);
1278 LASSERT((stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU) == 0);
1280 percpusize = lprocfs_stats_counter_size(stats);
1281 LIBCFS_ALLOC_ATOMIC(stats->ls_percpu[cpuid], percpusize);
1282 if (stats->ls_percpu[cpuid] != NULL) {
1284 if (unlikely(stats->ls_biggest_alloc_num <= cpuid)) {
1285 if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
1286 spin_lock_irqsave(&stats->ls_lock, flags);
1288 spin_lock(&stats->ls_lock);
1289 if (stats->ls_biggest_alloc_num <= cpuid)
1290 stats->ls_biggest_alloc_num = cpuid + 1;
1291 if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) {
1292 spin_unlock_irqrestore(&stats->ls_lock, flags);
1294 spin_unlock(&stats->ls_lock);
1297 /* initialize the ls_percpu[cpuid] non-zero counter */
1298 for (i = 0; i < stats->ls_num; ++i) {
1299 cntr = lprocfs_stats_counter_get(stats, cpuid, i);
1300 cntr->lc_min = LC_MIN_INIT;
1305 EXPORT_SYMBOL(lprocfs_stats_alloc_one);
1307 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1308 enum lprocfs_stats_flags flags)
1310 struct lprocfs_stats *stats;
1311 unsigned int num_entry;
1312 unsigned int percpusize = 0;
1318 if (lprocfs_no_percpu_stats != 0)
1319 flags |= LPROCFS_STATS_FLAG_NOPERCPU;
1321 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1324 num_entry = num_possible_cpus();
1326 /* alloc percpu pointers for all possible cpu slots */
1327 LIBCFS_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1331 stats->ls_num = num;
1332 stats->ls_flags = flags;
1333 spin_lock_init(&stats->ls_lock);
1335 /* alloc num of counter headers */
1336 LIBCFS_ALLOC(stats->ls_cnt_header,
1337 stats->ls_num * sizeof(struct lprocfs_counter_header));
1338 if (stats->ls_cnt_header == NULL)
1341 if ((flags & LPROCFS_STATS_FLAG_NOPERCPU) != 0) {
1342 /* contains only one set counters */
1343 percpusize = lprocfs_stats_counter_size(stats);
1344 LIBCFS_ALLOC_ATOMIC(stats->ls_percpu[0], percpusize);
1345 if (stats->ls_percpu[0] == NULL)
1347 stats->ls_biggest_alloc_num = 1;
1348 } else if ((flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0) {
1349 /* alloc all percpu data, currently only obd_memory use this */
1350 for (i = 0; i < num_entry; ++i)
1351 if (lprocfs_stats_alloc_one(stats, i) < 0)
1358 lprocfs_free_stats(&stats);
1361 EXPORT_SYMBOL(lprocfs_alloc_stats);
1363 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1365 struct lprocfs_stats *stats = *statsh;
1366 unsigned int num_entry;
1367 unsigned int percpusize;
1370 if (stats == NULL || stats->ls_num == 0)
1374 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1377 num_entry = num_possible_cpus();
1379 percpusize = lprocfs_stats_counter_size(stats);
1380 for (i = 0; i < num_entry; i++)
1381 if (stats->ls_percpu[i] != NULL)
1382 LIBCFS_FREE(stats->ls_percpu[i], percpusize);
1383 if (stats->ls_cnt_header != NULL)
1384 LIBCFS_FREE(stats->ls_cnt_header, stats->ls_num *
1385 sizeof(struct lprocfs_counter_header));
1386 LIBCFS_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1388 EXPORT_SYMBOL(lprocfs_free_stats);
1390 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1392 struct lprocfs_counter *percpu_cntr;
1395 unsigned int num_entry;
1396 unsigned long flags = 0;
1398 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1400 for (i = 0; i < num_entry; i++) {
1401 if (stats->ls_percpu[i] == NULL)
1403 for (j = 0; j < stats->ls_num; j++) {
1404 percpu_cntr = lprocfs_stats_counter_get(stats, i, j);
1405 percpu_cntr->lc_count = 0;
1406 percpu_cntr->lc_min = LC_MIN_INIT;
1407 percpu_cntr->lc_max = 0;
1408 percpu_cntr->lc_sumsquare = 0;
1409 percpu_cntr->lc_sum = 0;
1410 if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
1411 percpu_cntr->lc_sum_irq = 0;
1415 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1417 EXPORT_SYMBOL(lprocfs_clear_stats);
1419 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1420 size_t len, loff_t *off)
1422 struct seq_file *seq = file->private_data;
1423 struct lprocfs_stats *stats = seq->private;
1425 lprocfs_clear_stats(stats);
1430 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1432 struct lprocfs_stats *stats = p->private;
1434 return (*pos < stats->ls_num) ? pos : NULL;
1437 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1441 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1445 return lprocfs_stats_seq_start(p, pos);
1448 /* seq file export of one lprocfs counter */
1449 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1451 struct lprocfs_stats *stats = p->private;
1452 struct lprocfs_counter_header *hdr;
1453 struct lprocfs_counter ctr;
1454 int idx = *(loff_t *)v;
1460 do_gettimeofday(&now);
1461 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1462 "snapshot_time", now.tv_sec, now.tv_usec);
1467 hdr = &stats->ls_cnt_header[idx];
1468 lprocfs_stats_collect(stats, idx, &ctr);
1470 if (ctr.lc_count == 0)
1473 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", hdr->lc_name,
1474 ctr.lc_count, hdr->lc_units);
1478 if ((hdr->lc_config & LPROCFS_CNTR_AVGMINMAX) && ctr.lc_count > 0) {
1479 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1480 ctr.lc_min, ctr.lc_max, ctr.lc_sum);
1483 if (hdr->lc_config & LPROCFS_CNTR_STDDEV)
1484 rc = seq_printf(p, " "LPD64, ctr.lc_sumsquare);
1488 rc = seq_printf(p, "\n");
1490 return (rc < 0) ? rc : 0;
1493 struct seq_operations lprocfs_stats_seq_sops = {
1494 .start = lprocfs_stats_seq_start,
1495 .stop = lprocfs_stats_seq_stop,
1496 .next = lprocfs_stats_seq_next,
1497 .show = lprocfs_stats_seq_show,
1500 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1502 struct proc_dir_entry *dp = PDE(inode);
1503 struct seq_file *seq;
1506 if (LPROCFS_ENTRY_CHECK(dp))
1509 rc = seq_open(file, &lprocfs_stats_seq_sops);
1512 seq = file->private_data;
1513 seq->private = dp->data;
1517 struct file_operations lprocfs_stats_seq_fops = {
1518 .owner = THIS_MODULE,
1519 .open = lprocfs_stats_seq_open,
1521 .write = lprocfs_stats_seq_write,
1522 .llseek = seq_lseek,
1523 .release = lprocfs_seq_release,
1526 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1527 struct lprocfs_stats *stats)
1529 struct proc_dir_entry *entry;
1530 LASSERT(root != NULL);
1532 LPROCFS_WRITE_ENTRY();
1533 entry = create_proc_entry(name, 0644, root);
1535 entry->proc_fops = &lprocfs_stats_seq_fops;
1536 entry->data = stats;
1539 LPROCFS_WRITE_EXIT();
1546 EXPORT_SYMBOL(lprocfs_register_stats);
1548 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1549 unsigned conf, const char *name, const char *units)
1551 struct lprocfs_counter_header *header;
1552 struct lprocfs_counter *percpu_cntr;
1553 unsigned long flags = 0;
1555 unsigned int num_cpu;
1557 LASSERT(stats != NULL);
1559 header = &stats->ls_cnt_header[index];
1560 LASSERTF(header != NULL, "Failed to allocate stats header:[%d]%s/%s\n",
1561 index, name, units);
1563 header->lc_config = conf;
1564 header->lc_name = name;
1565 header->lc_units = units;
1567 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1568 for (i = 0; i < num_cpu; ++i) {
1569 if (stats->ls_percpu[i] == NULL)
1571 percpu_cntr = lprocfs_stats_counter_get(stats, i, index);
1572 percpu_cntr->lc_count = 0;
1573 percpu_cntr->lc_min = LC_MIN_INIT;
1574 percpu_cntr->lc_max = 0;
1575 percpu_cntr->lc_sumsquare = 0;
1576 percpu_cntr->lc_sum = 0;
1577 if ((stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
1578 percpu_cntr->lc_sum_irq = 0;
1580 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1582 EXPORT_SYMBOL(lprocfs_counter_init);
1584 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1586 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1587 LASSERT(coffset < stats->ls_num); \
1588 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1591 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1593 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1594 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1595 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1596 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1597 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1598 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1599 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1600 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1601 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1602 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1603 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1604 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1605 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1606 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1607 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1608 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1609 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1610 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1611 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1612 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1613 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1614 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1615 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1616 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1617 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1618 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1619 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1620 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1621 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1622 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1623 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1624 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1625 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1626 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1627 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1628 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1629 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1630 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1631 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1632 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1633 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1634 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1635 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1636 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
1637 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1638 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1639 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1640 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1641 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1642 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1643 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1644 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1645 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1646 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1647 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1648 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1649 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1650 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1651 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1652 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1653 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1654 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1655 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1656 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1657 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1658 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1659 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1661 CLASSERT(NUM_OBD_STATS == OBD_COUNTER_OFFSET(putref) + 1);
1663 EXPORT_SYMBOL(lprocfs_init_ops_stats);
1665 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1667 struct lprocfs_stats *stats;
1668 unsigned int num_stats;
1671 LASSERT(obd->obd_stats == NULL);
1672 LASSERT(obd->obd_proc_entry != NULL);
1673 LASSERT(obd->obd_cntr_base == 0);
1675 num_stats = NUM_OBD_STATS + num_private_stats;
1676 stats = lprocfs_alloc_stats(num_stats, 0);
1680 lprocfs_init_ops_stats(num_private_stats, stats);
1682 for (i = num_private_stats; i < num_stats; i++) {
1683 /* If this LBUGs, it is likely that an obd
1684 * operation was added to struct obd_ops in
1685 * <obd.h>, and that the corresponding line item
1686 * LPROCFS_OBD_OP_INIT(.., .., opname)
1687 * is missing from the list above. */
1688 LASSERTF(stats->ls_cnt_header[i].lc_name != NULL,
1689 "Missing obd_stat initializer obd_op "
1690 "operation at offset %d.\n", i - num_private_stats);
1692 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1694 lprocfs_free_stats(&stats);
1696 obd->obd_stats = stats;
1697 obd->obd_cntr_base = num_private_stats;
1701 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
1703 void lprocfs_free_obd_stats(struct obd_device *obd)
1706 lprocfs_free_stats(&obd->obd_stats);
1708 EXPORT_SYMBOL(lprocfs_free_obd_stats);
1710 /* Note that we only init md counters for ops whose offset is less
1711 * than NUM_MD_STATS. This is explained in a comment in the definition
1712 * of struct md_ops. */
1713 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1715 unsigned int _idx = base + MD_COUNTER_OFFSET(op); \
1717 if (MD_COUNTER_OFFSET(op) < NUM_MD_STATS) { \
1718 LASSERT(_idx < stats->ls_num); \
1719 lprocfs_counter_init(stats, _idx, 0, #op, "reqs"); \
1723 void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats)
1725 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1726 LPROCFS_MD_OP_INIT(num_private_stats, stats, null_inode);
1727 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
1728 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1729 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1730 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1731 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1732 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1733 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1734 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1735 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1736 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1737 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1738 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1739 LPROCFS_MD_OP_INIT(num_private_stats, stats, fsync);
1740 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1741 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1742 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1743 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1744 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1745 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1746 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1747 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1748 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1749 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1750 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1751 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1752 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1753 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1754 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1755 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1756 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1758 EXPORT_SYMBOL(lprocfs_init_mps_stats);
1760 int lprocfs_alloc_md_stats(struct obd_device *obd,
1761 unsigned int num_private_stats)
1763 struct lprocfs_stats *stats;
1764 unsigned int num_stats;
1767 CLASSERT(offsetof(struct md_ops, MD_STATS_FIRST_OP) == 0);
1768 CLASSERT(_MD_COUNTER_OFFSET(MD_STATS_FIRST_OP) == 0);
1769 CLASSERT(_MD_COUNTER_OFFSET(MD_STATS_LAST_OP) > 0);
1771 /* TODO Ensure that this function is only used where
1772 * appropriate by adding an assertion to the effect that
1773 * obd->obd_type->typ_md_ops is not NULL. We can't do this now
1774 * because mdt_procfs_init() uses this function to allocate
1775 * the stats backing /proc/fs/lustre/mdt/.../md_stats but the
1776 * mdt layer does not use the md_ops interface. This is
1777 * confusing and a waste of memory. See LU-2484.
1779 LASSERT(obd->obd_proc_entry != NULL);
1780 LASSERT(obd->obd_md_stats == NULL);
1781 LASSERT(obd->obd_md_cntr_base == 0);
1783 num_stats = NUM_MD_STATS + num_private_stats;
1784 stats = lprocfs_alloc_stats(num_stats, 0);
1788 lprocfs_init_mps_stats(num_private_stats, stats);
1790 for (i = num_private_stats; i < num_stats; i++) {
1791 if (stats->ls_cnt_header[i].lc_name == NULL) {
1792 CERROR("Missing md_stat initializer md_op "
1793 "operation at offset %d. Aborting.\n",
1794 i - num_private_stats);
1799 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1801 lprocfs_free_stats(&stats);
1803 obd->obd_md_stats = stats;
1804 obd->obd_md_cntr_base = num_private_stats;
1809 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
1811 void lprocfs_free_md_stats(struct obd_device *obd)
1813 struct lprocfs_stats *stats = obd->obd_md_stats;
1815 if (stats != NULL) {
1816 obd->obd_md_stats = NULL;
1817 obd->obd_md_cntr_base = 0;
1818 lprocfs_free_stats(&stats);
1821 EXPORT_SYMBOL(lprocfs_free_md_stats);
1823 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1825 lprocfs_counter_init(ldlm_stats,
1826 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1827 0, "ldlm_enqueue", "reqs");
1828 lprocfs_counter_init(ldlm_stats,
1829 LDLM_CONVERT - LDLM_FIRST_OPC,
1830 0, "ldlm_convert", "reqs");
1831 lprocfs_counter_init(ldlm_stats,
1832 LDLM_CANCEL - LDLM_FIRST_OPC,
1833 0, "ldlm_cancel", "reqs");
1834 lprocfs_counter_init(ldlm_stats,
1835 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1836 0, "ldlm_bl_callback", "reqs");
1837 lprocfs_counter_init(ldlm_stats,
1838 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1839 0, "ldlm_cp_callback", "reqs");
1840 lprocfs_counter_init(ldlm_stats,
1841 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1842 0, "ldlm_gl_callback", "reqs");
1844 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
1846 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1847 int *eof, void *data)
1849 struct obd_export *exp = data;
1850 LASSERT(exp != NULL);
1852 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1855 struct exp_uuid_cb_data {
1863 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1864 int count, int *eof, int *len)
1866 cb_data->page = page;
1867 cb_data->count = count;
1872 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1873 cfs_hlist_node_t *hnode, void *cb_data)
1876 struct obd_export *exp = cfs_hash_object(hs, hnode);
1877 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1879 if (exp->exp_nid_stats)
1880 *data->len += snprintf((data->page + *data->len),
1881 data->count, "%s\n",
1882 obd_uuid2str(&exp->exp_client_uuid));
1886 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1887 int *eof, void *data)
1889 struct nid_stat *stats = (struct nid_stat *)data;
1890 struct exp_uuid_cb_data cb_data;
1891 struct obd_device *obd = stats->nid_obd;
1896 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1897 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1898 lprocfs_exp_print_uuid, &cb_data);
1899 return (*cb_data.len);
1902 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1903 cfs_hlist_node_t *hnode, void *cb_data)
1906 struct exp_uuid_cb_data *data = cb_data;
1907 struct obd_export *exp = cfs_hash_object(hs, hnode);
1909 if (exp->exp_lock_hash != NULL) {
1911 *data->len += cfs_hash_debug_header(data->page,
1914 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1921 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1922 int *eof, void *data)
1924 struct nid_stat *stats = (struct nid_stat *)data;
1925 struct exp_uuid_cb_data cb_data;
1926 struct obd_device *obd = stats->nid_obd;
1931 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1933 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1934 lprocfs_exp_print_hash, &cb_data);
1935 return (*cb_data.len);
1938 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1939 int count, int *eof, void *data)
1942 return snprintf(page, count, "%s\n",
1943 "Write into this file to clear all nid stats and "
1944 "stale nid entries");
1946 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1948 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1950 struct nid_stat *stat = obj;
1953 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
1954 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 1) {
1955 /* object has only hash references. */
1956 spin_lock(&stat->nid_obd->obd_nid_lock);
1957 cfs_list_move(&stat->nid_list, data);
1958 spin_unlock(&stat->nid_obd->obd_nid_lock);
1961 /* we has reference to object - only clear data*/
1962 if (stat->nid_stats)
1963 lprocfs_clear_stats(stat->nid_stats);
1968 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1969 unsigned long count, void *data)
1971 struct obd_device *obd = (struct obd_device *)data;
1972 struct nid_stat *client_stat;
1973 CFS_LIST_HEAD(free_list);
1975 cfs_hash_cond_del(obd->obd_nid_stats_hash,
1976 lprocfs_nid_stats_clear_write_cb, &free_list);
1978 while (!cfs_list_empty(&free_list)) {
1979 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
1981 cfs_list_del_init(&client_stat->nid_list);
1982 lprocfs_free_client_stats(client_stat);
1987 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1989 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1991 struct nid_stat *new_stat, *old_stat;
1992 struct obd_device *obd = NULL;
1993 cfs_proc_dir_entry_t *entry;
1994 char *buffer = NULL;
2000 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
2001 !exp->exp_obd->obd_nid_stats_hash)
2004 /* not test against zero because eric say:
2005 * You may only test nid against another nid, or LNET_NID_ANY.
2006 * Anything else is nonsense.*/
2007 if (!nid || *nid == LNET_NID_ANY)
2010 spin_lock(&exp->exp_lock);
2011 if (exp->exp_nid_stats != NULL) {
2012 spin_unlock(&exp->exp_lock);
2015 spin_unlock(&exp->exp_lock);
2019 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
2021 OBD_ALLOC_PTR(new_stat);
2022 if (new_stat == NULL)
2025 new_stat->nid = *nid;
2026 new_stat->nid_obd = exp->exp_obd;
2027 /* we need set default refcount to 1 to balance obd_disconnect */
2028 cfs_atomic_set(&new_stat->nid_exp_ref_count, 1);
2030 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
2031 nid, &new_stat->nid_hash);
2032 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
2033 old_stat, libcfs_nid2str(*nid),
2034 cfs_atomic_read(&new_stat->nid_exp_ref_count));
2036 /* Return -EALREADY here so that we know that the /proc
2037 * entry already has been created */
2038 if (old_stat != new_stat) {
2039 nidstat_putref(old_stat);
2040 GOTO(destroy_new, rc = -EALREADY);
2042 /* not found - create */
2043 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
2045 GOTO(destroy_new, rc = -ENOMEM);
2047 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
2048 new_stat->nid_proc = lprocfs_register(buffer,
2049 obd->obd_proc_exports_entry,
2051 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
2053 if (IS_ERR(new_stat->nid_proc)) {
2054 rc = PTR_ERR(new_stat->nid_proc);
2055 new_stat->nid_proc = NULL;
2056 CERROR("%s: cannot create proc entry for export %s: rc = %d\n",
2057 obd->obd_name, libcfs_nid2str(*nid), rc);
2058 GOTO(destroy_new_ns, rc);
2061 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
2062 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
2063 if (IS_ERR(entry)) {
2064 CWARN("Error adding the NID stats file\n");
2065 rc = PTR_ERR(entry);
2066 GOTO(destroy_new_ns, rc);
2069 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
2070 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
2071 if (IS_ERR(entry)) {
2072 CWARN("Error adding the hash file\n");
2073 rc = PTR_ERR(entry);
2074 GOTO(destroy_new_ns, rc);
2077 spin_lock(&exp->exp_lock);
2078 exp->exp_nid_stats = new_stat;
2079 spin_unlock(&exp->exp_lock);
2081 /* protect competitive add to list, not need locking on destroy */
2082 spin_lock(&obd->obd_nid_lock);
2083 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
2084 spin_unlock(&obd->obd_nid_lock);
2089 if (new_stat->nid_proc != NULL)
2090 lprocfs_remove(&new_stat->nid_proc);
2091 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
2094 nidstat_putref(new_stat);
2095 OBD_FREE_PTR(new_stat);
2098 EXPORT_SYMBOL(lprocfs_exp_setup);
2100 int lprocfs_exp_cleanup(struct obd_export *exp)
2102 struct nid_stat *stat = exp->exp_nid_stats;
2104 if(!stat || !exp->exp_obd)
2107 nidstat_putref(exp->exp_nid_stats);
2108 exp->exp_nid_stats = NULL;
2112 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2114 __s64 lprocfs_read_helper(struct lprocfs_counter *lc,
2115 struct lprocfs_counter_header *header,
2116 enum lprocfs_stats_flags flags,
2117 enum lprocfs_fields_flags field)
2121 if (lc == NULL || header == NULL)
2125 case LPROCFS_FIELDS_FLAGS_CONFIG:
2126 ret = header->lc_config;
2128 case LPROCFS_FIELDS_FLAGS_SUM:
2130 if ((flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
2131 ret += lc->lc_sum_irq;
2133 case LPROCFS_FIELDS_FLAGS_MIN:
2136 case LPROCFS_FIELDS_FLAGS_MAX:
2139 case LPROCFS_FIELDS_FLAGS_AVG:
2140 ret = (lc->lc_max - lc->lc_min) / 2;
2142 case LPROCFS_FIELDS_FLAGS_SUMSQUARE:
2143 ret = lc->lc_sumsquare;
2145 case LPROCFS_FIELDS_FLAGS_COUNT:
2153 EXPORT_SYMBOL(lprocfs_read_helper);
2155 int lprocfs_write_helper(const char *buffer, unsigned long count,
2158 return lprocfs_write_frac_helper(buffer, count, val, 1);
2160 EXPORT_SYMBOL(lprocfs_write_helper);
2162 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
2165 char kernbuf[20], *end, *pbuf;
2167 if (count > (sizeof(kernbuf) - 1))
2170 if (copy_from_user(kernbuf, buffer, count))
2173 kernbuf[count] = '\0';
2180 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2184 if (end != NULL && *end == '.') {
2185 int temp_val, pow = 1;
2189 if (strlen(pbuf) > 5)
2190 pbuf[5] = '\0'; /*only allow 5bits fractional*/
2192 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2195 for (i = 0; i < (end - pbuf); i++)
2198 *val += temp_val / pow;
2203 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2205 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
2208 long decimal_val, frac_val;
2214 decimal_val = val / mult;
2215 prtn = snprintf(buffer, count, "%ld", decimal_val);
2216 frac_val = val % mult;
2218 if (prtn < (count - 4) && frac_val > 0) {
2220 int i, temp_mult = 1, frac_bits = 0;
2222 temp_frac = frac_val * 10;
2223 buffer[prtn++] = '.';
2224 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
2225 /* only reserved 2 bits fraction */
2226 buffer[prtn++] ='0';
2231 * Need to think these cases :
2232 * 1. #echo x.00 > /proc/xxx output result : x
2233 * 2. #echo x.0x > /proc/xxx output result : x.0x
2234 * 3. #echo x.x0 > /proc/xxx output result : x.x
2235 * 4. #echo x.xx > /proc/xxx output result : x.xx
2236 * Only reserved 2 bits fraction.
2238 for (i = 0; i < (5 - prtn); i++)
2241 frac_bits = min((int)count - prtn, 3 - frac_bits);
2242 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
2243 frac_val * temp_mult / mult);
2246 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
2248 if (buffer[prtn] == '.') {
2255 buffer[prtn++] ='\n';
2258 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2260 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
2262 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
2264 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2266 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
2267 __u64 *val, int mult)
2269 char kernbuf[22], *end, *pbuf;
2270 __u64 whole, frac = 0, units;
2271 unsigned frac_d = 1;
2273 if (count > (sizeof(kernbuf) - 1))
2276 if (copy_from_user(kernbuf, buffer, count))
2279 kernbuf[count] = '\0';
2286 whole = simple_strtoull(pbuf, &end, 10);
2290 if (end != NULL && *end == '.') {
2294 /* need to limit frac_d to a __u32 */
2295 if (strlen(pbuf) > 10)
2298 frac = simple_strtoull(pbuf, &end, 10);
2299 /* count decimal places */
2300 for (i = 0; i < (end - pbuf); i++)
2319 /* Specified units override the multiplier */
2321 mult = mult < 0 ? -units : units;
2324 do_div(frac, frac_d);
2325 *val = whole * mult + frac;
2328 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2330 static char *lprocfs_strnstr(const char *s1, const char *s2, size_t len)
2339 if (!memcmp(s1, s2, l2))
2347 * Find the string \a name in the input \a buffer, and return a pointer to the
2348 * value immediately following \a name, reducing \a count appropriately.
2349 * If \a name is not found the original \a buffer is returned.
2351 char *lprocfs_find_named_value(const char *buffer, const char *name,
2352 unsigned long *count)
2355 size_t buflen = *count;
2357 /* there is no strnstr() in rhel5 and ubuntu kernels */
2358 val = lprocfs_strnstr(buffer, name, buflen);
2360 return (char *)buffer;
2362 val += strlen(name); /* skip prefix */
2363 while (val < buffer + buflen && isspace(*val)) /* skip separator */
2367 while (val < buffer + buflen && isalnum(*val)) {
2372 return val - *count;
2374 EXPORT_SYMBOL(lprocfs_find_named_value);
2376 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent,
2379 const struct file_operations *seq_fops,
2382 struct proc_dir_entry *entry;
2385 /* Disallow secretly (un)writable entries. */
2386 LASSERT((seq_fops->write == NULL) == ((mode & 0222) == 0));
2388 LPROCFS_WRITE_ENTRY();
2389 entry = create_proc_entry(name, mode, parent);
2391 entry->proc_fops = seq_fops;
2394 LPROCFS_WRITE_EXIT();
2401 EXPORT_SYMBOL(lprocfs_seq_create);
2403 int lprocfs_obd_seq_create(struct obd_device *dev,
2406 const struct file_operations *seq_fops,
2409 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2410 mode, seq_fops, data));
2412 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2414 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2416 if (value >= OBD_HIST_MAX)
2417 value = OBD_HIST_MAX - 1;
2419 spin_lock(&oh->oh_lock);
2420 oh->oh_buckets[value]++;
2421 spin_unlock(&oh->oh_lock);
2423 EXPORT_SYMBOL(lprocfs_oh_tally);
2425 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2427 unsigned int val = 0;
2429 if (likely(value != 0))
2430 val = min(fls(value - 1), OBD_HIST_MAX);
2432 lprocfs_oh_tally(oh, val);
2434 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2436 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2438 unsigned long ret = 0;
2441 for (i = 0; i < OBD_HIST_MAX; i++)
2442 ret += oh->oh_buckets[i];
2445 EXPORT_SYMBOL(lprocfs_oh_sum);
2447 void lprocfs_oh_clear(struct obd_histogram *oh)
2449 spin_lock(&oh->oh_lock);
2450 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2451 spin_unlock(&oh->oh_lock);
2453 EXPORT_SYMBOL(lprocfs_oh_clear);
2455 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2456 int count, int *eof, void *data)
2458 struct obd_device *obd = data;
2464 c += cfs_hash_debug_header(page, count);
2465 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2466 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2467 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2471 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2473 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2474 int count, int *eof, void *data)
2476 struct obd_device *obd = data;
2479 LASSERT(obd != NULL);
2480 LASSERT(count >= 0);
2482 /* Set start of user data returned to
2483 page + off since the user may have
2484 requested to read much smaller than
2485 what we need to read */
2486 *start = page + off;
2489 * We know we are allocated a page here.
2490 * Also we know that this function will
2491 * not need to write more than a page
2492 * so we can truncate at PAGE_CACHE_SIZE.
2494 size = min(count + (int)off + 1, (int)PAGE_CACHE_SIZE);
2496 /* Initialize the page */
2497 memset(page, 0, size);
2499 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2501 if (obd->obd_max_recoverable_clients == 0) {
2502 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2508 /* sampled unlocked, but really... */
2509 if (obd->obd_recovering == 0) {
2510 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2512 if (lprocfs_obd_snprintf(&page, size, &len,
2513 "recovery_start: %lu\n",
2514 obd->obd_recovery_start) <= 0)
2516 if (lprocfs_obd_snprintf(&page, size, &len,
2517 "recovery_duration: %lu\n",
2518 obd->obd_recovery_end -
2519 obd->obd_recovery_start) <= 0)
2521 /* Number of clients that have completed recovery */
2522 if (lprocfs_obd_snprintf(&page, size, &len,
2523 "completed_clients: %d/%d\n",
2524 obd->obd_max_recoverable_clients -
2525 obd->obd_stale_clients,
2526 obd->obd_max_recoverable_clients) <= 0)
2528 if (lprocfs_obd_snprintf(&page, size, &len,
2529 "replayed_requests: %d\n",
2530 obd->obd_replayed_requests) <= 0)
2532 if (lprocfs_obd_snprintf(&page, size, &len,
2533 "last_transno: "LPD64"\n",
2534 obd->obd_next_recovery_transno - 1)<=0)
2536 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2537 obd->obd_version_recov ?
2538 "ENABLED" : "DISABLED") <=0)
2540 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
2542 "DISABLED" : "ENABLED") <= 0)
2547 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2549 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2550 obd->obd_recovery_start) <= 0)
2552 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2553 cfs_time_current_sec() >=
2554 obd->obd_recovery_start +
2555 obd->obd_recovery_timeout ? 0 :
2556 obd->obd_recovery_start +
2557 obd->obd_recovery_timeout -
2558 cfs_time_current_sec()) <= 0)
2560 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2561 cfs_atomic_read(&obd->obd_connected_clients),
2562 obd->obd_max_recoverable_clients) <= 0)
2564 /* Number of clients that have completed recovery */
2565 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2566 cfs_atomic_read(&obd->obd_req_replay_clients))
2569 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2570 cfs_atomic_read(&obd->obd_lock_replay_clients))
2573 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2574 cfs_atomic_read(&obd->obd_connected_clients) -
2575 cfs_atomic_read(&obd->obd_lock_replay_clients))
2578 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2579 obd->obd_stale_clients) <= 0)
2581 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2582 obd->obd_replayed_requests) <= 0)
2584 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2585 obd->obd_requests_queued_for_recovery) <= 0)
2588 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2589 obd->obd_next_recovery_transno) <= 0)
2595 return min(count, len - (int)off);
2597 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2599 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
2600 int count, int *eof, void *data)
2602 struct obd_device *obd = (struct obd_device *)data;
2603 LASSERT(obd != NULL);
2605 return snprintf(page, count, "%d\n",
2606 obd->obd_recovery_ir_factor);
2608 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
2610 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
2611 unsigned long count, void *data)
2613 struct obd_device *obd = (struct obd_device *)data;
2615 LASSERT(obd != NULL);
2617 rc = lprocfs_write_helper(buffer, count, &val);
2621 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
2624 obd->obd_recovery_ir_factor = val;
2627 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
2629 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
2630 int count, int *eof, void *data)
2632 struct obd_device *obd = (struct obd_device *)data;
2633 LASSERT(obd != NULL);
2635 return snprintf(page, count, "%d\n",
2636 obd->obd_recovery_timeout);
2638 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
2640 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
2641 unsigned long count, void *data)
2643 struct obd_device *obd = (struct obd_device *)data;
2645 LASSERT(obd != NULL);
2647 rc = lprocfs_write_helper(buffer, count, &val);
2651 obd->obd_recovery_timeout = val;
2654 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
2656 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
2657 int count, int *eof, void *data)
2659 struct obd_device *obd = data;
2660 LASSERT(obd != NULL);
2662 return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
2664 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
2666 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
2667 unsigned long count, void *data)
2669 struct obd_device *obd = data;
2671 LASSERT(obd != NULL);
2673 rc = lprocfs_write_helper(buffer, count, &val);
2677 obd->obd_recovery_time_hard = val;
2680 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
2682 int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
2683 int count, int *eof, void *data)
2685 struct obd_device *dev = data;
2686 struct client_obd *cli = &dev->u.cli;
2689 client_obd_list_lock(&cli->cl_loi_list_lock);
2690 rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
2691 client_obd_list_unlock(&cli->cl_loi_list_lock);
2694 EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
2696 #ifdef HAVE_SERVER_SUPPORT
2697 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
2698 int count, int *eof, void *data)
2700 struct obd_device *obd = (struct obd_device *)data;
2701 struct obd_device_target *target = &obd->u.obt;
2703 LASSERT(obd != NULL);
2704 LASSERT(target->obt_magic == OBT_MAGIC);
2706 return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
2708 EXPORT_SYMBOL(lprocfs_target_rd_instance);