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);
102 EXPORT_SYMBOL(lprocfs_srch);
104 /* lprocfs API calls */
106 /* Function that emulates snprintf but also has the side effect of advancing
107 the page pointer for the next write into the buffer, incrementing the total
108 length written to the buffer, and decrementing the size left in the
110 static int lprocfs_obd_snprintf(char **page, int end, int *len,
111 const char *format, ...)
119 va_start(list, format);
120 n = vsnprintf(*page, end - *len, format, list);
123 *page += n; *len += n;
127 cfs_proc_dir_entry_t *lprocfs_add_simple(struct proc_dir_entry *root,
129 read_proc_t *read_proc,
130 write_proc_t *write_proc,
132 struct file_operations *fops)
134 cfs_proc_dir_entry_t *proc;
137 if (root == NULL || name == NULL)
138 return ERR_PTR(-EINVAL);
145 LPROCFS_WRITE_ENTRY();
146 proc = create_proc_entry(name, mode, root);
148 CERROR("LprocFS: No memory to create /proc entry %s", name);
149 LPROCFS_WRITE_EXIT();
150 return ERR_PTR(-ENOMEM);
152 proc->read_proc = read_proc;
153 proc->write_proc = write_proc;
156 proc->proc_fops = fops;
157 LPROCFS_WRITE_EXIT();
160 EXPORT_SYMBOL(lprocfs_add_simple);
162 struct proc_dir_entry *lprocfs_add_symlink(const char *name,
163 struct proc_dir_entry *parent, const char *format, ...)
165 struct proc_dir_entry *entry;
169 if (parent == NULL || format == NULL)
172 OBD_ALLOC_WAIT(dest, MAX_STRING_SIZE + 1);
176 va_start(ap, format);
177 vsnprintf(dest, MAX_STRING_SIZE, format, ap);
180 entry = proc_symlink(name, parent, dest);
182 CERROR("LprocFS: Could not create symbolic link from %s to %s",
185 OBD_FREE(dest, MAX_STRING_SIZE + 1);
188 EXPORT_SYMBOL(lprocfs_add_symlink);
190 static ssize_t lprocfs_fops_read(struct file *f, char __user *buf,
191 size_t size, loff_t *ppos)
193 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
194 char *page, *start = NULL;
195 int rc = 0, eof = 1, count;
197 if (*ppos >= CFS_PAGE_SIZE)
200 page = (char *)__get_free_page(GFP_KERNEL);
204 if (LPROCFS_ENTRY_AND_CHECK(dp)) {
209 OBD_FAIL_TIMEOUT(OBD_FAIL_LPROC_REMOVE, 10);
211 rc = dp->read_proc(page, &start, *ppos, CFS_PAGE_SIZE,
217 /* for lustre proc read, the read count must be less than PAGE_SIZE */
226 start = page + *ppos;
227 } else if (start < page) {
231 count = (rc < size) ? rc : size;
232 if (cfs_copy_to_user(buf, start, count)) {
239 free_page((unsigned long)page);
243 static ssize_t lprocfs_fops_write(struct file *f, const char __user *buf,
244 size_t size, loff_t *ppos)
246 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
249 if (LPROCFS_ENTRY_AND_CHECK(dp))
252 rc = dp->write_proc(f, buf, size, dp->data);
257 static struct file_operations lprocfs_generic_fops = {
258 .owner = THIS_MODULE,
259 .read = lprocfs_fops_read,
260 .write = lprocfs_fops_write,
263 int lprocfs_evict_client_open(struct inode *inode, struct file *f)
265 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
266 struct obd_device *obd = dp->data;
268 cfs_atomic_inc(&obd->obd_evict_inprogress);
273 int lprocfs_evict_client_release(struct inode *inode, struct file *f)
275 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
276 struct obd_device *obd = dp->data;
278 cfs_atomic_dec(&obd->obd_evict_inprogress);
279 cfs_waitq_signal(&obd->obd_evict_inprogress_waitq);
284 struct file_operations lprocfs_evict_client_fops = {
285 .owner = THIS_MODULE,
286 .read = lprocfs_fops_read,
287 .write = lprocfs_fops_write,
288 .open = lprocfs_evict_client_open,
289 .release = lprocfs_evict_client_release,
291 EXPORT_SYMBOL(lprocfs_evict_client_fops);
296 * \param root [in] The parent proc entry on which new entry will be added.
297 * \param list [in] Array of proc entries to be added.
298 * \param data [in] The argument to be passed when entries read/write routines
299 * are called through /proc file.
301 * \retval 0 on success
304 int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list,
309 if (root == NULL || list == NULL)
312 LPROCFS_WRITE_ENTRY();
313 while (list->name != NULL) {
314 struct proc_dir_entry *cur_root, *proc;
315 char *pathcopy, *cur, *next, pathbuf[64];
316 int pathsize = strlen(list->name) + 1;
321 /* need copy of path for strsep */
322 if (strlen(list->name) > sizeof(pathbuf) - 1) {
323 OBD_ALLOC(pathcopy, pathsize);
324 if (pathcopy == NULL)
325 GOTO(out, rc = -ENOMEM);
331 strcpy(pathcopy, list->name);
333 while (cur_root != NULL && (cur = strsep(&next, "/"))) {
334 if (*cur =='\0') /* skip double/trailing "/" */
337 proc = __lprocfs_srch(cur_root, cur);
338 CDEBUG(D_OTHER, "cur_root=%s, cur=%s, next=%s, (%s)\n",
339 cur_root->name, cur, next,
340 (proc ? "exists" : "new"));
342 cur_root = (proc ? proc :
343 proc_mkdir(cur, cur_root));
344 } else if (proc == NULL) {
346 if (list->proc_mode != 0000) {
347 mode = list->proc_mode;
351 if (list->write_fptr)
354 proc = create_proc_entry(cur, mode, cur_root);
358 if (pathcopy != pathbuf)
359 OBD_FREE(pathcopy, pathsize);
361 if (cur_root == NULL || proc == NULL) {
362 CERROR("LprocFS: No memory to create /proc entry %s",
364 GOTO(out, rc = -ENOMEM);
368 proc->proc_fops = list->fops;
370 proc->proc_fops = &lprocfs_generic_fops;
371 proc->read_proc = list->read_fptr;
372 proc->write_proc = list->write_fptr;
373 proc->data = (list->data ? list->data : data);
377 LPROCFS_WRITE_EXIT();
380 EXPORT_SYMBOL(lprocfs_add_vars);
382 void lprocfs_remove(struct proc_dir_entry **rooth)
384 struct proc_dir_entry *root = *rooth;
385 struct proc_dir_entry *temp = root;
386 struct proc_dir_entry *rm_entry;
387 struct proc_dir_entry *parent;
393 parent = root->parent;
394 LASSERT(parent != NULL);
395 LPROCFS_WRITE_ENTRY(); /* search vs remove race */
398 while (temp->subdir != NULL)
404 /* Memory corruption once caused this to fail, and
405 without this LASSERT we would loop here forever. */
406 LASSERTF(strlen(rm_entry->name) == rm_entry->namelen,
407 "0x%p %s/%s len %d\n", rm_entry, temp->name,
408 rm_entry->name, (int)strlen(rm_entry->name));
410 #ifdef HAVE_PROCFS_USERS
411 /* if procfs uses user count to synchronize deletion of
412 * proc entry, there is no protection for rm_entry->data,
413 * then lprocfs_fops_read and lprocfs_fops_write maybe
414 * call proc_dir_entry->read_proc (or write_proc) with
415 * proc_dir_entry->data == NULL, then cause kernel Oops.
416 * see bug19706 for detailed information */
418 /* procfs won't free rm_entry->data if it isn't a LINK,
419 * and Lustre won't use rm_entry->data if it is a LINK */
420 if (S_ISLNK(rm_entry->mode))
421 rm_entry->data = NULL;
423 /* Now, the rm_entry->deleted flags is protected
424 * by _lprocfs_lock. */
425 rm_entry->data = NULL;
427 remove_proc_entry(rm_entry->name, temp);
431 LPROCFS_WRITE_EXIT();
433 EXPORT_SYMBOL(lprocfs_remove);
435 void lprocfs_remove_proc_entry(const char *name, struct proc_dir_entry *parent)
437 LASSERT(parent != NULL);
438 remove_proc_entry(name, parent);
440 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
442 struct proc_dir_entry *lprocfs_register(const char *name,
443 struct proc_dir_entry *parent,
444 struct lprocfs_vars *list, void *data)
446 struct proc_dir_entry *newchild;
448 newchild = lprocfs_srch(parent, name);
449 if (newchild != NULL) {
450 CERROR(" Lproc: Attempting to register %s more than once \n",
452 return ERR_PTR(-EALREADY);
455 newchild = proc_mkdir(name, parent);
456 if (newchild != NULL && list != NULL) {
457 int rc = lprocfs_add_vars(newchild, list, data);
459 lprocfs_remove(&newchild);
465 EXPORT_SYMBOL(lprocfs_register);
467 /* Generic callbacks */
468 int lprocfs_rd_uint(char *page, char **start, off_t off,
469 int count, int *eof, void *data)
471 unsigned int *temp = data;
472 return snprintf(page, count, "%u\n", *temp);
474 EXPORT_SYMBOL(lprocfs_rd_uint);
476 int lprocfs_wr_uint(struct file *file, const char *buffer,
477 unsigned long count, void *data)
480 char dummy[MAX_STRING_SIZE + 1], *end;
483 dummy[MAX_STRING_SIZE] = '\0';
484 if (cfs_copy_from_user(dummy, buffer, MAX_STRING_SIZE))
487 tmp = simple_strtoul(dummy, &end, 0);
491 *p = (unsigned int)tmp;
494 EXPORT_SYMBOL(lprocfs_wr_uint);
496 int lprocfs_rd_u64(char *page, char **start, off_t off,
497 int count, int *eof, void *data)
499 LASSERT(data != NULL);
501 return snprintf(page, count, LPU64"\n", *(__u64 *)data);
503 EXPORT_SYMBOL(lprocfs_rd_u64);
505 int lprocfs_rd_atomic(char *page, char **start, off_t off,
506 int count, int *eof, void *data)
508 cfs_atomic_t *atom = data;
509 LASSERT(atom != NULL);
511 return snprintf(page, count, "%d\n", cfs_atomic_read(atom));
513 EXPORT_SYMBOL(lprocfs_rd_atomic);
515 int lprocfs_wr_atomic(struct file *file, const char *buffer,
516 unsigned long count, void *data)
518 cfs_atomic_t *atm = data;
522 rc = lprocfs_write_helper(buffer, count, &val);
529 cfs_atomic_set(atm, val);
532 EXPORT_SYMBOL(lprocfs_wr_atomic);
534 int lprocfs_rd_uuid(char *page, char **start, off_t off, int count,
535 int *eof, void *data)
537 struct obd_device *obd = data;
539 LASSERT(obd != NULL);
541 return snprintf(page, count, "%s\n", obd->obd_uuid.uuid);
543 EXPORT_SYMBOL(lprocfs_rd_uuid);
545 int lprocfs_rd_name(char *page, char **start, off_t off, int count,
546 int *eof, void *data)
548 struct obd_device *dev = data;
550 LASSERT(dev != NULL);
551 LASSERT(dev->obd_name != NULL);
553 return snprintf(page, count, "%s\n", dev->obd_name);
555 EXPORT_SYMBOL(lprocfs_rd_name);
557 int lprocfs_rd_fstype(char *page, char **start, off_t off, int count, int *eof,
560 struct obd_device *obd = data;
562 LASSERT(obd != NULL);
563 LASSERT(obd->obd_fsops != NULL);
564 LASSERT(obd->obd_fsops->fs_type != NULL);
565 return snprintf(page, count, "%s\n", obd->obd_fsops->fs_type);
567 EXPORT_SYMBOL(lprocfs_rd_fstype);
569 int lprocfs_rd_blksize(char *page, char **start, off_t off, int count,
570 int *eof, void *data)
572 struct obd_device *obd = data;
573 struct obd_statfs osfs;
574 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
575 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
579 rc = snprintf(page, count, "%u\n", osfs.os_bsize);
583 EXPORT_SYMBOL(lprocfs_rd_blksize);
585 int lprocfs_osd_rd_blksize(char *page, char **start, off_t off,
586 int count, int *eof, void *data)
588 struct dt_device *dt = data;
589 struct obd_statfs osfs;
590 int rc = dt_statfs(NULL, dt, &osfs);
593 rc = snprintf(page, count, "%d\n",
594 (unsigned) osfs.os_bsize);
598 EXPORT_SYMBOL(lprocfs_osd_rd_blksize);
600 int lprocfs_rd_kbytestotal(char *page, char **start, off_t off, int count,
601 int *eof, void *data)
603 struct obd_device *obd = data;
604 struct obd_statfs osfs;
605 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
606 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
609 __u32 blk_size = osfs.os_bsize >> 10;
610 __u64 result = osfs.os_blocks;
612 while (blk_size >>= 1)
616 rc = snprintf(page, count, LPU64"\n", result);
620 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
622 int lprocfs_osd_rd_kbytestotal(char *page, char **start, off_t off,
623 int count, int *eof, void *data)
625 struct dt_device *dt = data;
626 struct obd_statfs osfs;
627 int rc = dt_statfs(NULL, dt, &osfs);
629 __u32 blk_size = osfs.os_bsize >> 10;
630 __u64 result = osfs.os_blocks;
632 while (blk_size >>= 1)
636 rc = snprintf(page, count, LPU64"\n", result);
640 EXPORT_SYMBOL(lprocfs_osd_rd_kbytestotal);
642 int lprocfs_rd_kbytesfree(char *page, char **start, off_t off, int count,
643 int *eof, void *data)
645 struct obd_device *obd = data;
646 struct obd_statfs osfs;
647 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
648 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
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);
662 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
664 int lprocfs_osd_rd_kbytesfree(char *page, char **start, off_t off,
665 int count, int *eof, void *data)
667 struct dt_device *dt = data;
668 struct obd_statfs osfs;
669 int rc = dt_statfs(NULL, dt, &osfs);
671 __u32 blk_size = osfs.os_bsize >> 10;
672 __u64 result = osfs.os_bfree;
674 while (blk_size >>= 1)
678 rc = snprintf(page, count, LPU64"\n", result);
682 EXPORT_SYMBOL(lprocfs_osd_rd_kbytesfree);
684 int lprocfs_rd_kbytesavail(char *page, char **start, off_t off, int count,
685 int *eof, void *data)
687 struct obd_device *obd = data;
688 struct obd_statfs osfs;
689 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
690 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
693 __u32 blk_size = osfs.os_bsize >> 10;
694 __u64 result = osfs.os_bavail;
696 while (blk_size >>= 1)
700 rc = snprintf(page, count, LPU64"\n", result);
704 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
706 int lprocfs_osd_rd_kbytesavail(char *page, char **start, off_t off,
707 int count, int *eof, void *data)
709 struct dt_device *dt = data;
710 struct obd_statfs osfs;
711 int rc = dt_statfs(NULL, dt, &osfs);
713 __u32 blk_size = osfs.os_bsize >> 10;
714 __u64 result = osfs.os_bavail;
716 while (blk_size >>= 1)
720 rc = snprintf(page, count, LPU64"\n", result);
724 EXPORT_SYMBOL(lprocfs_osd_rd_kbytesavail);
726 int lprocfs_rd_filestotal(char *page, char **start, off_t off, int count,
727 int *eof, void *data)
729 struct obd_device *obd = data;
730 struct obd_statfs osfs;
731 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
732 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
736 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
741 EXPORT_SYMBOL(lprocfs_rd_filestotal);
743 int lprocfs_osd_rd_filestotal(char *page, char **start, off_t off,
744 int count, int *eof, void *data)
746 struct dt_device *dt = data;
747 struct obd_statfs osfs;
748 int rc = dt_statfs(NULL, dt, &osfs);
751 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
756 EXPORT_SYMBOL(lprocfs_osd_rd_filestotal);
758 int lprocfs_rd_filesfree(char *page, char **start, off_t off, int count,
759 int *eof, void *data)
761 struct obd_device *obd = data;
762 struct obd_statfs osfs;
763 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
764 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
768 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
772 EXPORT_SYMBOL(lprocfs_rd_filesfree);
774 int lprocfs_osd_rd_filesfree(char *page, char **start, off_t off,
775 int count, int *eof, void *data)
777 struct dt_device *dt = data;
778 struct obd_statfs osfs;
779 int rc = dt_statfs(NULL, dt, &osfs);
782 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
786 EXPORT_SYMBOL(lprocfs_osd_rd_filesfree);
788 int lprocfs_rd_server_uuid(char *page, char **start, off_t off, int count,
789 int *eof, void *data)
791 struct obd_device *obd = data;
792 struct obd_import *imp;
793 char *imp_state_name = NULL;
796 LASSERT(obd != NULL);
797 LPROCFS_CLIMP_CHECK(obd);
798 imp = obd->u.cli.cl_import;
799 imp_state_name = ptlrpc_import_state_name(imp->imp_state);
801 rc = snprintf(page, count, "%s\t%s%s\n",
802 obd2cli_tgt(obd), imp_state_name,
803 imp->imp_deactive ? "\tDEACTIVATED" : "");
805 LPROCFS_CLIMP_EXIT(obd);
808 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
810 int lprocfs_rd_conn_uuid(char *page, char **start, off_t off, int count,
811 int *eof, void *data)
813 struct obd_device *obd = data;
814 struct ptlrpc_connection *conn;
817 LASSERT(obd != NULL);
819 LPROCFS_CLIMP_CHECK(obd);
820 conn = obd->u.cli.cl_import->imp_connection;
822 if (conn && obd->u.cli.cl_import) {
823 rc = snprintf(page, count, "%s\n",
824 conn->c_remote_uuid.uuid);
826 rc = snprintf(page, count, "%s\n", "<none>");
829 LPROCFS_CLIMP_EXIT(obd);
832 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
834 /** add up per-cpu counters */
835 void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
836 struct lprocfs_counter *cnt)
838 unsigned int num_entry;
839 struct lprocfs_counter t;
840 struct lprocfs_counter *percpu_cntr;
843 unsigned long flags = 0;
845 memset(cnt, 0, sizeof(*cnt));
848 /* set count to 1 to avoid divide-by-zero errs in callers */
853 cnt->lc_min = LC_MIN_INIT;
855 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
857 for (i = 0; i < num_entry; i++) {
858 if (stats->ls_percpu[i] == NULL)
860 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[idx];
863 centry = cfs_atomic_read(&percpu_cntr-> \
865 t.lc_count = percpu_cntr->lc_count;
866 t.lc_sum = percpu_cntr->lc_sum;
867 t.lc_min = percpu_cntr->lc_min;
868 t.lc_max = percpu_cntr->lc_max;
869 t.lc_sumsquare = percpu_cntr->lc_sumsquare;
870 } while (centry != cfs_atomic_read(&percpu_cntr->lc_cntl. \
872 centry != cfs_atomic_read(&percpu_cntr->lc_cntl. \
874 cnt->lc_count += t.lc_count;
875 cnt->lc_sum += t.lc_sum;
876 if (t.lc_min < cnt->lc_min)
877 cnt->lc_min = t.lc_min;
878 if (t.lc_max > cnt->lc_max)
879 cnt->lc_max = t.lc_max;
880 cnt->lc_sumsquare += t.lc_sumsquare;
883 cnt->lc_units = stats->ls_percpu[0]->lp_cntr[idx].lc_units;
884 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
886 EXPORT_SYMBOL(lprocfs_stats_collect);
889 * Append a space separated list of current set flags to str.
891 #define flag2str(flag) \
892 if (imp->imp_##flag && max - len > 0) \
893 len += snprintf(str + len, max - len, "%s" #flag, len ? ", " : "");
894 static int obd_import_flags2str(struct obd_import *imp, char *str, int max)
898 if (imp->imp_obd->obd_no_recov)
899 len += snprintf(str, max - len, "no_recov");
903 flag2str(replayable);
909 static const char *obd_connect_names[] = {
923 "join_file(obsolete)",
927 "remote_client_by_force",
936 "mds_mds_connection",
939 "alt_checksum_algorithm",
958 int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
963 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
965 ret += snprintf(page + ret, count - ret, "%s%s",
966 ret ? sep : "", obd_connect_names[i]);
968 if (flags & ~(mask - 1))
969 ret += snprintf(page + ret, count - ret,
970 "%sunknown flags "LPX64,
971 ret ? sep : "", flags & ~(mask - 1));
974 EXPORT_SYMBOL(obd_connect_flags2str);
976 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
977 int *eof, void *data)
979 struct lprocfs_counter ret;
980 struct obd_device *obd = (struct obd_device *)data;
981 struct obd_import *imp;
982 struct obd_import_conn *conn;
985 LASSERT(obd != NULL);
986 LPROCFS_CLIMP_CHECK(obd);
987 imp = obd->u.cli.cl_import;
990 i = snprintf(page, count,
999 ptlrpc_import_state_name(imp->imp_state),
1000 imp->imp_connect_data.ocd_instance);
1001 i += obd_connect_flags2str(page + i, count - i,
1002 imp->imp_connect_data.ocd_connect_flags,
1004 i += snprintf(page + i, count - i,
1006 " import_flags: [");
1007 i += obd_import_flags2str(imp, page + i, count - i);
1009 i += snprintf(page + i, count - i,
1012 " failover_nids: [");
1013 cfs_spin_lock(&imp->imp_lock);
1015 cfs_list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
1016 i += snprintf(page + i, count - i, "%s%s", j ? ", " : "",
1017 libcfs_nid2str(conn->oic_conn->c_peer.nid));
1020 i += snprintf(page + i, count - i,
1022 " current_connection: %s\n"
1023 " connection_attempts: %u\n"
1025 " in-progress_invalidations: %u\n",
1026 imp->imp_connection == NULL ? "<none>" :
1027 libcfs_nid2str(imp->imp_connection->c_peer.nid),
1029 imp->imp_generation,
1030 cfs_atomic_read(&imp->imp_inval_count));
1031 cfs_spin_unlock(&imp->imp_lock);
1033 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
1034 if (ret.lc_count != 0) {
1035 /* first argument to do_div MUST be __u64 */
1036 __u64 sum = ret.lc_sum;
1037 do_div(sum, ret.lc_count);
1041 i += snprintf(page + i, count - i,
1044 " unregistering: %u\n"
1046 " avg_waittime: "LPU64" %s\n",
1047 cfs_atomic_read(&imp->imp_inflight),
1048 cfs_atomic_read(&imp->imp_unregistering),
1049 cfs_atomic_read(&imp->imp_timeouts),
1050 ret.lc_sum, ret.lc_units);
1053 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
1054 if (imp->imp_at.iat_portal[j] == 0)
1056 k = max_t(unsigned int, k,
1057 at_get(&imp->imp_at.iat_service_estimate[j]));
1059 i += snprintf(page + i, count - i,
1060 " service_estimates:\n"
1061 " services: %u sec\n"
1062 " network: %u sec\n",
1064 at_get(&imp->imp_at.iat_net_latency));
1066 i += snprintf(page + i, count - i,
1068 " last_replay: "LPU64"\n"
1069 " peer_committed: "LPU64"\n"
1070 " last_checked: "LPU64"\n",
1071 imp->imp_last_replay_transno,
1072 imp->imp_peer_committed_transno,
1073 imp->imp_last_transno_checked);
1075 /* avg data rates */
1076 for (rw = 0; rw <= 1; rw++) {
1077 lprocfs_stats_collect(obd->obd_svc_stats,
1078 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
1080 if (ret.lc_sum > 0 && ret.lc_count > 0) {
1081 /* first argument to do_div MUST be __u64 */
1082 __u64 sum = ret.lc_sum;
1083 do_div(sum, ret.lc_count);
1085 i += snprintf(page + i, count - i,
1086 " %s_data_averages:\n"
1087 " bytes_per_rpc: "LPU64"\n",
1088 rw ? "write" : "read",
1091 k = (int)ret.lc_sum;
1092 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
1093 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
1094 if (ret.lc_sum > 0 && ret.lc_count != 0) {
1095 /* first argument to do_div MUST be __u64 */
1096 __u64 sum = ret.lc_sum;
1097 do_div(sum, ret.lc_count);
1099 i += snprintf(page + i, count - i,
1100 " %s_per_rpc: "LPU64"\n",
1101 ret.lc_units, ret.lc_sum);
1102 j = (int)ret.lc_sum;
1104 i += snprintf(page + i, count - i,
1105 " MB_per_sec: %u.%.02u\n",
1106 k / j, (100 * k / j) % 100);
1110 LPROCFS_CLIMP_EXIT(obd);
1113 EXPORT_SYMBOL(lprocfs_rd_import);
1115 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
1116 int *eof, void *data)
1118 struct obd_device *obd = (struct obd_device *)data;
1119 struct obd_import *imp;
1122 LASSERT(obd != NULL);
1123 LPROCFS_CLIMP_CHECK(obd);
1124 imp = obd->u.cli.cl_import;
1127 i = snprintf(page, count, "current_state: %s\n",
1128 ptlrpc_import_state_name(imp->imp_state));
1129 i += snprintf(page + i, count - i,
1130 "state_history:\n");
1131 k = imp->imp_state_hist_idx;
1132 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
1133 struct import_state_hist *ish =
1134 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
1135 if (ish->ish_state == 0)
1137 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
1139 ptlrpc_import_state_name(ish->ish_state));
1142 LPROCFS_CLIMP_EXIT(obd);
1145 EXPORT_SYMBOL(lprocfs_rd_state);
1147 int lprocfs_at_hist_helper(char *page, int count, int rc,
1148 struct adaptive_timeout *at)
1151 for (i = 0; i < AT_BINS; i++)
1152 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
1153 rc += snprintf(page + rc, count - rc, "\n");
1156 EXPORT_SYMBOL(lprocfs_at_hist_helper);
1158 /* See also ptlrpc_lprocfs_rd_timeouts */
1159 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
1160 int *eof, void *data)
1162 struct obd_device *obd = (struct obd_device *)data;
1163 struct obd_import *imp;
1164 unsigned int cur, worst;
1169 LASSERT(obd != NULL);
1170 LPROCFS_CLIMP_CHECK(obd);
1171 imp = obd->u.cli.cl_import;
1174 now = cfs_time_current_sec();
1176 /* Some network health info for kicks */
1177 s2dhms(&ts, now - imp->imp_last_reply_time);
1178 rc += snprintf(page + rc, count - rc,
1179 "%-10s : %ld, "DHMS_FMT" ago\n",
1180 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
1182 cur = at_get(&imp->imp_at.iat_net_latency);
1183 worst = imp->imp_at.iat_net_latency.at_worst_ever;
1184 worstt = imp->imp_at.iat_net_latency.at_worst_time;
1185 s2dhms(&ts, now - worstt);
1186 rc += snprintf(page + rc, count - rc,
1187 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
1188 "network", cur, worst, worstt, DHMS_VARS(&ts));
1189 rc = lprocfs_at_hist_helper(page, count, rc,
1190 &imp->imp_at.iat_net_latency);
1192 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
1193 if (imp->imp_at.iat_portal[i] == 0)
1195 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
1196 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
1197 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
1198 s2dhms(&ts, now - worstt);
1199 rc += snprintf(page + rc, count - rc,
1200 "portal %-2d : cur %3u worst %3u (at %ld, "
1201 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
1202 cur, worst, worstt, DHMS_VARS(&ts));
1203 rc = lprocfs_at_hist_helper(page, count, rc,
1204 &imp->imp_at.iat_service_estimate[i]);
1207 LPROCFS_CLIMP_EXIT(obd);
1210 EXPORT_SYMBOL(lprocfs_rd_timeouts);
1212 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1213 int count, int *eof, void *data)
1215 struct obd_device *obd = data;
1219 LPROCFS_CLIMP_CHECK(obd);
1220 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1221 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1222 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1223 ret += snprintf(page + ret, count - ret, "\n");
1224 LPROCFS_CLIMP_EXIT(obd);
1227 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1229 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1230 int *eof, void *data)
1232 struct obd_device *obd = data;
1234 LASSERT(obd != NULL);
1236 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1238 EXPORT_SYMBOL(lprocfs_rd_num_exports);
1240 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1241 int *eof, void *data)
1243 struct obd_type *class = (struct obd_type*) data;
1245 LASSERT(class != NULL);
1247 return snprintf(page, count, "%d\n", class->typ_refcnt);
1249 EXPORT_SYMBOL(lprocfs_rd_numrefs);
1251 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1255 LASSERT(obd != NULL);
1256 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1257 LASSERT(obd->obd_type->typ_procroot != NULL);
1259 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1260 obd->obd_type->typ_procroot,
1262 if (IS_ERR(obd->obd_proc_entry)) {
1263 rc = PTR_ERR(obd->obd_proc_entry);
1264 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1265 obd->obd_proc_entry = NULL;
1269 EXPORT_SYMBOL(lprocfs_obd_setup);
1271 int lprocfs_obd_cleanup(struct obd_device *obd)
1275 if (obd->obd_proc_exports_entry) {
1276 /* Should be no exports left */
1277 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1278 lprocfs_remove(&obd->obd_proc_exports_entry);
1279 obd->obd_proc_exports_entry = NULL;
1281 if (obd->obd_proc_entry) {
1282 lprocfs_remove(&obd->obd_proc_entry);
1283 obd->obd_proc_entry = NULL;
1287 EXPORT_SYMBOL(lprocfs_obd_cleanup);
1289 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1291 CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
1292 client_stat->nid_proc, client_stat->nid_stats,
1293 client_stat->nid_brw_stats);
1295 LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
1296 "nid %s:count %d\n", libcfs_nid2str(client_stat->nid),
1297 atomic_read(&client_stat->nid_exp_ref_count));
1299 if (client_stat->nid_proc)
1300 lprocfs_remove(&client_stat->nid_proc);
1302 if (client_stat->nid_stats)
1303 lprocfs_free_stats(&client_stat->nid_stats);
1305 if (client_stat->nid_brw_stats)
1306 OBD_FREE_PTR(client_stat->nid_brw_stats);
1308 if (client_stat->nid_ldlm_stats)
1309 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1311 OBD_FREE_PTR(client_stat);
1316 void lprocfs_free_per_client_stats(struct obd_device *obd)
1318 cfs_hash_t *hash = obd->obd_nid_stats_hash;
1319 struct nid_stat *stat;
1322 /* we need extra list - because hash_exit called to early */
1323 /* not need locking because all clients is died */
1324 while (!cfs_list_empty(&obd->obd_nid_stats)) {
1325 stat = cfs_list_entry(obd->obd_nid_stats.next,
1326 struct nid_stat, nid_list);
1327 cfs_list_del_init(&stat->nid_list);
1328 cfs_hash_del(hash, &stat->nid, &stat->nid_hash);
1329 lprocfs_free_client_stats(stat);
1333 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
1335 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1336 enum lprocfs_stats_flags flags)
1338 struct lprocfs_stats *stats;
1339 unsigned int percpusize;
1340 unsigned int num_entry;
1345 if (lprocfs_no_percpu_stats != 0)
1346 flags |= LPROCFS_STATS_FLAG_NOPERCPU;
1348 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1351 num_entry = cfs_num_possible_cpus() + 1;
1353 /* alloc percpu pointers for all possible cpu slots */
1354 OBD_ALLOC(stats, offsetof(struct lprocfs_stats, ls_percpu[num_entry]));
1358 stats->ls_num = num;
1359 stats->ls_biggest_alloc_num = 1;
1360 stats->ls_flags = flags;
1361 cfs_spin_lock_init(&stats->ls_lock);
1363 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
1365 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1367 /* for no percpu area, the 0th entry is for real use,
1368 * for percpu area, the 0th entry is for intialized entry template */
1369 OBD_ALLOC(stats->ls_percpu[0], percpusize);
1370 if (stats->ls_percpu[0] == NULL) {
1372 offsetof(struct lprocfs_stats, ls_percpu[num_entry]));
1377 EXPORT_SYMBOL(lprocfs_alloc_stats);
1379 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1381 struct lprocfs_stats *stats = *statsh;
1382 unsigned int num_entry;
1383 unsigned int percpusize;
1386 if (stats == NULL || stats->ls_num == 0)
1390 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1393 num_entry = cfs_num_possible_cpus() + 1;
1395 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
1397 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1398 for (i = 0; i < num_entry; i++)
1399 if (stats->ls_percpu[i] != NULL)
1400 OBD_FREE(stats->ls_percpu[i], percpusize);
1401 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1403 EXPORT_SYMBOL(lprocfs_free_stats);
1405 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1407 struct lprocfs_counter *percpu_cntr;
1410 unsigned int num_entry;
1411 unsigned long flags = 0;
1413 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1415 for (i = 0; i < num_entry; i++) {
1416 if (stats->ls_percpu[i] == NULL)
1418 for (j = 0; j < stats->ls_num; j++) {
1419 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
1420 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_entry);
1421 percpu_cntr->lc_count = 0;
1422 percpu_cntr->lc_sum = 0;
1423 percpu_cntr->lc_min = LC_MIN_INIT;
1424 percpu_cntr->lc_max = 0;
1425 percpu_cntr->lc_sumsquare = 0;
1426 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_exit);
1430 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1432 EXPORT_SYMBOL(lprocfs_clear_stats);
1434 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1435 size_t len, loff_t *off)
1437 struct seq_file *seq = file->private_data;
1438 struct lprocfs_stats *stats = seq->private;
1440 lprocfs_clear_stats(stats);
1445 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1447 struct lprocfs_stats *stats = p->private;
1448 /* return 1st cpu location */
1449 return (*pos >= stats->ls_num) ? NULL :
1450 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1453 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1457 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1459 struct lprocfs_stats *stats = p->private;
1461 return (*pos >= stats->ls_num) ? NULL :
1462 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1465 /* seq file export of one lprocfs counter */
1466 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1468 struct lprocfs_stats *stats = p->private;
1469 struct lprocfs_counter *cntr = v;
1470 struct lprocfs_counter ret;
1473 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
1475 cfs_gettimeofday(&now);
1476 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1477 "snapshot_time", now.tv_sec, now.tv_usec);
1481 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
1483 lprocfs_stats_collect(stats, idx, &ret);
1485 if (ret.lc_count == 0)
1488 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", cntr->lc_name,
1489 ret.lc_count, cntr->lc_units);
1494 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
1495 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1496 ret.lc_min, ret.lc_max, ret.lc_sum);
1499 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
1500 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1504 rc = seq_printf(p, "\n");
1506 return (rc < 0) ? rc : 0;
1509 struct seq_operations lprocfs_stats_seq_sops = {
1510 start: lprocfs_stats_seq_start,
1511 stop: lprocfs_stats_seq_stop,
1512 next: lprocfs_stats_seq_next,
1513 show: lprocfs_stats_seq_show,
1516 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1518 struct proc_dir_entry *dp = PDE(inode);
1519 struct seq_file *seq;
1522 if (LPROCFS_ENTRY_AND_CHECK(dp))
1525 rc = seq_open(file, &lprocfs_stats_seq_sops);
1530 seq = file->private_data;
1531 seq->private = dp->data;
1535 struct file_operations lprocfs_stats_seq_fops = {
1536 .owner = THIS_MODULE,
1537 .open = lprocfs_stats_seq_open,
1539 .write = lprocfs_stats_seq_write,
1540 .llseek = seq_lseek,
1541 .release = lprocfs_seq_release,
1544 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1545 struct lprocfs_stats *stats)
1547 struct proc_dir_entry *entry;
1548 LASSERT(root != NULL);
1550 LPROCFS_WRITE_ENTRY();
1551 entry = create_proc_entry(name, 0644, root);
1553 entry->proc_fops = &lprocfs_stats_seq_fops;
1554 entry->data = stats;
1557 LPROCFS_WRITE_EXIT();
1564 EXPORT_SYMBOL(lprocfs_register_stats);
1566 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1567 unsigned conf, const char *name, const char *units)
1569 struct lprocfs_counter *c = &(stats->ls_percpu[0]->lp_cntr[index]);
1570 unsigned long flags = 0;
1572 LASSERT(stats != NULL);
1573 LASSERT(stats->ls_percpu[0] != NULL);
1575 lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1576 c->lc_config = conf;
1579 c->lc_min = LC_MIN_INIT;
1582 c->lc_units = units;
1583 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1585 EXPORT_SYMBOL(lprocfs_counter_init);
1587 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1589 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1590 LASSERT(coffset < stats->ls_num); \
1591 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1594 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1596 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1597 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1598 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1599 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1600 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1601 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1602 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1603 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1604 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1605 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1606 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1607 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1608 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1609 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1610 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1611 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1612 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1613 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1614 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
1615 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1616 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1617 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1618 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1619 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1620 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1621 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1622 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1623 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1624 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1625 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1626 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1627 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1628 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1629 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1630 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1631 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1632 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1633 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1634 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1635 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1636 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1637 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1638 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1639 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1640 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
1641 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1642 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1643 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1644 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1645 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1646 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1647 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1648 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1649 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1650 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1651 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1652 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1653 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1654 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1655 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1656 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1657 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quota_adjust_qunit);
1658 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1659 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1660 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1661 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1662 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1663 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1664 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1666 EXPORT_SYMBOL(lprocfs_init_ops_stats);
1668 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1670 struct lprocfs_stats *stats;
1671 unsigned int num_stats;
1674 LASSERT(obd->obd_stats == NULL);
1675 LASSERT(obd->obd_proc_entry != NULL);
1676 LASSERT(obd->obd_cntr_base == 0);
1678 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1679 num_private_stats - 1 /* o_owner */;
1680 stats = lprocfs_alloc_stats(num_stats, 0);
1684 lprocfs_init_ops_stats(num_private_stats, stats);
1686 for (i = num_private_stats; i < num_stats; i++) {
1687 /* If this LBUGs, it is likely that an obd
1688 * operation was added to struct obd_ops in
1689 * <obd.h>, and that the corresponding line item
1690 * LPROCFS_OBD_OP_INIT(.., .., opname)
1691 * is missing from the list above. */
1692 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1693 "Missing obd_stat initializer obd_op "
1694 "operation at offset %d.\n", i - num_private_stats);
1696 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1698 lprocfs_free_stats(&stats);
1700 obd->obd_stats = stats;
1701 obd->obd_cntr_base = num_private_stats;
1705 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
1707 void lprocfs_free_obd_stats(struct obd_device *obd)
1710 lprocfs_free_stats(&obd->obd_stats);
1712 EXPORT_SYMBOL(lprocfs_free_obd_stats);
1714 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1716 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1717 LASSERT(coffset < stats->ls_num); \
1718 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1721 void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats)
1723 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1724 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1725 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
1726 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1727 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1728 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1729 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1730 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1731 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1732 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1733 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1734 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1735 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1736 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1737 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1738 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1739 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1740 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1741 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1742 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1743 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1744 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1745 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1746 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1747 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1748 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1749 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1750 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1751 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1752 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1753 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1754 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1756 EXPORT_SYMBOL(lprocfs_init_mps_stats);
1758 int lprocfs_alloc_md_stats(struct obd_device *obd,
1759 unsigned num_private_stats)
1761 struct lprocfs_stats *stats;
1762 unsigned int num_stats;
1765 LASSERT(obd->md_stats == NULL);
1766 LASSERT(obd->obd_proc_entry != NULL);
1767 LASSERT(obd->md_cntr_base == 0);
1769 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1771 stats = lprocfs_alloc_stats(num_stats, 0);
1775 lprocfs_init_mps_stats(num_private_stats, stats);
1777 for (i = num_private_stats; i < num_stats; i++) {
1778 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1779 CERROR("Missing md_stat initializer md_op "
1780 "operation at offset %d. Aborting.\n",
1781 i - num_private_stats);
1785 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1787 lprocfs_free_stats(&stats);
1789 obd->md_stats = stats;
1790 obd->md_cntr_base = num_private_stats;
1794 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
1796 void lprocfs_free_md_stats(struct obd_device *obd)
1798 struct lprocfs_stats *stats = obd->md_stats;
1800 if (stats != NULL) {
1801 obd->md_stats = NULL;
1802 obd->md_cntr_base = 0;
1803 lprocfs_free_stats(&stats);
1806 EXPORT_SYMBOL(lprocfs_free_md_stats);
1808 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1810 lprocfs_counter_init(ldlm_stats,
1811 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1812 0, "ldlm_enqueue", "reqs");
1813 lprocfs_counter_init(ldlm_stats,
1814 LDLM_CONVERT - LDLM_FIRST_OPC,
1815 0, "ldlm_convert", "reqs");
1816 lprocfs_counter_init(ldlm_stats,
1817 LDLM_CANCEL - LDLM_FIRST_OPC,
1818 0, "ldlm_cancel", "reqs");
1819 lprocfs_counter_init(ldlm_stats,
1820 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1821 0, "ldlm_bl_callback", "reqs");
1822 lprocfs_counter_init(ldlm_stats,
1823 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1824 0, "ldlm_cp_callback", "reqs");
1825 lprocfs_counter_init(ldlm_stats,
1826 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1827 0, "ldlm_gl_callback", "reqs");
1829 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
1831 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1832 int *eof, void *data)
1834 struct obd_export *exp = data;
1835 LASSERT(exp != NULL);
1837 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1840 struct exp_uuid_cb_data {
1848 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1849 int count, int *eof, int *len)
1851 cb_data->page = page;
1852 cb_data->count = count;
1857 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1858 cfs_hlist_node_t *hnode, void *cb_data)
1861 struct obd_export *exp = cfs_hash_object(hs, hnode);
1862 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1864 if (exp->exp_nid_stats)
1865 *data->len += snprintf((data->page + *data->len),
1866 data->count, "%s\n",
1867 obd_uuid2str(&exp->exp_client_uuid));
1871 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1872 int *eof, void *data)
1874 struct nid_stat *stats = (struct nid_stat *)data;
1875 struct exp_uuid_cb_data cb_data;
1876 struct obd_device *obd = stats->nid_obd;
1881 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1882 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1883 lprocfs_exp_print_uuid, &cb_data);
1884 return (*cb_data.len);
1887 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1888 cfs_hlist_node_t *hnode, void *cb_data)
1891 struct exp_uuid_cb_data *data = cb_data;
1892 struct obd_export *exp = cfs_hash_object(hs, hnode);
1894 if (exp->exp_lock_hash != NULL) {
1896 *data->len += cfs_hash_debug_header(data->page,
1899 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1906 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1907 int *eof, void *data)
1909 struct nid_stat *stats = (struct nid_stat *)data;
1910 struct exp_uuid_cb_data cb_data;
1911 struct obd_device *obd = stats->nid_obd;
1916 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1918 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1919 lprocfs_exp_print_hash, &cb_data);
1920 return (*cb_data.len);
1923 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1924 int count, int *eof, void *data)
1927 return snprintf(page, count, "%s\n",
1928 "Write into this file to clear all nid stats and "
1929 "stale nid entries");
1931 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1933 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1935 struct nid_stat *stat = obj;
1939 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
1940 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 1) {
1941 /* object has only hash references. */
1942 cfs_spin_lock(&stat->nid_obd->obd_nid_lock);
1943 cfs_list_move(&stat->nid_list, data);
1944 cfs_spin_unlock(&stat->nid_obd->obd_nid_lock);
1947 /* we has reference to object - only clear data*/
1948 if (stat->nid_stats)
1949 lprocfs_clear_stats(stat->nid_stats);
1951 if (stat->nid_brw_stats) {
1952 for (i = 0; i < BRW_LAST; i++)
1953 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
1958 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1959 unsigned long count, void *data)
1961 struct obd_device *obd = (struct obd_device *)data;
1962 struct nid_stat *client_stat;
1963 CFS_LIST_HEAD(free_list);
1965 cfs_hash_cond_del(obd->obd_nid_stats_hash,
1966 lprocfs_nid_stats_clear_write_cb, &free_list);
1968 while (!cfs_list_empty(&free_list)) {
1969 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
1971 cfs_list_del_init(&client_stat->nid_list);
1972 lprocfs_free_client_stats(client_stat);
1977 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1979 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1981 struct nid_stat *new_stat, *old_stat;
1982 struct obd_device *obd = NULL;
1983 cfs_proc_dir_entry_t *entry;
1984 char *buffer = NULL;
1990 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1991 !exp->exp_obd->obd_nid_stats_hash)
1994 /* not test against zero because eric say:
1995 * You may only test nid against another nid, or LNET_NID_ANY.
1996 * Anything else is nonsense.*/
1997 if (!nid || *nid == LNET_NID_ANY)
2002 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
2004 OBD_ALLOC_PTR(new_stat);
2005 if (new_stat == NULL)
2008 new_stat->nid = *nid;
2009 new_stat->nid_obd = exp->exp_obd;
2010 /* we need set default refcount to 1 to balance obd_disconnect */
2011 cfs_atomic_set(&new_stat->nid_exp_ref_count, 1);
2013 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
2014 nid, &new_stat->nid_hash);
2015 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
2016 old_stat, libcfs_nid2str(*nid),
2017 cfs_atomic_read(&new_stat->nid_exp_ref_count));
2019 /* We need to release old stats because lprocfs_exp_cleanup() hasn't
2020 * been and will never be called. */
2021 if (exp->exp_nid_stats) {
2022 nidstat_putref(exp->exp_nid_stats);
2023 exp->exp_nid_stats = NULL;
2026 /* Return -EALREADY here so that we know that the /proc
2027 * entry already has been created */
2028 if (old_stat != new_stat) {
2029 exp->exp_nid_stats = old_stat;
2030 GOTO(destroy_new, rc = -EALREADY);
2032 /* not found - create */
2033 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
2035 GOTO(destroy_new, rc = -ENOMEM);
2037 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
2038 new_stat->nid_proc = lprocfs_register(buffer,
2039 obd->obd_proc_exports_entry,
2041 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
2043 if (new_stat->nid_proc == NULL) {
2044 CERROR("Error making export directory for nid %s\n",
2045 libcfs_nid2str(*nid));
2046 GOTO(destroy_new_ns, rc = -ENOMEM);
2049 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
2050 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
2051 if (IS_ERR(entry)) {
2052 CWARN("Error adding the NID stats file\n");
2053 rc = PTR_ERR(entry);
2054 GOTO(destroy_new_ns, rc);
2057 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
2058 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
2059 if (IS_ERR(entry)) {
2060 CWARN("Error adding the hash file\n");
2061 rc = PTR_ERR(entry);
2062 GOTO(destroy_new_ns, rc);
2065 exp->exp_nid_stats = new_stat;
2067 /* protect competitive add to list, not need locking on destroy */
2068 cfs_spin_lock(&obd->obd_nid_lock);
2069 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
2070 cfs_spin_unlock(&obd->obd_nid_lock);
2075 if (new_stat->nid_proc != NULL)
2076 lprocfs_remove(&new_stat->nid_proc);
2077 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
2080 nidstat_putref(new_stat);
2081 OBD_FREE_PTR(new_stat);
2084 EXPORT_SYMBOL(lprocfs_exp_setup);
2086 int lprocfs_exp_cleanup(struct obd_export *exp)
2088 struct nid_stat *stat = exp->exp_nid_stats;
2090 if(!stat || !exp->exp_obd)
2093 nidstat_putref(exp->exp_nid_stats);
2094 exp->exp_nid_stats = NULL;
2098 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2100 int lprocfs_write_helper(const char *buffer, unsigned long count,
2103 return lprocfs_write_frac_helper(buffer, count, val, 1);
2105 EXPORT_SYMBOL(lprocfs_write_helper);
2107 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
2110 char kernbuf[20], *end, *pbuf;
2112 if (count > (sizeof(kernbuf) - 1))
2115 if (cfs_copy_from_user(kernbuf, buffer, count))
2118 kernbuf[count] = '\0';
2125 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2129 if (end != NULL && *end == '.') {
2130 int temp_val, pow = 1;
2134 if (strlen(pbuf) > 5)
2135 pbuf[5] = '\0'; /*only allow 5bits fractional*/
2137 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2140 for (i = 0; i < (end - pbuf); i++)
2143 *val += temp_val / pow;
2148 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2150 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
2153 long decimal_val, frac_val;
2159 decimal_val = val / mult;
2160 prtn = snprintf(buffer, count, "%ld", decimal_val);
2161 frac_val = val % mult;
2163 if (prtn < (count - 4) && frac_val > 0) {
2165 int i, temp_mult = 1, frac_bits = 0;
2167 temp_frac = frac_val * 10;
2168 buffer[prtn++] = '.';
2169 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
2170 /* only reserved 2 bits fraction */
2171 buffer[prtn++] ='0';
2176 * Need to think these cases :
2177 * 1. #echo x.00 > /proc/xxx output result : x
2178 * 2. #echo x.0x > /proc/xxx output result : x.0x
2179 * 3. #echo x.x0 > /proc/xxx output result : x.x
2180 * 4. #echo x.xx > /proc/xxx output result : x.xx
2181 * Only reserved 2 bits fraction.
2183 for (i = 0; i < (5 - prtn); i++)
2186 frac_bits = min((int)count - prtn, 3 - frac_bits);
2187 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
2188 frac_val * temp_mult / mult);
2191 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
2193 if (buffer[prtn] == '.') {
2200 buffer[prtn++] ='\n';
2203 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2205 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
2207 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
2209 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2211 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
2212 __u64 *val, int mult)
2214 char kernbuf[22], *end, *pbuf;
2215 __u64 whole, frac = 0, units;
2216 unsigned frac_d = 1;
2218 if (count > (sizeof(kernbuf) - 1))
2221 if (cfs_copy_from_user(kernbuf, buffer, count))
2224 kernbuf[count] = '\0';
2231 whole = simple_strtoull(pbuf, &end, 10);
2235 if (end != NULL && *end == '.') {
2239 /* need to limit frac_d to a __u32 */
2240 if (strlen(pbuf) > 10)
2243 frac = simple_strtoull(pbuf, &end, 10);
2244 /* count decimal places */
2245 for (i = 0; i < (end - pbuf); i++)
2262 /* Specified units override the multiplier */
2264 mult = mult < 0 ? -units : units;
2267 do_div(frac, frac_d);
2268 *val = whole * mult + frac;
2271 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2273 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent, char *name, mode_t mode,
2274 struct file_operations *seq_fops, void *data)
2276 struct proc_dir_entry *entry;
2279 LPROCFS_WRITE_ENTRY();
2280 entry = create_proc_entry(name, mode, parent);
2282 entry->proc_fops = seq_fops;
2285 LPROCFS_WRITE_EXIT();
2292 EXPORT_SYMBOL(lprocfs_seq_create);
2294 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
2296 struct file_operations *seq_fops,
2299 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2300 mode, seq_fops, data));
2302 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2304 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2306 if (value >= OBD_HIST_MAX)
2307 value = OBD_HIST_MAX - 1;
2309 cfs_spin_lock(&oh->oh_lock);
2310 oh->oh_buckets[value]++;
2311 cfs_spin_unlock(&oh->oh_lock);
2313 EXPORT_SYMBOL(lprocfs_oh_tally);
2315 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2319 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2322 lprocfs_oh_tally(oh, val);
2324 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2326 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2328 unsigned long ret = 0;
2331 for (i = 0; i < OBD_HIST_MAX; i++)
2332 ret += oh->oh_buckets[i];
2335 EXPORT_SYMBOL(lprocfs_oh_sum);
2337 void lprocfs_oh_clear(struct obd_histogram *oh)
2339 cfs_spin_lock(&oh->oh_lock);
2340 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2341 cfs_spin_unlock(&oh->oh_lock);
2343 EXPORT_SYMBOL(lprocfs_oh_clear);
2345 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2346 int count, int *eof, void *data)
2348 struct obd_device *obd = data;
2354 c += cfs_hash_debug_header(page, count);
2355 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2356 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2357 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2358 #ifdef HAVE_QUOTA_SUPPORT
2359 if (obd->u.obt.obt_qctxt.lqc_lqs_hash)
2360 c += cfs_hash_debug_str(obd->u.obt.obt_qctxt.lqc_lqs_hash,
2361 page + c, count - c);
2366 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2368 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2369 int count, int *eof, void *data)
2371 struct obd_device *obd = data;
2374 LASSERT(obd != NULL);
2375 LASSERT(count >= 0);
2377 /* Set start of user data returned to
2378 page + off since the user may have
2379 requested to read much smaller than
2380 what we need to read */
2381 *start = page + off;
2383 /* We know we are allocated a page here.
2384 Also we know that this function will
2385 not need to write more than a page
2386 so we can truncate at CFS_PAGE_SIZE. */
2387 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2389 /* Initialize the page */
2390 memset(page, 0, size);
2392 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2394 if (obd->obd_max_recoverable_clients == 0) {
2395 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2401 /* sampled unlocked, but really... */
2402 if (obd->obd_recovering == 0) {
2403 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2405 if (lprocfs_obd_snprintf(&page, size, &len,
2406 "recovery_start: %lu\n",
2407 obd->obd_recovery_start) <= 0)
2409 if (lprocfs_obd_snprintf(&page, size, &len,
2410 "recovery_duration: %lu\n",
2411 obd->obd_recovery_end -
2412 obd->obd_recovery_start) <= 0)
2414 /* Number of clients that have completed recovery */
2415 if (lprocfs_obd_snprintf(&page, size, &len,
2416 "completed_clients: %d/%d\n",
2417 obd->obd_max_recoverable_clients -
2418 obd->obd_stale_clients,
2419 obd->obd_max_recoverable_clients) <= 0)
2421 if (lprocfs_obd_snprintf(&page, size, &len,
2422 "replayed_requests: %d\n",
2423 obd->obd_replayed_requests) <= 0)
2425 if (lprocfs_obd_snprintf(&page, size, &len,
2426 "last_transno: "LPD64"\n",
2427 obd->obd_next_recovery_transno - 1)<=0)
2429 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2430 obd->obd_version_recov ? "ON" : "OFF")<=0)
2432 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
2433 obd->obd_no_ir ? "OFF" : "ON") <= 0)
2438 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2440 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2441 obd->obd_recovery_start) <= 0)
2443 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2444 cfs_time_current_sec() >=
2445 obd->obd_recovery_start +
2446 obd->obd_recovery_timeout ? 0 :
2447 obd->obd_recovery_start +
2448 obd->obd_recovery_timeout -
2449 cfs_time_current_sec()) <= 0)
2451 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2452 cfs_atomic_read(&obd->obd_connected_clients),
2453 obd->obd_max_recoverable_clients) <= 0)
2455 /* Number of clients that have completed recovery */
2456 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2457 cfs_atomic_read(&obd->obd_req_replay_clients))
2460 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2461 cfs_atomic_read(&obd->obd_lock_replay_clients))
2464 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2465 cfs_atomic_read(&obd->obd_connected_clients) -
2466 cfs_atomic_read(&obd->obd_lock_replay_clients))
2469 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2470 obd->obd_stale_clients) <= 0)
2472 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2473 obd->obd_replayed_requests) <= 0)
2475 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2476 obd->obd_requests_queued_for_recovery) <= 0)
2479 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2480 obd->obd_next_recovery_transno) <= 0)
2486 return min(count, len - (int)off);
2488 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2490 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
2491 int count, int *eof, void *data)
2493 struct obd_device *obd = (struct obd_device *)data;
2494 LASSERT(obd != NULL);
2496 return snprintf(page, count, "%d\n",
2497 obd->obd_recovery_ir_factor);
2499 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
2501 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
2502 unsigned long count, void *data)
2504 struct obd_device *obd = (struct obd_device *)data;
2506 LASSERT(obd != NULL);
2508 rc = lprocfs_write_helper(buffer, count, &val);
2512 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
2515 obd->obd_recovery_ir_factor = val;
2518 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
2520 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
2521 int count, int *eof, void *data)
2523 struct obd_device *obd = (struct obd_device *)data;
2524 LASSERT(obd != NULL);
2526 return snprintf(page, count, "%d\n",
2527 obd->obd_recovery_timeout);
2529 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
2531 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
2532 unsigned long count, void *data)
2534 struct obd_device *obd = (struct obd_device *)data;
2536 LASSERT(obd != NULL);
2538 rc = lprocfs_write_helper(buffer, count, &val);
2542 obd->obd_recovery_timeout = val;
2545 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
2547 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
2548 int count, int *eof, void *data)
2550 struct obd_device *obd = data;
2551 LASSERT(obd != NULL);
2553 return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
2555 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
2557 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
2558 unsigned long count, void *data)
2560 struct obd_device *obd = data;
2562 LASSERT(obd != NULL);
2564 rc = lprocfs_write_helper(buffer, count, &val);
2568 obd->obd_recovery_time_hard = val;
2571 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
2573 int lprocfs_obd_rd_mntdev(char *page, char **start, off_t off,
2574 int count, int *eof, void *data)
2576 struct obd_device *obd = (struct obd_device *)data;
2578 LASSERT(obd != NULL);
2579 LASSERT(mnt_get_devname(obd->u.obt.obt_vfsmnt));
2581 return snprintf(page, count, "%s\n",
2582 mnt_get_devname(obd->u.obt.obt_vfsmnt));
2584 EXPORT_SYMBOL(lprocfs_obd_rd_mntdev);
2586 int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
2587 int count, int *eof, void *data)
2589 struct obd_device *dev = data;
2590 struct client_obd *cli = &dev->u.cli;
2593 client_obd_list_lock(&cli->cl_loi_list_lock);
2594 rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
2595 client_obd_list_unlock(&cli->cl_loi_list_lock);
2598 EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
2600 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
2601 int count, int *eof, void *data)
2603 struct obd_device *obd = (struct obd_device *)data;
2604 struct obd_device_target *target = &obd->u.obt;
2606 LASSERT(obd != NULL);
2607 LASSERT(target->obt_magic == OBT_MAGIC);
2609 return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
2611 EXPORT_SYMBOL(lprocfs_target_rd_instance);