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",
962 int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
967 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
969 ret += snprintf(page + ret, count - ret, "%s%s",
970 ret ? sep : "", obd_connect_names[i]);
972 if (flags & ~(mask - 1))
973 ret += snprintf(page + ret, count - ret,
974 "%sunknown flags "LPX64,
975 ret ? sep : "", flags & ~(mask - 1));
978 EXPORT_SYMBOL(obd_connect_flags2str);
980 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
981 int *eof, void *data)
983 struct lprocfs_counter ret;
984 struct obd_device *obd = (struct obd_device *)data;
985 struct obd_import *imp;
986 struct obd_import_conn *conn;
989 LASSERT(obd != NULL);
990 LPROCFS_CLIMP_CHECK(obd);
991 imp = obd->u.cli.cl_import;
994 i = snprintf(page, count,
1000 " connect_flags: [",
1003 ptlrpc_import_state_name(imp->imp_state),
1004 imp->imp_connect_data.ocd_instance);
1005 i += obd_connect_flags2str(page + i, count - i,
1006 imp->imp_connect_data.ocd_connect_flags,
1008 i += snprintf(page + i, count - i,
1010 " import_flags: [");
1011 i += obd_import_flags2str(imp, page + i, count - i);
1013 i += snprintf(page + i, count - i,
1016 " failover_nids: [");
1017 cfs_spin_lock(&imp->imp_lock);
1019 cfs_list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
1020 i += snprintf(page + i, count - i, "%s%s", j ? ", " : "",
1021 libcfs_nid2str(conn->oic_conn->c_peer.nid));
1024 i += snprintf(page + i, count - i,
1026 " current_connection: %s\n"
1027 " connection_attempts: %u\n"
1029 " in-progress_invalidations: %u\n",
1030 imp->imp_connection == NULL ? "<none>" :
1031 libcfs_nid2str(imp->imp_connection->c_peer.nid),
1033 imp->imp_generation,
1034 cfs_atomic_read(&imp->imp_inval_count));
1035 cfs_spin_unlock(&imp->imp_lock);
1037 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
1038 if (ret.lc_count != 0) {
1039 /* first argument to do_div MUST be __u64 */
1040 __u64 sum = ret.lc_sum;
1041 do_div(sum, ret.lc_count);
1045 i += snprintf(page + i, count - i,
1048 " unregistering: %u\n"
1050 " avg_waittime: "LPU64" %s\n",
1051 cfs_atomic_read(&imp->imp_inflight),
1052 cfs_atomic_read(&imp->imp_unregistering),
1053 cfs_atomic_read(&imp->imp_timeouts),
1054 ret.lc_sum, ret.lc_units);
1057 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
1058 if (imp->imp_at.iat_portal[j] == 0)
1060 k = max_t(unsigned int, k,
1061 at_get(&imp->imp_at.iat_service_estimate[j]));
1063 i += snprintf(page + i, count - i,
1064 " service_estimates:\n"
1065 " services: %u sec\n"
1066 " network: %u sec\n",
1068 at_get(&imp->imp_at.iat_net_latency));
1070 i += snprintf(page + i, count - i,
1072 " last_replay: "LPU64"\n"
1073 " peer_committed: "LPU64"\n"
1074 " last_checked: "LPU64"\n",
1075 imp->imp_last_replay_transno,
1076 imp->imp_peer_committed_transno,
1077 imp->imp_last_transno_checked);
1079 /* avg data rates */
1080 for (rw = 0; rw <= 1; rw++) {
1081 lprocfs_stats_collect(obd->obd_svc_stats,
1082 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
1084 if (ret.lc_sum > 0 && ret.lc_count > 0) {
1085 /* first argument to do_div MUST be __u64 */
1086 __u64 sum = ret.lc_sum;
1087 do_div(sum, ret.lc_count);
1089 i += snprintf(page + i, count - i,
1090 " %s_data_averages:\n"
1091 " bytes_per_rpc: "LPU64"\n",
1092 rw ? "write" : "read",
1095 k = (int)ret.lc_sum;
1096 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
1097 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
1098 if (ret.lc_sum > 0 && ret.lc_count != 0) {
1099 /* first argument to do_div MUST be __u64 */
1100 __u64 sum = ret.lc_sum;
1101 do_div(sum, ret.lc_count);
1103 i += snprintf(page + i, count - i,
1104 " %s_per_rpc: "LPU64"\n",
1105 ret.lc_units, ret.lc_sum);
1106 j = (int)ret.lc_sum;
1108 i += snprintf(page + i, count - i,
1109 " MB_per_sec: %u.%.02u\n",
1110 k / j, (100 * k / j) % 100);
1114 LPROCFS_CLIMP_EXIT(obd);
1117 EXPORT_SYMBOL(lprocfs_rd_import);
1119 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
1120 int *eof, void *data)
1122 struct obd_device *obd = (struct obd_device *)data;
1123 struct obd_import *imp;
1126 LASSERT(obd != NULL);
1127 LPROCFS_CLIMP_CHECK(obd);
1128 imp = obd->u.cli.cl_import;
1131 i = snprintf(page, count, "current_state: %s\n",
1132 ptlrpc_import_state_name(imp->imp_state));
1133 i += snprintf(page + i, count - i,
1134 "state_history:\n");
1135 k = imp->imp_state_hist_idx;
1136 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
1137 struct import_state_hist *ish =
1138 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
1139 if (ish->ish_state == 0)
1141 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
1143 ptlrpc_import_state_name(ish->ish_state));
1146 LPROCFS_CLIMP_EXIT(obd);
1149 EXPORT_SYMBOL(lprocfs_rd_state);
1151 int lprocfs_at_hist_helper(char *page, int count, int rc,
1152 struct adaptive_timeout *at)
1155 for (i = 0; i < AT_BINS; i++)
1156 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
1157 rc += snprintf(page + rc, count - rc, "\n");
1160 EXPORT_SYMBOL(lprocfs_at_hist_helper);
1162 /* See also ptlrpc_lprocfs_rd_timeouts */
1163 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
1164 int *eof, void *data)
1166 struct obd_device *obd = (struct obd_device *)data;
1167 struct obd_import *imp;
1168 unsigned int cur, worst;
1173 LASSERT(obd != NULL);
1174 LPROCFS_CLIMP_CHECK(obd);
1175 imp = obd->u.cli.cl_import;
1178 now = cfs_time_current_sec();
1180 /* Some network health info for kicks */
1181 s2dhms(&ts, now - imp->imp_last_reply_time);
1182 rc += snprintf(page + rc, count - rc,
1183 "%-10s : %ld, "DHMS_FMT" ago\n",
1184 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
1186 cur = at_get(&imp->imp_at.iat_net_latency);
1187 worst = imp->imp_at.iat_net_latency.at_worst_ever;
1188 worstt = imp->imp_at.iat_net_latency.at_worst_time;
1189 s2dhms(&ts, now - worstt);
1190 rc += snprintf(page + rc, count - rc,
1191 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
1192 "network", cur, worst, worstt, DHMS_VARS(&ts));
1193 rc = lprocfs_at_hist_helper(page, count, rc,
1194 &imp->imp_at.iat_net_latency);
1196 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
1197 if (imp->imp_at.iat_portal[i] == 0)
1199 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
1200 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
1201 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
1202 s2dhms(&ts, now - worstt);
1203 rc += snprintf(page + rc, count - rc,
1204 "portal %-2d : cur %3u worst %3u (at %ld, "
1205 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
1206 cur, worst, worstt, DHMS_VARS(&ts));
1207 rc = lprocfs_at_hist_helper(page, count, rc,
1208 &imp->imp_at.iat_service_estimate[i]);
1211 LPROCFS_CLIMP_EXIT(obd);
1214 EXPORT_SYMBOL(lprocfs_rd_timeouts);
1216 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1217 int count, int *eof, void *data)
1219 struct obd_device *obd = data;
1223 LPROCFS_CLIMP_CHECK(obd);
1224 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1225 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1226 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1227 ret += snprintf(page + ret, count - ret, "\n");
1228 LPROCFS_CLIMP_EXIT(obd);
1231 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1233 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1234 int *eof, void *data)
1236 struct obd_device *obd = data;
1238 LASSERT(obd != NULL);
1240 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1242 EXPORT_SYMBOL(lprocfs_rd_num_exports);
1244 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1245 int *eof, void *data)
1247 struct obd_type *class = (struct obd_type*) data;
1249 LASSERT(class != NULL);
1251 return snprintf(page, count, "%d\n", class->typ_refcnt);
1253 EXPORT_SYMBOL(lprocfs_rd_numrefs);
1255 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1259 LASSERT(obd != NULL);
1260 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1261 LASSERT(obd->obd_type->typ_procroot != NULL);
1263 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1264 obd->obd_type->typ_procroot,
1266 if (IS_ERR(obd->obd_proc_entry)) {
1267 rc = PTR_ERR(obd->obd_proc_entry);
1268 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1269 obd->obd_proc_entry = NULL;
1273 EXPORT_SYMBOL(lprocfs_obd_setup);
1275 int lprocfs_obd_cleanup(struct obd_device *obd)
1279 if (obd->obd_proc_exports_entry) {
1280 /* Should be no exports left */
1281 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1282 lprocfs_remove(&obd->obd_proc_exports_entry);
1283 obd->obd_proc_exports_entry = NULL;
1285 if (obd->obd_proc_entry) {
1286 lprocfs_remove(&obd->obd_proc_entry);
1287 obd->obd_proc_entry = NULL;
1291 EXPORT_SYMBOL(lprocfs_obd_cleanup);
1293 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1295 CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
1296 client_stat->nid_proc, client_stat->nid_stats,
1297 client_stat->nid_brw_stats);
1299 LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
1300 "nid %s:count %d\n", libcfs_nid2str(client_stat->nid),
1301 atomic_read(&client_stat->nid_exp_ref_count));
1303 if (client_stat->nid_proc)
1304 lprocfs_remove(&client_stat->nid_proc);
1306 if (client_stat->nid_stats)
1307 lprocfs_free_stats(&client_stat->nid_stats);
1309 if (client_stat->nid_brw_stats)
1310 OBD_FREE_PTR(client_stat->nid_brw_stats);
1312 if (client_stat->nid_ldlm_stats)
1313 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1315 OBD_FREE_PTR(client_stat);
1320 void lprocfs_free_per_client_stats(struct obd_device *obd)
1322 cfs_hash_t *hash = obd->obd_nid_stats_hash;
1323 struct nid_stat *stat;
1326 /* we need extra list - because hash_exit called to early */
1327 /* not need locking because all clients is died */
1328 while (!cfs_list_empty(&obd->obd_nid_stats)) {
1329 stat = cfs_list_entry(obd->obd_nid_stats.next,
1330 struct nid_stat, nid_list);
1331 cfs_list_del_init(&stat->nid_list);
1332 cfs_hash_del(hash, &stat->nid, &stat->nid_hash);
1333 lprocfs_free_client_stats(stat);
1337 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
1339 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1340 enum lprocfs_stats_flags flags)
1342 struct lprocfs_stats *stats;
1343 unsigned int percpusize;
1344 unsigned int num_entry;
1349 if (lprocfs_no_percpu_stats != 0)
1350 flags |= LPROCFS_STATS_FLAG_NOPERCPU;
1352 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1355 num_entry = cfs_num_possible_cpus() + 1;
1357 /* alloc percpu pointers for all possible cpu slots */
1358 OBD_ALLOC(stats, offsetof(struct lprocfs_stats, ls_percpu[num_entry]));
1362 stats->ls_num = num;
1363 stats->ls_biggest_alloc_num = 1;
1364 stats->ls_flags = flags;
1365 cfs_spin_lock_init(&stats->ls_lock);
1367 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
1369 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1371 /* for no percpu area, the 0th entry is for real use,
1372 * for percpu area, the 0th entry is for intialized entry template */
1373 OBD_ALLOC(stats->ls_percpu[0], percpusize);
1374 if (stats->ls_percpu[0] == NULL) {
1376 offsetof(struct lprocfs_stats, ls_percpu[num_entry]));
1381 EXPORT_SYMBOL(lprocfs_alloc_stats);
1383 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1385 struct lprocfs_stats *stats = *statsh;
1386 unsigned int num_entry;
1387 unsigned int percpusize;
1390 if (stats == NULL || stats->ls_num == 0)
1394 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1397 num_entry = cfs_num_possible_cpus() + 1;
1399 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
1401 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1402 for (i = 0; i < num_entry; i++)
1403 if (stats->ls_percpu[i] != NULL)
1404 OBD_FREE(stats->ls_percpu[i], percpusize);
1405 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1407 EXPORT_SYMBOL(lprocfs_free_stats);
1409 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1411 struct lprocfs_counter *percpu_cntr;
1414 unsigned int num_entry;
1415 unsigned long flags = 0;
1417 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1419 for (i = 0; i < num_entry; i++) {
1420 if (stats->ls_percpu[i] == NULL)
1422 for (j = 0; j < stats->ls_num; j++) {
1423 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
1424 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_entry);
1425 percpu_cntr->lc_count = 0;
1426 percpu_cntr->lc_sum = 0;
1427 percpu_cntr->lc_min = LC_MIN_INIT;
1428 percpu_cntr->lc_max = 0;
1429 percpu_cntr->lc_sumsquare = 0;
1430 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_exit);
1434 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1436 EXPORT_SYMBOL(lprocfs_clear_stats);
1438 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1439 size_t len, loff_t *off)
1441 struct seq_file *seq = file->private_data;
1442 struct lprocfs_stats *stats = seq->private;
1444 lprocfs_clear_stats(stats);
1449 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1451 struct lprocfs_stats *stats = p->private;
1452 /* return 1st cpu location */
1453 return (*pos >= stats->ls_num) ? NULL :
1454 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1457 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1461 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1463 struct lprocfs_stats *stats = p->private;
1465 return (*pos >= stats->ls_num) ? NULL :
1466 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1469 /* seq file export of one lprocfs counter */
1470 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1472 struct lprocfs_stats *stats = p->private;
1473 struct lprocfs_counter *cntr = v;
1474 struct lprocfs_counter ret;
1477 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
1479 cfs_gettimeofday(&now);
1480 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1481 "snapshot_time", now.tv_sec, now.tv_usec);
1485 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
1487 lprocfs_stats_collect(stats, idx, &ret);
1489 if (ret.lc_count == 0)
1492 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", cntr->lc_name,
1493 ret.lc_count, cntr->lc_units);
1498 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
1499 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1500 ret.lc_min, ret.lc_max, ret.lc_sum);
1503 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
1504 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1508 rc = seq_printf(p, "\n");
1510 return (rc < 0) ? rc : 0;
1513 struct seq_operations lprocfs_stats_seq_sops = {
1514 start: lprocfs_stats_seq_start,
1515 stop: lprocfs_stats_seq_stop,
1516 next: lprocfs_stats_seq_next,
1517 show: lprocfs_stats_seq_show,
1520 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1522 struct proc_dir_entry *dp = PDE(inode);
1523 struct seq_file *seq;
1526 if (LPROCFS_ENTRY_AND_CHECK(dp))
1529 rc = seq_open(file, &lprocfs_stats_seq_sops);
1534 seq = file->private_data;
1535 seq->private = dp->data;
1539 struct file_operations lprocfs_stats_seq_fops = {
1540 .owner = THIS_MODULE,
1541 .open = lprocfs_stats_seq_open,
1543 .write = lprocfs_stats_seq_write,
1544 .llseek = seq_lseek,
1545 .release = lprocfs_seq_release,
1548 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1549 struct lprocfs_stats *stats)
1551 struct proc_dir_entry *entry;
1552 LASSERT(root != NULL);
1554 LPROCFS_WRITE_ENTRY();
1555 entry = create_proc_entry(name, 0644, root);
1557 entry->proc_fops = &lprocfs_stats_seq_fops;
1558 entry->data = stats;
1561 LPROCFS_WRITE_EXIT();
1568 EXPORT_SYMBOL(lprocfs_register_stats);
1570 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1571 unsigned conf, const char *name, const char *units)
1573 struct lprocfs_counter *c = &(stats->ls_percpu[0]->lp_cntr[index]);
1574 unsigned long flags = 0;
1576 LASSERT(stats != NULL);
1577 LASSERT(stats->ls_percpu[0] != NULL);
1579 lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1580 c->lc_config = conf;
1583 c->lc_min = LC_MIN_INIT;
1586 c->lc_units = units;
1587 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1589 EXPORT_SYMBOL(lprocfs_counter_init);
1591 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1593 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1594 LASSERT(coffset < stats->ls_num); \
1595 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1598 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1600 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1601 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1602 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1603 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1604 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1605 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1606 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1607 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1608 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1609 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1610 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1611 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1612 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1613 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1614 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1615 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1616 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1617 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1618 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
1619 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1620 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1621 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1622 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1623 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1624 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1625 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1626 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1627 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1628 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1629 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1630 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1631 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1632 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1633 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1634 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1635 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1636 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1637 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1638 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1639 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1640 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1641 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1642 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1643 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1644 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
1645 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1646 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1647 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1648 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1649 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1650 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1651 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1652 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1653 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1654 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1655 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1656 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1657 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1658 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1659 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1660 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1661 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quota_adjust_qunit);
1662 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1663 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1664 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1665 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1666 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1667 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1668 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1670 EXPORT_SYMBOL(lprocfs_init_ops_stats);
1672 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1674 struct lprocfs_stats *stats;
1675 unsigned int num_stats;
1678 LASSERT(obd->obd_stats == NULL);
1679 LASSERT(obd->obd_proc_entry != NULL);
1680 LASSERT(obd->obd_cntr_base == 0);
1682 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1683 num_private_stats - 1 /* o_owner */;
1684 stats = lprocfs_alloc_stats(num_stats, 0);
1688 lprocfs_init_ops_stats(num_private_stats, stats);
1690 for (i = num_private_stats; i < num_stats; i++) {
1691 /* If this LBUGs, it is likely that an obd
1692 * operation was added to struct obd_ops in
1693 * <obd.h>, and that the corresponding line item
1694 * LPROCFS_OBD_OP_INIT(.., .., opname)
1695 * is missing from the list above. */
1696 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1697 "Missing obd_stat initializer obd_op "
1698 "operation at offset %d.\n", i - num_private_stats);
1700 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1702 lprocfs_free_stats(&stats);
1704 obd->obd_stats = stats;
1705 obd->obd_cntr_base = num_private_stats;
1709 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
1711 void lprocfs_free_obd_stats(struct obd_device *obd)
1714 lprocfs_free_stats(&obd->obd_stats);
1716 EXPORT_SYMBOL(lprocfs_free_obd_stats);
1718 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1720 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1721 LASSERT(coffset < stats->ls_num); \
1722 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1725 void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats)
1727 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1728 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1729 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
1730 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1731 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1732 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1733 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1734 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1735 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1736 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1737 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1738 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1739 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1740 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1741 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1742 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1743 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1744 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1745 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1746 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1747 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1748 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1749 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1750 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1751 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1752 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1753 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1754 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1755 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1756 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1757 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1758 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1760 EXPORT_SYMBOL(lprocfs_init_mps_stats);
1762 int lprocfs_alloc_md_stats(struct obd_device *obd,
1763 unsigned num_private_stats)
1765 struct lprocfs_stats *stats;
1766 unsigned int num_stats;
1769 LASSERT(obd->md_stats == NULL);
1770 LASSERT(obd->obd_proc_entry != NULL);
1771 LASSERT(obd->md_cntr_base == 0);
1773 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1775 stats = lprocfs_alloc_stats(num_stats, 0);
1779 lprocfs_init_mps_stats(num_private_stats, stats);
1781 for (i = num_private_stats; i < num_stats; i++) {
1782 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1783 CERROR("Missing md_stat initializer md_op "
1784 "operation at offset %d. Aborting.\n",
1785 i - num_private_stats);
1789 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1791 lprocfs_free_stats(&stats);
1793 obd->md_stats = stats;
1794 obd->md_cntr_base = num_private_stats;
1798 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
1800 void lprocfs_free_md_stats(struct obd_device *obd)
1802 struct lprocfs_stats *stats = obd->md_stats;
1804 if (stats != NULL) {
1805 obd->md_stats = NULL;
1806 obd->md_cntr_base = 0;
1807 lprocfs_free_stats(&stats);
1810 EXPORT_SYMBOL(lprocfs_free_md_stats);
1812 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1814 lprocfs_counter_init(ldlm_stats,
1815 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1816 0, "ldlm_enqueue", "reqs");
1817 lprocfs_counter_init(ldlm_stats,
1818 LDLM_CONVERT - LDLM_FIRST_OPC,
1819 0, "ldlm_convert", "reqs");
1820 lprocfs_counter_init(ldlm_stats,
1821 LDLM_CANCEL - LDLM_FIRST_OPC,
1822 0, "ldlm_cancel", "reqs");
1823 lprocfs_counter_init(ldlm_stats,
1824 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1825 0, "ldlm_bl_callback", "reqs");
1826 lprocfs_counter_init(ldlm_stats,
1827 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1828 0, "ldlm_cp_callback", "reqs");
1829 lprocfs_counter_init(ldlm_stats,
1830 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1831 0, "ldlm_gl_callback", "reqs");
1833 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
1835 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1836 int *eof, void *data)
1838 struct obd_export *exp = data;
1839 LASSERT(exp != NULL);
1841 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1844 struct exp_uuid_cb_data {
1852 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1853 int count, int *eof, int *len)
1855 cb_data->page = page;
1856 cb_data->count = count;
1861 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1862 cfs_hlist_node_t *hnode, void *cb_data)
1865 struct obd_export *exp = cfs_hash_object(hs, hnode);
1866 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1868 if (exp->exp_nid_stats)
1869 *data->len += snprintf((data->page + *data->len),
1870 data->count, "%s\n",
1871 obd_uuid2str(&exp->exp_client_uuid));
1875 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1876 int *eof, void *data)
1878 struct nid_stat *stats = (struct nid_stat *)data;
1879 struct exp_uuid_cb_data cb_data;
1880 struct obd_device *obd = stats->nid_obd;
1885 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1886 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1887 lprocfs_exp_print_uuid, &cb_data);
1888 return (*cb_data.len);
1891 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1892 cfs_hlist_node_t *hnode, void *cb_data)
1895 struct exp_uuid_cb_data *data = cb_data;
1896 struct obd_export *exp = cfs_hash_object(hs, hnode);
1898 if (exp->exp_lock_hash != NULL) {
1900 *data->len += cfs_hash_debug_header(data->page,
1903 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1910 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1911 int *eof, void *data)
1913 struct nid_stat *stats = (struct nid_stat *)data;
1914 struct exp_uuid_cb_data cb_data;
1915 struct obd_device *obd = stats->nid_obd;
1920 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1922 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1923 lprocfs_exp_print_hash, &cb_data);
1924 return (*cb_data.len);
1927 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1928 int count, int *eof, void *data)
1931 return snprintf(page, count, "%s\n",
1932 "Write into this file to clear all nid stats and "
1933 "stale nid entries");
1935 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1937 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1939 struct nid_stat *stat = obj;
1943 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
1944 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 1) {
1945 /* object has only hash references. */
1946 cfs_spin_lock(&stat->nid_obd->obd_nid_lock);
1947 cfs_list_move(&stat->nid_list, data);
1948 cfs_spin_unlock(&stat->nid_obd->obd_nid_lock);
1951 /* we has reference to object - only clear data*/
1952 if (stat->nid_stats)
1953 lprocfs_clear_stats(stat->nid_stats);
1955 if (stat->nid_brw_stats) {
1956 for (i = 0; i < BRW_LAST; i++)
1957 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
1962 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1963 unsigned long count, void *data)
1965 struct obd_device *obd = (struct obd_device *)data;
1966 struct nid_stat *client_stat;
1967 CFS_LIST_HEAD(free_list);
1969 cfs_hash_cond_del(obd->obd_nid_stats_hash,
1970 lprocfs_nid_stats_clear_write_cb, &free_list);
1972 while (!cfs_list_empty(&free_list)) {
1973 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
1975 cfs_list_del_init(&client_stat->nid_list);
1976 lprocfs_free_client_stats(client_stat);
1981 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1983 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1985 struct nid_stat *new_stat, *old_stat;
1986 struct obd_device *obd = NULL;
1987 cfs_proc_dir_entry_t *entry;
1988 char *buffer = NULL;
1994 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1995 !exp->exp_obd->obd_nid_stats_hash)
1998 /* not test against zero because eric say:
1999 * You may only test nid against another nid, or LNET_NID_ANY.
2000 * Anything else is nonsense.*/
2001 if (!nid || *nid == LNET_NID_ANY)
2006 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
2008 OBD_ALLOC_PTR(new_stat);
2009 if (new_stat == NULL)
2012 new_stat->nid = *nid;
2013 new_stat->nid_obd = exp->exp_obd;
2014 /* we need set default refcount to 1 to balance obd_disconnect */
2015 cfs_atomic_set(&new_stat->nid_exp_ref_count, 1);
2017 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
2018 nid, &new_stat->nid_hash);
2019 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
2020 old_stat, libcfs_nid2str(*nid),
2021 cfs_atomic_read(&new_stat->nid_exp_ref_count));
2023 /* We need to release old stats because lprocfs_exp_cleanup() hasn't
2024 * been and will never be called. */
2025 if (exp->exp_nid_stats) {
2026 nidstat_putref(exp->exp_nid_stats);
2027 exp->exp_nid_stats = NULL;
2030 /* Return -EALREADY here so that we know that the /proc
2031 * entry already has been created */
2032 if (old_stat != new_stat) {
2033 exp->exp_nid_stats = old_stat;
2034 GOTO(destroy_new, rc = -EALREADY);
2036 /* not found - create */
2037 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
2039 GOTO(destroy_new, rc = -ENOMEM);
2041 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
2042 new_stat->nid_proc = lprocfs_register(buffer,
2043 obd->obd_proc_exports_entry,
2045 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
2047 if (new_stat->nid_proc == NULL) {
2048 CERROR("Error making export directory for nid %s\n",
2049 libcfs_nid2str(*nid));
2050 GOTO(destroy_new_ns, rc = -ENOMEM);
2053 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
2054 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
2055 if (IS_ERR(entry)) {
2056 CWARN("Error adding the NID stats file\n");
2057 rc = PTR_ERR(entry);
2058 GOTO(destroy_new_ns, rc);
2061 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
2062 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
2063 if (IS_ERR(entry)) {
2064 CWARN("Error adding the hash file\n");
2065 rc = PTR_ERR(entry);
2066 GOTO(destroy_new_ns, rc);
2069 exp->exp_nid_stats = new_stat;
2071 /* protect competitive add to list, not need locking on destroy */
2072 cfs_spin_lock(&obd->obd_nid_lock);
2073 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
2074 cfs_spin_unlock(&obd->obd_nid_lock);
2079 if (new_stat->nid_proc != NULL)
2080 lprocfs_remove(&new_stat->nid_proc);
2081 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
2084 nidstat_putref(new_stat);
2085 OBD_FREE_PTR(new_stat);
2088 EXPORT_SYMBOL(lprocfs_exp_setup);
2090 int lprocfs_exp_cleanup(struct obd_export *exp)
2092 struct nid_stat *stat = exp->exp_nid_stats;
2094 if(!stat || !exp->exp_obd)
2097 nidstat_putref(exp->exp_nid_stats);
2098 exp->exp_nid_stats = NULL;
2102 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2104 int lprocfs_write_helper(const char *buffer, unsigned long count,
2107 return lprocfs_write_frac_helper(buffer, count, val, 1);
2109 EXPORT_SYMBOL(lprocfs_write_helper);
2111 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
2114 char kernbuf[20], *end, *pbuf;
2116 if (count > (sizeof(kernbuf) - 1))
2119 if (cfs_copy_from_user(kernbuf, buffer, count))
2122 kernbuf[count] = '\0';
2129 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2133 if (end != NULL && *end == '.') {
2134 int temp_val, pow = 1;
2138 if (strlen(pbuf) > 5)
2139 pbuf[5] = '\0'; /*only allow 5bits fractional*/
2141 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2144 for (i = 0; i < (end - pbuf); i++)
2147 *val += temp_val / pow;
2152 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2154 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
2157 long decimal_val, frac_val;
2163 decimal_val = val / mult;
2164 prtn = snprintf(buffer, count, "%ld", decimal_val);
2165 frac_val = val % mult;
2167 if (prtn < (count - 4) && frac_val > 0) {
2169 int i, temp_mult = 1, frac_bits = 0;
2171 temp_frac = frac_val * 10;
2172 buffer[prtn++] = '.';
2173 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
2174 /* only reserved 2 bits fraction */
2175 buffer[prtn++] ='0';
2180 * Need to think these cases :
2181 * 1. #echo x.00 > /proc/xxx output result : x
2182 * 2. #echo x.0x > /proc/xxx output result : x.0x
2183 * 3. #echo x.x0 > /proc/xxx output result : x.x
2184 * 4. #echo x.xx > /proc/xxx output result : x.xx
2185 * Only reserved 2 bits fraction.
2187 for (i = 0; i < (5 - prtn); i++)
2190 frac_bits = min((int)count - prtn, 3 - frac_bits);
2191 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
2192 frac_val * temp_mult / mult);
2195 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
2197 if (buffer[prtn] == '.') {
2204 buffer[prtn++] ='\n';
2207 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2209 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
2211 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
2213 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2215 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
2216 __u64 *val, int mult)
2218 char kernbuf[22], *end, *pbuf;
2219 __u64 whole, frac = 0, units;
2220 unsigned frac_d = 1;
2222 if (count > (sizeof(kernbuf) - 1))
2225 if (cfs_copy_from_user(kernbuf, buffer, count))
2228 kernbuf[count] = '\0';
2235 whole = simple_strtoull(pbuf, &end, 10);
2239 if (end != NULL && *end == '.') {
2243 /* need to limit frac_d to a __u32 */
2244 if (strlen(pbuf) > 10)
2247 frac = simple_strtoull(pbuf, &end, 10);
2248 /* count decimal places */
2249 for (i = 0; i < (end - pbuf); i++)
2266 /* Specified units override the multiplier */
2268 mult = mult < 0 ? -units : units;
2271 do_div(frac, frac_d);
2272 *val = whole * mult + frac;
2275 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2277 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent, char *name, mode_t mode,
2278 struct file_operations *seq_fops, void *data)
2280 struct proc_dir_entry *entry;
2283 LPROCFS_WRITE_ENTRY();
2284 entry = create_proc_entry(name, mode, parent);
2286 entry->proc_fops = seq_fops;
2289 LPROCFS_WRITE_EXIT();
2296 EXPORT_SYMBOL(lprocfs_seq_create);
2298 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
2300 struct file_operations *seq_fops,
2303 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2304 mode, seq_fops, data));
2306 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2308 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2310 if (value >= OBD_HIST_MAX)
2311 value = OBD_HIST_MAX - 1;
2313 cfs_spin_lock(&oh->oh_lock);
2314 oh->oh_buckets[value]++;
2315 cfs_spin_unlock(&oh->oh_lock);
2317 EXPORT_SYMBOL(lprocfs_oh_tally);
2319 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2323 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2326 lprocfs_oh_tally(oh, val);
2328 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2330 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2332 unsigned long ret = 0;
2335 for (i = 0; i < OBD_HIST_MAX; i++)
2336 ret += oh->oh_buckets[i];
2339 EXPORT_SYMBOL(lprocfs_oh_sum);
2341 void lprocfs_oh_clear(struct obd_histogram *oh)
2343 cfs_spin_lock(&oh->oh_lock);
2344 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2345 cfs_spin_unlock(&oh->oh_lock);
2347 EXPORT_SYMBOL(lprocfs_oh_clear);
2349 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2350 int count, int *eof, void *data)
2352 struct obd_device *obd = data;
2358 c += cfs_hash_debug_header(page, count);
2359 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2360 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2361 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2362 #ifdef HAVE_QUOTA_SUPPORT
2363 if (obd->u.obt.obt_qctxt.lqc_lqs_hash)
2364 c += cfs_hash_debug_str(obd->u.obt.obt_qctxt.lqc_lqs_hash,
2365 page + c, count - c);
2370 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2372 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2373 int count, int *eof, void *data)
2375 struct obd_device *obd = data;
2378 LASSERT(obd != NULL);
2379 LASSERT(count >= 0);
2381 /* Set start of user data returned to
2382 page + off since the user may have
2383 requested to read much smaller than
2384 what we need to read */
2385 *start = page + off;
2387 /* We know we are allocated a page here.
2388 Also we know that this function will
2389 not need to write more than a page
2390 so we can truncate at CFS_PAGE_SIZE. */
2391 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2393 /* Initialize the page */
2394 memset(page, 0, size);
2396 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2398 if (obd->obd_max_recoverable_clients == 0) {
2399 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2405 /* sampled unlocked, but really... */
2406 if (obd->obd_recovering == 0) {
2407 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2409 if (lprocfs_obd_snprintf(&page, size, &len,
2410 "recovery_start: %lu\n",
2411 obd->obd_recovery_start) <= 0)
2413 if (lprocfs_obd_snprintf(&page, size, &len,
2414 "recovery_duration: %lu\n",
2415 obd->obd_recovery_end -
2416 obd->obd_recovery_start) <= 0)
2418 /* Number of clients that have completed recovery */
2419 if (lprocfs_obd_snprintf(&page, size, &len,
2420 "completed_clients: %d/%d\n",
2421 obd->obd_max_recoverable_clients -
2422 obd->obd_stale_clients,
2423 obd->obd_max_recoverable_clients) <= 0)
2425 if (lprocfs_obd_snprintf(&page, size, &len,
2426 "replayed_requests: %d\n",
2427 obd->obd_replayed_requests) <= 0)
2429 if (lprocfs_obd_snprintf(&page, size, &len,
2430 "last_transno: "LPD64"\n",
2431 obd->obd_next_recovery_transno - 1)<=0)
2433 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2434 obd->obd_version_recov ?
2435 "ENABLED" : "DISABLED") <=0)
2437 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
2439 "DISABLED" : "ENABLED") <= 0)
2444 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2446 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2447 obd->obd_recovery_start) <= 0)
2449 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2450 cfs_time_current_sec() >=
2451 obd->obd_recovery_start +
2452 obd->obd_recovery_timeout ? 0 :
2453 obd->obd_recovery_start +
2454 obd->obd_recovery_timeout -
2455 cfs_time_current_sec()) <= 0)
2457 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2458 cfs_atomic_read(&obd->obd_connected_clients),
2459 obd->obd_max_recoverable_clients) <= 0)
2461 /* Number of clients that have completed recovery */
2462 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2463 cfs_atomic_read(&obd->obd_req_replay_clients))
2466 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2467 cfs_atomic_read(&obd->obd_lock_replay_clients))
2470 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2471 cfs_atomic_read(&obd->obd_connected_clients) -
2472 cfs_atomic_read(&obd->obd_lock_replay_clients))
2475 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2476 obd->obd_stale_clients) <= 0)
2478 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2479 obd->obd_replayed_requests) <= 0)
2481 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2482 obd->obd_requests_queued_for_recovery) <= 0)
2485 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2486 obd->obd_next_recovery_transno) <= 0)
2492 return min(count, len - (int)off);
2494 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2496 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
2497 int count, int *eof, void *data)
2499 struct obd_device *obd = (struct obd_device *)data;
2500 LASSERT(obd != NULL);
2502 return snprintf(page, count, "%d\n",
2503 obd->obd_recovery_ir_factor);
2505 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
2507 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
2508 unsigned long count, void *data)
2510 struct obd_device *obd = (struct obd_device *)data;
2512 LASSERT(obd != NULL);
2514 rc = lprocfs_write_helper(buffer, count, &val);
2518 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
2521 obd->obd_recovery_ir_factor = val;
2524 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
2526 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
2527 int count, int *eof, void *data)
2529 struct obd_device *obd = (struct obd_device *)data;
2530 LASSERT(obd != NULL);
2532 return snprintf(page, count, "%d\n",
2533 obd->obd_recovery_timeout);
2535 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
2537 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
2538 unsigned long count, void *data)
2540 struct obd_device *obd = (struct obd_device *)data;
2542 LASSERT(obd != NULL);
2544 rc = lprocfs_write_helper(buffer, count, &val);
2548 obd->obd_recovery_timeout = val;
2551 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
2553 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
2554 int count, int *eof, void *data)
2556 struct obd_device *obd = data;
2557 LASSERT(obd != NULL);
2559 return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
2561 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
2563 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
2564 unsigned long count, void *data)
2566 struct obd_device *obd = data;
2568 LASSERT(obd != NULL);
2570 rc = lprocfs_write_helper(buffer, count, &val);
2574 obd->obd_recovery_time_hard = val;
2577 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
2579 int lprocfs_obd_rd_mntdev(char *page, char **start, off_t off,
2580 int count, int *eof, void *data)
2582 struct obd_device *obd = (struct obd_device *)data;
2584 LASSERT(obd != NULL);
2585 LASSERT(mnt_get_devname(obd->u.obt.obt_vfsmnt));
2587 return snprintf(page, count, "%s\n",
2588 mnt_get_devname(obd->u.obt.obt_vfsmnt));
2590 EXPORT_SYMBOL(lprocfs_obd_rd_mntdev);
2592 int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
2593 int count, int *eof, void *data)
2595 struct obd_device *dev = data;
2596 struct client_obd *cli = &dev->u.cli;
2599 client_obd_list_lock(&cli->cl_loi_list_lock);
2600 rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
2601 client_obd_list_unlock(&cli->cl_loi_list_lock);
2604 EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
2606 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
2607 int count, int *eof, void *data)
2609 struct obd_device *obd = (struct obd_device *)data;
2610 struct obd_device_target *target = &obd->u.obt;
2612 LASSERT(obd != NULL);
2613 LASSERT(target->obt_magic == OBT_MAGIC);
2615 return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
2617 EXPORT_SYMBOL(lprocfs_target_rd_instance);