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, 2012, Intel Corporation.
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_disk.h>
52 #include <lustre/lustre_idl.h>
53 #include <dt_object.h>
57 static int lprocfs_no_percpu_stats = 0;
58 CFS_MODULE_PARM(lprocfs_no_percpu_stats, "i", int, 0644,
59 "Do not alloc percpu data for lprocfs stats");
61 #define MAX_STRING_SIZE 128
63 /* for bug 10866, global variable */
64 DECLARE_RWSEM(_lprocfs_lock);
65 EXPORT_SYMBOL(_lprocfs_lock);
67 int lprocfs_single_release(struct inode *inode, struct file *file)
70 return single_release(inode, file);
72 EXPORT_SYMBOL(lprocfs_single_release);
74 int lprocfs_seq_release(struct inode *inode, struct file *file)
77 return seq_release(inode, file);
79 EXPORT_SYMBOL(lprocfs_seq_release);
81 static struct proc_dir_entry *__lprocfs_srch(struct proc_dir_entry *head,
84 struct proc_dir_entry *temp;
90 while (temp != NULL) {
91 if (strcmp(temp->name, name) == 0) {
100 struct proc_dir_entry *lprocfs_srch(struct proc_dir_entry *head,
103 struct proc_dir_entry *temp;
105 LPROCFS_SRCH_ENTRY();
106 temp = __lprocfs_srch(head, name);
110 EXPORT_SYMBOL(lprocfs_srch);
112 /* lprocfs API calls */
114 /* Function that emulates snprintf but also has the side effect of advancing
115 the page pointer for the next write into the buffer, incrementing the total
116 length written to the buffer, and decrementing the size left in the
118 static int lprocfs_obd_snprintf(char **page, int end, int *len,
119 const char *format, ...)
127 va_start(list, format);
128 n = vsnprintf(*page, end - *len, format, list);
131 *page += n; *len += n;
135 cfs_proc_dir_entry_t *lprocfs_add_simple(struct proc_dir_entry *root,
137 read_proc_t *read_proc,
138 write_proc_t *write_proc,
140 struct file_operations *fops)
142 cfs_proc_dir_entry_t *proc;
145 if (root == NULL || name == NULL)
146 return ERR_PTR(-EINVAL);
153 LPROCFS_WRITE_ENTRY();
154 proc = create_proc_entry(name, mode, root);
156 CERROR("LprocFS: No memory to create /proc entry %s", name);
157 LPROCFS_WRITE_EXIT();
158 return ERR_PTR(-ENOMEM);
160 proc->read_proc = read_proc;
161 proc->write_proc = write_proc;
164 proc->proc_fops = fops;
165 LPROCFS_WRITE_EXIT();
168 EXPORT_SYMBOL(lprocfs_add_simple);
170 struct proc_dir_entry *lprocfs_add_symlink(const char *name,
171 struct proc_dir_entry *parent, const char *format, ...)
173 struct proc_dir_entry *entry;
177 if (parent == NULL || format == NULL)
180 OBD_ALLOC_WAIT(dest, MAX_STRING_SIZE + 1);
184 va_start(ap, format);
185 vsnprintf(dest, MAX_STRING_SIZE, format, ap);
188 entry = proc_symlink(name, parent, dest);
190 CERROR("LprocFS: Could not create symbolic link from %s to %s",
193 OBD_FREE(dest, MAX_STRING_SIZE + 1);
196 EXPORT_SYMBOL(lprocfs_add_symlink);
198 static ssize_t lprocfs_fops_read(struct file *f, char __user *buf,
199 size_t size, loff_t *ppos)
201 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
202 char *page, *start = NULL;
203 int rc = 0, eof = 1, count;
205 if (*ppos >= CFS_PAGE_SIZE)
208 page = (char *)__get_free_page(GFP_KERNEL);
212 if (LPROCFS_ENTRY_AND_CHECK(dp)) {
217 OBD_FAIL_TIMEOUT(OBD_FAIL_LPROC_REMOVE, 10);
219 rc = dp->read_proc(page, &start, *ppos, CFS_PAGE_SIZE,
225 /* for lustre proc read, the read count must be less than PAGE_SIZE */
234 start = page + *ppos;
235 } else if (start < page) {
239 count = (rc < size) ? rc : size;
240 if (cfs_copy_to_user(buf, start, count)) {
247 free_page((unsigned long)page);
251 static ssize_t lprocfs_fops_write(struct file *f, const char __user *buf,
252 size_t size, loff_t *ppos)
254 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
257 if (LPROCFS_ENTRY_AND_CHECK(dp))
260 rc = dp->write_proc(f, buf, size, dp->data);
265 static struct file_operations lprocfs_generic_fops = {
266 .owner = THIS_MODULE,
267 .read = lprocfs_fops_read,
268 .write = lprocfs_fops_write,
271 int lprocfs_evict_client_open(struct inode *inode, struct file *f)
273 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
274 struct obd_device *obd = dp->data;
276 cfs_atomic_inc(&obd->obd_evict_inprogress);
281 int lprocfs_evict_client_release(struct inode *inode, struct file *f)
283 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
284 struct obd_device *obd = dp->data;
286 cfs_atomic_dec(&obd->obd_evict_inprogress);
287 cfs_waitq_signal(&obd->obd_evict_inprogress_waitq);
292 struct file_operations lprocfs_evict_client_fops = {
293 .owner = THIS_MODULE,
294 .read = lprocfs_fops_read,
295 .write = lprocfs_fops_write,
296 .open = lprocfs_evict_client_open,
297 .release = lprocfs_evict_client_release,
299 EXPORT_SYMBOL(lprocfs_evict_client_fops);
304 * \param root [in] The parent proc entry on which new entry will be added.
305 * \param list [in] Array of proc entries to be added.
306 * \param data [in] The argument to be passed when entries read/write routines
307 * are called through /proc file.
309 * \retval 0 on success
312 int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list,
317 if (root == NULL || list == NULL)
320 LPROCFS_WRITE_ENTRY();
321 while (list->name != NULL) {
322 struct proc_dir_entry *cur_root, *proc;
323 char *pathcopy, *cur, *next, pathbuf[64];
324 int pathsize = strlen(list->name) + 1;
329 /* need copy of path for strsep */
330 if (strlen(list->name) > sizeof(pathbuf) - 1) {
331 OBD_ALLOC(pathcopy, pathsize);
332 if (pathcopy == NULL)
333 GOTO(out, rc = -ENOMEM);
339 strcpy(pathcopy, list->name);
341 while (cur_root != NULL && (cur = strsep(&next, "/"))) {
342 if (*cur =='\0') /* skip double/trailing "/" */
345 proc = __lprocfs_srch(cur_root, cur);
346 CDEBUG(D_OTHER, "cur_root=%s, cur=%s, next=%s, (%s)\n",
347 cur_root->name, cur, next,
348 (proc ? "exists" : "new"));
350 cur_root = (proc ? proc :
351 proc_mkdir(cur, cur_root));
352 } else if (proc == NULL) {
354 if (list->proc_mode != 0000) {
355 mode = list->proc_mode;
359 if (list->write_fptr)
362 proc = create_proc_entry(cur, mode, cur_root);
366 if (pathcopy != pathbuf)
367 OBD_FREE(pathcopy, pathsize);
369 if (cur_root == NULL || proc == NULL) {
370 CERROR("LprocFS: No memory to create /proc entry %s",
372 GOTO(out, rc = -ENOMEM);
376 proc->proc_fops = list->fops;
378 proc->proc_fops = &lprocfs_generic_fops;
379 proc->read_proc = list->read_fptr;
380 proc->write_proc = list->write_fptr;
381 proc->data = (list->data ? list->data : data);
385 LPROCFS_WRITE_EXIT();
388 EXPORT_SYMBOL(lprocfs_add_vars);
390 void lprocfs_remove_nolock(struct proc_dir_entry **rooth)
392 struct proc_dir_entry *root = *rooth;
393 struct proc_dir_entry *temp = root;
394 struct proc_dir_entry *rm_entry;
395 struct proc_dir_entry *parent;
401 parent = root->parent;
402 LASSERT(parent != NULL);
405 while (temp->subdir != NULL)
411 /* Memory corruption once caused this to fail, and
412 without this LASSERT we would loop here forever. */
413 LASSERTF(strlen(rm_entry->name) == rm_entry->namelen,
414 "0x%p %s/%s len %d\n", rm_entry, temp->name,
415 rm_entry->name, (int)strlen(rm_entry->name));
417 remove_proc_entry(rm_entry->name, temp);
423 void lprocfs_remove(struct proc_dir_entry **rooth)
425 LPROCFS_WRITE_ENTRY(); /* search vs remove race */
426 lprocfs_remove_nolock(rooth);
427 LPROCFS_WRITE_EXIT();
429 EXPORT_SYMBOL(lprocfs_remove);
431 void lprocfs_remove_proc_entry(const char *name, struct proc_dir_entry *parent)
433 LASSERT(parent != NULL);
434 remove_proc_entry(name, parent);
436 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
438 void lprocfs_try_remove_proc_entry(const char *name,
439 struct proc_dir_entry *parent)
441 struct proc_dir_entry *t = NULL;
442 struct proc_dir_entry **p;
445 LASSERT(parent != NULL);
448 LPROCFS_WRITE_ENTRY();
450 /* lookup target name */
451 for (p = &parent->subdir; *p; p = &(*p)->next) {
452 if ((*p)->namelen != len)
454 if (memcmp(name, (*p)->name, len))
461 /* verify it's empty: do not count "num_refs" */
462 for (p = &t->subdir; *p; p = &(*p)->next) {
463 if ((*p)->namelen != strlen("num_refs")) {
467 if (memcmp("num_refs", (*p)->name,
468 strlen("num_refs"))) {
476 lprocfs_remove_nolock(&t);
478 LPROCFS_WRITE_EXIT();
482 EXPORT_SYMBOL(lprocfs_try_remove_proc_entry);
484 struct proc_dir_entry *lprocfs_register(const char *name,
485 struct proc_dir_entry *parent,
486 struct lprocfs_vars *list, void *data)
488 struct proc_dir_entry *newchild;
490 newchild = lprocfs_srch(parent, name);
491 if (newchild != NULL) {
492 CERROR(" Lproc: Attempting to register %s more than once \n",
494 return ERR_PTR(-EALREADY);
497 newchild = proc_mkdir(name, parent);
498 if (newchild != NULL && list != NULL) {
499 int rc = lprocfs_add_vars(newchild, list, data);
501 lprocfs_remove(&newchild);
507 EXPORT_SYMBOL(lprocfs_register);
509 /* Generic callbacks */
510 int lprocfs_rd_uint(char *page, char **start, off_t off,
511 int count, int *eof, void *data)
513 unsigned int *temp = data;
514 return snprintf(page, count, "%u\n", *temp);
516 EXPORT_SYMBOL(lprocfs_rd_uint);
518 int lprocfs_wr_uint(struct file *file, const char *buffer,
519 unsigned long count, void *data)
522 char dummy[MAX_STRING_SIZE + 1], *end;
525 dummy[MAX_STRING_SIZE] = '\0';
526 if (cfs_copy_from_user(dummy, buffer, MAX_STRING_SIZE))
529 tmp = simple_strtoul(dummy, &end, 0);
533 *p = (unsigned int)tmp;
536 EXPORT_SYMBOL(lprocfs_wr_uint);
538 int lprocfs_rd_u64(char *page, char **start, off_t off,
539 int count, int *eof, void *data)
541 LASSERT(data != NULL);
543 return snprintf(page, count, LPU64"\n", *(__u64 *)data);
545 EXPORT_SYMBOL(lprocfs_rd_u64);
547 int lprocfs_rd_atomic(char *page, char **start, off_t off,
548 int count, int *eof, void *data)
550 cfs_atomic_t *atom = data;
551 LASSERT(atom != NULL);
553 return snprintf(page, count, "%d\n", cfs_atomic_read(atom));
555 EXPORT_SYMBOL(lprocfs_rd_atomic);
557 int lprocfs_wr_atomic(struct file *file, const char *buffer,
558 unsigned long count, void *data)
560 cfs_atomic_t *atm = data;
564 rc = lprocfs_write_helper(buffer, count, &val);
571 cfs_atomic_set(atm, val);
574 EXPORT_SYMBOL(lprocfs_wr_atomic);
576 int lprocfs_rd_uuid(char *page, char **start, off_t off, int count,
577 int *eof, void *data)
579 struct obd_device *obd = data;
581 LASSERT(obd != NULL);
583 return snprintf(page, count, "%s\n", obd->obd_uuid.uuid);
585 EXPORT_SYMBOL(lprocfs_rd_uuid);
587 int lprocfs_rd_name(char *page, char **start, off_t off, int count,
588 int *eof, void *data)
590 struct obd_device *dev = data;
592 LASSERT(dev != NULL);
593 LASSERT(dev->obd_name != NULL);
595 return snprintf(page, count, "%s\n", dev->obd_name);
597 EXPORT_SYMBOL(lprocfs_rd_name);
599 int lprocfs_rd_blksize(char *page, char **start, off_t off, int count,
600 int *eof, void *data)
602 struct obd_device *obd = data;
603 struct obd_statfs osfs;
604 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
605 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
609 rc = snprintf(page, count, "%u\n", osfs.os_bsize);
613 EXPORT_SYMBOL(lprocfs_rd_blksize);
615 int lprocfs_osd_rd_blksize(char *page, char **start, off_t off,
616 int count, int *eof, void *data)
618 struct dt_device *dt = data;
619 struct obd_statfs osfs;
620 int rc = dt_statfs(NULL, dt, &osfs);
623 rc = snprintf(page, count, "%d\n",
624 (unsigned) osfs.os_bsize);
628 EXPORT_SYMBOL(lprocfs_osd_rd_blksize);
630 int lprocfs_rd_kbytestotal(char *page, char **start, off_t off, int count,
631 int *eof, void *data)
633 struct obd_device *obd = data;
634 struct obd_statfs osfs;
635 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
636 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
639 __u32 blk_size = osfs.os_bsize >> 10;
640 __u64 result = osfs.os_blocks;
642 while (blk_size >>= 1)
646 rc = snprintf(page, count, LPU64"\n", result);
650 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
652 int lprocfs_osd_rd_kbytestotal(char *page, char **start, off_t off,
653 int count, int *eof, void *data)
655 struct dt_device *dt = data;
656 struct obd_statfs osfs;
657 int rc = dt_statfs(NULL, dt, &osfs);
659 __u32 blk_size = osfs.os_bsize >> 10;
660 __u64 result = osfs.os_blocks;
662 while (blk_size >>= 1)
666 rc = snprintf(page, count, LPU64"\n", result);
670 EXPORT_SYMBOL(lprocfs_osd_rd_kbytestotal);
672 int lprocfs_rd_kbytesfree(char *page, char **start, off_t off, int count,
673 int *eof, void *data)
675 struct obd_device *obd = data;
676 struct obd_statfs osfs;
677 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
678 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
681 __u32 blk_size = osfs.os_bsize >> 10;
682 __u64 result = osfs.os_bfree;
684 while (blk_size >>= 1)
688 rc = snprintf(page, count, LPU64"\n", result);
692 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
694 int lprocfs_osd_rd_kbytesfree(char *page, char **start, off_t off,
695 int count, int *eof, void *data)
697 struct dt_device *dt = data;
698 struct obd_statfs osfs;
699 int rc = dt_statfs(NULL, dt, &osfs);
701 __u32 blk_size = osfs.os_bsize >> 10;
702 __u64 result = osfs.os_bfree;
704 while (blk_size >>= 1)
708 rc = snprintf(page, count, LPU64"\n", result);
712 EXPORT_SYMBOL(lprocfs_osd_rd_kbytesfree);
714 int lprocfs_rd_kbytesavail(char *page, char **start, off_t off, int count,
715 int *eof, void *data)
717 struct obd_device *obd = data;
718 struct obd_statfs osfs;
719 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
720 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
723 __u32 blk_size = osfs.os_bsize >> 10;
724 __u64 result = osfs.os_bavail;
726 while (blk_size >>= 1)
730 rc = snprintf(page, count, LPU64"\n", result);
734 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
736 int lprocfs_osd_rd_kbytesavail(char *page, char **start, off_t off,
737 int count, int *eof, void *data)
739 struct dt_device *dt = data;
740 struct obd_statfs osfs;
741 int rc = dt_statfs(NULL, dt, &osfs);
743 __u32 blk_size = osfs.os_bsize >> 10;
744 __u64 result = osfs.os_bavail;
746 while (blk_size >>= 1)
750 rc = snprintf(page, count, LPU64"\n", result);
754 EXPORT_SYMBOL(lprocfs_osd_rd_kbytesavail);
756 int lprocfs_rd_filestotal(char *page, char **start, off_t off, int count,
757 int *eof, void *data)
759 struct obd_device *obd = data;
760 struct obd_statfs osfs;
761 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
762 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
766 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
771 EXPORT_SYMBOL(lprocfs_rd_filestotal);
773 int lprocfs_osd_rd_filestotal(char *page, char **start, off_t off,
774 int count, int *eof, void *data)
776 struct dt_device *dt = data;
777 struct obd_statfs osfs;
778 int rc = dt_statfs(NULL, dt, &osfs);
781 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
786 EXPORT_SYMBOL(lprocfs_osd_rd_filestotal);
788 int lprocfs_rd_filesfree(char *page, char **start, off_t off, int count,
789 int *eof, void *data)
791 struct obd_device *obd = data;
792 struct obd_statfs osfs;
793 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
794 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
798 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
802 EXPORT_SYMBOL(lprocfs_rd_filesfree);
804 int lprocfs_osd_rd_filesfree(char *page, char **start, off_t off,
805 int count, int *eof, void *data)
807 struct dt_device *dt = data;
808 struct obd_statfs osfs;
809 int rc = dt_statfs(NULL, dt, &osfs);
812 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
816 EXPORT_SYMBOL(lprocfs_osd_rd_filesfree);
818 int lprocfs_rd_server_uuid(char *page, char **start, off_t off, int count,
819 int *eof, void *data)
821 struct obd_device *obd = data;
822 struct obd_import *imp;
823 char *imp_state_name = NULL;
826 LASSERT(obd != NULL);
827 LPROCFS_CLIMP_CHECK(obd);
828 imp = obd->u.cli.cl_import;
829 imp_state_name = ptlrpc_import_state_name(imp->imp_state);
831 rc = snprintf(page, count, "%s\t%s%s\n",
832 obd2cli_tgt(obd), imp_state_name,
833 imp->imp_deactive ? "\tDEACTIVATED" : "");
835 LPROCFS_CLIMP_EXIT(obd);
838 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
840 int lprocfs_rd_conn_uuid(char *page, char **start, off_t off, int count,
841 int *eof, void *data)
843 struct obd_device *obd = data;
844 struct ptlrpc_connection *conn;
847 LASSERT(obd != NULL);
849 LPROCFS_CLIMP_CHECK(obd);
850 conn = obd->u.cli.cl_import->imp_connection;
852 if (conn && obd->u.cli.cl_import) {
853 rc = snprintf(page, count, "%s\n",
854 conn->c_remote_uuid.uuid);
856 rc = snprintf(page, count, "%s\n", "<none>");
859 LPROCFS_CLIMP_EXIT(obd);
862 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
864 /** add up per-cpu counters */
865 void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
866 struct lprocfs_counter *cnt)
868 unsigned int num_entry;
869 struct lprocfs_counter *percpu_cntr;
870 struct lprocfs_counter_header *cntr_header;
872 unsigned long flags = 0;
874 memset(cnt, 0, sizeof(*cnt));
877 /* set count to 1 to avoid divide-by-zero errs in callers */
882 cnt->lc_min = LC_MIN_INIT;
884 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
886 for (i = 0; i < num_entry; i++) {
887 if (stats->ls_percpu[i] == NULL)
889 cntr_header = &stats->ls_cnt_header[idx];
890 percpu_cntr = lprocfs_stats_counter_get(stats, i, idx);
892 cnt->lc_count += percpu_cntr->lc_count;
893 cnt->lc_sum += percpu_cntr->lc_sum;
894 if (percpu_cntr->lc_min < cnt->lc_min)
895 cnt->lc_min = percpu_cntr->lc_min;
896 if (percpu_cntr->lc_max > cnt->lc_max)
897 cnt->lc_max = percpu_cntr->lc_max;
898 cnt->lc_sumsquare += percpu_cntr->lc_sumsquare;
901 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
903 EXPORT_SYMBOL(lprocfs_stats_collect);
906 * Append a space separated list of current set flags to str.
908 #define flag2str(flag) \
909 if (imp->imp_##flag && max - len > 0) \
910 len += snprintf(str + len, max - len, "%s" #flag, len ? ", " : "");
911 static int obd_import_flags2str(struct obd_import *imp, char *str, int max)
915 if (imp->imp_obd->obd_no_recov)
916 len += snprintf(str, max - len, "no_recov");
920 flag2str(replayable);
926 static const char *obd_connect_names[] = {
940 "join_file(obsolete)",
944 "remote_client_by_force",
953 "mds_mds_connection",
956 "alt_checksum_algorithm",
982 int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
987 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
989 ret += snprintf(page + ret, count - ret, "%s%s",
990 ret ? sep : "", obd_connect_names[i]);
992 if (flags & ~(mask - 1))
993 ret += snprintf(page + ret, count - ret,
994 "%sunknown flags "LPX64,
995 ret ? sep : "", flags & ~(mask - 1));
998 EXPORT_SYMBOL(obd_connect_flags2str);
1000 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
1001 int *eof, void *data)
1003 struct lprocfs_counter ret;
1004 struct lprocfs_counter_header *header;
1005 struct obd_device *obd = (struct obd_device *)data;
1006 struct obd_import *imp;
1007 struct obd_import_conn *conn;
1013 LASSERT(obd != NULL);
1014 LPROCFS_CLIMP_CHECK(obd);
1015 imp = obd->u.cli.cl_import;
1018 i = snprintf(page, count,
1024 " connect_flags: [",
1027 ptlrpc_import_state_name(imp->imp_state),
1028 imp->imp_connect_data.ocd_instance);
1029 i += obd_connect_flags2str(page + i, count - i,
1030 imp->imp_connect_data.ocd_connect_flags,
1032 i += snprintf(page + i, count - i,
1034 " import_flags: [");
1035 i += obd_import_flags2str(imp, page + i, count - i);
1037 i += snprintf(page + i, count - i,
1040 " failover_nids: [");
1041 spin_lock(&imp->imp_lock);
1043 cfs_list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
1044 i += snprintf(page + i, count - i, "%s%s", j ? ", " : "",
1045 libcfs_nid2str(conn->oic_conn->c_peer.nid));
1048 i += snprintf(page + i, count - i,
1050 " current_connection: %s\n"
1051 " connection_attempts: %u\n"
1053 " in-progress_invalidations: %u\n",
1054 imp->imp_connection == NULL ? "<none>" :
1055 libcfs_nid2str(imp->imp_connection->c_peer.nid),
1057 imp->imp_generation,
1058 cfs_atomic_read(&imp->imp_inval_count));
1059 spin_unlock(&imp->imp_lock);
1061 header = &obd->obd_svc_stats->ls_cnt_header[PTLRPC_REQWAIT_CNTR];
1062 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
1063 if (ret.lc_count != 0) {
1064 /* first argument to do_div MUST be __u64 */
1065 __u64 sum = ret.lc_sum;
1066 do_div(sum, ret.lc_count);
1070 i += snprintf(page + i, count - i,
1073 " unregistering: %u\n"
1075 " avg_waittime: "LPU64" %s\n",
1076 cfs_atomic_read(&imp->imp_inflight),
1077 cfs_atomic_read(&imp->imp_unregistering),
1078 cfs_atomic_read(&imp->imp_timeouts),
1079 ret.lc_sum, header->lc_units);
1082 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
1083 if (imp->imp_at.iat_portal[j] == 0)
1085 k = max_t(unsigned int, k,
1086 at_get(&imp->imp_at.iat_service_estimate[j]));
1088 i += snprintf(page + i, count - i,
1089 " service_estimates:\n"
1090 " services: %u sec\n"
1091 " network: %u sec\n",
1093 at_get(&imp->imp_at.iat_net_latency));
1095 i += snprintf(page + i, count - i,
1097 " last_replay: "LPU64"\n"
1098 " peer_committed: "LPU64"\n"
1099 " last_checked: "LPU64"\n",
1100 imp->imp_last_replay_transno,
1101 imp->imp_peer_committed_transno,
1102 imp->imp_last_transno_checked);
1104 /* avg data rates */
1105 for (rw = 0; rw <= 1; rw++) {
1106 lprocfs_stats_collect(obd->obd_svc_stats,
1107 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
1109 if (ret.lc_sum > 0 && ret.lc_count > 0) {
1110 /* first argument to do_div MUST be __u64 */
1111 __u64 sum = ret.lc_sum;
1112 do_div(sum, ret.lc_count);
1114 i += snprintf(page + i, count - i,
1115 " %s_data_averages:\n"
1116 " bytes_per_rpc: "LPU64"\n",
1117 rw ? "write" : "read",
1120 k = (int)ret.lc_sum;
1121 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
1122 header = &obd->obd_svc_stats->ls_cnt_header[j];
1123 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
1124 if (ret.lc_sum > 0 && ret.lc_count != 0) {
1125 /* first argument to do_div MUST be __u64 */
1126 __u64 sum = ret.lc_sum;
1127 do_div(sum, ret.lc_count);
1129 i += snprintf(page + i, count - i,
1130 " %s_per_rpc: "LPU64"\n",
1131 header->lc_units, ret.lc_sum);
1132 j = (int)ret.lc_sum;
1134 i += snprintf(page + i, count - i,
1135 " MB_per_sec: %u.%.02u\n",
1136 k / j, (100 * k / j) % 100);
1140 LPROCFS_CLIMP_EXIT(obd);
1143 EXPORT_SYMBOL(lprocfs_rd_import);
1145 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
1146 int *eof, void *data)
1148 struct obd_device *obd = (struct obd_device *)data;
1149 struct obd_import *imp;
1152 LASSERT(obd != NULL);
1153 LPROCFS_CLIMP_CHECK(obd);
1154 imp = obd->u.cli.cl_import;
1157 i = snprintf(page, count, "current_state: %s\n",
1158 ptlrpc_import_state_name(imp->imp_state));
1159 i += snprintf(page + i, count - i,
1160 "state_history:\n");
1161 k = imp->imp_state_hist_idx;
1162 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
1163 struct import_state_hist *ish =
1164 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
1165 if (ish->ish_state == 0)
1167 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
1169 ptlrpc_import_state_name(ish->ish_state));
1172 LPROCFS_CLIMP_EXIT(obd);
1175 EXPORT_SYMBOL(lprocfs_rd_state);
1177 int lprocfs_at_hist_helper(char *page, int count, int rc,
1178 struct adaptive_timeout *at)
1181 for (i = 0; i < AT_BINS; i++)
1182 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
1183 rc += snprintf(page + rc, count - rc, "\n");
1186 EXPORT_SYMBOL(lprocfs_at_hist_helper);
1188 /* See also ptlrpc_lprocfs_rd_timeouts */
1189 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
1190 int *eof, void *data)
1192 struct obd_device *obd = (struct obd_device *)data;
1193 struct obd_import *imp;
1194 unsigned int cur, worst;
1199 LASSERT(obd != NULL);
1200 LPROCFS_CLIMP_CHECK(obd);
1201 imp = obd->u.cli.cl_import;
1204 now = cfs_time_current_sec();
1206 /* Some network health info for kicks */
1207 s2dhms(&ts, now - imp->imp_last_reply_time);
1208 rc += snprintf(page + rc, count - rc,
1209 "%-10s : %ld, "DHMS_FMT" ago\n",
1210 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
1212 cur = at_get(&imp->imp_at.iat_net_latency);
1213 worst = imp->imp_at.iat_net_latency.at_worst_ever;
1214 worstt = imp->imp_at.iat_net_latency.at_worst_time;
1215 s2dhms(&ts, now - worstt);
1216 rc += snprintf(page + rc, count - rc,
1217 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
1218 "network", cur, worst, worstt, DHMS_VARS(&ts));
1219 rc = lprocfs_at_hist_helper(page, count, rc,
1220 &imp->imp_at.iat_net_latency);
1222 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
1223 if (imp->imp_at.iat_portal[i] == 0)
1225 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
1226 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
1227 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
1228 s2dhms(&ts, now - worstt);
1229 rc += snprintf(page + rc, count - rc,
1230 "portal %-2d : cur %3u worst %3u (at %ld, "
1231 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
1232 cur, worst, worstt, DHMS_VARS(&ts));
1233 rc = lprocfs_at_hist_helper(page, count, rc,
1234 &imp->imp_at.iat_service_estimate[i]);
1237 LPROCFS_CLIMP_EXIT(obd);
1240 EXPORT_SYMBOL(lprocfs_rd_timeouts);
1242 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1243 int count, int *eof, void *data)
1245 struct obd_device *obd = data;
1249 LPROCFS_CLIMP_CHECK(obd);
1250 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1251 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1252 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1253 ret += snprintf(page + ret, count - ret, "\n");
1254 LPROCFS_CLIMP_EXIT(obd);
1257 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1259 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1260 int *eof, void *data)
1262 struct obd_device *obd = data;
1264 LASSERT(obd != NULL);
1266 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1268 EXPORT_SYMBOL(lprocfs_rd_num_exports);
1270 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1271 int *eof, void *data)
1273 struct obd_type *class = (struct obd_type*) data;
1275 LASSERT(class != NULL);
1277 return snprintf(page, count, "%d\n", class->typ_refcnt);
1279 EXPORT_SYMBOL(lprocfs_rd_numrefs);
1281 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1285 LASSERT(obd != NULL);
1286 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1287 LASSERT(obd->obd_type->typ_procroot != NULL);
1289 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1290 obd->obd_type->typ_procroot,
1292 if (IS_ERR(obd->obd_proc_entry)) {
1293 rc = PTR_ERR(obd->obd_proc_entry);
1294 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1295 obd->obd_proc_entry = NULL;
1299 EXPORT_SYMBOL(lprocfs_obd_setup);
1301 int lprocfs_obd_cleanup(struct obd_device *obd)
1305 if (obd->obd_proc_exports_entry) {
1306 /* Should be no exports left */
1307 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1308 lprocfs_remove(&obd->obd_proc_exports_entry);
1309 obd->obd_proc_exports_entry = NULL;
1311 if (obd->obd_proc_entry) {
1312 lprocfs_remove(&obd->obd_proc_entry);
1313 obd->obd_proc_entry = NULL;
1317 EXPORT_SYMBOL(lprocfs_obd_cleanup);
1319 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1321 CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
1322 client_stat->nid_proc, client_stat->nid_stats,
1323 client_stat->nid_brw_stats);
1325 LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
1326 "nid %s:count %d\n", libcfs_nid2str(client_stat->nid),
1327 atomic_read(&client_stat->nid_exp_ref_count));
1329 if (client_stat->nid_proc)
1330 lprocfs_remove(&client_stat->nid_proc);
1332 if (client_stat->nid_stats)
1333 lprocfs_free_stats(&client_stat->nid_stats);
1335 if (client_stat->nid_brw_stats)
1336 OBD_FREE_PTR(client_stat->nid_brw_stats);
1338 if (client_stat->nid_ldlm_stats)
1339 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1341 OBD_FREE_PTR(client_stat);
1346 void lprocfs_free_per_client_stats(struct obd_device *obd)
1348 cfs_hash_t *hash = obd->obd_nid_stats_hash;
1349 struct nid_stat *stat;
1352 /* we need extra list - because hash_exit called to early */
1353 /* not need locking because all clients is died */
1354 while (!cfs_list_empty(&obd->obd_nid_stats)) {
1355 stat = cfs_list_entry(obd->obd_nid_stats.next,
1356 struct nid_stat, nid_list);
1357 cfs_list_del_init(&stat->nid_list);
1358 cfs_hash_del(hash, &stat->nid, &stat->nid_hash);
1359 lprocfs_free_client_stats(stat);
1363 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
1365 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1366 enum lprocfs_stats_flags flags)
1368 struct lprocfs_stats *stats;
1369 unsigned int num_entry;
1370 unsigned int percpusize = 0;
1376 if (lprocfs_no_percpu_stats != 0)
1377 flags |= LPROCFS_STATS_FLAG_NOPERCPU;
1379 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1382 num_entry = cfs_num_possible_cpus();
1384 /* alloc percpu pointers for all possible cpu slots */
1385 LIBCFS_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1389 stats->ls_num = num;
1390 stats->ls_flags = flags;
1391 spin_lock_init(&stats->ls_lock);
1393 /* alloc num of counter headers */
1394 LIBCFS_ALLOC(stats->ls_cnt_header,
1395 stats->ls_num * sizeof(struct lprocfs_counter_header));
1396 if (stats->ls_cnt_header == NULL)
1399 if ((flags & LPROCFS_STATS_FLAG_NOPERCPU) != 0) {
1400 /* contains only one set counters */
1401 percpusize = lprocfs_stats_counter_size(stats);
1402 LIBCFS_ALLOC_ATOMIC(stats->ls_percpu[0], percpusize);
1403 if (stats->ls_percpu[0] == NULL)
1405 stats->ls_biggest_alloc_num = 1;
1406 } else if ((flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0) {
1407 /* alloc all percpu data, currently only obd_memory use this */
1408 for (i = 0; i < num_entry; ++i)
1409 if (lprocfs_stats_alloc_one(stats, i) < 0)
1416 lprocfs_free_stats(&stats);
1419 EXPORT_SYMBOL(lprocfs_alloc_stats);
1421 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1423 struct lprocfs_stats *stats = *statsh;
1424 unsigned int num_entry;
1425 unsigned int percpusize;
1428 if (stats == NULL || stats->ls_num == 0)
1432 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1435 num_entry = cfs_num_possible_cpus();
1437 percpusize = lprocfs_stats_counter_size(stats);
1438 for (i = 0; i < num_entry; i++)
1439 if (stats->ls_percpu[i] != NULL)
1440 LIBCFS_FREE(stats->ls_percpu[i], percpusize);
1441 if (stats->ls_cnt_header != NULL)
1442 LIBCFS_FREE(stats->ls_cnt_header, stats->ls_num *
1443 sizeof(struct lprocfs_counter_header));
1444 LIBCFS_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1446 EXPORT_SYMBOL(lprocfs_free_stats);
1448 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1450 struct lprocfs_counter *percpu_cntr;
1451 struct lprocfs_counter_header *header;
1454 unsigned int num_entry;
1455 unsigned long flags = 0;
1457 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1459 for (i = 0; i < num_entry; i++) {
1460 if (stats->ls_percpu[i] == NULL)
1462 for (j = 0; j < stats->ls_num; j++) {
1463 header = &stats->ls_cnt_header[j];
1464 percpu_cntr = lprocfs_stats_counter_get(stats, i, j);
1465 percpu_cntr->lc_count = 0;
1466 percpu_cntr->lc_min = LC_MIN_INIT;
1467 percpu_cntr->lc_max = 0;
1468 percpu_cntr->lc_sumsquare = 0;
1469 percpu_cntr->lc_sum = 0;
1470 if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
1471 percpu_cntr->lc_sum_irq = 0;
1475 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1477 EXPORT_SYMBOL(lprocfs_clear_stats);
1479 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1480 size_t len, loff_t *off)
1482 struct seq_file *seq = file->private_data;
1483 struct lprocfs_stats *stats = seq->private;
1485 lprocfs_clear_stats(stats);
1490 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1492 struct lprocfs_stats *stats = p->private;
1493 /* return 1st cpu location */
1494 return (*pos >= stats->ls_num) ? NULL :
1495 lprocfs_stats_counter_get(stats, 0, *pos);
1498 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1502 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1504 struct lprocfs_stats *stats = p->private;
1506 return (*pos >= stats->ls_num) ? NULL :
1507 lprocfs_stats_counter_get(stats, 0, *pos);
1510 /* seq file export of one lprocfs counter */
1511 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1513 struct lprocfs_stats *stats = p->private;
1514 struct lprocfs_counter *cntr = v;
1515 struct lprocfs_counter ret;
1516 struct lprocfs_counter_header *header;
1521 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
1523 cfs_gettimeofday(&now);
1524 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1525 "snapshot_time", now.tv_sec, now.tv_usec);
1529 entry_size = sizeof(*cntr);
1530 if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
1531 entry_size += sizeof(__s64);
1532 idx = ((void *)cntr - (void *)&(stats->ls_percpu[0])->lp_cntr[0]) /
1535 header = &stats->ls_cnt_header[idx];
1536 lprocfs_stats_collect(stats, idx, &ret);
1538 if (ret.lc_count == 0)
1541 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", header->lc_name,
1542 ret.lc_count, header->lc_units);
1547 if ((header->lc_config & LPROCFS_CNTR_AVGMINMAX) &&
1548 (ret.lc_count > 0)) {
1549 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1550 ret.lc_min, ret.lc_max, ret.lc_sum);
1553 if (header->lc_config & LPROCFS_CNTR_STDDEV)
1554 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1558 rc = seq_printf(p, "\n");
1560 return (rc < 0) ? rc : 0;
1563 struct seq_operations lprocfs_stats_seq_sops = {
1564 start: lprocfs_stats_seq_start,
1565 stop: lprocfs_stats_seq_stop,
1566 next: lprocfs_stats_seq_next,
1567 show: lprocfs_stats_seq_show,
1570 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1572 struct proc_dir_entry *dp = PDE(inode);
1573 struct seq_file *seq;
1576 if (LPROCFS_ENTRY_AND_CHECK(dp))
1579 rc = seq_open(file, &lprocfs_stats_seq_sops);
1584 seq = file->private_data;
1585 seq->private = dp->data;
1589 struct file_operations lprocfs_stats_seq_fops = {
1590 .owner = THIS_MODULE,
1591 .open = lprocfs_stats_seq_open,
1593 .write = lprocfs_stats_seq_write,
1594 .llseek = seq_lseek,
1595 .release = lprocfs_seq_release,
1598 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1599 struct lprocfs_stats *stats)
1601 struct proc_dir_entry *entry;
1602 LASSERT(root != NULL);
1604 LPROCFS_WRITE_ENTRY();
1605 entry = create_proc_entry(name, 0644, root);
1607 entry->proc_fops = &lprocfs_stats_seq_fops;
1608 entry->data = stats;
1611 LPROCFS_WRITE_EXIT();
1618 EXPORT_SYMBOL(lprocfs_register_stats);
1620 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1621 unsigned conf, const char *name, const char *units)
1623 struct lprocfs_counter_header *header;
1624 struct lprocfs_counter *percpu_cntr;
1625 unsigned long flags = 0;
1627 unsigned int num_cpu;
1629 LASSERT(stats != NULL);
1631 header = &stats->ls_cnt_header[index];
1632 LASSERTF(header != NULL, "Failed to allocate stats header:[%d]%s/%s\n",
1633 index, name, units);
1635 header->lc_config = conf;
1636 header->lc_name = name;
1637 header->lc_units = units;
1639 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1640 for (i = 0; i < num_cpu; ++i) {
1641 if (stats->ls_percpu[i] == NULL)
1643 percpu_cntr = lprocfs_stats_counter_get(stats, i, index);
1644 percpu_cntr->lc_count = 0;
1645 percpu_cntr->lc_min = LC_MIN_INIT;
1646 percpu_cntr->lc_max = 0;
1647 percpu_cntr->lc_sumsquare = 0;
1648 percpu_cntr->lc_sum = 0;
1649 if ((stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
1650 percpu_cntr->lc_sum_irq = 0;
1652 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1654 EXPORT_SYMBOL(lprocfs_counter_init);
1656 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1658 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1659 LASSERT(coffset < stats->ls_num); \
1660 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1663 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1665 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1666 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1667 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1668 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1669 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1670 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1671 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1672 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1673 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1674 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1675 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1676 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1677 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1678 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1679 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1680 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1681 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1682 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1683 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1684 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1685 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1686 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1687 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1688 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1689 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1690 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1691 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1692 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1693 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1694 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1695 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1696 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1697 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1698 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1699 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1700 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1701 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1702 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1703 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1704 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1705 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1706 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1707 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1708 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
1709 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1710 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1711 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1712 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1713 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1714 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1715 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1716 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1717 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1718 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1719 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1720 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1721 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1722 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1723 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1724 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1725 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1726 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1727 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1728 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1729 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1730 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1731 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1733 EXPORT_SYMBOL(lprocfs_init_ops_stats);
1735 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1737 struct lprocfs_stats *stats;
1738 unsigned int num_stats;
1741 LASSERT(obd->obd_stats == NULL);
1742 LASSERT(obd->obd_proc_entry != NULL);
1743 LASSERT(obd->obd_cntr_base == 0);
1745 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1746 num_private_stats - 1 /* o_owner */;
1747 stats = lprocfs_alloc_stats(num_stats, 0);
1751 lprocfs_init_ops_stats(num_private_stats, stats);
1753 for (i = num_private_stats; i < num_stats; i++) {
1754 /* If this LBUGs, it is likely that an obd
1755 * operation was added to struct obd_ops in
1756 * <obd.h>, and that the corresponding line item
1757 * LPROCFS_OBD_OP_INIT(.., .., opname)
1758 * is missing from the list above. */
1759 LASSERTF(stats->ls_cnt_header[i].lc_name != NULL,
1760 "Missing obd_stat initializer obd_op "
1761 "operation at offset %d.\n", i - num_private_stats);
1763 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1765 lprocfs_free_stats(&stats);
1767 obd->obd_stats = stats;
1768 obd->obd_cntr_base = num_private_stats;
1772 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
1774 void lprocfs_free_obd_stats(struct obd_device *obd)
1777 lprocfs_free_stats(&obd->obd_stats);
1779 EXPORT_SYMBOL(lprocfs_free_obd_stats);
1781 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1783 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1784 LASSERT(coffset < stats->ls_num); \
1785 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1788 void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats)
1790 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1791 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1792 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
1793 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1794 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1795 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1796 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1797 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1798 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1799 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1800 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1801 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1802 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1803 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1804 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1805 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1806 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1807 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1808 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1809 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1810 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1811 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1812 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1813 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1814 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1815 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1816 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1817 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1818 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1819 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1820 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1821 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1823 EXPORT_SYMBOL(lprocfs_init_mps_stats);
1825 int lprocfs_alloc_md_stats(struct obd_device *obd,
1826 unsigned num_private_stats)
1828 struct lprocfs_stats *stats;
1829 unsigned int num_stats;
1832 LASSERT(obd->md_stats == NULL);
1833 LASSERT(obd->obd_proc_entry != NULL);
1834 LASSERT(obd->md_cntr_base == 0);
1836 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1838 stats = lprocfs_alloc_stats(num_stats, 0);
1842 lprocfs_init_mps_stats(num_private_stats, stats);
1844 for (i = num_private_stats; i < num_stats; i++) {
1845 if (stats->ls_cnt_header[i].lc_name == NULL) {
1846 CERROR("Missing md_stat initializer md_op "
1847 "operation at offset %d. Aborting.\n",
1848 i - num_private_stats);
1852 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1854 lprocfs_free_stats(&stats);
1856 obd->md_stats = stats;
1857 obd->md_cntr_base = num_private_stats;
1861 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
1863 void lprocfs_free_md_stats(struct obd_device *obd)
1865 struct lprocfs_stats *stats = obd->md_stats;
1867 if (stats != NULL) {
1868 obd->md_stats = NULL;
1869 obd->md_cntr_base = 0;
1870 lprocfs_free_stats(&stats);
1873 EXPORT_SYMBOL(lprocfs_free_md_stats);
1875 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1877 lprocfs_counter_init(ldlm_stats,
1878 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1879 0, "ldlm_enqueue", "reqs");
1880 lprocfs_counter_init(ldlm_stats,
1881 LDLM_CONVERT - LDLM_FIRST_OPC,
1882 0, "ldlm_convert", "reqs");
1883 lprocfs_counter_init(ldlm_stats,
1884 LDLM_CANCEL - LDLM_FIRST_OPC,
1885 0, "ldlm_cancel", "reqs");
1886 lprocfs_counter_init(ldlm_stats,
1887 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1888 0, "ldlm_bl_callback", "reqs");
1889 lprocfs_counter_init(ldlm_stats,
1890 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1891 0, "ldlm_cp_callback", "reqs");
1892 lprocfs_counter_init(ldlm_stats,
1893 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1894 0, "ldlm_gl_callback", "reqs");
1896 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
1898 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1899 int *eof, void *data)
1901 struct obd_export *exp = data;
1902 LASSERT(exp != NULL);
1904 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1907 struct exp_uuid_cb_data {
1915 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1916 int count, int *eof, int *len)
1918 cb_data->page = page;
1919 cb_data->count = count;
1924 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1925 cfs_hlist_node_t *hnode, void *cb_data)
1928 struct obd_export *exp = cfs_hash_object(hs, hnode);
1929 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1931 if (exp->exp_nid_stats)
1932 *data->len += snprintf((data->page + *data->len),
1933 data->count, "%s\n",
1934 obd_uuid2str(&exp->exp_client_uuid));
1938 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1939 int *eof, void *data)
1941 struct nid_stat *stats = (struct nid_stat *)data;
1942 struct exp_uuid_cb_data cb_data;
1943 struct obd_device *obd = stats->nid_obd;
1948 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1949 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1950 lprocfs_exp_print_uuid, &cb_data);
1951 return (*cb_data.len);
1954 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1955 cfs_hlist_node_t *hnode, void *cb_data)
1958 struct exp_uuid_cb_data *data = cb_data;
1959 struct obd_export *exp = cfs_hash_object(hs, hnode);
1961 if (exp->exp_lock_hash != NULL) {
1963 *data->len += cfs_hash_debug_header(data->page,
1966 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1973 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1974 int *eof, void *data)
1976 struct nid_stat *stats = (struct nid_stat *)data;
1977 struct exp_uuid_cb_data cb_data;
1978 struct obd_device *obd = stats->nid_obd;
1983 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1985 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1986 lprocfs_exp_print_hash, &cb_data);
1987 return (*cb_data.len);
1990 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1991 int count, int *eof, void *data)
1994 return snprintf(page, count, "%s\n",
1995 "Write into this file to clear all nid stats and "
1996 "stale nid entries");
1998 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
2000 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
2002 struct nid_stat *stat = obj;
2006 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
2007 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 1) {
2008 /* object has only hash references. */
2009 spin_lock(&stat->nid_obd->obd_nid_lock);
2010 cfs_list_move(&stat->nid_list, data);
2011 spin_unlock(&stat->nid_obd->obd_nid_lock);
2014 /* we has reference to object - only clear data*/
2015 if (stat->nid_stats)
2016 lprocfs_clear_stats(stat->nid_stats);
2018 if (stat->nid_brw_stats) {
2019 for (i = 0; i < BRW_LAST; i++)
2020 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
2025 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
2026 unsigned long count, void *data)
2028 struct obd_device *obd = (struct obd_device *)data;
2029 struct nid_stat *client_stat;
2030 CFS_LIST_HEAD(free_list);
2032 cfs_hash_cond_del(obd->obd_nid_stats_hash,
2033 lprocfs_nid_stats_clear_write_cb, &free_list);
2035 while (!cfs_list_empty(&free_list)) {
2036 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
2038 cfs_list_del_init(&client_stat->nid_list);
2039 lprocfs_free_client_stats(client_stat);
2044 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
2046 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
2048 struct nid_stat *new_stat, *old_stat;
2049 struct obd_device *obd = NULL;
2050 cfs_proc_dir_entry_t *entry;
2051 char *buffer = NULL;
2057 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
2058 !exp->exp_obd->obd_nid_stats_hash)
2061 /* not test against zero because eric say:
2062 * You may only test nid against another nid, or LNET_NID_ANY.
2063 * Anything else is nonsense.*/
2064 if (!nid || *nid == LNET_NID_ANY)
2069 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
2071 OBD_ALLOC_PTR(new_stat);
2072 if (new_stat == NULL)
2075 new_stat->nid = *nid;
2076 new_stat->nid_obd = exp->exp_obd;
2077 /* we need set default refcount to 1 to balance obd_disconnect */
2078 cfs_atomic_set(&new_stat->nid_exp_ref_count, 1);
2080 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
2081 nid, &new_stat->nid_hash);
2082 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
2083 old_stat, libcfs_nid2str(*nid),
2084 cfs_atomic_read(&new_stat->nid_exp_ref_count));
2086 /* We need to release old stats because lprocfs_exp_cleanup() hasn't
2087 * been and will never be called. */
2088 if (exp->exp_nid_stats) {
2089 nidstat_putref(exp->exp_nid_stats);
2090 exp->exp_nid_stats = NULL;
2093 /* Return -EALREADY here so that we know that the /proc
2094 * entry already has been created */
2095 if (old_stat != new_stat) {
2096 exp->exp_nid_stats = old_stat;
2097 GOTO(destroy_new, rc = -EALREADY);
2099 /* not found - create */
2100 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
2102 GOTO(destroy_new, rc = -ENOMEM);
2104 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
2105 new_stat->nid_proc = lprocfs_register(buffer,
2106 obd->obd_proc_exports_entry,
2108 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
2110 if (new_stat->nid_proc == NULL) {
2111 CERROR("Error making export directory for nid %s\n",
2112 libcfs_nid2str(*nid));
2113 GOTO(destroy_new_ns, rc = -ENOMEM);
2116 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
2117 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
2118 if (IS_ERR(entry)) {
2119 CWARN("Error adding the NID stats file\n");
2120 rc = PTR_ERR(entry);
2121 GOTO(destroy_new_ns, rc);
2124 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
2125 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
2126 if (IS_ERR(entry)) {
2127 CWARN("Error adding the hash file\n");
2128 rc = PTR_ERR(entry);
2129 GOTO(destroy_new_ns, rc);
2132 exp->exp_nid_stats = new_stat;
2134 /* protect competitive add to list, not need locking on destroy */
2135 spin_lock(&obd->obd_nid_lock);
2136 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
2137 spin_unlock(&obd->obd_nid_lock);
2142 if (new_stat->nid_proc != NULL)
2143 lprocfs_remove(&new_stat->nid_proc);
2144 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
2147 nidstat_putref(new_stat);
2148 OBD_FREE_PTR(new_stat);
2151 EXPORT_SYMBOL(lprocfs_exp_setup);
2153 int lprocfs_exp_cleanup(struct obd_export *exp)
2155 struct nid_stat *stat = exp->exp_nid_stats;
2157 if(!stat || !exp->exp_obd)
2160 nidstat_putref(exp->exp_nid_stats);
2161 exp->exp_nid_stats = NULL;
2165 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2167 int lprocfs_write_helper(const char *buffer, unsigned long count,
2170 return lprocfs_write_frac_helper(buffer, count, val, 1);
2172 EXPORT_SYMBOL(lprocfs_write_helper);
2174 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
2177 char kernbuf[20], *end, *pbuf;
2179 if (count > (sizeof(kernbuf) - 1))
2182 if (cfs_copy_from_user(kernbuf, buffer, count))
2185 kernbuf[count] = '\0';
2192 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2196 if (end != NULL && *end == '.') {
2197 int temp_val, pow = 1;
2201 if (strlen(pbuf) > 5)
2202 pbuf[5] = '\0'; /*only allow 5bits fractional*/
2204 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2207 for (i = 0; i < (end - pbuf); i++)
2210 *val += temp_val / pow;
2215 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2217 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
2220 long decimal_val, frac_val;
2226 decimal_val = val / mult;
2227 prtn = snprintf(buffer, count, "%ld", decimal_val);
2228 frac_val = val % mult;
2230 if (prtn < (count - 4) && frac_val > 0) {
2232 int i, temp_mult = 1, frac_bits = 0;
2234 temp_frac = frac_val * 10;
2235 buffer[prtn++] = '.';
2236 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
2237 /* only reserved 2 bits fraction */
2238 buffer[prtn++] ='0';
2243 * Need to think these cases :
2244 * 1. #echo x.00 > /proc/xxx output result : x
2245 * 2. #echo x.0x > /proc/xxx output result : x.0x
2246 * 3. #echo x.x0 > /proc/xxx output result : x.x
2247 * 4. #echo x.xx > /proc/xxx output result : x.xx
2248 * Only reserved 2 bits fraction.
2250 for (i = 0; i < (5 - prtn); i++)
2253 frac_bits = min((int)count - prtn, 3 - frac_bits);
2254 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
2255 frac_val * temp_mult / mult);
2258 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
2260 if (buffer[prtn] == '.') {
2267 buffer[prtn++] ='\n';
2270 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2272 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
2274 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
2276 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2278 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
2279 __u64 *val, int mult)
2281 char kernbuf[22], *end, *pbuf;
2282 __u64 whole, frac = 0, units;
2283 unsigned frac_d = 1;
2285 if (count > (sizeof(kernbuf) - 1))
2288 if (cfs_copy_from_user(kernbuf, buffer, count))
2291 kernbuf[count] = '\0';
2298 whole = simple_strtoull(pbuf, &end, 10);
2302 if (end != NULL && *end == '.') {
2306 /* need to limit frac_d to a __u32 */
2307 if (strlen(pbuf) > 10)
2310 frac = simple_strtoull(pbuf, &end, 10);
2311 /* count decimal places */
2312 for (i = 0; i < (end - pbuf); i++)
2329 /* Specified units override the multiplier */
2331 mult = mult < 0 ? -units : units;
2334 do_div(frac, frac_d);
2335 *val = whole * mult + frac;
2338 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2340 static char *lprocfs_strnstr(const char *s1, const char *s2, size_t len)
2349 if (!memcmp(s1, s2, l2))
2357 * Find the string \a name in the input \a buffer, and return a pointer to the
2358 * value immediately following \a name, reducing \a count appropriately.
2359 * If \a name is not found the original \a buffer is returned.
2361 char *lprocfs_find_named_value(const char *buffer, const char *name,
2362 unsigned long *count)
2365 size_t buflen = *count;
2367 /* there is no strnstr() in rhel5 and ubuntu kernels */
2368 val = lprocfs_strnstr(buffer, name, buflen);
2370 return (char *)buffer;
2372 val += strlen(name); /* skip prefix */
2373 while (val < buffer + buflen && isspace(*val)) /* skip separator */
2377 while (val < buffer + buflen && isalnum(*val)) {
2382 return val - *count;
2384 EXPORT_SYMBOL(lprocfs_find_named_value);
2386 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent,
2389 const struct file_operations *seq_fops,
2392 struct proc_dir_entry *entry;
2395 /* Disallow secretly (un)writable entries. */
2396 LASSERT((seq_fops->write == NULL) == ((mode & 0222) == 0));
2398 LPROCFS_WRITE_ENTRY();
2399 entry = create_proc_entry(name, mode, parent);
2401 entry->proc_fops = seq_fops;
2404 LPROCFS_WRITE_EXIT();
2411 EXPORT_SYMBOL(lprocfs_seq_create);
2413 int lprocfs_obd_seq_create(struct obd_device *dev,
2416 const struct file_operations *seq_fops,
2419 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2420 mode, seq_fops, data));
2422 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2424 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2426 if (value >= OBD_HIST_MAX)
2427 value = OBD_HIST_MAX - 1;
2429 spin_lock(&oh->oh_lock);
2430 oh->oh_buckets[value]++;
2431 spin_unlock(&oh->oh_lock);
2433 EXPORT_SYMBOL(lprocfs_oh_tally);
2435 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2439 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2442 lprocfs_oh_tally(oh, val);
2444 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2446 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2448 unsigned long ret = 0;
2451 for (i = 0; i < OBD_HIST_MAX; i++)
2452 ret += oh->oh_buckets[i];
2455 EXPORT_SYMBOL(lprocfs_oh_sum);
2457 void lprocfs_oh_clear(struct obd_histogram *oh)
2459 spin_lock(&oh->oh_lock);
2460 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2461 spin_unlock(&oh->oh_lock);
2463 EXPORT_SYMBOL(lprocfs_oh_clear);
2465 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2466 int count, int *eof, void *data)
2468 struct obd_device *obd = data;
2474 c += cfs_hash_debug_header(page, count);
2475 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2476 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2477 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2481 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2483 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2484 int count, int *eof, void *data)
2486 struct obd_device *obd = data;
2489 LASSERT(obd != NULL);
2490 LASSERT(count >= 0);
2492 /* Set start of user data returned to
2493 page + off since the user may have
2494 requested to read much smaller than
2495 what we need to read */
2496 *start = page + off;
2498 /* We know we are allocated a page here.
2499 Also we know that this function will
2500 not need to write more than a page
2501 so we can truncate at CFS_PAGE_SIZE. */
2502 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2504 /* Initialize the page */
2505 memset(page, 0, size);
2507 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2509 if (obd->obd_max_recoverable_clients == 0) {
2510 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2516 /* sampled unlocked, but really... */
2517 if (obd->obd_recovering == 0) {
2518 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2520 if (lprocfs_obd_snprintf(&page, size, &len,
2521 "recovery_start: %lu\n",
2522 obd->obd_recovery_start) <= 0)
2524 if (lprocfs_obd_snprintf(&page, size, &len,
2525 "recovery_duration: %lu\n",
2526 obd->obd_recovery_end -
2527 obd->obd_recovery_start) <= 0)
2529 /* Number of clients that have completed recovery */
2530 if (lprocfs_obd_snprintf(&page, size, &len,
2531 "completed_clients: %d/%d\n",
2532 obd->obd_max_recoverable_clients -
2533 obd->obd_stale_clients,
2534 obd->obd_max_recoverable_clients) <= 0)
2536 if (lprocfs_obd_snprintf(&page, size, &len,
2537 "replayed_requests: %d\n",
2538 obd->obd_replayed_requests) <= 0)
2540 if (lprocfs_obd_snprintf(&page, size, &len,
2541 "last_transno: "LPD64"\n",
2542 obd->obd_next_recovery_transno - 1)<=0)
2544 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2545 obd->obd_version_recov ?
2546 "ENABLED" : "DISABLED") <=0)
2548 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
2550 "DISABLED" : "ENABLED") <= 0)
2555 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2557 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2558 obd->obd_recovery_start) <= 0)
2560 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2561 cfs_time_current_sec() >=
2562 obd->obd_recovery_start +
2563 obd->obd_recovery_timeout ? 0 :
2564 obd->obd_recovery_start +
2565 obd->obd_recovery_timeout -
2566 cfs_time_current_sec()) <= 0)
2568 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2569 cfs_atomic_read(&obd->obd_connected_clients),
2570 obd->obd_max_recoverable_clients) <= 0)
2572 /* Number of clients that have completed recovery */
2573 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2574 cfs_atomic_read(&obd->obd_req_replay_clients))
2577 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2578 cfs_atomic_read(&obd->obd_lock_replay_clients))
2581 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2582 cfs_atomic_read(&obd->obd_connected_clients) -
2583 cfs_atomic_read(&obd->obd_lock_replay_clients))
2586 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2587 obd->obd_stale_clients) <= 0)
2589 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2590 obd->obd_replayed_requests) <= 0)
2592 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2593 obd->obd_requests_queued_for_recovery) <= 0)
2596 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2597 obd->obd_next_recovery_transno) <= 0)
2603 return min(count, len - (int)off);
2605 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2607 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
2608 int count, int *eof, void *data)
2610 struct obd_device *obd = (struct obd_device *)data;
2611 LASSERT(obd != NULL);
2613 return snprintf(page, count, "%d\n",
2614 obd->obd_recovery_ir_factor);
2616 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
2618 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
2619 unsigned long count, void *data)
2621 struct obd_device *obd = (struct obd_device *)data;
2623 LASSERT(obd != NULL);
2625 rc = lprocfs_write_helper(buffer, count, &val);
2629 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
2632 obd->obd_recovery_ir_factor = val;
2635 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
2637 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
2638 int count, int *eof, void *data)
2640 struct obd_device *obd = (struct obd_device *)data;
2641 LASSERT(obd != NULL);
2643 return snprintf(page, count, "%d\n",
2644 obd->obd_recovery_timeout);
2646 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
2648 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
2649 unsigned long count, void *data)
2651 struct obd_device *obd = (struct obd_device *)data;
2653 LASSERT(obd != NULL);
2655 rc = lprocfs_write_helper(buffer, count, &val);
2659 obd->obd_recovery_timeout = val;
2662 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
2664 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
2665 int count, int *eof, void *data)
2667 struct obd_device *obd = data;
2668 LASSERT(obd != NULL);
2670 return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
2672 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
2674 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
2675 unsigned long count, void *data)
2677 struct obd_device *obd = data;
2679 LASSERT(obd != NULL);
2681 rc = lprocfs_write_helper(buffer, count, &val);
2685 obd->obd_recovery_time_hard = val;
2688 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
2690 int lprocfs_obd_rd_mntdev(char *page, char **start, off_t off,
2691 int count, int *eof, void *data)
2693 struct obd_device *obd = (struct obd_device *)data;
2694 struct lustre_mount_info *lmi;
2695 const char *dev_name;
2697 LASSERT(obd != NULL);
2698 lmi = server_get_mount_2(obd->obd_name);
2699 dev_name = get_mntdev_name(lmi->lmi_sb);
2700 LASSERT(dev_name != NULL);
2702 server_put_mount_2(obd->obd_name, lmi->lmi_mnt);
2703 return snprintf(page, count, "%s\n", dev_name);
2705 EXPORT_SYMBOL(lprocfs_obd_rd_mntdev);
2707 int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
2708 int count, int *eof, void *data)
2710 struct obd_device *dev = data;
2711 struct client_obd *cli = &dev->u.cli;
2714 client_obd_list_lock(&cli->cl_loi_list_lock);
2715 rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
2716 client_obd_list_unlock(&cli->cl_loi_list_lock);
2719 EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
2721 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
2722 int count, int *eof, void *data)
2724 struct obd_device *obd = (struct obd_device *)data;
2725 struct obd_device_target *target = &obd->u.obt;
2727 LASSERT(obd != NULL);
2728 LASSERT(target->obt_magic == OBT_MAGIC);
2730 return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
2732 EXPORT_SYMBOL(lprocfs_target_rd_instance);