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_blksize(char *page, char **start, off_t off, int count,
599 int *eof, void *data)
601 struct obd_device *obd = data;
602 struct obd_statfs osfs;
603 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
604 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
608 rc = snprintf(page, count, "%u\n", osfs.os_bsize);
612 EXPORT_SYMBOL(lprocfs_rd_blksize);
614 int lprocfs_osd_rd_blksize(char *page, char **start, off_t off,
615 int count, int *eof, void *data)
617 struct dt_device *dt = data;
618 struct obd_statfs osfs;
619 int rc = dt_statfs(NULL, dt, &osfs);
622 rc = snprintf(page, count, "%d\n",
623 (unsigned) osfs.os_bsize);
627 EXPORT_SYMBOL(lprocfs_osd_rd_blksize);
629 int lprocfs_rd_kbytestotal(char *page, char **start, off_t off, int count,
630 int *eof, void *data)
632 struct obd_device *obd = data;
633 struct obd_statfs osfs;
634 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
635 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
638 __u32 blk_size = osfs.os_bsize >> 10;
639 __u64 result = osfs.os_blocks;
641 while (blk_size >>= 1)
645 rc = snprintf(page, count, LPU64"\n", result);
649 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
651 int lprocfs_osd_rd_kbytestotal(char *page, char **start, off_t off,
652 int count, int *eof, void *data)
654 struct dt_device *dt = data;
655 struct obd_statfs osfs;
656 int rc = dt_statfs(NULL, dt, &osfs);
658 __u32 blk_size = osfs.os_bsize >> 10;
659 __u64 result = osfs.os_blocks;
661 while (blk_size >>= 1)
665 rc = snprintf(page, count, LPU64"\n", result);
669 EXPORT_SYMBOL(lprocfs_osd_rd_kbytestotal);
671 int lprocfs_rd_kbytesfree(char *page, char **start, off_t off, int count,
672 int *eof, void *data)
674 struct obd_device *obd = data;
675 struct obd_statfs osfs;
676 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
677 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
680 __u32 blk_size = osfs.os_bsize >> 10;
681 __u64 result = osfs.os_bfree;
683 while (blk_size >>= 1)
687 rc = snprintf(page, count, LPU64"\n", result);
691 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
693 int lprocfs_osd_rd_kbytesfree(char *page, char **start, off_t off,
694 int count, int *eof, void *data)
696 struct dt_device *dt = data;
697 struct obd_statfs osfs;
698 int rc = dt_statfs(NULL, dt, &osfs);
700 __u32 blk_size = osfs.os_bsize >> 10;
701 __u64 result = osfs.os_bfree;
703 while (blk_size >>= 1)
707 rc = snprintf(page, count, LPU64"\n", result);
711 EXPORT_SYMBOL(lprocfs_osd_rd_kbytesfree);
713 int lprocfs_rd_kbytesavail(char *page, char **start, off_t off, int count,
714 int *eof, void *data)
716 struct obd_device *obd = data;
717 struct obd_statfs osfs;
718 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
719 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
722 __u32 blk_size = osfs.os_bsize >> 10;
723 __u64 result = osfs.os_bavail;
725 while (blk_size >>= 1)
729 rc = snprintf(page, count, LPU64"\n", result);
733 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
735 int lprocfs_osd_rd_kbytesavail(char *page, char **start, off_t off,
736 int count, int *eof, void *data)
738 struct dt_device *dt = data;
739 struct obd_statfs osfs;
740 int rc = dt_statfs(NULL, dt, &osfs);
742 __u32 blk_size = osfs.os_bsize >> 10;
743 __u64 result = osfs.os_bavail;
745 while (blk_size >>= 1)
749 rc = snprintf(page, count, LPU64"\n", result);
753 EXPORT_SYMBOL(lprocfs_osd_rd_kbytesavail);
755 int lprocfs_rd_filestotal(char *page, char **start, off_t off, int count,
756 int *eof, void *data)
758 struct obd_device *obd = data;
759 struct obd_statfs osfs;
760 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
761 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
765 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
770 EXPORT_SYMBOL(lprocfs_rd_filestotal);
772 int lprocfs_osd_rd_filestotal(char *page, char **start, off_t off,
773 int count, int *eof, void *data)
775 struct dt_device *dt = data;
776 struct obd_statfs osfs;
777 int rc = dt_statfs(NULL, dt, &osfs);
780 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
785 EXPORT_SYMBOL(lprocfs_osd_rd_filestotal);
787 int lprocfs_rd_filesfree(char *page, char **start, off_t off, int count,
788 int *eof, void *data)
790 struct obd_device *obd = data;
791 struct obd_statfs osfs;
792 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
793 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
797 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
801 EXPORT_SYMBOL(lprocfs_rd_filesfree);
803 int lprocfs_osd_rd_filesfree(char *page, char **start, off_t off,
804 int count, int *eof, void *data)
806 struct dt_device *dt = data;
807 struct obd_statfs osfs;
808 int rc = dt_statfs(NULL, dt, &osfs);
811 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
815 EXPORT_SYMBOL(lprocfs_osd_rd_filesfree);
817 int lprocfs_rd_server_uuid(char *page, char **start, off_t off, int count,
818 int *eof, void *data)
820 struct obd_device *obd = data;
821 struct obd_import *imp;
822 char *imp_state_name = NULL;
825 LASSERT(obd != NULL);
826 LPROCFS_CLIMP_CHECK(obd);
827 imp = obd->u.cli.cl_import;
828 imp_state_name = ptlrpc_import_state_name(imp->imp_state);
830 rc = snprintf(page, count, "%s\t%s%s\n",
831 obd2cli_tgt(obd), imp_state_name,
832 imp->imp_deactive ? "\tDEACTIVATED" : "");
834 LPROCFS_CLIMP_EXIT(obd);
837 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
839 int lprocfs_rd_conn_uuid(char *page, char **start, off_t off, int count,
840 int *eof, void *data)
842 struct obd_device *obd = data;
843 struct ptlrpc_connection *conn;
846 LASSERT(obd != NULL);
848 LPROCFS_CLIMP_CHECK(obd);
849 conn = obd->u.cli.cl_import->imp_connection;
851 if (conn && obd->u.cli.cl_import) {
852 rc = snprintf(page, count, "%s\n",
853 conn->c_remote_uuid.uuid);
855 rc = snprintf(page, count, "%s\n", "<none>");
858 LPROCFS_CLIMP_EXIT(obd);
861 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
863 /** add up per-cpu counters */
864 void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
865 struct lprocfs_counter *cnt)
867 struct lprocfs_counter *ptr;
868 unsigned int num_entry;
870 unsigned long flags = 0;
872 memset(cnt, 0, sizeof(*cnt));
875 /* set count to 1 to avoid divide-by-zero errs in callers */
880 cnt->lc_min = LC_MIN_INIT;
882 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
884 for (i = 0; i < num_entry; i++) {
885 if (stats->ls_percpu[i] == NULL)
888 ptr = &(stats->ls_percpu[i])->lp_cntr[idx];
889 cnt->lc_count += ptr->lc_count;
890 cnt->lc_sum += ptr->lc_sum;
891 if (ptr->lc_min < cnt->lc_min)
892 cnt->lc_min = ptr->lc_min;
893 if (ptr->lc_max > cnt->lc_max)
894 cnt->lc_max = ptr->lc_max;
895 cnt->lc_sumsquare += ptr->lc_sumsquare;
898 cnt->lc_units = stats->ls_percpu[0]->lp_cntr[idx].lc_units;
899 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
901 EXPORT_SYMBOL(lprocfs_stats_collect);
904 * Append a space separated list of current set flags to str.
906 #define flag2str(flag) \
907 if (imp->imp_##flag && max - len > 0) \
908 len += snprintf(str + len, max - len, "%s" #flag, len ? ", " : "");
909 static int obd_import_flags2str(struct obd_import *imp, char *str, int max)
913 if (imp->imp_obd->obd_no_recov)
914 len += snprintf(str, max - len, "no_recov");
918 flag2str(replayable);
924 static const char *obd_connect_names[] = {
938 "join_file(obsolete)",
942 "remote_client_by_force",
951 "mds_mds_connection",
954 "alt_checksum_algorithm",
979 int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
984 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
986 ret += snprintf(page + ret, count - ret, "%s%s",
987 ret ? sep : "", obd_connect_names[i]);
989 if (flags & ~(mask - 1))
990 ret += snprintf(page + ret, count - ret,
991 "%sunknown flags "LPX64,
992 ret ? sep : "", flags & ~(mask - 1));
995 EXPORT_SYMBOL(obd_connect_flags2str);
997 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
998 int *eof, void *data)
1000 struct lprocfs_counter ret;
1001 struct obd_device *obd = (struct obd_device *)data;
1002 struct obd_import *imp;
1003 struct obd_import_conn *conn;
1004 int i, j, k, rw = 0;
1006 LASSERT(obd != NULL);
1007 LPROCFS_CLIMP_CHECK(obd);
1008 imp = obd->u.cli.cl_import;
1011 i = snprintf(page, count,
1017 " connect_flags: [",
1020 ptlrpc_import_state_name(imp->imp_state),
1021 imp->imp_connect_data.ocd_instance);
1022 i += obd_connect_flags2str(page + i, count - i,
1023 imp->imp_connect_data.ocd_connect_flags,
1025 i += snprintf(page + i, count - i,
1027 " import_flags: [");
1028 i += obd_import_flags2str(imp, page + i, count - i);
1030 i += snprintf(page + i, count - i,
1033 " failover_nids: [");
1034 spin_lock(&imp->imp_lock);
1036 cfs_list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
1037 i += snprintf(page + i, count - i, "%s%s", j ? ", " : "",
1038 libcfs_nid2str(conn->oic_conn->c_peer.nid));
1041 i += snprintf(page + i, count - i,
1043 " current_connection: %s\n"
1044 " connection_attempts: %u\n"
1046 " in-progress_invalidations: %u\n",
1047 imp->imp_connection == NULL ? "<none>" :
1048 libcfs_nid2str(imp->imp_connection->c_peer.nid),
1050 imp->imp_generation,
1051 cfs_atomic_read(&imp->imp_inval_count));
1052 spin_unlock(&imp->imp_lock);
1054 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
1055 if (ret.lc_count != 0) {
1056 /* first argument to do_div MUST be __u64 */
1057 __u64 sum = ret.lc_sum;
1058 do_div(sum, ret.lc_count);
1062 i += snprintf(page + i, count - i,
1065 " unregistering: %u\n"
1067 " avg_waittime: "LPU64" %s\n",
1068 cfs_atomic_read(&imp->imp_inflight),
1069 cfs_atomic_read(&imp->imp_unregistering),
1070 cfs_atomic_read(&imp->imp_timeouts),
1071 ret.lc_sum, ret.lc_units);
1074 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
1075 if (imp->imp_at.iat_portal[j] == 0)
1077 k = max_t(unsigned int, k,
1078 at_get(&imp->imp_at.iat_service_estimate[j]));
1080 i += snprintf(page + i, count - i,
1081 " service_estimates:\n"
1082 " services: %u sec\n"
1083 " network: %u sec\n",
1085 at_get(&imp->imp_at.iat_net_latency));
1087 i += snprintf(page + i, count - i,
1089 " last_replay: "LPU64"\n"
1090 " peer_committed: "LPU64"\n"
1091 " last_checked: "LPU64"\n",
1092 imp->imp_last_replay_transno,
1093 imp->imp_peer_committed_transno,
1094 imp->imp_last_transno_checked);
1096 /* avg data rates */
1097 for (rw = 0; rw <= 1; rw++) {
1098 lprocfs_stats_collect(obd->obd_svc_stats,
1099 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
1101 if (ret.lc_sum > 0 && ret.lc_count > 0) {
1102 /* first argument to do_div MUST be __u64 */
1103 __u64 sum = ret.lc_sum;
1104 do_div(sum, ret.lc_count);
1106 i += snprintf(page + i, count - i,
1107 " %s_data_averages:\n"
1108 " bytes_per_rpc: "LPU64"\n",
1109 rw ? "write" : "read",
1112 k = (int)ret.lc_sum;
1113 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
1114 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
1115 if (ret.lc_sum > 0 && ret.lc_count != 0) {
1116 /* first argument to do_div MUST be __u64 */
1117 __u64 sum = ret.lc_sum;
1118 do_div(sum, ret.lc_count);
1120 i += snprintf(page + i, count - i,
1121 " %s_per_rpc: "LPU64"\n",
1122 ret.lc_units, ret.lc_sum);
1123 j = (int)ret.lc_sum;
1125 i += snprintf(page + i, count - i,
1126 " MB_per_sec: %u.%.02u\n",
1127 k / j, (100 * k / j) % 100);
1131 LPROCFS_CLIMP_EXIT(obd);
1134 EXPORT_SYMBOL(lprocfs_rd_import);
1136 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
1137 int *eof, void *data)
1139 struct obd_device *obd = (struct obd_device *)data;
1140 struct obd_import *imp;
1143 LASSERT(obd != NULL);
1144 LPROCFS_CLIMP_CHECK(obd);
1145 imp = obd->u.cli.cl_import;
1148 i = snprintf(page, count, "current_state: %s\n",
1149 ptlrpc_import_state_name(imp->imp_state));
1150 i += snprintf(page + i, count - i,
1151 "state_history:\n");
1152 k = imp->imp_state_hist_idx;
1153 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
1154 struct import_state_hist *ish =
1155 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
1156 if (ish->ish_state == 0)
1158 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
1160 ptlrpc_import_state_name(ish->ish_state));
1163 LPROCFS_CLIMP_EXIT(obd);
1166 EXPORT_SYMBOL(lprocfs_rd_state);
1168 int lprocfs_at_hist_helper(char *page, int count, int rc,
1169 struct adaptive_timeout *at)
1172 for (i = 0; i < AT_BINS; i++)
1173 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
1174 rc += snprintf(page + rc, count - rc, "\n");
1177 EXPORT_SYMBOL(lprocfs_at_hist_helper);
1179 /* See also ptlrpc_lprocfs_rd_timeouts */
1180 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
1181 int *eof, void *data)
1183 struct obd_device *obd = (struct obd_device *)data;
1184 struct obd_import *imp;
1185 unsigned int cur, worst;
1190 LASSERT(obd != NULL);
1191 LPROCFS_CLIMP_CHECK(obd);
1192 imp = obd->u.cli.cl_import;
1195 now = cfs_time_current_sec();
1197 /* Some network health info for kicks */
1198 s2dhms(&ts, now - imp->imp_last_reply_time);
1199 rc += snprintf(page + rc, count - rc,
1200 "%-10s : %ld, "DHMS_FMT" ago\n",
1201 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
1203 cur = at_get(&imp->imp_at.iat_net_latency);
1204 worst = imp->imp_at.iat_net_latency.at_worst_ever;
1205 worstt = imp->imp_at.iat_net_latency.at_worst_time;
1206 s2dhms(&ts, now - worstt);
1207 rc += snprintf(page + rc, count - rc,
1208 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
1209 "network", cur, worst, worstt, DHMS_VARS(&ts));
1210 rc = lprocfs_at_hist_helper(page, count, rc,
1211 &imp->imp_at.iat_net_latency);
1213 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
1214 if (imp->imp_at.iat_portal[i] == 0)
1216 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
1217 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
1218 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
1219 s2dhms(&ts, now - worstt);
1220 rc += snprintf(page + rc, count - rc,
1221 "portal %-2d : cur %3u worst %3u (at %ld, "
1222 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
1223 cur, worst, worstt, DHMS_VARS(&ts));
1224 rc = lprocfs_at_hist_helper(page, count, rc,
1225 &imp->imp_at.iat_service_estimate[i]);
1228 LPROCFS_CLIMP_EXIT(obd);
1231 EXPORT_SYMBOL(lprocfs_rd_timeouts);
1233 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1234 int count, int *eof, void *data)
1236 struct obd_device *obd = data;
1240 LPROCFS_CLIMP_CHECK(obd);
1241 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1242 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1243 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1244 ret += snprintf(page + ret, count - ret, "\n");
1245 LPROCFS_CLIMP_EXIT(obd);
1248 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1250 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1251 int *eof, void *data)
1253 struct obd_device *obd = data;
1255 LASSERT(obd != NULL);
1257 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1259 EXPORT_SYMBOL(lprocfs_rd_num_exports);
1261 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1262 int *eof, void *data)
1264 struct obd_type *class = (struct obd_type*) data;
1266 LASSERT(class != NULL);
1268 return snprintf(page, count, "%d\n", class->typ_refcnt);
1270 EXPORT_SYMBOL(lprocfs_rd_numrefs);
1272 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1276 LASSERT(obd != NULL);
1277 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1278 LASSERT(obd->obd_type->typ_procroot != NULL);
1280 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1281 obd->obd_type->typ_procroot,
1283 if (IS_ERR(obd->obd_proc_entry)) {
1284 rc = PTR_ERR(obd->obd_proc_entry);
1285 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1286 obd->obd_proc_entry = NULL;
1290 EXPORT_SYMBOL(lprocfs_obd_setup);
1292 int lprocfs_obd_cleanup(struct obd_device *obd)
1296 if (obd->obd_proc_exports_entry) {
1297 /* Should be no exports left */
1298 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1299 lprocfs_remove(&obd->obd_proc_exports_entry);
1300 obd->obd_proc_exports_entry = NULL;
1302 if (obd->obd_proc_entry) {
1303 lprocfs_remove(&obd->obd_proc_entry);
1304 obd->obd_proc_entry = NULL;
1308 EXPORT_SYMBOL(lprocfs_obd_cleanup);
1310 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1312 CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
1313 client_stat->nid_proc, client_stat->nid_stats,
1314 client_stat->nid_brw_stats);
1316 LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
1317 "nid %s:count %d\n", libcfs_nid2str(client_stat->nid),
1318 atomic_read(&client_stat->nid_exp_ref_count));
1320 if (client_stat->nid_proc)
1321 lprocfs_remove(&client_stat->nid_proc);
1323 if (client_stat->nid_stats)
1324 lprocfs_free_stats(&client_stat->nid_stats);
1326 if (client_stat->nid_brw_stats)
1327 OBD_FREE_PTR(client_stat->nid_brw_stats);
1329 if (client_stat->nid_ldlm_stats)
1330 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1332 OBD_FREE_PTR(client_stat);
1337 void lprocfs_free_per_client_stats(struct obd_device *obd)
1339 cfs_hash_t *hash = obd->obd_nid_stats_hash;
1340 struct nid_stat *stat;
1343 /* we need extra list - because hash_exit called to early */
1344 /* not need locking because all clients is died */
1345 while (!cfs_list_empty(&obd->obd_nid_stats)) {
1346 stat = cfs_list_entry(obd->obd_nid_stats.next,
1347 struct nid_stat, nid_list);
1348 cfs_list_del_init(&stat->nid_list);
1349 cfs_hash_del(hash, &stat->nid, &stat->nid_hash);
1350 lprocfs_free_client_stats(stat);
1354 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
1356 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1357 enum lprocfs_stats_flags flags)
1359 struct lprocfs_stats *stats;
1360 unsigned int percpusize;
1361 unsigned int num_entry;
1366 if (lprocfs_no_percpu_stats != 0)
1367 flags |= LPROCFS_STATS_FLAG_NOPERCPU;
1369 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1372 num_entry = cfs_num_possible_cpus() + 1;
1374 /* alloc percpu pointers for all possible cpu slots */
1375 OBD_ALLOC(stats, offsetof(struct lprocfs_stats, ls_percpu[num_entry]));
1379 stats->ls_num = num;
1380 stats->ls_biggest_alloc_num = 1;
1381 stats->ls_flags = flags;
1382 spin_lock_init(&stats->ls_lock);
1384 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
1386 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1388 /* for no percpu area, the 0th entry is for real use,
1389 * for percpu area, the 0th entry is for intialized entry template */
1390 OBD_ALLOC(stats->ls_percpu[0], percpusize);
1391 if (stats->ls_percpu[0] == NULL) {
1393 offsetof(struct lprocfs_stats, ls_percpu[num_entry]));
1398 EXPORT_SYMBOL(lprocfs_alloc_stats);
1400 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1402 struct lprocfs_stats *stats = *statsh;
1403 unsigned int num_entry;
1404 unsigned int percpusize;
1407 if (stats == NULL || stats->ls_num == 0)
1411 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1414 num_entry = cfs_num_possible_cpus() + 1;
1416 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
1418 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1419 for (i = 0; i < num_entry; i++)
1420 if (stats->ls_percpu[i] != NULL)
1421 OBD_FREE(stats->ls_percpu[i], percpusize);
1422 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1424 EXPORT_SYMBOL(lprocfs_free_stats);
1426 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1428 struct lprocfs_counter *percpu_cntr;
1431 unsigned int num_entry;
1432 unsigned long flags = 0;
1434 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1436 for (i = 0; i < num_entry; i++) {
1437 if (stats->ls_percpu[i] == NULL)
1439 for (j = 0; j < stats->ls_num; j++) {
1440 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
1441 percpu_cntr->lc_count = 0;
1442 percpu_cntr->lc_sum = 0;
1443 percpu_cntr->lc_min = LC_MIN_INIT;
1444 percpu_cntr->lc_max = 0;
1445 percpu_cntr->lc_sumsquare = 0;
1449 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1451 EXPORT_SYMBOL(lprocfs_clear_stats);
1453 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1454 size_t len, loff_t *off)
1456 struct seq_file *seq = file->private_data;
1457 struct lprocfs_stats *stats = seq->private;
1459 lprocfs_clear_stats(stats);
1464 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1466 struct lprocfs_stats *stats = p->private;
1467 /* return 1st cpu location */
1468 return (*pos >= stats->ls_num) ? NULL :
1469 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1472 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1476 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1478 struct lprocfs_stats *stats = p->private;
1480 return (*pos >= stats->ls_num) ? NULL :
1481 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1484 /* seq file export of one lprocfs counter */
1485 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1487 struct lprocfs_stats *stats = p->private;
1488 struct lprocfs_counter *cntr = v;
1489 struct lprocfs_counter ret;
1492 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
1494 cfs_gettimeofday(&now);
1495 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1496 "snapshot_time", now.tv_sec, now.tv_usec);
1500 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
1502 lprocfs_stats_collect(stats, idx, &ret);
1504 if (ret.lc_count == 0)
1507 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", cntr->lc_name,
1508 ret.lc_count, cntr->lc_units);
1513 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
1514 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1515 ret.lc_min, ret.lc_max, ret.lc_sum);
1518 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
1519 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1523 rc = seq_printf(p, "\n");
1525 return (rc < 0) ? rc : 0;
1528 struct seq_operations lprocfs_stats_seq_sops = {
1529 start: lprocfs_stats_seq_start,
1530 stop: lprocfs_stats_seq_stop,
1531 next: lprocfs_stats_seq_next,
1532 show: lprocfs_stats_seq_show,
1535 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1537 struct proc_dir_entry *dp = PDE(inode);
1538 struct seq_file *seq;
1541 if (LPROCFS_ENTRY_AND_CHECK(dp))
1544 rc = seq_open(file, &lprocfs_stats_seq_sops);
1549 seq = file->private_data;
1550 seq->private = dp->data;
1554 struct file_operations lprocfs_stats_seq_fops = {
1555 .owner = THIS_MODULE,
1556 .open = lprocfs_stats_seq_open,
1558 .write = lprocfs_stats_seq_write,
1559 .llseek = seq_lseek,
1560 .release = lprocfs_seq_release,
1563 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1564 struct lprocfs_stats *stats)
1566 struct proc_dir_entry *entry;
1567 LASSERT(root != NULL);
1569 LPROCFS_WRITE_ENTRY();
1570 entry = create_proc_entry(name, 0644, root);
1572 entry->proc_fops = &lprocfs_stats_seq_fops;
1573 entry->data = stats;
1576 LPROCFS_WRITE_EXIT();
1583 EXPORT_SYMBOL(lprocfs_register_stats);
1585 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1586 unsigned conf, const char *name, const char *units)
1588 struct lprocfs_counter *c = &(stats->ls_percpu[0]->lp_cntr[index]);
1589 unsigned long flags = 0;
1591 LASSERT(stats != NULL);
1592 LASSERT(stats->ls_percpu[0] != NULL);
1594 lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1595 c->lc_config = conf;
1598 c->lc_min = LC_MIN_INIT;
1601 c->lc_units = units;
1602 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1604 EXPORT_SYMBOL(lprocfs_counter_init);
1606 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1608 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1609 LASSERT(coffset < stats->ls_num); \
1610 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1613 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1615 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1616 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1617 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1618 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1619 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1620 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1621 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1622 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1623 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1624 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1625 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1626 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1627 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1628 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1629 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1630 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1631 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1632 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1633 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1634 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1635 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1636 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1637 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1638 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1639 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1640 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1641 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1642 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1643 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1644 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1645 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1646 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1647 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1648 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1649 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1650 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1651 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1652 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1653 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1654 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1655 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1656 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1657 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1658 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
1659 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1660 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1661 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1662 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1663 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1664 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1665 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1666 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1667 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1668 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1669 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1670 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1671 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1672 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1673 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1674 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1675 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1676 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1677 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1678 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1679 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1680 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1681 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1683 EXPORT_SYMBOL(lprocfs_init_ops_stats);
1685 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1687 struct lprocfs_stats *stats;
1688 unsigned int num_stats;
1691 LASSERT(obd->obd_stats == NULL);
1692 LASSERT(obd->obd_proc_entry != NULL);
1693 LASSERT(obd->obd_cntr_base == 0);
1695 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1696 num_private_stats - 1 /* o_owner */;
1697 stats = lprocfs_alloc_stats(num_stats, 0);
1701 lprocfs_init_ops_stats(num_private_stats, stats);
1703 for (i = num_private_stats; i < num_stats; i++) {
1704 /* If this LBUGs, it is likely that an obd
1705 * operation was added to struct obd_ops in
1706 * <obd.h>, and that the corresponding line item
1707 * LPROCFS_OBD_OP_INIT(.., .., opname)
1708 * is missing from the list above. */
1709 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1710 "Missing obd_stat initializer obd_op "
1711 "operation at offset %d.\n", i - num_private_stats);
1713 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1715 lprocfs_free_stats(&stats);
1717 obd->obd_stats = stats;
1718 obd->obd_cntr_base = num_private_stats;
1722 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
1724 void lprocfs_free_obd_stats(struct obd_device *obd)
1727 lprocfs_free_stats(&obd->obd_stats);
1729 EXPORT_SYMBOL(lprocfs_free_obd_stats);
1731 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1733 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1734 LASSERT(coffset < stats->ls_num); \
1735 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1738 void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats)
1740 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1741 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1742 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
1743 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1744 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1745 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1746 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1747 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1748 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1749 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1750 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1751 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1752 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1753 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1754 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1755 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1756 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1757 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1758 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1759 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1760 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1761 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1762 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1763 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1764 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1765 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1766 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1767 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1768 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1769 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1770 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1771 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1773 EXPORT_SYMBOL(lprocfs_init_mps_stats);
1775 int lprocfs_alloc_md_stats(struct obd_device *obd,
1776 unsigned num_private_stats)
1778 struct lprocfs_stats *stats;
1779 unsigned int num_stats;
1782 LASSERT(obd->md_stats == NULL);
1783 LASSERT(obd->obd_proc_entry != NULL);
1784 LASSERT(obd->md_cntr_base == 0);
1786 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1788 stats = lprocfs_alloc_stats(num_stats, 0);
1792 lprocfs_init_mps_stats(num_private_stats, stats);
1794 for (i = num_private_stats; i < num_stats; i++) {
1795 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1796 CERROR("Missing md_stat initializer md_op "
1797 "operation at offset %d. Aborting.\n",
1798 i - num_private_stats);
1802 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1804 lprocfs_free_stats(&stats);
1806 obd->md_stats = stats;
1807 obd->md_cntr_base = num_private_stats;
1811 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
1813 void lprocfs_free_md_stats(struct obd_device *obd)
1815 struct lprocfs_stats *stats = obd->md_stats;
1817 if (stats != NULL) {
1818 obd->md_stats = NULL;
1819 obd->md_cntr_base = 0;
1820 lprocfs_free_stats(&stats);
1823 EXPORT_SYMBOL(lprocfs_free_md_stats);
1825 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1827 lprocfs_counter_init(ldlm_stats,
1828 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1829 0, "ldlm_enqueue", "reqs");
1830 lprocfs_counter_init(ldlm_stats,
1831 LDLM_CONVERT - LDLM_FIRST_OPC,
1832 0, "ldlm_convert", "reqs");
1833 lprocfs_counter_init(ldlm_stats,
1834 LDLM_CANCEL - LDLM_FIRST_OPC,
1835 0, "ldlm_cancel", "reqs");
1836 lprocfs_counter_init(ldlm_stats,
1837 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1838 0, "ldlm_bl_callback", "reqs");
1839 lprocfs_counter_init(ldlm_stats,
1840 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1841 0, "ldlm_cp_callback", "reqs");
1842 lprocfs_counter_init(ldlm_stats,
1843 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1844 0, "ldlm_gl_callback", "reqs");
1846 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
1848 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1849 int *eof, void *data)
1851 struct obd_export *exp = data;
1852 LASSERT(exp != NULL);
1854 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1857 struct exp_uuid_cb_data {
1865 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1866 int count, int *eof, int *len)
1868 cb_data->page = page;
1869 cb_data->count = count;
1874 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1875 cfs_hlist_node_t *hnode, void *cb_data)
1878 struct obd_export *exp = cfs_hash_object(hs, hnode);
1879 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1881 if (exp->exp_nid_stats)
1882 *data->len += snprintf((data->page + *data->len),
1883 data->count, "%s\n",
1884 obd_uuid2str(&exp->exp_client_uuid));
1888 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1889 int *eof, void *data)
1891 struct nid_stat *stats = (struct nid_stat *)data;
1892 struct exp_uuid_cb_data cb_data;
1893 struct obd_device *obd = stats->nid_obd;
1898 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1899 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1900 lprocfs_exp_print_uuid, &cb_data);
1901 return (*cb_data.len);
1904 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1905 cfs_hlist_node_t *hnode, void *cb_data)
1908 struct exp_uuid_cb_data *data = cb_data;
1909 struct obd_export *exp = cfs_hash_object(hs, hnode);
1911 if (exp->exp_lock_hash != NULL) {
1913 *data->len += cfs_hash_debug_header(data->page,
1916 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1923 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1924 int *eof, void *data)
1926 struct nid_stat *stats = (struct nid_stat *)data;
1927 struct exp_uuid_cb_data cb_data;
1928 struct obd_device *obd = stats->nid_obd;
1933 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1935 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1936 lprocfs_exp_print_hash, &cb_data);
1937 return (*cb_data.len);
1940 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1941 int count, int *eof, void *data)
1944 return snprintf(page, count, "%s\n",
1945 "Write into this file to clear all nid stats and "
1946 "stale nid entries");
1948 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1950 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1952 struct nid_stat *stat = obj;
1956 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
1957 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 1) {
1958 /* object has only hash references. */
1959 spin_lock(&stat->nid_obd->obd_nid_lock);
1960 cfs_list_move(&stat->nid_list, data);
1961 spin_unlock(&stat->nid_obd->obd_nid_lock);
1964 /* we has reference to object - only clear data*/
1965 if (stat->nid_stats)
1966 lprocfs_clear_stats(stat->nid_stats);
1968 if (stat->nid_brw_stats) {
1969 for (i = 0; i < BRW_LAST; i++)
1970 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
1975 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1976 unsigned long count, void *data)
1978 struct obd_device *obd = (struct obd_device *)data;
1979 struct nid_stat *client_stat;
1980 CFS_LIST_HEAD(free_list);
1982 cfs_hash_cond_del(obd->obd_nid_stats_hash,
1983 lprocfs_nid_stats_clear_write_cb, &free_list);
1985 while (!cfs_list_empty(&free_list)) {
1986 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
1988 cfs_list_del_init(&client_stat->nid_list);
1989 lprocfs_free_client_stats(client_stat);
1994 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1996 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1998 struct nid_stat *new_stat, *old_stat;
1999 struct obd_device *obd = NULL;
2000 cfs_proc_dir_entry_t *entry;
2001 char *buffer = NULL;
2007 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
2008 !exp->exp_obd->obd_nid_stats_hash)
2011 /* not test against zero because eric say:
2012 * You may only test nid against another nid, or LNET_NID_ANY.
2013 * Anything else is nonsense.*/
2014 if (!nid || *nid == LNET_NID_ANY)
2019 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
2021 OBD_ALLOC_PTR(new_stat);
2022 if (new_stat == NULL)
2025 new_stat->nid = *nid;
2026 new_stat->nid_obd = exp->exp_obd;
2027 /* we need set default refcount to 1 to balance obd_disconnect */
2028 cfs_atomic_set(&new_stat->nid_exp_ref_count, 1);
2030 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
2031 nid, &new_stat->nid_hash);
2032 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
2033 old_stat, libcfs_nid2str(*nid),
2034 cfs_atomic_read(&new_stat->nid_exp_ref_count));
2036 /* We need to release old stats because lprocfs_exp_cleanup() hasn't
2037 * been and will never be called. */
2038 if (exp->exp_nid_stats) {
2039 nidstat_putref(exp->exp_nid_stats);
2040 exp->exp_nid_stats = NULL;
2043 /* Return -EALREADY here so that we know that the /proc
2044 * entry already has been created */
2045 if (old_stat != new_stat) {
2046 exp->exp_nid_stats = old_stat;
2047 GOTO(destroy_new, rc = -EALREADY);
2049 /* not found - create */
2050 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
2052 GOTO(destroy_new, rc = -ENOMEM);
2054 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
2055 new_stat->nid_proc = lprocfs_register(buffer,
2056 obd->obd_proc_exports_entry,
2058 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
2060 if (new_stat->nid_proc == NULL) {
2061 CERROR("Error making export directory for nid %s\n",
2062 libcfs_nid2str(*nid));
2063 GOTO(destroy_new_ns, rc = -ENOMEM);
2066 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
2067 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
2068 if (IS_ERR(entry)) {
2069 CWARN("Error adding the NID stats file\n");
2070 rc = PTR_ERR(entry);
2071 GOTO(destroy_new_ns, rc);
2074 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
2075 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
2076 if (IS_ERR(entry)) {
2077 CWARN("Error adding the hash file\n");
2078 rc = PTR_ERR(entry);
2079 GOTO(destroy_new_ns, rc);
2082 exp->exp_nid_stats = new_stat;
2084 /* protect competitive add to list, not need locking on destroy */
2085 spin_lock(&obd->obd_nid_lock);
2086 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
2087 spin_unlock(&obd->obd_nid_lock);
2092 if (new_stat->nid_proc != NULL)
2093 lprocfs_remove(&new_stat->nid_proc);
2094 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
2097 nidstat_putref(new_stat);
2098 OBD_FREE_PTR(new_stat);
2101 EXPORT_SYMBOL(lprocfs_exp_setup);
2103 int lprocfs_exp_cleanup(struct obd_export *exp)
2105 struct nid_stat *stat = exp->exp_nid_stats;
2107 if(!stat || !exp->exp_obd)
2110 nidstat_putref(exp->exp_nid_stats);
2111 exp->exp_nid_stats = NULL;
2115 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2117 int lprocfs_write_helper(const char *buffer, unsigned long count,
2120 return lprocfs_write_frac_helper(buffer, count, val, 1);
2122 EXPORT_SYMBOL(lprocfs_write_helper);
2124 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
2127 char kernbuf[20], *end, *pbuf;
2129 if (count > (sizeof(kernbuf) - 1))
2132 if (cfs_copy_from_user(kernbuf, buffer, count))
2135 kernbuf[count] = '\0';
2142 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2146 if (end != NULL && *end == '.') {
2147 int temp_val, pow = 1;
2151 if (strlen(pbuf) > 5)
2152 pbuf[5] = '\0'; /*only allow 5bits fractional*/
2154 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2157 for (i = 0; i < (end - pbuf); i++)
2160 *val += temp_val / pow;
2165 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2167 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
2170 long decimal_val, frac_val;
2176 decimal_val = val / mult;
2177 prtn = snprintf(buffer, count, "%ld", decimal_val);
2178 frac_val = val % mult;
2180 if (prtn < (count - 4) && frac_val > 0) {
2182 int i, temp_mult = 1, frac_bits = 0;
2184 temp_frac = frac_val * 10;
2185 buffer[prtn++] = '.';
2186 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
2187 /* only reserved 2 bits fraction */
2188 buffer[prtn++] ='0';
2193 * Need to think these cases :
2194 * 1. #echo x.00 > /proc/xxx output result : x
2195 * 2. #echo x.0x > /proc/xxx output result : x.0x
2196 * 3. #echo x.x0 > /proc/xxx output result : x.x
2197 * 4. #echo x.xx > /proc/xxx output result : x.xx
2198 * Only reserved 2 bits fraction.
2200 for (i = 0; i < (5 - prtn); i++)
2203 frac_bits = min((int)count - prtn, 3 - frac_bits);
2204 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
2205 frac_val * temp_mult / mult);
2208 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
2210 if (buffer[prtn] == '.') {
2217 buffer[prtn++] ='\n';
2220 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2222 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
2224 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
2226 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2228 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
2229 __u64 *val, int mult)
2231 char kernbuf[22], *end, *pbuf;
2232 __u64 whole, frac = 0, units;
2233 unsigned frac_d = 1;
2235 if (count > (sizeof(kernbuf) - 1))
2238 if (cfs_copy_from_user(kernbuf, buffer, count))
2241 kernbuf[count] = '\0';
2248 whole = simple_strtoull(pbuf, &end, 10);
2252 if (end != NULL && *end == '.') {
2256 /* need to limit frac_d to a __u32 */
2257 if (strlen(pbuf) > 10)
2260 frac = simple_strtoull(pbuf, &end, 10);
2261 /* count decimal places */
2262 for (i = 0; i < (end - pbuf); i++)
2279 /* Specified units override the multiplier */
2281 mult = mult < 0 ? -units : units;
2284 do_div(frac, frac_d);
2285 *val = whole * mult + frac;
2288 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2290 static char *lprocfs_strnstr(const char *s1, const char *s2, size_t len)
2299 if (!memcmp(s1, s2, l2))
2307 * Find the string \a name in the input \a buffer, and return a pointer to the
2308 * value immediately following \a name, reducing \a count appropriately.
2309 * If \a name is not found the original \a buffer is returned.
2311 char *lprocfs_find_named_value(const char *buffer, const char *name,
2312 unsigned long *count)
2315 size_t buflen = *count;
2317 /* there is no strnstr() in rhel5 and ubuntu kernels */
2318 val = lprocfs_strnstr(buffer, name, buflen);
2320 return (char *)buffer;
2322 val += strlen(name); /* skip prefix */
2323 while (val < buffer + buflen && isspace(*val)) /* skip separator */
2327 while (val < buffer + buflen && isalnum(*val)) {
2332 return val - *count;
2334 EXPORT_SYMBOL(lprocfs_find_named_value);
2336 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent,
2339 const struct file_operations *seq_fops,
2342 struct proc_dir_entry *entry;
2345 LPROCFS_WRITE_ENTRY();
2346 entry = create_proc_entry(name, mode, parent);
2348 entry->proc_fops = seq_fops;
2351 LPROCFS_WRITE_EXIT();
2358 EXPORT_SYMBOL(lprocfs_seq_create);
2360 int lprocfs_obd_seq_create(struct obd_device *dev,
2363 const struct file_operations *seq_fops,
2366 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2367 mode, seq_fops, data));
2369 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2371 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2373 if (value >= OBD_HIST_MAX)
2374 value = OBD_HIST_MAX - 1;
2376 spin_lock(&oh->oh_lock);
2377 oh->oh_buckets[value]++;
2378 spin_unlock(&oh->oh_lock);
2380 EXPORT_SYMBOL(lprocfs_oh_tally);
2382 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2386 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2389 lprocfs_oh_tally(oh, val);
2391 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2393 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2395 unsigned long ret = 0;
2398 for (i = 0; i < OBD_HIST_MAX; i++)
2399 ret += oh->oh_buckets[i];
2402 EXPORT_SYMBOL(lprocfs_oh_sum);
2404 void lprocfs_oh_clear(struct obd_histogram *oh)
2406 spin_lock(&oh->oh_lock);
2407 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2408 spin_unlock(&oh->oh_lock);
2410 EXPORT_SYMBOL(lprocfs_oh_clear);
2412 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2413 int count, int *eof, void *data)
2415 struct obd_device *obd = data;
2421 c += cfs_hash_debug_header(page, count);
2422 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2423 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2424 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2428 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2430 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2431 int count, int *eof, void *data)
2433 struct obd_device *obd = data;
2436 LASSERT(obd != NULL);
2437 LASSERT(count >= 0);
2439 /* Set start of user data returned to
2440 page + off since the user may have
2441 requested to read much smaller than
2442 what we need to read */
2443 *start = page + off;
2445 /* We know we are allocated a page here.
2446 Also we know that this function will
2447 not need to write more than a page
2448 so we can truncate at CFS_PAGE_SIZE. */
2449 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2451 /* Initialize the page */
2452 memset(page, 0, size);
2454 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2456 if (obd->obd_max_recoverable_clients == 0) {
2457 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2463 /* sampled unlocked, but really... */
2464 if (obd->obd_recovering == 0) {
2465 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2467 if (lprocfs_obd_snprintf(&page, size, &len,
2468 "recovery_start: %lu\n",
2469 obd->obd_recovery_start) <= 0)
2471 if (lprocfs_obd_snprintf(&page, size, &len,
2472 "recovery_duration: %lu\n",
2473 obd->obd_recovery_end -
2474 obd->obd_recovery_start) <= 0)
2476 /* Number of clients that have completed recovery */
2477 if (lprocfs_obd_snprintf(&page, size, &len,
2478 "completed_clients: %d/%d\n",
2479 obd->obd_max_recoverable_clients -
2480 obd->obd_stale_clients,
2481 obd->obd_max_recoverable_clients) <= 0)
2483 if (lprocfs_obd_snprintf(&page, size, &len,
2484 "replayed_requests: %d\n",
2485 obd->obd_replayed_requests) <= 0)
2487 if (lprocfs_obd_snprintf(&page, size, &len,
2488 "last_transno: "LPD64"\n",
2489 obd->obd_next_recovery_transno - 1)<=0)
2491 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2492 obd->obd_version_recov ?
2493 "ENABLED" : "DISABLED") <=0)
2495 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
2497 "DISABLED" : "ENABLED") <= 0)
2502 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2504 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2505 obd->obd_recovery_start) <= 0)
2507 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2508 cfs_time_current_sec() >=
2509 obd->obd_recovery_start +
2510 obd->obd_recovery_timeout ? 0 :
2511 obd->obd_recovery_start +
2512 obd->obd_recovery_timeout -
2513 cfs_time_current_sec()) <= 0)
2515 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2516 cfs_atomic_read(&obd->obd_connected_clients),
2517 obd->obd_max_recoverable_clients) <= 0)
2519 /* Number of clients that have completed recovery */
2520 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2521 cfs_atomic_read(&obd->obd_req_replay_clients))
2524 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2525 cfs_atomic_read(&obd->obd_lock_replay_clients))
2528 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2529 cfs_atomic_read(&obd->obd_connected_clients) -
2530 cfs_atomic_read(&obd->obd_lock_replay_clients))
2533 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2534 obd->obd_stale_clients) <= 0)
2536 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2537 obd->obd_replayed_requests) <= 0)
2539 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2540 obd->obd_requests_queued_for_recovery) <= 0)
2543 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2544 obd->obd_next_recovery_transno) <= 0)
2550 return min(count, len - (int)off);
2552 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2554 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
2555 int count, int *eof, void *data)
2557 struct obd_device *obd = (struct obd_device *)data;
2558 LASSERT(obd != NULL);
2560 return snprintf(page, count, "%d\n",
2561 obd->obd_recovery_ir_factor);
2563 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
2565 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
2566 unsigned long count, void *data)
2568 struct obd_device *obd = (struct obd_device *)data;
2570 LASSERT(obd != NULL);
2572 rc = lprocfs_write_helper(buffer, count, &val);
2576 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
2579 obd->obd_recovery_ir_factor = val;
2582 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
2584 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
2585 int count, int *eof, void *data)
2587 struct obd_device *obd = (struct obd_device *)data;
2588 LASSERT(obd != NULL);
2590 return snprintf(page, count, "%d\n",
2591 obd->obd_recovery_timeout);
2593 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
2595 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
2596 unsigned long count, void *data)
2598 struct obd_device *obd = (struct obd_device *)data;
2600 LASSERT(obd != NULL);
2602 rc = lprocfs_write_helper(buffer, count, &val);
2606 obd->obd_recovery_timeout = val;
2609 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
2611 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
2612 int count, int *eof, void *data)
2614 struct obd_device *obd = data;
2615 LASSERT(obd != NULL);
2617 return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
2619 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
2621 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
2622 unsigned long count, void *data)
2624 struct obd_device *obd = data;
2626 LASSERT(obd != NULL);
2628 rc = lprocfs_write_helper(buffer, count, &val);
2632 obd->obd_recovery_time_hard = val;
2635 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
2637 int lprocfs_obd_rd_mntdev(char *page, char **start, off_t off,
2638 int count, int *eof, void *data)
2640 struct obd_device *obd = (struct obd_device *)data;
2642 LASSERT(obd != NULL);
2643 LASSERT(mnt_get_devname(obd->u.obt.obt_vfsmnt));
2645 return snprintf(page, count, "%s\n",
2646 mnt_get_devname(obd->u.obt.obt_vfsmnt));
2648 EXPORT_SYMBOL(lprocfs_obd_rd_mntdev);
2650 int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
2651 int count, int *eof, void *data)
2653 struct obd_device *dev = data;
2654 struct client_obd *cli = &dev->u.cli;
2657 client_obd_list_lock(&cli->cl_loi_list_lock);
2658 rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
2659 client_obd_list_unlock(&cli->cl_loi_list_lock);
2662 EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
2664 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
2665 int count, int *eof, void *data)
2667 struct obd_device *obd = (struct obd_device *)data;
2668 struct obd_device_target *target = &obd->u.obt;
2670 LASSERT(obd != NULL);
2671 LASSERT(target->obt_magic == OBT_MAGIC);
2673 return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
2675 EXPORT_SYMBOL(lprocfs_target_rd_instance);