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 int lprocfs_stats_alloc_one(struct lprocfs_stats *stats, unsigned int cpuid)
1272 struct lprocfs_counter *cntr;
1273 unsigned int percpusize;
1275 unsigned long flags = 0;
1278 LASSERT(stats->ls_percpu[cpuid] == NULL);
1279 LASSERT((stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU) == 0);
1281 percpusize = lprocfs_stats_counter_size(stats);
1282 LIBCFS_ALLOC_ATOMIC(stats->ls_percpu[cpuid], percpusize);
1283 if (stats->ls_percpu[cpuid] != NULL) {
1285 if (unlikely(stats->ls_biggest_alloc_num <= cpuid)) {
1286 if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
1287 spin_lock_irqsave(&stats->ls_lock, flags);
1289 spin_lock(&stats->ls_lock);
1290 if (stats->ls_biggest_alloc_num <= cpuid)
1291 stats->ls_biggest_alloc_num = cpuid + 1;
1292 if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) {
1293 spin_unlock_irqrestore(&stats->ls_lock, flags);
1295 spin_unlock(&stats->ls_lock);
1298 /* initialize the ls_percpu[cpuid] non-zero counter */
1299 for (i = 0; i < stats->ls_num; ++i) {
1300 cntr = lprocfs_stats_counter_get(stats, cpuid, i);
1301 cntr->lc_min = LC_MIN_INIT;
1306 EXPORT_SYMBOL(lprocfs_stats_alloc_one);
1308 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1309 enum lprocfs_stats_flags flags)
1311 struct lprocfs_stats *stats;
1312 unsigned int num_entry;
1313 unsigned int percpusize = 0;
1319 if (lprocfs_no_percpu_stats != 0)
1320 flags |= LPROCFS_STATS_FLAG_NOPERCPU;
1322 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1325 num_entry = num_possible_cpus();
1327 /* alloc percpu pointers for all possible cpu slots */
1328 LIBCFS_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1332 stats->ls_num = num;
1333 stats->ls_flags = flags;
1334 spin_lock_init(&stats->ls_lock);
1336 /* alloc num of counter headers */
1337 LIBCFS_ALLOC(stats->ls_cnt_header,
1338 stats->ls_num * sizeof(struct lprocfs_counter_header));
1339 if (stats->ls_cnt_header == NULL)
1342 if ((flags & LPROCFS_STATS_FLAG_NOPERCPU) != 0) {
1343 /* contains only one set counters */
1344 percpusize = lprocfs_stats_counter_size(stats);
1345 LIBCFS_ALLOC_ATOMIC(stats->ls_percpu[0], percpusize);
1346 if (stats->ls_percpu[0] == NULL)
1348 stats->ls_biggest_alloc_num = 1;
1349 } else if ((flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0) {
1350 /* alloc all percpu data, currently only obd_memory use this */
1351 for (i = 0; i < num_entry; ++i)
1352 if (lprocfs_stats_alloc_one(stats, i) < 0)
1359 lprocfs_free_stats(&stats);
1362 EXPORT_SYMBOL(lprocfs_alloc_stats);
1364 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1366 struct lprocfs_stats *stats = *statsh;
1367 unsigned int num_entry;
1368 unsigned int percpusize;
1371 if (stats == NULL || stats->ls_num == 0)
1375 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1378 num_entry = num_possible_cpus();
1380 percpusize = lprocfs_stats_counter_size(stats);
1381 for (i = 0; i < num_entry; i++)
1382 if (stats->ls_percpu[i] != NULL)
1383 LIBCFS_FREE(stats->ls_percpu[i], percpusize);
1384 if (stats->ls_cnt_header != NULL)
1385 LIBCFS_FREE(stats->ls_cnt_header, stats->ls_num *
1386 sizeof(struct lprocfs_counter_header));
1387 LIBCFS_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1389 EXPORT_SYMBOL(lprocfs_free_stats);
1391 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1393 struct lprocfs_counter *percpu_cntr;
1396 unsigned int num_entry;
1397 unsigned long flags = 0;
1399 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1401 for (i = 0; i < num_entry; i++) {
1402 if (stats->ls_percpu[i] == NULL)
1404 for (j = 0; j < stats->ls_num; j++) {
1405 percpu_cntr = lprocfs_stats_counter_get(stats, i, j);
1406 percpu_cntr->lc_count = 0;
1407 percpu_cntr->lc_min = LC_MIN_INIT;
1408 percpu_cntr->lc_max = 0;
1409 percpu_cntr->lc_sumsquare = 0;
1410 percpu_cntr->lc_sum = 0;
1411 if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
1412 percpu_cntr->lc_sum_irq = 0;
1416 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1418 EXPORT_SYMBOL(lprocfs_clear_stats);
1420 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1421 size_t len, loff_t *off)
1423 struct seq_file *seq = file->private_data;
1424 struct lprocfs_stats *stats = seq->private;
1426 lprocfs_clear_stats(stats);
1431 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1433 struct lprocfs_stats *stats = p->private;
1435 return (*pos < stats->ls_num) ? pos : NULL;
1438 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1442 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1446 return lprocfs_stats_seq_start(p, pos);
1449 /* seq file export of one lprocfs counter */
1450 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1452 struct lprocfs_stats *stats = p->private;
1453 struct lprocfs_counter_header *hdr;
1454 struct lprocfs_counter ctr;
1455 int idx = *(loff_t *)v;
1461 do_gettimeofday(&now);
1462 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1463 "snapshot_time", now.tv_sec, now.tv_usec);
1468 hdr = &stats->ls_cnt_header[idx];
1469 lprocfs_stats_collect(stats, idx, &ctr);
1471 if (ctr.lc_count == 0)
1474 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", hdr->lc_name,
1475 ctr.lc_count, hdr->lc_units);
1479 if ((hdr->lc_config & LPROCFS_CNTR_AVGMINMAX) && ctr.lc_count > 0) {
1480 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1481 ctr.lc_min, ctr.lc_max, ctr.lc_sum);
1484 if (hdr->lc_config & LPROCFS_CNTR_STDDEV)
1485 rc = seq_printf(p, " "LPD64, ctr.lc_sumsquare);
1489 rc = seq_printf(p, "\n");
1491 return (rc < 0) ? rc : 0;
1494 struct seq_operations lprocfs_stats_seq_sops = {
1495 .start = lprocfs_stats_seq_start,
1496 .stop = lprocfs_stats_seq_stop,
1497 .next = lprocfs_stats_seq_next,
1498 .show = lprocfs_stats_seq_show,
1501 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1503 struct proc_dir_entry *dp = PDE(inode);
1504 struct seq_file *seq;
1507 if (LPROCFS_ENTRY_CHECK(dp))
1510 rc = seq_open(file, &lprocfs_stats_seq_sops);
1513 seq = file->private_data;
1514 seq->private = dp->data;
1518 struct file_operations lprocfs_stats_seq_fops = {
1519 .owner = THIS_MODULE,
1520 .open = lprocfs_stats_seq_open,
1522 .write = lprocfs_stats_seq_write,
1523 .llseek = seq_lseek,
1524 .release = lprocfs_seq_release,
1527 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1528 struct lprocfs_stats *stats)
1530 struct proc_dir_entry *entry;
1531 LASSERT(root != NULL);
1533 LPROCFS_WRITE_ENTRY();
1534 entry = create_proc_entry(name, 0644, root);
1536 entry->proc_fops = &lprocfs_stats_seq_fops;
1537 entry->data = stats;
1540 LPROCFS_WRITE_EXIT();
1547 EXPORT_SYMBOL(lprocfs_register_stats);
1549 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1550 unsigned conf, const char *name, const char *units)
1552 struct lprocfs_counter_header *header;
1553 struct lprocfs_counter *percpu_cntr;
1554 unsigned long flags = 0;
1556 unsigned int num_cpu;
1558 LASSERT(stats != NULL);
1560 header = &stats->ls_cnt_header[index];
1561 LASSERTF(header != NULL, "Failed to allocate stats header:[%d]%s/%s\n",
1562 index, name, units);
1564 header->lc_config = conf;
1565 header->lc_name = name;
1566 header->lc_units = units;
1568 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1569 for (i = 0; i < num_cpu; ++i) {
1570 if (stats->ls_percpu[i] == NULL)
1572 percpu_cntr = lprocfs_stats_counter_get(stats, i, index);
1573 percpu_cntr->lc_count = 0;
1574 percpu_cntr->lc_min = LC_MIN_INIT;
1575 percpu_cntr->lc_max = 0;
1576 percpu_cntr->lc_sumsquare = 0;
1577 percpu_cntr->lc_sum = 0;
1578 if ((stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
1579 percpu_cntr->lc_sum_irq = 0;
1581 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1583 EXPORT_SYMBOL(lprocfs_counter_init);
1585 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1587 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1588 LASSERT(coffset < stats->ls_num); \
1589 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1592 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1594 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1595 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1596 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1597 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1598 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1599 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1600 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1601 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1602 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1603 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1604 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1605 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1606 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1607 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1608 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1609 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1610 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1611 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1612 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1613 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1614 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1615 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1616 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1617 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1618 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1619 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1620 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1621 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1622 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1623 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1624 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1625 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1626 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1627 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1628 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1629 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1630 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1631 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1632 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1633 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1634 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1635 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1636 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1637 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
1638 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1639 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1640 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1641 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1642 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1643 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1644 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1645 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1646 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1647 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1648 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1649 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1650 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1651 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1652 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1653 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1654 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1655 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1656 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1657 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1658 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1659 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1660 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1662 CLASSERT(NUM_OBD_STATS == OBD_COUNTER_OFFSET(putref) + 1);
1664 EXPORT_SYMBOL(lprocfs_init_ops_stats);
1666 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1668 struct lprocfs_stats *stats;
1669 unsigned int num_stats;
1672 LASSERT(obd->obd_stats == NULL);
1673 LASSERT(obd->obd_proc_entry != NULL);
1674 LASSERT(obd->obd_cntr_base == 0);
1676 num_stats = NUM_OBD_STATS + num_private_stats;
1677 stats = lprocfs_alloc_stats(num_stats, 0);
1681 lprocfs_init_ops_stats(num_private_stats, stats);
1683 for (i = num_private_stats; i < num_stats; i++) {
1684 /* If this LBUGs, it is likely that an obd
1685 * operation was added to struct obd_ops in
1686 * <obd.h>, and that the corresponding line item
1687 * LPROCFS_OBD_OP_INIT(.., .., opname)
1688 * is missing from the list above. */
1689 LASSERTF(stats->ls_cnt_header[i].lc_name != NULL,
1690 "Missing obd_stat initializer obd_op "
1691 "operation at offset %d.\n", i - num_private_stats);
1693 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1695 lprocfs_free_stats(&stats);
1697 obd->obd_stats = stats;
1698 obd->obd_cntr_base = num_private_stats;
1702 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
1704 void lprocfs_free_obd_stats(struct obd_device *obd)
1707 lprocfs_free_stats(&obd->obd_stats);
1709 EXPORT_SYMBOL(lprocfs_free_obd_stats);
1711 /* Note that we only init md counters for ops whose offset is less
1712 * than NUM_MD_STATS. This is explained in a comment in the definition
1713 * of struct md_ops. */
1714 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1716 unsigned int _idx = base + MD_COUNTER_OFFSET(op); \
1718 if (MD_COUNTER_OFFSET(op) < NUM_MD_STATS) { \
1719 LASSERT(_idx < stats->ls_num); \
1720 lprocfs_counter_init(stats, _idx, 0, #op, "reqs"); \
1724 void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats)
1726 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1727 LPROCFS_MD_OP_INIT(num_private_stats, stats, null_inode);
1728 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
1729 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1730 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1731 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1732 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1733 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1734 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1735 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1736 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1737 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1738 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1739 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1740 LPROCFS_MD_OP_INIT(num_private_stats, stats, fsync);
1741 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1742 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1743 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1744 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1745 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1746 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1747 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1748 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1749 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1750 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1751 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1752 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1753 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1754 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1755 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1756 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1757 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1759 EXPORT_SYMBOL(lprocfs_init_mps_stats);
1761 int lprocfs_alloc_md_stats(struct obd_device *obd,
1762 unsigned int num_private_stats)
1764 struct lprocfs_stats *stats;
1765 unsigned int num_stats;
1768 CLASSERT(offsetof(struct md_ops, MD_STATS_FIRST_OP) == 0);
1769 CLASSERT(_MD_COUNTER_OFFSET(MD_STATS_FIRST_OP) == 0);
1770 CLASSERT(_MD_COUNTER_OFFSET(MD_STATS_LAST_OP) > 0);
1772 /* TODO Ensure that this function is only used where
1773 * appropriate by adding an assertion to the effect that
1774 * obd->obd_type->typ_md_ops is not NULL. We can't do this now
1775 * because mdt_procfs_init() uses this function to allocate
1776 * the stats backing /proc/fs/lustre/mdt/.../md_stats but the
1777 * mdt layer does not use the md_ops interface. This is
1778 * confusing and a waste of memory. See LU-2484.
1780 LASSERT(obd->obd_proc_entry != NULL);
1781 LASSERT(obd->obd_md_stats == NULL);
1782 LASSERT(obd->obd_md_cntr_base == 0);
1784 num_stats = NUM_MD_STATS + num_private_stats;
1785 stats = lprocfs_alloc_stats(num_stats, 0);
1789 lprocfs_init_mps_stats(num_private_stats, stats);
1791 for (i = num_private_stats; i < num_stats; i++) {
1792 if (stats->ls_cnt_header[i].lc_name == NULL) {
1793 CERROR("Missing md_stat initializer md_op "
1794 "operation at offset %d. Aborting.\n",
1795 i - num_private_stats);
1800 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1802 lprocfs_free_stats(&stats);
1804 obd->obd_md_stats = stats;
1805 obd->obd_md_cntr_base = num_private_stats;
1810 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
1812 void lprocfs_free_md_stats(struct obd_device *obd)
1814 struct lprocfs_stats *stats = obd->obd_md_stats;
1816 if (stats != NULL) {
1817 obd->obd_md_stats = NULL;
1818 obd->obd_md_cntr_base = 0;
1819 lprocfs_free_stats(&stats);
1822 EXPORT_SYMBOL(lprocfs_free_md_stats);
1824 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1826 lprocfs_counter_init(ldlm_stats,
1827 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1828 0, "ldlm_enqueue", "reqs");
1829 lprocfs_counter_init(ldlm_stats,
1830 LDLM_CONVERT - LDLM_FIRST_OPC,
1831 0, "ldlm_convert", "reqs");
1832 lprocfs_counter_init(ldlm_stats,
1833 LDLM_CANCEL - LDLM_FIRST_OPC,
1834 0, "ldlm_cancel", "reqs");
1835 lprocfs_counter_init(ldlm_stats,
1836 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1837 0, "ldlm_bl_callback", "reqs");
1838 lprocfs_counter_init(ldlm_stats,
1839 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1840 0, "ldlm_cp_callback", "reqs");
1841 lprocfs_counter_init(ldlm_stats,
1842 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1843 0, "ldlm_gl_callback", "reqs");
1845 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
1847 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1848 int *eof, void *data)
1850 struct obd_export *exp = data;
1851 LASSERT(exp != NULL);
1853 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1856 struct exp_uuid_cb_data {
1864 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1865 int count, int *eof, int *len)
1867 cb_data->page = page;
1868 cb_data->count = count;
1873 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1874 cfs_hlist_node_t *hnode, void *cb_data)
1877 struct obd_export *exp = cfs_hash_object(hs, hnode);
1878 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1880 if (exp->exp_nid_stats)
1881 *data->len += snprintf((data->page + *data->len),
1882 data->count, "%s\n",
1883 obd_uuid2str(&exp->exp_client_uuid));
1887 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1888 int *eof, void *data)
1890 struct nid_stat *stats = (struct nid_stat *)data;
1891 struct exp_uuid_cb_data cb_data;
1892 struct obd_device *obd = stats->nid_obd;
1897 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1898 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1899 lprocfs_exp_print_uuid, &cb_data);
1900 return (*cb_data.len);
1903 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1904 cfs_hlist_node_t *hnode, void *cb_data)
1907 struct exp_uuid_cb_data *data = cb_data;
1908 struct obd_export *exp = cfs_hash_object(hs, hnode);
1910 if (exp->exp_lock_hash != NULL) {
1912 *data->len += cfs_hash_debug_header(data->page,
1915 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1922 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1923 int *eof, void *data)
1925 struct nid_stat *stats = (struct nid_stat *)data;
1926 struct exp_uuid_cb_data cb_data;
1927 struct obd_device *obd = stats->nid_obd;
1932 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1934 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1935 lprocfs_exp_print_hash, &cb_data);
1936 return (*cb_data.len);
1939 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1940 int count, int *eof, void *data)
1943 return snprintf(page, count, "%s\n",
1944 "Write into this file to clear all nid stats and "
1945 "stale nid entries");
1947 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1949 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1951 struct nid_stat *stat = obj;
1954 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
1955 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 1) {
1956 /* object has only hash references. */
1957 spin_lock(&stat->nid_obd->obd_nid_lock);
1958 cfs_list_move(&stat->nid_list, data);
1959 spin_unlock(&stat->nid_obd->obd_nid_lock);
1962 /* we has reference to object - only clear data*/
1963 if (stat->nid_stats)
1964 lprocfs_clear_stats(stat->nid_stats);
1969 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1970 unsigned long count, void *data)
1972 struct obd_device *obd = (struct obd_device *)data;
1973 struct nid_stat *client_stat;
1974 CFS_LIST_HEAD(free_list);
1976 cfs_hash_cond_del(obd->obd_nid_stats_hash,
1977 lprocfs_nid_stats_clear_write_cb, &free_list);
1979 while (!cfs_list_empty(&free_list)) {
1980 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
1982 cfs_list_del_init(&client_stat->nid_list);
1983 lprocfs_free_client_stats(client_stat);
1988 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1990 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1992 struct nid_stat *new_stat, *old_stat;
1993 struct obd_device *obd = NULL;
1994 cfs_proc_dir_entry_t *entry;
1995 char *buffer = NULL;
2001 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
2002 !exp->exp_obd->obd_nid_stats_hash)
2005 /* not test against zero because eric say:
2006 * You may only test nid against another nid, or LNET_NID_ANY.
2007 * Anything else is nonsense.*/
2008 if (!nid || *nid == LNET_NID_ANY)
2011 spin_lock(&exp->exp_lock);
2012 if (exp->exp_nid_stats != NULL) {
2013 spin_unlock(&exp->exp_lock);
2016 spin_unlock(&exp->exp_lock);
2020 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
2022 OBD_ALLOC_PTR(new_stat);
2023 if (new_stat == NULL)
2026 new_stat->nid = *nid;
2027 new_stat->nid_obd = exp->exp_obd;
2028 /* we need set default refcount to 1 to balance obd_disconnect */
2029 cfs_atomic_set(&new_stat->nid_exp_ref_count, 1);
2031 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
2032 nid, &new_stat->nid_hash);
2033 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
2034 old_stat, libcfs_nid2str(*nid),
2035 cfs_atomic_read(&new_stat->nid_exp_ref_count));
2037 /* Return -EALREADY here so that we know that the /proc
2038 * entry already has been created */
2039 if (old_stat != new_stat) {
2040 nidstat_putref(old_stat);
2041 GOTO(destroy_new, rc = -EALREADY);
2043 /* not found - create */
2044 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
2046 GOTO(destroy_new, rc = -ENOMEM);
2048 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
2049 new_stat->nid_proc = lprocfs_register(buffer,
2050 obd->obd_proc_exports_entry,
2052 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
2054 if (IS_ERR(new_stat->nid_proc)) {
2055 rc = PTR_ERR(new_stat->nid_proc);
2056 new_stat->nid_proc = NULL;
2057 CERROR("%s: cannot create proc entry for export %s: rc = %d\n",
2058 obd->obd_name, libcfs_nid2str(*nid), rc);
2059 GOTO(destroy_new_ns, rc);
2062 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
2063 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
2064 if (IS_ERR(entry)) {
2065 CWARN("Error adding the NID stats file\n");
2066 rc = PTR_ERR(entry);
2067 GOTO(destroy_new_ns, rc);
2070 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
2071 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
2072 if (IS_ERR(entry)) {
2073 CWARN("Error adding the hash file\n");
2074 rc = PTR_ERR(entry);
2075 GOTO(destroy_new_ns, rc);
2078 spin_lock(&exp->exp_lock);
2079 exp->exp_nid_stats = new_stat;
2080 spin_unlock(&exp->exp_lock);
2082 /* protect competitive add to list, not need locking on destroy */
2083 spin_lock(&obd->obd_nid_lock);
2084 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
2085 spin_unlock(&obd->obd_nid_lock);
2090 if (new_stat->nid_proc != NULL)
2091 lprocfs_remove(&new_stat->nid_proc);
2092 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
2095 nidstat_putref(new_stat);
2096 OBD_FREE_PTR(new_stat);
2099 EXPORT_SYMBOL(lprocfs_exp_setup);
2101 int lprocfs_exp_cleanup(struct obd_export *exp)
2103 struct nid_stat *stat = exp->exp_nid_stats;
2105 if(!stat || !exp->exp_obd)
2108 nidstat_putref(exp->exp_nid_stats);
2109 exp->exp_nid_stats = NULL;
2113 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2115 __s64 lprocfs_read_helper(struct lprocfs_counter *lc,
2116 struct lprocfs_counter_header *header,
2117 enum lprocfs_stats_flags flags,
2118 enum lprocfs_fields_flags field)
2122 if (lc == NULL || header == NULL)
2126 case LPROCFS_FIELDS_FLAGS_CONFIG:
2127 ret = header->lc_config;
2129 case LPROCFS_FIELDS_FLAGS_SUM:
2131 if ((flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
2132 ret += lc->lc_sum_irq;
2134 case LPROCFS_FIELDS_FLAGS_MIN:
2137 case LPROCFS_FIELDS_FLAGS_MAX:
2140 case LPROCFS_FIELDS_FLAGS_AVG:
2141 ret = (lc->lc_max - lc->lc_min) / 2;
2143 case LPROCFS_FIELDS_FLAGS_SUMSQUARE:
2144 ret = lc->lc_sumsquare;
2146 case LPROCFS_FIELDS_FLAGS_COUNT:
2154 EXPORT_SYMBOL(lprocfs_read_helper);
2156 int lprocfs_write_helper(const char *buffer, unsigned long count,
2159 return lprocfs_write_frac_helper(buffer, count, val, 1);
2161 EXPORT_SYMBOL(lprocfs_write_helper);
2163 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
2166 char kernbuf[20], *end, *pbuf;
2168 if (count > (sizeof(kernbuf) - 1))
2171 if (copy_from_user(kernbuf, buffer, count))
2174 kernbuf[count] = '\0';
2181 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2185 if (end != NULL && *end == '.') {
2186 int temp_val, pow = 1;
2190 if (strlen(pbuf) > 5)
2191 pbuf[5] = '\0'; /*only allow 5bits fractional*/
2193 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2196 for (i = 0; i < (end - pbuf); i++)
2199 *val += temp_val / pow;
2204 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2206 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
2209 long decimal_val, frac_val;
2215 decimal_val = val / mult;
2216 prtn = snprintf(buffer, count, "%ld", decimal_val);
2217 frac_val = val % mult;
2219 if (prtn < (count - 4) && frac_val > 0) {
2221 int i, temp_mult = 1, frac_bits = 0;
2223 temp_frac = frac_val * 10;
2224 buffer[prtn++] = '.';
2225 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
2226 /* only reserved 2 bits fraction */
2227 buffer[prtn++] ='0';
2232 * Need to think these cases :
2233 * 1. #echo x.00 > /proc/xxx output result : x
2234 * 2. #echo x.0x > /proc/xxx output result : x.0x
2235 * 3. #echo x.x0 > /proc/xxx output result : x.x
2236 * 4. #echo x.xx > /proc/xxx output result : x.xx
2237 * Only reserved 2 bits fraction.
2239 for (i = 0; i < (5 - prtn); i++)
2242 frac_bits = min((int)count - prtn, 3 - frac_bits);
2243 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
2244 frac_val * temp_mult / mult);
2247 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
2249 if (buffer[prtn] == '.') {
2256 buffer[prtn++] ='\n';
2259 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2261 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
2263 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
2265 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2267 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
2268 __u64 *val, int mult)
2270 char kernbuf[22], *end, *pbuf;
2271 __u64 whole, frac = 0, units;
2272 unsigned frac_d = 1;
2274 if (count > (sizeof(kernbuf) - 1))
2277 if (copy_from_user(kernbuf, buffer, count))
2280 kernbuf[count] = '\0';
2287 whole = simple_strtoull(pbuf, &end, 10);
2291 if (end != NULL && *end == '.') {
2295 /* need to limit frac_d to a __u32 */
2296 if (strlen(pbuf) > 10)
2299 frac = simple_strtoull(pbuf, &end, 10);
2300 /* count decimal places */
2301 for (i = 0; i < (end - pbuf); i++)
2320 /* Specified units override the multiplier */
2322 mult = mult < 0 ? -units : units;
2325 do_div(frac, frac_d);
2326 *val = whole * mult + frac;
2329 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2331 static char *lprocfs_strnstr(const char *s1, const char *s2, size_t len)
2340 if (!memcmp(s1, s2, l2))
2348 * Find the string \a name in the input \a buffer, and return a pointer to the
2349 * value immediately following \a name, reducing \a count appropriately.
2350 * If \a name is not found the original \a buffer is returned.
2352 char *lprocfs_find_named_value(const char *buffer, const char *name,
2353 unsigned long *count)
2356 size_t buflen = *count;
2358 /* there is no strnstr() in rhel5 and ubuntu kernels */
2359 val = lprocfs_strnstr(buffer, name, buflen);
2361 return (char *)buffer;
2363 val += strlen(name); /* skip prefix */
2364 while (val < buffer + buflen && isspace(*val)) /* skip separator */
2368 while (val < buffer + buflen && isalnum(*val)) {
2373 return val - *count;
2375 EXPORT_SYMBOL(lprocfs_find_named_value);
2377 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent,
2380 const struct file_operations *seq_fops,
2383 struct proc_dir_entry *entry;
2386 /* Disallow secretly (un)writable entries. */
2387 LASSERT((seq_fops->write == NULL) == ((mode & 0222) == 0));
2389 LPROCFS_WRITE_ENTRY();
2390 entry = create_proc_entry(name, mode, parent);
2392 entry->proc_fops = seq_fops;
2395 LPROCFS_WRITE_EXIT();
2402 EXPORT_SYMBOL(lprocfs_seq_create);
2404 int lprocfs_obd_seq_create(struct obd_device *dev,
2407 const struct file_operations *seq_fops,
2410 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2411 mode, seq_fops, data));
2413 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2415 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2417 if (value >= OBD_HIST_MAX)
2418 value = OBD_HIST_MAX - 1;
2420 spin_lock(&oh->oh_lock);
2421 oh->oh_buckets[value]++;
2422 spin_unlock(&oh->oh_lock);
2424 EXPORT_SYMBOL(lprocfs_oh_tally);
2426 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2428 unsigned int val = 0;
2430 if (likely(value != 0))
2431 val = min(fls(value - 1), OBD_HIST_MAX);
2433 lprocfs_oh_tally(oh, val);
2435 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2437 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2439 unsigned long ret = 0;
2442 for (i = 0; i < OBD_HIST_MAX; i++)
2443 ret += oh->oh_buckets[i];
2446 EXPORT_SYMBOL(lprocfs_oh_sum);
2448 void lprocfs_oh_clear(struct obd_histogram *oh)
2450 spin_lock(&oh->oh_lock);
2451 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2452 spin_unlock(&oh->oh_lock);
2454 EXPORT_SYMBOL(lprocfs_oh_clear);
2456 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2457 int count, int *eof, void *data)
2459 struct obd_device *obd = data;
2465 c += cfs_hash_debug_header(page, count);
2466 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2467 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2468 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2472 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2474 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2475 int count, int *eof, void *data)
2477 struct obd_device *obd = data;
2480 LASSERT(obd != NULL);
2481 LASSERT(count >= 0);
2483 /* Set start of user data returned to
2484 page + off since the user may have
2485 requested to read much smaller than
2486 what we need to read */
2487 *start = page + off;
2490 * We know we are allocated a page here.
2491 * Also we know that this function will
2492 * not need to write more than a page
2493 * so we can truncate at PAGE_CACHE_SIZE.
2495 size = min(count + (int)off + 1, (int)PAGE_CACHE_SIZE);
2497 /* Initialize the page */
2498 memset(page, 0, size);
2500 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2502 if (obd->obd_max_recoverable_clients == 0) {
2503 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2509 /* sampled unlocked, but really... */
2510 if (obd->obd_recovering == 0) {
2511 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2513 if (lprocfs_obd_snprintf(&page, size, &len,
2514 "recovery_start: %lu\n",
2515 obd->obd_recovery_start) <= 0)
2517 if (lprocfs_obd_snprintf(&page, size, &len,
2518 "recovery_duration: %lu\n",
2519 obd->obd_recovery_end -
2520 obd->obd_recovery_start) <= 0)
2522 /* Number of clients that have completed recovery */
2523 if (lprocfs_obd_snprintf(&page, size, &len,
2524 "completed_clients: %d/%d\n",
2525 obd->obd_max_recoverable_clients -
2526 obd->obd_stale_clients,
2527 obd->obd_max_recoverable_clients) <= 0)
2529 if (lprocfs_obd_snprintf(&page, size, &len,
2530 "replayed_requests: %d\n",
2531 obd->obd_replayed_requests) <= 0)
2533 if (lprocfs_obd_snprintf(&page, size, &len,
2534 "last_transno: "LPD64"\n",
2535 obd->obd_next_recovery_transno - 1)<=0)
2537 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2538 obd->obd_version_recov ?
2539 "ENABLED" : "DISABLED") <=0)
2541 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
2543 "DISABLED" : "ENABLED") <= 0)
2548 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2550 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2551 obd->obd_recovery_start) <= 0)
2553 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2554 cfs_time_current_sec() >=
2555 obd->obd_recovery_start +
2556 obd->obd_recovery_timeout ? 0 :
2557 obd->obd_recovery_start +
2558 obd->obd_recovery_timeout -
2559 cfs_time_current_sec()) <= 0)
2561 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2562 cfs_atomic_read(&obd->obd_connected_clients),
2563 obd->obd_max_recoverable_clients) <= 0)
2565 /* Number of clients that have completed recovery */
2566 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2567 cfs_atomic_read(&obd->obd_req_replay_clients))
2570 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2571 cfs_atomic_read(&obd->obd_lock_replay_clients))
2574 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2575 cfs_atomic_read(&obd->obd_connected_clients) -
2576 cfs_atomic_read(&obd->obd_lock_replay_clients))
2579 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2580 obd->obd_stale_clients) <= 0)
2582 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2583 obd->obd_replayed_requests) <= 0)
2585 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2586 obd->obd_requests_queued_for_recovery) <= 0)
2589 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2590 obd->obd_next_recovery_transno) <= 0)
2596 return min(count, len - (int)off);
2598 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2600 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
2601 int count, int *eof, void *data)
2603 struct obd_device *obd = (struct obd_device *)data;
2604 LASSERT(obd != NULL);
2606 return snprintf(page, count, "%d\n",
2607 obd->obd_recovery_ir_factor);
2609 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
2611 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
2612 unsigned long count, void *data)
2614 struct obd_device *obd = (struct obd_device *)data;
2616 LASSERT(obd != NULL);
2618 rc = lprocfs_write_helper(buffer, count, &val);
2622 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
2625 obd->obd_recovery_ir_factor = val;
2628 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
2630 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
2631 int count, int *eof, void *data)
2633 struct obd_device *obd = (struct obd_device *)data;
2634 LASSERT(obd != NULL);
2636 return snprintf(page, count, "%d\n",
2637 obd->obd_recovery_timeout);
2639 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
2641 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
2642 unsigned long count, void *data)
2644 struct obd_device *obd = (struct obd_device *)data;
2646 LASSERT(obd != NULL);
2648 rc = lprocfs_write_helper(buffer, count, &val);
2652 obd->obd_recovery_timeout = val;
2655 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
2657 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
2658 int count, int *eof, void *data)
2660 struct obd_device *obd = data;
2661 LASSERT(obd != NULL);
2663 return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
2665 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
2667 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
2668 unsigned long count, void *data)
2670 struct obd_device *obd = data;
2672 LASSERT(obd != NULL);
2674 rc = lprocfs_write_helper(buffer, count, &val);
2678 obd->obd_recovery_time_hard = val;
2681 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
2683 int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
2684 int count, int *eof, void *data)
2686 struct obd_device *dev = data;
2687 struct client_obd *cli = &dev->u.cli;
2690 client_obd_list_lock(&cli->cl_loi_list_lock);
2691 rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
2692 client_obd_list_unlock(&cli->cl_loi_list_lock);
2695 EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
2697 #ifdef HAVE_SERVER_SUPPORT
2698 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
2699 int count, int *eof, void *data)
2701 struct obd_device *obd = (struct obd_device *)data;
2702 struct obd_device_target *target = &obd->u.obt;
2704 LASSERT(obd != NULL);
2705 LASSERT(target->obt_magic == OBT_MAGIC);
2707 return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
2709 EXPORT_SYMBOL(lprocfs_target_rd_instance);