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 cfs_spin_unlock(&imp->imp_lock);
991 i += snprintf(page + i, count - i,
993 " current_connection: %s\n"
994 " connection_attempts: %u\n"
996 " in-progress_invalidations: %u\n",
997 libcfs_nid2str(imp->imp_connection->c_peer.nid),
1000 cfs_atomic_read(&imp->imp_inval_count));
1002 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
1003 if (ret.lc_count != 0) {
1004 /* first argument to do_div MUST be __u64 */
1005 __u64 sum = ret.lc_sum;
1006 do_div(sum, ret.lc_count);
1010 i += snprintf(page + i, count - i,
1013 " unregistering: %u\n"
1015 " avg_waittime: "LPU64" %s\n",
1016 cfs_atomic_read(&imp->imp_inflight),
1017 cfs_atomic_read(&imp->imp_unregistering),
1018 cfs_atomic_read(&imp->imp_timeouts),
1019 ret.lc_sum, ret.lc_units);
1022 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
1023 if (imp->imp_at.iat_portal[j] == 0)
1025 k = max_t(unsigned int, k,
1026 at_get(&imp->imp_at.iat_service_estimate[j]));
1028 i += snprintf(page + i, count - i,
1029 " service_estimates:\n"
1030 " services: %u sec\n"
1031 " network: %u sec\n",
1033 at_get(&imp->imp_at.iat_net_latency));
1035 i += snprintf(page + i, count - i,
1037 " last_replay: "LPU64"\n"
1038 " peer_committed: "LPU64"\n"
1039 " last_checked: "LPU64"\n",
1040 imp->imp_last_replay_transno,
1041 imp->imp_peer_committed_transno,
1042 imp->imp_last_transno_checked);
1044 /* avg data rates */
1045 for (rw = 0; rw <= 1; rw++) {
1046 lprocfs_stats_collect(obd->obd_svc_stats,
1047 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
1049 if (ret.lc_sum > 0 && ret.lc_count > 0) {
1050 /* first argument to do_div MUST be __u64 */
1051 __u64 sum = ret.lc_sum;
1052 do_div(sum, ret.lc_count);
1054 i += snprintf(page + i, count - i,
1055 " %s_data_averages:\n"
1056 " bytes_per_rpc: "LPU64"\n",
1057 rw ? "write" : "read",
1060 k = (int)ret.lc_sum;
1061 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
1062 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
1063 if (ret.lc_sum > 0 && ret.lc_count != 0) {
1064 /* first argument to do_div MUST be __u64 */
1065 __u64 sum = ret.lc_sum;
1066 do_div(sum, ret.lc_count);
1068 i += snprintf(page + i, count - i,
1069 " %s_per_rpc: "LPU64"\n",
1070 ret.lc_units, ret.lc_sum);
1071 j = (int)ret.lc_sum;
1073 i += snprintf(page + i, count - i,
1074 " MB_per_sec: %u.%.02u\n",
1075 k / j, (100 * k / j) % 100);
1079 LPROCFS_CLIMP_EXIT(obd);
1083 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
1084 int *eof, void *data)
1086 struct obd_device *obd = (struct obd_device *)data;
1087 struct obd_import *imp;
1090 LASSERT(obd != NULL);
1091 LPROCFS_CLIMP_CHECK(obd);
1092 imp = obd->u.cli.cl_import;
1095 i = snprintf(page, count, "current_state: %s\n",
1096 ptlrpc_import_state_name(imp->imp_state));
1097 i += snprintf(page + i, count - i,
1098 "state_history:\n");
1099 k = imp->imp_state_hist_idx;
1100 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
1101 struct import_state_hist *ish =
1102 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
1103 if (ish->ish_state == 0)
1105 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
1107 ptlrpc_import_state_name(ish->ish_state));
1110 LPROCFS_CLIMP_EXIT(obd);
1114 int lprocfs_at_hist_helper(char *page, int count, int rc,
1115 struct adaptive_timeout *at)
1118 for (i = 0; i < AT_BINS; i++)
1119 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
1120 rc += snprintf(page + rc, count - rc, "\n");
1124 /* See also ptlrpc_lprocfs_rd_timeouts */
1125 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
1126 int *eof, void *data)
1128 struct obd_device *obd = (struct obd_device *)data;
1129 struct obd_import *imp;
1130 unsigned int cur, worst;
1135 LASSERT(obd != NULL);
1136 LPROCFS_CLIMP_CHECK(obd);
1137 imp = obd->u.cli.cl_import;
1140 now = cfs_time_current_sec();
1142 /* Some network health info for kicks */
1143 s2dhms(&ts, now - imp->imp_last_reply_time);
1144 rc += snprintf(page + rc, count - rc,
1145 "%-10s : %ld, "DHMS_FMT" ago\n",
1146 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
1148 cur = at_get(&imp->imp_at.iat_net_latency);
1149 worst = imp->imp_at.iat_net_latency.at_worst_ever;
1150 worstt = imp->imp_at.iat_net_latency.at_worst_time;
1151 s2dhms(&ts, now - worstt);
1152 rc += snprintf(page + rc, count - rc,
1153 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
1154 "network", cur, worst, worstt, DHMS_VARS(&ts));
1155 rc = lprocfs_at_hist_helper(page, count, rc,
1156 &imp->imp_at.iat_net_latency);
1158 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
1159 if (imp->imp_at.iat_portal[i] == 0)
1161 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
1162 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
1163 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
1164 s2dhms(&ts, now - worstt);
1165 rc += snprintf(page + rc, count - rc,
1166 "portal %-2d : cur %3u worst %3u (at %ld, "
1167 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
1168 cur, worst, worstt, DHMS_VARS(&ts));
1169 rc = lprocfs_at_hist_helper(page, count, rc,
1170 &imp->imp_at.iat_service_estimate[i]);
1173 LPROCFS_CLIMP_EXIT(obd);
1177 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1178 int count, int *eof, void *data)
1180 struct obd_device *obd = data;
1184 LPROCFS_CLIMP_CHECK(obd);
1185 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1186 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1187 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1188 ret += snprintf(page + ret, count - ret, "\n");
1189 LPROCFS_CLIMP_EXIT(obd);
1192 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1194 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1195 int *eof, void *data)
1197 struct obd_device *obd = data;
1199 LASSERT(obd != NULL);
1201 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1204 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1205 int *eof, void *data)
1207 struct obd_type *class = (struct obd_type*) data;
1209 LASSERT(class != NULL);
1211 return snprintf(page, count, "%d\n", class->typ_refcnt);
1214 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1218 LASSERT(obd != NULL);
1219 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1220 LASSERT(obd->obd_type->typ_procroot != NULL);
1222 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1223 obd->obd_type->typ_procroot,
1225 if (IS_ERR(obd->obd_proc_entry)) {
1226 rc = PTR_ERR(obd->obd_proc_entry);
1227 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1228 obd->obd_proc_entry = NULL;
1233 int lprocfs_obd_cleanup(struct obd_device *obd)
1237 if (obd->obd_proc_exports_entry) {
1238 /* Should be no exports left */
1239 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1240 lprocfs_remove(&obd->obd_proc_exports_entry);
1241 obd->obd_proc_exports_entry = NULL;
1243 if (obd->obd_proc_entry) {
1244 lprocfs_remove(&obd->obd_proc_entry);
1245 obd->obd_proc_entry = NULL;
1250 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1252 CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
1253 client_stat->nid_proc, client_stat->nid_stats,
1254 client_stat->nid_brw_stats);
1256 LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
1257 "nid %s:count %d\n", libcfs_nid2str(client_stat->nid),
1258 atomic_read(&client_stat->nid_exp_ref_count));
1260 if (client_stat->nid_proc)
1261 lprocfs_remove(&client_stat->nid_proc);
1263 if (client_stat->nid_stats)
1264 lprocfs_free_stats(&client_stat->nid_stats);
1266 if (client_stat->nid_brw_stats)
1267 OBD_FREE_PTR(client_stat->nid_brw_stats);
1269 if (client_stat->nid_ldlm_stats)
1270 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1272 OBD_FREE_PTR(client_stat);
1277 void lprocfs_free_per_client_stats(struct obd_device *obd)
1279 cfs_hash_t *hash = obd->obd_nid_stats_hash;
1280 struct nid_stat *stat;
1283 /* we need extra list - because hash_exit called to early */
1284 /* not need locking because all clients is died */
1285 while (!cfs_list_empty(&obd->obd_nid_stats)) {
1286 stat = cfs_list_entry(obd->obd_nid_stats.next,
1287 struct nid_stat, nid_list);
1288 cfs_list_del_init(&stat->nid_list);
1289 cfs_hash_del(hash, &stat->nid, &stat->nid_hash);
1290 lprocfs_free_client_stats(stat);
1295 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1296 enum lprocfs_stats_flags flags)
1298 struct lprocfs_stats *stats;
1299 unsigned int percpusize;
1300 unsigned int num_entry;
1305 if (lprocfs_no_percpu_stats != 0)
1306 flags |= LPROCFS_STATS_FLAG_NOPERCPU;
1308 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1311 num_entry = cfs_num_possible_cpus() + 1;
1313 /* alloc percpu pointers for all possible cpu slots */
1314 OBD_ALLOC(stats, offsetof(struct lprocfs_stats, ls_percpu[num_entry]));
1318 stats->ls_num = num;
1319 stats->ls_biggest_alloc_num = 1;
1320 if (flags & LPROCFS_STATS_FLAG_NOPERCPU) {
1321 stats->ls_flags = flags;
1322 cfs_spin_lock_init(&stats->ls_lock);
1323 /* Use this lock only if there are no percpu areas */
1325 stats->ls_flags = 0;
1328 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
1330 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1332 /* for no percpu area, the 0th entry is for real use,
1333 * for percpu area, the 0th entry is for intialized entry template */
1334 OBD_ALLOC(stats->ls_percpu[0], percpusize);
1335 if (stats->ls_percpu[0] == NULL) {
1337 offsetof(struct lprocfs_stats, ls_percpu[num_entry]));
1343 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1345 struct lprocfs_stats *stats = *statsh;
1346 unsigned int num_entry;
1347 unsigned int percpusize;
1350 if (stats == NULL || stats->ls_num == 0)
1354 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1357 num_entry = cfs_num_possible_cpus() + 1;
1359 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
1361 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1362 for (i = 0; i < num_entry; i++)
1363 if (stats->ls_percpu[i] != NULL)
1364 OBD_FREE(stats->ls_percpu[i], percpusize);
1365 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1368 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1370 struct lprocfs_counter *percpu_cntr;
1373 unsigned int num_entry;
1374 unsigned int percpusize;
1375 unsigned long flags = 0;
1377 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1379 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
1381 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1383 for (i = 0; i < num_entry; i++) {
1384 if (stats->ls_percpu[i] == NULL)
1386 /* the 1st percpu entry was statically allocated in
1387 * lprocfs_alloc_stats() */
1389 OBD_FREE(stats->ls_percpu[i], percpusize);
1390 stats->ls_percpu[i] = NULL;
1393 for (j = 0; j < stats->ls_num; j++) {
1394 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
1395 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_entry);
1396 percpu_cntr->lc_count = 0;
1397 percpu_cntr->lc_sum = 0;
1398 percpu_cntr->lc_min = LC_MIN_INIT;
1399 percpu_cntr->lc_max = 0;
1400 percpu_cntr->lc_sumsquare = 0;
1401 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_exit);
1405 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1408 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1409 size_t len, loff_t *off)
1411 struct seq_file *seq = file->private_data;
1412 struct lprocfs_stats *stats = seq->private;
1414 lprocfs_clear_stats(stats);
1419 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1421 struct lprocfs_stats *stats = p->private;
1422 /* return 1st cpu location */
1423 return (*pos >= stats->ls_num) ? NULL :
1424 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1427 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1431 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1433 struct lprocfs_stats *stats = p->private;
1435 return (*pos >= stats->ls_num) ? NULL :
1436 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1439 /* seq file export of one lprocfs counter */
1440 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1442 struct lprocfs_stats *stats = p->private;
1443 struct lprocfs_counter *cntr = v;
1444 struct lprocfs_counter ret;
1447 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
1449 cfs_gettimeofday(&now);
1450 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1451 "snapshot_time", now.tv_sec, now.tv_usec);
1455 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
1457 lprocfs_stats_collect(stats, idx, &ret);
1459 if (ret.lc_count == 0)
1462 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", cntr->lc_name,
1463 ret.lc_count, cntr->lc_units);
1468 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
1469 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1470 ret.lc_min, ret.lc_max, ret.lc_sum);
1473 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
1474 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1478 rc = seq_printf(p, "\n");
1480 return (rc < 0) ? rc : 0;
1483 struct seq_operations lprocfs_stats_seq_sops = {
1484 start: lprocfs_stats_seq_start,
1485 stop: lprocfs_stats_seq_stop,
1486 next: lprocfs_stats_seq_next,
1487 show: lprocfs_stats_seq_show,
1490 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1492 struct proc_dir_entry *dp = PDE(inode);
1493 struct seq_file *seq;
1496 if (LPROCFS_ENTRY_AND_CHECK(dp))
1499 rc = seq_open(file, &lprocfs_stats_seq_sops);
1504 seq = file->private_data;
1505 seq->private = dp->data;
1509 struct file_operations lprocfs_stats_seq_fops = {
1510 .owner = THIS_MODULE,
1511 .open = lprocfs_stats_seq_open,
1513 .write = lprocfs_stats_seq_write,
1514 .llseek = seq_lseek,
1515 .release = lprocfs_seq_release,
1518 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1519 struct lprocfs_stats *stats)
1521 struct proc_dir_entry *entry;
1522 LASSERT(root != NULL);
1524 LPROCFS_WRITE_ENTRY();
1525 entry = create_proc_entry(name, 0644, root);
1527 entry->proc_fops = &lprocfs_stats_seq_fops;
1528 entry->data = stats;
1531 LPROCFS_WRITE_EXIT();
1539 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1540 unsigned conf, const char *name, const char *units)
1542 struct lprocfs_counter *c = &(stats->ls_percpu[0]->lp_cntr[index]);
1543 unsigned long flags = 0;
1545 LASSERT(stats != NULL);
1546 LASSERT(stats->ls_percpu[0] != NULL);
1548 lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1549 c->lc_config = conf;
1552 c->lc_min = LC_MIN_INIT;
1555 c->lc_units = units;
1556 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1558 EXPORT_SYMBOL(lprocfs_counter_init);
1560 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1562 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1563 LASSERT(coffset < stats->ls_num); \
1564 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1567 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1569 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1570 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1571 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1572 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1573 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1574 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1575 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1576 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1577 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1578 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1579 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1580 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1581 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1582 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1583 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1584 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1585 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1586 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1587 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
1588 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1589 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1590 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1591 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1592 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1593 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1594 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1595 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1596 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1597 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1598 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1599 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1600 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1601 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1602 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1603 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1604 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1605 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1606 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1607 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1608 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1609 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1610 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1611 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1612 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1613 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
1614 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1615 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1616 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1617 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1618 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1619 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1620 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1621 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1622 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1623 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1624 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1625 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1626 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1627 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1628 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1629 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1630 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quota_adjust_qunit);
1631 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1632 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1633 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1634 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1635 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1636 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1637 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1640 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1642 struct lprocfs_stats *stats;
1643 unsigned int num_stats;
1646 LASSERT(obd->obd_stats == NULL);
1647 LASSERT(obd->obd_proc_entry != NULL);
1648 LASSERT(obd->obd_cntr_base == 0);
1650 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1651 num_private_stats - 1 /* o_owner */;
1652 stats = lprocfs_alloc_stats(num_stats, 0);
1656 lprocfs_init_ops_stats(num_private_stats, stats);
1658 for (i = num_private_stats; i < num_stats; i++) {
1659 /* If this LBUGs, it is likely that an obd
1660 * operation was added to struct obd_ops in
1661 * <obd.h>, and that the corresponding line item
1662 * LPROCFS_OBD_OP_INIT(.., .., opname)
1663 * is missing from the list above. */
1664 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1665 "Missing obd_stat initializer obd_op "
1666 "operation at offset %d.\n", i - num_private_stats);
1668 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1670 lprocfs_free_stats(&stats);
1672 obd->obd_stats = stats;
1673 obd->obd_cntr_base = num_private_stats;
1678 void lprocfs_free_obd_stats(struct obd_device *obd)
1681 lprocfs_free_stats(&obd->obd_stats);
1684 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1686 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1687 LASSERT(coffset < stats->ls_num); \
1688 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1691 void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats)
1693 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1694 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1695 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
1696 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1697 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1698 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1699 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1700 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1701 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1702 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1703 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1704 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1705 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1706 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1707 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1708 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1709 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1710 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1711 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1712 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1713 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1714 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1715 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1716 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1717 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1718 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1719 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1720 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1721 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1722 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1723 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1724 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1727 int lprocfs_alloc_md_stats(struct obd_device *obd,
1728 unsigned num_private_stats)
1730 struct lprocfs_stats *stats;
1731 unsigned int num_stats;
1734 LASSERT(obd->md_stats == NULL);
1735 LASSERT(obd->obd_proc_entry != NULL);
1736 LASSERT(obd->md_cntr_base == 0);
1738 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1740 stats = lprocfs_alloc_stats(num_stats, 0);
1744 lprocfs_init_mps_stats(num_private_stats, stats);
1746 for (i = num_private_stats; i < num_stats; i++) {
1747 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1748 CERROR("Missing md_stat initializer md_op "
1749 "operation at offset %d. Aborting.\n",
1750 i - num_private_stats);
1754 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1756 lprocfs_free_stats(&stats);
1758 obd->md_stats = stats;
1759 obd->md_cntr_base = num_private_stats;
1764 void lprocfs_free_md_stats(struct obd_device *obd)
1766 struct lprocfs_stats *stats = obd->md_stats;
1768 if (stats != NULL) {
1769 obd->md_stats = NULL;
1770 obd->md_cntr_base = 0;
1771 lprocfs_free_stats(&stats);
1775 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1777 lprocfs_counter_init(ldlm_stats,
1778 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1779 0, "ldlm_enqueue", "reqs");
1780 lprocfs_counter_init(ldlm_stats,
1781 LDLM_CONVERT - LDLM_FIRST_OPC,
1782 0, "ldlm_convert", "reqs");
1783 lprocfs_counter_init(ldlm_stats,
1784 LDLM_CANCEL - LDLM_FIRST_OPC,
1785 0, "ldlm_cancel", "reqs");
1786 lprocfs_counter_init(ldlm_stats,
1787 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1788 0, "ldlm_bl_callback", "reqs");
1789 lprocfs_counter_init(ldlm_stats,
1790 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1791 0, "ldlm_cp_callback", "reqs");
1792 lprocfs_counter_init(ldlm_stats,
1793 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1794 0, "ldlm_gl_callback", "reqs");
1797 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1798 int *eof, void *data)
1800 struct obd_export *exp = data;
1801 LASSERT(exp != NULL);
1803 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1806 struct exp_uuid_cb_data {
1814 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1815 int count, int *eof, int *len)
1817 cb_data->page = page;
1818 cb_data->count = count;
1823 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1824 cfs_hlist_node_t *hnode, void *cb_data)
1827 struct obd_export *exp = cfs_hash_object(hs, hnode);
1828 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1830 if (exp->exp_nid_stats)
1831 *data->len += snprintf((data->page + *data->len),
1832 data->count, "%s\n",
1833 obd_uuid2str(&exp->exp_client_uuid));
1837 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1838 int *eof, void *data)
1840 struct nid_stat *stats = (struct nid_stat *)data;
1841 struct exp_uuid_cb_data cb_data;
1842 struct obd_device *obd = stats->nid_obd;
1847 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1848 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1849 lprocfs_exp_print_uuid, &cb_data);
1850 return (*cb_data.len);
1853 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1854 cfs_hlist_node_t *hnode, void *cb_data)
1857 struct exp_uuid_cb_data *data = cb_data;
1858 struct obd_export *exp = cfs_hash_object(hs, hnode);
1860 if (exp->exp_lock_hash != NULL) {
1862 *data->len += cfs_hash_debug_header(data->page,
1865 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1872 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1873 int *eof, void *data)
1875 struct nid_stat *stats = (struct nid_stat *)data;
1876 struct exp_uuid_cb_data cb_data;
1877 struct obd_device *obd = stats->nid_obd;
1882 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1884 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1885 lprocfs_exp_print_hash, &cb_data);
1886 return (*cb_data.len);
1889 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1890 int count, int *eof, void *data)
1893 return snprintf(page, count, "%s\n",
1894 "Write into this file to clear all nid stats and "
1895 "stale nid entries");
1897 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1899 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1901 struct nid_stat *stat = obj;
1905 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
1906 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 1) {
1907 /* object has only hash references. */
1908 cfs_spin_lock(&stat->nid_obd->obd_nid_lock);
1909 cfs_list_move(&stat->nid_list, data);
1910 cfs_spin_unlock(&stat->nid_obd->obd_nid_lock);
1913 /* we has reference to object - only clear data*/
1914 if (stat->nid_stats)
1915 lprocfs_clear_stats(stat->nid_stats);
1917 if (stat->nid_brw_stats) {
1918 for (i = 0; i < BRW_LAST; i++)
1919 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
1924 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1925 unsigned long count, void *data)
1927 struct obd_device *obd = (struct obd_device *)data;
1928 struct nid_stat *client_stat;
1929 CFS_LIST_HEAD(free_list);
1931 cfs_hash_cond_del(obd->obd_nid_stats_hash,
1932 lprocfs_nid_stats_clear_write_cb, &free_list);
1934 while (!cfs_list_empty(&free_list)) {
1935 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
1937 cfs_list_del_init(&client_stat->nid_list);
1938 lprocfs_free_client_stats(client_stat);
1943 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1945 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1947 struct nid_stat *new_stat, *old_stat;
1948 struct obd_device *obd = NULL;
1949 cfs_proc_dir_entry_t *entry;
1950 char *buffer = NULL;
1956 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1957 !exp->exp_obd->obd_nid_stats_hash)
1960 /* not test against zero because eric say:
1961 * You may only test nid against another nid, or LNET_NID_ANY.
1962 * Anything else is nonsense.*/
1963 if (!nid || *nid == LNET_NID_ANY)
1968 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
1970 OBD_ALLOC_PTR(new_stat);
1971 if (new_stat == NULL)
1974 new_stat->nid = *nid;
1975 new_stat->nid_obd = exp->exp_obd;
1976 /* we need set default refcount to 1 to balance obd_disconnect */
1977 cfs_atomic_set(&new_stat->nid_exp_ref_count, 1);
1979 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
1980 nid, &new_stat->nid_hash);
1981 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
1982 old_stat, libcfs_nid2str(*nid),
1983 cfs_atomic_read(&new_stat->nid_exp_ref_count));
1985 /* We need to release old stats because lprocfs_exp_cleanup() hasn't
1986 * been and will never be called. */
1987 if (exp->exp_nid_stats) {
1988 nidstat_putref(exp->exp_nid_stats);
1989 exp->exp_nid_stats = NULL;
1992 /* Return -EALREADY here so that we know that the /proc
1993 * entry already has been created */
1994 if (old_stat != new_stat) {
1995 exp->exp_nid_stats = old_stat;
1996 GOTO(destroy_new, rc = -EALREADY);
1998 /* not found - create */
1999 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
2001 GOTO(destroy_new, rc = -ENOMEM);
2003 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
2004 new_stat->nid_proc = lprocfs_register(buffer,
2005 obd->obd_proc_exports_entry,
2007 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
2009 if (new_stat->nid_proc == NULL) {
2010 CERROR("Error making export directory for nid %s\n",
2011 libcfs_nid2str(*nid));
2012 GOTO(destroy_new_ns, rc = -ENOMEM);
2015 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
2016 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
2017 if (IS_ERR(entry)) {
2018 CWARN("Error adding the NID stats file\n");
2019 rc = PTR_ERR(entry);
2020 GOTO(destroy_new_ns, rc);
2023 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
2024 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
2025 if (IS_ERR(entry)) {
2026 CWARN("Error adding the hash file\n");
2027 rc = PTR_ERR(entry);
2028 GOTO(destroy_new_ns, rc);
2031 exp->exp_nid_stats = new_stat;
2033 /* protect competitive add to list, not need locking on destroy */
2034 cfs_spin_lock(&obd->obd_nid_lock);
2035 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
2036 cfs_spin_unlock(&obd->obd_nid_lock);
2041 if (new_stat->nid_proc != NULL)
2042 lprocfs_remove(&new_stat->nid_proc);
2043 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
2046 nidstat_putref(new_stat);
2047 OBD_FREE_PTR(new_stat);
2051 int lprocfs_exp_cleanup(struct obd_export *exp)
2053 struct nid_stat *stat = exp->exp_nid_stats;
2055 if(!stat || !exp->exp_obd)
2058 nidstat_putref(exp->exp_nid_stats);
2059 exp->exp_nid_stats = NULL;
2064 int lprocfs_write_helper(const char *buffer, unsigned long count,
2067 return lprocfs_write_frac_helper(buffer, count, val, 1);
2070 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
2073 char kernbuf[20], *end, *pbuf;
2075 if (count > (sizeof(kernbuf) - 1))
2078 if (cfs_copy_from_user(kernbuf, buffer, count))
2081 kernbuf[count] = '\0';
2088 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2092 if (end != NULL && *end == '.') {
2093 int temp_val, pow = 1;
2097 if (strlen(pbuf) > 5)
2098 pbuf[5] = '\0'; /*only allow 5bits fractional*/
2100 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2103 for (i = 0; i < (end - pbuf); i++)
2106 *val += temp_val / pow;
2112 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
2115 long decimal_val, frac_val;
2121 decimal_val = val / mult;
2122 prtn = snprintf(buffer, count, "%ld", decimal_val);
2123 frac_val = val % mult;
2125 if (prtn < (count - 4) && frac_val > 0) {
2127 int i, temp_mult = 1, frac_bits = 0;
2129 temp_frac = frac_val * 10;
2130 buffer[prtn++] = '.';
2131 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
2132 /* only reserved 2 bits fraction */
2133 buffer[prtn++] ='0';
2138 * Need to think these cases :
2139 * 1. #echo x.00 > /proc/xxx output result : x
2140 * 2. #echo x.0x > /proc/xxx output result : x.0x
2141 * 3. #echo x.x0 > /proc/xxx output result : x.x
2142 * 4. #echo x.xx > /proc/xxx output result : x.xx
2143 * Only reserved 2 bits fraction.
2145 for (i = 0; i < (5 - prtn); i++)
2148 frac_bits = min((int)count - prtn, 3 - frac_bits);
2149 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
2150 frac_val * temp_mult / mult);
2153 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
2155 if (buffer[prtn] == '.') {
2162 buffer[prtn++] ='\n';
2166 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
2168 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
2171 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
2172 __u64 *val, int mult)
2174 char kernbuf[22], *end, *pbuf;
2175 __u64 whole, frac = 0, units;
2176 unsigned frac_d = 1;
2178 if (count > (sizeof(kernbuf) - 1))
2181 if (cfs_copy_from_user(kernbuf, buffer, count))
2184 kernbuf[count] = '\0';
2191 whole = simple_strtoull(pbuf, &end, 10);
2195 if (end != NULL && *end == '.') {
2199 /* need to limit frac_d to a __u32 */
2200 if (strlen(pbuf) > 10)
2203 frac = simple_strtoull(pbuf, &end, 10);
2204 /* count decimal places */
2205 for (i = 0; i < (end - pbuf); i++)
2222 /* Specified units override the multiplier */
2224 mult = mult < 0 ? -units : units;
2227 do_div(frac, frac_d);
2228 *val = whole * mult + frac;
2232 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent, char *name, mode_t mode,
2233 struct file_operations *seq_fops, void *data)
2235 struct proc_dir_entry *entry;
2238 LPROCFS_WRITE_ENTRY();
2239 entry = create_proc_entry(name, mode, parent);
2241 entry->proc_fops = seq_fops;
2244 LPROCFS_WRITE_EXIT();
2251 EXPORT_SYMBOL(lprocfs_seq_create);
2253 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
2255 struct file_operations *seq_fops,
2258 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2259 mode, seq_fops, data));
2261 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2263 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2265 if (value >= OBD_HIST_MAX)
2266 value = OBD_HIST_MAX - 1;
2268 cfs_spin_lock(&oh->oh_lock);
2269 oh->oh_buckets[value]++;
2270 cfs_spin_unlock(&oh->oh_lock);
2272 EXPORT_SYMBOL(lprocfs_oh_tally);
2274 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2278 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2281 lprocfs_oh_tally(oh, val);
2283 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2285 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2287 unsigned long ret = 0;
2290 for (i = 0; i < OBD_HIST_MAX; i++)
2291 ret += oh->oh_buckets[i];
2294 EXPORT_SYMBOL(lprocfs_oh_sum);
2296 void lprocfs_oh_clear(struct obd_histogram *oh)
2298 cfs_spin_lock(&oh->oh_lock);
2299 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2300 cfs_spin_unlock(&oh->oh_lock);
2302 EXPORT_SYMBOL(lprocfs_oh_clear);
2304 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2305 int count, int *eof, void *data)
2307 struct obd_device *obd = data;
2313 c += cfs_hash_debug_header(page, count);
2314 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2315 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2316 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2317 #ifdef HAVE_QUOTA_SUPPORT
2318 if (obd->u.obt.obt_qctxt.lqc_lqs_hash)
2319 c += cfs_hash_debug_str(obd->u.obt.obt_qctxt.lqc_lqs_hash,
2320 page + c, count - c);
2325 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2327 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2328 int count, int *eof, void *data)
2330 struct obd_device *obd = data;
2333 LASSERT(obd != NULL);
2334 LASSERT(count >= 0);
2336 /* Set start of user data returned to
2337 page + off since the user may have
2338 requested to read much smaller than
2339 what we need to read */
2340 *start = page + off;
2342 /* We know we are allocated a page here.
2343 Also we know that this function will
2344 not need to write more than a page
2345 so we can truncate at CFS_PAGE_SIZE. */
2346 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2348 /* Initialize the page */
2349 memset(page, 0, size);
2351 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2353 if (obd->obd_max_recoverable_clients == 0) {
2354 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2360 /* sampled unlocked, but really... */
2361 if (obd->obd_recovering == 0) {
2362 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2364 if (lprocfs_obd_snprintf(&page, size, &len,
2365 "recovery_start: %lu\n",
2366 obd->obd_recovery_start) <= 0)
2368 if (lprocfs_obd_snprintf(&page, size, &len,
2369 "recovery_duration: %lu\n",
2370 obd->obd_recovery_end -
2371 obd->obd_recovery_start) <= 0)
2373 /* Number of clients that have completed recovery */
2374 if (lprocfs_obd_snprintf(&page, size, &len,
2375 "completed_clients: %d/%d\n",
2376 obd->obd_max_recoverable_clients -
2377 obd->obd_stale_clients,
2378 obd->obd_max_recoverable_clients) <= 0)
2380 if (lprocfs_obd_snprintf(&page, size, &len,
2381 "replayed_requests: %d\n",
2382 obd->obd_replayed_requests) <= 0)
2384 if (lprocfs_obd_snprintf(&page, size, &len,
2385 "last_transno: "LPD64"\n",
2386 obd->obd_next_recovery_transno - 1)<=0)
2388 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2389 obd->obd_version_recov ? "ON" : "OFF")<=0)
2391 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
2392 obd->obd_no_ir ? "OFF" : "ON") <= 0)
2397 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2399 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2400 obd->obd_recovery_start) <= 0)
2402 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2403 cfs_time_current_sec() >=
2404 obd->obd_recovery_start +
2405 obd->obd_recovery_timeout ? 0 :
2406 obd->obd_recovery_start +
2407 obd->obd_recovery_timeout -
2408 cfs_time_current_sec()) <= 0)
2410 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2411 cfs_atomic_read(&obd->obd_connected_clients),
2412 obd->obd_max_recoverable_clients) <= 0)
2414 /* Number of clients that have completed recovery */
2415 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2416 cfs_atomic_read(&obd->obd_req_replay_clients))
2419 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2420 cfs_atomic_read(&obd->obd_lock_replay_clients))
2423 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2424 cfs_atomic_read(&obd->obd_connected_clients) -
2425 cfs_atomic_read(&obd->obd_lock_replay_clients))
2428 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2429 obd->obd_stale_clients) <= 0)
2431 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2432 obd->obd_replayed_requests) <= 0)
2434 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2435 obd->obd_requests_queued_for_recovery) <= 0)
2438 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2439 obd->obd_next_recovery_transno) <= 0)
2445 return min(count, len - (int)off);
2447 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2449 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
2450 int count, int *eof, void *data)
2452 struct obd_device *obd = (struct obd_device *)data;
2453 LASSERT(obd != NULL);
2455 return snprintf(page, count, "%d\n",
2456 obd->obd_recovery_ir_factor);
2458 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
2460 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
2461 unsigned long count, void *data)
2463 struct obd_device *obd = (struct obd_device *)data;
2465 LASSERT(obd != NULL);
2467 rc = lprocfs_write_helper(buffer, count, &val);
2471 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
2474 obd->obd_recovery_ir_factor = val;
2477 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
2479 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
2480 int count, int *eof, void *data)
2482 struct obd_device *obd = (struct obd_device *)data;
2483 LASSERT(obd != NULL);
2485 return snprintf(page, count, "%d\n",
2486 obd->obd_recovery_timeout);
2488 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
2490 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
2491 unsigned long count, void *data)
2493 struct obd_device *obd = (struct obd_device *)data;
2495 LASSERT(obd != NULL);
2497 rc = lprocfs_write_helper(buffer, count, &val);
2501 obd->obd_recovery_timeout = val;
2504 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
2506 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
2507 int count, int *eof, void *data)
2509 struct obd_device *obd = data;
2510 LASSERT(obd != NULL);
2512 return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
2514 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
2516 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
2517 unsigned long count, void *data)
2519 struct obd_device *obd = data;
2521 LASSERT(obd != NULL);
2523 rc = lprocfs_write_helper(buffer, count, &val);
2527 obd->obd_recovery_time_hard = val;
2530 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
2532 int lprocfs_obd_rd_mntdev(char *page, char **start, off_t off,
2533 int count, int *eof, void *data)
2535 struct obd_device *obd = (struct obd_device *)data;
2537 LASSERT(obd != NULL);
2538 LASSERT(obd->u.obt.obt_vfsmnt->mnt_devname);
2540 return snprintf(page, count, "%s\n",
2541 obd->u.obt.obt_vfsmnt->mnt_devname);
2543 EXPORT_SYMBOL(lprocfs_obd_rd_mntdev);
2545 int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
2546 int count, int *eof, void *data)
2548 struct obd_device *dev = data;
2549 struct client_obd *cli = &dev->u.cli;
2552 client_obd_list_lock(&cli->cl_loi_list_lock);
2553 rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
2554 client_obd_list_unlock(&cli->cl_loi_list_lock);
2557 EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
2559 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
2560 int count, int *eof, void *data)
2562 struct obd_device *obd = (struct obd_device *)data;
2563 struct obd_device_target *target = &obd->u.obt;
2565 LASSERT(obd != NULL);
2566 LASSERT(target->obt_magic == OBT_MAGIC);
2568 return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
2570 EXPORT_SYMBOL(lprocfs_target_rd_instance);
2572 EXPORT_SYMBOL(lprocfs_register);
2573 EXPORT_SYMBOL(lprocfs_srch);
2574 EXPORT_SYMBOL(lprocfs_remove);
2575 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
2576 EXPORT_SYMBOL(lprocfs_add_vars);
2577 EXPORT_SYMBOL(lprocfs_obd_setup);
2578 EXPORT_SYMBOL(lprocfs_obd_cleanup);
2579 EXPORT_SYMBOL(lprocfs_add_simple);
2580 EXPORT_SYMBOL(lprocfs_add_symlink);
2581 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
2582 EXPORT_SYMBOL(lprocfs_alloc_stats);
2583 EXPORT_SYMBOL(lprocfs_free_stats);
2584 EXPORT_SYMBOL(lprocfs_clear_stats);
2585 EXPORT_SYMBOL(lprocfs_register_stats);
2586 EXPORT_SYMBOL(lprocfs_init_ops_stats);
2587 EXPORT_SYMBOL(lprocfs_init_mps_stats);
2588 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
2589 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
2590 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
2591 EXPORT_SYMBOL(lprocfs_free_obd_stats);
2592 EXPORT_SYMBOL(lprocfs_free_md_stats);
2593 EXPORT_SYMBOL(lprocfs_exp_setup);
2594 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2596 EXPORT_SYMBOL(lprocfs_rd_u64);
2597 EXPORT_SYMBOL(lprocfs_rd_atomic);
2598 EXPORT_SYMBOL(lprocfs_wr_atomic);
2599 EXPORT_SYMBOL(lprocfs_rd_uint);
2600 EXPORT_SYMBOL(lprocfs_wr_uint);
2601 EXPORT_SYMBOL(lprocfs_rd_uuid);
2602 EXPORT_SYMBOL(lprocfs_rd_name);
2603 EXPORT_SYMBOL(lprocfs_rd_fstype);
2604 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
2605 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
2606 EXPORT_SYMBOL(lprocfs_rd_num_exports);
2607 EXPORT_SYMBOL(lprocfs_rd_numrefs);
2608 EXPORT_SYMBOL(lprocfs_at_hist_helper);
2609 EXPORT_SYMBOL(lprocfs_rd_import);
2610 EXPORT_SYMBOL(lprocfs_rd_state);
2611 EXPORT_SYMBOL(lprocfs_rd_timeouts);
2612 EXPORT_SYMBOL(lprocfs_rd_blksize);
2613 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
2614 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
2615 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
2616 EXPORT_SYMBOL(lprocfs_rd_filestotal);
2617 EXPORT_SYMBOL(lprocfs_rd_filesfree);
2619 EXPORT_SYMBOL(lprocfs_write_helper);
2620 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2621 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2622 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2623 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2624 EXPORT_SYMBOL(lprocfs_stats_collect);