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 unsigned int num_entry;
880 struct lprocfs_counter t;
881 struct lprocfs_counter *percpu_cntr;
884 unsigned long flags = 0;
886 memset(cnt, 0, sizeof(*cnt));
889 /* set count to 1 to avoid divide-by-zero errs in callers */
894 cnt->lc_min = LC_MIN_INIT;
896 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
898 for (i = 0; i < num_entry; i++) {
899 if (stats->ls_percpu[i] == NULL)
901 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[idx];
904 centry = cfs_atomic_read(&percpu_cntr-> \
906 t.lc_count = percpu_cntr->lc_count;
907 t.lc_sum = percpu_cntr->lc_sum;
908 t.lc_min = percpu_cntr->lc_min;
909 t.lc_max = percpu_cntr->lc_max;
910 t.lc_sumsquare = percpu_cntr->lc_sumsquare;
911 } while (centry != cfs_atomic_read(&percpu_cntr->lc_cntl. \
913 centry != cfs_atomic_read(&percpu_cntr->lc_cntl. \
915 cnt->lc_count += t.lc_count;
916 cnt->lc_sum += t.lc_sum;
917 if (t.lc_min < cnt->lc_min)
918 cnt->lc_min = t.lc_min;
919 if (t.lc_max > cnt->lc_max)
920 cnt->lc_max = t.lc_max;
921 cnt->lc_sumsquare += t.lc_sumsquare;
924 cnt->lc_units = stats->ls_percpu[0]->lp_cntr[idx].lc_units;
925 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
927 EXPORT_SYMBOL(lprocfs_stats_collect);
930 * Append a space separated list of current set flags to str.
932 #define flag2str(flag) \
933 if (imp->imp_##flag && max - len > 0) \
934 len += snprintf(str + len, max - len, "%s" #flag, len ? ", " : "");
935 static int obd_import_flags2str(struct obd_import *imp, char *str, int max)
939 if (imp->imp_obd->obd_no_recov)
940 len += snprintf(str, max - len, "no_recov");
944 flag2str(replayable);
950 static const char *obd_connect_names[] = {
964 "join_file(obsolete)",
968 "remote_client_by_force",
977 "mds_mds_connection",
980 "alt_checksum_algorithm",
1005 int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
1010 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
1012 ret += snprintf(page + ret, count - ret, "%s%s",
1013 ret ? sep : "", obd_connect_names[i]);
1015 if (flags & ~(mask - 1))
1016 ret += snprintf(page + ret, count - ret,
1017 "%sunknown flags "LPX64,
1018 ret ? sep : "", flags & ~(mask - 1));
1021 EXPORT_SYMBOL(obd_connect_flags2str);
1023 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
1024 int *eof, void *data)
1026 struct lprocfs_counter ret;
1027 struct obd_device *obd = (struct obd_device *)data;
1028 struct obd_import *imp;
1029 struct obd_import_conn *conn;
1030 int i, j, k, rw = 0;
1032 LASSERT(obd != NULL);
1033 LPROCFS_CLIMP_CHECK(obd);
1034 imp = obd->u.cli.cl_import;
1037 i = snprintf(page, count,
1043 " connect_flags: [",
1046 ptlrpc_import_state_name(imp->imp_state),
1047 imp->imp_connect_data.ocd_instance);
1048 i += obd_connect_flags2str(page + i, count - i,
1049 imp->imp_connect_data.ocd_connect_flags,
1051 i += snprintf(page + i, count - i,
1053 " import_flags: [");
1054 i += obd_import_flags2str(imp, page + i, count - i);
1056 i += snprintf(page + i, count - i,
1059 " failover_nids: [");
1060 spin_lock(&imp->imp_lock);
1062 cfs_list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
1063 i += snprintf(page + i, count - i, "%s%s", j ? ", " : "",
1064 libcfs_nid2str(conn->oic_conn->c_peer.nid));
1067 i += snprintf(page + i, count - i,
1069 " current_connection: %s\n"
1070 " connection_attempts: %u\n"
1072 " in-progress_invalidations: %u\n",
1073 imp->imp_connection == NULL ? "<none>" :
1074 libcfs_nid2str(imp->imp_connection->c_peer.nid),
1076 imp->imp_generation,
1077 cfs_atomic_read(&imp->imp_inval_count));
1078 spin_unlock(&imp->imp_lock);
1080 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
1081 if (ret.lc_count != 0) {
1082 /* first argument to do_div MUST be __u64 */
1083 __u64 sum = ret.lc_sum;
1084 do_div(sum, ret.lc_count);
1088 i += snprintf(page + i, count - i,
1091 " unregistering: %u\n"
1093 " avg_waittime: "LPU64" %s\n",
1094 cfs_atomic_read(&imp->imp_inflight),
1095 cfs_atomic_read(&imp->imp_unregistering),
1096 cfs_atomic_read(&imp->imp_timeouts),
1097 ret.lc_sum, ret.lc_units);
1100 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
1101 if (imp->imp_at.iat_portal[j] == 0)
1103 k = max_t(unsigned int, k,
1104 at_get(&imp->imp_at.iat_service_estimate[j]));
1106 i += snprintf(page + i, count - i,
1107 " service_estimates:\n"
1108 " services: %u sec\n"
1109 " network: %u sec\n",
1111 at_get(&imp->imp_at.iat_net_latency));
1113 i += snprintf(page + i, count - i,
1115 " last_replay: "LPU64"\n"
1116 " peer_committed: "LPU64"\n"
1117 " last_checked: "LPU64"\n",
1118 imp->imp_last_replay_transno,
1119 imp->imp_peer_committed_transno,
1120 imp->imp_last_transno_checked);
1122 /* avg data rates */
1123 for (rw = 0; rw <= 1; rw++) {
1124 lprocfs_stats_collect(obd->obd_svc_stats,
1125 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
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_data_averages:\n"
1134 " bytes_per_rpc: "LPU64"\n",
1135 rw ? "write" : "read",
1138 k = (int)ret.lc_sum;
1139 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
1140 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
1141 if (ret.lc_sum > 0 && ret.lc_count != 0) {
1142 /* first argument to do_div MUST be __u64 */
1143 __u64 sum = ret.lc_sum;
1144 do_div(sum, ret.lc_count);
1146 i += snprintf(page + i, count - i,
1147 " %s_per_rpc: "LPU64"\n",
1148 ret.lc_units, ret.lc_sum);
1149 j = (int)ret.lc_sum;
1151 i += snprintf(page + i, count - i,
1152 " MB_per_sec: %u.%.02u\n",
1153 k / j, (100 * k / j) % 100);
1157 LPROCFS_CLIMP_EXIT(obd);
1160 EXPORT_SYMBOL(lprocfs_rd_import);
1162 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
1163 int *eof, void *data)
1165 struct obd_device *obd = (struct obd_device *)data;
1166 struct obd_import *imp;
1169 LASSERT(obd != NULL);
1170 LPROCFS_CLIMP_CHECK(obd);
1171 imp = obd->u.cli.cl_import;
1174 i = snprintf(page, count, "current_state: %s\n",
1175 ptlrpc_import_state_name(imp->imp_state));
1176 i += snprintf(page + i, count - i,
1177 "state_history:\n");
1178 k = imp->imp_state_hist_idx;
1179 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
1180 struct import_state_hist *ish =
1181 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
1182 if (ish->ish_state == 0)
1184 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
1186 ptlrpc_import_state_name(ish->ish_state));
1189 LPROCFS_CLIMP_EXIT(obd);
1192 EXPORT_SYMBOL(lprocfs_rd_state);
1194 int lprocfs_at_hist_helper(char *page, int count, int rc,
1195 struct adaptive_timeout *at)
1198 for (i = 0; i < AT_BINS; i++)
1199 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
1200 rc += snprintf(page + rc, count - rc, "\n");
1203 EXPORT_SYMBOL(lprocfs_at_hist_helper);
1205 /* See also ptlrpc_lprocfs_rd_timeouts */
1206 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
1207 int *eof, void *data)
1209 struct obd_device *obd = (struct obd_device *)data;
1210 struct obd_import *imp;
1211 unsigned int cur, worst;
1216 LASSERT(obd != NULL);
1217 LPROCFS_CLIMP_CHECK(obd);
1218 imp = obd->u.cli.cl_import;
1221 now = cfs_time_current_sec();
1223 /* Some network health info for kicks */
1224 s2dhms(&ts, now - imp->imp_last_reply_time);
1225 rc += snprintf(page + rc, count - rc,
1226 "%-10s : %ld, "DHMS_FMT" ago\n",
1227 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
1229 cur = at_get(&imp->imp_at.iat_net_latency);
1230 worst = imp->imp_at.iat_net_latency.at_worst_ever;
1231 worstt = imp->imp_at.iat_net_latency.at_worst_time;
1232 s2dhms(&ts, now - worstt);
1233 rc += snprintf(page + rc, count - rc,
1234 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
1235 "network", cur, worst, worstt, DHMS_VARS(&ts));
1236 rc = lprocfs_at_hist_helper(page, count, rc,
1237 &imp->imp_at.iat_net_latency);
1239 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
1240 if (imp->imp_at.iat_portal[i] == 0)
1242 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
1243 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
1244 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
1245 s2dhms(&ts, now - worstt);
1246 rc += snprintf(page + rc, count - rc,
1247 "portal %-2d : cur %3u worst %3u (at %ld, "
1248 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
1249 cur, worst, worstt, DHMS_VARS(&ts));
1250 rc = lprocfs_at_hist_helper(page, count, rc,
1251 &imp->imp_at.iat_service_estimate[i]);
1254 LPROCFS_CLIMP_EXIT(obd);
1257 EXPORT_SYMBOL(lprocfs_rd_timeouts);
1259 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1260 int count, int *eof, void *data)
1262 struct obd_device *obd = data;
1266 LPROCFS_CLIMP_CHECK(obd);
1267 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1268 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1269 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1270 ret += snprintf(page + ret, count - ret, "\n");
1271 LPROCFS_CLIMP_EXIT(obd);
1274 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1276 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1277 int *eof, void *data)
1279 struct obd_device *obd = data;
1281 LASSERT(obd != NULL);
1283 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1285 EXPORT_SYMBOL(lprocfs_rd_num_exports);
1287 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1288 int *eof, void *data)
1290 struct obd_type *class = (struct obd_type*) data;
1292 LASSERT(class != NULL);
1294 return snprintf(page, count, "%d\n", class->typ_refcnt);
1296 EXPORT_SYMBOL(lprocfs_rd_numrefs);
1298 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1302 LASSERT(obd != NULL);
1303 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1304 LASSERT(obd->obd_type->typ_procroot != NULL);
1306 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1307 obd->obd_type->typ_procroot,
1309 if (IS_ERR(obd->obd_proc_entry)) {
1310 rc = PTR_ERR(obd->obd_proc_entry);
1311 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1312 obd->obd_proc_entry = NULL;
1316 EXPORT_SYMBOL(lprocfs_obd_setup);
1318 int lprocfs_obd_cleanup(struct obd_device *obd)
1322 if (obd->obd_proc_exports_entry) {
1323 /* Should be no exports left */
1324 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1325 lprocfs_remove(&obd->obd_proc_exports_entry);
1326 obd->obd_proc_exports_entry = NULL;
1328 if (obd->obd_proc_entry) {
1329 lprocfs_remove(&obd->obd_proc_entry);
1330 obd->obd_proc_entry = NULL;
1334 EXPORT_SYMBOL(lprocfs_obd_cleanup);
1336 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1338 CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
1339 client_stat->nid_proc, client_stat->nid_stats,
1340 client_stat->nid_brw_stats);
1342 LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
1343 "nid %s:count %d\n", libcfs_nid2str(client_stat->nid),
1344 atomic_read(&client_stat->nid_exp_ref_count));
1346 if (client_stat->nid_proc)
1347 lprocfs_remove(&client_stat->nid_proc);
1349 if (client_stat->nid_stats)
1350 lprocfs_free_stats(&client_stat->nid_stats);
1352 if (client_stat->nid_brw_stats)
1353 OBD_FREE_PTR(client_stat->nid_brw_stats);
1355 if (client_stat->nid_ldlm_stats)
1356 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1358 OBD_FREE_PTR(client_stat);
1363 void lprocfs_free_per_client_stats(struct obd_device *obd)
1365 cfs_hash_t *hash = obd->obd_nid_stats_hash;
1366 struct nid_stat *stat;
1369 /* we need extra list - because hash_exit called to early */
1370 /* not need locking because all clients is died */
1371 while (!cfs_list_empty(&obd->obd_nid_stats)) {
1372 stat = cfs_list_entry(obd->obd_nid_stats.next,
1373 struct nid_stat, nid_list);
1374 cfs_list_del_init(&stat->nid_list);
1375 cfs_hash_del(hash, &stat->nid, &stat->nid_hash);
1376 lprocfs_free_client_stats(stat);
1380 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
1382 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1383 enum lprocfs_stats_flags flags)
1385 struct lprocfs_stats *stats;
1386 unsigned int percpusize;
1387 unsigned int num_entry;
1392 if (lprocfs_no_percpu_stats != 0)
1393 flags |= LPROCFS_STATS_FLAG_NOPERCPU;
1395 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1398 num_entry = cfs_num_possible_cpus() + 1;
1400 /* alloc percpu pointers for all possible cpu slots */
1401 OBD_ALLOC(stats, offsetof(struct lprocfs_stats, ls_percpu[num_entry]));
1405 stats->ls_num = num;
1406 stats->ls_biggest_alloc_num = 1;
1407 stats->ls_flags = flags;
1408 spin_lock_init(&stats->ls_lock);
1410 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
1412 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1414 /* for no percpu area, the 0th entry is for real use,
1415 * for percpu area, the 0th entry is for intialized entry template */
1416 OBD_ALLOC(stats->ls_percpu[0], percpusize);
1417 if (stats->ls_percpu[0] == NULL) {
1419 offsetof(struct lprocfs_stats, ls_percpu[num_entry]));
1424 EXPORT_SYMBOL(lprocfs_alloc_stats);
1426 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1428 struct lprocfs_stats *stats = *statsh;
1429 unsigned int num_entry;
1430 unsigned int percpusize;
1433 if (stats == NULL || stats->ls_num == 0)
1437 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1440 num_entry = cfs_num_possible_cpus() + 1;
1442 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
1444 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1445 for (i = 0; i < num_entry; i++)
1446 if (stats->ls_percpu[i] != NULL)
1447 OBD_FREE(stats->ls_percpu[i], percpusize);
1448 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1450 EXPORT_SYMBOL(lprocfs_free_stats);
1452 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1454 struct lprocfs_counter *percpu_cntr;
1457 unsigned int num_entry;
1458 unsigned long flags = 0;
1460 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1462 for (i = 0; i < num_entry; i++) {
1463 if (stats->ls_percpu[i] == NULL)
1465 for (j = 0; j < stats->ls_num; j++) {
1466 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
1467 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_entry);
1468 percpu_cntr->lc_count = 0;
1469 percpu_cntr->lc_sum = 0;
1470 percpu_cntr->lc_min = LC_MIN_INIT;
1471 percpu_cntr->lc_max = 0;
1472 percpu_cntr->lc_sumsquare = 0;
1473 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_exit);
1477 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1479 EXPORT_SYMBOL(lprocfs_clear_stats);
1481 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1482 size_t len, loff_t *off)
1484 struct seq_file *seq = file->private_data;
1485 struct lprocfs_stats *stats = seq->private;
1487 lprocfs_clear_stats(stats);
1492 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1494 struct lprocfs_stats *stats = p->private;
1495 /* return 1st cpu location */
1496 return (*pos >= stats->ls_num) ? NULL :
1497 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1500 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1504 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1506 struct lprocfs_stats *stats = p->private;
1508 return (*pos >= stats->ls_num) ? NULL :
1509 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1512 /* seq file export of one lprocfs counter */
1513 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1515 struct lprocfs_stats *stats = p->private;
1516 struct lprocfs_counter *cntr = v;
1517 struct lprocfs_counter ret;
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 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
1530 lprocfs_stats_collect(stats, idx, &ret);
1532 if (ret.lc_count == 0)
1535 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", cntr->lc_name,
1536 ret.lc_count, cntr->lc_units);
1541 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
1542 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1543 ret.lc_min, ret.lc_max, ret.lc_sum);
1546 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
1547 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1551 rc = seq_printf(p, "\n");
1553 return (rc < 0) ? rc : 0;
1556 struct seq_operations lprocfs_stats_seq_sops = {
1557 start: lprocfs_stats_seq_start,
1558 stop: lprocfs_stats_seq_stop,
1559 next: lprocfs_stats_seq_next,
1560 show: lprocfs_stats_seq_show,
1563 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1565 struct proc_dir_entry *dp = PDE(inode);
1566 struct seq_file *seq;
1569 if (LPROCFS_ENTRY_AND_CHECK(dp))
1572 rc = seq_open(file, &lprocfs_stats_seq_sops);
1577 seq = file->private_data;
1578 seq->private = dp->data;
1582 struct file_operations lprocfs_stats_seq_fops = {
1583 .owner = THIS_MODULE,
1584 .open = lprocfs_stats_seq_open,
1586 .write = lprocfs_stats_seq_write,
1587 .llseek = seq_lseek,
1588 .release = lprocfs_seq_release,
1591 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1592 struct lprocfs_stats *stats)
1594 struct proc_dir_entry *entry;
1595 LASSERT(root != NULL);
1597 LPROCFS_WRITE_ENTRY();
1598 entry = create_proc_entry(name, 0644, root);
1600 entry->proc_fops = &lprocfs_stats_seq_fops;
1601 entry->data = stats;
1604 LPROCFS_WRITE_EXIT();
1611 EXPORT_SYMBOL(lprocfs_register_stats);
1613 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1614 unsigned conf, const char *name, const char *units)
1616 struct lprocfs_counter *c = &(stats->ls_percpu[0]->lp_cntr[index]);
1617 unsigned long flags = 0;
1619 LASSERT(stats != NULL);
1620 LASSERT(stats->ls_percpu[0] != NULL);
1622 lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1623 c->lc_config = conf;
1626 c->lc_min = LC_MIN_INIT;
1629 c->lc_units = units;
1630 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1632 EXPORT_SYMBOL(lprocfs_counter_init);
1634 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1636 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1637 LASSERT(coffset < stats->ls_num); \
1638 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1641 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1643 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1644 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1645 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1646 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1647 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1648 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1649 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1650 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1651 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1652 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1653 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1654 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1655 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1656 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1657 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1658 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1659 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1660 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1661 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
1662 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1663 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1664 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1665 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1666 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1667 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1668 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1669 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1670 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1671 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1672 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1673 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1674 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1675 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1676 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1677 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1678 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1679 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1680 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1681 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1682 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1683 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1684 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1685 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1686 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1687 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
1688 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1689 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1690 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1691 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1692 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1693 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1694 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1695 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1696 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1697 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1698 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1699 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1700 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1701 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1702 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1703 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1704 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1705 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1706 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1707 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1708 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1709 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1710 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1712 EXPORT_SYMBOL(lprocfs_init_ops_stats);
1714 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1716 struct lprocfs_stats *stats;
1717 unsigned int num_stats;
1720 LASSERT(obd->obd_stats == NULL);
1721 LASSERT(obd->obd_proc_entry != NULL);
1722 LASSERT(obd->obd_cntr_base == 0);
1724 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1725 num_private_stats - 1 /* o_owner */;
1726 stats = lprocfs_alloc_stats(num_stats, 0);
1730 lprocfs_init_ops_stats(num_private_stats, stats);
1732 for (i = num_private_stats; i < num_stats; i++) {
1733 /* If this LBUGs, it is likely that an obd
1734 * operation was added to struct obd_ops in
1735 * <obd.h>, and that the corresponding line item
1736 * LPROCFS_OBD_OP_INIT(.., .., opname)
1737 * is missing from the list above. */
1738 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1739 "Missing obd_stat initializer obd_op "
1740 "operation at offset %d.\n", i - num_private_stats);
1742 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1744 lprocfs_free_stats(&stats);
1746 obd->obd_stats = stats;
1747 obd->obd_cntr_base = num_private_stats;
1751 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
1753 void lprocfs_free_obd_stats(struct obd_device *obd)
1756 lprocfs_free_stats(&obd->obd_stats);
1758 EXPORT_SYMBOL(lprocfs_free_obd_stats);
1760 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1762 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1763 LASSERT(coffset < stats->ls_num); \
1764 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1767 void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats)
1769 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1770 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1771 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
1772 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1773 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1774 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1775 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1776 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1777 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1778 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1779 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1780 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1781 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1782 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1783 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1784 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1785 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1786 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1787 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1788 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1789 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1790 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1791 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1792 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1793 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1794 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1795 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1796 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1797 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1798 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1799 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1800 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1802 EXPORT_SYMBOL(lprocfs_init_mps_stats);
1804 int lprocfs_alloc_md_stats(struct obd_device *obd,
1805 unsigned num_private_stats)
1807 struct lprocfs_stats *stats;
1808 unsigned int num_stats;
1811 LASSERT(obd->md_stats == NULL);
1812 LASSERT(obd->obd_proc_entry != NULL);
1813 LASSERT(obd->md_cntr_base == 0);
1815 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1817 stats = lprocfs_alloc_stats(num_stats, 0);
1821 lprocfs_init_mps_stats(num_private_stats, stats);
1823 for (i = num_private_stats; i < num_stats; i++) {
1824 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1825 CERROR("Missing md_stat initializer md_op "
1826 "operation at offset %d. Aborting.\n",
1827 i - num_private_stats);
1831 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1833 lprocfs_free_stats(&stats);
1835 obd->md_stats = stats;
1836 obd->md_cntr_base = num_private_stats;
1840 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
1842 void lprocfs_free_md_stats(struct obd_device *obd)
1844 struct lprocfs_stats *stats = obd->md_stats;
1846 if (stats != NULL) {
1847 obd->md_stats = NULL;
1848 obd->md_cntr_base = 0;
1849 lprocfs_free_stats(&stats);
1852 EXPORT_SYMBOL(lprocfs_free_md_stats);
1854 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1856 lprocfs_counter_init(ldlm_stats,
1857 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1858 0, "ldlm_enqueue", "reqs");
1859 lprocfs_counter_init(ldlm_stats,
1860 LDLM_CONVERT - LDLM_FIRST_OPC,
1861 0, "ldlm_convert", "reqs");
1862 lprocfs_counter_init(ldlm_stats,
1863 LDLM_CANCEL - LDLM_FIRST_OPC,
1864 0, "ldlm_cancel", "reqs");
1865 lprocfs_counter_init(ldlm_stats,
1866 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1867 0, "ldlm_bl_callback", "reqs");
1868 lprocfs_counter_init(ldlm_stats,
1869 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1870 0, "ldlm_cp_callback", "reqs");
1871 lprocfs_counter_init(ldlm_stats,
1872 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1873 0, "ldlm_gl_callback", "reqs");
1875 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
1877 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1878 int *eof, void *data)
1880 struct obd_export *exp = data;
1881 LASSERT(exp != NULL);
1883 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1886 struct exp_uuid_cb_data {
1894 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1895 int count, int *eof, int *len)
1897 cb_data->page = page;
1898 cb_data->count = count;
1903 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1904 cfs_hlist_node_t *hnode, void *cb_data)
1907 struct obd_export *exp = cfs_hash_object(hs, hnode);
1908 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1910 if (exp->exp_nid_stats)
1911 *data->len += snprintf((data->page + *data->len),
1912 data->count, "%s\n",
1913 obd_uuid2str(&exp->exp_client_uuid));
1917 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1918 int *eof, void *data)
1920 struct nid_stat *stats = (struct nid_stat *)data;
1921 struct exp_uuid_cb_data cb_data;
1922 struct obd_device *obd = stats->nid_obd;
1927 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1928 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1929 lprocfs_exp_print_uuid, &cb_data);
1930 return (*cb_data.len);
1933 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1934 cfs_hlist_node_t *hnode, void *cb_data)
1937 struct exp_uuid_cb_data *data = cb_data;
1938 struct obd_export *exp = cfs_hash_object(hs, hnode);
1940 if (exp->exp_lock_hash != NULL) {
1942 *data->len += cfs_hash_debug_header(data->page,
1945 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1952 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1953 int *eof, void *data)
1955 struct nid_stat *stats = (struct nid_stat *)data;
1956 struct exp_uuid_cb_data cb_data;
1957 struct obd_device *obd = stats->nid_obd;
1962 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1964 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1965 lprocfs_exp_print_hash, &cb_data);
1966 return (*cb_data.len);
1969 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1970 int count, int *eof, void *data)
1973 return snprintf(page, count, "%s\n",
1974 "Write into this file to clear all nid stats and "
1975 "stale nid entries");
1977 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1979 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1981 struct nid_stat *stat = obj;
1985 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
1986 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 1) {
1987 /* object has only hash references. */
1988 spin_lock(&stat->nid_obd->obd_nid_lock);
1989 cfs_list_move(&stat->nid_list, data);
1990 spin_unlock(&stat->nid_obd->obd_nid_lock);
1993 /* we has reference to object - only clear data*/
1994 if (stat->nid_stats)
1995 lprocfs_clear_stats(stat->nid_stats);
1997 if (stat->nid_brw_stats) {
1998 for (i = 0; i < BRW_LAST; i++)
1999 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
2004 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
2005 unsigned long count, void *data)
2007 struct obd_device *obd = (struct obd_device *)data;
2008 struct nid_stat *client_stat;
2009 CFS_LIST_HEAD(free_list);
2011 cfs_hash_cond_del(obd->obd_nid_stats_hash,
2012 lprocfs_nid_stats_clear_write_cb, &free_list);
2014 while (!cfs_list_empty(&free_list)) {
2015 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
2017 cfs_list_del_init(&client_stat->nid_list);
2018 lprocfs_free_client_stats(client_stat);
2023 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
2025 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
2027 struct nid_stat *new_stat, *old_stat;
2028 struct obd_device *obd = NULL;
2029 cfs_proc_dir_entry_t *entry;
2030 char *buffer = NULL;
2036 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
2037 !exp->exp_obd->obd_nid_stats_hash)
2040 /* not test against zero because eric say:
2041 * You may only test nid against another nid, or LNET_NID_ANY.
2042 * Anything else is nonsense.*/
2043 if (!nid || *nid == LNET_NID_ANY)
2048 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
2050 OBD_ALLOC_PTR(new_stat);
2051 if (new_stat == NULL)
2054 new_stat->nid = *nid;
2055 new_stat->nid_obd = exp->exp_obd;
2056 /* we need set default refcount to 1 to balance obd_disconnect */
2057 cfs_atomic_set(&new_stat->nid_exp_ref_count, 1);
2059 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
2060 nid, &new_stat->nid_hash);
2061 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
2062 old_stat, libcfs_nid2str(*nid),
2063 cfs_atomic_read(&new_stat->nid_exp_ref_count));
2065 /* We need to release old stats because lprocfs_exp_cleanup() hasn't
2066 * been and will never be called. */
2067 if (exp->exp_nid_stats) {
2068 nidstat_putref(exp->exp_nid_stats);
2069 exp->exp_nid_stats = NULL;
2072 /* Return -EALREADY here so that we know that the /proc
2073 * entry already has been created */
2074 if (old_stat != new_stat) {
2075 exp->exp_nid_stats = old_stat;
2076 GOTO(destroy_new, rc = -EALREADY);
2078 /* not found - create */
2079 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
2081 GOTO(destroy_new, rc = -ENOMEM);
2083 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
2084 new_stat->nid_proc = lprocfs_register(buffer,
2085 obd->obd_proc_exports_entry,
2087 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
2089 if (new_stat->nid_proc == NULL) {
2090 CERROR("Error making export directory for nid %s\n",
2091 libcfs_nid2str(*nid));
2092 GOTO(destroy_new_ns, rc = -ENOMEM);
2095 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
2096 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
2097 if (IS_ERR(entry)) {
2098 CWARN("Error adding the NID stats file\n");
2099 rc = PTR_ERR(entry);
2100 GOTO(destroy_new_ns, rc);
2103 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
2104 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
2105 if (IS_ERR(entry)) {
2106 CWARN("Error adding the hash file\n");
2107 rc = PTR_ERR(entry);
2108 GOTO(destroy_new_ns, rc);
2111 exp->exp_nid_stats = new_stat;
2113 /* protect competitive add to list, not need locking on destroy */
2114 spin_lock(&obd->obd_nid_lock);
2115 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
2116 spin_unlock(&obd->obd_nid_lock);
2121 if (new_stat->nid_proc != NULL)
2122 lprocfs_remove(&new_stat->nid_proc);
2123 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
2126 nidstat_putref(new_stat);
2127 OBD_FREE_PTR(new_stat);
2130 EXPORT_SYMBOL(lprocfs_exp_setup);
2132 int lprocfs_exp_cleanup(struct obd_export *exp)
2134 struct nid_stat *stat = exp->exp_nid_stats;
2136 if(!stat || !exp->exp_obd)
2139 nidstat_putref(exp->exp_nid_stats);
2140 exp->exp_nid_stats = NULL;
2144 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2146 int lprocfs_write_helper(const char *buffer, unsigned long count,
2149 return lprocfs_write_frac_helper(buffer, count, val, 1);
2151 EXPORT_SYMBOL(lprocfs_write_helper);
2153 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
2156 char kernbuf[20], *end, *pbuf;
2158 if (count > (sizeof(kernbuf) - 1))
2161 if (cfs_copy_from_user(kernbuf, buffer, count))
2164 kernbuf[count] = '\0';
2171 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2175 if (end != NULL && *end == '.') {
2176 int temp_val, pow = 1;
2180 if (strlen(pbuf) > 5)
2181 pbuf[5] = '\0'; /*only allow 5bits fractional*/
2183 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2186 for (i = 0; i < (end - pbuf); i++)
2189 *val += temp_val / pow;
2194 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2196 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
2199 long decimal_val, frac_val;
2205 decimal_val = val / mult;
2206 prtn = snprintf(buffer, count, "%ld", decimal_val);
2207 frac_val = val % mult;
2209 if (prtn < (count - 4) && frac_val > 0) {
2211 int i, temp_mult = 1, frac_bits = 0;
2213 temp_frac = frac_val * 10;
2214 buffer[prtn++] = '.';
2215 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
2216 /* only reserved 2 bits fraction */
2217 buffer[prtn++] ='0';
2222 * Need to think these cases :
2223 * 1. #echo x.00 > /proc/xxx output result : x
2224 * 2. #echo x.0x > /proc/xxx output result : x.0x
2225 * 3. #echo x.x0 > /proc/xxx output result : x.x
2226 * 4. #echo x.xx > /proc/xxx output result : x.xx
2227 * Only reserved 2 bits fraction.
2229 for (i = 0; i < (5 - prtn); i++)
2232 frac_bits = min((int)count - prtn, 3 - frac_bits);
2233 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
2234 frac_val * temp_mult / mult);
2237 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
2239 if (buffer[prtn] == '.') {
2246 buffer[prtn++] ='\n';
2249 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2251 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
2253 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
2255 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2257 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
2258 __u64 *val, int mult)
2260 char kernbuf[22], *end, *pbuf;
2261 __u64 whole, frac = 0, units;
2262 unsigned frac_d = 1;
2264 if (count > (sizeof(kernbuf) - 1))
2267 if (cfs_copy_from_user(kernbuf, buffer, count))
2270 kernbuf[count] = '\0';
2277 whole = simple_strtoull(pbuf, &end, 10);
2281 if (end != NULL && *end == '.') {
2285 /* need to limit frac_d to a __u32 */
2286 if (strlen(pbuf) > 10)
2289 frac = simple_strtoull(pbuf, &end, 10);
2290 /* count decimal places */
2291 for (i = 0; i < (end - pbuf); i++)
2308 /* Specified units override the multiplier */
2310 mult = mult < 0 ? -units : units;
2313 do_div(frac, frac_d);
2314 *val = whole * mult + frac;
2317 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2319 static char *lprocfs_strnstr(const char *s1, const char *s2, size_t len)
2328 if (!memcmp(s1, s2, l2))
2336 * Find the string \a name in the input \a buffer, and return a pointer to the
2337 * value immediately following \a name, reducing \a count appropriately.
2338 * If \a name is not found the original \a buffer is returned.
2340 char *lprocfs_find_named_value(const char *buffer, const char *name,
2341 unsigned long *count)
2344 size_t buflen = *count;
2346 /* there is no strnstr() in rhel5 and ubuntu kernels */
2347 val = lprocfs_strnstr(buffer, name, buflen);
2349 return (char *)buffer;
2351 val += strlen(name); /* skip prefix */
2352 while (val < buffer + buflen && isspace(*val)) /* skip separator */
2356 while (val < buffer + buflen && isalnum(*val)) {
2361 return val - *count;
2363 EXPORT_SYMBOL(lprocfs_find_named_value);
2365 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent, char *name, mode_t mode,
2366 struct file_operations *seq_fops, void *data)
2368 struct proc_dir_entry *entry;
2371 LPROCFS_WRITE_ENTRY();
2372 entry = create_proc_entry(name, mode, parent);
2374 entry->proc_fops = seq_fops;
2377 LPROCFS_WRITE_EXIT();
2384 EXPORT_SYMBOL(lprocfs_seq_create);
2386 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
2388 struct file_operations *seq_fops,
2391 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2392 mode, seq_fops, data));
2394 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2396 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2398 if (value >= OBD_HIST_MAX)
2399 value = OBD_HIST_MAX - 1;
2401 spin_lock(&oh->oh_lock);
2402 oh->oh_buckets[value]++;
2403 spin_unlock(&oh->oh_lock);
2405 EXPORT_SYMBOL(lprocfs_oh_tally);
2407 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2411 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2414 lprocfs_oh_tally(oh, val);
2416 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2418 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2420 unsigned long ret = 0;
2423 for (i = 0; i < OBD_HIST_MAX; i++)
2424 ret += oh->oh_buckets[i];
2427 EXPORT_SYMBOL(lprocfs_oh_sum);
2429 void lprocfs_oh_clear(struct obd_histogram *oh)
2431 spin_lock(&oh->oh_lock);
2432 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2433 spin_unlock(&oh->oh_lock);
2435 EXPORT_SYMBOL(lprocfs_oh_clear);
2437 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2438 int count, int *eof, void *data)
2440 struct obd_device *obd = data;
2446 c += cfs_hash_debug_header(page, count);
2447 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2448 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2449 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2453 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2455 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2456 int count, int *eof, void *data)
2458 struct obd_device *obd = data;
2461 LASSERT(obd != NULL);
2462 LASSERT(count >= 0);
2464 /* Set start of user data returned to
2465 page + off since the user may have
2466 requested to read much smaller than
2467 what we need to read */
2468 *start = page + off;
2470 /* We know we are allocated a page here.
2471 Also we know that this function will
2472 not need to write more than a page
2473 so we can truncate at CFS_PAGE_SIZE. */
2474 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2476 /* Initialize the page */
2477 memset(page, 0, size);
2479 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2481 if (obd->obd_max_recoverable_clients == 0) {
2482 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2488 /* sampled unlocked, but really... */
2489 if (obd->obd_recovering == 0) {
2490 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2492 if (lprocfs_obd_snprintf(&page, size, &len,
2493 "recovery_start: %lu\n",
2494 obd->obd_recovery_start) <= 0)
2496 if (lprocfs_obd_snprintf(&page, size, &len,
2497 "recovery_duration: %lu\n",
2498 obd->obd_recovery_end -
2499 obd->obd_recovery_start) <= 0)
2501 /* Number of clients that have completed recovery */
2502 if (lprocfs_obd_snprintf(&page, size, &len,
2503 "completed_clients: %d/%d\n",
2504 obd->obd_max_recoverable_clients -
2505 obd->obd_stale_clients,
2506 obd->obd_max_recoverable_clients) <= 0)
2508 if (lprocfs_obd_snprintf(&page, size, &len,
2509 "replayed_requests: %d\n",
2510 obd->obd_replayed_requests) <= 0)
2512 if (lprocfs_obd_snprintf(&page, size, &len,
2513 "last_transno: "LPD64"\n",
2514 obd->obd_next_recovery_transno - 1)<=0)
2516 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2517 obd->obd_version_recov ?
2518 "ENABLED" : "DISABLED") <=0)
2520 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
2522 "DISABLED" : "ENABLED") <= 0)
2527 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2529 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2530 obd->obd_recovery_start) <= 0)
2532 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2533 cfs_time_current_sec() >=
2534 obd->obd_recovery_start +
2535 obd->obd_recovery_timeout ? 0 :
2536 obd->obd_recovery_start +
2537 obd->obd_recovery_timeout -
2538 cfs_time_current_sec()) <= 0)
2540 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2541 cfs_atomic_read(&obd->obd_connected_clients),
2542 obd->obd_max_recoverable_clients) <= 0)
2544 /* Number of clients that have completed recovery */
2545 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2546 cfs_atomic_read(&obd->obd_req_replay_clients))
2549 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2550 cfs_atomic_read(&obd->obd_lock_replay_clients))
2553 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2554 cfs_atomic_read(&obd->obd_connected_clients) -
2555 cfs_atomic_read(&obd->obd_lock_replay_clients))
2558 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2559 obd->obd_stale_clients) <= 0)
2561 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2562 obd->obd_replayed_requests) <= 0)
2564 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2565 obd->obd_requests_queued_for_recovery) <= 0)
2568 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2569 obd->obd_next_recovery_transno) <= 0)
2575 return min(count, len - (int)off);
2577 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2579 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
2580 int count, int *eof, void *data)
2582 struct obd_device *obd = (struct obd_device *)data;
2583 LASSERT(obd != NULL);
2585 return snprintf(page, count, "%d\n",
2586 obd->obd_recovery_ir_factor);
2588 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
2590 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
2591 unsigned long count, void *data)
2593 struct obd_device *obd = (struct obd_device *)data;
2595 LASSERT(obd != NULL);
2597 rc = lprocfs_write_helper(buffer, count, &val);
2601 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
2604 obd->obd_recovery_ir_factor = val;
2607 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
2609 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
2610 int count, int *eof, void *data)
2612 struct obd_device *obd = (struct obd_device *)data;
2613 LASSERT(obd != NULL);
2615 return snprintf(page, count, "%d\n",
2616 obd->obd_recovery_timeout);
2618 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
2620 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
2621 unsigned long count, void *data)
2623 struct obd_device *obd = (struct obd_device *)data;
2625 LASSERT(obd != NULL);
2627 rc = lprocfs_write_helper(buffer, count, &val);
2631 obd->obd_recovery_timeout = val;
2634 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
2636 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
2637 int count, int *eof, void *data)
2639 struct obd_device *obd = data;
2640 LASSERT(obd != NULL);
2642 return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
2644 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
2646 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
2647 unsigned long count, void *data)
2649 struct obd_device *obd = data;
2651 LASSERT(obd != NULL);
2653 rc = lprocfs_write_helper(buffer, count, &val);
2657 obd->obd_recovery_time_hard = val;
2660 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
2662 int lprocfs_obd_rd_mntdev(char *page, char **start, off_t off,
2663 int count, int *eof, void *data)
2665 struct obd_device *obd = (struct obd_device *)data;
2667 LASSERT(obd != NULL);
2668 LASSERT(mnt_get_devname(obd->u.obt.obt_vfsmnt));
2670 return snprintf(page, count, "%s\n",
2671 mnt_get_devname(obd->u.obt.obt_vfsmnt));
2673 EXPORT_SYMBOL(lprocfs_obd_rd_mntdev);
2675 int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
2676 int count, int *eof, void *data)
2678 struct obd_device *dev = data;
2679 struct client_obd *cli = &dev->u.cli;
2682 client_obd_list_lock(&cli->cl_loi_list_lock);
2683 rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
2684 client_obd_list_unlock(&cli->cl_loi_list_lock);
2687 EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
2689 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
2690 int count, int *eof, void *data)
2692 struct obd_device *obd = (struct obd_device *)data;
2693 struct obd_device_target *target = &obd->u.obt;
2695 LASSERT(obd != NULL);
2696 LASSERT(target->obt_magic == OBT_MAGIC);
2698 return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
2700 EXPORT_SYMBOL(lprocfs_target_rd_instance);