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, Whamcloud, Inc.
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/lustre_idl.h>
52 #include <dt_object.h>
56 static int lprocfs_no_percpu_stats = 0;
57 CFS_MODULE_PARM(lprocfs_no_percpu_stats, "i", int, 0644,
58 "Do not alloc percpu data for lprocfs stats");
60 #define MAX_STRING_SIZE 128
62 /* for bug 10866, global variable */
63 DECLARE_RWSEM(_lprocfs_lock);
64 EXPORT_SYMBOL(_lprocfs_lock);
66 int lprocfs_single_release(struct inode *inode, struct file *file)
69 return single_release(inode, file);
71 EXPORT_SYMBOL(lprocfs_single_release);
73 int lprocfs_seq_release(struct inode *inode, struct file *file)
76 return seq_release(inode, file);
78 EXPORT_SYMBOL(lprocfs_seq_release);
80 static struct proc_dir_entry *__lprocfs_srch(struct proc_dir_entry *head,
83 struct proc_dir_entry *temp;
89 while (temp != NULL) {
90 if (strcmp(temp->name, name) == 0) {
99 struct proc_dir_entry *lprocfs_srch(struct proc_dir_entry *head,
102 struct proc_dir_entry *temp;
104 LPROCFS_SRCH_ENTRY();
105 temp = __lprocfs_srch(head, name);
109 EXPORT_SYMBOL(lprocfs_srch);
111 /* lprocfs API calls */
113 /* Function that emulates snprintf but also has the side effect of advancing
114 the page pointer for the next write into the buffer, incrementing the total
115 length written to the buffer, and decrementing the size left in the
117 static int lprocfs_obd_snprintf(char **page, int end, int *len,
118 const char *format, ...)
126 va_start(list, format);
127 n = vsnprintf(*page, end - *len, format, list);
130 *page += n; *len += n;
134 cfs_proc_dir_entry_t *lprocfs_add_simple(struct proc_dir_entry *root,
136 read_proc_t *read_proc,
137 write_proc_t *write_proc,
139 struct file_operations *fops)
141 cfs_proc_dir_entry_t *proc;
144 if (root == NULL || name == NULL)
145 return ERR_PTR(-EINVAL);
152 LPROCFS_WRITE_ENTRY();
153 proc = create_proc_entry(name, mode, root);
155 CERROR("LprocFS: No memory to create /proc entry %s", name);
156 LPROCFS_WRITE_EXIT();
157 return ERR_PTR(-ENOMEM);
159 proc->read_proc = read_proc;
160 proc->write_proc = write_proc;
163 proc->proc_fops = fops;
164 LPROCFS_WRITE_EXIT();
167 EXPORT_SYMBOL(lprocfs_add_simple);
169 struct proc_dir_entry *lprocfs_add_symlink(const char *name,
170 struct proc_dir_entry *parent, const char *format, ...)
172 struct proc_dir_entry *entry;
176 if (parent == NULL || format == NULL)
179 OBD_ALLOC_WAIT(dest, MAX_STRING_SIZE + 1);
183 va_start(ap, format);
184 vsnprintf(dest, MAX_STRING_SIZE, format, ap);
187 entry = proc_symlink(name, parent, dest);
189 CERROR("LprocFS: Could not create symbolic link from %s to %s",
192 OBD_FREE(dest, MAX_STRING_SIZE + 1);
195 EXPORT_SYMBOL(lprocfs_add_symlink);
197 static ssize_t lprocfs_fops_read(struct file *f, char __user *buf,
198 size_t size, loff_t *ppos)
200 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
201 char *page, *start = NULL;
202 int rc = 0, eof = 1, count;
204 if (*ppos >= CFS_PAGE_SIZE)
207 page = (char *)__get_free_page(GFP_KERNEL);
211 if (LPROCFS_ENTRY_AND_CHECK(dp)) {
216 OBD_FAIL_TIMEOUT(OBD_FAIL_LPROC_REMOVE, 10);
218 rc = dp->read_proc(page, &start, *ppos, CFS_PAGE_SIZE,
224 /* for lustre proc read, the read count must be less than PAGE_SIZE */
233 start = page + *ppos;
234 } else if (start < page) {
238 count = (rc < size) ? rc : size;
239 if (cfs_copy_to_user(buf, start, count)) {
246 free_page((unsigned long)page);
250 static ssize_t lprocfs_fops_write(struct file *f, const char __user *buf,
251 size_t size, loff_t *ppos)
253 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
256 if (LPROCFS_ENTRY_AND_CHECK(dp))
259 rc = dp->write_proc(f, buf, size, dp->data);
264 static struct file_operations lprocfs_generic_fops = {
265 .owner = THIS_MODULE,
266 .read = lprocfs_fops_read,
267 .write = lprocfs_fops_write,
270 int lprocfs_evict_client_open(struct inode *inode, struct file *f)
272 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
273 struct obd_device *obd = dp->data;
275 cfs_atomic_inc(&obd->obd_evict_inprogress);
280 int lprocfs_evict_client_release(struct inode *inode, struct file *f)
282 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
283 struct obd_device *obd = dp->data;
285 cfs_atomic_dec(&obd->obd_evict_inprogress);
286 cfs_waitq_signal(&obd->obd_evict_inprogress_waitq);
291 struct file_operations lprocfs_evict_client_fops = {
292 .owner = THIS_MODULE,
293 .read = lprocfs_fops_read,
294 .write = lprocfs_fops_write,
295 .open = lprocfs_evict_client_open,
296 .release = lprocfs_evict_client_release,
298 EXPORT_SYMBOL(lprocfs_evict_client_fops);
303 * \param root [in] The parent proc entry on which new entry will be added.
304 * \param list [in] Array of proc entries to be added.
305 * \param data [in] The argument to be passed when entries read/write routines
306 * are called through /proc file.
308 * \retval 0 on success
311 int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list,
316 if (root == NULL || list == NULL)
319 LPROCFS_WRITE_ENTRY();
320 while (list->name != NULL) {
321 struct proc_dir_entry *cur_root, *proc;
322 char *pathcopy, *cur, *next, pathbuf[64];
323 int pathsize = strlen(list->name) + 1;
328 /* need copy of path for strsep */
329 if (strlen(list->name) > sizeof(pathbuf) - 1) {
330 OBD_ALLOC(pathcopy, pathsize);
331 if (pathcopy == NULL)
332 GOTO(out, rc = -ENOMEM);
338 strcpy(pathcopy, list->name);
340 while (cur_root != NULL && (cur = strsep(&next, "/"))) {
341 if (*cur =='\0') /* skip double/trailing "/" */
344 proc = __lprocfs_srch(cur_root, cur);
345 CDEBUG(D_OTHER, "cur_root=%s, cur=%s, next=%s, (%s)\n",
346 cur_root->name, cur, next,
347 (proc ? "exists" : "new"));
349 cur_root = (proc ? proc :
350 proc_mkdir(cur, cur_root));
351 } else if (proc == NULL) {
353 if (list->proc_mode != 0000) {
354 mode = list->proc_mode;
358 if (list->write_fptr)
361 proc = create_proc_entry(cur, mode, cur_root);
365 if (pathcopy != pathbuf)
366 OBD_FREE(pathcopy, pathsize);
368 if (cur_root == NULL || proc == NULL) {
369 CERROR("LprocFS: No memory to create /proc entry %s",
371 GOTO(out, rc = -ENOMEM);
375 proc->proc_fops = list->fops;
377 proc->proc_fops = &lprocfs_generic_fops;
378 proc->read_proc = list->read_fptr;
379 proc->write_proc = list->write_fptr;
380 proc->data = (list->data ? list->data : data);
384 LPROCFS_WRITE_EXIT();
387 EXPORT_SYMBOL(lprocfs_add_vars);
389 void lprocfs_remove_nolock(struct proc_dir_entry **rooth)
391 struct proc_dir_entry *root = *rooth;
392 struct proc_dir_entry *temp = root;
393 struct proc_dir_entry *rm_entry;
394 struct proc_dir_entry *parent;
400 parent = root->parent;
401 LASSERT(parent != NULL);
404 while (temp->subdir != NULL)
410 /* Memory corruption once caused this to fail, and
411 without this LASSERT we would loop here forever. */
412 LASSERTF(strlen(rm_entry->name) == rm_entry->namelen,
413 "0x%p %s/%s len %d\n", rm_entry, temp->name,
414 rm_entry->name, (int)strlen(rm_entry->name));
416 remove_proc_entry(rm_entry->name, temp);
422 void lprocfs_remove(struct proc_dir_entry **rooth)
424 LPROCFS_WRITE_ENTRY(); /* search vs remove race */
425 lprocfs_remove_nolock(rooth);
426 LPROCFS_WRITE_EXIT();
428 EXPORT_SYMBOL(lprocfs_remove);
430 void lprocfs_remove_proc_entry(const char *name, struct proc_dir_entry *parent)
432 LASSERT(parent != NULL);
433 remove_proc_entry(name, parent);
435 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
437 void lprocfs_try_remove_proc_entry(const char *name,
438 struct proc_dir_entry *parent)
440 struct proc_dir_entry *t = NULL;
441 struct proc_dir_entry **p;
444 LASSERT(parent != NULL);
447 LPROCFS_WRITE_ENTRY();
449 /* lookup target name */
450 for (p = &parent->subdir; *p; p = &(*p)->next) {
451 if ((*p)->namelen != len)
453 if (memcmp(name, (*p)->name, len))
460 /* verify it's empty: do not count "num_refs" */
461 for (p = &t->subdir; *p; p = &(*p)->next) {
462 if ((*p)->namelen != strlen("num_refs")) {
466 if (memcmp("num_refs", (*p)->name,
467 strlen("num_refs"))) {
475 lprocfs_remove_nolock(&t);
477 LPROCFS_WRITE_EXIT();
481 EXPORT_SYMBOL(lprocfs_try_remove_proc_entry);
483 struct proc_dir_entry *lprocfs_register(const char *name,
484 struct proc_dir_entry *parent,
485 struct lprocfs_vars *list, void *data)
487 struct proc_dir_entry *newchild;
489 newchild = lprocfs_srch(parent, name);
490 if (newchild != NULL) {
491 CERROR(" Lproc: Attempting to register %s more than once \n",
493 return ERR_PTR(-EALREADY);
496 newchild = proc_mkdir(name, parent);
497 if (newchild != NULL && list != NULL) {
498 int rc = lprocfs_add_vars(newchild, list, data);
500 lprocfs_remove(&newchild);
506 EXPORT_SYMBOL(lprocfs_register);
508 /* Generic callbacks */
509 int lprocfs_rd_uint(char *page, char **start, off_t off,
510 int count, int *eof, void *data)
512 unsigned int *temp = data;
513 return snprintf(page, count, "%u\n", *temp);
515 EXPORT_SYMBOL(lprocfs_rd_uint);
517 int lprocfs_wr_uint(struct file *file, const char *buffer,
518 unsigned long count, void *data)
521 char dummy[MAX_STRING_SIZE + 1], *end;
524 dummy[MAX_STRING_SIZE] = '\0';
525 if (cfs_copy_from_user(dummy, buffer, MAX_STRING_SIZE))
528 tmp = simple_strtoul(dummy, &end, 0);
532 *p = (unsigned int)tmp;
535 EXPORT_SYMBOL(lprocfs_wr_uint);
537 int lprocfs_rd_u64(char *page, char **start, off_t off,
538 int count, int *eof, void *data)
540 LASSERT(data != NULL);
542 return snprintf(page, count, LPU64"\n", *(__u64 *)data);
544 EXPORT_SYMBOL(lprocfs_rd_u64);
546 int lprocfs_rd_atomic(char *page, char **start, off_t off,
547 int count, int *eof, void *data)
549 cfs_atomic_t *atom = data;
550 LASSERT(atom != NULL);
552 return snprintf(page, count, "%d\n", cfs_atomic_read(atom));
554 EXPORT_SYMBOL(lprocfs_rd_atomic);
556 int lprocfs_wr_atomic(struct file *file, const char *buffer,
557 unsigned long count, void *data)
559 cfs_atomic_t *atm = data;
563 rc = lprocfs_write_helper(buffer, count, &val);
570 cfs_atomic_set(atm, val);
573 EXPORT_SYMBOL(lprocfs_wr_atomic);
575 int lprocfs_rd_uuid(char *page, char **start, off_t off, int count,
576 int *eof, void *data)
578 struct obd_device *obd = data;
580 LASSERT(obd != NULL);
582 return snprintf(page, count, "%s\n", obd->obd_uuid.uuid);
584 EXPORT_SYMBOL(lprocfs_rd_uuid);
586 int lprocfs_rd_name(char *page, char **start, off_t off, int count,
587 int *eof, void *data)
589 struct obd_device *dev = data;
591 LASSERT(dev != NULL);
592 LASSERT(dev->obd_name != NULL);
594 return snprintf(page, count, "%s\n", dev->obd_name);
596 EXPORT_SYMBOL(lprocfs_rd_name);
598 int lprocfs_rd_fstype(char *page, char **start, off_t off, int count, int *eof,
601 struct obd_device *obd = data;
603 LASSERT(obd != NULL);
604 LASSERT(obd->obd_fsops != NULL);
605 LASSERT(obd->obd_fsops->fs_type != NULL);
606 return snprintf(page, count, "%s\n", obd->obd_fsops->fs_type);
608 EXPORT_SYMBOL(lprocfs_rd_fstype);
610 int lprocfs_rd_blksize(char *page, char **start, off_t off, int count,
611 int *eof, void *data)
613 struct obd_device *obd = data;
614 struct obd_statfs osfs;
615 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
616 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
620 rc = snprintf(page, count, "%u\n", osfs.os_bsize);
624 EXPORT_SYMBOL(lprocfs_rd_blksize);
626 int lprocfs_osd_rd_blksize(char *page, char **start, off_t off,
627 int count, int *eof, void *data)
629 struct dt_device *dt = data;
630 struct obd_statfs osfs;
631 int rc = dt_statfs(NULL, dt, &osfs);
634 rc = snprintf(page, count, "%d\n",
635 (unsigned) osfs.os_bsize);
639 EXPORT_SYMBOL(lprocfs_osd_rd_blksize);
641 int lprocfs_rd_kbytestotal(char *page, char **start, off_t off, int count,
642 int *eof, void *data)
644 struct obd_device *obd = data;
645 struct obd_statfs osfs;
646 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
647 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
650 __u32 blk_size = osfs.os_bsize >> 10;
651 __u64 result = osfs.os_blocks;
653 while (blk_size >>= 1)
657 rc = snprintf(page, count, LPU64"\n", result);
661 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
663 int lprocfs_osd_rd_kbytestotal(char *page, char **start, off_t off,
664 int count, int *eof, void *data)
666 struct dt_device *dt = data;
667 struct obd_statfs osfs;
668 int rc = dt_statfs(NULL, dt, &osfs);
670 __u32 blk_size = osfs.os_bsize >> 10;
671 __u64 result = osfs.os_blocks;
673 while (blk_size >>= 1)
677 rc = snprintf(page, count, LPU64"\n", result);
681 EXPORT_SYMBOL(lprocfs_osd_rd_kbytestotal);
683 int lprocfs_rd_kbytesfree(char *page, char **start, off_t off, int count,
684 int *eof, void *data)
686 struct obd_device *obd = data;
687 struct obd_statfs osfs;
688 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
689 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
692 __u32 blk_size = osfs.os_bsize >> 10;
693 __u64 result = osfs.os_bfree;
695 while (blk_size >>= 1)
699 rc = snprintf(page, count, LPU64"\n", result);
703 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
705 int lprocfs_osd_rd_kbytesfree(char *page, char **start, off_t off,
706 int count, int *eof, void *data)
708 struct dt_device *dt = data;
709 struct obd_statfs osfs;
710 int rc = dt_statfs(NULL, dt, &osfs);
712 __u32 blk_size = osfs.os_bsize >> 10;
713 __u64 result = osfs.os_bfree;
715 while (blk_size >>= 1)
719 rc = snprintf(page, count, LPU64"\n", result);
723 EXPORT_SYMBOL(lprocfs_osd_rd_kbytesfree);
725 int lprocfs_rd_kbytesavail(char *page, char **start, off_t off, int count,
726 int *eof, void *data)
728 struct obd_device *obd = data;
729 struct obd_statfs osfs;
730 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
731 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
734 __u32 blk_size = osfs.os_bsize >> 10;
735 __u64 result = osfs.os_bavail;
737 while (blk_size >>= 1)
741 rc = snprintf(page, count, LPU64"\n", result);
745 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
747 int lprocfs_osd_rd_kbytesavail(char *page, char **start, off_t off,
748 int count, int *eof, void *data)
750 struct dt_device *dt = data;
751 struct obd_statfs osfs;
752 int rc = dt_statfs(NULL, dt, &osfs);
754 __u32 blk_size = osfs.os_bsize >> 10;
755 __u64 result = osfs.os_bavail;
757 while (blk_size >>= 1)
761 rc = snprintf(page, count, LPU64"\n", result);
765 EXPORT_SYMBOL(lprocfs_osd_rd_kbytesavail);
767 int lprocfs_rd_filestotal(char *page, char **start, off_t off, int count,
768 int *eof, void *data)
770 struct obd_device *obd = data;
771 struct obd_statfs osfs;
772 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
773 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
777 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
782 EXPORT_SYMBOL(lprocfs_rd_filestotal);
784 int lprocfs_osd_rd_filestotal(char *page, char **start, off_t off,
785 int count, int *eof, void *data)
787 struct dt_device *dt = data;
788 struct obd_statfs osfs;
789 int rc = dt_statfs(NULL, dt, &osfs);
792 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
797 EXPORT_SYMBOL(lprocfs_osd_rd_filestotal);
799 int lprocfs_rd_filesfree(char *page, char **start, off_t off, int count,
800 int *eof, void *data)
802 struct obd_device *obd = data;
803 struct obd_statfs osfs;
804 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
805 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
809 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
813 EXPORT_SYMBOL(lprocfs_rd_filesfree);
815 int lprocfs_osd_rd_filesfree(char *page, char **start, off_t off,
816 int count, int *eof, void *data)
818 struct dt_device *dt = data;
819 struct obd_statfs osfs;
820 int rc = dt_statfs(NULL, dt, &osfs);
823 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
827 EXPORT_SYMBOL(lprocfs_osd_rd_filesfree);
829 int lprocfs_rd_server_uuid(char *page, char **start, off_t off, int count,
830 int *eof, void *data)
832 struct obd_device *obd = data;
833 struct obd_import *imp;
834 char *imp_state_name = NULL;
837 LASSERT(obd != NULL);
838 LPROCFS_CLIMP_CHECK(obd);
839 imp = obd->u.cli.cl_import;
840 imp_state_name = ptlrpc_import_state_name(imp->imp_state);
842 rc = snprintf(page, count, "%s\t%s%s\n",
843 obd2cli_tgt(obd), imp_state_name,
844 imp->imp_deactive ? "\tDEACTIVATED" : "");
846 LPROCFS_CLIMP_EXIT(obd);
849 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
851 int lprocfs_rd_conn_uuid(char *page, char **start, off_t off, int count,
852 int *eof, void *data)
854 struct obd_device *obd = data;
855 struct ptlrpc_connection *conn;
858 LASSERT(obd != NULL);
860 LPROCFS_CLIMP_CHECK(obd);
861 conn = obd->u.cli.cl_import->imp_connection;
863 if (conn && obd->u.cli.cl_import) {
864 rc = snprintf(page, count, "%s\n",
865 conn->c_remote_uuid.uuid);
867 rc = snprintf(page, count, "%s\n", "<none>");
870 LPROCFS_CLIMP_EXIT(obd);
873 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
875 /** add up per-cpu counters */
876 void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
877 struct lprocfs_counter *cnt)
879 struct lprocfs_counter *ptr;
880 unsigned int num_entry;
882 unsigned long flags = 0;
884 memset(cnt, 0, sizeof(*cnt));
887 /* set count to 1 to avoid divide-by-zero errs in callers */
892 cnt->lc_min = LC_MIN_INIT;
894 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
896 for (i = 0; i < num_entry; i++) {
897 if (stats->ls_percpu[i] == NULL)
900 ptr = &(stats->ls_percpu[i])->lp_cntr[idx];
901 cnt->lc_count += ptr->lc_count;
902 cnt->lc_sum += ptr->lc_sum;
903 if (ptr->lc_min < cnt->lc_min)
904 cnt->lc_min = ptr->lc_min;
905 if (ptr->lc_max > cnt->lc_max)
906 cnt->lc_max = ptr->lc_max;
907 cnt->lc_sumsquare += ptr->lc_sumsquare;
910 cnt->lc_units = stats->ls_percpu[0]->lp_cntr[idx].lc_units;
911 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
913 EXPORT_SYMBOL(lprocfs_stats_collect);
916 * Append a space separated list of current set flags to str.
918 #define flag2str(flag) \
919 if (imp->imp_##flag && max - len > 0) \
920 len += snprintf(str + len, max - len, "%s" #flag, len ? ", " : "");
921 static int obd_import_flags2str(struct obd_import *imp, char *str, int max)
925 if (imp->imp_obd->obd_no_recov)
926 len += snprintf(str, max - len, "no_recov");
930 flag2str(replayable);
936 static const char *obd_connect_names[] = {
950 "join_file(obsolete)",
954 "remote_client_by_force",
963 "mds_mds_connection",
966 "alt_checksum_algorithm",
991 int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
996 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
998 ret += snprintf(page + ret, count - ret, "%s%s",
999 ret ? sep : "", obd_connect_names[i]);
1001 if (flags & ~(mask - 1))
1002 ret += snprintf(page + ret, count - ret,
1003 "%sunknown flags "LPX64,
1004 ret ? sep : "", flags & ~(mask - 1));
1007 EXPORT_SYMBOL(obd_connect_flags2str);
1009 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
1010 int *eof, void *data)
1012 struct lprocfs_counter ret;
1013 struct obd_device *obd = (struct obd_device *)data;
1014 struct obd_import *imp;
1015 struct obd_import_conn *conn;
1016 int i, j, k, rw = 0;
1018 LASSERT(obd != NULL);
1019 LPROCFS_CLIMP_CHECK(obd);
1020 imp = obd->u.cli.cl_import;
1023 i = snprintf(page, count,
1029 " connect_flags: [",
1032 ptlrpc_import_state_name(imp->imp_state),
1033 imp->imp_connect_data.ocd_instance);
1034 i += obd_connect_flags2str(page + i, count - i,
1035 imp->imp_connect_data.ocd_connect_flags,
1037 i += snprintf(page + i, count - i,
1039 " import_flags: [");
1040 i += obd_import_flags2str(imp, page + i, count - i);
1042 i += snprintf(page + i, count - i,
1045 " failover_nids: [");
1046 spin_lock(&imp->imp_lock);
1048 cfs_list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
1049 i += snprintf(page + i, count - i, "%s%s", j ? ", " : "",
1050 libcfs_nid2str(conn->oic_conn->c_peer.nid));
1053 i += snprintf(page + i, count - i,
1055 " current_connection: %s\n"
1056 " connection_attempts: %u\n"
1058 " in-progress_invalidations: %u\n",
1059 imp->imp_connection == NULL ? "<none>" :
1060 libcfs_nid2str(imp->imp_connection->c_peer.nid),
1062 imp->imp_generation,
1063 cfs_atomic_read(&imp->imp_inval_count));
1064 spin_unlock(&imp->imp_lock);
1066 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
1067 if (ret.lc_count != 0) {
1068 /* first argument to do_div MUST be __u64 */
1069 __u64 sum = ret.lc_sum;
1070 do_div(sum, ret.lc_count);
1074 i += snprintf(page + i, count - i,
1077 " unregistering: %u\n"
1079 " avg_waittime: "LPU64" %s\n",
1080 cfs_atomic_read(&imp->imp_inflight),
1081 cfs_atomic_read(&imp->imp_unregistering),
1082 cfs_atomic_read(&imp->imp_timeouts),
1083 ret.lc_sum, ret.lc_units);
1086 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
1087 if (imp->imp_at.iat_portal[j] == 0)
1089 k = max_t(unsigned int, k,
1090 at_get(&imp->imp_at.iat_service_estimate[j]));
1092 i += snprintf(page + i, count - i,
1093 " service_estimates:\n"
1094 " services: %u sec\n"
1095 " network: %u sec\n",
1097 at_get(&imp->imp_at.iat_net_latency));
1099 i += snprintf(page + i, count - i,
1101 " last_replay: "LPU64"\n"
1102 " peer_committed: "LPU64"\n"
1103 " last_checked: "LPU64"\n",
1104 imp->imp_last_replay_transno,
1105 imp->imp_peer_committed_transno,
1106 imp->imp_last_transno_checked);
1108 /* avg data rates */
1109 for (rw = 0; rw <= 1; rw++) {
1110 lprocfs_stats_collect(obd->obd_svc_stats,
1111 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
1113 if (ret.lc_sum > 0 && ret.lc_count > 0) {
1114 /* first argument to do_div MUST be __u64 */
1115 __u64 sum = ret.lc_sum;
1116 do_div(sum, ret.lc_count);
1118 i += snprintf(page + i, count - i,
1119 " %s_data_averages:\n"
1120 " bytes_per_rpc: "LPU64"\n",
1121 rw ? "write" : "read",
1124 k = (int)ret.lc_sum;
1125 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
1126 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
1127 if (ret.lc_sum > 0 && ret.lc_count != 0) {
1128 /* first argument to do_div MUST be __u64 */
1129 __u64 sum = ret.lc_sum;
1130 do_div(sum, ret.lc_count);
1132 i += snprintf(page + i, count - i,
1133 " %s_per_rpc: "LPU64"\n",
1134 ret.lc_units, ret.lc_sum);
1135 j = (int)ret.lc_sum;
1137 i += snprintf(page + i, count - i,
1138 " MB_per_sec: %u.%.02u\n",
1139 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/%p\n", client_stat,
1325 client_stat->nid_proc, client_stat->nid_stats,
1326 client_stat->nid_brw_stats);
1328 LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
1329 "nid %s:count %d\n", libcfs_nid2str(client_stat->nid),
1330 atomic_read(&client_stat->nid_exp_ref_count));
1332 if (client_stat->nid_proc)
1333 lprocfs_remove(&client_stat->nid_proc);
1335 if (client_stat->nid_stats)
1336 lprocfs_free_stats(&client_stat->nid_stats);
1338 if (client_stat->nid_brw_stats)
1339 OBD_FREE_PTR(client_stat->nid_brw_stats);
1341 if (client_stat->nid_ldlm_stats)
1342 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1344 OBD_FREE_PTR(client_stat);
1349 void lprocfs_free_per_client_stats(struct obd_device *obd)
1351 cfs_hash_t *hash = obd->obd_nid_stats_hash;
1352 struct nid_stat *stat;
1355 /* we need extra list - because hash_exit called to early */
1356 /* not need locking because all clients is died */
1357 while (!cfs_list_empty(&obd->obd_nid_stats)) {
1358 stat = cfs_list_entry(obd->obd_nid_stats.next,
1359 struct nid_stat, nid_list);
1360 cfs_list_del_init(&stat->nid_list);
1361 cfs_hash_del(hash, &stat->nid, &stat->nid_hash);
1362 lprocfs_free_client_stats(stat);
1366 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
1368 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1369 enum lprocfs_stats_flags flags)
1371 struct lprocfs_stats *stats;
1372 unsigned int percpusize;
1373 unsigned int num_entry;
1378 if (lprocfs_no_percpu_stats != 0)
1379 flags |= LPROCFS_STATS_FLAG_NOPERCPU;
1381 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1384 num_entry = cfs_num_possible_cpus() + 1;
1386 /* alloc percpu pointers for all possible cpu slots */
1387 OBD_ALLOC(stats, offsetof(struct lprocfs_stats, ls_percpu[num_entry]));
1391 stats->ls_num = num;
1392 stats->ls_biggest_alloc_num = 1;
1393 stats->ls_flags = flags;
1394 spin_lock_init(&stats->ls_lock);
1396 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
1398 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1400 /* for no percpu area, the 0th entry is for real use,
1401 * for percpu area, the 0th entry is for intialized entry template */
1402 OBD_ALLOC(stats->ls_percpu[0], percpusize);
1403 if (stats->ls_percpu[0] == NULL) {
1405 offsetof(struct lprocfs_stats, ls_percpu[num_entry]));
1410 EXPORT_SYMBOL(lprocfs_alloc_stats);
1412 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1414 struct lprocfs_stats *stats = *statsh;
1415 unsigned int num_entry;
1416 unsigned int percpusize;
1419 if (stats == NULL || stats->ls_num == 0)
1423 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1426 num_entry = cfs_num_possible_cpus() + 1;
1428 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
1430 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1431 for (i = 0; i < num_entry; i++)
1432 if (stats->ls_percpu[i] != NULL)
1433 OBD_FREE(stats->ls_percpu[i], percpusize);
1434 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1436 EXPORT_SYMBOL(lprocfs_free_stats);
1438 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1440 struct lprocfs_counter *percpu_cntr;
1443 unsigned int num_entry;
1444 unsigned long flags = 0;
1446 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1448 for (i = 0; i < num_entry; i++) {
1449 if (stats->ls_percpu[i] == NULL)
1451 for (j = 0; j < stats->ls_num; j++) {
1452 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
1453 percpu_cntr->lc_count = 0;
1454 percpu_cntr->lc_sum = 0;
1455 percpu_cntr->lc_min = LC_MIN_INIT;
1456 percpu_cntr->lc_max = 0;
1457 percpu_cntr->lc_sumsquare = 0;
1461 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1463 EXPORT_SYMBOL(lprocfs_clear_stats);
1465 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1466 size_t len, loff_t *off)
1468 struct seq_file *seq = file->private_data;
1469 struct lprocfs_stats *stats = seq->private;
1471 lprocfs_clear_stats(stats);
1476 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1478 struct lprocfs_stats *stats = p->private;
1479 /* return 1st cpu location */
1480 return (*pos >= stats->ls_num) ? NULL :
1481 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1484 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1488 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1490 struct lprocfs_stats *stats = p->private;
1492 return (*pos >= stats->ls_num) ? NULL :
1493 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1496 /* seq file export of one lprocfs counter */
1497 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1499 struct lprocfs_stats *stats = p->private;
1500 struct lprocfs_counter *cntr = v;
1501 struct lprocfs_counter ret;
1504 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
1506 cfs_gettimeofday(&now);
1507 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1508 "snapshot_time", now.tv_sec, now.tv_usec);
1512 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
1514 lprocfs_stats_collect(stats, idx, &ret);
1516 if (ret.lc_count == 0)
1519 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", cntr->lc_name,
1520 ret.lc_count, cntr->lc_units);
1525 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
1526 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1527 ret.lc_min, ret.lc_max, ret.lc_sum);
1530 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
1531 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1535 rc = seq_printf(p, "\n");
1537 return (rc < 0) ? rc : 0;
1540 struct seq_operations lprocfs_stats_seq_sops = {
1541 start: lprocfs_stats_seq_start,
1542 stop: lprocfs_stats_seq_stop,
1543 next: lprocfs_stats_seq_next,
1544 show: lprocfs_stats_seq_show,
1547 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1549 struct proc_dir_entry *dp = PDE(inode);
1550 struct seq_file *seq;
1553 if (LPROCFS_ENTRY_AND_CHECK(dp))
1556 rc = seq_open(file, &lprocfs_stats_seq_sops);
1561 seq = file->private_data;
1562 seq->private = dp->data;
1566 struct file_operations lprocfs_stats_seq_fops = {
1567 .owner = THIS_MODULE,
1568 .open = lprocfs_stats_seq_open,
1570 .write = lprocfs_stats_seq_write,
1571 .llseek = seq_lseek,
1572 .release = lprocfs_seq_release,
1575 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1576 struct lprocfs_stats *stats)
1578 struct proc_dir_entry *entry;
1579 LASSERT(root != NULL);
1581 LPROCFS_WRITE_ENTRY();
1582 entry = create_proc_entry(name, 0644, root);
1584 entry->proc_fops = &lprocfs_stats_seq_fops;
1585 entry->data = stats;
1588 LPROCFS_WRITE_EXIT();
1595 EXPORT_SYMBOL(lprocfs_register_stats);
1597 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1598 unsigned conf, const char *name, const char *units)
1600 struct lprocfs_counter *c = &(stats->ls_percpu[0]->lp_cntr[index]);
1601 unsigned long flags = 0;
1603 LASSERT(stats != NULL);
1604 LASSERT(stats->ls_percpu[0] != NULL);
1606 lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1607 c->lc_config = conf;
1610 c->lc_min = LC_MIN_INIT;
1613 c->lc_units = units;
1614 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1616 EXPORT_SYMBOL(lprocfs_counter_init);
1618 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1620 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1621 LASSERT(coffset < stats->ls_num); \
1622 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1625 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1627 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1628 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1629 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1630 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1631 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1632 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1633 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1634 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1635 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1636 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1637 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1638 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1639 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1640 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1641 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1642 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1643 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1644 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1645 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
1646 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1647 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1648 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1649 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1650 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1651 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1652 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1653 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1654 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1655 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1656 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1657 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1658 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1659 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1660 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1661 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1662 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1663 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1664 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1665 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1666 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1667 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1668 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1669 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1670 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1671 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
1672 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1673 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1674 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1675 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1676 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1677 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1678 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1679 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1680 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1681 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1682 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1683 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1684 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1685 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1686 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1687 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1688 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1689 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1690 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1691 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1692 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1693 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1694 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1696 EXPORT_SYMBOL(lprocfs_init_ops_stats);
1698 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1700 struct lprocfs_stats *stats;
1701 unsigned int num_stats;
1704 LASSERT(obd->obd_stats == NULL);
1705 LASSERT(obd->obd_proc_entry != NULL);
1706 LASSERT(obd->obd_cntr_base == 0);
1708 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1709 num_private_stats - 1 /* o_owner */;
1710 stats = lprocfs_alloc_stats(num_stats, 0);
1714 lprocfs_init_ops_stats(num_private_stats, stats);
1716 for (i = num_private_stats; i < num_stats; i++) {
1717 /* If this LBUGs, it is likely that an obd
1718 * operation was added to struct obd_ops in
1719 * <obd.h>, and that the corresponding line item
1720 * LPROCFS_OBD_OP_INIT(.., .., opname)
1721 * is missing from the list above. */
1722 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1723 "Missing obd_stat initializer obd_op "
1724 "operation at offset %d.\n", i - num_private_stats);
1726 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1728 lprocfs_free_stats(&stats);
1730 obd->obd_stats = stats;
1731 obd->obd_cntr_base = num_private_stats;
1735 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
1737 void lprocfs_free_obd_stats(struct obd_device *obd)
1740 lprocfs_free_stats(&obd->obd_stats);
1742 EXPORT_SYMBOL(lprocfs_free_obd_stats);
1744 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1746 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1747 LASSERT(coffset < stats->ls_num); \
1748 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1751 void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats)
1753 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1754 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1755 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
1756 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1757 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1758 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1759 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1760 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1761 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1762 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1763 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1764 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1765 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1766 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1767 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1768 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1769 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1770 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1771 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1772 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1773 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1774 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1775 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1776 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1777 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1778 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1779 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1780 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1781 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1782 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1783 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1784 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1786 EXPORT_SYMBOL(lprocfs_init_mps_stats);
1788 int lprocfs_alloc_md_stats(struct obd_device *obd,
1789 unsigned num_private_stats)
1791 struct lprocfs_stats *stats;
1792 unsigned int num_stats;
1795 LASSERT(obd->md_stats == NULL);
1796 LASSERT(obd->obd_proc_entry != NULL);
1797 LASSERT(obd->md_cntr_base == 0);
1799 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1801 stats = lprocfs_alloc_stats(num_stats, 0);
1805 lprocfs_init_mps_stats(num_private_stats, stats);
1807 for (i = num_private_stats; i < num_stats; i++) {
1808 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1809 CERROR("Missing md_stat initializer md_op "
1810 "operation at offset %d. Aborting.\n",
1811 i - num_private_stats);
1815 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1817 lprocfs_free_stats(&stats);
1819 obd->md_stats = stats;
1820 obd->md_cntr_base = num_private_stats;
1824 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
1826 void lprocfs_free_md_stats(struct obd_device *obd)
1828 struct lprocfs_stats *stats = obd->md_stats;
1830 if (stats != NULL) {
1831 obd->md_stats = NULL;
1832 obd->md_cntr_base = 0;
1833 lprocfs_free_stats(&stats);
1836 EXPORT_SYMBOL(lprocfs_free_md_stats);
1838 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1840 lprocfs_counter_init(ldlm_stats,
1841 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1842 0, "ldlm_enqueue", "reqs");
1843 lprocfs_counter_init(ldlm_stats,
1844 LDLM_CONVERT - LDLM_FIRST_OPC,
1845 0, "ldlm_convert", "reqs");
1846 lprocfs_counter_init(ldlm_stats,
1847 LDLM_CANCEL - LDLM_FIRST_OPC,
1848 0, "ldlm_cancel", "reqs");
1849 lprocfs_counter_init(ldlm_stats,
1850 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1851 0, "ldlm_bl_callback", "reqs");
1852 lprocfs_counter_init(ldlm_stats,
1853 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1854 0, "ldlm_cp_callback", "reqs");
1855 lprocfs_counter_init(ldlm_stats,
1856 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1857 0, "ldlm_gl_callback", "reqs");
1859 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
1861 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1862 int *eof, void *data)
1864 struct obd_export *exp = data;
1865 LASSERT(exp != NULL);
1867 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1870 struct exp_uuid_cb_data {
1878 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1879 int count, int *eof, int *len)
1881 cb_data->page = page;
1882 cb_data->count = count;
1887 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1888 cfs_hlist_node_t *hnode, void *cb_data)
1891 struct obd_export *exp = cfs_hash_object(hs, hnode);
1892 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1894 if (exp->exp_nid_stats)
1895 *data->len += snprintf((data->page + *data->len),
1896 data->count, "%s\n",
1897 obd_uuid2str(&exp->exp_client_uuid));
1901 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1902 int *eof, void *data)
1904 struct nid_stat *stats = (struct nid_stat *)data;
1905 struct exp_uuid_cb_data cb_data;
1906 struct obd_device *obd = stats->nid_obd;
1911 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1912 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1913 lprocfs_exp_print_uuid, &cb_data);
1914 return (*cb_data.len);
1917 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1918 cfs_hlist_node_t *hnode, void *cb_data)
1921 struct exp_uuid_cb_data *data = cb_data;
1922 struct obd_export *exp = cfs_hash_object(hs, hnode);
1924 if (exp->exp_lock_hash != NULL) {
1926 *data->len += cfs_hash_debug_header(data->page,
1929 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1936 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1937 int *eof, void *data)
1939 struct nid_stat *stats = (struct nid_stat *)data;
1940 struct exp_uuid_cb_data cb_data;
1941 struct obd_device *obd = stats->nid_obd;
1946 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_hash, &cb_data);
1950 return (*cb_data.len);
1953 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1954 int count, int *eof, void *data)
1957 return snprintf(page, count, "%s\n",
1958 "Write into this file to clear all nid stats and "
1959 "stale nid entries");
1961 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1963 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1965 struct nid_stat *stat = obj;
1969 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
1970 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 1) {
1971 /* object has only hash references. */
1972 spin_lock(&stat->nid_obd->obd_nid_lock);
1973 cfs_list_move(&stat->nid_list, data);
1974 spin_unlock(&stat->nid_obd->obd_nid_lock);
1977 /* we has reference to object - only clear data*/
1978 if (stat->nid_stats)
1979 lprocfs_clear_stats(stat->nid_stats);
1981 if (stat->nid_brw_stats) {
1982 for (i = 0; i < BRW_LAST; i++)
1983 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
1988 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1989 unsigned long count, void *data)
1991 struct obd_device *obd = (struct obd_device *)data;
1992 struct nid_stat *client_stat;
1993 CFS_LIST_HEAD(free_list);
1995 cfs_hash_cond_del(obd->obd_nid_stats_hash,
1996 lprocfs_nid_stats_clear_write_cb, &free_list);
1998 while (!cfs_list_empty(&free_list)) {
1999 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
2001 cfs_list_del_init(&client_stat->nid_list);
2002 lprocfs_free_client_stats(client_stat);
2007 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
2009 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
2011 struct nid_stat *new_stat, *old_stat;
2012 struct obd_device *obd = NULL;
2013 cfs_proc_dir_entry_t *entry;
2014 char *buffer = NULL;
2020 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
2021 !exp->exp_obd->obd_nid_stats_hash)
2024 /* not test against zero because eric say:
2025 * You may only test nid against another nid, or LNET_NID_ANY.
2026 * Anything else is nonsense.*/
2027 if (!nid || *nid == LNET_NID_ANY)
2032 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
2034 OBD_ALLOC_PTR(new_stat);
2035 if (new_stat == NULL)
2038 new_stat->nid = *nid;
2039 new_stat->nid_obd = exp->exp_obd;
2040 /* we need set default refcount to 1 to balance obd_disconnect */
2041 cfs_atomic_set(&new_stat->nid_exp_ref_count, 1);
2043 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
2044 nid, &new_stat->nid_hash);
2045 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
2046 old_stat, libcfs_nid2str(*nid),
2047 cfs_atomic_read(&new_stat->nid_exp_ref_count));
2049 /* We need to release old stats because lprocfs_exp_cleanup() hasn't
2050 * been and will never be called. */
2051 if (exp->exp_nid_stats) {
2052 nidstat_putref(exp->exp_nid_stats);
2053 exp->exp_nid_stats = NULL;
2056 /* Return -EALREADY here so that we know that the /proc
2057 * entry already has been created */
2058 if (old_stat != new_stat) {
2059 exp->exp_nid_stats = old_stat;
2060 GOTO(destroy_new, rc = -EALREADY);
2062 /* not found - create */
2063 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
2065 GOTO(destroy_new, rc = -ENOMEM);
2067 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
2068 new_stat->nid_proc = lprocfs_register(buffer,
2069 obd->obd_proc_exports_entry,
2071 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
2073 if (new_stat->nid_proc == NULL) {
2074 CERROR("Error making export directory for nid %s\n",
2075 libcfs_nid2str(*nid));
2076 GOTO(destroy_new_ns, rc = -ENOMEM);
2079 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
2080 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
2081 if (IS_ERR(entry)) {
2082 CWARN("Error adding the NID stats file\n");
2083 rc = PTR_ERR(entry);
2084 GOTO(destroy_new_ns, rc);
2087 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
2088 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
2089 if (IS_ERR(entry)) {
2090 CWARN("Error adding the hash file\n");
2091 rc = PTR_ERR(entry);
2092 GOTO(destroy_new_ns, rc);
2095 exp->exp_nid_stats = new_stat;
2097 /* protect competitive add to list, not need locking on destroy */
2098 spin_lock(&obd->obd_nid_lock);
2099 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
2100 spin_unlock(&obd->obd_nid_lock);
2105 if (new_stat->nid_proc != NULL)
2106 lprocfs_remove(&new_stat->nid_proc);
2107 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
2110 nidstat_putref(new_stat);
2111 OBD_FREE_PTR(new_stat);
2114 EXPORT_SYMBOL(lprocfs_exp_setup);
2116 int lprocfs_exp_cleanup(struct obd_export *exp)
2118 struct nid_stat *stat = exp->exp_nid_stats;
2120 if(!stat || !exp->exp_obd)
2123 nidstat_putref(exp->exp_nid_stats);
2124 exp->exp_nid_stats = NULL;
2128 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2130 int lprocfs_write_helper(const char *buffer, unsigned long count,
2133 return lprocfs_write_frac_helper(buffer, count, val, 1);
2135 EXPORT_SYMBOL(lprocfs_write_helper);
2137 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
2140 char kernbuf[20], *end, *pbuf;
2142 if (count > (sizeof(kernbuf) - 1))
2145 if (cfs_copy_from_user(kernbuf, buffer, count))
2148 kernbuf[count] = '\0';
2155 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2159 if (end != NULL && *end == '.') {
2160 int temp_val, pow = 1;
2164 if (strlen(pbuf) > 5)
2165 pbuf[5] = '\0'; /*only allow 5bits fractional*/
2167 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2170 for (i = 0; i < (end - pbuf); i++)
2173 *val += temp_val / pow;
2178 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2180 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
2183 long decimal_val, frac_val;
2189 decimal_val = val / mult;
2190 prtn = snprintf(buffer, count, "%ld", decimal_val);
2191 frac_val = val % mult;
2193 if (prtn < (count - 4) && frac_val > 0) {
2195 int i, temp_mult = 1, frac_bits = 0;
2197 temp_frac = frac_val * 10;
2198 buffer[prtn++] = '.';
2199 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
2200 /* only reserved 2 bits fraction */
2201 buffer[prtn++] ='0';
2206 * Need to think these cases :
2207 * 1. #echo x.00 > /proc/xxx output result : x
2208 * 2. #echo x.0x > /proc/xxx output result : x.0x
2209 * 3. #echo x.x0 > /proc/xxx output result : x.x
2210 * 4. #echo x.xx > /proc/xxx output result : x.xx
2211 * Only reserved 2 bits fraction.
2213 for (i = 0; i < (5 - prtn); i++)
2216 frac_bits = min((int)count - prtn, 3 - frac_bits);
2217 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
2218 frac_val * temp_mult / mult);
2221 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
2223 if (buffer[prtn] == '.') {
2230 buffer[prtn++] ='\n';
2233 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2235 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
2237 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
2239 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2241 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
2242 __u64 *val, int mult)
2244 char kernbuf[22], *end, *pbuf;
2245 __u64 whole, frac = 0, units;
2246 unsigned frac_d = 1;
2248 if (count > (sizeof(kernbuf) - 1))
2251 if (cfs_copy_from_user(kernbuf, buffer, count))
2254 kernbuf[count] = '\0';
2261 whole = simple_strtoull(pbuf, &end, 10);
2265 if (end != NULL && *end == '.') {
2269 /* need to limit frac_d to a __u32 */
2270 if (strlen(pbuf) > 10)
2273 frac = simple_strtoull(pbuf, &end, 10);
2274 /* count decimal places */
2275 for (i = 0; i < (end - pbuf); i++)
2292 /* Specified units override the multiplier */
2294 mult = mult < 0 ? -units : units;
2297 do_div(frac, frac_d);
2298 *val = whole * mult + frac;
2301 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2303 static char *lprocfs_strnstr(const char *s1, const char *s2, size_t len)
2312 if (!memcmp(s1, s2, l2))
2320 * Find the string \a name in the input \a buffer, and return a pointer to the
2321 * value immediately following \a name, reducing \a count appropriately.
2322 * If \a name is not found the original \a buffer is returned.
2324 char *lprocfs_find_named_value(const char *buffer, const char *name,
2325 unsigned long *count)
2328 size_t buflen = *count;
2330 /* there is no strnstr() in rhel5 and ubuntu kernels */
2331 val = lprocfs_strnstr(buffer, name, buflen);
2333 return (char *)buffer;
2335 val += strlen(name); /* skip prefix */
2336 while (val < buffer + buflen && isspace(*val)) /* skip separator */
2340 while (val < buffer + buflen && isalnum(*val)) {
2345 return val - *count;
2347 EXPORT_SYMBOL(lprocfs_find_named_value);
2349 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent,
2352 const struct file_operations *seq_fops,
2355 struct proc_dir_entry *entry;
2358 LPROCFS_WRITE_ENTRY();
2359 entry = create_proc_entry(name, mode, parent);
2361 entry->proc_fops = seq_fops;
2364 LPROCFS_WRITE_EXIT();
2371 EXPORT_SYMBOL(lprocfs_seq_create);
2373 int lprocfs_obd_seq_create(struct obd_device *dev,
2376 const struct file_operations *seq_fops,
2379 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2380 mode, seq_fops, data));
2382 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2384 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2386 if (value >= OBD_HIST_MAX)
2387 value = OBD_HIST_MAX - 1;
2389 spin_lock(&oh->oh_lock);
2390 oh->oh_buckets[value]++;
2391 spin_unlock(&oh->oh_lock);
2393 EXPORT_SYMBOL(lprocfs_oh_tally);
2395 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2399 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2402 lprocfs_oh_tally(oh, val);
2404 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2406 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2408 unsigned long ret = 0;
2411 for (i = 0; i < OBD_HIST_MAX; i++)
2412 ret += oh->oh_buckets[i];
2415 EXPORT_SYMBOL(lprocfs_oh_sum);
2417 void lprocfs_oh_clear(struct obd_histogram *oh)
2419 spin_lock(&oh->oh_lock);
2420 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2421 spin_unlock(&oh->oh_lock);
2423 EXPORT_SYMBOL(lprocfs_oh_clear);
2425 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2426 int count, int *eof, void *data)
2428 struct obd_device *obd = data;
2434 c += cfs_hash_debug_header(page, count);
2435 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2436 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2437 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2441 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2443 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2444 int count, int *eof, void *data)
2446 struct obd_device *obd = data;
2449 LASSERT(obd != NULL);
2450 LASSERT(count >= 0);
2452 /* Set start of user data returned to
2453 page + off since the user may have
2454 requested to read much smaller than
2455 what we need to read */
2456 *start = page + off;
2458 /* We know we are allocated a page here.
2459 Also we know that this function will
2460 not need to write more than a page
2461 so we can truncate at CFS_PAGE_SIZE. */
2462 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2464 /* Initialize the page */
2465 memset(page, 0, size);
2467 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2469 if (obd->obd_max_recoverable_clients == 0) {
2470 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2476 /* sampled unlocked, but really... */
2477 if (obd->obd_recovering == 0) {
2478 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2480 if (lprocfs_obd_snprintf(&page, size, &len,
2481 "recovery_start: %lu\n",
2482 obd->obd_recovery_start) <= 0)
2484 if (lprocfs_obd_snprintf(&page, size, &len,
2485 "recovery_duration: %lu\n",
2486 obd->obd_recovery_end -
2487 obd->obd_recovery_start) <= 0)
2489 /* Number of clients that have completed recovery */
2490 if (lprocfs_obd_snprintf(&page, size, &len,
2491 "completed_clients: %d/%d\n",
2492 obd->obd_max_recoverable_clients -
2493 obd->obd_stale_clients,
2494 obd->obd_max_recoverable_clients) <= 0)
2496 if (lprocfs_obd_snprintf(&page, size, &len,
2497 "replayed_requests: %d\n",
2498 obd->obd_replayed_requests) <= 0)
2500 if (lprocfs_obd_snprintf(&page, size, &len,
2501 "last_transno: "LPD64"\n",
2502 obd->obd_next_recovery_transno - 1)<=0)
2504 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2505 obd->obd_version_recov ?
2506 "ENABLED" : "DISABLED") <=0)
2508 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
2510 "DISABLED" : "ENABLED") <= 0)
2515 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2517 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2518 obd->obd_recovery_start) <= 0)
2520 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2521 cfs_time_current_sec() >=
2522 obd->obd_recovery_start +
2523 obd->obd_recovery_timeout ? 0 :
2524 obd->obd_recovery_start +
2525 obd->obd_recovery_timeout -
2526 cfs_time_current_sec()) <= 0)
2528 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2529 cfs_atomic_read(&obd->obd_connected_clients),
2530 obd->obd_max_recoverable_clients) <= 0)
2532 /* Number of clients that have completed recovery */
2533 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2534 cfs_atomic_read(&obd->obd_req_replay_clients))
2537 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2538 cfs_atomic_read(&obd->obd_lock_replay_clients))
2541 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2542 cfs_atomic_read(&obd->obd_connected_clients) -
2543 cfs_atomic_read(&obd->obd_lock_replay_clients))
2546 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2547 obd->obd_stale_clients) <= 0)
2549 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2550 obd->obd_replayed_requests) <= 0)
2552 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2553 obd->obd_requests_queued_for_recovery) <= 0)
2556 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2557 obd->obd_next_recovery_transno) <= 0)
2563 return min(count, len - (int)off);
2565 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2567 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
2568 int count, int *eof, void *data)
2570 struct obd_device *obd = (struct obd_device *)data;
2571 LASSERT(obd != NULL);
2573 return snprintf(page, count, "%d\n",
2574 obd->obd_recovery_ir_factor);
2576 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
2578 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
2579 unsigned long count, void *data)
2581 struct obd_device *obd = (struct obd_device *)data;
2583 LASSERT(obd != NULL);
2585 rc = lprocfs_write_helper(buffer, count, &val);
2589 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
2592 obd->obd_recovery_ir_factor = val;
2595 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
2597 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
2598 int count, int *eof, void *data)
2600 struct obd_device *obd = (struct obd_device *)data;
2601 LASSERT(obd != NULL);
2603 return snprintf(page, count, "%d\n",
2604 obd->obd_recovery_timeout);
2606 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
2608 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
2609 unsigned long count, void *data)
2611 struct obd_device *obd = (struct obd_device *)data;
2613 LASSERT(obd != NULL);
2615 rc = lprocfs_write_helper(buffer, count, &val);
2619 obd->obd_recovery_timeout = val;
2622 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
2624 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
2625 int count, int *eof, void *data)
2627 struct obd_device *obd = data;
2628 LASSERT(obd != NULL);
2630 return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
2632 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
2634 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
2635 unsigned long count, void *data)
2637 struct obd_device *obd = data;
2639 LASSERT(obd != NULL);
2641 rc = lprocfs_write_helper(buffer, count, &val);
2645 obd->obd_recovery_time_hard = val;
2648 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
2650 int lprocfs_obd_rd_mntdev(char *page, char **start, off_t off,
2651 int count, int *eof, void *data)
2653 struct obd_device *obd = (struct obd_device *)data;
2655 LASSERT(obd != NULL);
2656 LASSERT(mnt_get_devname(obd->u.obt.obt_vfsmnt));
2658 return snprintf(page, count, "%s\n",
2659 mnt_get_devname(obd->u.obt.obt_vfsmnt));
2661 EXPORT_SYMBOL(lprocfs_obd_rd_mntdev);
2663 int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
2664 int count, int *eof, void *data)
2666 struct obd_device *dev = data;
2667 struct client_obd *cli = &dev->u.cli;
2670 client_obd_list_lock(&cli->cl_loi_list_lock);
2671 rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
2672 client_obd_list_unlock(&cli->cl_loi_list_lock);
2675 EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
2677 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
2678 int count, int *eof, void *data)
2680 struct obd_device *obd = (struct obd_device *)data;
2681 struct obd_device_target *target = &obd->u.obt;
2683 LASSERT(obd != NULL);
2684 LASSERT(target->obt_magic == OBT_MAGIC);
2686 return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
2688 EXPORT_SYMBOL(lprocfs_target_rd_instance);