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 struct lprocfs_counter *ptr;
869 unsigned int num_entry;
871 unsigned long flags = 0;
873 memset(cnt, 0, sizeof(*cnt));
876 /* set count to 1 to avoid divide-by-zero errs in callers */
881 cnt->lc_min = LC_MIN_INIT;
883 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
885 for (i = 0; i < num_entry; i++) {
886 if (stats->ls_percpu[i] == NULL)
889 ptr = &(stats->ls_percpu[i])->lp_cntr[idx];
890 cnt->lc_count += ptr->lc_count;
891 cnt->lc_sum += ptr->lc_sum;
892 if (ptr->lc_min < cnt->lc_min)
893 cnt->lc_min = ptr->lc_min;
894 if (ptr->lc_max > cnt->lc_max)
895 cnt->lc_max = ptr->lc_max;
896 cnt->lc_sumsquare += ptr->lc_sumsquare;
899 cnt->lc_units = stats->ls_percpu[0]->lp_cntr[idx].lc_units;
900 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
902 EXPORT_SYMBOL(lprocfs_stats_collect);
905 * Append a space separated list of current set flags to str.
907 #define flag2str(flag) \
908 if (imp->imp_##flag && max - len > 0) \
909 len += snprintf(str + len, max - len, "%s" #flag, len ? ", " : "");
910 static int obd_import_flags2str(struct obd_import *imp, char *str, int max)
914 if (imp->imp_obd->obd_no_recov)
915 len += snprintf(str, max - len, "no_recov");
919 flag2str(replayable);
925 static const char *obd_connect_names[] = {
939 "join_file(obsolete)",
943 "remote_client_by_force",
952 "mds_mds_connection",
955 "alt_checksum_algorithm",
980 int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
985 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
987 ret += snprintf(page + ret, count - ret, "%s%s",
988 ret ? sep : "", obd_connect_names[i]);
990 if (flags & ~(mask - 1))
991 ret += snprintf(page + ret, count - ret,
992 "%sunknown flags "LPX64,
993 ret ? sep : "", flags & ~(mask - 1));
996 EXPORT_SYMBOL(obd_connect_flags2str);
998 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
999 int *eof, void *data)
1001 struct lprocfs_counter ret;
1002 struct obd_device *obd = (struct obd_device *)data;
1003 struct obd_import *imp;
1004 struct obd_import_conn *conn;
1005 int i, j, k, rw = 0;
1007 LASSERT(obd != NULL);
1008 LPROCFS_CLIMP_CHECK(obd);
1009 imp = obd->u.cli.cl_import;
1012 i = snprintf(page, count,
1018 " connect_flags: [",
1021 ptlrpc_import_state_name(imp->imp_state),
1022 imp->imp_connect_data.ocd_instance);
1023 i += obd_connect_flags2str(page + i, count - i,
1024 imp->imp_connect_data.ocd_connect_flags,
1026 i += snprintf(page + i, count - i,
1028 " import_flags: [");
1029 i += obd_import_flags2str(imp, page + i, count - i);
1031 i += snprintf(page + i, count - i,
1034 " failover_nids: [");
1035 spin_lock(&imp->imp_lock);
1037 cfs_list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
1038 i += snprintf(page + i, count - i, "%s%s", j ? ", " : "",
1039 libcfs_nid2str(conn->oic_conn->c_peer.nid));
1042 i += snprintf(page + i, count - i,
1044 " current_connection: %s\n"
1045 " connection_attempts: %u\n"
1047 " in-progress_invalidations: %u\n",
1048 imp->imp_connection == NULL ? "<none>" :
1049 libcfs_nid2str(imp->imp_connection->c_peer.nid),
1051 imp->imp_generation,
1052 cfs_atomic_read(&imp->imp_inval_count));
1053 spin_unlock(&imp->imp_lock);
1055 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
1056 if (ret.lc_count != 0) {
1057 /* first argument to do_div MUST be __u64 */
1058 __u64 sum = ret.lc_sum;
1059 do_div(sum, ret.lc_count);
1063 i += snprintf(page + i, count - i,
1066 " unregistering: %u\n"
1068 " avg_waittime: "LPU64" %s\n",
1069 cfs_atomic_read(&imp->imp_inflight),
1070 cfs_atomic_read(&imp->imp_unregistering),
1071 cfs_atomic_read(&imp->imp_timeouts),
1072 ret.lc_sum, ret.lc_units);
1075 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
1076 if (imp->imp_at.iat_portal[j] == 0)
1078 k = max_t(unsigned int, k,
1079 at_get(&imp->imp_at.iat_service_estimate[j]));
1081 i += snprintf(page + i, count - i,
1082 " service_estimates:\n"
1083 " services: %u sec\n"
1084 " network: %u sec\n",
1086 at_get(&imp->imp_at.iat_net_latency));
1088 i += snprintf(page + i, count - i,
1090 " last_replay: "LPU64"\n"
1091 " peer_committed: "LPU64"\n"
1092 " last_checked: "LPU64"\n",
1093 imp->imp_last_replay_transno,
1094 imp->imp_peer_committed_transno,
1095 imp->imp_last_transno_checked);
1097 /* avg data rates */
1098 for (rw = 0; rw <= 1; rw++) {
1099 lprocfs_stats_collect(obd->obd_svc_stats,
1100 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
1102 if (ret.lc_sum > 0 && ret.lc_count > 0) {
1103 /* first argument to do_div MUST be __u64 */
1104 __u64 sum = ret.lc_sum;
1105 do_div(sum, ret.lc_count);
1107 i += snprintf(page + i, count - i,
1108 " %s_data_averages:\n"
1109 " bytes_per_rpc: "LPU64"\n",
1110 rw ? "write" : "read",
1113 k = (int)ret.lc_sum;
1114 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
1115 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
1116 if (ret.lc_sum > 0 && ret.lc_count != 0) {
1117 /* first argument to do_div MUST be __u64 */
1118 __u64 sum = ret.lc_sum;
1119 do_div(sum, ret.lc_count);
1121 i += snprintf(page + i, count - i,
1122 " %s_per_rpc: "LPU64"\n",
1123 ret.lc_units, ret.lc_sum);
1124 j = (int)ret.lc_sum;
1126 i += snprintf(page + i, count - i,
1127 " MB_per_sec: %u.%.02u\n",
1128 k / j, (100 * k / j) % 100);
1132 LPROCFS_CLIMP_EXIT(obd);
1135 EXPORT_SYMBOL(lprocfs_rd_import);
1137 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
1138 int *eof, void *data)
1140 struct obd_device *obd = (struct obd_device *)data;
1141 struct obd_import *imp;
1144 LASSERT(obd != NULL);
1145 LPROCFS_CLIMP_CHECK(obd);
1146 imp = obd->u.cli.cl_import;
1149 i = snprintf(page, count, "current_state: %s\n",
1150 ptlrpc_import_state_name(imp->imp_state));
1151 i += snprintf(page + i, count - i,
1152 "state_history:\n");
1153 k = imp->imp_state_hist_idx;
1154 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
1155 struct import_state_hist *ish =
1156 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
1157 if (ish->ish_state == 0)
1159 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
1161 ptlrpc_import_state_name(ish->ish_state));
1164 LPROCFS_CLIMP_EXIT(obd);
1167 EXPORT_SYMBOL(lprocfs_rd_state);
1169 int lprocfs_at_hist_helper(char *page, int count, int rc,
1170 struct adaptive_timeout *at)
1173 for (i = 0; i < AT_BINS; i++)
1174 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
1175 rc += snprintf(page + rc, count - rc, "\n");
1178 EXPORT_SYMBOL(lprocfs_at_hist_helper);
1180 /* See also ptlrpc_lprocfs_rd_timeouts */
1181 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
1182 int *eof, void *data)
1184 struct obd_device *obd = (struct obd_device *)data;
1185 struct obd_import *imp;
1186 unsigned int cur, worst;
1191 LASSERT(obd != NULL);
1192 LPROCFS_CLIMP_CHECK(obd);
1193 imp = obd->u.cli.cl_import;
1196 now = cfs_time_current_sec();
1198 /* Some network health info for kicks */
1199 s2dhms(&ts, now - imp->imp_last_reply_time);
1200 rc += snprintf(page + rc, count - rc,
1201 "%-10s : %ld, "DHMS_FMT" ago\n",
1202 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
1204 cur = at_get(&imp->imp_at.iat_net_latency);
1205 worst = imp->imp_at.iat_net_latency.at_worst_ever;
1206 worstt = imp->imp_at.iat_net_latency.at_worst_time;
1207 s2dhms(&ts, now - worstt);
1208 rc += snprintf(page + rc, count - rc,
1209 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
1210 "network", cur, worst, worstt, DHMS_VARS(&ts));
1211 rc = lprocfs_at_hist_helper(page, count, rc,
1212 &imp->imp_at.iat_net_latency);
1214 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
1215 if (imp->imp_at.iat_portal[i] == 0)
1217 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
1218 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
1219 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
1220 s2dhms(&ts, now - worstt);
1221 rc += snprintf(page + rc, count - rc,
1222 "portal %-2d : cur %3u worst %3u (at %ld, "
1223 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
1224 cur, worst, worstt, DHMS_VARS(&ts));
1225 rc = lprocfs_at_hist_helper(page, count, rc,
1226 &imp->imp_at.iat_service_estimate[i]);
1229 LPROCFS_CLIMP_EXIT(obd);
1232 EXPORT_SYMBOL(lprocfs_rd_timeouts);
1234 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1235 int count, int *eof, void *data)
1237 struct obd_device *obd = data;
1241 LPROCFS_CLIMP_CHECK(obd);
1242 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1243 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1244 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1245 ret += snprintf(page + ret, count - ret, "\n");
1246 LPROCFS_CLIMP_EXIT(obd);
1249 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1251 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1252 int *eof, void *data)
1254 struct obd_device *obd = data;
1256 LASSERT(obd != NULL);
1258 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1260 EXPORT_SYMBOL(lprocfs_rd_num_exports);
1262 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1263 int *eof, void *data)
1265 struct obd_type *class = (struct obd_type*) data;
1267 LASSERT(class != NULL);
1269 return snprintf(page, count, "%d\n", class->typ_refcnt);
1271 EXPORT_SYMBOL(lprocfs_rd_numrefs);
1273 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1277 LASSERT(obd != NULL);
1278 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1279 LASSERT(obd->obd_type->typ_procroot != NULL);
1281 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1282 obd->obd_type->typ_procroot,
1284 if (IS_ERR(obd->obd_proc_entry)) {
1285 rc = PTR_ERR(obd->obd_proc_entry);
1286 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1287 obd->obd_proc_entry = NULL;
1291 EXPORT_SYMBOL(lprocfs_obd_setup);
1293 int lprocfs_obd_cleanup(struct obd_device *obd)
1297 if (obd->obd_proc_exports_entry) {
1298 /* Should be no exports left */
1299 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1300 lprocfs_remove(&obd->obd_proc_exports_entry);
1301 obd->obd_proc_exports_entry = NULL;
1303 if (obd->obd_proc_entry) {
1304 lprocfs_remove(&obd->obd_proc_entry);
1305 obd->obd_proc_entry = NULL;
1309 EXPORT_SYMBOL(lprocfs_obd_cleanup);
1311 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1313 CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
1314 client_stat->nid_proc, client_stat->nid_stats,
1315 client_stat->nid_brw_stats);
1317 LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
1318 "nid %s:count %d\n", libcfs_nid2str(client_stat->nid),
1319 atomic_read(&client_stat->nid_exp_ref_count));
1321 if (client_stat->nid_proc)
1322 lprocfs_remove(&client_stat->nid_proc);
1324 if (client_stat->nid_stats)
1325 lprocfs_free_stats(&client_stat->nid_stats);
1327 if (client_stat->nid_brw_stats)
1328 OBD_FREE_PTR(client_stat->nid_brw_stats);
1330 if (client_stat->nid_ldlm_stats)
1331 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1333 OBD_FREE_PTR(client_stat);
1338 void lprocfs_free_per_client_stats(struct obd_device *obd)
1340 cfs_hash_t *hash = obd->obd_nid_stats_hash;
1341 struct nid_stat *stat;
1344 /* we need extra list - because hash_exit called to early */
1345 /* not need locking because all clients is died */
1346 while (!cfs_list_empty(&obd->obd_nid_stats)) {
1347 stat = cfs_list_entry(obd->obd_nid_stats.next,
1348 struct nid_stat, nid_list);
1349 cfs_list_del_init(&stat->nid_list);
1350 cfs_hash_del(hash, &stat->nid, &stat->nid_hash);
1351 lprocfs_free_client_stats(stat);
1355 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
1357 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1358 enum lprocfs_stats_flags flags)
1360 struct lprocfs_stats *stats;
1361 unsigned int percpusize;
1362 unsigned int num_entry;
1367 if (lprocfs_no_percpu_stats != 0)
1368 flags |= LPROCFS_STATS_FLAG_NOPERCPU;
1370 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1373 num_entry = cfs_num_possible_cpus() + 1;
1375 /* alloc percpu pointers for all possible cpu slots */
1376 OBD_ALLOC(stats, offsetof(struct lprocfs_stats, ls_percpu[num_entry]));
1380 stats->ls_num = num;
1381 stats->ls_biggest_alloc_num = 1;
1382 stats->ls_flags = flags;
1383 spin_lock_init(&stats->ls_lock);
1385 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
1387 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1389 /* for no percpu area, the 0th entry is for real use,
1390 * for percpu area, the 0th entry is for intialized entry template */
1391 OBD_ALLOC(stats->ls_percpu[0], percpusize);
1392 if (stats->ls_percpu[0] == NULL) {
1394 offsetof(struct lprocfs_stats, ls_percpu[num_entry]));
1399 EXPORT_SYMBOL(lprocfs_alloc_stats);
1401 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1403 struct lprocfs_stats *stats = *statsh;
1404 unsigned int num_entry;
1405 unsigned int percpusize;
1408 if (stats == NULL || stats->ls_num == 0)
1412 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1415 num_entry = cfs_num_possible_cpus() + 1;
1417 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
1419 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1420 for (i = 0; i < num_entry; i++)
1421 if (stats->ls_percpu[i] != NULL)
1422 OBD_FREE(stats->ls_percpu[i], percpusize);
1423 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1425 EXPORT_SYMBOL(lprocfs_free_stats);
1427 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1429 struct lprocfs_counter *percpu_cntr;
1432 unsigned int num_entry;
1433 unsigned long flags = 0;
1435 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1437 for (i = 0; i < num_entry; i++) {
1438 if (stats->ls_percpu[i] == NULL)
1440 for (j = 0; j < stats->ls_num; j++) {
1441 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
1442 percpu_cntr->lc_count = 0;
1443 percpu_cntr->lc_sum = 0;
1444 percpu_cntr->lc_min = LC_MIN_INIT;
1445 percpu_cntr->lc_max = 0;
1446 percpu_cntr->lc_sumsquare = 0;
1450 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1452 EXPORT_SYMBOL(lprocfs_clear_stats);
1454 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1455 size_t len, loff_t *off)
1457 struct seq_file *seq = file->private_data;
1458 struct lprocfs_stats *stats = seq->private;
1460 lprocfs_clear_stats(stats);
1465 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1467 struct lprocfs_stats *stats = p->private;
1468 /* return 1st cpu location */
1469 return (*pos >= stats->ls_num) ? NULL :
1470 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1473 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1477 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1479 struct lprocfs_stats *stats = p->private;
1481 return (*pos >= stats->ls_num) ? NULL :
1482 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1485 /* seq file export of one lprocfs counter */
1486 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1488 struct lprocfs_stats *stats = p->private;
1489 struct lprocfs_counter *cntr = v;
1490 struct lprocfs_counter ret;
1493 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
1495 cfs_gettimeofday(&now);
1496 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1497 "snapshot_time", now.tv_sec, now.tv_usec);
1501 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
1503 lprocfs_stats_collect(stats, idx, &ret);
1505 if (ret.lc_count == 0)
1508 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", cntr->lc_name,
1509 ret.lc_count, cntr->lc_units);
1514 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
1515 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1516 ret.lc_min, ret.lc_max, ret.lc_sum);
1519 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
1520 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1524 rc = seq_printf(p, "\n");
1526 return (rc < 0) ? rc : 0;
1529 struct seq_operations lprocfs_stats_seq_sops = {
1530 start: lprocfs_stats_seq_start,
1531 stop: lprocfs_stats_seq_stop,
1532 next: lprocfs_stats_seq_next,
1533 show: lprocfs_stats_seq_show,
1536 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1538 struct proc_dir_entry *dp = PDE(inode);
1539 struct seq_file *seq;
1542 if (LPROCFS_ENTRY_AND_CHECK(dp))
1545 rc = seq_open(file, &lprocfs_stats_seq_sops);
1550 seq = file->private_data;
1551 seq->private = dp->data;
1555 struct file_operations lprocfs_stats_seq_fops = {
1556 .owner = THIS_MODULE,
1557 .open = lprocfs_stats_seq_open,
1559 .write = lprocfs_stats_seq_write,
1560 .llseek = seq_lseek,
1561 .release = lprocfs_seq_release,
1564 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1565 struct lprocfs_stats *stats)
1567 struct proc_dir_entry *entry;
1568 LASSERT(root != NULL);
1570 LPROCFS_WRITE_ENTRY();
1571 entry = create_proc_entry(name, 0644, root);
1573 entry->proc_fops = &lprocfs_stats_seq_fops;
1574 entry->data = stats;
1577 LPROCFS_WRITE_EXIT();
1584 EXPORT_SYMBOL(lprocfs_register_stats);
1586 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1587 unsigned conf, const char *name, const char *units)
1589 struct lprocfs_counter *c = &(stats->ls_percpu[0]->lp_cntr[index]);
1590 unsigned long flags = 0;
1592 LASSERT(stats != NULL);
1593 LASSERT(stats->ls_percpu[0] != NULL);
1595 lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1596 c->lc_config = conf;
1599 c->lc_min = LC_MIN_INIT;
1602 c->lc_units = units;
1603 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1605 EXPORT_SYMBOL(lprocfs_counter_init);
1607 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1609 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1610 LASSERT(coffset < stats->ls_num); \
1611 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1614 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1616 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1617 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1618 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1619 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1620 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1621 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1622 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1623 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1624 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1625 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1626 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1627 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1628 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1629 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1630 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1631 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1632 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1633 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1634 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1635 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1636 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1637 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1638 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1639 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1640 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1641 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1642 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1643 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1644 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1645 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1646 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1647 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1648 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1649 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1650 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1651 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1652 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1653 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1654 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1655 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1656 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1657 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1658 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1659 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
1660 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1661 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1662 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1663 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1664 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1665 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1666 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1667 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1668 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1669 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1670 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1671 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1672 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1673 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1674 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1675 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1676 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1677 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1678 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1679 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1680 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1681 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1682 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1684 EXPORT_SYMBOL(lprocfs_init_ops_stats);
1686 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1688 struct lprocfs_stats *stats;
1689 unsigned int num_stats;
1692 LASSERT(obd->obd_stats == NULL);
1693 LASSERT(obd->obd_proc_entry != NULL);
1694 LASSERT(obd->obd_cntr_base == 0);
1696 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1697 num_private_stats - 1 /* o_owner */;
1698 stats = lprocfs_alloc_stats(num_stats, 0);
1702 lprocfs_init_ops_stats(num_private_stats, stats);
1704 for (i = num_private_stats; i < num_stats; i++) {
1705 /* If this LBUGs, it is likely that an obd
1706 * operation was added to struct obd_ops in
1707 * <obd.h>, and that the corresponding line item
1708 * LPROCFS_OBD_OP_INIT(.., .., opname)
1709 * is missing from the list above. */
1710 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1711 "Missing obd_stat initializer obd_op "
1712 "operation at offset %d.\n", i - num_private_stats);
1714 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1716 lprocfs_free_stats(&stats);
1718 obd->obd_stats = stats;
1719 obd->obd_cntr_base = num_private_stats;
1723 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
1725 void lprocfs_free_obd_stats(struct obd_device *obd)
1728 lprocfs_free_stats(&obd->obd_stats);
1730 EXPORT_SYMBOL(lprocfs_free_obd_stats);
1732 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1734 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1735 LASSERT(coffset < stats->ls_num); \
1736 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1739 void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats)
1741 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1742 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1743 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
1744 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1745 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1746 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1747 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1748 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1749 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1750 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1751 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1752 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1753 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1754 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1755 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1756 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1757 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1758 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1759 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1760 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1761 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1762 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1763 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1764 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1765 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1766 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1767 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1768 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1769 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1770 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1771 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1772 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1774 EXPORT_SYMBOL(lprocfs_init_mps_stats);
1776 int lprocfs_alloc_md_stats(struct obd_device *obd,
1777 unsigned num_private_stats)
1779 struct lprocfs_stats *stats;
1780 unsigned int num_stats;
1783 LASSERT(obd->md_stats == NULL);
1784 LASSERT(obd->obd_proc_entry != NULL);
1785 LASSERT(obd->md_cntr_base == 0);
1787 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1789 stats = lprocfs_alloc_stats(num_stats, 0);
1793 lprocfs_init_mps_stats(num_private_stats, stats);
1795 for (i = num_private_stats; i < num_stats; i++) {
1796 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1797 CERROR("Missing md_stat initializer md_op "
1798 "operation at offset %d. Aborting.\n",
1799 i - num_private_stats);
1803 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1805 lprocfs_free_stats(&stats);
1807 obd->md_stats = stats;
1808 obd->md_cntr_base = num_private_stats;
1812 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
1814 void lprocfs_free_md_stats(struct obd_device *obd)
1816 struct lprocfs_stats *stats = obd->md_stats;
1818 if (stats != NULL) {
1819 obd->md_stats = NULL;
1820 obd->md_cntr_base = 0;
1821 lprocfs_free_stats(&stats);
1824 EXPORT_SYMBOL(lprocfs_free_md_stats);
1826 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1828 lprocfs_counter_init(ldlm_stats,
1829 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1830 0, "ldlm_enqueue", "reqs");
1831 lprocfs_counter_init(ldlm_stats,
1832 LDLM_CONVERT - LDLM_FIRST_OPC,
1833 0, "ldlm_convert", "reqs");
1834 lprocfs_counter_init(ldlm_stats,
1835 LDLM_CANCEL - LDLM_FIRST_OPC,
1836 0, "ldlm_cancel", "reqs");
1837 lprocfs_counter_init(ldlm_stats,
1838 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1839 0, "ldlm_bl_callback", "reqs");
1840 lprocfs_counter_init(ldlm_stats,
1841 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1842 0, "ldlm_cp_callback", "reqs");
1843 lprocfs_counter_init(ldlm_stats,
1844 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1845 0, "ldlm_gl_callback", "reqs");
1847 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
1849 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1850 int *eof, void *data)
1852 struct obd_export *exp = data;
1853 LASSERT(exp != NULL);
1855 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1858 struct exp_uuid_cb_data {
1866 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1867 int count, int *eof, int *len)
1869 cb_data->page = page;
1870 cb_data->count = count;
1875 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1876 cfs_hlist_node_t *hnode, void *cb_data)
1879 struct obd_export *exp = cfs_hash_object(hs, hnode);
1880 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1882 if (exp->exp_nid_stats)
1883 *data->len += snprintf((data->page + *data->len),
1884 data->count, "%s\n",
1885 obd_uuid2str(&exp->exp_client_uuid));
1889 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1890 int *eof, void *data)
1892 struct nid_stat *stats = (struct nid_stat *)data;
1893 struct exp_uuid_cb_data cb_data;
1894 struct obd_device *obd = stats->nid_obd;
1899 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1900 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1901 lprocfs_exp_print_uuid, &cb_data);
1902 return (*cb_data.len);
1905 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1906 cfs_hlist_node_t *hnode, void *cb_data)
1909 struct exp_uuid_cb_data *data = cb_data;
1910 struct obd_export *exp = cfs_hash_object(hs, hnode);
1912 if (exp->exp_lock_hash != NULL) {
1914 *data->len += cfs_hash_debug_header(data->page,
1917 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1924 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1925 int *eof, void *data)
1927 struct nid_stat *stats = (struct nid_stat *)data;
1928 struct exp_uuid_cb_data cb_data;
1929 struct obd_device *obd = stats->nid_obd;
1934 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1936 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1937 lprocfs_exp_print_hash, &cb_data);
1938 return (*cb_data.len);
1941 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1942 int count, int *eof, void *data)
1945 return snprintf(page, count, "%s\n",
1946 "Write into this file to clear all nid stats and "
1947 "stale nid entries");
1949 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1951 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1953 struct nid_stat *stat = obj;
1957 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
1958 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 1) {
1959 /* object has only hash references. */
1960 spin_lock(&stat->nid_obd->obd_nid_lock);
1961 cfs_list_move(&stat->nid_list, data);
1962 spin_unlock(&stat->nid_obd->obd_nid_lock);
1965 /* we has reference to object - only clear data*/
1966 if (stat->nid_stats)
1967 lprocfs_clear_stats(stat->nid_stats);
1969 if (stat->nid_brw_stats) {
1970 for (i = 0; i < BRW_LAST; i++)
1971 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
1976 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1977 unsigned long count, void *data)
1979 struct obd_device *obd = (struct obd_device *)data;
1980 struct nid_stat *client_stat;
1981 CFS_LIST_HEAD(free_list);
1983 cfs_hash_cond_del(obd->obd_nid_stats_hash,
1984 lprocfs_nid_stats_clear_write_cb, &free_list);
1986 while (!cfs_list_empty(&free_list)) {
1987 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
1989 cfs_list_del_init(&client_stat->nid_list);
1990 lprocfs_free_client_stats(client_stat);
1995 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1997 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1999 struct nid_stat *new_stat, *old_stat;
2000 struct obd_device *obd = NULL;
2001 cfs_proc_dir_entry_t *entry;
2002 char *buffer = NULL;
2008 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
2009 !exp->exp_obd->obd_nid_stats_hash)
2012 /* not test against zero because eric say:
2013 * You may only test nid against another nid, or LNET_NID_ANY.
2014 * Anything else is nonsense.*/
2015 if (!nid || *nid == LNET_NID_ANY)
2020 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
2022 OBD_ALLOC_PTR(new_stat);
2023 if (new_stat == NULL)
2026 new_stat->nid = *nid;
2027 new_stat->nid_obd = exp->exp_obd;
2028 /* we need set default refcount to 1 to balance obd_disconnect */
2029 cfs_atomic_set(&new_stat->nid_exp_ref_count, 1);
2031 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
2032 nid, &new_stat->nid_hash);
2033 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
2034 old_stat, libcfs_nid2str(*nid),
2035 cfs_atomic_read(&new_stat->nid_exp_ref_count));
2037 /* We need to release old stats because lprocfs_exp_cleanup() hasn't
2038 * been and will never be called. */
2039 if (exp->exp_nid_stats) {
2040 nidstat_putref(exp->exp_nid_stats);
2041 exp->exp_nid_stats = NULL;
2044 /* Return -EALREADY here so that we know that the /proc
2045 * entry already has been created */
2046 if (old_stat != new_stat) {
2047 exp->exp_nid_stats = old_stat;
2048 GOTO(destroy_new, rc = -EALREADY);
2050 /* not found - create */
2051 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
2053 GOTO(destroy_new, rc = -ENOMEM);
2055 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
2056 new_stat->nid_proc = lprocfs_register(buffer,
2057 obd->obd_proc_exports_entry,
2059 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
2061 if (new_stat->nid_proc == NULL) {
2062 CERROR("Error making export directory for nid %s\n",
2063 libcfs_nid2str(*nid));
2064 GOTO(destroy_new_ns, rc = -ENOMEM);
2067 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
2068 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
2069 if (IS_ERR(entry)) {
2070 CWARN("Error adding the NID stats file\n");
2071 rc = PTR_ERR(entry);
2072 GOTO(destroy_new_ns, rc);
2075 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
2076 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
2077 if (IS_ERR(entry)) {
2078 CWARN("Error adding the hash file\n");
2079 rc = PTR_ERR(entry);
2080 GOTO(destroy_new_ns, rc);
2083 exp->exp_nid_stats = new_stat;
2085 /* protect competitive add to list, not need locking on destroy */
2086 spin_lock(&obd->obd_nid_lock);
2087 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
2088 spin_unlock(&obd->obd_nid_lock);
2093 if (new_stat->nid_proc != NULL)
2094 lprocfs_remove(&new_stat->nid_proc);
2095 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
2098 nidstat_putref(new_stat);
2099 OBD_FREE_PTR(new_stat);
2102 EXPORT_SYMBOL(lprocfs_exp_setup);
2104 int lprocfs_exp_cleanup(struct obd_export *exp)
2106 struct nid_stat *stat = exp->exp_nid_stats;
2108 if(!stat || !exp->exp_obd)
2111 nidstat_putref(exp->exp_nid_stats);
2112 exp->exp_nid_stats = NULL;
2116 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2118 int lprocfs_write_helper(const char *buffer, unsigned long count,
2121 return lprocfs_write_frac_helper(buffer, count, val, 1);
2123 EXPORT_SYMBOL(lprocfs_write_helper);
2125 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
2128 char kernbuf[20], *end, *pbuf;
2130 if (count > (sizeof(kernbuf) - 1))
2133 if (cfs_copy_from_user(kernbuf, buffer, count))
2136 kernbuf[count] = '\0';
2143 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2147 if (end != NULL && *end == '.') {
2148 int temp_val, pow = 1;
2152 if (strlen(pbuf) > 5)
2153 pbuf[5] = '\0'; /*only allow 5bits fractional*/
2155 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2158 for (i = 0; i < (end - pbuf); i++)
2161 *val += temp_val / pow;
2166 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2168 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
2171 long decimal_val, frac_val;
2177 decimal_val = val / mult;
2178 prtn = snprintf(buffer, count, "%ld", decimal_val);
2179 frac_val = val % mult;
2181 if (prtn < (count - 4) && frac_val > 0) {
2183 int i, temp_mult = 1, frac_bits = 0;
2185 temp_frac = frac_val * 10;
2186 buffer[prtn++] = '.';
2187 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
2188 /* only reserved 2 bits fraction */
2189 buffer[prtn++] ='0';
2194 * Need to think these cases :
2195 * 1. #echo x.00 > /proc/xxx output result : x
2196 * 2. #echo x.0x > /proc/xxx output result : x.0x
2197 * 3. #echo x.x0 > /proc/xxx output result : x.x
2198 * 4. #echo x.xx > /proc/xxx output result : x.xx
2199 * Only reserved 2 bits fraction.
2201 for (i = 0; i < (5 - prtn); i++)
2204 frac_bits = min((int)count - prtn, 3 - frac_bits);
2205 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
2206 frac_val * temp_mult / mult);
2209 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
2211 if (buffer[prtn] == '.') {
2218 buffer[prtn++] ='\n';
2221 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2223 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
2225 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
2227 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2229 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
2230 __u64 *val, int mult)
2232 char kernbuf[22], *end, *pbuf;
2233 __u64 whole, frac = 0, units;
2234 unsigned frac_d = 1;
2236 if (count > (sizeof(kernbuf) - 1))
2239 if (cfs_copy_from_user(kernbuf, buffer, count))
2242 kernbuf[count] = '\0';
2249 whole = simple_strtoull(pbuf, &end, 10);
2253 if (end != NULL && *end == '.') {
2257 /* need to limit frac_d to a __u32 */
2258 if (strlen(pbuf) > 10)
2261 frac = simple_strtoull(pbuf, &end, 10);
2262 /* count decimal places */
2263 for (i = 0; i < (end - pbuf); i++)
2280 /* Specified units override the multiplier */
2282 mult = mult < 0 ? -units : units;
2285 do_div(frac, frac_d);
2286 *val = whole * mult + frac;
2289 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2291 static char *lprocfs_strnstr(const char *s1, const char *s2, size_t len)
2300 if (!memcmp(s1, s2, l2))
2308 * Find the string \a name in the input \a buffer, and return a pointer to the
2309 * value immediately following \a name, reducing \a count appropriately.
2310 * If \a name is not found the original \a buffer is returned.
2312 char *lprocfs_find_named_value(const char *buffer, const char *name,
2313 unsigned long *count)
2316 size_t buflen = *count;
2318 /* there is no strnstr() in rhel5 and ubuntu kernels */
2319 val = lprocfs_strnstr(buffer, name, buflen);
2321 return (char *)buffer;
2323 val += strlen(name); /* skip prefix */
2324 while (val < buffer + buflen && isspace(*val)) /* skip separator */
2328 while (val < buffer + buflen && isalnum(*val)) {
2333 return val - *count;
2335 EXPORT_SYMBOL(lprocfs_find_named_value);
2337 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent,
2340 const struct file_operations *seq_fops,
2343 struct proc_dir_entry *entry;
2346 LPROCFS_WRITE_ENTRY();
2347 entry = create_proc_entry(name, mode, parent);
2349 entry->proc_fops = seq_fops;
2352 LPROCFS_WRITE_EXIT();
2359 EXPORT_SYMBOL(lprocfs_seq_create);
2361 int lprocfs_obd_seq_create(struct obd_device *dev,
2364 const struct file_operations *seq_fops,
2367 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2368 mode, seq_fops, data));
2370 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2372 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2374 if (value >= OBD_HIST_MAX)
2375 value = OBD_HIST_MAX - 1;
2377 spin_lock(&oh->oh_lock);
2378 oh->oh_buckets[value]++;
2379 spin_unlock(&oh->oh_lock);
2381 EXPORT_SYMBOL(lprocfs_oh_tally);
2383 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2387 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2390 lprocfs_oh_tally(oh, val);
2392 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2394 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2396 unsigned long ret = 0;
2399 for (i = 0; i < OBD_HIST_MAX; i++)
2400 ret += oh->oh_buckets[i];
2403 EXPORT_SYMBOL(lprocfs_oh_sum);
2405 void lprocfs_oh_clear(struct obd_histogram *oh)
2407 spin_lock(&oh->oh_lock);
2408 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2409 spin_unlock(&oh->oh_lock);
2411 EXPORT_SYMBOL(lprocfs_oh_clear);
2413 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2414 int count, int *eof, void *data)
2416 struct obd_device *obd = data;
2422 c += cfs_hash_debug_header(page, count);
2423 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2424 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2425 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2429 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2431 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2432 int count, int *eof, void *data)
2434 struct obd_device *obd = data;
2437 LASSERT(obd != NULL);
2438 LASSERT(count >= 0);
2440 /* Set start of user data returned to
2441 page + off since the user may have
2442 requested to read much smaller than
2443 what we need to read */
2444 *start = page + off;
2446 /* We know we are allocated a page here.
2447 Also we know that this function will
2448 not need to write more than a page
2449 so we can truncate at CFS_PAGE_SIZE. */
2450 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2452 /* Initialize the page */
2453 memset(page, 0, size);
2455 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2457 if (obd->obd_max_recoverable_clients == 0) {
2458 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2464 /* sampled unlocked, but really... */
2465 if (obd->obd_recovering == 0) {
2466 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2468 if (lprocfs_obd_snprintf(&page, size, &len,
2469 "recovery_start: %lu\n",
2470 obd->obd_recovery_start) <= 0)
2472 if (lprocfs_obd_snprintf(&page, size, &len,
2473 "recovery_duration: %lu\n",
2474 obd->obd_recovery_end -
2475 obd->obd_recovery_start) <= 0)
2477 /* Number of clients that have completed recovery */
2478 if (lprocfs_obd_snprintf(&page, size, &len,
2479 "completed_clients: %d/%d\n",
2480 obd->obd_max_recoverable_clients -
2481 obd->obd_stale_clients,
2482 obd->obd_max_recoverable_clients) <= 0)
2484 if (lprocfs_obd_snprintf(&page, size, &len,
2485 "replayed_requests: %d\n",
2486 obd->obd_replayed_requests) <= 0)
2488 if (lprocfs_obd_snprintf(&page, size, &len,
2489 "last_transno: "LPD64"\n",
2490 obd->obd_next_recovery_transno - 1)<=0)
2492 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2493 obd->obd_version_recov ?
2494 "ENABLED" : "DISABLED") <=0)
2496 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
2498 "DISABLED" : "ENABLED") <= 0)
2503 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2505 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2506 obd->obd_recovery_start) <= 0)
2508 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2509 cfs_time_current_sec() >=
2510 obd->obd_recovery_start +
2511 obd->obd_recovery_timeout ? 0 :
2512 obd->obd_recovery_start +
2513 obd->obd_recovery_timeout -
2514 cfs_time_current_sec()) <= 0)
2516 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2517 cfs_atomic_read(&obd->obd_connected_clients),
2518 obd->obd_max_recoverable_clients) <= 0)
2520 /* Number of clients that have completed recovery */
2521 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2522 cfs_atomic_read(&obd->obd_req_replay_clients))
2525 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2526 cfs_atomic_read(&obd->obd_lock_replay_clients))
2529 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2530 cfs_atomic_read(&obd->obd_connected_clients) -
2531 cfs_atomic_read(&obd->obd_lock_replay_clients))
2534 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2535 obd->obd_stale_clients) <= 0)
2537 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2538 obd->obd_replayed_requests) <= 0)
2540 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2541 obd->obd_requests_queued_for_recovery) <= 0)
2544 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2545 obd->obd_next_recovery_transno) <= 0)
2551 return min(count, len - (int)off);
2553 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2555 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
2556 int count, int *eof, void *data)
2558 struct obd_device *obd = (struct obd_device *)data;
2559 LASSERT(obd != NULL);
2561 return snprintf(page, count, "%d\n",
2562 obd->obd_recovery_ir_factor);
2564 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
2566 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
2567 unsigned long count, void *data)
2569 struct obd_device *obd = (struct obd_device *)data;
2571 LASSERT(obd != NULL);
2573 rc = lprocfs_write_helper(buffer, count, &val);
2577 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
2580 obd->obd_recovery_ir_factor = val;
2583 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
2585 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
2586 int count, int *eof, void *data)
2588 struct obd_device *obd = (struct obd_device *)data;
2589 LASSERT(obd != NULL);
2591 return snprintf(page, count, "%d\n",
2592 obd->obd_recovery_timeout);
2594 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
2596 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
2597 unsigned long count, void *data)
2599 struct obd_device *obd = (struct obd_device *)data;
2601 LASSERT(obd != NULL);
2603 rc = lprocfs_write_helper(buffer, count, &val);
2607 obd->obd_recovery_timeout = val;
2610 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
2612 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
2613 int count, int *eof, void *data)
2615 struct obd_device *obd = data;
2616 LASSERT(obd != NULL);
2618 return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
2620 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
2622 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
2623 unsigned long count, void *data)
2625 struct obd_device *obd = data;
2627 LASSERT(obd != NULL);
2629 rc = lprocfs_write_helper(buffer, count, &val);
2633 obd->obd_recovery_time_hard = val;
2636 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
2638 int lprocfs_obd_rd_mntdev(char *page, char **start, off_t off,
2639 int count, int *eof, void *data)
2641 struct obd_device *obd = (struct obd_device *)data;
2642 struct lustre_mount_info *lmi;
2643 const char *dev_name;
2645 LASSERT(obd != NULL);
2646 lmi = server_get_mount_2(obd->obd_name);
2647 dev_name = get_mntdev_name(lmi->lmi_sb);
2648 LASSERT(dev_name != NULL);
2650 server_put_mount_2(obd->obd_name, lmi->lmi_mnt);
2651 return snprintf(page, count, "%s\n", dev_name);
2653 EXPORT_SYMBOL(lprocfs_obd_rd_mntdev);
2655 int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
2656 int count, int *eof, void *data)
2658 struct obd_device *dev = data;
2659 struct client_obd *cli = &dev->u.cli;
2662 client_obd_list_lock(&cli->cl_loi_list_lock);
2663 rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
2664 client_obd_list_unlock(&cli->cl_loi_list_lock);
2667 EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
2669 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
2670 int count, int *eof, void *data)
2672 struct obd_device *obd = (struct obd_device *)data;
2673 struct obd_device_target *target = &obd->u.obt;
2675 LASSERT(obd != NULL);
2676 LASSERT(target->obt_magic == OBT_MAGIC);
2678 return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
2680 EXPORT_SYMBOL(lprocfs_target_rd_instance);