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;
1590 unsigned long flags = 0;
1592 LASSERT(stats != NULL);
1593 LASSERT(stats->ls_percpu[0] != NULL);
1595 c = &(stats->ls_percpu[0]->lp_cntr[index]);
1597 lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1598 c->lc_config = conf;
1601 c->lc_min = LC_MIN_INIT;
1604 c->lc_units = units;
1605 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1607 EXPORT_SYMBOL(lprocfs_counter_init);
1609 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1611 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1612 LASSERT(coffset < stats->ls_num); \
1613 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1616 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1618 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1619 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1620 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1621 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1622 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1623 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1624 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1625 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1626 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1627 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1628 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1629 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1630 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1631 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1632 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1633 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1634 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1635 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1636 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1637 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1638 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1639 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1640 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1641 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1642 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1643 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1644 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1645 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1646 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1647 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1648 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1649 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1650 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1651 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1652 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1653 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1654 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1655 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1656 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1657 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1658 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1659 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1660 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1661 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
1662 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1663 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1664 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1665 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1666 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1667 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1668 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1669 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1670 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1671 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1672 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1673 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1674 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1675 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1676 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1677 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1678 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1679 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1680 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1681 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1682 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1683 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1684 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1686 EXPORT_SYMBOL(lprocfs_init_ops_stats);
1688 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1690 struct lprocfs_stats *stats;
1691 unsigned int num_stats;
1694 LASSERT(obd->obd_stats == NULL);
1695 LASSERT(obd->obd_proc_entry != NULL);
1696 LASSERT(obd->obd_cntr_base == 0);
1698 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1699 num_private_stats - 1 /* o_owner */;
1700 stats = lprocfs_alloc_stats(num_stats, 0);
1704 lprocfs_init_ops_stats(num_private_stats, stats);
1706 for (i = num_private_stats; i < num_stats; i++) {
1707 /* If this LBUGs, it is likely that an obd
1708 * operation was added to struct obd_ops in
1709 * <obd.h>, and that the corresponding line item
1710 * LPROCFS_OBD_OP_INIT(.., .., opname)
1711 * is missing from the list above. */
1712 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1713 "Missing obd_stat initializer obd_op "
1714 "operation at offset %d.\n", i - num_private_stats);
1716 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1718 lprocfs_free_stats(&stats);
1720 obd->obd_stats = stats;
1721 obd->obd_cntr_base = num_private_stats;
1725 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
1727 void lprocfs_free_obd_stats(struct obd_device *obd)
1730 lprocfs_free_stats(&obd->obd_stats);
1732 EXPORT_SYMBOL(lprocfs_free_obd_stats);
1734 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1736 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1737 LASSERT(coffset < stats->ls_num); \
1738 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1741 void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats)
1743 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1744 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1745 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
1746 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1747 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1748 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1749 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1750 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1751 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1752 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1753 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1754 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1755 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1756 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1757 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1758 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1759 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1760 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1761 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1762 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1763 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1764 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1765 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1766 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1767 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1768 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1769 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1770 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1771 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1772 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1773 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1774 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1776 EXPORT_SYMBOL(lprocfs_init_mps_stats);
1778 int lprocfs_alloc_md_stats(struct obd_device *obd,
1779 unsigned num_private_stats)
1781 struct lprocfs_stats *stats;
1782 unsigned int num_stats;
1785 LASSERT(obd->md_stats == NULL);
1786 LASSERT(obd->obd_proc_entry != NULL);
1787 LASSERT(obd->md_cntr_base == 0);
1789 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1791 stats = lprocfs_alloc_stats(num_stats, 0);
1795 lprocfs_init_mps_stats(num_private_stats, stats);
1797 for (i = num_private_stats; i < num_stats; i++) {
1798 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1799 CERROR("Missing md_stat initializer md_op "
1800 "operation at offset %d. Aborting.\n",
1801 i - num_private_stats);
1805 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1807 lprocfs_free_stats(&stats);
1809 obd->md_stats = stats;
1810 obd->md_cntr_base = num_private_stats;
1814 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
1816 void lprocfs_free_md_stats(struct obd_device *obd)
1818 struct lprocfs_stats *stats = obd->md_stats;
1820 if (stats != NULL) {
1821 obd->md_stats = NULL;
1822 obd->md_cntr_base = 0;
1823 lprocfs_free_stats(&stats);
1826 EXPORT_SYMBOL(lprocfs_free_md_stats);
1828 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1830 lprocfs_counter_init(ldlm_stats,
1831 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1832 0, "ldlm_enqueue", "reqs");
1833 lprocfs_counter_init(ldlm_stats,
1834 LDLM_CONVERT - LDLM_FIRST_OPC,
1835 0, "ldlm_convert", "reqs");
1836 lprocfs_counter_init(ldlm_stats,
1837 LDLM_CANCEL - LDLM_FIRST_OPC,
1838 0, "ldlm_cancel", "reqs");
1839 lprocfs_counter_init(ldlm_stats,
1840 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1841 0, "ldlm_bl_callback", "reqs");
1842 lprocfs_counter_init(ldlm_stats,
1843 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1844 0, "ldlm_cp_callback", "reqs");
1845 lprocfs_counter_init(ldlm_stats,
1846 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1847 0, "ldlm_gl_callback", "reqs");
1849 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
1851 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1852 int *eof, void *data)
1854 struct obd_export *exp = data;
1855 LASSERT(exp != NULL);
1857 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1860 struct exp_uuid_cb_data {
1868 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1869 int count, int *eof, int *len)
1871 cb_data->page = page;
1872 cb_data->count = count;
1877 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1878 cfs_hlist_node_t *hnode, void *cb_data)
1881 struct obd_export *exp = cfs_hash_object(hs, hnode);
1882 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1884 if (exp->exp_nid_stats)
1885 *data->len += snprintf((data->page + *data->len),
1886 data->count, "%s\n",
1887 obd_uuid2str(&exp->exp_client_uuid));
1891 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1892 int *eof, void *data)
1894 struct nid_stat *stats = (struct nid_stat *)data;
1895 struct exp_uuid_cb_data cb_data;
1896 struct obd_device *obd = stats->nid_obd;
1901 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1902 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1903 lprocfs_exp_print_uuid, &cb_data);
1904 return (*cb_data.len);
1907 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1908 cfs_hlist_node_t *hnode, void *cb_data)
1911 struct exp_uuid_cb_data *data = cb_data;
1912 struct obd_export *exp = cfs_hash_object(hs, hnode);
1914 if (exp->exp_lock_hash != NULL) {
1916 *data->len += cfs_hash_debug_header(data->page,
1919 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1926 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1927 int *eof, void *data)
1929 struct nid_stat *stats = (struct nid_stat *)data;
1930 struct exp_uuid_cb_data cb_data;
1931 struct obd_device *obd = stats->nid_obd;
1936 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1938 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1939 lprocfs_exp_print_hash, &cb_data);
1940 return (*cb_data.len);
1943 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1944 int count, int *eof, void *data)
1947 return snprintf(page, count, "%s\n",
1948 "Write into this file to clear all nid stats and "
1949 "stale nid entries");
1951 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1953 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1955 struct nid_stat *stat = obj;
1959 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
1960 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 1) {
1961 /* object has only hash references. */
1962 spin_lock(&stat->nid_obd->obd_nid_lock);
1963 cfs_list_move(&stat->nid_list, data);
1964 spin_unlock(&stat->nid_obd->obd_nid_lock);
1967 /* we has reference to object - only clear data*/
1968 if (stat->nid_stats)
1969 lprocfs_clear_stats(stat->nid_stats);
1971 if (stat->nid_brw_stats) {
1972 for (i = 0; i < BRW_LAST; i++)
1973 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
1978 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1979 unsigned long count, void *data)
1981 struct obd_device *obd = (struct obd_device *)data;
1982 struct nid_stat *client_stat;
1983 CFS_LIST_HEAD(free_list);
1985 cfs_hash_cond_del(obd->obd_nid_stats_hash,
1986 lprocfs_nid_stats_clear_write_cb, &free_list);
1988 while (!cfs_list_empty(&free_list)) {
1989 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
1991 cfs_list_del_init(&client_stat->nid_list);
1992 lprocfs_free_client_stats(client_stat);
1997 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1999 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
2001 struct nid_stat *new_stat, *old_stat;
2002 struct obd_device *obd = NULL;
2003 cfs_proc_dir_entry_t *entry;
2004 char *buffer = NULL;
2010 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
2011 !exp->exp_obd->obd_nid_stats_hash)
2014 /* not test against zero because eric say:
2015 * You may only test nid against another nid, or LNET_NID_ANY.
2016 * Anything else is nonsense.*/
2017 if (!nid || *nid == LNET_NID_ANY)
2022 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
2024 OBD_ALLOC_PTR(new_stat);
2025 if (new_stat == NULL)
2028 new_stat->nid = *nid;
2029 new_stat->nid_obd = exp->exp_obd;
2030 /* we need set default refcount to 1 to balance obd_disconnect */
2031 cfs_atomic_set(&new_stat->nid_exp_ref_count, 1);
2033 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
2034 nid, &new_stat->nid_hash);
2035 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
2036 old_stat, libcfs_nid2str(*nid),
2037 cfs_atomic_read(&new_stat->nid_exp_ref_count));
2039 /* We need to release old stats because lprocfs_exp_cleanup() hasn't
2040 * been and will never be called. */
2041 if (exp->exp_nid_stats) {
2042 nidstat_putref(exp->exp_nid_stats);
2043 exp->exp_nid_stats = NULL;
2046 /* Return -EALREADY here so that we know that the /proc
2047 * entry already has been created */
2048 if (old_stat != new_stat) {
2049 exp->exp_nid_stats = old_stat;
2050 GOTO(destroy_new, rc = -EALREADY);
2052 /* not found - create */
2053 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
2055 GOTO(destroy_new, rc = -ENOMEM);
2057 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
2058 new_stat->nid_proc = lprocfs_register(buffer,
2059 obd->obd_proc_exports_entry,
2061 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
2063 if (new_stat->nid_proc == NULL) {
2064 CERROR("Error making export directory for nid %s\n",
2065 libcfs_nid2str(*nid));
2066 GOTO(destroy_new_ns, rc = -ENOMEM);
2069 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
2070 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
2071 if (IS_ERR(entry)) {
2072 CWARN("Error adding the NID stats file\n");
2073 rc = PTR_ERR(entry);
2074 GOTO(destroy_new_ns, rc);
2077 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
2078 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
2079 if (IS_ERR(entry)) {
2080 CWARN("Error adding the hash file\n");
2081 rc = PTR_ERR(entry);
2082 GOTO(destroy_new_ns, rc);
2085 exp->exp_nid_stats = new_stat;
2087 /* protect competitive add to list, not need locking on destroy */
2088 spin_lock(&obd->obd_nid_lock);
2089 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
2090 spin_unlock(&obd->obd_nid_lock);
2095 if (new_stat->nid_proc != NULL)
2096 lprocfs_remove(&new_stat->nid_proc);
2097 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
2100 nidstat_putref(new_stat);
2101 OBD_FREE_PTR(new_stat);
2104 EXPORT_SYMBOL(lprocfs_exp_setup);
2106 int lprocfs_exp_cleanup(struct obd_export *exp)
2108 struct nid_stat *stat = exp->exp_nid_stats;
2110 if(!stat || !exp->exp_obd)
2113 nidstat_putref(exp->exp_nid_stats);
2114 exp->exp_nid_stats = NULL;
2118 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2120 int lprocfs_write_helper(const char *buffer, unsigned long count,
2123 return lprocfs_write_frac_helper(buffer, count, val, 1);
2125 EXPORT_SYMBOL(lprocfs_write_helper);
2127 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
2130 char kernbuf[20], *end, *pbuf;
2132 if (count > (sizeof(kernbuf) - 1))
2135 if (cfs_copy_from_user(kernbuf, buffer, count))
2138 kernbuf[count] = '\0';
2145 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2149 if (end != NULL && *end == '.') {
2150 int temp_val, pow = 1;
2154 if (strlen(pbuf) > 5)
2155 pbuf[5] = '\0'; /*only allow 5bits fractional*/
2157 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2160 for (i = 0; i < (end - pbuf); i++)
2163 *val += temp_val / pow;
2168 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2170 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
2173 long decimal_val, frac_val;
2179 decimal_val = val / mult;
2180 prtn = snprintf(buffer, count, "%ld", decimal_val);
2181 frac_val = val % mult;
2183 if (prtn < (count - 4) && frac_val > 0) {
2185 int i, temp_mult = 1, frac_bits = 0;
2187 temp_frac = frac_val * 10;
2188 buffer[prtn++] = '.';
2189 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
2190 /* only reserved 2 bits fraction */
2191 buffer[prtn++] ='0';
2196 * Need to think these cases :
2197 * 1. #echo x.00 > /proc/xxx output result : x
2198 * 2. #echo x.0x > /proc/xxx output result : x.0x
2199 * 3. #echo x.x0 > /proc/xxx output result : x.x
2200 * 4. #echo x.xx > /proc/xxx output result : x.xx
2201 * Only reserved 2 bits fraction.
2203 for (i = 0; i < (5 - prtn); i++)
2206 frac_bits = min((int)count - prtn, 3 - frac_bits);
2207 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
2208 frac_val * temp_mult / mult);
2211 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
2213 if (buffer[prtn] == '.') {
2220 buffer[prtn++] ='\n';
2223 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2225 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
2227 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
2229 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2231 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
2232 __u64 *val, int mult)
2234 char kernbuf[22], *end, *pbuf;
2235 __u64 whole, frac = 0, units;
2236 unsigned frac_d = 1;
2238 if (count > (sizeof(kernbuf) - 1))
2241 if (cfs_copy_from_user(kernbuf, buffer, count))
2244 kernbuf[count] = '\0';
2251 whole = simple_strtoull(pbuf, &end, 10);
2255 if (end != NULL && *end == '.') {
2259 /* need to limit frac_d to a __u32 */
2260 if (strlen(pbuf) > 10)
2263 frac = simple_strtoull(pbuf, &end, 10);
2264 /* count decimal places */
2265 for (i = 0; i < (end - pbuf); i++)
2282 /* Specified units override the multiplier */
2284 mult = mult < 0 ? -units : units;
2287 do_div(frac, frac_d);
2288 *val = whole * mult + frac;
2291 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2293 static char *lprocfs_strnstr(const char *s1, const char *s2, size_t len)
2302 if (!memcmp(s1, s2, l2))
2310 * Find the string \a name in the input \a buffer, and return a pointer to the
2311 * value immediately following \a name, reducing \a count appropriately.
2312 * If \a name is not found the original \a buffer is returned.
2314 char *lprocfs_find_named_value(const char *buffer, const char *name,
2315 unsigned long *count)
2318 size_t buflen = *count;
2320 /* there is no strnstr() in rhel5 and ubuntu kernels */
2321 val = lprocfs_strnstr(buffer, name, buflen);
2323 return (char *)buffer;
2325 val += strlen(name); /* skip prefix */
2326 while (val < buffer + buflen && isspace(*val)) /* skip separator */
2330 while (val < buffer + buflen && isalnum(*val)) {
2335 return val - *count;
2337 EXPORT_SYMBOL(lprocfs_find_named_value);
2339 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent,
2342 const struct file_operations *seq_fops,
2345 struct proc_dir_entry *entry;
2348 /* Disallow secretly (un)writable entries. */
2349 LASSERT((seq_fops->write == NULL) == ((mode & 0222) == 0));
2351 LPROCFS_WRITE_ENTRY();
2352 entry = create_proc_entry(name, mode, parent);
2354 entry->proc_fops = seq_fops;
2357 LPROCFS_WRITE_EXIT();
2364 EXPORT_SYMBOL(lprocfs_seq_create);
2366 int lprocfs_obd_seq_create(struct obd_device *dev,
2369 const struct file_operations *seq_fops,
2372 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2373 mode, seq_fops, data));
2375 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2377 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2379 if (value >= OBD_HIST_MAX)
2380 value = OBD_HIST_MAX - 1;
2382 spin_lock(&oh->oh_lock);
2383 oh->oh_buckets[value]++;
2384 spin_unlock(&oh->oh_lock);
2386 EXPORT_SYMBOL(lprocfs_oh_tally);
2388 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2392 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2395 lprocfs_oh_tally(oh, val);
2397 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2399 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2401 unsigned long ret = 0;
2404 for (i = 0; i < OBD_HIST_MAX; i++)
2405 ret += oh->oh_buckets[i];
2408 EXPORT_SYMBOL(lprocfs_oh_sum);
2410 void lprocfs_oh_clear(struct obd_histogram *oh)
2412 spin_lock(&oh->oh_lock);
2413 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2414 spin_unlock(&oh->oh_lock);
2416 EXPORT_SYMBOL(lprocfs_oh_clear);
2418 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2419 int count, int *eof, void *data)
2421 struct obd_device *obd = data;
2427 c += cfs_hash_debug_header(page, count);
2428 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2429 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2430 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2434 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2436 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2437 int count, int *eof, void *data)
2439 struct obd_device *obd = data;
2442 LASSERT(obd != NULL);
2443 LASSERT(count >= 0);
2445 /* Set start of user data returned to
2446 page + off since the user may have
2447 requested to read much smaller than
2448 what we need to read */
2449 *start = page + off;
2451 /* We know we are allocated a page here.
2452 Also we know that this function will
2453 not need to write more than a page
2454 so we can truncate at CFS_PAGE_SIZE. */
2455 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2457 /* Initialize the page */
2458 memset(page, 0, size);
2460 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2462 if (obd->obd_max_recoverable_clients == 0) {
2463 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2469 /* sampled unlocked, but really... */
2470 if (obd->obd_recovering == 0) {
2471 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2473 if (lprocfs_obd_snprintf(&page, size, &len,
2474 "recovery_start: %lu\n",
2475 obd->obd_recovery_start) <= 0)
2477 if (lprocfs_obd_snprintf(&page, size, &len,
2478 "recovery_duration: %lu\n",
2479 obd->obd_recovery_end -
2480 obd->obd_recovery_start) <= 0)
2482 /* Number of clients that have completed recovery */
2483 if (lprocfs_obd_snprintf(&page, size, &len,
2484 "completed_clients: %d/%d\n",
2485 obd->obd_max_recoverable_clients -
2486 obd->obd_stale_clients,
2487 obd->obd_max_recoverable_clients) <= 0)
2489 if (lprocfs_obd_snprintf(&page, size, &len,
2490 "replayed_requests: %d\n",
2491 obd->obd_replayed_requests) <= 0)
2493 if (lprocfs_obd_snprintf(&page, size, &len,
2494 "last_transno: "LPD64"\n",
2495 obd->obd_next_recovery_transno - 1)<=0)
2497 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2498 obd->obd_version_recov ?
2499 "ENABLED" : "DISABLED") <=0)
2501 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
2503 "DISABLED" : "ENABLED") <= 0)
2508 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2510 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2511 obd->obd_recovery_start) <= 0)
2513 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2514 cfs_time_current_sec() >=
2515 obd->obd_recovery_start +
2516 obd->obd_recovery_timeout ? 0 :
2517 obd->obd_recovery_start +
2518 obd->obd_recovery_timeout -
2519 cfs_time_current_sec()) <= 0)
2521 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2522 cfs_atomic_read(&obd->obd_connected_clients),
2523 obd->obd_max_recoverable_clients) <= 0)
2525 /* Number of clients that have completed recovery */
2526 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2527 cfs_atomic_read(&obd->obd_req_replay_clients))
2530 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2531 cfs_atomic_read(&obd->obd_lock_replay_clients))
2534 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2535 cfs_atomic_read(&obd->obd_connected_clients) -
2536 cfs_atomic_read(&obd->obd_lock_replay_clients))
2539 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2540 obd->obd_stale_clients) <= 0)
2542 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2543 obd->obd_replayed_requests) <= 0)
2545 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2546 obd->obd_requests_queued_for_recovery) <= 0)
2549 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2550 obd->obd_next_recovery_transno) <= 0)
2556 return min(count, len - (int)off);
2558 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2560 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
2561 int count, int *eof, void *data)
2563 struct obd_device *obd = (struct obd_device *)data;
2564 LASSERT(obd != NULL);
2566 return snprintf(page, count, "%d\n",
2567 obd->obd_recovery_ir_factor);
2569 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
2571 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
2572 unsigned long count, void *data)
2574 struct obd_device *obd = (struct obd_device *)data;
2576 LASSERT(obd != NULL);
2578 rc = lprocfs_write_helper(buffer, count, &val);
2582 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
2585 obd->obd_recovery_ir_factor = val;
2588 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
2590 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
2591 int count, int *eof, void *data)
2593 struct obd_device *obd = (struct obd_device *)data;
2594 LASSERT(obd != NULL);
2596 return snprintf(page, count, "%d\n",
2597 obd->obd_recovery_timeout);
2599 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
2601 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
2602 unsigned long count, void *data)
2604 struct obd_device *obd = (struct obd_device *)data;
2606 LASSERT(obd != NULL);
2608 rc = lprocfs_write_helper(buffer, count, &val);
2612 obd->obd_recovery_timeout = val;
2615 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
2617 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
2618 int count, int *eof, void *data)
2620 struct obd_device *obd = data;
2621 LASSERT(obd != NULL);
2623 return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
2625 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
2627 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
2628 unsigned long count, void *data)
2630 struct obd_device *obd = data;
2632 LASSERT(obd != NULL);
2634 rc = lprocfs_write_helper(buffer, count, &val);
2638 obd->obd_recovery_time_hard = val;
2641 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
2643 int lprocfs_obd_rd_mntdev(char *page, char **start, off_t off,
2644 int count, int *eof, void *data)
2646 struct obd_device *obd = (struct obd_device *)data;
2647 struct lustre_mount_info *lmi;
2648 const char *dev_name;
2650 LASSERT(obd != NULL);
2651 lmi = server_get_mount_2(obd->obd_name);
2652 dev_name = get_mntdev_name(lmi->lmi_sb);
2653 LASSERT(dev_name != NULL);
2655 server_put_mount_2(obd->obd_name, lmi->lmi_mnt);
2656 return snprintf(page, count, "%s\n", dev_name);
2658 EXPORT_SYMBOL(lprocfs_obd_rd_mntdev);
2660 int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
2661 int count, int *eof, void *data)
2663 struct obd_device *dev = data;
2664 struct client_obd *cli = &dev->u.cli;
2667 client_obd_list_lock(&cli->cl_loi_list_lock);
2668 rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
2669 client_obd_list_unlock(&cli->cl_loi_list_lock);
2672 EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
2674 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
2675 int count, int *eof, void *data)
2677 struct obd_device *obd = (struct obd_device *)data;
2678 struct obd_device_target *target = &obd->u.obt;
2680 LASSERT(obd != NULL);
2681 LASSERT(target->obt_magic == OBT_MAGIC);
2683 return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
2685 EXPORT_SYMBOL(lprocfs_target_rd_instance);