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, 2013, 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/lustre_idl.h>
53 static int lprocfs_no_percpu_stats = 0;
54 CFS_MODULE_PARM(lprocfs_no_percpu_stats, "i", int, 0644,
55 "Do not alloc percpu data for lprocfs stats");
57 #define MAX_STRING_SIZE 128
59 int lprocfs_single_release(struct inode *inode, struct file *file)
61 return single_release(inode, file);
63 EXPORT_SYMBOL(lprocfs_single_release);
65 int lprocfs_seq_release(struct inode *inode, struct file *file)
67 return seq_release(inode, file);
69 EXPORT_SYMBOL(lprocfs_seq_release);
71 #ifndef HAVE_ONLY_PROCFS_SEQ
72 /* for b=10866, global variable */
73 DECLARE_RWSEM(_lprocfs_lock);
74 EXPORT_SYMBOL(_lprocfs_lock);
76 static struct proc_dir_entry *__lprocfs_srch(struct proc_dir_entry *head,
79 struct proc_dir_entry *temp;
85 while (temp != NULL) {
86 if (strcmp(temp->name, name) == 0) {
95 struct proc_dir_entry *lprocfs_srch(struct proc_dir_entry *head,
98 struct proc_dir_entry *temp;
100 LPROCFS_SRCH_ENTRY();
101 temp = __lprocfs_srch(head, name);
105 EXPORT_SYMBOL(lprocfs_srch);
107 /* lprocfs API calls */
109 /* Function that emulates snprintf but also has the side effect of advancing
110 the page pointer for the next write into the buffer, incrementing the total
111 length written to the buffer, and decrementing the size left in the
113 #ifdef HAVE_SERVER_SUPPORT
114 static int lprocfs_obd_snprintf(char **page, int end, int *len,
115 const char *format, ...)
123 va_start(list, format);
124 n = vsnprintf(*page, end - *len, format, list);
127 *page += n; *len += n;
130 #endif /* HAVE_SERVER_SUPPORT */
131 #endif /* HAVE_ONLY_PROCFS_SEQ */
133 cfs_proc_dir_entry_t *lprocfs_add_simple(struct proc_dir_entry *root,
135 #ifndef HAVE_ONLY_PROCFS_SEQ
136 read_proc_t *read_proc,
137 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);
149 #ifndef HAVE_ONLY_PROCFS_SEQ
155 LPROCFS_WRITE_ENTRY();
156 proc = create_proc_entry(name, mode, root);
158 CERROR("LprocFS: No memory to create /proc entry %s", name);
159 LPROCFS_WRITE_EXIT();
160 return ERR_PTR(-ENOMEM);
162 proc->read_proc = read_proc;
163 proc->write_proc = write_proc;
165 LPROCFS_WRITE_EXIT();
167 return ERR_PTR(-EINVAL);
174 proc = proc_create_data(name, mode, root, fops, data);
176 CERROR("LprocFS: No memory to create /proc entry %s",
178 return ERR_PTR(-ENOMEM);
183 EXPORT_SYMBOL(lprocfs_add_simple);
185 struct proc_dir_entry *lprocfs_add_symlink(const char *name,
186 struct proc_dir_entry *parent, const char *format, ...)
188 struct proc_dir_entry *entry;
192 if (parent == NULL || format == NULL)
195 OBD_ALLOC_WAIT(dest, MAX_STRING_SIZE + 1);
199 va_start(ap, format);
200 vsnprintf(dest, MAX_STRING_SIZE, format, ap);
203 entry = proc_symlink(name, parent, dest);
205 CERROR("LprocFS: Could not create symbolic link from %s to %s",
208 OBD_FREE(dest, MAX_STRING_SIZE + 1);
211 EXPORT_SYMBOL(lprocfs_add_symlink);
213 #ifndef HAVE_ONLY_PROCFS_SEQ
214 static ssize_t lprocfs_fops_read(struct file *f, char __user *buf,
215 size_t size, loff_t *ppos)
217 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
218 char *page, *start = NULL;
219 int rc = 0, eof = 1, count;
221 if (*ppos >= PAGE_CACHE_SIZE)
224 page = (char *)__get_free_page(GFP_KERNEL);
228 if (LPROCFS_ENTRY_CHECK(dp)) {
233 OBD_FAIL_TIMEOUT(OBD_FAIL_LPROC_REMOVE, 10);
235 rc = dp->read_proc(page, &start, *ppos, PAGE_CACHE_SIZE,
240 /* for lustre proc read, the read count must be less than PAGE_SIZE */
249 start = page + *ppos;
250 } else if (start < page) {
254 count = (rc < size) ? rc : size;
255 if (copy_to_user(buf, start, count)) {
262 free_page((unsigned long)page);
266 static ssize_t lprocfs_fops_write(struct file *f, const char __user *buf,
267 size_t size, loff_t *ppos)
269 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
272 if (LPROCFS_ENTRY_CHECK(dp))
275 rc = dp->write_proc(f, buf, size, dp->data);
279 static struct file_operations lprocfs_generic_fops = {
280 .owner = THIS_MODULE,
281 .read = lprocfs_fops_read,
282 .write = lprocfs_fops_write,
285 static struct file_operations lprocfs_generic_fops = { };
288 #ifdef HAVE_SERVER_SUPPORT
289 int lprocfs_evict_client_open(struct inode *inode, struct file *f)
291 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
292 struct obd_device *obd = dp->data;
294 atomic_inc(&obd->obd_evict_inprogress);
299 int lprocfs_evict_client_release(struct inode *inode, struct file *f)
301 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
302 struct obd_device *obd = dp->data;
304 atomic_dec(&obd->obd_evict_inprogress);
305 wake_up(&obd->obd_evict_inprogress_waitq);
310 struct file_operations lprocfs_evict_client_fops = {
311 .owner = THIS_MODULE,
312 .read = lprocfs_fops_read,
313 .write = lprocfs_fops_write,
314 .open = lprocfs_evict_client_open,
315 .release = lprocfs_evict_client_release,
317 EXPORT_SYMBOL(lprocfs_evict_client_fops);
320 #ifndef HAVE_ONLY_PROCFS_SEQ
321 static int __lprocfs_add_vars(struct proc_dir_entry *root,
322 struct lprocfs_vars *list,
327 if (root == NULL || list == NULL)
330 while (list->name != NULL) {
331 struct proc_dir_entry *cur_root, *proc;
332 char *pathcopy, *cur, *next, pathbuf[64];
333 int pathsize = strlen(list->name) + 1;
338 /* need copy of path for strsep */
339 if (strlen(list->name) > sizeof(pathbuf) - 1) {
340 OBD_ALLOC(pathcopy, pathsize);
341 if (pathcopy == NULL)
342 GOTO(out, rc = -ENOMEM);
348 strcpy(pathcopy, list->name);
350 while (cur_root != NULL && (cur = strsep(&next, "/"))) {
351 if (*cur =='\0') /* skip double/trailing "/" */
354 proc = __lprocfs_srch(cur_root, cur);
355 CDEBUG(D_OTHER, "cur_root=%s, cur=%s, next=%s, (%s)\n",
356 cur_root->name, cur, next,
357 (proc ? "exists" : "new"));
359 cur_root = (proc ? proc :
360 proc_mkdir(cur, cur_root));
361 } else if (proc == NULL) {
363 if (list->proc_mode != 0000) {
364 mode = list->proc_mode;
368 if (list->write_fptr)
371 proc = create_proc_entry(cur, mode, cur_root);
375 if (pathcopy != pathbuf)
376 OBD_FREE(pathcopy, pathsize);
378 if (cur_root == NULL || proc == NULL) {
379 CERROR("LprocFS: No memory to create /proc entry %s",
381 GOTO(out, rc = -ENOMEM);
385 proc->proc_fops = list->fops;
387 proc->proc_fops = &lprocfs_generic_fops;
388 proc->read_proc = list->read_fptr;
389 proc->write_proc = list->write_fptr;
390 proc->data = (list->data ? list->data : data);
397 int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list,
402 LPROCFS_WRITE_ENTRY();
403 rc = __lprocfs_add_vars(root, list, data);
404 LPROCFS_WRITE_EXIT();
408 EXPORT_SYMBOL(lprocfs_add_vars);
415 * \param root [in] The parent proc entry on which new entry will be added.
416 * \param list [in] Array of proc entries to be added.
417 * \param data [in] The argument to be passed when entries read/write routines
418 * are called through /proc file.
420 * \retval 0 on success
424 lprocfs_seq_add_vars(struct proc_dir_entry *root, struct lprocfs_seq_vars *list,
427 if (root == NULL || list == NULL)
430 while (list->name != NULL) {
431 struct proc_dir_entry *proc;
434 if (list->proc_mode != 0000) {
435 mode = list->proc_mode;
436 } else if (list->fops) {
437 if (list->fops->read)
439 if (list->fops->write)
442 proc = proc_create_data(list->name, mode, root,
443 list->fops ?: &lprocfs_generic_fops,
451 EXPORT_SYMBOL(lprocfs_seq_add_vars);
453 #ifndef HAVE_ONLY_PROCFS_SEQ
454 void lprocfs_remove_nolock(struct proc_dir_entry **proot)
456 struct proc_dir_entry *root = *proot;
457 struct proc_dir_entry *temp = root;
458 struct proc_dir_entry *rm_entry;
459 struct proc_dir_entry *parent;
462 if (root == NULL || IS_ERR(root))
465 parent = root->parent;
466 LASSERT(parent != NULL);
469 while (temp->subdir != NULL)
475 /* Memory corruption once caused this to fail, and
476 without this LASSERT we would loop here forever. */
477 LASSERTF(strlen(rm_entry->name) == rm_entry->namelen,
478 "0x%p %s/%s len %d\n", rm_entry, temp->name,
479 rm_entry->name, (int)strlen(rm_entry->name));
481 remove_proc_entry(rm_entry->name, temp);
488 void lprocfs_remove(struct proc_dir_entry **rooth)
490 #ifndef HAVE_ONLY_PROCFS_SEQ
491 LPROCFS_WRITE_ENTRY(); /* search vs remove race */
492 lprocfs_remove_nolock(rooth);
493 LPROCFS_WRITE_EXIT();
499 EXPORT_SYMBOL(lprocfs_remove);
501 void lprocfs_remove_proc_entry(const char *name, struct proc_dir_entry *parent)
503 LASSERT(parent != NULL);
504 remove_proc_entry(name, parent);
506 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
508 #ifndef HAVE_ONLY_PROCFS_SEQ
509 void lprocfs_try_remove_proc_entry(const char *name,
510 struct proc_dir_entry *parent)
512 struct proc_dir_entry *t = NULL;
513 struct proc_dir_entry **p;
516 LASSERT(parent != NULL);
519 LPROCFS_WRITE_ENTRY();
521 /* lookup target name */
522 for (p = &parent->subdir; *p; p = &(*p)->next) {
523 if ((*p)->namelen != len)
525 if (memcmp(name, (*p)->name, len))
532 /* verify it's empty: do not count "num_refs" */
533 for (p = &t->subdir; *p; p = &(*p)->next) {
534 if ((*p)->namelen != strlen("num_refs")) {
538 if (memcmp("num_refs", (*p)->name,
539 strlen("num_refs"))) {
547 lprocfs_remove_nolock(&t);
549 LPROCFS_WRITE_EXIT();
553 EXPORT_SYMBOL(lprocfs_try_remove_proc_entry);
555 struct proc_dir_entry *lprocfs_register(const char *name,
556 struct proc_dir_entry *parent,
557 struct lprocfs_vars *list, void *data)
559 struct proc_dir_entry *entry;
562 LPROCFS_WRITE_ENTRY();
563 entry = __lprocfs_srch(parent, name);
565 CERROR("entry '%s' already registered\n", name);
566 GOTO(out, entry = ERR_PTR(-EALREADY));
569 entry = proc_mkdir(name, parent);
571 GOTO(out, entry = ERR_PTR(-ENOMEM));
574 rc = __lprocfs_add_vars(entry, list, data);
576 lprocfs_remove_nolock(&entry);
577 GOTO(out, entry = ERR_PTR(rc));
581 LPROCFS_WRITE_EXIT();
584 EXPORT_SYMBOL(lprocfs_register);
587 struct proc_dir_entry *
588 lprocfs_seq_register(const char *name, struct proc_dir_entry *parent,
589 struct lprocfs_seq_vars *list, void *data)
591 struct proc_dir_entry *newchild;
593 newchild = proc_mkdir(name, parent);
594 if (newchild != NULL && list != NULL) {
595 int rc = lprocfs_seq_add_vars(newchild, list, data);
597 lprocfs_remove(&newchild);
603 EXPORT_SYMBOL(lprocfs_seq_register);
605 /* Generic callbacks */
606 int lprocfs_uint_seq_show(struct seq_file *m, void *data)
608 return seq_printf(m, "%u\n", *(unsigned int *)data);
610 EXPORT_SYMBOL(lprocfs_uint_seq_show);
612 int lprocfs_wr_uint(struct file *file, const char *buffer,
613 unsigned long count, void *data)
616 char dummy[MAX_STRING_SIZE + 1], *end;
619 dummy[MAX_STRING_SIZE] = '\0';
620 if (copy_from_user(dummy, buffer, MAX_STRING_SIZE))
623 tmp = simple_strtoul(dummy, &end, 0);
627 *p = (unsigned int)tmp;
630 EXPORT_SYMBOL(lprocfs_wr_uint);
632 ssize_t lprocfs_uint_seq_write(struct file *file, const char *buffer,
633 size_t count, loff_t *off)
635 int *data = ((struct seq_file *)file->private_data)->private;
638 rc = lprocfs_write_helper(buffer, count, &val);
642 return lprocfs_wr_uint(file, buffer, count, data);
644 EXPORT_SYMBOL(lprocfs_uint_seq_write);
646 int lprocfs_u64_seq_show(struct seq_file *m, void *data)
648 LASSERT(data != NULL);
649 return seq_printf(m, LPU64"\n", *(__u64 *)data);
651 EXPORT_SYMBOL(lprocfs_u64_seq_show);
653 int lprocfs_atomic_seq_show(struct seq_file *m, void *data)
655 atomic_t *atom = data;
656 LASSERT(atom != NULL);
657 return seq_printf(m, "%d\n", atomic_read(atom));
659 EXPORT_SYMBOL(lprocfs_atomic_seq_show);
662 lprocfs_atomic_seq_write(struct file *file, const char *buffer,
663 size_t count, loff_t *off)
665 atomic_t *atm = ((struct seq_file *)file->private_data)->private;
669 rc = lprocfs_write_helper(buffer, count, &val);
676 atomic_set(atm, val);
679 EXPORT_SYMBOL(lprocfs_atomic_seq_write);
681 int lprocfs_uuid_seq_show(struct seq_file *m, void *data)
683 struct obd_device *obd = data;
685 LASSERT(obd != NULL);
686 return seq_printf(m, "%s\n", obd->obd_uuid.uuid);
688 EXPORT_SYMBOL(lprocfs_uuid_seq_show);
690 int lprocfs_name_seq_show(struct seq_file *m, void *data)
692 struct obd_device *dev = data;
694 LASSERT(dev != NULL);
695 return seq_printf(m, "%s\n", dev->obd_name);
697 EXPORT_SYMBOL(lprocfs_name_seq_show);
699 int lprocfs_blksize_seq_show(struct seq_file *m, void *data)
701 struct obd_device *obd = data;
702 struct obd_statfs osfs;
703 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
704 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
707 rc = seq_printf(m, "%u\n", osfs.os_bsize);
710 EXPORT_SYMBOL(lprocfs_blksize_seq_show);
712 int lprocfs_kbytestotal_seq_show(struct seq_file *m, void *data)
714 struct obd_device *obd = data;
715 struct obd_statfs osfs;
716 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
717 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
720 __u32 blk_size = osfs.os_bsize >> 10;
721 __u64 result = osfs.os_blocks;
723 while (blk_size >>= 1)
726 rc = seq_printf(m, LPU64"\n", result);
730 EXPORT_SYMBOL(lprocfs_kbytestotal_seq_show);
732 int lprocfs_kbytesfree_seq_show(struct seq_file *m, void *data)
734 struct obd_device *obd = data;
735 struct obd_statfs osfs;
736 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
737 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
740 __u32 blk_size = osfs.os_bsize >> 10;
741 __u64 result = osfs.os_bfree;
743 while (blk_size >>= 1)
746 rc = seq_printf(m, LPU64"\n", result);
750 EXPORT_SYMBOL(lprocfs_kbytesfree_seq_show);
752 int lprocfs_kbytesavail_seq_show(struct seq_file *m, void *data)
754 struct obd_device *obd = data;
755 struct obd_statfs osfs;
756 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
757 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
760 __u32 blk_size = osfs.os_bsize >> 10;
761 __u64 result = osfs.os_bavail;
763 while (blk_size >>= 1)
766 rc = seq_printf(m, LPU64"\n", result);
770 EXPORT_SYMBOL(lprocfs_kbytesavail_seq_show);
772 int lprocfs_filestotal_seq_show(struct seq_file *m, void *data)
774 struct obd_device *obd = data;
775 struct obd_statfs osfs;
776 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
777 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
780 rc = seq_printf(m, LPU64"\n", osfs.os_files);
783 EXPORT_SYMBOL(lprocfs_filestotal_seq_show);
785 int lprocfs_filesfree_seq_show(struct seq_file *m, void *data)
787 struct obd_device *obd = data;
788 struct obd_statfs osfs;
789 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
790 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
793 rc = seq_printf(m, LPU64"\n", osfs.os_ffree);
796 EXPORT_SYMBOL(lprocfs_filesfree_seq_show);
798 int lprocfs_server_uuid_seq_show(struct seq_file *m, void *data)
800 struct obd_device *obd = data;
801 struct obd_import *imp;
802 char *imp_state_name = NULL;
805 LASSERT(obd != NULL);
806 LPROCFS_CLIMP_CHECK(obd);
807 imp = obd->u.cli.cl_import;
808 imp_state_name = ptlrpc_import_state_name(imp->imp_state);
809 rc = seq_printf(m, "%s\t%s%s\n", obd2cli_tgt(obd), imp_state_name,
810 imp->imp_deactive ? "\tDEACTIVATED" : "");
812 LPROCFS_CLIMP_EXIT(obd);
815 EXPORT_SYMBOL(lprocfs_server_uuid_seq_show);
817 int lprocfs_conn_uuid_seq_show(struct seq_file *m, void *data)
819 struct obd_device *obd = data;
820 struct ptlrpc_connection *conn;
823 LASSERT(obd != NULL);
825 LPROCFS_CLIMP_CHECK(obd);
826 conn = obd->u.cli.cl_import->imp_connection;
827 if (conn && obd->u.cli.cl_import)
828 rc = seq_printf(m, "%s\n", conn->c_remote_uuid.uuid);
830 rc = seq_printf(m, "%s\n", "<none>");
832 LPROCFS_CLIMP_EXIT(obd);
835 EXPORT_SYMBOL(lprocfs_conn_uuid_seq_show);
837 /** add up per-cpu counters */
838 void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
839 struct lprocfs_counter *cnt)
841 unsigned int num_entry;
842 struct lprocfs_counter *percpu_cntr;
844 unsigned long flags = 0;
846 memset(cnt, 0, sizeof(*cnt));
849 /* set count to 1 to avoid divide-by-zero errs in callers */
854 cnt->lc_min = LC_MIN_INIT;
856 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
858 for (i = 0; i < num_entry; i++) {
859 if (stats->ls_percpu[i] == NULL)
861 percpu_cntr = lprocfs_stats_counter_get(stats, i, idx);
863 cnt->lc_count += percpu_cntr->lc_count;
864 cnt->lc_sum += percpu_cntr->lc_sum;
865 if (percpu_cntr->lc_min < cnt->lc_min)
866 cnt->lc_min = percpu_cntr->lc_min;
867 if (percpu_cntr->lc_max > cnt->lc_max)
868 cnt->lc_max = percpu_cntr->lc_max;
869 cnt->lc_sumsquare += percpu_cntr->lc_sumsquare;
872 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
874 EXPORT_SYMBOL(lprocfs_stats_collect);
877 * Append a space separated list of current set flags to str.
879 #define flag2seqstr(flag) \
881 if (imp->imp_##flag) \
882 seq_printf(m, "%s" #flag, first ? "" : ", "); \
884 static int obd_import_flags2seqstr(struct obd_import *imp, struct seq_file *m)
888 if (imp->imp_obd->obd_no_recov) {
889 seq_printf(m, "no_recov");
893 flag2seqstr(invalid);
894 flag2seqstr(deactive);
895 flag2seqstr(replayable);
896 flag2seqstr(pingable);
901 static const char *obd_connect_names[] = {
915 "join_file(obsolete)",
919 "remote_client_by_force",
928 "mds_mds_connection",
931 "alt_checksum_algorithm",
959 static void obd_connect_seq_flags2str(struct seq_file *m, __u64 flags, char *sep)
965 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
967 seq_printf(m, "%s%s",
968 first ? "" : sep, obd_connect_names[i]);
972 if (flags & ~(mask - 1))
973 seq_printf(m, "%sunknown flags "LPX64,
974 first ? "" : sep, flags & ~(mask - 1));
977 int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
982 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
984 ret += snprintf(page + ret, count - ret, "%s%s",
985 ret ? sep : "", obd_connect_names[i]);
987 if (flags & ~(mask - 1))
988 ret += snprintf(page + ret, count - ret,
989 "%sunknown flags "LPX64,
990 ret ? sep : "", flags & ~(mask - 1));
993 EXPORT_SYMBOL(obd_connect_flags2str);
995 static void obd_connect_data_seqprint(struct seq_file *m,
996 struct obd_connect_data *ocd)
1000 LASSERT(ocd != NULL);
1001 flags = ocd->ocd_connect_flags;
1003 seq_printf(m, " connect_data:\n"
1006 ocd->ocd_connect_flags,
1008 if (flags & OBD_CONNECT_VERSION)
1009 seq_printf(m, " target_version: %u.%u.%u.%u\n",
1010 OBD_OCD_VERSION_MAJOR(ocd->ocd_version),
1011 OBD_OCD_VERSION_MINOR(ocd->ocd_version),
1012 OBD_OCD_VERSION_PATCH(ocd->ocd_version),
1013 OBD_OCD_VERSION_FIX(ocd->ocd_version));
1014 if (flags & OBD_CONNECT_MDS)
1015 seq_printf(m, " mdt_index: %d\n", ocd->ocd_group);
1016 if (flags & OBD_CONNECT_GRANT)
1017 seq_printf(m, " initial_grant: %d\n", ocd->ocd_grant);
1018 if (flags & OBD_CONNECT_INDEX)
1019 seq_printf(m, " target_index: %u\n", ocd->ocd_index);
1020 if (flags & OBD_CONNECT_BRW_SIZE)
1021 seq_printf(m, " max_brw_size: %d\n", ocd->ocd_brw_size);
1022 if (flags & OBD_CONNECT_IBITS)
1023 seq_printf(m, " ibits_known: "LPX64"\n",
1024 ocd->ocd_ibits_known);
1025 if (flags & OBD_CONNECT_GRANT_PARAM)
1026 seq_printf(m, " grant_block_size: %d\n"
1027 " grant_inode_size: %d\n"
1028 " grant_extent_overhead: %d\n",
1030 ocd->ocd_inodespace,
1031 ocd->ocd_grant_extent);
1032 if (flags & OBD_CONNECT_TRANSNO)
1033 seq_printf(m, " first_transno: "LPX64"\n",
1035 if (flags & OBD_CONNECT_CKSUM)
1036 seq_printf(m, " cksum_types: %#x\n",
1037 ocd->ocd_cksum_types);
1038 if (flags & OBD_CONNECT_MAX_EASIZE)
1039 seq_printf(m, " max_easize: %d\n", ocd->ocd_max_easize);
1040 if (flags & OBD_CONNECT_MAXBYTES)
1041 seq_printf(m, " max_object_bytes: "LPU64"\n",
1045 int lprocfs_import_seq_show(struct seq_file *m, void *data)
1047 struct lprocfs_counter ret;
1048 struct lprocfs_counter_header *header;
1049 struct obd_device *obd = (struct obd_device *)data;
1050 struct obd_import *imp;
1051 struct obd_import_conn *conn;
1052 struct obd_connect_data *ocd;
1057 LASSERT(obd != NULL);
1058 LPROCFS_CLIMP_CHECK(obd);
1059 imp = obd->u.cli.cl_import;
1060 ocd = &imp->imp_connect_data;
1062 seq_printf(m, "import:\n"
1066 " connect_flags: [",
1069 ptlrpc_import_state_name(imp->imp_state));
1070 obd_connect_seq_flags2str(m, imp->imp_connect_data.ocd_connect_flags,
1072 seq_printf(m, "]\n");
1073 obd_connect_data_seqprint(m, ocd);
1074 seq_printf(m, " import_flags: [");
1075 obd_import_flags2seqstr(imp, m);
1079 " failover_nids: [");
1080 spin_lock(&imp->imp_lock);
1082 list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
1083 seq_printf(m, "%s%s", j ? ", " : "",
1084 libcfs_nid2str(conn->oic_conn->c_peer.nid));
1088 " current_connection: %s\n"
1089 " connection_attempts: %u\n"
1091 " in-progress_invalidations: %u\n",
1092 imp->imp_connection == NULL ? "<none>" :
1093 libcfs_nid2str(imp->imp_connection->c_peer.nid),
1095 imp->imp_generation,
1096 atomic_read(&imp->imp_inval_count));
1097 spin_unlock(&imp->imp_lock);
1099 if (obd->obd_svc_stats == NULL)
1102 header = &obd->obd_svc_stats->ls_cnt_header[PTLRPC_REQWAIT_CNTR];
1103 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
1104 if (ret.lc_count != 0) {
1105 /* first argument to do_div MUST be __u64 */
1106 __u64 sum = ret.lc_sum;
1107 do_div(sum, ret.lc_count);
1111 seq_printf(m, " rpcs:\n"
1113 " unregistering: %u\n"
1115 " avg_waittime: "LPU64" %s\n",
1116 atomic_read(&imp->imp_inflight),
1117 atomic_read(&imp->imp_unregistering),
1118 atomic_read(&imp->imp_timeouts),
1119 ret.lc_sum, header->lc_units);
1122 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
1123 if (imp->imp_at.iat_portal[j] == 0)
1125 k = max_t(unsigned int, k,
1126 at_get(&imp->imp_at.iat_service_estimate[j]));
1128 seq_printf(m, " service_estimates:\n"
1129 " services: %u sec\n"
1130 " network: %u sec\n",
1132 at_get(&imp->imp_at.iat_net_latency));
1134 seq_printf(m, " transactions:\n"
1135 " last_replay: "LPU64"\n"
1136 " peer_committed: "LPU64"\n"
1137 " last_checked: "LPU64"\n",
1138 imp->imp_last_replay_transno,
1139 imp->imp_peer_committed_transno,
1140 imp->imp_last_transno_checked);
1142 /* avg data rates */
1143 for (rw = 0; rw <= 1; rw++) {
1144 lprocfs_stats_collect(obd->obd_svc_stats,
1145 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
1147 if (ret.lc_sum > 0 && ret.lc_count > 0) {
1148 /* first argument to do_div MUST be __u64 */
1149 __u64 sum = ret.lc_sum;
1150 do_div(sum, ret.lc_count);
1152 seq_printf(m, " %s_data_averages:\n"
1153 " bytes_per_rpc: "LPU64"\n",
1154 rw ? "write" : "read",
1157 k = (int)ret.lc_sum;
1158 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
1159 header = &obd->obd_svc_stats->ls_cnt_header[j];
1160 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
1161 if (ret.lc_sum > 0 && ret.lc_count != 0) {
1162 /* first argument to do_div MUST be __u64 */
1163 __u64 sum = ret.lc_sum;
1164 do_div(sum, ret.lc_count);
1166 seq_printf(m, " %s_per_rpc: "LPU64"\n",
1167 header->lc_units, ret.lc_sum);
1168 j = (int)ret.lc_sum;
1170 seq_printf(m, " MB_per_sec: %u.%.02u\n",
1171 k / j, (100 * k / j) % 100);
1176 LPROCFS_CLIMP_EXIT(obd);
1179 EXPORT_SYMBOL(lprocfs_import_seq_show);
1181 int lprocfs_state_seq_show(struct seq_file *m, void *data)
1183 struct obd_device *obd = (struct obd_device *)data;
1184 struct obd_import *imp;
1187 LASSERT(obd != NULL);
1188 LPROCFS_CLIMP_CHECK(obd);
1189 imp = obd->u.cli.cl_import;
1191 seq_printf(m, "current_state: %s\n",
1192 ptlrpc_import_state_name(imp->imp_state));
1193 seq_printf(m, "state_history:\n");
1194 k = imp->imp_state_hist_idx;
1195 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
1196 struct import_state_hist *ish =
1197 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
1198 if (ish->ish_state == 0)
1200 seq_printf(m, " - ["CFS_TIME_T", %s]\n",
1202 ptlrpc_import_state_name(ish->ish_state));
1205 LPROCFS_CLIMP_EXIT(obd);
1208 EXPORT_SYMBOL(lprocfs_state_seq_show);
1210 int lprocfs_seq_at_hist_helper(struct seq_file *m, struct adaptive_timeout *at)
1213 for (i = 0; i < AT_BINS; i++)
1214 seq_printf(m, "%3u ", at->at_hist[i]);
1215 seq_printf(m, "\n");
1218 EXPORT_SYMBOL(lprocfs_seq_at_hist_helper);
1220 /* See also ptlrpc_lprocfs_timeouts_show_seq */
1221 int lprocfs_timeouts_seq_show(struct seq_file *m, void *data)
1223 struct obd_device *obd = (struct obd_device *)data;
1224 struct obd_import *imp;
1225 unsigned int cur, worst;
1230 LASSERT(obd != NULL);
1231 LPROCFS_CLIMP_CHECK(obd);
1232 imp = obd->u.cli.cl_import;
1234 now = cfs_time_current_sec();
1236 /* Some network health info for kicks */
1237 s2dhms(&ts, now - imp->imp_last_reply_time);
1238 seq_printf(m, "%-10s : %ld, "DHMS_FMT" ago\n",
1239 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
1241 cur = at_get(&imp->imp_at.iat_net_latency);
1242 worst = imp->imp_at.iat_net_latency.at_worst_ever;
1243 worstt = imp->imp_at.iat_net_latency.at_worst_time;
1244 s2dhms(&ts, now - worstt);
1245 seq_printf(m, "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
1246 "network", cur, worst, worstt, DHMS_VARS(&ts));
1247 lprocfs_seq_at_hist_helper(m, &imp->imp_at.iat_net_latency);
1249 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
1250 if (imp->imp_at.iat_portal[i] == 0)
1252 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
1253 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
1254 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
1255 s2dhms(&ts, now - worstt);
1256 seq_printf(m, "portal %-2d : cur %3u worst %3u (at %ld, "
1257 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
1258 cur, worst, worstt, DHMS_VARS(&ts));
1259 lprocfs_seq_at_hist_helper(m, &imp->imp_at.iat_service_estimate[i]);
1262 LPROCFS_CLIMP_EXIT(obd);
1265 EXPORT_SYMBOL(lprocfs_timeouts_seq_show);
1267 int lprocfs_connect_flags_seq_show(struct seq_file *m, void *data)
1269 struct obd_device *obd = data;
1272 LPROCFS_CLIMP_CHECK(obd);
1273 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1274 seq_printf(m, "flags="LPX64"\n", flags);
1275 obd_connect_seq_flags2str(m, flags, "\n");
1276 seq_printf(m, "\n");
1277 LPROCFS_CLIMP_EXIT(obd);
1280 EXPORT_SYMBOL(lprocfs_connect_flags_seq_show);
1282 #ifndef HAVE_ONLY_PROCFS_SEQ
1284 int lprocfs_rd_uint(char *page, char **start, off_t off,
1285 int count, int *eof, void *data)
1287 unsigned int *temp = data;
1288 return snprintf(page, count, "%u\n", *temp);
1290 EXPORT_SYMBOL(lprocfs_rd_uint);
1292 int lprocfs_rd_u64(char *page, char **start, off_t off,
1293 int count, int *eof, void *data)
1295 LASSERT(data != NULL);
1297 return snprintf(page, count, LPU64"\n", *(__u64 *)data);
1299 EXPORT_SYMBOL(lprocfs_rd_u64);
1301 int lprocfs_rd_atomic(char *page, char **start, off_t off,
1302 int count, int *eof, void *data)
1304 atomic_t *atom = data;
1305 LASSERT(atom != NULL);
1307 return snprintf(page, count, "%d\n", atomic_read(atom));
1309 EXPORT_SYMBOL(lprocfs_rd_atomic);
1311 int lprocfs_wr_atomic(struct file *file, const char *buffer,
1312 unsigned long count, void *data)
1314 atomic_t *atm = data;
1318 rc = lprocfs_write_helper(buffer, count, &val);
1325 atomic_set(atm, val);
1328 EXPORT_SYMBOL(lprocfs_wr_atomic);
1330 int lprocfs_rd_uuid(char *page, char **start, off_t off, int count,
1331 int *eof, void *data)
1333 struct obd_device *obd = data;
1335 LASSERT(obd != NULL);
1337 return snprintf(page, count, "%s\n", obd->obd_uuid.uuid);
1339 EXPORT_SYMBOL(lprocfs_rd_uuid);
1341 int lprocfs_rd_name(char *page, char **start, off_t off, int count,
1342 int *eof, void *data)
1344 struct obd_device *dev = data;
1346 LASSERT(dev != NULL);
1348 return snprintf(page, count, "%s\n", dev->obd_name);
1350 EXPORT_SYMBOL(lprocfs_rd_name);
1352 int lprocfs_rd_blksize(char *page, char **start, off_t off, int count,
1353 int *eof, void *data)
1355 struct obd_device *obd = data;
1356 struct obd_statfs osfs;
1357 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
1358 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
1359 OBD_STATFS_NODELAY);
1362 rc = snprintf(page, count, "%u\n", osfs.os_bsize);
1366 EXPORT_SYMBOL(lprocfs_rd_blksize);
1368 int lprocfs_rd_kbytestotal(char *page, char **start, off_t off, int count,
1369 int *eof, void *data)
1371 struct obd_device *obd = data;
1372 struct obd_statfs osfs;
1373 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
1374 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
1375 OBD_STATFS_NODELAY);
1377 __u32 blk_size = osfs.os_bsize >> 10;
1378 __u64 result = osfs.os_blocks;
1380 while (blk_size >>= 1)
1384 rc = snprintf(page, count, LPU64"\n", result);
1388 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
1390 int lprocfs_rd_kbytesfree(char *page, char **start, off_t off, int count,
1391 int *eof, void *data)
1393 struct obd_device *obd = data;
1394 struct obd_statfs osfs;
1395 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
1396 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
1397 OBD_STATFS_NODELAY);
1399 __u32 blk_size = osfs.os_bsize >> 10;
1400 __u64 result = osfs.os_bfree;
1402 while (blk_size >>= 1)
1406 rc = snprintf(page, count, LPU64"\n", result);
1410 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
1412 int lprocfs_rd_kbytesavail(char *page, char **start, off_t off, int count,
1413 int *eof, void *data)
1415 struct obd_device *obd = data;
1416 struct obd_statfs osfs;
1417 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
1418 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
1419 OBD_STATFS_NODELAY);
1421 __u32 blk_size = osfs.os_bsize >> 10;
1422 __u64 result = osfs.os_bavail;
1424 while (blk_size >>= 1)
1428 rc = snprintf(page, count, LPU64"\n", result);
1432 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
1434 int lprocfs_rd_filestotal(char *page, char **start, off_t off, int count,
1435 int *eof, void *data)
1437 struct obd_device *obd = data;
1438 struct obd_statfs osfs;
1439 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
1440 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
1441 OBD_STATFS_NODELAY);
1444 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
1449 EXPORT_SYMBOL(lprocfs_rd_filestotal);
1451 int lprocfs_rd_filesfree(char *page, char **start, off_t off, int count,
1452 int *eof, void *data)
1454 struct obd_device *obd = data;
1455 struct obd_statfs osfs;
1456 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
1457 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
1458 OBD_STATFS_NODELAY);
1461 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
1465 EXPORT_SYMBOL(lprocfs_rd_filesfree);
1467 int lprocfs_rd_server_uuid(char *page, char **start, off_t off, int count,
1468 int *eof, void *data)
1470 struct obd_device *obd = data;
1471 struct obd_import *imp;
1472 char *imp_state_name = NULL;
1475 LASSERT(obd != NULL);
1476 LPROCFS_CLIMP_CHECK(obd);
1477 imp = obd->u.cli.cl_import;
1478 imp_state_name = ptlrpc_import_state_name(imp->imp_state);
1480 rc = snprintf(page, count, "%s\t%s%s\n",
1481 obd2cli_tgt(obd), imp_state_name,
1482 imp->imp_deactive ? "\tDEACTIVATED" : "");
1484 LPROCFS_CLIMP_EXIT(obd);
1487 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
1489 int lprocfs_rd_conn_uuid(char *page, char **start, off_t off, int count,
1490 int *eof, void *data)
1492 struct obd_device *obd = data;
1493 struct ptlrpc_connection *conn;
1496 LASSERT(obd != NULL);
1498 LPROCFS_CLIMP_CHECK(obd);
1499 conn = obd->u.cli.cl_import->imp_connection;
1501 if (conn && obd->u.cli.cl_import) {
1502 rc = snprintf(page, count, "%s\n",
1503 conn->c_remote_uuid.uuid);
1505 rc = snprintf(page, count, "%s\n", "<none>");
1508 LPROCFS_CLIMP_EXIT(obd);
1511 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
1514 * Append a space separated list of current set flags to str.
1516 #define flag2str(flag) \
1517 if (imp->imp_##flag && max - len > 0) \
1518 len += snprintf(str + len, max - len, "%s" #flag, len ? ", " : "");
1519 static int obd_import_flags2str(struct obd_import *imp, char *str, int max)
1523 if (imp->imp_obd->obd_no_recov)
1524 len += snprintf(str, max - len, "no_recov");
1528 flag2str(replayable);
1534 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
1535 int *eof, void *data)
1537 struct lprocfs_counter ret;
1538 struct lprocfs_counter_header *header;
1539 struct obd_device *obd = (struct obd_device *)data;
1540 struct obd_import *imp;
1541 struct obd_import_conn *conn;
1547 LASSERT(obd != NULL);
1548 LPROCFS_CLIMP_CHECK(obd);
1549 imp = obd->u.cli.cl_import;
1552 i = snprintf(page, count,
1558 " connect_flags: [",
1561 ptlrpc_import_state_name(imp->imp_state),
1562 imp->imp_connect_data.ocd_instance);
1563 i += obd_connect_flags2str(page + i, count - i,
1564 imp->imp_connect_data.ocd_connect_flags,
1566 i += snprintf(page + i, count - i,
1568 " import_flags: [");
1569 i += obd_import_flags2str(imp, page + i, count - i);
1571 i += snprintf(page + i, count - i,
1574 " failover_nids: [");
1575 spin_lock(&imp->imp_lock);
1577 cfs_list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
1578 i += snprintf(page + i, count - i, "%s%s", j ? ", " : "",
1579 libcfs_nid2str(conn->oic_conn->c_peer.nid));
1582 i += snprintf(page + i, count - i,
1584 " current_connection: %s\n"
1585 " connection_attempts: %u\n"
1587 " in-progress_invalidations: %u\n",
1588 imp->imp_connection == NULL ? "<none>" :
1589 libcfs_nid2str(imp->imp_connection->c_peer.nid),
1591 imp->imp_generation,
1592 atomic_read(&imp->imp_inval_count));
1593 spin_unlock(&imp->imp_lock);
1595 if (obd->obd_svc_stats == NULL)
1598 header = &obd->obd_svc_stats->ls_cnt_header[PTLRPC_REQWAIT_CNTR];
1599 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
1600 if (ret.lc_count != 0) {
1601 /* first argument to do_div MUST be __u64 */
1602 __u64 sum = ret.lc_sum;
1603 do_div(sum, ret.lc_count);
1607 i += snprintf(page + i, count - i,
1610 " unregistering: %u\n"
1612 " avg_waittime: "LPU64" %s\n",
1613 atomic_read(&imp->imp_inflight),
1614 atomic_read(&imp->imp_unregistering),
1615 atomic_read(&imp->imp_timeouts),
1616 ret.lc_sum, header->lc_units);
1619 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
1620 if (imp->imp_at.iat_portal[j] == 0)
1622 k = max_t(unsigned int, k,
1623 at_get(&imp->imp_at.iat_service_estimate[j]));
1625 i += snprintf(page + i, count - i,
1626 " service_estimates:\n"
1627 " services: %u sec\n"
1628 " network: %u sec\n",
1630 at_get(&imp->imp_at.iat_net_latency));
1632 i += snprintf(page + i, count - i,
1634 " last_replay: "LPU64"\n"
1635 " peer_committed: "LPU64"\n"
1636 " last_checked: "LPU64"\n",
1637 imp->imp_last_replay_transno,
1638 imp->imp_peer_committed_transno,
1639 imp->imp_last_transno_checked);
1641 /* avg data rates */
1642 for (rw = 0; rw <= 1; rw++) {
1643 lprocfs_stats_collect(obd->obd_svc_stats,
1644 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
1646 if (ret.lc_sum > 0 && ret.lc_count > 0) {
1647 /* first argument to do_div MUST be __u64 */
1648 __u64 sum = ret.lc_sum;
1649 do_div(sum, ret.lc_count);
1651 i += snprintf(page + i, count - i,
1652 " %s_data_averages:\n"
1653 " bytes_per_rpc: "LPU64"\n",
1654 rw ? "write" : "read",
1657 k = (int)ret.lc_sum;
1658 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
1659 header = &obd->obd_svc_stats->ls_cnt_header[j];
1660 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
1661 if (ret.lc_sum > 0 && ret.lc_count != 0) {
1662 /* first argument to do_div MUST be __u64 */
1663 __u64 sum = ret.lc_sum;
1664 do_div(sum, ret.lc_count);
1666 i += snprintf(page + i, count - i,
1667 " %s_per_rpc: "LPU64"\n",
1668 header->lc_units, ret.lc_sum);
1669 j = (int)ret.lc_sum;
1671 i += snprintf(page + i, count - i,
1672 " MB_per_sec: %u.%.02u\n",
1673 k / j, (100 * k / j) % 100);
1678 LPROCFS_CLIMP_EXIT(obd);
1681 EXPORT_SYMBOL(lprocfs_rd_import);
1683 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
1684 int *eof, void *data)
1686 struct obd_device *obd = (struct obd_device *)data;
1687 struct obd_import *imp;
1690 LASSERT(obd != NULL);
1691 LPROCFS_CLIMP_CHECK(obd);
1692 imp = obd->u.cli.cl_import;
1695 i = snprintf(page, count, "current_state: %s\n",
1696 ptlrpc_import_state_name(imp->imp_state));
1697 i += snprintf(page + i, count - i,
1698 "state_history:\n");
1699 k = imp->imp_state_hist_idx;
1700 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
1701 struct import_state_hist *ish =
1702 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
1703 if (ish->ish_state == 0)
1705 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
1707 ptlrpc_import_state_name(ish->ish_state));
1710 LPROCFS_CLIMP_EXIT(obd);
1713 EXPORT_SYMBOL(lprocfs_rd_state);
1715 int lprocfs_at_hist_helper(char *page, int count, int rc,
1716 struct adaptive_timeout *at)
1719 for (i = 0; i < AT_BINS; i++)
1720 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
1721 rc += snprintf(page + rc, count - rc, "\n");
1724 EXPORT_SYMBOL(lprocfs_at_hist_helper);
1726 /* See also ptlrpc_lprocfs_rd_timeouts */
1727 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
1728 int *eof, void *data)
1730 struct obd_device *obd = (struct obd_device *)data;
1731 struct obd_import *imp;
1732 unsigned int cur, worst;
1737 LASSERT(obd != NULL);
1738 LPROCFS_CLIMP_CHECK(obd);
1739 imp = obd->u.cli.cl_import;
1742 now = cfs_time_current_sec();
1744 /* Some network health info for kicks */
1745 s2dhms(&ts, now - imp->imp_last_reply_time);
1746 rc += snprintf(page + rc, count - rc,
1747 "%-10s : %ld, "DHMS_FMT" ago\n",
1748 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
1750 cur = at_get(&imp->imp_at.iat_net_latency);
1751 worst = imp->imp_at.iat_net_latency.at_worst_ever;
1752 worstt = imp->imp_at.iat_net_latency.at_worst_time;
1753 s2dhms(&ts, now - worstt);
1754 rc += snprintf(page + rc, count - rc,
1755 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
1756 "network", cur, worst, worstt, DHMS_VARS(&ts));
1757 rc = lprocfs_at_hist_helper(page, count, rc,
1758 &imp->imp_at.iat_net_latency);
1760 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
1761 if (imp->imp_at.iat_portal[i] == 0)
1763 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
1764 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
1765 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
1766 s2dhms(&ts, now - worstt);
1767 rc += snprintf(page + rc, count - rc,
1768 "portal %-2d : cur %3u worst %3u (at %ld, "
1769 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
1770 cur, worst, worstt, DHMS_VARS(&ts));
1771 rc = lprocfs_at_hist_helper(page, count, rc,
1772 &imp->imp_at.iat_service_estimate[i]);
1775 LPROCFS_CLIMP_EXIT(obd);
1778 EXPORT_SYMBOL(lprocfs_rd_timeouts);
1780 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1781 int count, int *eof, void *data)
1783 struct obd_device *obd = data;
1787 LPROCFS_CLIMP_CHECK(obd);
1788 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1789 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1790 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1791 ret += snprintf(page + ret, count - ret, "\n");
1792 LPROCFS_CLIMP_EXIT(obd);
1795 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1797 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1798 int *eof, void *data)
1800 struct obd_device *obd = data;
1802 LASSERT(obd != NULL);
1804 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1806 EXPORT_SYMBOL(lprocfs_rd_num_exports);
1808 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1809 int *eof, void *data)
1811 struct obd_type *class = (struct obd_type*) data;
1813 LASSERT(class != NULL);
1815 return snprintf(page, count, "%d\n", class->typ_refcnt);
1817 EXPORT_SYMBOL(lprocfs_rd_numrefs);
1819 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1823 LASSERT(obd != NULL);
1824 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1825 LASSERT(obd->obd_type->typ_procroot != NULL);
1827 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1828 obd->obd_type->typ_procroot,
1830 if (IS_ERR(obd->obd_proc_entry)) {
1831 rc = PTR_ERR(obd->obd_proc_entry);
1832 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1833 obd->obd_proc_entry = NULL;
1837 EXPORT_SYMBOL(lprocfs_obd_setup);
1841 lprocfs_seq_obd_setup(struct obd_device *obd)
1845 LASSERT(obd != NULL);
1846 LASSERT(obd->obd_vars != NULL);
1847 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1848 LASSERT(obd->obd_type->typ_procroot != NULL);
1850 obd->obd_proc_entry = lprocfs_seq_register(obd->obd_name,
1851 obd->obd_type->typ_procroot,
1852 obd->obd_vars, obd);
1853 if (IS_ERR(obd->obd_proc_entry)) {
1854 rc = PTR_ERR(obd->obd_proc_entry);
1855 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1856 obd->obd_proc_entry = NULL;
1860 EXPORT_SYMBOL(lprocfs_seq_obd_setup);
1862 int lprocfs_obd_cleanup(struct obd_device *obd)
1866 if (obd->obd_proc_exports_entry) {
1867 /* Should be no exports left */
1868 lprocfs_remove(&obd->obd_proc_exports_entry);
1869 obd->obd_proc_exports_entry = NULL;
1871 if (obd->obd_proc_entry) {
1872 lprocfs_remove(&obd->obd_proc_entry);
1873 obd->obd_proc_entry = NULL;
1877 EXPORT_SYMBOL(lprocfs_obd_cleanup);
1879 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1881 CDEBUG(D_CONFIG, "stat %p - data %p/%p\n", client_stat,
1882 client_stat->nid_proc, client_stat->nid_stats);
1884 LASSERTF(atomic_read(&client_stat->nid_exp_ref_count) == 0,
1885 "nid %s:count %d\n", libcfs_nid2str(client_stat->nid),
1886 atomic_read(&client_stat->nid_exp_ref_count));
1888 if (client_stat->nid_proc)
1889 lprocfs_remove(&client_stat->nid_proc);
1891 if (client_stat->nid_stats)
1892 lprocfs_free_stats(&client_stat->nid_stats);
1894 if (client_stat->nid_ldlm_stats)
1895 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1897 OBD_FREE_PTR(client_stat);
1902 void lprocfs_free_per_client_stats(struct obd_device *obd)
1904 cfs_hash_t *hash = obd->obd_nid_stats_hash;
1905 struct nid_stat *stat;
1908 /* we need extra list - because hash_exit called to early */
1909 /* not need locking because all clients is died */
1910 while (!cfs_list_empty(&obd->obd_nid_stats)) {
1911 stat = cfs_list_entry(obd->obd_nid_stats.next,
1912 struct nid_stat, nid_list);
1913 cfs_list_del_init(&stat->nid_list);
1914 cfs_hash_del(hash, &stat->nid, &stat->nid_hash);
1915 lprocfs_free_client_stats(stat);
1919 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
1921 int lprocfs_stats_alloc_one(struct lprocfs_stats *stats, unsigned int cpuid)
1923 struct lprocfs_counter *cntr;
1924 unsigned int percpusize;
1926 unsigned long flags = 0;
1929 LASSERT(stats->ls_percpu[cpuid] == NULL);
1930 LASSERT((stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU) == 0);
1932 percpusize = lprocfs_stats_counter_size(stats);
1933 LIBCFS_ALLOC_ATOMIC(stats->ls_percpu[cpuid], percpusize);
1934 if (stats->ls_percpu[cpuid] != NULL) {
1936 if (unlikely(stats->ls_biggest_alloc_num <= cpuid)) {
1937 if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
1938 spin_lock_irqsave(&stats->ls_lock, flags);
1940 spin_lock(&stats->ls_lock);
1941 if (stats->ls_biggest_alloc_num <= cpuid)
1942 stats->ls_biggest_alloc_num = cpuid + 1;
1943 if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) {
1944 spin_unlock_irqrestore(&stats->ls_lock, flags);
1946 spin_unlock(&stats->ls_lock);
1949 /* initialize the ls_percpu[cpuid] non-zero counter */
1950 for (i = 0; i < stats->ls_num; ++i) {
1951 cntr = lprocfs_stats_counter_get(stats, cpuid, i);
1952 cntr->lc_min = LC_MIN_INIT;
1957 EXPORT_SYMBOL(lprocfs_stats_alloc_one);
1959 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1960 enum lprocfs_stats_flags flags)
1962 struct lprocfs_stats *stats;
1963 unsigned int num_entry;
1964 unsigned int percpusize = 0;
1970 if (lprocfs_no_percpu_stats != 0)
1971 flags |= LPROCFS_STATS_FLAG_NOPERCPU;
1973 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1976 num_entry = num_possible_cpus();
1978 /* alloc percpu pointers for all possible cpu slots */
1979 LIBCFS_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1983 stats->ls_num = num;
1984 stats->ls_flags = flags;
1985 spin_lock_init(&stats->ls_lock);
1987 /* alloc num of counter headers */
1988 LIBCFS_ALLOC(stats->ls_cnt_header,
1989 stats->ls_num * sizeof(struct lprocfs_counter_header));
1990 if (stats->ls_cnt_header == NULL)
1993 if ((flags & LPROCFS_STATS_FLAG_NOPERCPU) != 0) {
1994 /* contains only one set counters */
1995 percpusize = lprocfs_stats_counter_size(stats);
1996 LIBCFS_ALLOC_ATOMIC(stats->ls_percpu[0], percpusize);
1997 if (stats->ls_percpu[0] == NULL)
1999 stats->ls_biggest_alloc_num = 1;
2000 } else if ((flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0) {
2001 /* alloc all percpu data, currently only obd_memory use this */
2002 for (i = 0; i < num_entry; ++i)
2003 if (lprocfs_stats_alloc_one(stats, i) < 0)
2010 lprocfs_free_stats(&stats);
2013 EXPORT_SYMBOL(lprocfs_alloc_stats);
2015 void lprocfs_free_stats(struct lprocfs_stats **statsh)
2017 struct lprocfs_stats *stats = *statsh;
2018 unsigned int num_entry;
2019 unsigned int percpusize;
2022 if (stats == NULL || stats->ls_num == 0)
2026 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
2029 num_entry = num_possible_cpus();
2031 percpusize = lprocfs_stats_counter_size(stats);
2032 for (i = 0; i < num_entry; i++)
2033 if (stats->ls_percpu[i] != NULL)
2034 LIBCFS_FREE(stats->ls_percpu[i], percpusize);
2035 if (stats->ls_cnt_header != NULL)
2036 LIBCFS_FREE(stats->ls_cnt_header, stats->ls_num *
2037 sizeof(struct lprocfs_counter_header));
2038 LIBCFS_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
2040 EXPORT_SYMBOL(lprocfs_free_stats);
2042 void lprocfs_clear_stats(struct lprocfs_stats *stats)
2044 struct lprocfs_counter *percpu_cntr;
2047 unsigned int num_entry;
2048 unsigned long flags = 0;
2050 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
2052 for (i = 0; i < num_entry; i++) {
2053 if (stats->ls_percpu[i] == NULL)
2055 for (j = 0; j < stats->ls_num; j++) {
2056 percpu_cntr = lprocfs_stats_counter_get(stats, i, j);
2057 percpu_cntr->lc_count = 0;
2058 percpu_cntr->lc_min = LC_MIN_INIT;
2059 percpu_cntr->lc_max = 0;
2060 percpu_cntr->lc_sumsquare = 0;
2061 percpu_cntr->lc_sum = 0;
2062 if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
2063 percpu_cntr->lc_sum_irq = 0;
2067 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
2069 EXPORT_SYMBOL(lprocfs_clear_stats);
2071 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
2072 size_t len, loff_t *off)
2074 struct seq_file *seq = file->private_data;
2075 struct lprocfs_stats *stats = seq->private;
2077 lprocfs_clear_stats(stats);
2082 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
2084 struct lprocfs_stats *stats = p->private;
2086 return (*pos < stats->ls_num) ? pos : NULL;
2089 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
2093 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
2097 return lprocfs_stats_seq_start(p, pos);
2100 /* seq file export of one lprocfs counter */
2101 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
2103 struct lprocfs_stats *stats = p->private;
2104 struct lprocfs_counter_header *hdr;
2105 struct lprocfs_counter ctr;
2106 int idx = *(loff_t *)v;
2112 do_gettimeofday(&now);
2113 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
2114 "snapshot_time", now.tv_sec, now.tv_usec);
2119 hdr = &stats->ls_cnt_header[idx];
2120 lprocfs_stats_collect(stats, idx, &ctr);
2122 if (ctr.lc_count == 0)
2125 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", hdr->lc_name,
2126 ctr.lc_count, hdr->lc_units);
2130 if ((hdr->lc_config & LPROCFS_CNTR_AVGMINMAX) && ctr.lc_count > 0) {
2131 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
2132 ctr.lc_min, ctr.lc_max, ctr.lc_sum);
2135 if (hdr->lc_config & LPROCFS_CNTR_STDDEV)
2136 rc = seq_printf(p, " "LPD64, ctr.lc_sumsquare);
2140 rc = seq_printf(p, "\n");
2142 return (rc < 0) ? rc : 0;
2145 struct seq_operations lprocfs_stats_seq_sops = {
2146 .start = lprocfs_stats_seq_start,
2147 .stop = lprocfs_stats_seq_stop,
2148 .next = lprocfs_stats_seq_next,
2149 .show = lprocfs_stats_seq_show,
2152 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
2154 struct seq_file *seq;
2157 #ifndef HAVE_ONLY_PROCFS_SEQ
2158 if (LPROCFS_ENTRY_CHECK(PDE(inode)))
2161 rc = seq_open(file, &lprocfs_stats_seq_sops);
2164 seq = file->private_data;
2165 seq->private = PDE_DATA(inode);
2169 struct file_operations lprocfs_stats_seq_fops = {
2170 .owner = THIS_MODULE,
2171 .open = lprocfs_stats_seq_open,
2173 .write = lprocfs_stats_seq_write,
2174 .llseek = seq_lseek,
2175 .release = lprocfs_seq_release,
2178 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
2179 struct lprocfs_stats *stats)
2181 struct proc_dir_entry *entry;
2182 LASSERT(root != NULL);
2184 entry = proc_create_data(name, 0644, root,
2185 &lprocfs_stats_seq_fops, stats);
2190 EXPORT_SYMBOL(lprocfs_register_stats);
2192 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
2193 unsigned conf, const char *name, const char *units)
2195 struct lprocfs_counter_header *header;
2196 struct lprocfs_counter *percpu_cntr;
2197 unsigned long flags = 0;
2199 unsigned int num_cpu;
2201 LASSERT(stats != NULL);
2203 header = &stats->ls_cnt_header[index];
2204 LASSERTF(header != NULL, "Failed to allocate stats header:[%d]%s/%s\n",
2205 index, name, units);
2207 header->lc_config = conf;
2208 header->lc_name = name;
2209 header->lc_units = units;
2211 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
2212 for (i = 0; i < num_cpu; ++i) {
2213 if (stats->ls_percpu[i] == NULL)
2215 percpu_cntr = lprocfs_stats_counter_get(stats, i, index);
2216 percpu_cntr->lc_count = 0;
2217 percpu_cntr->lc_min = LC_MIN_INIT;
2218 percpu_cntr->lc_max = 0;
2219 percpu_cntr->lc_sumsquare = 0;
2220 percpu_cntr->lc_sum = 0;
2221 if ((stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
2222 percpu_cntr->lc_sum_irq = 0;
2224 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
2226 EXPORT_SYMBOL(lprocfs_counter_init);
2228 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
2230 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
2231 LASSERT(coffset < stats->ls_num); \
2232 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
2235 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
2237 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
2238 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
2239 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
2240 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
2241 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
2242 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
2243 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
2244 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
2245 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
2246 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
2247 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
2248 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
2249 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
2250 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
2251 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
2252 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
2253 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
2254 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
2255 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
2256 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
2257 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
2258 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
2259 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
2260 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
2261 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
2262 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
2263 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
2264 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
2265 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
2266 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
2267 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
2268 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
2269 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
2270 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
2271 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
2272 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
2273 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
2274 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
2275 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
2276 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
2277 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
2278 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
2279 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
2280 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
2281 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
2282 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
2283 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
2284 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
2285 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
2286 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
2287 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
2288 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
2289 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
2290 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
2291 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
2292 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
2293 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
2294 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
2295 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
2296 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
2297 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
2298 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
2299 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
2300 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
2301 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
2302 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
2303 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
2305 CLASSERT(NUM_OBD_STATS == OBD_COUNTER_OFFSET(putref) + 1);
2307 EXPORT_SYMBOL(lprocfs_init_ops_stats);
2309 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
2311 struct lprocfs_stats *stats;
2312 unsigned int num_stats;
2315 LASSERT(obd->obd_stats == NULL);
2316 LASSERT(obd->obd_proc_entry != NULL);
2317 LASSERT(obd->obd_cntr_base == 0);
2319 num_stats = NUM_OBD_STATS + num_private_stats;
2320 stats = lprocfs_alloc_stats(num_stats, 0);
2324 lprocfs_init_ops_stats(num_private_stats, stats);
2326 for (i = num_private_stats; i < num_stats; i++) {
2327 /* If this LBUGs, it is likely that an obd
2328 * operation was added to struct obd_ops in
2329 * <obd.h>, and that the corresponding line item
2330 * LPROCFS_OBD_OP_INIT(.., .., opname)
2331 * is missing from the list above. */
2332 LASSERTF(stats->ls_cnt_header[i].lc_name != NULL,
2333 "Missing obd_stat initializer obd_op "
2334 "operation at offset %d.\n", i - num_private_stats);
2336 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
2338 lprocfs_free_stats(&stats);
2340 obd->obd_stats = stats;
2341 obd->obd_cntr_base = num_private_stats;
2345 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
2347 void lprocfs_free_obd_stats(struct obd_device *obd)
2350 lprocfs_free_stats(&obd->obd_stats);
2352 EXPORT_SYMBOL(lprocfs_free_obd_stats);
2354 /* Note that we only init md counters for ops whose offset is less
2355 * than NUM_MD_STATS. This is explained in a comment in the definition
2356 * of struct md_ops. */
2357 #define LPROCFS_MD_OP_INIT(base, stats, op) \
2359 unsigned int _idx = base + MD_COUNTER_OFFSET(op); \
2361 if (MD_COUNTER_OFFSET(op) < NUM_MD_STATS) { \
2362 LASSERT(_idx < stats->ls_num); \
2363 lprocfs_counter_init(stats, _idx, 0, #op, "reqs"); \
2367 void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats)
2369 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
2370 LPROCFS_MD_OP_INIT(num_private_stats, stats, null_inode);
2371 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
2372 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
2373 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
2374 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
2375 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
2376 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
2377 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
2378 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
2379 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
2380 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
2381 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
2382 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
2383 LPROCFS_MD_OP_INIT(num_private_stats, stats, fsync);
2384 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
2385 LPROCFS_MD_OP_INIT(num_private_stats, stats, read_entry);
2386 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
2387 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
2388 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
2389 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
2390 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
2391 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
2392 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
2393 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
2394 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
2395 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
2396 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
2397 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
2398 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
2399 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
2400 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
2401 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
2403 EXPORT_SYMBOL(lprocfs_init_mps_stats);
2405 int lprocfs_alloc_md_stats(struct obd_device *obd,
2406 unsigned int num_private_stats)
2408 struct lprocfs_stats *stats;
2409 unsigned int num_stats;
2412 CLASSERT(offsetof(struct md_ops, MD_STATS_FIRST_OP) == 0);
2413 CLASSERT(_MD_COUNTER_OFFSET(MD_STATS_FIRST_OP) == 0);
2414 CLASSERT(_MD_COUNTER_OFFSET(MD_STATS_LAST_OP) > 0);
2416 /* TODO Ensure that this function is only used where
2417 * appropriate by adding an assertion to the effect that
2418 * obd->obd_type->typ_md_ops is not NULL. We can't do this now
2419 * because mdt_procfs_init() uses this function to allocate
2420 * the stats backing /proc/fs/lustre/mdt/.../md_stats but the
2421 * mdt layer does not use the md_ops interface. This is
2422 * confusing and a waste of memory. See LU-2484.
2424 LASSERT(obd->obd_proc_entry != NULL);
2425 LASSERT(obd->obd_md_stats == NULL);
2426 LASSERT(obd->obd_md_cntr_base == 0);
2428 num_stats = NUM_MD_STATS + num_private_stats;
2429 stats = lprocfs_alloc_stats(num_stats, 0);
2433 lprocfs_init_mps_stats(num_private_stats, stats);
2435 for (i = num_private_stats; i < num_stats; i++) {
2436 if (stats->ls_cnt_header[i].lc_name == NULL) {
2437 CERROR("Missing md_stat initializer md_op "
2438 "operation at offset %d. Aborting.\n",
2439 i - num_private_stats);
2444 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
2446 lprocfs_free_stats(&stats);
2448 obd->obd_md_stats = stats;
2449 obd->obd_md_cntr_base = num_private_stats;
2454 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
2456 void lprocfs_free_md_stats(struct obd_device *obd)
2458 struct lprocfs_stats *stats = obd->obd_md_stats;
2460 if (stats != NULL) {
2461 obd->obd_md_stats = NULL;
2462 obd->obd_md_cntr_base = 0;
2463 lprocfs_free_stats(&stats);
2466 EXPORT_SYMBOL(lprocfs_free_md_stats);
2468 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
2470 lprocfs_counter_init(ldlm_stats,
2471 LDLM_ENQUEUE - LDLM_FIRST_OPC,
2472 0, "ldlm_enqueue", "reqs");
2473 lprocfs_counter_init(ldlm_stats,
2474 LDLM_CONVERT - LDLM_FIRST_OPC,
2475 0, "ldlm_convert", "reqs");
2476 lprocfs_counter_init(ldlm_stats,
2477 LDLM_CANCEL - LDLM_FIRST_OPC,
2478 0, "ldlm_cancel", "reqs");
2479 lprocfs_counter_init(ldlm_stats,
2480 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
2481 0, "ldlm_bl_callback", "reqs");
2482 lprocfs_counter_init(ldlm_stats,
2483 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
2484 0, "ldlm_cp_callback", "reqs");
2485 lprocfs_counter_init(ldlm_stats,
2486 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
2487 0, "ldlm_gl_callback", "reqs");
2489 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
2491 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
2492 int *eof, void *data)
2494 struct obd_export *exp = data;
2495 LASSERT(exp != NULL);
2497 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
2500 struct exp_uuid_cb_data {
2508 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
2509 int count, int *eof, int *len)
2511 cb_data->page = page;
2512 cb_data->count = count;
2517 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
2518 cfs_hlist_node_t *hnode, void *cb_data)
2521 struct obd_export *exp = cfs_hash_object(hs, hnode);
2522 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
2524 if (exp->exp_nid_stats)
2525 *data->len += snprintf((data->page + *data->len),
2526 data->count, "%s\n",
2527 obd_uuid2str(&exp->exp_client_uuid));
2531 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
2532 int *eof, void *data)
2534 struct nid_stat *stats = (struct nid_stat *)data;
2535 struct exp_uuid_cb_data cb_data;
2536 struct obd_device *obd = stats->nid_obd;
2541 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
2542 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
2543 lprocfs_exp_print_uuid, &cb_data);
2544 return (*cb_data.len);
2547 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
2548 cfs_hlist_node_t *hnode, void *cb_data)
2551 struct exp_uuid_cb_data *data = cb_data;
2552 struct obd_export *exp = cfs_hash_object(hs, hnode);
2554 if (exp->exp_lock_hash != NULL) {
2556 *data->len += cfs_hash_debug_header(data->page,
2559 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
2566 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
2567 int *eof, void *data)
2569 struct nid_stat *stats = (struct nid_stat *)data;
2570 struct exp_uuid_cb_data cb_data;
2571 struct obd_device *obd = stats->nid_obd;
2576 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
2578 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
2579 lprocfs_exp_print_hash, &cb_data);
2580 return (*cb_data.len);
2583 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
2584 int count, int *eof, void *data)
2587 return snprintf(page, count, "%s\n",
2588 "Write into this file to clear all nid stats and "
2589 "stale nid entries");
2591 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
2593 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
2595 struct nid_stat *stat = obj;
2598 CDEBUG(D_INFO,"refcnt %d\n", atomic_read(&stat->nid_exp_ref_count));
2599 if (atomic_read(&stat->nid_exp_ref_count) == 1) {
2600 /* object has only hash references. */
2601 spin_lock(&stat->nid_obd->obd_nid_lock);
2602 cfs_list_move(&stat->nid_list, data);
2603 spin_unlock(&stat->nid_obd->obd_nid_lock);
2606 /* we has reference to object - only clear data*/
2607 if (stat->nid_stats)
2608 lprocfs_clear_stats(stat->nid_stats);
2613 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
2614 unsigned long count, void *data)
2616 struct obd_device *obd = (struct obd_device *)data;
2617 struct nid_stat *client_stat;
2618 CFS_LIST_HEAD(free_list);
2620 cfs_hash_cond_del(obd->obd_nid_stats_hash,
2621 lprocfs_nid_stats_clear_write_cb, &free_list);
2623 while (!cfs_list_empty(&free_list)) {
2624 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
2626 cfs_list_del_init(&client_stat->nid_list);
2627 lprocfs_free_client_stats(client_stat);
2632 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
2634 #ifdef HAVE_SERVER_SUPPORT
2635 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
2637 struct nid_stat *new_stat, *old_stat;
2638 struct obd_device *obd = NULL;
2639 cfs_proc_dir_entry_t *entry;
2640 char *buffer = NULL;
2646 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
2647 !exp->exp_obd->obd_nid_stats_hash)
2650 /* not test against zero because eric say:
2651 * You may only test nid against another nid, or LNET_NID_ANY.
2652 * Anything else is nonsense.*/
2653 if (!nid || *nid == LNET_NID_ANY)
2656 spin_lock(&exp->exp_lock);
2657 if (exp->exp_nid_stats != NULL) {
2658 spin_unlock(&exp->exp_lock);
2661 spin_unlock(&exp->exp_lock);
2665 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
2667 OBD_ALLOC_PTR(new_stat);
2668 if (new_stat == NULL)
2671 new_stat->nid = *nid;
2672 new_stat->nid_obd = exp->exp_obd;
2673 /* we need set default refcount to 1 to balance obd_disconnect */
2674 atomic_set(&new_stat->nid_exp_ref_count, 1);
2676 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
2677 nid, &new_stat->nid_hash);
2678 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
2679 old_stat, libcfs_nid2str(*nid),
2680 atomic_read(&new_stat->nid_exp_ref_count));
2682 /* Return -EALREADY here so that we know that the /proc
2683 * entry already has been created */
2684 if (old_stat != new_stat) {
2685 nidstat_putref(old_stat);
2686 GOTO(destroy_new, rc = -EALREADY);
2688 /* not found - create */
2689 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
2691 GOTO(destroy_new, rc = -ENOMEM);
2693 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
2694 new_stat->nid_proc = lprocfs_register(buffer,
2695 obd->obd_proc_exports_entry,
2697 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
2699 if (IS_ERR(new_stat->nid_proc)) {
2700 rc = PTR_ERR(new_stat->nid_proc);
2701 new_stat->nid_proc = NULL;
2702 CERROR("%s: cannot create proc entry for export %s: rc = %d\n",
2703 obd->obd_name, libcfs_nid2str(*nid), rc);
2704 GOTO(destroy_new_ns, rc);
2707 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
2708 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
2709 if (IS_ERR(entry)) {
2710 CWARN("Error adding the NID stats file\n");
2711 rc = PTR_ERR(entry);
2712 GOTO(destroy_new_ns, rc);
2715 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
2716 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
2717 if (IS_ERR(entry)) {
2718 CWARN("Error adding the hash file\n");
2719 rc = PTR_ERR(entry);
2720 GOTO(destroy_new_ns, rc);
2723 spin_lock(&exp->exp_lock);
2724 exp->exp_nid_stats = new_stat;
2725 spin_unlock(&exp->exp_lock);
2727 /* protect competitive add to list, not need locking on destroy */
2728 spin_lock(&obd->obd_nid_lock);
2729 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
2730 spin_unlock(&obd->obd_nid_lock);
2735 if (new_stat->nid_proc != NULL)
2736 lprocfs_remove(&new_stat->nid_proc);
2737 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
2740 nidstat_putref(new_stat);
2741 OBD_FREE_PTR(new_stat);
2744 EXPORT_SYMBOL(lprocfs_exp_setup);
2747 int lprocfs_exp_cleanup(struct obd_export *exp)
2749 struct nid_stat *stat = exp->exp_nid_stats;
2751 if(!stat || !exp->exp_obd)
2754 nidstat_putref(exp->exp_nid_stats);
2755 exp->exp_nid_stats = NULL;
2759 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2761 __s64 lprocfs_read_helper(struct lprocfs_counter *lc,
2762 struct lprocfs_counter_header *header,
2763 enum lprocfs_stats_flags flags,
2764 enum lprocfs_fields_flags field)
2768 if (lc == NULL || header == NULL)
2772 case LPROCFS_FIELDS_FLAGS_CONFIG:
2773 ret = header->lc_config;
2775 case LPROCFS_FIELDS_FLAGS_SUM:
2777 if ((flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
2778 ret += lc->lc_sum_irq;
2780 case LPROCFS_FIELDS_FLAGS_MIN:
2783 case LPROCFS_FIELDS_FLAGS_MAX:
2786 case LPROCFS_FIELDS_FLAGS_AVG:
2787 ret = (lc->lc_max - lc->lc_min) / 2;
2789 case LPROCFS_FIELDS_FLAGS_SUMSQUARE:
2790 ret = lc->lc_sumsquare;
2792 case LPROCFS_FIELDS_FLAGS_COUNT:
2800 EXPORT_SYMBOL(lprocfs_read_helper);
2802 int lprocfs_write_helper(const char *buffer, unsigned long count,
2805 return lprocfs_write_frac_helper(buffer, count, val, 1);
2807 EXPORT_SYMBOL(lprocfs_write_helper);
2809 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
2812 char kernbuf[20], *end, *pbuf;
2814 if (count > (sizeof(kernbuf) - 1))
2817 if (copy_from_user(kernbuf, buffer, count))
2820 kernbuf[count] = '\0';
2827 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2831 if (end != NULL && *end == '.') {
2832 int temp_val, pow = 1;
2836 if (strlen(pbuf) > 5)
2837 pbuf[5] = '\0'; /*only allow 5bits fractional*/
2839 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2842 for (i = 0; i < (end - pbuf); i++)
2845 *val += temp_val / pow;
2850 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2852 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
2855 long decimal_val, frac_val;
2861 decimal_val = val / mult;
2862 prtn = snprintf(buffer, count, "%ld", decimal_val);
2863 frac_val = val % mult;
2865 if (prtn < (count - 4) && frac_val > 0) {
2867 int i, temp_mult = 1, frac_bits = 0;
2869 temp_frac = frac_val * 10;
2870 buffer[prtn++] = '.';
2871 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
2872 /* only reserved 2 bits fraction */
2873 buffer[prtn++] ='0';
2878 * Need to think these cases :
2879 * 1. #echo x.00 > /proc/xxx output result : x
2880 * 2. #echo x.0x > /proc/xxx output result : x.0x
2881 * 3. #echo x.x0 > /proc/xxx output result : x.x
2882 * 4. #echo x.xx > /proc/xxx output result : x.xx
2883 * Only reserved 2 bits fraction.
2885 for (i = 0; i < (5 - prtn); i++)
2888 frac_bits = min((int)count - prtn, 3 - frac_bits);
2889 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
2890 frac_val * temp_mult / mult);
2893 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
2895 if (buffer[prtn] == '.') {
2902 buffer[prtn++] ='\n';
2905 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2907 int lprocfs_seq_read_frac_helper(struct seq_file *m, long val, int mult)
2909 long decimal_val, frac_val;
2911 decimal_val = val / mult;
2912 seq_printf(m, "%ld", decimal_val);
2913 frac_val = val % mult;
2920 /* Three cases: x0, xx, 0x */
2921 if ((frac_val % 10) != 0)
2922 seq_printf(m, ".%ld", frac_val);
2924 seq_printf(m, ".%ld", frac_val / 10);
2927 seq_printf(m, "\n");
2930 EXPORT_SYMBOL(lprocfs_seq_read_frac_helper);
2932 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
2934 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
2936 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2938 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
2939 __u64 *val, int mult)
2941 char kernbuf[22], *end, *pbuf;
2942 __u64 whole, frac = 0, units;
2943 unsigned frac_d = 1;
2945 if (count > (sizeof(kernbuf) - 1))
2948 if (copy_from_user(kernbuf, buffer, count))
2951 kernbuf[count] = '\0';
2958 whole = simple_strtoull(pbuf, &end, 10);
2962 if (end != NULL && *end == '.') {
2966 /* need to limit frac_d to a __u32 */
2967 if (strlen(pbuf) > 10)
2970 frac = simple_strtoull(pbuf, &end, 10);
2971 /* count decimal places */
2972 for (i = 0; i < (end - pbuf); i++)
2991 /* Specified units override the multiplier */
2993 mult = mult < 0 ? -units : units;
2996 do_div(frac, frac_d);
2997 *val = whole * mult + frac;
3000 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
3002 static char *lprocfs_strnstr(const char *s1, const char *s2, size_t len)
3011 if (!memcmp(s1, s2, l2))
3019 * Find the string \a name in the input \a buffer, and return a pointer to the
3020 * value immediately following \a name, reducing \a count appropriately.
3021 * If \a name is not found the original \a buffer is returned.
3023 char *lprocfs_find_named_value(const char *buffer, const char *name,
3027 size_t buflen = *count;
3029 /* there is no strnstr() in rhel5 and ubuntu kernels */
3030 val = lprocfs_strnstr(buffer, name, buflen);
3032 return (char *)buffer;
3034 val += strlen(name); /* skip prefix */
3035 while (val < buffer + buflen && isspace(*val)) /* skip separator */
3039 while (val < buffer + buflen && isalnum(*val)) {
3044 return val - *count;
3046 EXPORT_SYMBOL(lprocfs_find_named_value);
3048 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent,
3051 const struct file_operations *seq_fops,
3054 struct proc_dir_entry *entry;
3057 /* Disallow secretly (un)writable entries. */
3058 LASSERT((seq_fops->write == NULL) == ((mode & 0222) == 0));
3060 entry = proc_create_data(name, mode, parent, seq_fops, data);
3067 EXPORT_SYMBOL(lprocfs_seq_create);
3069 int lprocfs_obd_seq_create(struct obd_device *dev,
3072 const struct file_operations *seq_fops,
3075 return (lprocfs_seq_create(dev->obd_proc_entry, name,
3076 mode, seq_fops, data));
3078 EXPORT_SYMBOL(lprocfs_obd_seq_create);
3080 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
3082 if (value >= OBD_HIST_MAX)
3083 value = OBD_HIST_MAX - 1;
3085 spin_lock(&oh->oh_lock);
3086 oh->oh_buckets[value]++;
3087 spin_unlock(&oh->oh_lock);
3089 EXPORT_SYMBOL(lprocfs_oh_tally);
3091 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
3093 unsigned int val = 0;
3095 if (likely(value != 0))
3096 val = min(fls(value - 1), OBD_HIST_MAX);
3098 lprocfs_oh_tally(oh, val);
3100 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
3102 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
3104 unsigned long ret = 0;
3107 for (i = 0; i < OBD_HIST_MAX; i++)
3108 ret += oh->oh_buckets[i];
3111 EXPORT_SYMBOL(lprocfs_oh_sum);
3113 void lprocfs_oh_clear(struct obd_histogram *oh)
3115 spin_lock(&oh->oh_lock);
3116 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
3117 spin_unlock(&oh->oh_lock);
3119 EXPORT_SYMBOL(lprocfs_oh_clear);
3121 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
3122 int count, int *eof, void *data)
3124 struct obd_device *obd = data;
3130 c += cfs_hash_debug_header(page, count);
3131 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
3132 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
3133 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
3137 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
3139 #ifdef HAVE_SERVER_SUPPORT
3140 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
3141 int count, int *eof, void *data)
3143 struct obd_device *obd = data;
3146 LASSERT(obd != NULL);
3147 LASSERT(count >= 0);
3149 /* Set start of user data returned to
3150 page + off since the user may have
3151 requested to read much smaller than
3152 what we need to read */
3153 *start = page + off;
3156 * We know we are allocated a page here.
3157 * Also we know that this function will
3158 * not need to write more than a page
3159 * so we can truncate at PAGE_CACHE_SIZE.
3161 size = min(count + (int)off + 1, (int)PAGE_CACHE_SIZE);
3163 /* Initialize the page */
3164 memset(page, 0, size);
3166 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
3168 if (obd->obd_max_recoverable_clients == 0) {
3169 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
3175 /* sampled unlocked, but really... */
3176 if (obd->obd_recovering == 0) {
3177 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
3179 if (lprocfs_obd_snprintf(&page, size, &len,
3180 "recovery_start: %lu\n",
3181 obd->obd_recovery_start) <= 0)
3183 if (lprocfs_obd_snprintf(&page, size, &len,
3184 "recovery_duration: %lu\n",
3185 obd->obd_recovery_end -
3186 obd->obd_recovery_start) <= 0)
3188 /* Number of clients that have completed recovery */
3189 if (lprocfs_obd_snprintf(&page, size, &len,
3190 "completed_clients: %d/%d\n",
3191 obd->obd_max_recoverable_clients -
3192 obd->obd_stale_clients,
3193 obd->obd_max_recoverable_clients) <= 0)
3195 if (lprocfs_obd_snprintf(&page, size, &len,
3196 "replayed_requests: %d\n",
3197 obd->obd_replayed_requests) <= 0)
3199 if (lprocfs_obd_snprintf(&page, size, &len,
3200 "last_transno: "LPD64"\n",
3201 obd->obd_next_recovery_transno - 1)<=0)
3203 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
3204 obd->obd_version_recov ?
3205 "ENABLED" : "DISABLED") <=0)
3207 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
3209 "DISABLED" : "ENABLED") <= 0)
3214 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
3216 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
3217 obd->obd_recovery_start) <= 0)
3219 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
3220 cfs_time_current_sec() >=
3221 obd->obd_recovery_start +
3222 obd->obd_recovery_timeout ? 0 :
3223 obd->obd_recovery_start +
3224 obd->obd_recovery_timeout -
3225 cfs_time_current_sec()) <= 0)
3227 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
3228 atomic_read(&obd->obd_connected_clients),
3229 obd->obd_max_recoverable_clients) <= 0)
3231 /* Number of clients that have completed recovery */
3232 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
3233 atomic_read(&obd->obd_req_replay_clients))
3236 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
3237 atomic_read(&obd->obd_lock_replay_clients))
3240 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
3241 atomic_read(&obd->obd_connected_clients) -
3242 atomic_read(&obd->obd_lock_replay_clients))
3245 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
3246 obd->obd_stale_clients) <= 0)
3248 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
3249 obd->obd_replayed_requests) <= 0)
3251 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
3252 obd->obd_requests_queued_for_recovery) <= 0)
3255 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
3256 obd->obd_next_recovery_transno) <= 0)
3262 return min(count, len - (int)off);
3264 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
3267 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
3268 int count, int *eof, void *data)
3270 struct obd_device *obd = (struct obd_device *)data;
3271 LASSERT(obd != NULL);
3273 return snprintf(page, count, "%d\n",
3274 obd->obd_recovery_ir_factor);
3276 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
3278 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
3279 unsigned long count, void *data)
3281 struct obd_device *obd = (struct obd_device *)data;
3283 LASSERT(obd != NULL);
3285 rc = lprocfs_write_helper(buffer, count, &val);
3289 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
3292 obd->obd_recovery_ir_factor = val;
3295 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
3297 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
3298 int count, int *eof, void *data)
3300 struct obd_device *obd = (struct obd_device *)data;
3301 LASSERT(obd != NULL);
3303 return snprintf(page, count, "%d\n",
3304 obd->obd_recovery_timeout);
3306 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
3308 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
3309 unsigned long count, void *data)
3311 struct obd_device *obd = (struct obd_device *)data;
3313 LASSERT(obd != NULL);
3315 rc = lprocfs_write_helper(buffer, count, &val);
3319 obd->obd_recovery_timeout = val;
3322 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
3324 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
3325 int count, int *eof, void *data)
3327 struct obd_device *obd = data;
3328 LASSERT(obd != NULL);
3330 return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
3332 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
3334 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
3335 unsigned long count, void *data)
3337 struct obd_device *obd = data;
3339 LASSERT(obd != NULL);
3341 rc = lprocfs_write_helper(buffer, count, &val);
3345 obd->obd_recovery_time_hard = val;
3348 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
3350 int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
3351 int count, int *eof, void *data)
3353 struct obd_device *dev = data;
3354 struct client_obd *cli = &dev->u.cli;
3357 client_obd_list_lock(&cli->cl_loi_list_lock);
3358 rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
3359 client_obd_list_unlock(&cli->cl_loi_list_lock);
3362 EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
3364 int lprocfs_obd_max_pages_per_rpc_seq_show(struct seq_file *m, void *data)
3366 struct obd_device *dev = data;
3367 struct client_obd *cli = &dev->u.cli;
3370 client_obd_list_lock(&cli->cl_loi_list_lock);
3371 rc = seq_printf(m, "%d\n", cli->cl_max_pages_per_rpc);
3372 client_obd_list_unlock(&cli->cl_loi_list_lock);
3375 EXPORT_SYMBOL(lprocfs_obd_max_pages_per_rpc_seq_show);
3377 #ifdef HAVE_SERVER_SUPPORT
3378 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
3379 int count, int *eof, void *data)
3381 struct obd_device *obd = (struct obd_device *)data;
3382 struct obd_device_target *target = &obd->u.obt;
3384 LASSERT(obd != NULL);
3385 LASSERT(target->obt_magic == OBT_MAGIC);
3387 return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
3389 EXPORT_SYMBOL(lprocfs_target_rd_instance);