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",
981 int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
986 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
988 ret += snprintf(page + ret, count - ret, "%s%s",
989 ret ? sep : "", obd_connect_names[i]);
991 if (flags & ~(mask - 1))
992 ret += snprintf(page + ret, count - ret,
993 "%sunknown flags "LPX64,
994 ret ? sep : "", flags & ~(mask - 1));
997 EXPORT_SYMBOL(obd_connect_flags2str);
999 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
1000 int *eof, void *data)
1002 struct lprocfs_counter ret;
1003 struct lprocfs_counter_header *header;
1004 struct obd_device *obd = (struct obd_device *)data;
1005 struct obd_import *imp;
1006 struct obd_import_conn *conn;
1012 LASSERT(obd != NULL);
1013 LPROCFS_CLIMP_CHECK(obd);
1014 imp = obd->u.cli.cl_import;
1017 i = snprintf(page, count,
1023 " connect_flags: [",
1026 ptlrpc_import_state_name(imp->imp_state),
1027 imp->imp_connect_data.ocd_instance);
1028 i += obd_connect_flags2str(page + i, count - i,
1029 imp->imp_connect_data.ocd_connect_flags,
1031 i += snprintf(page + i, count - i,
1033 " import_flags: [");
1034 i += obd_import_flags2str(imp, page + i, count - i);
1036 i += snprintf(page + i, count - i,
1039 " failover_nids: [");
1040 spin_lock(&imp->imp_lock);
1042 cfs_list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
1043 i += snprintf(page + i, count - i, "%s%s", j ? ", " : "",
1044 libcfs_nid2str(conn->oic_conn->c_peer.nid));
1047 i += snprintf(page + i, count - i,
1049 " current_connection: %s\n"
1050 " connection_attempts: %u\n"
1052 " in-progress_invalidations: %u\n",
1053 imp->imp_connection == NULL ? "<none>" :
1054 libcfs_nid2str(imp->imp_connection->c_peer.nid),
1056 imp->imp_generation,
1057 cfs_atomic_read(&imp->imp_inval_count));
1058 spin_unlock(&imp->imp_lock);
1060 header = &obd->obd_svc_stats->ls_cnt_header[PTLRPC_REQWAIT_CNTR];
1061 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
1062 if (ret.lc_count != 0) {
1063 /* first argument to do_div MUST be __u64 */
1064 __u64 sum = ret.lc_sum;
1065 do_div(sum, ret.lc_count);
1069 i += snprintf(page + i, count - i,
1072 " unregistering: %u\n"
1074 " avg_waittime: "LPU64" %s\n",
1075 cfs_atomic_read(&imp->imp_inflight),
1076 cfs_atomic_read(&imp->imp_unregistering),
1077 cfs_atomic_read(&imp->imp_timeouts),
1078 ret.lc_sum, header->lc_units);
1081 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
1082 if (imp->imp_at.iat_portal[j] == 0)
1084 k = max_t(unsigned int, k,
1085 at_get(&imp->imp_at.iat_service_estimate[j]));
1087 i += snprintf(page + i, count - i,
1088 " service_estimates:\n"
1089 " services: %u sec\n"
1090 " network: %u sec\n",
1092 at_get(&imp->imp_at.iat_net_latency));
1094 i += snprintf(page + i, count - i,
1096 " last_replay: "LPU64"\n"
1097 " peer_committed: "LPU64"\n"
1098 " last_checked: "LPU64"\n",
1099 imp->imp_last_replay_transno,
1100 imp->imp_peer_committed_transno,
1101 imp->imp_last_transno_checked);
1103 /* avg data rates */
1104 for (rw = 0; rw <= 1; rw++) {
1105 lprocfs_stats_collect(obd->obd_svc_stats,
1106 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
1108 if (ret.lc_sum > 0 && ret.lc_count > 0) {
1109 /* first argument to do_div MUST be __u64 */
1110 __u64 sum = ret.lc_sum;
1111 do_div(sum, ret.lc_count);
1113 i += snprintf(page + i, count - i,
1114 " %s_data_averages:\n"
1115 " bytes_per_rpc: "LPU64"\n",
1116 rw ? "write" : "read",
1119 k = (int)ret.lc_sum;
1120 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
1121 header = &obd->obd_svc_stats->ls_cnt_header[j];
1122 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
1123 if (ret.lc_sum > 0 && ret.lc_count != 0) {
1124 /* first argument to do_div MUST be __u64 */
1125 __u64 sum = ret.lc_sum;
1126 do_div(sum, ret.lc_count);
1128 i += snprintf(page + i, count - i,
1129 " %s_per_rpc: "LPU64"\n",
1130 header->lc_units, ret.lc_sum);
1131 j = (int)ret.lc_sum;
1133 i += snprintf(page + i, count - i,
1134 " MB_per_sec: %u.%.02u\n",
1135 k / j, (100 * k / j) % 100);
1139 LPROCFS_CLIMP_EXIT(obd);
1142 EXPORT_SYMBOL(lprocfs_rd_import);
1144 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
1145 int *eof, void *data)
1147 struct obd_device *obd = (struct obd_device *)data;
1148 struct obd_import *imp;
1151 LASSERT(obd != NULL);
1152 LPROCFS_CLIMP_CHECK(obd);
1153 imp = obd->u.cli.cl_import;
1156 i = snprintf(page, count, "current_state: %s\n",
1157 ptlrpc_import_state_name(imp->imp_state));
1158 i += snprintf(page + i, count - i,
1159 "state_history:\n");
1160 k = imp->imp_state_hist_idx;
1161 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
1162 struct import_state_hist *ish =
1163 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
1164 if (ish->ish_state == 0)
1166 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
1168 ptlrpc_import_state_name(ish->ish_state));
1171 LPROCFS_CLIMP_EXIT(obd);
1174 EXPORT_SYMBOL(lprocfs_rd_state);
1176 int lprocfs_at_hist_helper(char *page, int count, int rc,
1177 struct adaptive_timeout *at)
1180 for (i = 0; i < AT_BINS; i++)
1181 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
1182 rc += snprintf(page + rc, count - rc, "\n");
1185 EXPORT_SYMBOL(lprocfs_at_hist_helper);
1187 /* See also ptlrpc_lprocfs_rd_timeouts */
1188 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
1189 int *eof, void *data)
1191 struct obd_device *obd = (struct obd_device *)data;
1192 struct obd_import *imp;
1193 unsigned int cur, worst;
1198 LASSERT(obd != NULL);
1199 LPROCFS_CLIMP_CHECK(obd);
1200 imp = obd->u.cli.cl_import;
1203 now = cfs_time_current_sec();
1205 /* Some network health info for kicks */
1206 s2dhms(&ts, now - imp->imp_last_reply_time);
1207 rc += snprintf(page + rc, count - rc,
1208 "%-10s : %ld, "DHMS_FMT" ago\n",
1209 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
1211 cur = at_get(&imp->imp_at.iat_net_latency);
1212 worst = imp->imp_at.iat_net_latency.at_worst_ever;
1213 worstt = imp->imp_at.iat_net_latency.at_worst_time;
1214 s2dhms(&ts, now - worstt);
1215 rc += snprintf(page + rc, count - rc,
1216 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
1217 "network", cur, worst, worstt, DHMS_VARS(&ts));
1218 rc = lprocfs_at_hist_helper(page, count, rc,
1219 &imp->imp_at.iat_net_latency);
1221 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
1222 if (imp->imp_at.iat_portal[i] == 0)
1224 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
1225 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
1226 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
1227 s2dhms(&ts, now - worstt);
1228 rc += snprintf(page + rc, count - rc,
1229 "portal %-2d : cur %3u worst %3u (at %ld, "
1230 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
1231 cur, worst, worstt, DHMS_VARS(&ts));
1232 rc = lprocfs_at_hist_helper(page, count, rc,
1233 &imp->imp_at.iat_service_estimate[i]);
1236 LPROCFS_CLIMP_EXIT(obd);
1239 EXPORT_SYMBOL(lprocfs_rd_timeouts);
1241 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1242 int count, int *eof, void *data)
1244 struct obd_device *obd = data;
1248 LPROCFS_CLIMP_CHECK(obd);
1249 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1250 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1251 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1252 ret += snprintf(page + ret, count - ret, "\n");
1253 LPROCFS_CLIMP_EXIT(obd);
1256 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1258 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1259 int *eof, void *data)
1261 struct obd_device *obd = data;
1263 LASSERT(obd != NULL);
1265 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1267 EXPORT_SYMBOL(lprocfs_rd_num_exports);
1269 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1270 int *eof, void *data)
1272 struct obd_type *class = (struct obd_type*) data;
1274 LASSERT(class != NULL);
1276 return snprintf(page, count, "%d\n", class->typ_refcnt);
1278 EXPORT_SYMBOL(lprocfs_rd_numrefs);
1280 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1284 LASSERT(obd != NULL);
1285 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1286 LASSERT(obd->obd_type->typ_procroot != NULL);
1288 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1289 obd->obd_type->typ_procroot,
1291 if (IS_ERR(obd->obd_proc_entry)) {
1292 rc = PTR_ERR(obd->obd_proc_entry);
1293 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1294 obd->obd_proc_entry = NULL;
1298 EXPORT_SYMBOL(lprocfs_obd_setup);
1300 int lprocfs_obd_cleanup(struct obd_device *obd)
1304 if (obd->obd_proc_exports_entry) {
1305 /* Should be no exports left */
1306 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1307 lprocfs_remove(&obd->obd_proc_exports_entry);
1308 obd->obd_proc_exports_entry = NULL;
1310 if (obd->obd_proc_entry) {
1311 lprocfs_remove(&obd->obd_proc_entry);
1312 obd->obd_proc_entry = NULL;
1316 EXPORT_SYMBOL(lprocfs_obd_cleanup);
1318 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1320 CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
1321 client_stat->nid_proc, client_stat->nid_stats,
1322 client_stat->nid_brw_stats);
1324 LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
1325 "nid %s:count %d\n", libcfs_nid2str(client_stat->nid),
1326 atomic_read(&client_stat->nid_exp_ref_count));
1328 if (client_stat->nid_proc)
1329 lprocfs_remove(&client_stat->nid_proc);
1331 if (client_stat->nid_stats)
1332 lprocfs_free_stats(&client_stat->nid_stats);
1334 if (client_stat->nid_brw_stats)
1335 OBD_FREE_PTR(client_stat->nid_brw_stats);
1337 if (client_stat->nid_ldlm_stats)
1338 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1340 OBD_FREE_PTR(client_stat);
1345 void lprocfs_free_per_client_stats(struct obd_device *obd)
1347 cfs_hash_t *hash = obd->obd_nid_stats_hash;
1348 struct nid_stat *stat;
1351 /* we need extra list - because hash_exit called to early */
1352 /* not need locking because all clients is died */
1353 while (!cfs_list_empty(&obd->obd_nid_stats)) {
1354 stat = cfs_list_entry(obd->obd_nid_stats.next,
1355 struct nid_stat, nid_list);
1356 cfs_list_del_init(&stat->nid_list);
1357 cfs_hash_del(hash, &stat->nid, &stat->nid_hash);
1358 lprocfs_free_client_stats(stat);
1362 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
1364 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1365 enum lprocfs_stats_flags flags)
1367 struct lprocfs_stats *stats;
1368 unsigned int num_entry;
1369 unsigned int percpusize = 0;
1375 if (lprocfs_no_percpu_stats != 0)
1376 flags |= LPROCFS_STATS_FLAG_NOPERCPU;
1378 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1381 num_entry = cfs_num_possible_cpus();
1383 /* alloc percpu pointers for all possible cpu slots */
1384 LIBCFS_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1388 stats->ls_num = num;
1389 stats->ls_flags = flags;
1390 spin_lock_init(&stats->ls_lock);
1392 /* alloc num of counter headers */
1393 LIBCFS_ALLOC(stats->ls_cnt_header,
1394 stats->ls_num * sizeof(struct lprocfs_counter_header));
1395 if (stats->ls_cnt_header == NULL)
1398 if ((flags & LPROCFS_STATS_FLAG_NOPERCPU) != 0) {
1399 /* contains only one set counters */
1400 percpusize = lprocfs_stats_counter_size(stats);
1401 LIBCFS_ALLOC_ATOMIC(stats->ls_percpu[0], percpusize);
1402 if (stats->ls_percpu[0] == NULL)
1404 stats->ls_biggest_alloc_num = 1;
1405 } else if ((flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0) {
1406 /* alloc all percpu data, currently only obd_memory use this */
1407 for (i = 0; i < num_entry; ++i)
1408 if (lprocfs_stats_alloc_one(stats, i) < 0)
1415 lprocfs_free_stats(&stats);
1418 EXPORT_SYMBOL(lprocfs_alloc_stats);
1420 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1422 struct lprocfs_stats *stats = *statsh;
1423 unsigned int num_entry;
1424 unsigned int percpusize;
1427 if (stats == NULL || stats->ls_num == 0)
1431 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1434 num_entry = cfs_num_possible_cpus();
1436 percpusize = lprocfs_stats_counter_size(stats);
1437 for (i = 0; i < num_entry; i++)
1438 if (stats->ls_percpu[i] != NULL)
1439 LIBCFS_FREE(stats->ls_percpu[i], percpusize);
1440 if (stats->ls_cnt_header != NULL)
1441 LIBCFS_FREE(stats->ls_cnt_header, stats->ls_num *
1442 sizeof(struct lprocfs_counter_header));
1443 LIBCFS_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1445 EXPORT_SYMBOL(lprocfs_free_stats);
1447 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1449 struct lprocfs_counter *percpu_cntr;
1450 struct lprocfs_counter_header *header;
1453 unsigned int num_entry;
1454 unsigned long flags = 0;
1456 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1458 for (i = 0; i < num_entry; i++) {
1459 if (stats->ls_percpu[i] == NULL)
1461 for (j = 0; j < stats->ls_num; j++) {
1462 header = &stats->ls_cnt_header[j];
1463 percpu_cntr = lprocfs_stats_counter_get(stats, i, j);
1464 percpu_cntr->lc_count = 0;
1465 percpu_cntr->lc_min = LC_MIN_INIT;
1466 percpu_cntr->lc_max = 0;
1467 percpu_cntr->lc_sumsquare = 0;
1468 percpu_cntr->lc_sum = 0;
1469 if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
1470 percpu_cntr->lc_sum_irq = 0;
1474 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1476 EXPORT_SYMBOL(lprocfs_clear_stats);
1478 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1479 size_t len, loff_t *off)
1481 struct seq_file *seq = file->private_data;
1482 struct lprocfs_stats *stats = seq->private;
1484 lprocfs_clear_stats(stats);
1489 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1491 struct lprocfs_stats *stats = p->private;
1492 /* return 1st cpu location */
1493 return (*pos >= stats->ls_num) ? NULL :
1494 lprocfs_stats_counter_get(stats, 0, *pos);
1497 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1501 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1503 struct lprocfs_stats *stats = p->private;
1505 return (*pos >= stats->ls_num) ? NULL :
1506 lprocfs_stats_counter_get(stats, 0, *pos);
1509 /* seq file export of one lprocfs counter */
1510 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1512 struct lprocfs_stats *stats = p->private;
1513 struct lprocfs_counter *cntr = v;
1514 struct lprocfs_counter ret;
1515 struct lprocfs_counter_header *header;
1520 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
1522 cfs_gettimeofday(&now);
1523 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1524 "snapshot_time", now.tv_sec, now.tv_usec);
1528 entry_size = sizeof(*cntr);
1529 if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
1530 entry_size += sizeof(__s64);
1531 idx = ((void *)cntr - (void *)&(stats->ls_percpu[0])->lp_cntr[0]) /
1534 header = &stats->ls_cnt_header[idx];
1535 lprocfs_stats_collect(stats, idx, &ret);
1537 if (ret.lc_count == 0)
1540 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", header->lc_name,
1541 ret.lc_count, header->lc_units);
1546 if ((header->lc_config & LPROCFS_CNTR_AVGMINMAX) &&
1547 (ret.lc_count > 0)) {
1548 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1549 ret.lc_min, ret.lc_max, ret.lc_sum);
1552 if (header->lc_config & LPROCFS_CNTR_STDDEV)
1553 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1557 rc = seq_printf(p, "\n");
1559 return (rc < 0) ? rc : 0;
1562 struct seq_operations lprocfs_stats_seq_sops = {
1563 start: lprocfs_stats_seq_start,
1564 stop: lprocfs_stats_seq_stop,
1565 next: lprocfs_stats_seq_next,
1566 show: lprocfs_stats_seq_show,
1569 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1571 struct proc_dir_entry *dp = PDE(inode);
1572 struct seq_file *seq;
1575 if (LPROCFS_ENTRY_AND_CHECK(dp))
1578 rc = seq_open(file, &lprocfs_stats_seq_sops);
1583 seq = file->private_data;
1584 seq->private = dp->data;
1588 struct file_operations lprocfs_stats_seq_fops = {
1589 .owner = THIS_MODULE,
1590 .open = lprocfs_stats_seq_open,
1592 .write = lprocfs_stats_seq_write,
1593 .llseek = seq_lseek,
1594 .release = lprocfs_seq_release,
1597 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1598 struct lprocfs_stats *stats)
1600 struct proc_dir_entry *entry;
1601 LASSERT(root != NULL);
1603 LPROCFS_WRITE_ENTRY();
1604 entry = create_proc_entry(name, 0644, root);
1606 entry->proc_fops = &lprocfs_stats_seq_fops;
1607 entry->data = stats;
1610 LPROCFS_WRITE_EXIT();
1617 EXPORT_SYMBOL(lprocfs_register_stats);
1619 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1620 unsigned conf, const char *name, const char *units)
1622 struct lprocfs_counter_header *header;
1623 struct lprocfs_counter *percpu_cntr;
1624 unsigned long flags = 0;
1626 unsigned int num_cpu;
1628 LASSERT(stats != NULL);
1630 header = &stats->ls_cnt_header[index];
1631 LASSERTF(header != NULL, "Failed to allocate stats header:[%d]%s/%s\n",
1632 index, name, units);
1634 header->lc_config = conf;
1635 header->lc_name = name;
1636 header->lc_units = units;
1638 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1639 for (i = 0; i < num_cpu; ++i) {
1640 if (stats->ls_percpu[i] == NULL)
1642 percpu_cntr = lprocfs_stats_counter_get(stats, i, index);
1643 percpu_cntr->lc_count = 0;
1644 percpu_cntr->lc_min = LC_MIN_INIT;
1645 percpu_cntr->lc_max = 0;
1646 percpu_cntr->lc_sumsquare = 0;
1647 percpu_cntr->lc_sum = 0;
1648 if ((stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
1649 percpu_cntr->lc_sum_irq = 0;
1651 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1653 EXPORT_SYMBOL(lprocfs_counter_init);
1655 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1657 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1658 LASSERT(coffset < stats->ls_num); \
1659 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1662 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1664 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1665 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1666 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1667 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1668 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1669 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1670 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1671 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1672 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1673 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1674 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1675 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1676 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1677 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1678 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1679 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1680 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1681 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1682 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1683 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1684 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1685 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1686 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1687 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1688 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1689 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1690 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1691 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1692 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1693 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1694 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1695 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1696 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1697 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1698 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1699 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1700 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1701 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1702 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1703 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1704 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1705 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1706 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1707 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
1708 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1709 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1710 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1711 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1712 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1713 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1714 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1715 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1716 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1717 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1718 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1719 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1720 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1721 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1722 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1723 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1724 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1725 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1726 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1727 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1728 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1729 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1730 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1732 EXPORT_SYMBOL(lprocfs_init_ops_stats);
1734 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1736 struct lprocfs_stats *stats;
1737 unsigned int num_stats;
1740 LASSERT(obd->obd_stats == NULL);
1741 LASSERT(obd->obd_proc_entry != NULL);
1742 LASSERT(obd->obd_cntr_base == 0);
1744 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1745 num_private_stats - 1 /* o_owner */;
1746 stats = lprocfs_alloc_stats(num_stats, 0);
1750 lprocfs_init_ops_stats(num_private_stats, stats);
1752 for (i = num_private_stats; i < num_stats; i++) {
1753 /* If this LBUGs, it is likely that an obd
1754 * operation was added to struct obd_ops in
1755 * <obd.h>, and that the corresponding line item
1756 * LPROCFS_OBD_OP_INIT(.., .., opname)
1757 * is missing from the list above. */
1758 LASSERTF(stats->ls_cnt_header[i].lc_name != NULL,
1759 "Missing obd_stat initializer obd_op "
1760 "operation at offset %d.\n", i - num_private_stats);
1762 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1764 lprocfs_free_stats(&stats);
1766 obd->obd_stats = stats;
1767 obd->obd_cntr_base = num_private_stats;
1771 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
1773 void lprocfs_free_obd_stats(struct obd_device *obd)
1776 lprocfs_free_stats(&obd->obd_stats);
1778 EXPORT_SYMBOL(lprocfs_free_obd_stats);
1780 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1782 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1783 LASSERT(coffset < stats->ls_num); \
1784 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1787 void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats)
1789 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1790 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1791 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
1792 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1793 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1794 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1795 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1796 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1797 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1798 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1799 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1800 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1801 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1802 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1803 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1804 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1805 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1806 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1807 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1808 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1809 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1810 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1811 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1812 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1813 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1814 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1815 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1816 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1817 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1818 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1819 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1820 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1822 EXPORT_SYMBOL(lprocfs_init_mps_stats);
1824 int lprocfs_alloc_md_stats(struct obd_device *obd,
1825 unsigned num_private_stats)
1827 struct lprocfs_stats *stats;
1828 unsigned int num_stats;
1831 LASSERT(obd->md_stats == NULL);
1832 LASSERT(obd->obd_proc_entry != NULL);
1833 LASSERT(obd->md_cntr_base == 0);
1835 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1837 stats = lprocfs_alloc_stats(num_stats, 0);
1841 lprocfs_init_mps_stats(num_private_stats, stats);
1843 for (i = num_private_stats; i < num_stats; i++) {
1844 if (stats->ls_cnt_header[i].lc_name == NULL) {
1845 CERROR("Missing md_stat initializer md_op "
1846 "operation at offset %d. Aborting.\n",
1847 i - num_private_stats);
1851 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1853 lprocfs_free_stats(&stats);
1855 obd->md_stats = stats;
1856 obd->md_cntr_base = num_private_stats;
1860 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
1862 void lprocfs_free_md_stats(struct obd_device *obd)
1864 struct lprocfs_stats *stats = obd->md_stats;
1866 if (stats != NULL) {
1867 obd->md_stats = NULL;
1868 obd->md_cntr_base = 0;
1869 lprocfs_free_stats(&stats);
1872 EXPORT_SYMBOL(lprocfs_free_md_stats);
1874 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1876 lprocfs_counter_init(ldlm_stats,
1877 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1878 0, "ldlm_enqueue", "reqs");
1879 lprocfs_counter_init(ldlm_stats,
1880 LDLM_CONVERT - LDLM_FIRST_OPC,
1881 0, "ldlm_convert", "reqs");
1882 lprocfs_counter_init(ldlm_stats,
1883 LDLM_CANCEL - LDLM_FIRST_OPC,
1884 0, "ldlm_cancel", "reqs");
1885 lprocfs_counter_init(ldlm_stats,
1886 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1887 0, "ldlm_bl_callback", "reqs");
1888 lprocfs_counter_init(ldlm_stats,
1889 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1890 0, "ldlm_cp_callback", "reqs");
1891 lprocfs_counter_init(ldlm_stats,
1892 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1893 0, "ldlm_gl_callback", "reqs");
1895 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
1897 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1898 int *eof, void *data)
1900 struct obd_export *exp = data;
1901 LASSERT(exp != NULL);
1903 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1906 struct exp_uuid_cb_data {
1914 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1915 int count, int *eof, int *len)
1917 cb_data->page = page;
1918 cb_data->count = count;
1923 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1924 cfs_hlist_node_t *hnode, void *cb_data)
1927 struct obd_export *exp = cfs_hash_object(hs, hnode);
1928 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1930 if (exp->exp_nid_stats)
1931 *data->len += snprintf((data->page + *data->len),
1932 data->count, "%s\n",
1933 obd_uuid2str(&exp->exp_client_uuid));
1937 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1938 int *eof, void *data)
1940 struct nid_stat *stats = (struct nid_stat *)data;
1941 struct exp_uuid_cb_data cb_data;
1942 struct obd_device *obd = stats->nid_obd;
1947 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1948 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1949 lprocfs_exp_print_uuid, &cb_data);
1950 return (*cb_data.len);
1953 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1954 cfs_hlist_node_t *hnode, void *cb_data)
1957 struct exp_uuid_cb_data *data = cb_data;
1958 struct obd_export *exp = cfs_hash_object(hs, hnode);
1960 if (exp->exp_lock_hash != NULL) {
1962 *data->len += cfs_hash_debug_header(data->page,
1965 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1972 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1973 int *eof, void *data)
1975 struct nid_stat *stats = (struct nid_stat *)data;
1976 struct exp_uuid_cb_data cb_data;
1977 struct obd_device *obd = stats->nid_obd;
1982 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1984 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1985 lprocfs_exp_print_hash, &cb_data);
1986 return (*cb_data.len);
1989 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1990 int count, int *eof, void *data)
1993 return snprintf(page, count, "%s\n",
1994 "Write into this file to clear all nid stats and "
1995 "stale nid entries");
1997 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1999 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
2001 struct nid_stat *stat = obj;
2005 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
2006 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 1) {
2007 /* object has only hash references. */
2008 spin_lock(&stat->nid_obd->obd_nid_lock);
2009 cfs_list_move(&stat->nid_list, data);
2010 spin_unlock(&stat->nid_obd->obd_nid_lock);
2013 /* we has reference to object - only clear data*/
2014 if (stat->nid_stats)
2015 lprocfs_clear_stats(stat->nid_stats);
2017 if (stat->nid_brw_stats) {
2018 for (i = 0; i < BRW_LAST; i++)
2019 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
2024 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
2025 unsigned long count, void *data)
2027 struct obd_device *obd = (struct obd_device *)data;
2028 struct nid_stat *client_stat;
2029 CFS_LIST_HEAD(free_list);
2031 cfs_hash_cond_del(obd->obd_nid_stats_hash,
2032 lprocfs_nid_stats_clear_write_cb, &free_list);
2034 while (!cfs_list_empty(&free_list)) {
2035 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
2037 cfs_list_del_init(&client_stat->nid_list);
2038 lprocfs_free_client_stats(client_stat);
2043 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
2045 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
2047 struct nid_stat *new_stat, *old_stat;
2048 struct obd_device *obd = NULL;
2049 cfs_proc_dir_entry_t *entry;
2050 char *buffer = NULL;
2056 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
2057 !exp->exp_obd->obd_nid_stats_hash)
2060 /* not test against zero because eric say:
2061 * You may only test nid against another nid, or LNET_NID_ANY.
2062 * Anything else is nonsense.*/
2063 if (!nid || *nid == LNET_NID_ANY)
2068 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
2070 OBD_ALLOC_PTR(new_stat);
2071 if (new_stat == NULL)
2074 new_stat->nid = *nid;
2075 new_stat->nid_obd = exp->exp_obd;
2076 /* we need set default refcount to 1 to balance obd_disconnect */
2077 cfs_atomic_set(&new_stat->nid_exp_ref_count, 1);
2079 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
2080 nid, &new_stat->nid_hash);
2081 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
2082 old_stat, libcfs_nid2str(*nid),
2083 cfs_atomic_read(&new_stat->nid_exp_ref_count));
2085 /* We need to release old stats because lprocfs_exp_cleanup() hasn't
2086 * been and will never be called. */
2087 if (exp->exp_nid_stats) {
2088 nidstat_putref(exp->exp_nid_stats);
2089 exp->exp_nid_stats = NULL;
2092 /* Return -EALREADY here so that we know that the /proc
2093 * entry already has been created */
2094 if (old_stat != new_stat) {
2095 exp->exp_nid_stats = old_stat;
2096 GOTO(destroy_new, rc = -EALREADY);
2098 /* not found - create */
2099 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
2101 GOTO(destroy_new, rc = -ENOMEM);
2103 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
2104 new_stat->nid_proc = lprocfs_register(buffer,
2105 obd->obd_proc_exports_entry,
2107 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
2109 if (new_stat->nid_proc == NULL) {
2110 CERROR("Error making export directory for nid %s\n",
2111 libcfs_nid2str(*nid));
2112 GOTO(destroy_new_ns, rc = -ENOMEM);
2115 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
2116 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
2117 if (IS_ERR(entry)) {
2118 CWARN("Error adding the NID stats file\n");
2119 rc = PTR_ERR(entry);
2120 GOTO(destroy_new_ns, rc);
2123 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
2124 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
2125 if (IS_ERR(entry)) {
2126 CWARN("Error adding the hash file\n");
2127 rc = PTR_ERR(entry);
2128 GOTO(destroy_new_ns, rc);
2131 exp->exp_nid_stats = new_stat;
2133 /* protect competitive add to list, not need locking on destroy */
2134 spin_lock(&obd->obd_nid_lock);
2135 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
2136 spin_unlock(&obd->obd_nid_lock);
2141 if (new_stat->nid_proc != NULL)
2142 lprocfs_remove(&new_stat->nid_proc);
2143 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
2146 nidstat_putref(new_stat);
2147 OBD_FREE_PTR(new_stat);
2150 EXPORT_SYMBOL(lprocfs_exp_setup);
2152 int lprocfs_exp_cleanup(struct obd_export *exp)
2154 struct nid_stat *stat = exp->exp_nid_stats;
2156 if(!stat || !exp->exp_obd)
2159 nidstat_putref(exp->exp_nid_stats);
2160 exp->exp_nid_stats = NULL;
2164 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2166 int lprocfs_write_helper(const char *buffer, unsigned long count,
2169 return lprocfs_write_frac_helper(buffer, count, val, 1);
2171 EXPORT_SYMBOL(lprocfs_write_helper);
2173 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
2176 char kernbuf[20], *end, *pbuf;
2178 if (count > (sizeof(kernbuf) - 1))
2181 if (cfs_copy_from_user(kernbuf, buffer, count))
2184 kernbuf[count] = '\0';
2191 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2195 if (end != NULL && *end == '.') {
2196 int temp_val, pow = 1;
2200 if (strlen(pbuf) > 5)
2201 pbuf[5] = '\0'; /*only allow 5bits fractional*/
2203 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2206 for (i = 0; i < (end - pbuf); i++)
2209 *val += temp_val / pow;
2214 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2216 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
2219 long decimal_val, frac_val;
2225 decimal_val = val / mult;
2226 prtn = snprintf(buffer, count, "%ld", decimal_val);
2227 frac_val = val % mult;
2229 if (prtn < (count - 4) && frac_val > 0) {
2231 int i, temp_mult = 1, frac_bits = 0;
2233 temp_frac = frac_val * 10;
2234 buffer[prtn++] = '.';
2235 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
2236 /* only reserved 2 bits fraction */
2237 buffer[prtn++] ='0';
2242 * Need to think these cases :
2243 * 1. #echo x.00 > /proc/xxx output result : x
2244 * 2. #echo x.0x > /proc/xxx output result : x.0x
2245 * 3. #echo x.x0 > /proc/xxx output result : x.x
2246 * 4. #echo x.xx > /proc/xxx output result : x.xx
2247 * Only reserved 2 bits fraction.
2249 for (i = 0; i < (5 - prtn); i++)
2252 frac_bits = min((int)count - prtn, 3 - frac_bits);
2253 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
2254 frac_val * temp_mult / mult);
2257 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
2259 if (buffer[prtn] == '.') {
2266 buffer[prtn++] ='\n';
2269 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2271 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
2273 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
2275 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2277 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
2278 __u64 *val, int mult)
2280 char kernbuf[22], *end, *pbuf;
2281 __u64 whole, frac = 0, units;
2282 unsigned frac_d = 1;
2284 if (count > (sizeof(kernbuf) - 1))
2287 if (cfs_copy_from_user(kernbuf, buffer, count))
2290 kernbuf[count] = '\0';
2297 whole = simple_strtoull(pbuf, &end, 10);
2301 if (end != NULL && *end == '.') {
2305 /* need to limit frac_d to a __u32 */
2306 if (strlen(pbuf) > 10)
2309 frac = simple_strtoull(pbuf, &end, 10);
2310 /* count decimal places */
2311 for (i = 0; i < (end - pbuf); i++)
2328 /* Specified units override the multiplier */
2330 mult = mult < 0 ? -units : units;
2333 do_div(frac, frac_d);
2334 *val = whole * mult + frac;
2337 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2339 static char *lprocfs_strnstr(const char *s1, const char *s2, size_t len)
2348 if (!memcmp(s1, s2, l2))
2356 * Find the string \a name in the input \a buffer, and return a pointer to the
2357 * value immediately following \a name, reducing \a count appropriately.
2358 * If \a name is not found the original \a buffer is returned.
2360 char *lprocfs_find_named_value(const char *buffer, const char *name,
2361 unsigned long *count)
2364 size_t buflen = *count;
2366 /* there is no strnstr() in rhel5 and ubuntu kernels */
2367 val = lprocfs_strnstr(buffer, name, buflen);
2369 return (char *)buffer;
2371 val += strlen(name); /* skip prefix */
2372 while (val < buffer + buflen && isspace(*val)) /* skip separator */
2376 while (val < buffer + buflen && isalnum(*val)) {
2381 return val - *count;
2383 EXPORT_SYMBOL(lprocfs_find_named_value);
2385 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent,
2388 const struct file_operations *seq_fops,
2391 struct proc_dir_entry *entry;
2394 /* Disallow secretly (un)writable entries. */
2395 LASSERT((seq_fops->write == NULL) == ((mode & 0222) == 0));
2397 LPROCFS_WRITE_ENTRY();
2398 entry = create_proc_entry(name, mode, parent);
2400 entry->proc_fops = seq_fops;
2403 LPROCFS_WRITE_EXIT();
2410 EXPORT_SYMBOL(lprocfs_seq_create);
2412 int lprocfs_obd_seq_create(struct obd_device *dev,
2415 const struct file_operations *seq_fops,
2418 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2419 mode, seq_fops, data));
2421 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2423 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2425 if (value >= OBD_HIST_MAX)
2426 value = OBD_HIST_MAX - 1;
2428 spin_lock(&oh->oh_lock);
2429 oh->oh_buckets[value]++;
2430 spin_unlock(&oh->oh_lock);
2432 EXPORT_SYMBOL(lprocfs_oh_tally);
2434 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2438 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2441 lprocfs_oh_tally(oh, val);
2443 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2445 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2447 unsigned long ret = 0;
2450 for (i = 0; i < OBD_HIST_MAX; i++)
2451 ret += oh->oh_buckets[i];
2454 EXPORT_SYMBOL(lprocfs_oh_sum);
2456 void lprocfs_oh_clear(struct obd_histogram *oh)
2458 spin_lock(&oh->oh_lock);
2459 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2460 spin_unlock(&oh->oh_lock);
2462 EXPORT_SYMBOL(lprocfs_oh_clear);
2464 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2465 int count, int *eof, void *data)
2467 struct obd_device *obd = data;
2473 c += cfs_hash_debug_header(page, count);
2474 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2475 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2476 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2480 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2482 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2483 int count, int *eof, void *data)
2485 struct obd_device *obd = data;
2488 LASSERT(obd != NULL);
2489 LASSERT(count >= 0);
2491 /* Set start of user data returned to
2492 page + off since the user may have
2493 requested to read much smaller than
2494 what we need to read */
2495 *start = page + off;
2497 /* We know we are allocated a page here.
2498 Also we know that this function will
2499 not need to write more than a page
2500 so we can truncate at CFS_PAGE_SIZE. */
2501 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2503 /* Initialize the page */
2504 memset(page, 0, size);
2506 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2508 if (obd->obd_max_recoverable_clients == 0) {
2509 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2515 /* sampled unlocked, but really... */
2516 if (obd->obd_recovering == 0) {
2517 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2519 if (lprocfs_obd_snprintf(&page, size, &len,
2520 "recovery_start: %lu\n",
2521 obd->obd_recovery_start) <= 0)
2523 if (lprocfs_obd_snprintf(&page, size, &len,
2524 "recovery_duration: %lu\n",
2525 obd->obd_recovery_end -
2526 obd->obd_recovery_start) <= 0)
2528 /* Number of clients that have completed recovery */
2529 if (lprocfs_obd_snprintf(&page, size, &len,
2530 "completed_clients: %d/%d\n",
2531 obd->obd_max_recoverable_clients -
2532 obd->obd_stale_clients,
2533 obd->obd_max_recoverable_clients) <= 0)
2535 if (lprocfs_obd_snprintf(&page, size, &len,
2536 "replayed_requests: %d\n",
2537 obd->obd_replayed_requests) <= 0)
2539 if (lprocfs_obd_snprintf(&page, size, &len,
2540 "last_transno: "LPD64"\n",
2541 obd->obd_next_recovery_transno - 1)<=0)
2543 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2544 obd->obd_version_recov ?
2545 "ENABLED" : "DISABLED") <=0)
2547 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
2549 "DISABLED" : "ENABLED") <= 0)
2554 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2556 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2557 obd->obd_recovery_start) <= 0)
2559 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2560 cfs_time_current_sec() >=
2561 obd->obd_recovery_start +
2562 obd->obd_recovery_timeout ? 0 :
2563 obd->obd_recovery_start +
2564 obd->obd_recovery_timeout -
2565 cfs_time_current_sec()) <= 0)
2567 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2568 cfs_atomic_read(&obd->obd_connected_clients),
2569 obd->obd_max_recoverable_clients) <= 0)
2571 /* Number of clients that have completed recovery */
2572 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2573 cfs_atomic_read(&obd->obd_req_replay_clients))
2576 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2577 cfs_atomic_read(&obd->obd_lock_replay_clients))
2580 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2581 cfs_atomic_read(&obd->obd_connected_clients) -
2582 cfs_atomic_read(&obd->obd_lock_replay_clients))
2585 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2586 obd->obd_stale_clients) <= 0)
2588 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2589 obd->obd_replayed_requests) <= 0)
2591 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2592 obd->obd_requests_queued_for_recovery) <= 0)
2595 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2596 obd->obd_next_recovery_transno) <= 0)
2602 return min(count, len - (int)off);
2604 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2606 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
2607 int count, int *eof, void *data)
2609 struct obd_device *obd = (struct obd_device *)data;
2610 LASSERT(obd != NULL);
2612 return snprintf(page, count, "%d\n",
2613 obd->obd_recovery_ir_factor);
2615 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
2617 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
2618 unsigned long count, void *data)
2620 struct obd_device *obd = (struct obd_device *)data;
2622 LASSERT(obd != NULL);
2624 rc = lprocfs_write_helper(buffer, count, &val);
2628 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
2631 obd->obd_recovery_ir_factor = val;
2634 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
2636 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
2637 int count, int *eof, void *data)
2639 struct obd_device *obd = (struct obd_device *)data;
2640 LASSERT(obd != NULL);
2642 return snprintf(page, count, "%d\n",
2643 obd->obd_recovery_timeout);
2645 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
2647 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
2648 unsigned long count, void *data)
2650 struct obd_device *obd = (struct obd_device *)data;
2652 LASSERT(obd != NULL);
2654 rc = lprocfs_write_helper(buffer, count, &val);
2658 obd->obd_recovery_timeout = val;
2661 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
2663 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
2664 int count, int *eof, void *data)
2666 struct obd_device *obd = data;
2667 LASSERT(obd != NULL);
2669 return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
2671 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
2673 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
2674 unsigned long count, void *data)
2676 struct obd_device *obd = data;
2678 LASSERT(obd != NULL);
2680 rc = lprocfs_write_helper(buffer, count, &val);
2684 obd->obd_recovery_time_hard = val;
2687 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
2689 int lprocfs_obd_rd_mntdev(char *page, char **start, off_t off,
2690 int count, int *eof, void *data)
2692 struct obd_device *obd = (struct obd_device *)data;
2693 struct lustre_mount_info *lmi;
2694 const char *dev_name;
2696 LASSERT(obd != NULL);
2697 lmi = server_get_mount_2(obd->obd_name);
2698 dev_name = get_mntdev_name(lmi->lmi_sb);
2699 LASSERT(dev_name != NULL);
2701 server_put_mount_2(obd->obd_name, lmi->lmi_mnt);
2702 return snprintf(page, count, "%s\n", dev_name);
2704 EXPORT_SYMBOL(lprocfs_obd_rd_mntdev);
2706 int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
2707 int count, int *eof, void *data)
2709 struct obd_device *dev = data;
2710 struct client_obd *cli = &dev->u.cli;
2713 client_obd_list_lock(&cli->cl_loi_list_lock);
2714 rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
2715 client_obd_list_unlock(&cli->cl_loi_list_lock);
2718 EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
2720 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
2721 int count, int *eof, void *data)
2723 struct obd_device *obd = (struct obd_device *)data;
2724 struct obd_device_target *target = &obd->u.obt;
2726 LASSERT(obd != NULL);
2727 LASSERT(target->obt_magic == OBT_MAGIC);
2729 return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
2731 EXPORT_SYMBOL(lprocfs_target_rd_instance);