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 CFS_DECLARE_RWSEM(_lprocfs_lock);
64 EXPORT_SYMBOL(_lprocfs_lock);
66 int lprocfs_seq_release(struct inode *inode, struct file *file)
69 return seq_release(inode, file);
71 EXPORT_SYMBOL(lprocfs_seq_release);
73 static struct proc_dir_entry *__lprocfs_srch(struct proc_dir_entry *head,
76 struct proc_dir_entry *temp;
82 while (temp != NULL) {
83 if (strcmp(temp->name, name) == 0) {
92 struct proc_dir_entry *lprocfs_srch(struct proc_dir_entry *head,
95 struct proc_dir_entry *temp;
98 temp = __lprocfs_srch(head, name);
103 /* lprocfs API calls */
105 /* Function that emulates snprintf but also has the side effect of advancing
106 the page pointer for the next write into the buffer, incrementing the total
107 length written to the buffer, and decrementing the size left in the
109 static int lprocfs_obd_snprintf(char **page, int end, int *len,
110 const char *format, ...)
118 va_start(list, format);
119 n = vsnprintf(*page, end - *len, format, list);
122 *page += n; *len += n;
126 cfs_proc_dir_entry_t *lprocfs_add_simple(struct proc_dir_entry *root,
128 read_proc_t *read_proc,
129 write_proc_t *write_proc,
131 struct file_operations *fops)
133 cfs_proc_dir_entry_t *proc;
136 if (root == NULL || name == NULL)
137 return ERR_PTR(-EINVAL);
144 LPROCFS_WRITE_ENTRY();
145 proc = create_proc_entry(name, mode, root);
147 CERROR("LprocFS: No memory to create /proc entry %s", name);
148 LPROCFS_WRITE_EXIT();
149 return ERR_PTR(-ENOMEM);
151 proc->read_proc = read_proc;
152 proc->write_proc = write_proc;
155 proc->proc_fops = fops;
156 LPROCFS_WRITE_EXIT();
160 struct proc_dir_entry *lprocfs_add_symlink(const char *name,
161 struct proc_dir_entry *parent, const char *format, ...)
163 struct proc_dir_entry *entry;
167 if (parent == NULL || format == NULL)
170 OBD_ALLOC_WAIT(dest, MAX_STRING_SIZE + 1);
174 va_start(ap, format);
175 vsnprintf(dest, MAX_STRING_SIZE, format, ap);
178 entry = proc_symlink(name, parent, dest);
180 CERROR("LprocFS: Could not create symbolic link from %s to %s",
183 OBD_FREE(dest, MAX_STRING_SIZE + 1);
187 static ssize_t lprocfs_fops_read(struct file *f, char __user *buf,
188 size_t size, loff_t *ppos)
190 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
191 char *page, *start = NULL;
192 int rc = 0, eof = 1, count;
194 if (*ppos >= CFS_PAGE_SIZE)
197 page = (char *)__get_free_page(GFP_KERNEL);
201 if (LPROCFS_ENTRY_AND_CHECK(dp)) {
206 OBD_FAIL_TIMEOUT(OBD_FAIL_LPROC_REMOVE, 10);
208 rc = dp->read_proc(page, &start, *ppos, CFS_PAGE_SIZE,
214 /* for lustre proc read, the read count must be less than PAGE_SIZE */
223 start = page + *ppos;
224 } else if (start < page) {
228 count = (rc < size) ? rc : size;
229 if (cfs_copy_to_user(buf, start, count)) {
236 free_page((unsigned long)page);
240 static ssize_t lprocfs_fops_write(struct file *f, const char __user *buf,
241 size_t size, loff_t *ppos)
243 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
246 if (LPROCFS_ENTRY_AND_CHECK(dp))
249 rc = dp->write_proc(f, buf, size, dp->data);
254 static struct file_operations lprocfs_generic_fops = {
255 .owner = THIS_MODULE,
256 .read = lprocfs_fops_read,
257 .write = lprocfs_fops_write,
260 int lprocfs_evict_client_open(struct inode *inode, struct file *f)
262 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
263 struct obd_device *obd = dp->data;
265 cfs_atomic_inc(&obd->obd_evict_inprogress);
270 int lprocfs_evict_client_release(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_dec(&obd->obd_evict_inprogress);
276 cfs_waitq_signal(&obd->obd_evict_inprogress_waitq);
281 struct file_operations lprocfs_evict_client_fops = {
282 .owner = THIS_MODULE,
283 .read = lprocfs_fops_read,
284 .write = lprocfs_fops_write,
285 .open = lprocfs_evict_client_open,
286 .release = lprocfs_evict_client_release,
288 EXPORT_SYMBOL(lprocfs_evict_client_fops);
293 * \param root [in] The parent proc entry on which new entry will be added.
294 * \param list [in] Array of proc entries to be added.
295 * \param data [in] The argument to be passed when entries read/write routines
296 * are called through /proc file.
298 * \retval 0 on success
301 int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list,
306 if (root == NULL || list == NULL)
309 LPROCFS_WRITE_ENTRY();
310 while (list->name != NULL) {
311 struct proc_dir_entry *cur_root, *proc;
312 char *pathcopy, *cur, *next, pathbuf[64];
313 int pathsize = strlen(list->name) + 1;
318 /* need copy of path for strsep */
319 if (strlen(list->name) > sizeof(pathbuf) - 1) {
320 OBD_ALLOC(pathcopy, pathsize);
321 if (pathcopy == NULL)
322 GOTO(out, rc = -ENOMEM);
328 strcpy(pathcopy, list->name);
330 while (cur_root != NULL && (cur = strsep(&next, "/"))) {
331 if (*cur =='\0') /* skip double/trailing "/" */
334 proc = __lprocfs_srch(cur_root, cur);
335 CDEBUG(D_OTHER, "cur_root=%s, cur=%s, next=%s, (%s)\n",
336 cur_root->name, cur, next,
337 (proc ? "exists" : "new"));
339 cur_root = (proc ? proc :
340 proc_mkdir(cur, cur_root));
341 } else if (proc == NULL) {
343 if (list->proc_mode != 0000) {
344 mode = list->proc_mode;
348 if (list->write_fptr)
351 proc = create_proc_entry(cur, mode, cur_root);
355 if (pathcopy != pathbuf)
356 OBD_FREE(pathcopy, pathsize);
358 if (cur_root == NULL || proc == NULL) {
359 CERROR("LprocFS: No memory to create /proc entry %s",
361 GOTO(out, rc = -ENOMEM);
365 proc->proc_fops = list->fops;
367 proc->proc_fops = &lprocfs_generic_fops;
368 proc->read_proc = list->read_fptr;
369 proc->write_proc = list->write_fptr;
370 proc->data = (list->data ? list->data : data);
374 LPROCFS_WRITE_EXIT();
378 void lprocfs_remove(struct proc_dir_entry **rooth)
380 struct proc_dir_entry *root = *rooth;
381 struct proc_dir_entry *temp = root;
382 struct proc_dir_entry *rm_entry;
383 struct proc_dir_entry *parent;
389 parent = root->parent;
390 LASSERT(parent != NULL);
391 LPROCFS_WRITE_ENTRY(); /* search vs remove race */
394 while (temp->subdir != NULL)
400 /* Memory corruption once caused this to fail, and
401 without this LASSERT we would loop here forever. */
402 LASSERTF(strlen(rm_entry->name) == rm_entry->namelen,
403 "0x%p %s/%s len %d\n", rm_entry, temp->name,
404 rm_entry->name, (int)strlen(rm_entry->name));
406 #ifdef HAVE_PROCFS_USERS
407 /* if procfs uses user count to synchronize deletion of
408 * proc entry, there is no protection for rm_entry->data,
409 * then lprocfs_fops_read and lprocfs_fops_write maybe
410 * call proc_dir_entry->read_proc (or write_proc) with
411 * proc_dir_entry->data == NULL, then cause kernel Oops.
412 * see bug19706 for detailed information */
414 /* procfs won't free rm_entry->data if it isn't a LINK,
415 * and Lustre won't use rm_entry->data if it is a LINK */
416 if (S_ISLNK(rm_entry->mode))
417 rm_entry->data = NULL;
419 /* Now, the rm_entry->deleted flags is protected
420 * by _lprocfs_lock. */
421 rm_entry->data = NULL;
423 remove_proc_entry(rm_entry->name, temp);
427 LPROCFS_WRITE_EXIT();
430 void lprocfs_remove_proc_entry(const char *name, struct proc_dir_entry *parent)
432 LASSERT(parent != NULL);
433 remove_proc_entry(name, parent);
436 struct proc_dir_entry *lprocfs_register(const char *name,
437 struct proc_dir_entry *parent,
438 struct lprocfs_vars *list, void *data)
440 struct proc_dir_entry *newchild;
442 newchild = lprocfs_srch(parent, name);
443 if (newchild != NULL) {
444 CERROR(" Lproc: Attempting to register %s more than once \n",
446 return ERR_PTR(-EALREADY);
449 newchild = proc_mkdir(name, parent);
450 if (newchild != NULL && list != NULL) {
451 int rc = lprocfs_add_vars(newchild, list, data);
453 lprocfs_remove(&newchild);
460 /* Generic callbacks */
461 int lprocfs_rd_uint(char *page, char **start, off_t off,
462 int count, int *eof, void *data)
464 unsigned int *temp = data;
465 return snprintf(page, count, "%u\n", *temp);
468 int lprocfs_wr_uint(struct file *file, const char *buffer,
469 unsigned long count, void *data)
472 char dummy[MAX_STRING_SIZE + 1], *end;
475 dummy[MAX_STRING_SIZE] = '\0';
476 if (cfs_copy_from_user(dummy, buffer, MAX_STRING_SIZE))
479 tmp = simple_strtoul(dummy, &end, 0);
483 *p = (unsigned int)tmp;
487 int lprocfs_rd_u64(char *page, char **start, off_t off,
488 int count, int *eof, void *data)
490 LASSERT(data != NULL);
492 return snprintf(page, count, LPU64"\n", *(__u64 *)data);
495 int lprocfs_rd_atomic(char *page, char **start, off_t off,
496 int count, int *eof, void *data)
498 cfs_atomic_t *atom = data;
499 LASSERT(atom != NULL);
501 return snprintf(page, count, "%d\n", cfs_atomic_read(atom));
504 int lprocfs_wr_atomic(struct file *file, const char *buffer,
505 unsigned long count, void *data)
507 cfs_atomic_t *atm = data;
511 rc = lprocfs_write_helper(buffer, count, &val);
518 cfs_atomic_set(atm, val);
522 int lprocfs_rd_uuid(char *page, char **start, off_t off, int count,
523 int *eof, void *data)
525 struct obd_device *obd = data;
527 LASSERT(obd != NULL);
529 return snprintf(page, count, "%s\n", obd->obd_uuid.uuid);
532 int lprocfs_rd_name(char *page, char **start, off_t off, int count,
533 int *eof, void *data)
535 struct obd_device *dev = data;
537 LASSERT(dev != NULL);
538 LASSERT(dev->obd_name != NULL);
540 return snprintf(page, count, "%s\n", dev->obd_name);
543 int lprocfs_rd_fstype(char *page, char **start, off_t off, int count, int *eof,
546 struct obd_device *obd = data;
548 LASSERT(obd != NULL);
549 LASSERT(obd->obd_fsops != NULL);
550 LASSERT(obd->obd_fsops->fs_type != NULL);
551 return snprintf(page, count, "%s\n", obd->obd_fsops->fs_type);
554 int lprocfs_rd_blksize(char *page, char **start, off_t off, int count,
555 int *eof, void *data)
557 struct obd_device *obd = data;
558 struct obd_statfs osfs;
559 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
560 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
564 rc = snprintf(page, count, "%u\n", osfs.os_bsize);
569 int lprocfs_osd_rd_blksize(char *page, char **start, off_t off,
570 int count, int *eof, void *data)
572 struct dt_device *dt = data;
573 struct obd_statfs osfs;
574 int rc = dt_statfs(NULL, dt, &osfs);
577 rc = snprintf(page, count, "%d\n",
578 (unsigned) osfs.os_bsize);
583 int lprocfs_rd_kbytestotal(char *page, char **start, off_t off, int count,
584 int *eof, void *data)
586 struct obd_device *obd = data;
587 struct obd_statfs osfs;
588 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
589 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
592 __u32 blk_size = osfs.os_bsize >> 10;
593 __u64 result = osfs.os_blocks;
595 while (blk_size >>= 1)
599 rc = snprintf(page, count, LPU64"\n", result);
604 int lprocfs_osd_rd_kbytestotal(char *page, char **start, off_t off,
605 int count, int *eof, void *data)
607 struct dt_device *dt = data;
608 struct obd_statfs osfs;
609 int rc = dt_statfs(NULL, dt, &osfs);
611 __u32 blk_size = osfs.os_bsize >> 10;
612 __u64 result = osfs.os_blocks;
614 while (blk_size >>= 1)
618 rc = snprintf(page, count, LPU64"\n", result);
623 int lprocfs_rd_kbytesfree(char *page, char **start, off_t off, int count,
624 int *eof, void *data)
626 struct obd_device *obd = data;
627 struct obd_statfs osfs;
628 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
629 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
632 __u32 blk_size = osfs.os_bsize >> 10;
633 __u64 result = osfs.os_bfree;
635 while (blk_size >>= 1)
639 rc = snprintf(page, count, LPU64"\n", result);
644 int lprocfs_osd_rd_kbytesfree(char *page, char **start, off_t off,
645 int count, int *eof, void *data)
647 struct dt_device *dt = data;
648 struct obd_statfs osfs;
649 int rc = dt_statfs(NULL, dt, &osfs);
651 __u32 blk_size = osfs.os_bsize >> 10;
652 __u64 result = osfs.os_bfree;
654 while (blk_size >>= 1)
658 rc = snprintf(page, count, LPU64"\n", result);
663 int lprocfs_rd_kbytesavail(char *page, char **start, off_t off, int count,
664 int *eof, void *data)
666 struct obd_device *obd = data;
667 struct obd_statfs osfs;
668 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
669 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
672 __u32 blk_size = osfs.os_bsize >> 10;
673 __u64 result = osfs.os_bavail;
675 while (blk_size >>= 1)
679 rc = snprintf(page, count, LPU64"\n", result);
684 int lprocfs_osd_rd_kbytesavail(char *page, char **start, off_t off,
685 int count, int *eof, void *data)
687 struct dt_device *dt = data;
688 struct obd_statfs osfs;
689 int rc = dt_statfs(NULL, dt, &osfs);
691 __u32 blk_size = osfs.os_bsize >> 10;
692 __u64 result = osfs.os_bavail;
694 while (blk_size >>= 1)
698 rc = snprintf(page, count, LPU64"\n", result);
703 int lprocfs_rd_filestotal(char *page, char **start, off_t off, int count,
704 int *eof, void *data)
706 struct obd_device *obd = data;
707 struct obd_statfs osfs;
708 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
709 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
713 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
719 int lprocfs_osd_rd_filestotal(char *page, char **start, off_t off,
720 int count, int *eof, void *data)
722 struct dt_device *dt = data;
723 struct obd_statfs osfs;
724 int rc = dt_statfs(NULL, dt, &osfs);
727 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
733 int lprocfs_rd_filesfree(char *page, char **start, off_t off, int count,
734 int *eof, void *data)
736 struct obd_device *obd = data;
737 struct obd_statfs osfs;
738 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
739 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
743 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
748 int lprocfs_osd_rd_filesfree(char *page, char **start, off_t off,
749 int count, int *eof, void *data)
751 struct dt_device *dt = data;
752 struct obd_statfs osfs;
753 int rc = dt_statfs(NULL, dt, &osfs);
756 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
761 int lprocfs_rd_server_uuid(char *page, char **start, off_t off, int count,
762 int *eof, void *data)
764 struct obd_device *obd = data;
765 struct obd_import *imp;
766 char *imp_state_name = NULL;
769 LASSERT(obd != NULL);
770 LPROCFS_CLIMP_CHECK(obd);
771 imp = obd->u.cli.cl_import;
772 imp_state_name = ptlrpc_import_state_name(imp->imp_state);
774 rc = snprintf(page, count, "%s\t%s%s\n",
775 obd2cli_tgt(obd), imp_state_name,
776 imp->imp_deactive ? "\tDEACTIVATED" : "");
778 LPROCFS_CLIMP_EXIT(obd);
782 int lprocfs_rd_conn_uuid(char *page, char **start, off_t off, int count,
783 int *eof, void *data)
785 struct obd_device *obd = data;
786 struct ptlrpc_connection *conn;
789 LASSERT(obd != NULL);
791 LPROCFS_CLIMP_CHECK(obd);
792 conn = obd->u.cli.cl_import->imp_connection;
794 if (conn && obd->u.cli.cl_import) {
795 rc = snprintf(page, count, "%s\n",
796 conn->c_remote_uuid.uuid);
798 rc = snprintf(page, count, "%s\n", "<none>");
801 LPROCFS_CLIMP_EXIT(obd);
805 /** add up per-cpu counters */
806 void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
807 struct lprocfs_counter *cnt)
809 unsigned int num_entry;
810 struct lprocfs_counter t;
811 struct lprocfs_counter *percpu_cntr;
814 unsigned long flags = 0;
816 memset(cnt, 0, sizeof(*cnt));
819 /* set count to 1 to avoid divide-by-zero errs in callers */
824 cnt->lc_min = LC_MIN_INIT;
826 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
828 for (i = 0; i < num_entry; i++) {
829 if (stats->ls_percpu[i] == NULL)
831 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[idx];
834 centry = cfs_atomic_read(&percpu_cntr-> \
836 t.lc_count = percpu_cntr->lc_count;
837 t.lc_sum = percpu_cntr->lc_sum;
838 t.lc_min = percpu_cntr->lc_min;
839 t.lc_max = percpu_cntr->lc_max;
840 t.lc_sumsquare = percpu_cntr->lc_sumsquare;
841 } while (centry != cfs_atomic_read(&percpu_cntr->lc_cntl. \
843 centry != cfs_atomic_read(&percpu_cntr->lc_cntl. \
845 cnt->lc_count += t.lc_count;
846 cnt->lc_sum += t.lc_sum;
847 if (t.lc_min < cnt->lc_min)
848 cnt->lc_min = t.lc_min;
849 if (t.lc_max > cnt->lc_max)
850 cnt->lc_max = t.lc_max;
851 cnt->lc_sumsquare += t.lc_sumsquare;
854 cnt->lc_units = stats->ls_percpu[0]->lp_cntr[idx].lc_units;
855 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
859 * Append a space separated list of current set flags to str.
861 #define flag2str(flag) \
862 if (imp->imp_##flag && max - len > 0) \
863 len += snprintf(str + len, max - len, "%s" #flag, len ? ", " : "");
864 static int obd_import_flags2str(struct obd_import *imp, char *str, int max)
868 if (imp->imp_obd->obd_no_recov)
869 len += snprintf(str, max - len, "no_recov");
873 flag2str(replayable);
879 static const char *obd_connect_names[] = {
893 "join_file(obsolete)",
897 "remote_client_by_force",
906 "mds_mds_connection",
909 "alt_checksum_algorithm",
928 int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
933 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
935 ret += snprintf(page + ret, count - ret, "%s%s",
936 ret ? sep : "", obd_connect_names[i]);
938 if (flags & ~(mask - 1))
939 ret += snprintf(page + ret, count - ret,
940 "%sunknown flags "LPX64,
941 ret ? sep : "", flags & ~(mask - 1));
944 EXPORT_SYMBOL(obd_connect_flags2str);
946 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
947 int *eof, void *data)
949 struct lprocfs_counter ret;
950 struct obd_device *obd = (struct obd_device *)data;
951 struct obd_import *imp;
952 struct obd_import_conn *conn;
955 LASSERT(obd != NULL);
956 LPROCFS_CLIMP_CHECK(obd);
957 imp = obd->u.cli.cl_import;
960 i = snprintf(page, count,
969 ptlrpc_import_state_name(imp->imp_state),
970 imp->imp_connect_data.ocd_instance);
971 i += obd_connect_flags2str(page + i, count - i,
972 imp->imp_connect_data.ocd_connect_flags,
974 i += snprintf(page + i, count - i,
977 i += obd_import_flags2str(imp, page + i, count - i);
979 i += snprintf(page + i, count - i,
982 " failover_nids: [");
983 cfs_spin_lock(&imp->imp_lock);
985 cfs_list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
986 i += snprintf(page + i, count - i, "%s%s", j ? ", " : "",
987 libcfs_nid2str(conn->oic_conn->c_peer.nid));
990 i += snprintf(page + i, count - i,
992 " current_connection: %s\n"
993 " connection_attempts: %u\n"
995 " in-progress_invalidations: %u\n",
996 imp->imp_connection == NULL ? "<none>" :
997 libcfs_nid2str(imp->imp_connection->c_peer.nid),
1000 cfs_atomic_read(&imp->imp_inval_count));
1001 cfs_spin_unlock(&imp->imp_lock);
1003 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
1004 if (ret.lc_count != 0) {
1005 /* first argument to do_div MUST be __u64 */
1006 __u64 sum = ret.lc_sum;
1007 do_div(sum, ret.lc_count);
1011 i += snprintf(page + i, count - i,
1014 " unregistering: %u\n"
1016 " avg_waittime: "LPU64" %s\n",
1017 cfs_atomic_read(&imp->imp_inflight),
1018 cfs_atomic_read(&imp->imp_unregistering),
1019 cfs_atomic_read(&imp->imp_timeouts),
1020 ret.lc_sum, ret.lc_units);
1023 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
1024 if (imp->imp_at.iat_portal[j] == 0)
1026 k = max_t(unsigned int, k,
1027 at_get(&imp->imp_at.iat_service_estimate[j]));
1029 i += snprintf(page + i, count - i,
1030 " service_estimates:\n"
1031 " services: %u sec\n"
1032 " network: %u sec\n",
1034 at_get(&imp->imp_at.iat_net_latency));
1036 i += snprintf(page + i, count - i,
1038 " last_replay: "LPU64"\n"
1039 " peer_committed: "LPU64"\n"
1040 " last_checked: "LPU64"\n",
1041 imp->imp_last_replay_transno,
1042 imp->imp_peer_committed_transno,
1043 imp->imp_last_transno_checked);
1045 /* avg data rates */
1046 for (rw = 0; rw <= 1; rw++) {
1047 lprocfs_stats_collect(obd->obd_svc_stats,
1048 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
1050 if (ret.lc_sum > 0 && ret.lc_count > 0) {
1051 /* first argument to do_div MUST be __u64 */
1052 __u64 sum = ret.lc_sum;
1053 do_div(sum, ret.lc_count);
1055 i += snprintf(page + i, count - i,
1056 " %s_data_averages:\n"
1057 " bytes_per_rpc: "LPU64"\n",
1058 rw ? "write" : "read",
1061 k = (int)ret.lc_sum;
1062 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
1063 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
1064 if (ret.lc_sum > 0 && ret.lc_count != 0) {
1065 /* first argument to do_div MUST be __u64 */
1066 __u64 sum = ret.lc_sum;
1067 do_div(sum, ret.lc_count);
1069 i += snprintf(page + i, count - i,
1070 " %s_per_rpc: "LPU64"\n",
1071 ret.lc_units, ret.lc_sum);
1072 j = (int)ret.lc_sum;
1074 i += snprintf(page + i, count - i,
1075 " MB_per_sec: %u.%.02u\n",
1076 k / j, (100 * k / j) % 100);
1080 LPROCFS_CLIMP_EXIT(obd);
1084 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
1085 int *eof, void *data)
1087 struct obd_device *obd = (struct obd_device *)data;
1088 struct obd_import *imp;
1091 LASSERT(obd != NULL);
1092 LPROCFS_CLIMP_CHECK(obd);
1093 imp = obd->u.cli.cl_import;
1096 i = snprintf(page, count, "current_state: %s\n",
1097 ptlrpc_import_state_name(imp->imp_state));
1098 i += snprintf(page + i, count - i,
1099 "state_history:\n");
1100 k = imp->imp_state_hist_idx;
1101 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
1102 struct import_state_hist *ish =
1103 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
1104 if (ish->ish_state == 0)
1106 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
1108 ptlrpc_import_state_name(ish->ish_state));
1111 LPROCFS_CLIMP_EXIT(obd);
1115 int lprocfs_at_hist_helper(char *page, int count, int rc,
1116 struct adaptive_timeout *at)
1119 for (i = 0; i < AT_BINS; i++)
1120 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
1121 rc += snprintf(page + rc, count - rc, "\n");
1125 /* See also ptlrpc_lprocfs_rd_timeouts */
1126 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
1127 int *eof, void *data)
1129 struct obd_device *obd = (struct obd_device *)data;
1130 struct obd_import *imp;
1131 unsigned int cur, worst;
1136 LASSERT(obd != NULL);
1137 LPROCFS_CLIMP_CHECK(obd);
1138 imp = obd->u.cli.cl_import;
1141 now = cfs_time_current_sec();
1143 /* Some network health info for kicks */
1144 s2dhms(&ts, now - imp->imp_last_reply_time);
1145 rc += snprintf(page + rc, count - rc,
1146 "%-10s : %ld, "DHMS_FMT" ago\n",
1147 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
1149 cur = at_get(&imp->imp_at.iat_net_latency);
1150 worst = imp->imp_at.iat_net_latency.at_worst_ever;
1151 worstt = imp->imp_at.iat_net_latency.at_worst_time;
1152 s2dhms(&ts, now - worstt);
1153 rc += snprintf(page + rc, count - rc,
1154 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
1155 "network", cur, worst, worstt, DHMS_VARS(&ts));
1156 rc = lprocfs_at_hist_helper(page, count, rc,
1157 &imp->imp_at.iat_net_latency);
1159 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
1160 if (imp->imp_at.iat_portal[i] == 0)
1162 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
1163 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
1164 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
1165 s2dhms(&ts, now - worstt);
1166 rc += snprintf(page + rc, count - rc,
1167 "portal %-2d : cur %3u worst %3u (at %ld, "
1168 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
1169 cur, worst, worstt, DHMS_VARS(&ts));
1170 rc = lprocfs_at_hist_helper(page, count, rc,
1171 &imp->imp_at.iat_service_estimate[i]);
1174 LPROCFS_CLIMP_EXIT(obd);
1178 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1179 int count, int *eof, void *data)
1181 struct obd_device *obd = data;
1185 LPROCFS_CLIMP_CHECK(obd);
1186 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1187 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1188 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1189 ret += snprintf(page + ret, count - ret, "\n");
1190 LPROCFS_CLIMP_EXIT(obd);
1193 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1195 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1196 int *eof, void *data)
1198 struct obd_device *obd = data;
1200 LASSERT(obd != NULL);
1202 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1205 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1206 int *eof, void *data)
1208 struct obd_type *class = (struct obd_type*) data;
1210 LASSERT(class != NULL);
1212 return snprintf(page, count, "%d\n", class->typ_refcnt);
1215 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1219 LASSERT(obd != NULL);
1220 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1221 LASSERT(obd->obd_type->typ_procroot != NULL);
1223 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1224 obd->obd_type->typ_procroot,
1226 if (IS_ERR(obd->obd_proc_entry)) {
1227 rc = PTR_ERR(obd->obd_proc_entry);
1228 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1229 obd->obd_proc_entry = NULL;
1234 int lprocfs_obd_cleanup(struct obd_device *obd)
1238 if (obd->obd_proc_exports_entry) {
1239 /* Should be no exports left */
1240 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1241 lprocfs_remove(&obd->obd_proc_exports_entry);
1242 obd->obd_proc_exports_entry = NULL;
1244 if (obd->obd_proc_entry) {
1245 lprocfs_remove(&obd->obd_proc_entry);
1246 obd->obd_proc_entry = NULL;
1251 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1253 CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
1254 client_stat->nid_proc, client_stat->nid_stats,
1255 client_stat->nid_brw_stats);
1257 LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
1258 "nid %s:count %d\n", libcfs_nid2str(client_stat->nid),
1259 atomic_read(&client_stat->nid_exp_ref_count));
1261 if (client_stat->nid_proc)
1262 lprocfs_remove(&client_stat->nid_proc);
1264 if (client_stat->nid_stats)
1265 lprocfs_free_stats(&client_stat->nid_stats);
1267 if (client_stat->nid_brw_stats)
1268 OBD_FREE_PTR(client_stat->nid_brw_stats);
1270 if (client_stat->nid_ldlm_stats)
1271 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1273 OBD_FREE_PTR(client_stat);
1278 void lprocfs_free_per_client_stats(struct obd_device *obd)
1280 cfs_hash_t *hash = obd->obd_nid_stats_hash;
1281 struct nid_stat *stat;
1284 /* we need extra list - because hash_exit called to early */
1285 /* not need locking because all clients is died */
1286 while (!cfs_list_empty(&obd->obd_nid_stats)) {
1287 stat = cfs_list_entry(obd->obd_nid_stats.next,
1288 struct nid_stat, nid_list);
1289 cfs_list_del_init(&stat->nid_list);
1290 cfs_hash_del(hash, &stat->nid, &stat->nid_hash);
1291 lprocfs_free_client_stats(stat);
1296 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1297 enum lprocfs_stats_flags flags)
1299 struct lprocfs_stats *stats;
1300 unsigned int percpusize;
1301 unsigned int num_entry;
1306 if (lprocfs_no_percpu_stats != 0)
1307 flags |= LPROCFS_STATS_FLAG_NOPERCPU;
1309 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1312 num_entry = cfs_num_possible_cpus() + 1;
1314 /* alloc percpu pointers for all possible cpu slots */
1315 OBD_ALLOC(stats, offsetof(struct lprocfs_stats, ls_percpu[num_entry]));
1319 stats->ls_num = num;
1320 stats->ls_biggest_alloc_num = 1;
1321 if (flags & LPROCFS_STATS_FLAG_NOPERCPU) {
1322 stats->ls_flags = flags;
1323 cfs_spin_lock_init(&stats->ls_lock);
1324 /* Use this lock only if there are no percpu areas */
1326 stats->ls_flags = 0;
1329 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
1331 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1333 /* for no percpu area, the 0th entry is for real use,
1334 * for percpu area, the 0th entry is for intialized entry template */
1335 OBD_ALLOC(stats->ls_percpu[0], percpusize);
1336 if (stats->ls_percpu[0] == NULL) {
1338 offsetof(struct lprocfs_stats, ls_percpu[num_entry]));
1344 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1346 struct lprocfs_stats *stats = *statsh;
1347 unsigned int num_entry;
1348 unsigned int percpusize;
1351 if (stats == NULL || stats->ls_num == 0)
1355 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1358 num_entry = cfs_num_possible_cpus() + 1;
1360 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
1362 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1363 for (i = 0; i < num_entry; i++)
1364 if (stats->ls_percpu[i] != NULL)
1365 OBD_FREE(stats->ls_percpu[i], percpusize);
1366 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1369 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1371 struct lprocfs_counter *percpu_cntr;
1374 unsigned int num_entry;
1375 unsigned int percpusize;
1376 unsigned long flags = 0;
1378 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1380 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
1382 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1384 for (i = 0; i < num_entry; i++) {
1385 if (stats->ls_percpu[i] == NULL)
1387 /* the 1st percpu entry was statically allocated in
1388 * lprocfs_alloc_stats() */
1390 OBD_FREE(stats->ls_percpu[i], percpusize);
1391 stats->ls_percpu[i] = NULL;
1394 for (j = 0; j < stats->ls_num; j++) {
1395 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
1396 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_entry);
1397 percpu_cntr->lc_count = 0;
1398 percpu_cntr->lc_sum = 0;
1399 percpu_cntr->lc_min = LC_MIN_INIT;
1400 percpu_cntr->lc_max = 0;
1401 percpu_cntr->lc_sumsquare = 0;
1402 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_exit);
1406 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1409 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1410 size_t len, loff_t *off)
1412 struct seq_file *seq = file->private_data;
1413 struct lprocfs_stats *stats = seq->private;
1415 lprocfs_clear_stats(stats);
1420 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1422 struct lprocfs_stats *stats = p->private;
1423 /* return 1st cpu location */
1424 return (*pos >= stats->ls_num) ? NULL :
1425 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1428 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1432 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1434 struct lprocfs_stats *stats = p->private;
1436 return (*pos >= stats->ls_num) ? NULL :
1437 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1440 /* seq file export of one lprocfs counter */
1441 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1443 struct lprocfs_stats *stats = p->private;
1444 struct lprocfs_counter *cntr = v;
1445 struct lprocfs_counter ret;
1448 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
1450 cfs_gettimeofday(&now);
1451 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1452 "snapshot_time", now.tv_sec, now.tv_usec);
1456 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
1458 lprocfs_stats_collect(stats, idx, &ret);
1460 if (ret.lc_count == 0)
1463 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", cntr->lc_name,
1464 ret.lc_count, cntr->lc_units);
1469 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
1470 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1471 ret.lc_min, ret.lc_max, ret.lc_sum);
1474 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
1475 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1479 rc = seq_printf(p, "\n");
1481 return (rc < 0) ? rc : 0;
1484 struct seq_operations lprocfs_stats_seq_sops = {
1485 start: lprocfs_stats_seq_start,
1486 stop: lprocfs_stats_seq_stop,
1487 next: lprocfs_stats_seq_next,
1488 show: lprocfs_stats_seq_show,
1491 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1493 struct proc_dir_entry *dp = PDE(inode);
1494 struct seq_file *seq;
1497 if (LPROCFS_ENTRY_AND_CHECK(dp))
1500 rc = seq_open(file, &lprocfs_stats_seq_sops);
1505 seq = file->private_data;
1506 seq->private = dp->data;
1510 struct file_operations lprocfs_stats_seq_fops = {
1511 .owner = THIS_MODULE,
1512 .open = lprocfs_stats_seq_open,
1514 .write = lprocfs_stats_seq_write,
1515 .llseek = seq_lseek,
1516 .release = lprocfs_seq_release,
1519 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1520 struct lprocfs_stats *stats)
1522 struct proc_dir_entry *entry;
1523 LASSERT(root != NULL);
1525 LPROCFS_WRITE_ENTRY();
1526 entry = create_proc_entry(name, 0644, root);
1528 entry->proc_fops = &lprocfs_stats_seq_fops;
1529 entry->data = stats;
1532 LPROCFS_WRITE_EXIT();
1540 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1541 unsigned conf, const char *name, const char *units)
1543 struct lprocfs_counter *c = &(stats->ls_percpu[0]->lp_cntr[index]);
1544 unsigned long flags = 0;
1546 LASSERT(stats != NULL);
1547 LASSERT(stats->ls_percpu[0] != NULL);
1549 lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1550 c->lc_config = conf;
1553 c->lc_min = LC_MIN_INIT;
1556 c->lc_units = units;
1557 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1559 EXPORT_SYMBOL(lprocfs_counter_init);
1561 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1563 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1564 LASSERT(coffset < stats->ls_num); \
1565 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1568 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1570 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1571 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1572 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1573 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1574 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1575 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1576 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1577 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1578 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1579 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1580 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1581 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1582 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1583 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1584 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1585 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1586 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1587 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1588 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
1589 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1590 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1591 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1592 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1593 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1594 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1595 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1596 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1597 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1598 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1599 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1600 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1601 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1602 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1603 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1604 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1605 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1606 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1607 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1608 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1609 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1610 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1611 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1612 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1613 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1614 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
1615 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1616 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1617 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1618 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1619 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1620 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1621 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1622 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1623 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1624 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1625 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1626 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1627 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1628 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1629 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1630 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1631 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quota_adjust_qunit);
1632 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1633 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1634 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1635 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1636 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1637 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1638 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1641 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1643 struct lprocfs_stats *stats;
1644 unsigned int num_stats;
1647 LASSERT(obd->obd_stats == NULL);
1648 LASSERT(obd->obd_proc_entry != NULL);
1649 LASSERT(obd->obd_cntr_base == 0);
1651 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1652 num_private_stats - 1 /* o_owner */;
1653 stats = lprocfs_alloc_stats(num_stats, 0);
1657 lprocfs_init_ops_stats(num_private_stats, stats);
1659 for (i = num_private_stats; i < num_stats; i++) {
1660 /* If this LBUGs, it is likely that an obd
1661 * operation was added to struct obd_ops in
1662 * <obd.h>, and that the corresponding line item
1663 * LPROCFS_OBD_OP_INIT(.., .., opname)
1664 * is missing from the list above. */
1665 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1666 "Missing obd_stat initializer obd_op "
1667 "operation at offset %d.\n", i - num_private_stats);
1669 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1671 lprocfs_free_stats(&stats);
1673 obd->obd_stats = stats;
1674 obd->obd_cntr_base = num_private_stats;
1679 void lprocfs_free_obd_stats(struct obd_device *obd)
1682 lprocfs_free_stats(&obd->obd_stats);
1685 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1687 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1688 LASSERT(coffset < stats->ls_num); \
1689 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1692 void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats)
1694 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1695 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1696 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
1697 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1698 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1699 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1700 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1701 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1702 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1703 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1704 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1705 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1706 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1707 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1708 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1709 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1710 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1711 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1712 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1713 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1714 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1715 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1716 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1717 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1718 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1719 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1720 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1721 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1722 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1723 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1724 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1725 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1728 int lprocfs_alloc_md_stats(struct obd_device *obd,
1729 unsigned num_private_stats)
1731 struct lprocfs_stats *stats;
1732 unsigned int num_stats;
1735 LASSERT(obd->md_stats == NULL);
1736 LASSERT(obd->obd_proc_entry != NULL);
1737 LASSERT(obd->md_cntr_base == 0);
1739 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1741 stats = lprocfs_alloc_stats(num_stats, 0);
1745 lprocfs_init_mps_stats(num_private_stats, stats);
1747 for (i = num_private_stats; i < num_stats; i++) {
1748 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1749 CERROR("Missing md_stat initializer md_op "
1750 "operation at offset %d. Aborting.\n",
1751 i - num_private_stats);
1755 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1757 lprocfs_free_stats(&stats);
1759 obd->md_stats = stats;
1760 obd->md_cntr_base = num_private_stats;
1765 void lprocfs_free_md_stats(struct obd_device *obd)
1767 struct lprocfs_stats *stats = obd->md_stats;
1769 if (stats != NULL) {
1770 obd->md_stats = NULL;
1771 obd->md_cntr_base = 0;
1772 lprocfs_free_stats(&stats);
1776 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1778 lprocfs_counter_init(ldlm_stats,
1779 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1780 0, "ldlm_enqueue", "reqs");
1781 lprocfs_counter_init(ldlm_stats,
1782 LDLM_CONVERT - LDLM_FIRST_OPC,
1783 0, "ldlm_convert", "reqs");
1784 lprocfs_counter_init(ldlm_stats,
1785 LDLM_CANCEL - LDLM_FIRST_OPC,
1786 0, "ldlm_cancel", "reqs");
1787 lprocfs_counter_init(ldlm_stats,
1788 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1789 0, "ldlm_bl_callback", "reqs");
1790 lprocfs_counter_init(ldlm_stats,
1791 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1792 0, "ldlm_cp_callback", "reqs");
1793 lprocfs_counter_init(ldlm_stats,
1794 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1795 0, "ldlm_gl_callback", "reqs");
1798 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1799 int *eof, void *data)
1801 struct obd_export *exp = data;
1802 LASSERT(exp != NULL);
1804 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1807 struct exp_uuid_cb_data {
1815 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1816 int count, int *eof, int *len)
1818 cb_data->page = page;
1819 cb_data->count = count;
1824 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1825 cfs_hlist_node_t *hnode, void *cb_data)
1828 struct obd_export *exp = cfs_hash_object(hs, hnode);
1829 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1831 if (exp->exp_nid_stats)
1832 *data->len += snprintf((data->page + *data->len),
1833 data->count, "%s\n",
1834 obd_uuid2str(&exp->exp_client_uuid));
1838 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1839 int *eof, void *data)
1841 struct nid_stat *stats = (struct nid_stat *)data;
1842 struct exp_uuid_cb_data cb_data;
1843 struct obd_device *obd = stats->nid_obd;
1848 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1849 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1850 lprocfs_exp_print_uuid, &cb_data);
1851 return (*cb_data.len);
1854 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1855 cfs_hlist_node_t *hnode, void *cb_data)
1858 struct exp_uuid_cb_data *data = cb_data;
1859 struct obd_export *exp = cfs_hash_object(hs, hnode);
1861 if (exp->exp_lock_hash != NULL) {
1863 *data->len += cfs_hash_debug_header(data->page,
1866 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1873 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1874 int *eof, void *data)
1876 struct nid_stat *stats = (struct nid_stat *)data;
1877 struct exp_uuid_cb_data cb_data;
1878 struct obd_device *obd = stats->nid_obd;
1883 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1885 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1886 lprocfs_exp_print_hash, &cb_data);
1887 return (*cb_data.len);
1890 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1891 int count, int *eof, void *data)
1894 return snprintf(page, count, "%s\n",
1895 "Write into this file to clear all nid stats and "
1896 "stale nid entries");
1898 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1900 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1902 struct nid_stat *stat = obj;
1906 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
1907 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 1) {
1908 /* object has only hash references. */
1909 cfs_spin_lock(&stat->nid_obd->obd_nid_lock);
1910 cfs_list_move(&stat->nid_list, data);
1911 cfs_spin_unlock(&stat->nid_obd->obd_nid_lock);
1914 /* we has reference to object - only clear data*/
1915 if (stat->nid_stats)
1916 lprocfs_clear_stats(stat->nid_stats);
1918 if (stat->nid_brw_stats) {
1919 for (i = 0; i < BRW_LAST; i++)
1920 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
1925 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1926 unsigned long count, void *data)
1928 struct obd_device *obd = (struct obd_device *)data;
1929 struct nid_stat *client_stat;
1930 CFS_LIST_HEAD(free_list);
1932 cfs_hash_cond_del(obd->obd_nid_stats_hash,
1933 lprocfs_nid_stats_clear_write_cb, &free_list);
1935 while (!cfs_list_empty(&free_list)) {
1936 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
1938 cfs_list_del_init(&client_stat->nid_list);
1939 lprocfs_free_client_stats(client_stat);
1944 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1946 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1948 struct nid_stat *new_stat, *old_stat;
1949 struct obd_device *obd = NULL;
1950 cfs_proc_dir_entry_t *entry;
1951 char *buffer = NULL;
1957 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1958 !exp->exp_obd->obd_nid_stats_hash)
1961 /* not test against zero because eric say:
1962 * You may only test nid against another nid, or LNET_NID_ANY.
1963 * Anything else is nonsense.*/
1964 if (!nid || *nid == LNET_NID_ANY)
1969 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
1971 OBD_ALLOC_PTR(new_stat);
1972 if (new_stat == NULL)
1975 new_stat->nid = *nid;
1976 new_stat->nid_obd = exp->exp_obd;
1977 /* we need set default refcount to 1 to balance obd_disconnect */
1978 cfs_atomic_set(&new_stat->nid_exp_ref_count, 1);
1980 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
1981 nid, &new_stat->nid_hash);
1982 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
1983 old_stat, libcfs_nid2str(*nid),
1984 cfs_atomic_read(&new_stat->nid_exp_ref_count));
1986 /* We need to release old stats because lprocfs_exp_cleanup() hasn't
1987 * been and will never be called. */
1988 if (exp->exp_nid_stats) {
1989 nidstat_putref(exp->exp_nid_stats);
1990 exp->exp_nid_stats = NULL;
1993 /* Return -EALREADY here so that we know that the /proc
1994 * entry already has been created */
1995 if (old_stat != new_stat) {
1996 exp->exp_nid_stats = old_stat;
1997 GOTO(destroy_new, rc = -EALREADY);
1999 /* not found - create */
2000 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
2002 GOTO(destroy_new, rc = -ENOMEM);
2004 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
2005 new_stat->nid_proc = lprocfs_register(buffer,
2006 obd->obd_proc_exports_entry,
2008 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
2010 if (new_stat->nid_proc == NULL) {
2011 CERROR("Error making export directory for nid %s\n",
2012 libcfs_nid2str(*nid));
2013 GOTO(destroy_new_ns, rc = -ENOMEM);
2016 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
2017 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
2018 if (IS_ERR(entry)) {
2019 CWARN("Error adding the NID stats file\n");
2020 rc = PTR_ERR(entry);
2021 GOTO(destroy_new_ns, rc);
2024 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
2025 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
2026 if (IS_ERR(entry)) {
2027 CWARN("Error adding the hash file\n");
2028 rc = PTR_ERR(entry);
2029 GOTO(destroy_new_ns, rc);
2032 exp->exp_nid_stats = new_stat;
2034 /* protect competitive add to list, not need locking on destroy */
2035 cfs_spin_lock(&obd->obd_nid_lock);
2036 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
2037 cfs_spin_unlock(&obd->obd_nid_lock);
2042 if (new_stat->nid_proc != NULL)
2043 lprocfs_remove(&new_stat->nid_proc);
2044 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
2047 nidstat_putref(new_stat);
2048 OBD_FREE_PTR(new_stat);
2052 int lprocfs_exp_cleanup(struct obd_export *exp)
2054 struct nid_stat *stat = exp->exp_nid_stats;
2056 if(!stat || !exp->exp_obd)
2059 nidstat_putref(exp->exp_nid_stats);
2060 exp->exp_nid_stats = NULL;
2065 int lprocfs_write_helper(const char *buffer, unsigned long count,
2068 return lprocfs_write_frac_helper(buffer, count, val, 1);
2071 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
2074 char kernbuf[20], *end, *pbuf;
2076 if (count > (sizeof(kernbuf) - 1))
2079 if (cfs_copy_from_user(kernbuf, buffer, count))
2082 kernbuf[count] = '\0';
2089 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2093 if (end != NULL && *end == '.') {
2094 int temp_val, pow = 1;
2098 if (strlen(pbuf) > 5)
2099 pbuf[5] = '\0'; /*only allow 5bits fractional*/
2101 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2104 for (i = 0; i < (end - pbuf); i++)
2107 *val += temp_val / pow;
2113 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
2116 long decimal_val, frac_val;
2122 decimal_val = val / mult;
2123 prtn = snprintf(buffer, count, "%ld", decimal_val);
2124 frac_val = val % mult;
2126 if (prtn < (count - 4) && frac_val > 0) {
2128 int i, temp_mult = 1, frac_bits = 0;
2130 temp_frac = frac_val * 10;
2131 buffer[prtn++] = '.';
2132 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
2133 /* only reserved 2 bits fraction */
2134 buffer[prtn++] ='0';
2139 * Need to think these cases :
2140 * 1. #echo x.00 > /proc/xxx output result : x
2141 * 2. #echo x.0x > /proc/xxx output result : x.0x
2142 * 3. #echo x.x0 > /proc/xxx output result : x.x
2143 * 4. #echo x.xx > /proc/xxx output result : x.xx
2144 * Only reserved 2 bits fraction.
2146 for (i = 0; i < (5 - prtn); i++)
2149 frac_bits = min((int)count - prtn, 3 - frac_bits);
2150 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
2151 frac_val * temp_mult / mult);
2154 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
2156 if (buffer[prtn] == '.') {
2163 buffer[prtn++] ='\n';
2167 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
2169 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
2172 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
2173 __u64 *val, int mult)
2175 char kernbuf[22], *end, *pbuf;
2176 __u64 whole, frac = 0, units;
2177 unsigned frac_d = 1;
2179 if (count > (sizeof(kernbuf) - 1))
2182 if (cfs_copy_from_user(kernbuf, buffer, count))
2185 kernbuf[count] = '\0';
2192 whole = simple_strtoull(pbuf, &end, 10);
2196 if (end != NULL && *end == '.') {
2200 /* need to limit frac_d to a __u32 */
2201 if (strlen(pbuf) > 10)
2204 frac = simple_strtoull(pbuf, &end, 10);
2205 /* count decimal places */
2206 for (i = 0; i < (end - pbuf); i++)
2223 /* Specified units override the multiplier */
2225 mult = mult < 0 ? -units : units;
2228 do_div(frac, frac_d);
2229 *val = whole * mult + frac;
2233 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent, char *name, mode_t mode,
2234 struct file_operations *seq_fops, void *data)
2236 struct proc_dir_entry *entry;
2239 LPROCFS_WRITE_ENTRY();
2240 entry = create_proc_entry(name, mode, parent);
2242 entry->proc_fops = seq_fops;
2245 LPROCFS_WRITE_EXIT();
2252 EXPORT_SYMBOL(lprocfs_seq_create);
2254 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
2256 struct file_operations *seq_fops,
2259 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2260 mode, seq_fops, data));
2262 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2264 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2266 if (value >= OBD_HIST_MAX)
2267 value = OBD_HIST_MAX - 1;
2269 cfs_spin_lock(&oh->oh_lock);
2270 oh->oh_buckets[value]++;
2271 cfs_spin_unlock(&oh->oh_lock);
2273 EXPORT_SYMBOL(lprocfs_oh_tally);
2275 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2279 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2282 lprocfs_oh_tally(oh, val);
2284 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2286 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2288 unsigned long ret = 0;
2291 for (i = 0; i < OBD_HIST_MAX; i++)
2292 ret += oh->oh_buckets[i];
2295 EXPORT_SYMBOL(lprocfs_oh_sum);
2297 void lprocfs_oh_clear(struct obd_histogram *oh)
2299 cfs_spin_lock(&oh->oh_lock);
2300 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2301 cfs_spin_unlock(&oh->oh_lock);
2303 EXPORT_SYMBOL(lprocfs_oh_clear);
2305 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2306 int count, int *eof, void *data)
2308 struct obd_device *obd = data;
2314 c += cfs_hash_debug_header(page, count);
2315 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2316 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2317 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2318 #ifdef HAVE_QUOTA_SUPPORT
2319 if (obd->u.obt.obt_qctxt.lqc_lqs_hash)
2320 c += cfs_hash_debug_str(obd->u.obt.obt_qctxt.lqc_lqs_hash,
2321 page + c, count - c);
2326 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2328 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2329 int count, int *eof, void *data)
2331 struct obd_device *obd = data;
2334 LASSERT(obd != NULL);
2335 LASSERT(count >= 0);
2337 /* Set start of user data returned to
2338 page + off since the user may have
2339 requested to read much smaller than
2340 what we need to read */
2341 *start = page + off;
2343 /* We know we are allocated a page here.
2344 Also we know that this function will
2345 not need to write more than a page
2346 so we can truncate at CFS_PAGE_SIZE. */
2347 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2349 /* Initialize the page */
2350 memset(page, 0, size);
2352 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2354 if (obd->obd_max_recoverable_clients == 0) {
2355 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2361 /* sampled unlocked, but really... */
2362 if (obd->obd_recovering == 0) {
2363 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2365 if (lprocfs_obd_snprintf(&page, size, &len,
2366 "recovery_start: %lu\n",
2367 obd->obd_recovery_start) <= 0)
2369 if (lprocfs_obd_snprintf(&page, size, &len,
2370 "recovery_duration: %lu\n",
2371 obd->obd_recovery_end -
2372 obd->obd_recovery_start) <= 0)
2374 /* Number of clients that have completed recovery */
2375 if (lprocfs_obd_snprintf(&page, size, &len,
2376 "completed_clients: %d/%d\n",
2377 obd->obd_max_recoverable_clients -
2378 obd->obd_stale_clients,
2379 obd->obd_max_recoverable_clients) <= 0)
2381 if (lprocfs_obd_snprintf(&page, size, &len,
2382 "replayed_requests: %d\n",
2383 obd->obd_replayed_requests) <= 0)
2385 if (lprocfs_obd_snprintf(&page, size, &len,
2386 "last_transno: "LPD64"\n",
2387 obd->obd_next_recovery_transno - 1)<=0)
2389 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2390 obd->obd_version_recov ? "ON" : "OFF")<=0)
2392 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
2393 obd->obd_no_ir ? "OFF" : "ON") <= 0)
2398 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2400 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2401 obd->obd_recovery_start) <= 0)
2403 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2404 cfs_time_current_sec() >=
2405 obd->obd_recovery_start +
2406 obd->obd_recovery_timeout ? 0 :
2407 obd->obd_recovery_start +
2408 obd->obd_recovery_timeout -
2409 cfs_time_current_sec()) <= 0)
2411 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2412 cfs_atomic_read(&obd->obd_connected_clients),
2413 obd->obd_max_recoverable_clients) <= 0)
2415 /* Number of clients that have completed recovery */
2416 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2417 cfs_atomic_read(&obd->obd_req_replay_clients))
2420 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2421 cfs_atomic_read(&obd->obd_lock_replay_clients))
2424 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2425 cfs_atomic_read(&obd->obd_connected_clients) -
2426 cfs_atomic_read(&obd->obd_lock_replay_clients))
2429 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2430 obd->obd_stale_clients) <= 0)
2432 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2433 obd->obd_replayed_requests) <= 0)
2435 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2436 obd->obd_requests_queued_for_recovery) <= 0)
2439 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2440 obd->obd_next_recovery_transno) <= 0)
2446 return min(count, len - (int)off);
2448 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2450 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
2451 int count, int *eof, void *data)
2453 struct obd_device *obd = (struct obd_device *)data;
2454 LASSERT(obd != NULL);
2456 return snprintf(page, count, "%d\n",
2457 obd->obd_recovery_ir_factor);
2459 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
2461 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
2462 unsigned long count, void *data)
2464 struct obd_device *obd = (struct obd_device *)data;
2466 LASSERT(obd != NULL);
2468 rc = lprocfs_write_helper(buffer, count, &val);
2472 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
2475 obd->obd_recovery_ir_factor = val;
2478 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
2480 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
2481 int count, int *eof, void *data)
2483 struct obd_device *obd = (struct obd_device *)data;
2484 LASSERT(obd != NULL);
2486 return snprintf(page, count, "%d\n",
2487 obd->obd_recovery_timeout);
2489 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
2491 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
2492 unsigned long count, void *data)
2494 struct obd_device *obd = (struct obd_device *)data;
2496 LASSERT(obd != NULL);
2498 rc = lprocfs_write_helper(buffer, count, &val);
2502 obd->obd_recovery_timeout = val;
2505 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
2507 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
2508 int count, int *eof, void *data)
2510 struct obd_device *obd = data;
2511 LASSERT(obd != NULL);
2513 return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
2515 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
2517 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
2518 unsigned long count, void *data)
2520 struct obd_device *obd = data;
2522 LASSERT(obd != NULL);
2524 rc = lprocfs_write_helper(buffer, count, &val);
2528 obd->obd_recovery_time_hard = val;
2531 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
2533 int lprocfs_obd_rd_mntdev(char *page, char **start, off_t off,
2534 int count, int *eof, void *data)
2536 struct obd_device *obd = (struct obd_device *)data;
2538 LASSERT(obd != NULL);
2539 LASSERT(obd->u.obt.obt_vfsmnt->mnt_devname);
2541 return snprintf(page, count, "%s\n",
2542 obd->u.obt.obt_vfsmnt->mnt_devname);
2544 EXPORT_SYMBOL(lprocfs_obd_rd_mntdev);
2546 int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
2547 int count, int *eof, void *data)
2549 struct obd_device *dev = data;
2550 struct client_obd *cli = &dev->u.cli;
2553 client_obd_list_lock(&cli->cl_loi_list_lock);
2554 rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
2555 client_obd_list_unlock(&cli->cl_loi_list_lock);
2558 EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
2560 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
2561 int count, int *eof, void *data)
2563 struct obd_device *obd = (struct obd_device *)data;
2564 struct obd_device_target *target = &obd->u.obt;
2566 LASSERT(obd != NULL);
2567 LASSERT(target->obt_magic == OBT_MAGIC);
2569 return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
2571 EXPORT_SYMBOL(lprocfs_target_rd_instance);
2573 EXPORT_SYMBOL(lprocfs_register);
2574 EXPORT_SYMBOL(lprocfs_srch);
2575 EXPORT_SYMBOL(lprocfs_remove);
2576 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
2577 EXPORT_SYMBOL(lprocfs_add_vars);
2578 EXPORT_SYMBOL(lprocfs_obd_setup);
2579 EXPORT_SYMBOL(lprocfs_obd_cleanup);
2580 EXPORT_SYMBOL(lprocfs_add_simple);
2581 EXPORT_SYMBOL(lprocfs_add_symlink);
2582 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
2583 EXPORT_SYMBOL(lprocfs_alloc_stats);
2584 EXPORT_SYMBOL(lprocfs_free_stats);
2585 EXPORT_SYMBOL(lprocfs_clear_stats);
2586 EXPORT_SYMBOL(lprocfs_register_stats);
2587 EXPORT_SYMBOL(lprocfs_init_ops_stats);
2588 EXPORT_SYMBOL(lprocfs_init_mps_stats);
2589 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
2590 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
2591 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
2592 EXPORT_SYMBOL(lprocfs_free_obd_stats);
2593 EXPORT_SYMBOL(lprocfs_free_md_stats);
2594 EXPORT_SYMBOL(lprocfs_exp_setup);
2595 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2597 EXPORT_SYMBOL(lprocfs_rd_u64);
2598 EXPORT_SYMBOL(lprocfs_rd_atomic);
2599 EXPORT_SYMBOL(lprocfs_wr_atomic);
2600 EXPORT_SYMBOL(lprocfs_rd_uint);
2601 EXPORT_SYMBOL(lprocfs_wr_uint);
2602 EXPORT_SYMBOL(lprocfs_rd_uuid);
2603 EXPORT_SYMBOL(lprocfs_rd_name);
2604 EXPORT_SYMBOL(lprocfs_rd_fstype);
2605 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
2606 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
2607 EXPORT_SYMBOL(lprocfs_rd_num_exports);
2608 EXPORT_SYMBOL(lprocfs_rd_numrefs);
2609 EXPORT_SYMBOL(lprocfs_at_hist_helper);
2610 EXPORT_SYMBOL(lprocfs_rd_import);
2611 EXPORT_SYMBOL(lprocfs_rd_state);
2612 EXPORT_SYMBOL(lprocfs_rd_timeouts);
2613 EXPORT_SYMBOL(lprocfs_rd_blksize);
2614 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
2615 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
2616 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
2617 EXPORT_SYMBOL(lprocfs_rd_filestotal);
2618 EXPORT_SYMBOL(lprocfs_rd_filesfree);
2620 EXPORT_SYMBOL(lprocfs_write_helper);
2621 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2622 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2623 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2624 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2625 EXPORT_SYMBOL(lprocfs_stats_collect);