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, 2012, 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_fsfilt.h>
50 #include <lustre_log.h>
51 #include <lustre_disk.h>
52 #include <lustre/lustre_idl.h>
53 #include <dt_object.h>
57 static int lprocfs_no_percpu_stats = 0;
58 CFS_MODULE_PARM(lprocfs_no_percpu_stats, "i", int, 0644,
59 "Do not alloc percpu data for lprocfs stats");
61 #define MAX_STRING_SIZE 128
63 /* for bug 10866, global variable */
64 DECLARE_RWSEM(_lprocfs_lock);
65 EXPORT_SYMBOL(_lprocfs_lock);
67 int lprocfs_single_release(struct inode *inode, struct file *file)
70 return single_release(inode, file);
72 EXPORT_SYMBOL(lprocfs_single_release);
74 int lprocfs_seq_release(struct inode *inode, struct file *file)
77 return seq_release(inode, file);
79 EXPORT_SYMBOL(lprocfs_seq_release);
81 static struct proc_dir_entry *__lprocfs_srch(struct proc_dir_entry *head,
84 struct proc_dir_entry *temp;
90 while (temp != NULL) {
91 if (strcmp(temp->name, name) == 0) {
100 struct proc_dir_entry *lprocfs_srch(struct proc_dir_entry *head,
103 struct proc_dir_entry *temp;
105 LPROCFS_SRCH_ENTRY();
106 temp = __lprocfs_srch(head, name);
110 EXPORT_SYMBOL(lprocfs_srch);
112 /* lprocfs API calls */
114 /* Function that emulates snprintf but also has the side effect of advancing
115 the page pointer for the next write into the buffer, incrementing the total
116 length written to the buffer, and decrementing the size left in the
118 static int lprocfs_obd_snprintf(char **page, int end, int *len,
119 const char *format, ...)
127 va_start(list, format);
128 n = vsnprintf(*page, end - *len, format, list);
131 *page += n; *len += n;
135 cfs_proc_dir_entry_t *lprocfs_add_simple(struct proc_dir_entry *root,
137 read_proc_t *read_proc,
138 write_proc_t *write_proc,
140 struct file_operations *fops)
142 cfs_proc_dir_entry_t *proc;
145 if (root == NULL || name == NULL)
146 return ERR_PTR(-EINVAL);
153 LPROCFS_WRITE_ENTRY();
154 proc = create_proc_entry(name, mode, root);
156 CERROR("LprocFS: No memory to create /proc entry %s", name);
157 LPROCFS_WRITE_EXIT();
158 return ERR_PTR(-ENOMEM);
160 proc->read_proc = read_proc;
161 proc->write_proc = write_proc;
164 proc->proc_fops = fops;
165 LPROCFS_WRITE_EXIT();
168 EXPORT_SYMBOL(lprocfs_add_simple);
170 struct proc_dir_entry *lprocfs_add_symlink(const char *name,
171 struct proc_dir_entry *parent, const char *format, ...)
173 struct proc_dir_entry *entry;
177 if (parent == NULL || format == NULL)
180 OBD_ALLOC_WAIT(dest, MAX_STRING_SIZE + 1);
184 va_start(ap, format);
185 vsnprintf(dest, MAX_STRING_SIZE, format, ap);
188 entry = proc_symlink(name, parent, dest);
190 CERROR("LprocFS: Could not create symbolic link from %s to %s",
193 OBD_FREE(dest, MAX_STRING_SIZE + 1);
196 EXPORT_SYMBOL(lprocfs_add_symlink);
198 static ssize_t lprocfs_fops_read(struct file *f, char __user *buf,
199 size_t size, loff_t *ppos)
201 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
202 char *page, *start = NULL;
203 int rc = 0, eof = 1, count;
205 if (*ppos >= CFS_PAGE_SIZE)
208 page = (char *)__get_free_page(GFP_KERNEL);
212 if (LPROCFS_ENTRY_AND_CHECK(dp)) {
217 OBD_FAIL_TIMEOUT(OBD_FAIL_LPROC_REMOVE, 10);
219 rc = dp->read_proc(page, &start, *ppos, CFS_PAGE_SIZE,
225 /* for lustre proc read, the read count must be less than PAGE_SIZE */
234 start = page + *ppos;
235 } else if (start < page) {
239 count = (rc < size) ? rc : size;
240 if (cfs_copy_to_user(buf, start, count)) {
247 free_page((unsigned long)page);
251 static ssize_t lprocfs_fops_write(struct file *f, const char __user *buf,
252 size_t size, loff_t *ppos)
254 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
257 if (LPROCFS_ENTRY_AND_CHECK(dp))
260 rc = dp->write_proc(f, buf, size, dp->data);
265 static struct file_operations lprocfs_generic_fops = {
266 .owner = THIS_MODULE,
267 .read = lprocfs_fops_read,
268 .write = lprocfs_fops_write,
271 int lprocfs_evict_client_open(struct inode *inode, struct file *f)
273 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
274 struct obd_device *obd = dp->data;
276 cfs_atomic_inc(&obd->obd_evict_inprogress);
281 int lprocfs_evict_client_release(struct inode *inode, struct file *f)
283 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
284 struct obd_device *obd = dp->data;
286 cfs_atomic_dec(&obd->obd_evict_inprogress);
287 cfs_waitq_signal(&obd->obd_evict_inprogress_waitq);
292 struct file_operations lprocfs_evict_client_fops = {
293 .owner = THIS_MODULE,
294 .read = lprocfs_fops_read,
295 .write = lprocfs_fops_write,
296 .open = lprocfs_evict_client_open,
297 .release = lprocfs_evict_client_release,
299 EXPORT_SYMBOL(lprocfs_evict_client_fops);
304 * \param root [in] The parent proc entry on which new entry will be added.
305 * \param list [in] Array of proc entries to be added.
306 * \param data [in] The argument to be passed when entries read/write routines
307 * are called through /proc file.
309 * \retval 0 on success
312 int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list,
317 if (root == NULL || list == NULL)
320 LPROCFS_WRITE_ENTRY();
321 while (list->name != NULL) {
322 struct proc_dir_entry *cur_root, *proc;
323 char *pathcopy, *cur, *next, pathbuf[64];
324 int pathsize = strlen(list->name) + 1;
329 /* need copy of path for strsep */
330 if (strlen(list->name) > sizeof(pathbuf) - 1) {
331 OBD_ALLOC(pathcopy, pathsize);
332 if (pathcopy == NULL)
333 GOTO(out, rc = -ENOMEM);
339 strcpy(pathcopy, list->name);
341 while (cur_root != NULL && (cur = strsep(&next, "/"))) {
342 if (*cur =='\0') /* skip double/trailing "/" */
345 proc = __lprocfs_srch(cur_root, cur);
346 CDEBUG(D_OTHER, "cur_root=%s, cur=%s, next=%s, (%s)\n",
347 cur_root->name, cur, next,
348 (proc ? "exists" : "new"));
350 cur_root = (proc ? proc :
351 proc_mkdir(cur, cur_root));
352 } else if (proc == NULL) {
354 if (list->proc_mode != 0000) {
355 mode = list->proc_mode;
359 if (list->write_fptr)
362 proc = create_proc_entry(cur, mode, cur_root);
366 if (pathcopy != pathbuf)
367 OBD_FREE(pathcopy, pathsize);
369 if (cur_root == NULL || proc == NULL) {
370 CERROR("LprocFS: No memory to create /proc entry %s",
372 GOTO(out, rc = -ENOMEM);
376 proc->proc_fops = list->fops;
378 proc->proc_fops = &lprocfs_generic_fops;
379 proc->read_proc = list->read_fptr;
380 proc->write_proc = list->write_fptr;
381 proc->data = (list->data ? list->data : data);
385 LPROCFS_WRITE_EXIT();
388 EXPORT_SYMBOL(lprocfs_add_vars);
390 void lprocfs_remove_nolock(struct proc_dir_entry **rooth)
392 struct proc_dir_entry *root = *rooth;
393 struct proc_dir_entry *temp = root;
394 struct proc_dir_entry *rm_entry;
395 struct proc_dir_entry *parent;
401 parent = root->parent;
402 LASSERT(parent != NULL);
405 while (temp->subdir != NULL)
411 /* Memory corruption once caused this to fail, and
412 without this LASSERT we would loop here forever. */
413 LASSERTF(strlen(rm_entry->name) == rm_entry->namelen,
414 "0x%p %s/%s len %d\n", rm_entry, temp->name,
415 rm_entry->name, (int)strlen(rm_entry->name));
417 remove_proc_entry(rm_entry->name, temp);
423 void lprocfs_remove(struct proc_dir_entry **rooth)
425 LPROCFS_WRITE_ENTRY(); /* search vs remove race */
426 lprocfs_remove_nolock(rooth);
427 LPROCFS_WRITE_EXIT();
429 EXPORT_SYMBOL(lprocfs_remove);
431 void lprocfs_remove_proc_entry(const char *name, struct proc_dir_entry *parent)
433 LASSERT(parent != NULL);
434 remove_proc_entry(name, parent);
436 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
438 void lprocfs_try_remove_proc_entry(const char *name,
439 struct proc_dir_entry *parent)
441 struct proc_dir_entry *t = NULL;
442 struct proc_dir_entry **p;
445 LASSERT(parent != NULL);
448 LPROCFS_WRITE_ENTRY();
450 /* lookup target name */
451 for (p = &parent->subdir; *p; p = &(*p)->next) {
452 if ((*p)->namelen != len)
454 if (memcmp(name, (*p)->name, len))
461 /* verify it's empty: do not count "num_refs" */
462 for (p = &t->subdir; *p; p = &(*p)->next) {
463 if ((*p)->namelen != strlen("num_refs")) {
467 if (memcmp("num_refs", (*p)->name,
468 strlen("num_refs"))) {
476 lprocfs_remove_nolock(&t);
478 LPROCFS_WRITE_EXIT();
482 EXPORT_SYMBOL(lprocfs_try_remove_proc_entry);
484 struct proc_dir_entry *lprocfs_register(const char *name,
485 struct proc_dir_entry *parent,
486 struct lprocfs_vars *list, void *data)
488 struct proc_dir_entry *newchild;
490 newchild = lprocfs_srch(parent, name);
491 if (newchild != NULL) {
492 CERROR(" Lproc: Attempting to register %s more than once \n",
494 return ERR_PTR(-EALREADY);
497 newchild = proc_mkdir(name, parent);
498 if (newchild != NULL && list != NULL) {
499 int rc = lprocfs_add_vars(newchild, list, data);
501 lprocfs_remove(&newchild);
507 EXPORT_SYMBOL(lprocfs_register);
509 /* Generic callbacks */
510 int lprocfs_rd_uint(char *page, char **start, off_t off,
511 int count, int *eof, void *data)
513 unsigned int *temp = data;
514 return snprintf(page, count, "%u\n", *temp);
516 EXPORT_SYMBOL(lprocfs_rd_uint);
518 int lprocfs_wr_uint(struct file *file, const char *buffer,
519 unsigned long count, void *data)
522 char dummy[MAX_STRING_SIZE + 1], *end;
525 dummy[MAX_STRING_SIZE] = '\0';
526 if (cfs_copy_from_user(dummy, buffer, MAX_STRING_SIZE))
529 tmp = simple_strtoul(dummy, &end, 0);
533 *p = (unsigned int)tmp;
536 EXPORT_SYMBOL(lprocfs_wr_uint);
538 int lprocfs_rd_u64(char *page, char **start, off_t off,
539 int count, int *eof, void *data)
541 LASSERT(data != NULL);
543 return snprintf(page, count, LPU64"\n", *(__u64 *)data);
545 EXPORT_SYMBOL(lprocfs_rd_u64);
547 int lprocfs_rd_atomic(char *page, char **start, off_t off,
548 int count, int *eof, void *data)
550 cfs_atomic_t *atom = data;
551 LASSERT(atom != NULL);
553 return snprintf(page, count, "%d\n", cfs_atomic_read(atom));
555 EXPORT_SYMBOL(lprocfs_rd_atomic);
557 int lprocfs_wr_atomic(struct file *file, const char *buffer,
558 unsigned long count, void *data)
560 cfs_atomic_t *atm = data;
564 rc = lprocfs_write_helper(buffer, count, &val);
571 cfs_atomic_set(atm, val);
574 EXPORT_SYMBOL(lprocfs_wr_atomic);
576 int lprocfs_rd_uuid(char *page, char **start, off_t off, int count,
577 int *eof, void *data)
579 struct obd_device *obd = data;
581 LASSERT(obd != NULL);
583 return snprintf(page, count, "%s\n", obd->obd_uuid.uuid);
585 EXPORT_SYMBOL(lprocfs_rd_uuid);
587 int lprocfs_rd_name(char *page, char **start, off_t off, int count,
588 int *eof, void *data)
590 struct obd_device *dev = data;
592 LASSERT(dev != NULL);
594 return snprintf(page, count, "%s\n", dev->obd_name);
596 EXPORT_SYMBOL(lprocfs_rd_name);
598 int lprocfs_rd_blksize(char *page, char **start, off_t off, int count,
599 int *eof, void *data)
601 struct obd_device *obd = data;
602 struct obd_statfs osfs;
603 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
604 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
608 rc = snprintf(page, count, "%u\n", osfs.os_bsize);
612 EXPORT_SYMBOL(lprocfs_rd_blksize);
614 int lprocfs_osd_rd_blksize(char *page, char **start, off_t off,
615 int count, int *eof, void *data)
617 struct dt_device *dt = data;
618 struct obd_statfs osfs;
619 int rc = dt_statfs(NULL, dt, &osfs);
622 rc = snprintf(page, count, "%d\n",
623 (unsigned) osfs.os_bsize);
627 EXPORT_SYMBOL(lprocfs_osd_rd_blksize);
629 int lprocfs_rd_kbytestotal(char *page, char **start, off_t off, int count,
630 int *eof, void *data)
632 struct obd_device *obd = data;
633 struct obd_statfs osfs;
634 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
635 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
638 __u32 blk_size = osfs.os_bsize >> 10;
639 __u64 result = osfs.os_blocks;
641 while (blk_size >>= 1)
645 rc = snprintf(page, count, LPU64"\n", result);
649 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
651 int lprocfs_osd_rd_kbytestotal(char *page, char **start, off_t off,
652 int count, int *eof, void *data)
654 struct dt_device *dt = data;
655 struct obd_statfs osfs;
656 int rc = dt_statfs(NULL, dt, &osfs);
658 __u32 blk_size = osfs.os_bsize >> 10;
659 __u64 result = osfs.os_blocks;
661 while (blk_size >>= 1)
665 rc = snprintf(page, count, LPU64"\n", result);
669 EXPORT_SYMBOL(lprocfs_osd_rd_kbytestotal);
671 int lprocfs_rd_kbytesfree(char *page, char **start, off_t off, int count,
672 int *eof, void *data)
674 struct obd_device *obd = data;
675 struct obd_statfs osfs;
676 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
677 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
680 __u32 blk_size = osfs.os_bsize >> 10;
681 __u64 result = osfs.os_bfree;
683 while (blk_size >>= 1)
687 rc = snprintf(page, count, LPU64"\n", result);
691 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
693 int lprocfs_osd_rd_kbytesfree(char *page, char **start, off_t off,
694 int count, int *eof, void *data)
696 struct dt_device *dt = data;
697 struct obd_statfs osfs;
698 int rc = dt_statfs(NULL, dt, &osfs);
700 __u32 blk_size = osfs.os_bsize >> 10;
701 __u64 result = osfs.os_bfree;
703 while (blk_size >>= 1)
707 rc = snprintf(page, count, LPU64"\n", result);
711 EXPORT_SYMBOL(lprocfs_osd_rd_kbytesfree);
713 int lprocfs_rd_kbytesavail(char *page, char **start, off_t off, int count,
714 int *eof, void *data)
716 struct obd_device *obd = data;
717 struct obd_statfs osfs;
718 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
719 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
722 __u32 blk_size = osfs.os_bsize >> 10;
723 __u64 result = osfs.os_bavail;
725 while (blk_size >>= 1)
729 rc = snprintf(page, count, LPU64"\n", result);
733 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
735 int lprocfs_osd_rd_kbytesavail(char *page, char **start, off_t off,
736 int count, int *eof, void *data)
738 struct dt_device *dt = data;
739 struct obd_statfs osfs;
740 int rc = dt_statfs(NULL, dt, &osfs);
742 __u32 blk_size = osfs.os_bsize >> 10;
743 __u64 result = osfs.os_bavail;
745 while (blk_size >>= 1)
749 rc = snprintf(page, count, LPU64"\n", result);
753 EXPORT_SYMBOL(lprocfs_osd_rd_kbytesavail);
755 int lprocfs_rd_filestotal(char *page, char **start, off_t off, int count,
756 int *eof, void *data)
758 struct obd_device *obd = data;
759 struct obd_statfs osfs;
760 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
761 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
765 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
770 EXPORT_SYMBOL(lprocfs_rd_filestotal);
772 int lprocfs_osd_rd_filestotal(char *page, char **start, off_t off,
773 int count, int *eof, void *data)
775 struct dt_device *dt = data;
776 struct obd_statfs osfs;
777 int rc = dt_statfs(NULL, dt, &osfs);
780 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
785 EXPORT_SYMBOL(lprocfs_osd_rd_filestotal);
787 int lprocfs_rd_filesfree(char *page, char **start, off_t off, int count,
788 int *eof, void *data)
790 struct obd_device *obd = data;
791 struct obd_statfs osfs;
792 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
793 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
797 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
801 EXPORT_SYMBOL(lprocfs_rd_filesfree);
803 int lprocfs_osd_rd_filesfree(char *page, char **start, off_t off,
804 int count, int *eof, void *data)
806 struct dt_device *dt = data;
807 struct obd_statfs osfs;
808 int rc = dt_statfs(NULL, dt, &osfs);
811 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
815 EXPORT_SYMBOL(lprocfs_osd_rd_filesfree);
817 int lprocfs_rd_server_uuid(char *page, char **start, off_t off, int count,
818 int *eof, void *data)
820 struct obd_device *obd = data;
821 struct obd_import *imp;
822 char *imp_state_name = NULL;
825 LASSERT(obd != NULL);
826 LPROCFS_CLIMP_CHECK(obd);
827 imp = obd->u.cli.cl_import;
828 imp_state_name = ptlrpc_import_state_name(imp->imp_state);
830 rc = snprintf(page, count, "%s\t%s%s\n",
831 obd2cli_tgt(obd), imp_state_name,
832 imp->imp_deactive ? "\tDEACTIVATED" : "");
834 LPROCFS_CLIMP_EXIT(obd);
837 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
839 int lprocfs_rd_conn_uuid(char *page, char **start, off_t off, int count,
840 int *eof, void *data)
842 struct obd_device *obd = data;
843 struct ptlrpc_connection *conn;
846 LASSERT(obd != NULL);
848 LPROCFS_CLIMP_CHECK(obd);
849 conn = obd->u.cli.cl_import->imp_connection;
851 if (conn && obd->u.cli.cl_import) {
852 rc = snprintf(page, count, "%s\n",
853 conn->c_remote_uuid.uuid);
855 rc = snprintf(page, count, "%s\n", "<none>");
858 LPROCFS_CLIMP_EXIT(obd);
861 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
863 /** add up per-cpu counters */
864 void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
865 struct lprocfs_counter *cnt)
867 unsigned int num_entry;
868 struct lprocfs_counter *percpu_cntr;
869 struct lprocfs_counter_header *cntr_header;
871 unsigned long flags = 0;
873 memset(cnt, 0, sizeof(*cnt));
876 /* set count to 1 to avoid divide-by-zero errs in callers */
881 cnt->lc_min = LC_MIN_INIT;
883 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
885 for (i = 0; i < num_entry; i++) {
886 if (stats->ls_percpu[i] == NULL)
888 cntr_header = &stats->ls_cnt_header[idx];
889 percpu_cntr = lprocfs_stats_counter_get(stats, i, idx);
891 cnt->lc_count += percpu_cntr->lc_count;
892 cnt->lc_sum += percpu_cntr->lc_sum;
893 if (percpu_cntr->lc_min < cnt->lc_min)
894 cnt->lc_min = percpu_cntr->lc_min;
895 if (percpu_cntr->lc_max > cnt->lc_max)
896 cnt->lc_max = percpu_cntr->lc_max;
897 cnt->lc_sumsquare += percpu_cntr->lc_sumsquare;
900 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
902 EXPORT_SYMBOL(lprocfs_stats_collect);
905 * Append a space separated list of current set flags to str.
907 #define flag2str(flag) \
908 if (imp->imp_##flag && max - len > 0) \
909 len += snprintf(str + len, max - len, "%s" #flag, len ? ", " : "");
910 static int obd_import_flags2str(struct obd_import *imp, char *str, int max)
914 if (imp->imp_obd->obd_no_recov)
915 len += snprintf(str, max - len, "no_recov");
919 flag2str(replayable);
925 static const char *obd_connect_names[] = {
939 "join_file(obsolete)",
943 "remote_client_by_force",
952 "mds_mds_connection",
955 "alt_checksum_algorithm",
981 int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
986 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
988 ret += snprintf(page + ret, count - ret, "%s%s",
989 ret ? sep : "", obd_connect_names[i]);
991 if (flags & ~(mask - 1))
992 ret += snprintf(page + ret, count - ret,
993 "%sunknown flags "LPX64,
994 ret ? sep : "", flags & ~(mask - 1));
997 EXPORT_SYMBOL(obd_connect_flags2str);
999 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
1000 int *eof, void *data)
1002 struct lprocfs_counter ret;
1003 struct lprocfs_counter_header *header;
1004 struct obd_device *obd = (struct obd_device *)data;
1005 struct obd_import *imp;
1006 struct obd_import_conn *conn;
1012 LASSERT(obd != NULL);
1013 LPROCFS_CLIMP_CHECK(obd);
1014 imp = obd->u.cli.cl_import;
1017 i = snprintf(page, count,
1023 " connect_flags: [",
1026 ptlrpc_import_state_name(imp->imp_state),
1027 imp->imp_connect_data.ocd_instance);
1028 i += obd_connect_flags2str(page + i, count - i,
1029 imp->imp_connect_data.ocd_connect_flags,
1031 i += snprintf(page + i, count - i,
1033 " import_flags: [");
1034 i += obd_import_flags2str(imp, page + i, count - i);
1036 i += snprintf(page + i, count - i,
1039 " failover_nids: [");
1040 spin_lock(&imp->imp_lock);
1042 cfs_list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
1043 i += snprintf(page + i, count - i, "%s%s", j ? ", " : "",
1044 libcfs_nid2str(conn->oic_conn->c_peer.nid));
1047 i += snprintf(page + i, count - i,
1049 " current_connection: %s\n"
1050 " connection_attempts: %u\n"
1052 " in-progress_invalidations: %u\n",
1053 imp->imp_connection == NULL ? "<none>" :
1054 libcfs_nid2str(imp->imp_connection->c_peer.nid),
1056 imp->imp_generation,
1057 cfs_atomic_read(&imp->imp_inval_count));
1058 spin_unlock(&imp->imp_lock);
1060 if (obd->obd_svc_stats == NULL)
1063 header = &obd->obd_svc_stats->ls_cnt_header[PTLRPC_REQWAIT_CNTR];
1064 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
1065 if (ret.lc_count != 0) {
1066 /* first argument to do_div MUST be __u64 */
1067 __u64 sum = ret.lc_sum;
1068 do_div(sum, ret.lc_count);
1072 i += snprintf(page + i, count - i,
1075 " unregistering: %u\n"
1077 " avg_waittime: "LPU64" %s\n",
1078 cfs_atomic_read(&imp->imp_inflight),
1079 cfs_atomic_read(&imp->imp_unregistering),
1080 cfs_atomic_read(&imp->imp_timeouts),
1081 ret.lc_sum, header->lc_units);
1084 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
1085 if (imp->imp_at.iat_portal[j] == 0)
1087 k = max_t(unsigned int, k,
1088 at_get(&imp->imp_at.iat_service_estimate[j]));
1090 i += snprintf(page + i, count - i,
1091 " service_estimates:\n"
1092 " services: %u sec\n"
1093 " network: %u sec\n",
1095 at_get(&imp->imp_at.iat_net_latency));
1097 i += snprintf(page + i, count - i,
1099 " last_replay: "LPU64"\n"
1100 " peer_committed: "LPU64"\n"
1101 " last_checked: "LPU64"\n",
1102 imp->imp_last_replay_transno,
1103 imp->imp_peer_committed_transno,
1104 imp->imp_last_transno_checked);
1106 /* avg data rates */
1107 for (rw = 0; rw <= 1; rw++) {
1108 lprocfs_stats_collect(obd->obd_svc_stats,
1109 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
1111 if (ret.lc_sum > 0 && ret.lc_count > 0) {
1112 /* first argument to do_div MUST be __u64 */
1113 __u64 sum = ret.lc_sum;
1114 do_div(sum, ret.lc_count);
1116 i += snprintf(page + i, count - i,
1117 " %s_data_averages:\n"
1118 " bytes_per_rpc: "LPU64"\n",
1119 rw ? "write" : "read",
1122 k = (int)ret.lc_sum;
1123 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
1124 header = &obd->obd_svc_stats->ls_cnt_header[j];
1125 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
1126 if (ret.lc_sum > 0 && ret.lc_count != 0) {
1127 /* first argument to do_div MUST be __u64 */
1128 __u64 sum = ret.lc_sum;
1129 do_div(sum, ret.lc_count);
1131 i += snprintf(page + i, count - i,
1132 " %s_per_rpc: "LPU64"\n",
1133 header->lc_units, ret.lc_sum);
1134 j = (int)ret.lc_sum;
1136 i += snprintf(page + i, count - i,
1137 " MB_per_sec: %u.%.02u\n",
1138 k / j, (100 * k / j) % 100);
1143 LPROCFS_CLIMP_EXIT(obd);
1146 EXPORT_SYMBOL(lprocfs_rd_import);
1148 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
1149 int *eof, void *data)
1151 struct obd_device *obd = (struct obd_device *)data;
1152 struct obd_import *imp;
1155 LASSERT(obd != NULL);
1156 LPROCFS_CLIMP_CHECK(obd);
1157 imp = obd->u.cli.cl_import;
1160 i = snprintf(page, count, "current_state: %s\n",
1161 ptlrpc_import_state_name(imp->imp_state));
1162 i += snprintf(page + i, count - i,
1163 "state_history:\n");
1164 k = imp->imp_state_hist_idx;
1165 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
1166 struct import_state_hist *ish =
1167 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
1168 if (ish->ish_state == 0)
1170 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
1172 ptlrpc_import_state_name(ish->ish_state));
1175 LPROCFS_CLIMP_EXIT(obd);
1178 EXPORT_SYMBOL(lprocfs_rd_state);
1180 int lprocfs_at_hist_helper(char *page, int count, int rc,
1181 struct adaptive_timeout *at)
1184 for (i = 0; i < AT_BINS; i++)
1185 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
1186 rc += snprintf(page + rc, count - rc, "\n");
1189 EXPORT_SYMBOL(lprocfs_at_hist_helper);
1191 /* See also ptlrpc_lprocfs_rd_timeouts */
1192 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
1193 int *eof, void *data)
1195 struct obd_device *obd = (struct obd_device *)data;
1196 struct obd_import *imp;
1197 unsigned int cur, worst;
1202 LASSERT(obd != NULL);
1203 LPROCFS_CLIMP_CHECK(obd);
1204 imp = obd->u.cli.cl_import;
1207 now = cfs_time_current_sec();
1209 /* Some network health info for kicks */
1210 s2dhms(&ts, now - imp->imp_last_reply_time);
1211 rc += snprintf(page + rc, count - rc,
1212 "%-10s : %ld, "DHMS_FMT" ago\n",
1213 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
1215 cur = at_get(&imp->imp_at.iat_net_latency);
1216 worst = imp->imp_at.iat_net_latency.at_worst_ever;
1217 worstt = imp->imp_at.iat_net_latency.at_worst_time;
1218 s2dhms(&ts, now - worstt);
1219 rc += snprintf(page + rc, count - rc,
1220 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
1221 "network", cur, worst, worstt, DHMS_VARS(&ts));
1222 rc = lprocfs_at_hist_helper(page, count, rc,
1223 &imp->imp_at.iat_net_latency);
1225 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
1226 if (imp->imp_at.iat_portal[i] == 0)
1228 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
1229 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
1230 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
1231 s2dhms(&ts, now - worstt);
1232 rc += snprintf(page + rc, count - rc,
1233 "portal %-2d : cur %3u worst %3u (at %ld, "
1234 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
1235 cur, worst, worstt, DHMS_VARS(&ts));
1236 rc = lprocfs_at_hist_helper(page, count, rc,
1237 &imp->imp_at.iat_service_estimate[i]);
1240 LPROCFS_CLIMP_EXIT(obd);
1243 EXPORT_SYMBOL(lprocfs_rd_timeouts);
1245 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1246 int count, int *eof, void *data)
1248 struct obd_device *obd = data;
1252 LPROCFS_CLIMP_CHECK(obd);
1253 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1254 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1255 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1256 ret += snprintf(page + ret, count - ret, "\n");
1257 LPROCFS_CLIMP_EXIT(obd);
1260 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1262 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1263 int *eof, void *data)
1265 struct obd_device *obd = data;
1267 LASSERT(obd != NULL);
1269 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1271 EXPORT_SYMBOL(lprocfs_rd_num_exports);
1273 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1274 int *eof, void *data)
1276 struct obd_type *class = (struct obd_type*) data;
1278 LASSERT(class != NULL);
1280 return snprintf(page, count, "%d\n", class->typ_refcnt);
1282 EXPORT_SYMBOL(lprocfs_rd_numrefs);
1284 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1288 LASSERT(obd != NULL);
1289 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1290 LASSERT(obd->obd_type->typ_procroot != NULL);
1292 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1293 obd->obd_type->typ_procroot,
1295 if (IS_ERR(obd->obd_proc_entry)) {
1296 rc = PTR_ERR(obd->obd_proc_entry);
1297 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1298 obd->obd_proc_entry = NULL;
1302 EXPORT_SYMBOL(lprocfs_obd_setup);
1304 int lprocfs_obd_cleanup(struct obd_device *obd)
1308 if (obd->obd_proc_exports_entry) {
1309 /* Should be no exports left */
1310 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1311 lprocfs_remove(&obd->obd_proc_exports_entry);
1312 obd->obd_proc_exports_entry = NULL;
1314 if (obd->obd_proc_entry) {
1315 lprocfs_remove(&obd->obd_proc_entry);
1316 obd->obd_proc_entry = NULL;
1320 EXPORT_SYMBOL(lprocfs_obd_cleanup);
1322 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1324 CDEBUG(D_CONFIG, "stat %p - data %p/%p\n", client_stat,
1325 client_stat->nid_proc, client_stat->nid_stats);
1327 LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
1328 "nid %s:count %d\n", libcfs_nid2str(client_stat->nid),
1329 atomic_read(&client_stat->nid_exp_ref_count));
1331 if (client_stat->nid_proc)
1332 lprocfs_remove(&client_stat->nid_proc);
1334 if (client_stat->nid_stats)
1335 lprocfs_free_stats(&client_stat->nid_stats);
1337 if (client_stat->nid_ldlm_stats)
1338 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1340 OBD_FREE_PTR(client_stat);
1345 void lprocfs_free_per_client_stats(struct obd_device *obd)
1347 cfs_hash_t *hash = obd->obd_nid_stats_hash;
1348 struct nid_stat *stat;
1351 /* we need extra list - because hash_exit called to early */
1352 /* not need locking because all clients is died */
1353 while (!cfs_list_empty(&obd->obd_nid_stats)) {
1354 stat = cfs_list_entry(obd->obd_nid_stats.next,
1355 struct nid_stat, nid_list);
1356 cfs_list_del_init(&stat->nid_list);
1357 cfs_hash_del(hash, &stat->nid, &stat->nid_hash);
1358 lprocfs_free_client_stats(stat);
1362 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
1364 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1365 enum lprocfs_stats_flags flags)
1367 struct lprocfs_stats *stats;
1368 unsigned int num_entry;
1369 unsigned int percpusize = 0;
1375 if (lprocfs_no_percpu_stats != 0)
1376 flags |= LPROCFS_STATS_FLAG_NOPERCPU;
1378 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1381 num_entry = cfs_num_possible_cpus();
1383 /* alloc percpu pointers for all possible cpu slots */
1384 LIBCFS_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1388 stats->ls_num = num;
1389 stats->ls_flags = flags;
1390 spin_lock_init(&stats->ls_lock);
1392 /* alloc num of counter headers */
1393 LIBCFS_ALLOC(stats->ls_cnt_header,
1394 stats->ls_num * sizeof(struct lprocfs_counter_header));
1395 if (stats->ls_cnt_header == NULL)
1398 if ((flags & LPROCFS_STATS_FLAG_NOPERCPU) != 0) {
1399 /* contains only one set counters */
1400 percpusize = lprocfs_stats_counter_size(stats);
1401 LIBCFS_ALLOC_ATOMIC(stats->ls_percpu[0], percpusize);
1402 if (stats->ls_percpu[0] == NULL)
1404 stats->ls_biggest_alloc_num = 1;
1405 } else if ((flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0) {
1406 /* alloc all percpu data, currently only obd_memory use this */
1407 for (i = 0; i < num_entry; ++i)
1408 if (lprocfs_stats_alloc_one(stats, i) < 0)
1415 lprocfs_free_stats(&stats);
1418 EXPORT_SYMBOL(lprocfs_alloc_stats);
1420 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1422 struct lprocfs_stats *stats = *statsh;
1423 unsigned int num_entry;
1424 unsigned int percpusize;
1427 if (stats == NULL || stats->ls_num == 0)
1431 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1434 num_entry = cfs_num_possible_cpus();
1436 percpusize = lprocfs_stats_counter_size(stats);
1437 for (i = 0; i < num_entry; i++)
1438 if (stats->ls_percpu[i] != NULL)
1439 LIBCFS_FREE(stats->ls_percpu[i], percpusize);
1440 if (stats->ls_cnt_header != NULL)
1441 LIBCFS_FREE(stats->ls_cnt_header, stats->ls_num *
1442 sizeof(struct lprocfs_counter_header));
1443 LIBCFS_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1445 EXPORT_SYMBOL(lprocfs_free_stats);
1447 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1449 struct lprocfs_counter *percpu_cntr;
1450 struct lprocfs_counter_header *header;
1453 unsigned int num_entry;
1454 unsigned long flags = 0;
1456 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1458 for (i = 0; i < num_entry; i++) {
1459 if (stats->ls_percpu[i] == NULL)
1461 for (j = 0; j < stats->ls_num; j++) {
1462 header = &stats->ls_cnt_header[j];
1463 percpu_cntr = lprocfs_stats_counter_get(stats, i, j);
1464 percpu_cntr->lc_count = 0;
1465 percpu_cntr->lc_min = LC_MIN_INIT;
1466 percpu_cntr->lc_max = 0;
1467 percpu_cntr->lc_sumsquare = 0;
1468 percpu_cntr->lc_sum = 0;
1469 if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
1470 percpu_cntr->lc_sum_irq = 0;
1474 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1476 EXPORT_SYMBOL(lprocfs_clear_stats);
1478 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1479 size_t len, loff_t *off)
1481 struct seq_file *seq = file->private_data;
1482 struct lprocfs_stats *stats = seq->private;
1484 lprocfs_clear_stats(stats);
1489 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1491 struct lprocfs_stats *stats = p->private;
1492 /* return 1st cpu location */
1493 return (*pos >= stats->ls_num) ? NULL :
1494 lprocfs_stats_counter_get(stats, 0, *pos);
1497 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1501 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1503 struct lprocfs_stats *stats = p->private;
1505 return (*pos >= stats->ls_num) ? NULL :
1506 lprocfs_stats_counter_get(stats, 0, *pos);
1509 /* seq file export of one lprocfs counter */
1510 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1512 struct lprocfs_stats *stats = p->private;
1513 struct lprocfs_counter *cntr = v;
1514 struct lprocfs_counter ret;
1515 struct lprocfs_counter_header *header;
1520 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
1522 cfs_gettimeofday(&now);
1523 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1524 "snapshot_time", now.tv_sec, now.tv_usec);
1528 entry_size = sizeof(*cntr);
1529 if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
1530 entry_size += sizeof(__s64);
1531 idx = ((void *)cntr - (void *)&(stats->ls_percpu[0])->lp_cntr[0]) /
1534 header = &stats->ls_cnt_header[idx];
1535 lprocfs_stats_collect(stats, idx, &ret);
1537 if (ret.lc_count == 0)
1540 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", header->lc_name,
1541 ret.lc_count, header->lc_units);
1546 if ((header->lc_config & LPROCFS_CNTR_AVGMINMAX) &&
1547 (ret.lc_count > 0)) {
1548 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1549 ret.lc_min, ret.lc_max, ret.lc_sum);
1552 if (header->lc_config & LPROCFS_CNTR_STDDEV)
1553 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1557 rc = seq_printf(p, "\n");
1559 return (rc < 0) ? rc : 0;
1562 struct seq_operations lprocfs_stats_seq_sops = {
1563 start: lprocfs_stats_seq_start,
1564 stop: lprocfs_stats_seq_stop,
1565 next: lprocfs_stats_seq_next,
1566 show: lprocfs_stats_seq_show,
1569 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1571 struct proc_dir_entry *dp = PDE(inode);
1572 struct seq_file *seq;
1575 if (LPROCFS_ENTRY_AND_CHECK(dp))
1578 rc = seq_open(file, &lprocfs_stats_seq_sops);
1583 seq = file->private_data;
1584 seq->private = dp->data;
1588 struct file_operations lprocfs_stats_seq_fops = {
1589 .owner = THIS_MODULE,
1590 .open = lprocfs_stats_seq_open,
1592 .write = lprocfs_stats_seq_write,
1593 .llseek = seq_lseek,
1594 .release = lprocfs_seq_release,
1597 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1598 struct lprocfs_stats *stats)
1600 struct proc_dir_entry *entry;
1601 LASSERT(root != NULL);
1603 LPROCFS_WRITE_ENTRY();
1604 entry = create_proc_entry(name, 0644, root);
1606 entry->proc_fops = &lprocfs_stats_seq_fops;
1607 entry->data = stats;
1610 LPROCFS_WRITE_EXIT();
1617 EXPORT_SYMBOL(lprocfs_register_stats);
1619 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1620 unsigned conf, const char *name, const char *units)
1622 struct lprocfs_counter_header *header;
1623 struct lprocfs_counter *percpu_cntr;
1624 unsigned long flags = 0;
1626 unsigned int num_cpu;
1628 LASSERT(stats != NULL);
1630 header = &stats->ls_cnt_header[index];
1631 LASSERTF(header != NULL, "Failed to allocate stats header:[%d]%s/%s\n",
1632 index, name, units);
1634 header->lc_config = conf;
1635 header->lc_name = name;
1636 header->lc_units = units;
1638 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1639 for (i = 0; i < num_cpu; ++i) {
1640 if (stats->ls_percpu[i] == NULL)
1642 percpu_cntr = lprocfs_stats_counter_get(stats, i, index);
1643 percpu_cntr->lc_count = 0;
1644 percpu_cntr->lc_min = LC_MIN_INIT;
1645 percpu_cntr->lc_max = 0;
1646 percpu_cntr->lc_sumsquare = 0;
1647 percpu_cntr->lc_sum = 0;
1648 if ((stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
1649 percpu_cntr->lc_sum_irq = 0;
1651 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1653 EXPORT_SYMBOL(lprocfs_counter_init);
1655 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1657 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1658 LASSERT(coffset < stats->ls_num); \
1659 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1662 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1664 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1665 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1666 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1667 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1668 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1669 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1670 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1671 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1672 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1673 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1674 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1675 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1676 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1677 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1678 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1679 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1680 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1681 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1682 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1683 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1684 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1685 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1686 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1687 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1688 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1689 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1690 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1691 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1692 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1693 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1694 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1695 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1696 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1697 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1698 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1699 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1700 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1701 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1702 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1703 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1704 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1705 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1706 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1707 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
1708 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1709 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1710 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1711 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1712 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1713 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1714 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1715 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1716 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1717 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1718 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1719 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1720 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1721 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1722 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1723 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1724 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1725 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1726 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1727 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1728 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1729 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1730 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1732 EXPORT_SYMBOL(lprocfs_init_ops_stats);
1734 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1736 struct lprocfs_stats *stats;
1737 unsigned int num_stats;
1740 LASSERT(obd->obd_stats == NULL);
1741 LASSERT(obd->obd_proc_entry != NULL);
1742 LASSERT(obd->obd_cntr_base == 0);
1744 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1745 num_private_stats - 1 /* o_owner */;
1746 stats = lprocfs_alloc_stats(num_stats, 0);
1750 lprocfs_init_ops_stats(num_private_stats, stats);
1752 for (i = num_private_stats; i < num_stats; i++) {
1753 /* If this LBUGs, it is likely that an obd
1754 * operation was added to struct obd_ops in
1755 * <obd.h>, and that the corresponding line item
1756 * LPROCFS_OBD_OP_INIT(.., .., opname)
1757 * is missing from the list above. */
1758 LASSERTF(stats->ls_cnt_header[i].lc_name != NULL,
1759 "Missing obd_stat initializer obd_op "
1760 "operation at offset %d.\n", i - num_private_stats);
1762 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1764 lprocfs_free_stats(&stats);
1766 obd->obd_stats = stats;
1767 obd->obd_cntr_base = num_private_stats;
1771 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
1773 void lprocfs_free_obd_stats(struct obd_device *obd)
1776 lprocfs_free_stats(&obd->obd_stats);
1778 EXPORT_SYMBOL(lprocfs_free_obd_stats);
1780 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1782 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1783 LASSERT(coffset < stats->ls_num); \
1784 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1787 void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats)
1789 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1790 LPROCFS_MD_OP_INIT(num_private_stats, stats, null_inode);
1791 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
1792 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1793 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1794 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1795 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1796 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1797 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1798 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1799 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1800 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1801 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1802 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1803 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1804 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1805 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1806 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1807 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1808 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1809 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1810 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1811 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1812 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1813 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1814 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1815 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1816 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1817 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1818 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1819 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1820 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1822 EXPORT_SYMBOL(lprocfs_init_mps_stats);
1824 int lprocfs_alloc_md_stats(struct obd_device *obd,
1825 unsigned num_private_stats)
1827 struct lprocfs_stats *stats;
1828 unsigned int num_stats;
1831 LASSERT(obd->md_stats == NULL);
1832 LASSERT(obd->obd_proc_entry != NULL);
1833 LASSERT(obd->md_cntr_base == 0);
1835 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1837 stats = lprocfs_alloc_stats(num_stats, 0);
1841 lprocfs_init_mps_stats(num_private_stats, stats);
1843 for (i = num_private_stats; i < num_stats; i++) {
1844 if (stats->ls_cnt_header[i].lc_name == NULL) {
1845 CERROR("Missing md_stat initializer md_op "
1846 "operation at offset %d. Aborting.\n",
1847 i - num_private_stats);
1851 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1853 lprocfs_free_stats(&stats);
1855 obd->md_stats = stats;
1856 obd->md_cntr_base = num_private_stats;
1860 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
1862 void lprocfs_free_md_stats(struct obd_device *obd)
1864 struct lprocfs_stats *stats = obd->md_stats;
1866 if (stats != NULL) {
1867 obd->md_stats = NULL;
1868 obd->md_cntr_base = 0;
1869 lprocfs_free_stats(&stats);
1872 EXPORT_SYMBOL(lprocfs_free_md_stats);
1874 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1876 lprocfs_counter_init(ldlm_stats,
1877 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1878 0, "ldlm_enqueue", "reqs");
1879 lprocfs_counter_init(ldlm_stats,
1880 LDLM_CONVERT - LDLM_FIRST_OPC,
1881 0, "ldlm_convert", "reqs");
1882 lprocfs_counter_init(ldlm_stats,
1883 LDLM_CANCEL - LDLM_FIRST_OPC,
1884 0, "ldlm_cancel", "reqs");
1885 lprocfs_counter_init(ldlm_stats,
1886 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1887 0, "ldlm_bl_callback", "reqs");
1888 lprocfs_counter_init(ldlm_stats,
1889 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1890 0, "ldlm_cp_callback", "reqs");
1891 lprocfs_counter_init(ldlm_stats,
1892 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1893 0, "ldlm_gl_callback", "reqs");
1895 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
1897 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1898 int *eof, void *data)
1900 struct obd_export *exp = data;
1901 LASSERT(exp != NULL);
1903 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1906 struct exp_uuid_cb_data {
1914 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1915 int count, int *eof, int *len)
1917 cb_data->page = page;
1918 cb_data->count = count;
1923 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1924 cfs_hlist_node_t *hnode, void *cb_data)
1927 struct obd_export *exp = cfs_hash_object(hs, hnode);
1928 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1930 if (exp->exp_nid_stats)
1931 *data->len += snprintf((data->page + *data->len),
1932 data->count, "%s\n",
1933 obd_uuid2str(&exp->exp_client_uuid));
1937 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1938 int *eof, void *data)
1940 struct nid_stat *stats = (struct nid_stat *)data;
1941 struct exp_uuid_cb_data cb_data;
1942 struct obd_device *obd = stats->nid_obd;
1947 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1948 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1949 lprocfs_exp_print_uuid, &cb_data);
1950 return (*cb_data.len);
1953 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1954 cfs_hlist_node_t *hnode, void *cb_data)
1957 struct exp_uuid_cb_data *data = cb_data;
1958 struct obd_export *exp = cfs_hash_object(hs, hnode);
1960 if (exp->exp_lock_hash != NULL) {
1962 *data->len += cfs_hash_debug_header(data->page,
1965 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1972 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1973 int *eof, void *data)
1975 struct nid_stat *stats = (struct nid_stat *)data;
1976 struct exp_uuid_cb_data cb_data;
1977 struct obd_device *obd = stats->nid_obd;
1982 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1984 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1985 lprocfs_exp_print_hash, &cb_data);
1986 return (*cb_data.len);
1989 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1990 int count, int *eof, void *data)
1993 return snprintf(page, count, "%s\n",
1994 "Write into this file to clear all nid stats and "
1995 "stale nid entries");
1997 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1999 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
2001 struct nid_stat *stat = obj;
2004 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
2005 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 1) {
2006 /* object has only hash references. */
2007 spin_lock(&stat->nid_obd->obd_nid_lock);
2008 cfs_list_move(&stat->nid_list, data);
2009 spin_unlock(&stat->nid_obd->obd_nid_lock);
2012 /* we has reference to object - only clear data*/
2013 if (stat->nid_stats)
2014 lprocfs_clear_stats(stat->nid_stats);
2019 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
2020 unsigned long count, void *data)
2022 struct obd_device *obd = (struct obd_device *)data;
2023 struct nid_stat *client_stat;
2024 CFS_LIST_HEAD(free_list);
2026 cfs_hash_cond_del(obd->obd_nid_stats_hash,
2027 lprocfs_nid_stats_clear_write_cb, &free_list);
2029 while (!cfs_list_empty(&free_list)) {
2030 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
2032 cfs_list_del_init(&client_stat->nid_list);
2033 lprocfs_free_client_stats(client_stat);
2038 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
2040 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
2042 struct nid_stat *new_stat, *old_stat;
2043 struct obd_device *obd = NULL;
2044 cfs_proc_dir_entry_t *entry;
2045 char *buffer = NULL;
2051 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
2052 !exp->exp_obd->obd_nid_stats_hash)
2055 /* not test against zero because eric say:
2056 * You may only test nid against another nid, or LNET_NID_ANY.
2057 * Anything else is nonsense.*/
2058 if (!nid || *nid == LNET_NID_ANY)
2063 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
2065 OBD_ALLOC_PTR(new_stat);
2066 if (new_stat == NULL)
2069 new_stat->nid = *nid;
2070 new_stat->nid_obd = exp->exp_obd;
2071 /* we need set default refcount to 1 to balance obd_disconnect */
2072 cfs_atomic_set(&new_stat->nid_exp_ref_count, 1);
2074 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
2075 nid, &new_stat->nid_hash);
2076 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
2077 old_stat, libcfs_nid2str(*nid),
2078 cfs_atomic_read(&new_stat->nid_exp_ref_count));
2080 /* We need to release old stats because lprocfs_exp_cleanup() hasn't
2081 * been and will never be called. */
2082 if (exp->exp_nid_stats) {
2083 nidstat_putref(exp->exp_nid_stats);
2084 exp->exp_nid_stats = NULL;
2087 /* Return -EALREADY here so that we know that the /proc
2088 * entry already has been created */
2089 if (old_stat != new_stat) {
2090 exp->exp_nid_stats = old_stat;
2091 GOTO(destroy_new, rc = -EALREADY);
2093 /* not found - create */
2094 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
2096 GOTO(destroy_new, rc = -ENOMEM);
2098 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
2099 new_stat->nid_proc = lprocfs_register(buffer,
2100 obd->obd_proc_exports_entry,
2102 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
2104 if (new_stat->nid_proc == NULL) {
2105 CERROR("Error making export directory for nid %s\n",
2106 libcfs_nid2str(*nid));
2107 GOTO(destroy_new_ns, rc = -ENOMEM);
2110 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
2111 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
2112 if (IS_ERR(entry)) {
2113 CWARN("Error adding the NID stats file\n");
2114 rc = PTR_ERR(entry);
2115 GOTO(destroy_new_ns, rc);
2118 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
2119 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
2120 if (IS_ERR(entry)) {
2121 CWARN("Error adding the hash file\n");
2122 rc = PTR_ERR(entry);
2123 GOTO(destroy_new_ns, rc);
2126 exp->exp_nid_stats = new_stat;
2128 /* protect competitive add to list, not need locking on destroy */
2129 spin_lock(&obd->obd_nid_lock);
2130 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
2131 spin_unlock(&obd->obd_nid_lock);
2136 if (new_stat->nid_proc != NULL)
2137 lprocfs_remove(&new_stat->nid_proc);
2138 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
2141 nidstat_putref(new_stat);
2142 OBD_FREE_PTR(new_stat);
2145 EXPORT_SYMBOL(lprocfs_exp_setup);
2147 int lprocfs_exp_cleanup(struct obd_export *exp)
2149 struct nid_stat *stat = exp->exp_nid_stats;
2151 if(!stat || !exp->exp_obd)
2154 nidstat_putref(exp->exp_nid_stats);
2155 exp->exp_nid_stats = NULL;
2159 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2161 int lprocfs_write_helper(const char *buffer, unsigned long count,
2164 return lprocfs_write_frac_helper(buffer, count, val, 1);
2166 EXPORT_SYMBOL(lprocfs_write_helper);
2168 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
2171 char kernbuf[20], *end, *pbuf;
2173 if (count > (sizeof(kernbuf) - 1))
2176 if (cfs_copy_from_user(kernbuf, buffer, count))
2179 kernbuf[count] = '\0';
2186 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2190 if (end != NULL && *end == '.') {
2191 int temp_val, pow = 1;
2195 if (strlen(pbuf) > 5)
2196 pbuf[5] = '\0'; /*only allow 5bits fractional*/
2198 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2201 for (i = 0; i < (end - pbuf); i++)
2204 *val += temp_val / pow;
2209 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2211 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
2214 long decimal_val, frac_val;
2220 decimal_val = val / mult;
2221 prtn = snprintf(buffer, count, "%ld", decimal_val);
2222 frac_val = val % mult;
2224 if (prtn < (count - 4) && frac_val > 0) {
2226 int i, temp_mult = 1, frac_bits = 0;
2228 temp_frac = frac_val * 10;
2229 buffer[prtn++] = '.';
2230 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
2231 /* only reserved 2 bits fraction */
2232 buffer[prtn++] ='0';
2237 * Need to think these cases :
2238 * 1. #echo x.00 > /proc/xxx output result : x
2239 * 2. #echo x.0x > /proc/xxx output result : x.0x
2240 * 3. #echo x.x0 > /proc/xxx output result : x.x
2241 * 4. #echo x.xx > /proc/xxx output result : x.xx
2242 * Only reserved 2 bits fraction.
2244 for (i = 0; i < (5 - prtn); i++)
2247 frac_bits = min((int)count - prtn, 3 - frac_bits);
2248 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
2249 frac_val * temp_mult / mult);
2252 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
2254 if (buffer[prtn] == '.') {
2261 buffer[prtn++] ='\n';
2264 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2266 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
2268 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
2270 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2272 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
2273 __u64 *val, int mult)
2275 char kernbuf[22], *end, *pbuf;
2276 __u64 whole, frac = 0, units;
2277 unsigned frac_d = 1;
2279 if (count > (sizeof(kernbuf) - 1))
2282 if (cfs_copy_from_user(kernbuf, buffer, count))
2285 kernbuf[count] = '\0';
2292 whole = simple_strtoull(pbuf, &end, 10);
2296 if (end != NULL && *end == '.') {
2300 /* need to limit frac_d to a __u32 */
2301 if (strlen(pbuf) > 10)
2304 frac = simple_strtoull(pbuf, &end, 10);
2305 /* count decimal places */
2306 for (i = 0; i < (end - pbuf); i++)
2323 /* Specified units override the multiplier */
2325 mult = mult < 0 ? -units : units;
2328 do_div(frac, frac_d);
2329 *val = whole * mult + frac;
2332 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2334 static char *lprocfs_strnstr(const char *s1, const char *s2, size_t len)
2343 if (!memcmp(s1, s2, l2))
2351 * Find the string \a name in the input \a buffer, and return a pointer to the
2352 * value immediately following \a name, reducing \a count appropriately.
2353 * If \a name is not found the original \a buffer is returned.
2355 char *lprocfs_find_named_value(const char *buffer, const char *name,
2356 unsigned long *count)
2359 size_t buflen = *count;
2361 /* there is no strnstr() in rhel5 and ubuntu kernels */
2362 val = lprocfs_strnstr(buffer, name, buflen);
2364 return (char *)buffer;
2366 val += strlen(name); /* skip prefix */
2367 while (val < buffer + buflen && isspace(*val)) /* skip separator */
2371 while (val < buffer + buflen && isalnum(*val)) {
2376 return val - *count;
2378 EXPORT_SYMBOL(lprocfs_find_named_value);
2380 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent,
2383 const struct file_operations *seq_fops,
2386 struct proc_dir_entry *entry;
2389 /* Disallow secretly (un)writable entries. */
2390 LASSERT((seq_fops->write == NULL) == ((mode & 0222) == 0));
2392 LPROCFS_WRITE_ENTRY();
2393 entry = create_proc_entry(name, mode, parent);
2395 entry->proc_fops = seq_fops;
2398 LPROCFS_WRITE_EXIT();
2405 EXPORT_SYMBOL(lprocfs_seq_create);
2407 int lprocfs_obd_seq_create(struct obd_device *dev,
2410 const struct file_operations *seq_fops,
2413 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2414 mode, seq_fops, data));
2416 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2418 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2420 if (value >= OBD_HIST_MAX)
2421 value = OBD_HIST_MAX - 1;
2423 spin_lock(&oh->oh_lock);
2424 oh->oh_buckets[value]++;
2425 spin_unlock(&oh->oh_lock);
2427 EXPORT_SYMBOL(lprocfs_oh_tally);
2429 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2433 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2436 lprocfs_oh_tally(oh, val);
2438 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2440 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2442 unsigned long ret = 0;
2445 for (i = 0; i < OBD_HIST_MAX; i++)
2446 ret += oh->oh_buckets[i];
2449 EXPORT_SYMBOL(lprocfs_oh_sum);
2451 void lprocfs_oh_clear(struct obd_histogram *oh)
2453 spin_lock(&oh->oh_lock);
2454 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2455 spin_unlock(&oh->oh_lock);
2457 EXPORT_SYMBOL(lprocfs_oh_clear);
2459 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2460 int count, int *eof, void *data)
2462 struct obd_device *obd = data;
2468 c += cfs_hash_debug_header(page, count);
2469 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2470 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2471 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2475 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2477 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2478 int count, int *eof, void *data)
2480 struct obd_device *obd = data;
2483 LASSERT(obd != NULL);
2484 LASSERT(count >= 0);
2486 /* Set start of user data returned to
2487 page + off since the user may have
2488 requested to read much smaller than
2489 what we need to read */
2490 *start = page + off;
2492 /* We know we are allocated a page here.
2493 Also we know that this function will
2494 not need to write more than a page
2495 so we can truncate at CFS_PAGE_SIZE. */
2496 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2498 /* Initialize the page */
2499 memset(page, 0, size);
2501 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2503 if (obd->obd_max_recoverable_clients == 0) {
2504 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2510 /* sampled unlocked, but really... */
2511 if (obd->obd_recovering == 0) {
2512 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2514 if (lprocfs_obd_snprintf(&page, size, &len,
2515 "recovery_start: %lu\n",
2516 obd->obd_recovery_start) <= 0)
2518 if (lprocfs_obd_snprintf(&page, size, &len,
2519 "recovery_duration: %lu\n",
2520 obd->obd_recovery_end -
2521 obd->obd_recovery_start) <= 0)
2523 /* Number of clients that have completed recovery */
2524 if (lprocfs_obd_snprintf(&page, size, &len,
2525 "completed_clients: %d/%d\n",
2526 obd->obd_max_recoverable_clients -
2527 obd->obd_stale_clients,
2528 obd->obd_max_recoverable_clients) <= 0)
2530 if (lprocfs_obd_snprintf(&page, size, &len,
2531 "replayed_requests: %d\n",
2532 obd->obd_replayed_requests) <= 0)
2534 if (lprocfs_obd_snprintf(&page, size, &len,
2535 "last_transno: "LPD64"\n",
2536 obd->obd_next_recovery_transno - 1)<=0)
2538 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2539 obd->obd_version_recov ?
2540 "ENABLED" : "DISABLED") <=0)
2542 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
2544 "DISABLED" : "ENABLED") <= 0)
2549 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2551 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2552 obd->obd_recovery_start) <= 0)
2554 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2555 cfs_time_current_sec() >=
2556 obd->obd_recovery_start +
2557 obd->obd_recovery_timeout ? 0 :
2558 obd->obd_recovery_start +
2559 obd->obd_recovery_timeout -
2560 cfs_time_current_sec()) <= 0)
2562 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2563 cfs_atomic_read(&obd->obd_connected_clients),
2564 obd->obd_max_recoverable_clients) <= 0)
2566 /* Number of clients that have completed recovery */
2567 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2568 cfs_atomic_read(&obd->obd_req_replay_clients))
2571 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2572 cfs_atomic_read(&obd->obd_lock_replay_clients))
2575 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2576 cfs_atomic_read(&obd->obd_connected_clients) -
2577 cfs_atomic_read(&obd->obd_lock_replay_clients))
2580 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2581 obd->obd_stale_clients) <= 0)
2583 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2584 obd->obd_replayed_requests) <= 0)
2586 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2587 obd->obd_requests_queued_for_recovery) <= 0)
2590 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2591 obd->obd_next_recovery_transno) <= 0)
2597 return min(count, len - (int)off);
2599 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2601 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
2602 int count, int *eof, void *data)
2604 struct obd_device *obd = (struct obd_device *)data;
2605 LASSERT(obd != NULL);
2607 return snprintf(page, count, "%d\n",
2608 obd->obd_recovery_ir_factor);
2610 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
2612 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
2613 unsigned long count, void *data)
2615 struct obd_device *obd = (struct obd_device *)data;
2617 LASSERT(obd != NULL);
2619 rc = lprocfs_write_helper(buffer, count, &val);
2623 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
2626 obd->obd_recovery_ir_factor = val;
2629 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
2631 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
2632 int count, int *eof, void *data)
2634 struct obd_device *obd = (struct obd_device *)data;
2635 LASSERT(obd != NULL);
2637 return snprintf(page, count, "%d\n",
2638 obd->obd_recovery_timeout);
2640 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
2642 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
2643 unsigned long count, void *data)
2645 struct obd_device *obd = (struct obd_device *)data;
2647 LASSERT(obd != NULL);
2649 rc = lprocfs_write_helper(buffer, count, &val);
2653 obd->obd_recovery_timeout = val;
2656 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
2658 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
2659 int count, int *eof, void *data)
2661 struct obd_device *obd = data;
2662 LASSERT(obd != NULL);
2664 return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
2666 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
2668 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
2669 unsigned long count, void *data)
2671 struct obd_device *obd = data;
2673 LASSERT(obd != NULL);
2675 rc = lprocfs_write_helper(buffer, count, &val);
2679 obd->obd_recovery_time_hard = val;
2682 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
2684 int lprocfs_obd_rd_mntdev(char *page, char **start, off_t off,
2685 int count, int *eof, void *data)
2687 struct obd_device *obd = (struct obd_device *)data;
2688 struct lustre_mount_info *lmi;
2689 const char *dev_name;
2691 LASSERT(obd != NULL);
2692 lmi = server_get_mount_2(obd->obd_name);
2693 dev_name = get_mntdev_name(lmi->lmi_sb);
2694 LASSERT(dev_name != NULL);
2696 server_put_mount_2(obd->obd_name, lmi->lmi_mnt);
2697 return snprintf(page, count, "%s\n", dev_name);
2699 EXPORT_SYMBOL(lprocfs_obd_rd_mntdev);
2701 int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
2702 int count, int *eof, void *data)
2704 struct obd_device *dev = data;
2705 struct client_obd *cli = &dev->u.cli;
2708 client_obd_list_lock(&cli->cl_loi_list_lock);
2709 rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
2710 client_obd_list_unlock(&cli->cl_loi_list_lock);
2713 EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
2715 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
2716 int count, int *eof, void *data)
2718 struct obd_device *obd = (struct obd_device *)data;
2719 struct obd_device_target *target = &obd->u.obt;
2721 LASSERT(obd != NULL);
2722 LASSERT(target->obt_magic == OBT_MAGIC);
2724 return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
2726 EXPORT_SYMBOL(lprocfs_target_rd_instance);