4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; If not, see
18 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21 * CA 95054 USA or visit www.sun.com if you need additional information or
27 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Use is subject to license terms.
30 * Copyright (c) 2011, 2012, Intel Corporation.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
36 * lustre/obdclass/lprocfs_status.c
38 * Author: Hariharan Thantry <thantry@users.sourceforge.net>
41 #define DEBUG_SUBSYSTEM S_CLASS
44 # include <liblustre.h>
47 #include <obd_class.h>
48 #include <lprocfs_status.h>
49 #include <lustre_fsfilt.h>
50 #include <lustre_log.h>
51 #include <lustre_disk.h>
52 #include <lustre/lustre_idl.h>
53 #include <dt_object.h>
57 static int lprocfs_no_percpu_stats = 0;
58 CFS_MODULE_PARM(lprocfs_no_percpu_stats, "i", int, 0644,
59 "Do not alloc percpu data for lprocfs stats");
61 #define MAX_STRING_SIZE 128
63 /* for bug 10866, global variable */
64 DECLARE_RWSEM(_lprocfs_lock);
65 EXPORT_SYMBOL(_lprocfs_lock);
67 int lprocfs_single_release(struct inode *inode, struct file *file)
70 return single_release(inode, file);
72 EXPORT_SYMBOL(lprocfs_single_release);
74 int lprocfs_seq_release(struct inode *inode, struct file *file)
77 return seq_release(inode, file);
79 EXPORT_SYMBOL(lprocfs_seq_release);
81 static struct proc_dir_entry *__lprocfs_srch(struct proc_dir_entry *head,
84 struct proc_dir_entry *temp;
90 while (temp != NULL) {
91 if (strcmp(temp->name, name) == 0) {
100 struct proc_dir_entry *lprocfs_srch(struct proc_dir_entry *head,
103 struct proc_dir_entry *temp;
105 LPROCFS_SRCH_ENTRY();
106 temp = __lprocfs_srch(head, name);
110 EXPORT_SYMBOL(lprocfs_srch);
112 /* lprocfs API calls */
114 /* Function that emulates snprintf but also has the side effect of advancing
115 the page pointer for the next write into the buffer, incrementing the total
116 length written to the buffer, and decrementing the size left in the
118 static int lprocfs_obd_snprintf(char **page, int end, int *len,
119 const char *format, ...)
127 va_start(list, format);
128 n = vsnprintf(*page, end - *len, format, list);
131 *page += n; *len += n;
135 cfs_proc_dir_entry_t *lprocfs_add_simple(struct proc_dir_entry *root,
137 read_proc_t *read_proc,
138 write_proc_t *write_proc,
140 struct file_operations *fops)
142 cfs_proc_dir_entry_t *proc;
145 if (root == NULL || name == NULL)
146 return ERR_PTR(-EINVAL);
153 LPROCFS_WRITE_ENTRY();
154 proc = create_proc_entry(name, mode, root);
156 CERROR("LprocFS: No memory to create /proc entry %s", name);
157 LPROCFS_WRITE_EXIT();
158 return ERR_PTR(-ENOMEM);
160 proc->read_proc = read_proc;
161 proc->write_proc = write_proc;
164 proc->proc_fops = fops;
165 LPROCFS_WRITE_EXIT();
168 EXPORT_SYMBOL(lprocfs_add_simple);
170 struct proc_dir_entry *lprocfs_add_symlink(const char *name,
171 struct proc_dir_entry *parent, const char *format, ...)
173 struct proc_dir_entry *entry;
177 if (parent == NULL || format == NULL)
180 OBD_ALLOC_WAIT(dest, MAX_STRING_SIZE + 1);
184 va_start(ap, format);
185 vsnprintf(dest, MAX_STRING_SIZE, format, ap);
188 entry = proc_symlink(name, parent, dest);
190 CERROR("LprocFS: Could not create symbolic link from %s to %s",
193 OBD_FREE(dest, MAX_STRING_SIZE + 1);
196 EXPORT_SYMBOL(lprocfs_add_symlink);
198 static ssize_t lprocfs_fops_read(struct file *f, char __user *buf,
199 size_t size, loff_t *ppos)
201 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
202 char *page, *start = NULL;
203 int rc = 0, eof = 1, count;
205 if (*ppos >= CFS_PAGE_SIZE)
208 page = (char *)__get_free_page(GFP_KERNEL);
212 if (LPROCFS_ENTRY_AND_CHECK(dp)) {
217 OBD_FAIL_TIMEOUT(OBD_FAIL_LPROC_REMOVE, 10);
219 rc = dp->read_proc(page, &start, *ppos, CFS_PAGE_SIZE,
225 /* for lustre proc read, the read count must be less than PAGE_SIZE */
234 start = page + *ppos;
235 } else if (start < page) {
239 count = (rc < size) ? rc : size;
240 if (cfs_copy_to_user(buf, start, count)) {
247 free_page((unsigned long)page);
251 static ssize_t lprocfs_fops_write(struct file *f, const char __user *buf,
252 size_t size, loff_t *ppos)
254 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
257 if (LPROCFS_ENTRY_AND_CHECK(dp))
260 rc = dp->write_proc(f, buf, size, dp->data);
265 static struct file_operations lprocfs_generic_fops = {
266 .owner = THIS_MODULE,
267 .read = lprocfs_fops_read,
268 .write = lprocfs_fops_write,
271 int lprocfs_evict_client_open(struct inode *inode, struct file *f)
273 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
274 struct obd_device *obd = dp->data;
276 cfs_atomic_inc(&obd->obd_evict_inprogress);
281 int lprocfs_evict_client_release(struct inode *inode, struct file *f)
283 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
284 struct obd_device *obd = dp->data;
286 cfs_atomic_dec(&obd->obd_evict_inprogress);
287 cfs_waitq_signal(&obd->obd_evict_inprogress_waitq);
292 struct file_operations lprocfs_evict_client_fops = {
293 .owner = THIS_MODULE,
294 .read = lprocfs_fops_read,
295 .write = lprocfs_fops_write,
296 .open = lprocfs_evict_client_open,
297 .release = lprocfs_evict_client_release,
299 EXPORT_SYMBOL(lprocfs_evict_client_fops);
304 * \param root [in] The parent proc entry on which new entry will be added.
305 * \param list [in] Array of proc entries to be added.
306 * \param data [in] The argument to be passed when entries read/write routines
307 * are called through /proc file.
309 * \retval 0 on success
312 int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list,
317 if (root == NULL || list == NULL)
320 LPROCFS_WRITE_ENTRY();
321 while (list->name != NULL) {
322 struct proc_dir_entry *cur_root, *proc;
323 char *pathcopy, *cur, *next, pathbuf[64];
324 int pathsize = strlen(list->name) + 1;
329 /* need copy of path for strsep */
330 if (strlen(list->name) > sizeof(pathbuf) - 1) {
331 OBD_ALLOC(pathcopy, pathsize);
332 if (pathcopy == NULL)
333 GOTO(out, rc = -ENOMEM);
339 strcpy(pathcopy, list->name);
341 while (cur_root != NULL && (cur = strsep(&next, "/"))) {
342 if (*cur =='\0') /* skip double/trailing "/" */
345 proc = __lprocfs_srch(cur_root, cur);
346 CDEBUG(D_OTHER, "cur_root=%s, cur=%s, next=%s, (%s)\n",
347 cur_root->name, cur, next,
348 (proc ? "exists" : "new"));
350 cur_root = (proc ? proc :
351 proc_mkdir(cur, cur_root));
352 } else if (proc == NULL) {
354 if (list->proc_mode != 0000) {
355 mode = list->proc_mode;
359 if (list->write_fptr)
362 proc = create_proc_entry(cur, mode, cur_root);
366 if (pathcopy != pathbuf)
367 OBD_FREE(pathcopy, pathsize);
369 if (cur_root == NULL || proc == NULL) {
370 CERROR("LprocFS: No memory to create /proc entry %s",
372 GOTO(out, rc = -ENOMEM);
376 proc->proc_fops = list->fops;
378 proc->proc_fops = &lprocfs_generic_fops;
379 proc->read_proc = list->read_fptr;
380 proc->write_proc = list->write_fptr;
381 proc->data = (list->data ? list->data : data);
385 LPROCFS_WRITE_EXIT();
388 EXPORT_SYMBOL(lprocfs_add_vars);
390 void lprocfs_remove_nolock(struct proc_dir_entry **rooth)
392 struct proc_dir_entry *root = *rooth;
393 struct proc_dir_entry *temp = root;
394 struct proc_dir_entry *rm_entry;
395 struct proc_dir_entry *parent;
401 parent = root->parent;
402 LASSERT(parent != NULL);
405 while (temp->subdir != NULL)
411 /* Memory corruption once caused this to fail, and
412 without this LASSERT we would loop here forever. */
413 LASSERTF(strlen(rm_entry->name) == rm_entry->namelen,
414 "0x%p %s/%s len %d\n", rm_entry, temp->name,
415 rm_entry->name, (int)strlen(rm_entry->name));
417 remove_proc_entry(rm_entry->name, temp);
423 void lprocfs_remove(struct proc_dir_entry **rooth)
425 LPROCFS_WRITE_ENTRY(); /* search vs remove race */
426 lprocfs_remove_nolock(rooth);
427 LPROCFS_WRITE_EXIT();
429 EXPORT_SYMBOL(lprocfs_remove);
431 void lprocfs_remove_proc_entry(const char *name, struct proc_dir_entry *parent)
433 LASSERT(parent != NULL);
434 remove_proc_entry(name, parent);
436 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
438 void lprocfs_try_remove_proc_entry(const char *name,
439 struct proc_dir_entry *parent)
441 struct proc_dir_entry *t = NULL;
442 struct proc_dir_entry **p;
445 LASSERT(parent != NULL);
448 LPROCFS_WRITE_ENTRY();
450 /* lookup target name */
451 for (p = &parent->subdir; *p; p = &(*p)->next) {
452 if ((*p)->namelen != len)
454 if (memcmp(name, (*p)->name, len))
461 /* verify it's empty: do not count "num_refs" */
462 for (p = &t->subdir; *p; p = &(*p)->next) {
463 if ((*p)->namelen != strlen("num_refs")) {
467 if (memcmp("num_refs", (*p)->name,
468 strlen("num_refs"))) {
476 lprocfs_remove_nolock(&t);
478 LPROCFS_WRITE_EXIT();
482 EXPORT_SYMBOL(lprocfs_try_remove_proc_entry);
484 struct proc_dir_entry *lprocfs_register(const char *name,
485 struct proc_dir_entry *parent,
486 struct lprocfs_vars *list, void *data)
488 struct proc_dir_entry *newchild;
490 newchild = lprocfs_srch(parent, name);
491 if (newchild != NULL) {
492 CERROR(" Lproc: Attempting to register %s more than once \n",
494 return ERR_PTR(-EALREADY);
497 newchild = proc_mkdir(name, parent);
498 if (newchild != NULL && list != NULL) {
499 int rc = lprocfs_add_vars(newchild, list, data);
501 lprocfs_remove(&newchild);
507 EXPORT_SYMBOL(lprocfs_register);
509 /* Generic callbacks */
510 int lprocfs_rd_uint(char *page, char **start, off_t off,
511 int count, int *eof, void *data)
513 unsigned int *temp = data;
514 return snprintf(page, count, "%u\n", *temp);
516 EXPORT_SYMBOL(lprocfs_rd_uint);
518 int lprocfs_wr_uint(struct file *file, const char *buffer,
519 unsigned long count, void *data)
522 char dummy[MAX_STRING_SIZE + 1], *end;
525 dummy[MAX_STRING_SIZE] = '\0';
526 if (cfs_copy_from_user(dummy, buffer, MAX_STRING_SIZE))
529 tmp = simple_strtoul(dummy, &end, 0);
533 *p = (unsigned int)tmp;
536 EXPORT_SYMBOL(lprocfs_wr_uint);
538 int lprocfs_rd_u64(char *page, char **start, off_t off,
539 int count, int *eof, void *data)
541 LASSERT(data != NULL);
543 return snprintf(page, count, LPU64"\n", *(__u64 *)data);
545 EXPORT_SYMBOL(lprocfs_rd_u64);
547 int lprocfs_rd_atomic(char *page, char **start, off_t off,
548 int count, int *eof, void *data)
550 cfs_atomic_t *atom = data;
551 LASSERT(atom != NULL);
553 return snprintf(page, count, "%d\n", cfs_atomic_read(atom));
555 EXPORT_SYMBOL(lprocfs_rd_atomic);
557 int lprocfs_wr_atomic(struct file *file, const char *buffer,
558 unsigned long count, void *data)
560 cfs_atomic_t *atm = data;
564 rc = lprocfs_write_helper(buffer, count, &val);
571 cfs_atomic_set(atm, val);
574 EXPORT_SYMBOL(lprocfs_wr_atomic);
576 int lprocfs_rd_uuid(char *page, char **start, off_t off, int count,
577 int *eof, void *data)
579 struct obd_device *obd = data;
581 LASSERT(obd != NULL);
583 return snprintf(page, count, "%s\n", obd->obd_uuid.uuid);
585 EXPORT_SYMBOL(lprocfs_rd_uuid);
587 int lprocfs_rd_name(char *page, char **start, off_t off, int count,
588 int *eof, void *data)
590 struct obd_device *dev = data;
592 LASSERT(dev != NULL);
593 LASSERT(dev->obd_name != NULL);
595 return snprintf(page, count, "%s\n", dev->obd_name);
597 EXPORT_SYMBOL(lprocfs_rd_name);
599 int lprocfs_rd_blksize(char *page, char **start, off_t off, int count,
600 int *eof, void *data)
602 struct obd_device *obd = data;
603 struct obd_statfs osfs;
604 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
605 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
609 rc = snprintf(page, count, "%u\n", osfs.os_bsize);
613 EXPORT_SYMBOL(lprocfs_rd_blksize);
615 int lprocfs_osd_rd_blksize(char *page, char **start, off_t off,
616 int count, int *eof, void *data)
618 struct dt_device *dt = data;
619 struct obd_statfs osfs;
620 int rc = dt_statfs(NULL, dt, &osfs);
623 rc = snprintf(page, count, "%d\n",
624 (unsigned) osfs.os_bsize);
628 EXPORT_SYMBOL(lprocfs_osd_rd_blksize);
630 int lprocfs_rd_kbytestotal(char *page, char **start, off_t off, int count,
631 int *eof, void *data)
633 struct obd_device *obd = data;
634 struct obd_statfs osfs;
635 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
636 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
639 __u32 blk_size = osfs.os_bsize >> 10;
640 __u64 result = osfs.os_blocks;
642 while (blk_size >>= 1)
646 rc = snprintf(page, count, LPU64"\n", result);
650 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
652 int lprocfs_osd_rd_kbytestotal(char *page, char **start, off_t off,
653 int count, int *eof, void *data)
655 struct dt_device *dt = data;
656 struct obd_statfs osfs;
657 int rc = dt_statfs(NULL, dt, &osfs);
659 __u32 blk_size = osfs.os_bsize >> 10;
660 __u64 result = osfs.os_blocks;
662 while (blk_size >>= 1)
666 rc = snprintf(page, count, LPU64"\n", result);
670 EXPORT_SYMBOL(lprocfs_osd_rd_kbytestotal);
672 int lprocfs_rd_kbytesfree(char *page, char **start, off_t off, int count,
673 int *eof, void *data)
675 struct obd_device *obd = data;
676 struct obd_statfs osfs;
677 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
678 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
681 __u32 blk_size = osfs.os_bsize >> 10;
682 __u64 result = osfs.os_bfree;
684 while (blk_size >>= 1)
688 rc = snprintf(page, count, LPU64"\n", result);
692 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
694 int lprocfs_osd_rd_kbytesfree(char *page, char **start, off_t off,
695 int count, int *eof, void *data)
697 struct dt_device *dt = data;
698 struct obd_statfs osfs;
699 int rc = dt_statfs(NULL, dt, &osfs);
701 __u32 blk_size = osfs.os_bsize >> 10;
702 __u64 result = osfs.os_bfree;
704 while (blk_size >>= 1)
708 rc = snprintf(page, count, LPU64"\n", result);
712 EXPORT_SYMBOL(lprocfs_osd_rd_kbytesfree);
714 int lprocfs_rd_kbytesavail(char *page, char **start, off_t off, int count,
715 int *eof, void *data)
717 struct obd_device *obd = data;
718 struct obd_statfs osfs;
719 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
720 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
723 __u32 blk_size = osfs.os_bsize >> 10;
724 __u64 result = osfs.os_bavail;
726 while (blk_size >>= 1)
730 rc = snprintf(page, count, LPU64"\n", result);
734 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
736 int lprocfs_osd_rd_kbytesavail(char *page, char **start, off_t off,
737 int count, int *eof, void *data)
739 struct dt_device *dt = data;
740 struct obd_statfs osfs;
741 int rc = dt_statfs(NULL, dt, &osfs);
743 __u32 blk_size = osfs.os_bsize >> 10;
744 __u64 result = osfs.os_bavail;
746 while (blk_size >>= 1)
750 rc = snprintf(page, count, LPU64"\n", result);
754 EXPORT_SYMBOL(lprocfs_osd_rd_kbytesavail);
756 int lprocfs_rd_filestotal(char *page, char **start, off_t off, int count,
757 int *eof, void *data)
759 struct obd_device *obd = data;
760 struct obd_statfs osfs;
761 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
762 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
766 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
771 EXPORT_SYMBOL(lprocfs_rd_filestotal);
773 int lprocfs_osd_rd_filestotal(char *page, char **start, off_t off,
774 int count, int *eof, void *data)
776 struct dt_device *dt = data;
777 struct obd_statfs osfs;
778 int rc = dt_statfs(NULL, dt, &osfs);
781 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
786 EXPORT_SYMBOL(lprocfs_osd_rd_filestotal);
788 int lprocfs_rd_filesfree(char *page, char **start, off_t off, int count,
789 int *eof, void *data)
791 struct obd_device *obd = data;
792 struct obd_statfs osfs;
793 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
794 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
798 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
802 EXPORT_SYMBOL(lprocfs_rd_filesfree);
804 int lprocfs_osd_rd_filesfree(char *page, char **start, off_t off,
805 int count, int *eof, void *data)
807 struct dt_device *dt = data;
808 struct obd_statfs osfs;
809 int rc = dt_statfs(NULL, dt, &osfs);
812 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
816 EXPORT_SYMBOL(lprocfs_osd_rd_filesfree);
818 int lprocfs_rd_server_uuid(char *page, char **start, off_t off, int count,
819 int *eof, void *data)
821 struct obd_device *obd = data;
822 struct obd_import *imp;
823 char *imp_state_name = NULL;
826 LASSERT(obd != NULL);
827 LPROCFS_CLIMP_CHECK(obd);
828 imp = obd->u.cli.cl_import;
829 imp_state_name = ptlrpc_import_state_name(imp->imp_state);
831 rc = snprintf(page, count, "%s\t%s%s\n",
832 obd2cli_tgt(obd), imp_state_name,
833 imp->imp_deactive ? "\tDEACTIVATED" : "");
835 LPROCFS_CLIMP_EXIT(obd);
838 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
840 int lprocfs_rd_conn_uuid(char *page, char **start, off_t off, int count,
841 int *eof, void *data)
843 struct obd_device *obd = data;
844 struct ptlrpc_connection *conn;
847 LASSERT(obd != NULL);
849 LPROCFS_CLIMP_CHECK(obd);
850 conn = obd->u.cli.cl_import->imp_connection;
852 if (conn && obd->u.cli.cl_import) {
853 rc = snprintf(page, count, "%s\n",
854 conn->c_remote_uuid.uuid);
856 rc = snprintf(page, count, "%s\n", "<none>");
859 LPROCFS_CLIMP_EXIT(obd);
862 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
864 /** add up per-cpu counters */
865 void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
866 struct lprocfs_counter *cnt)
868 unsigned int num_entry;
869 struct lprocfs_counter *percpu_cntr;
870 struct lprocfs_counter_header *cntr_header;
872 unsigned long flags = 0;
874 memset(cnt, 0, sizeof(*cnt));
877 /* set count to 1 to avoid divide-by-zero errs in callers */
882 cnt->lc_min = LC_MIN_INIT;
884 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
886 for (i = 0; i < num_entry; i++) {
887 if (stats->ls_percpu[i] == NULL)
889 cntr_header = &stats->ls_cnt_header[idx];
890 percpu_cntr = lprocfs_stats_counter_get(stats, i, idx);
892 cnt->lc_count += percpu_cntr->lc_count;
893 cnt->lc_sum += percpu_cntr->lc_sum;
894 if (percpu_cntr->lc_min < cnt->lc_min)
895 cnt->lc_min = percpu_cntr->lc_min;
896 if (percpu_cntr->lc_max > cnt->lc_max)
897 cnt->lc_max = percpu_cntr->lc_max;
898 cnt->lc_sumsquare += percpu_cntr->lc_sumsquare;
901 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
903 EXPORT_SYMBOL(lprocfs_stats_collect);
906 * Append a space separated list of current set flags to str.
908 #define flag2str(flag) \
909 if (imp->imp_##flag && max - len > 0) \
910 len += snprintf(str + len, max - len, "%s" #flag, len ? ", " : "");
911 static int obd_import_flags2str(struct obd_import *imp, char *str, int max)
915 if (imp->imp_obd->obd_no_recov)
916 len += snprintf(str, max - len, "no_recov");
920 flag2str(replayable);
926 static const char *obd_connect_names[] = {
940 "join_file(obsolete)",
944 "remote_client_by_force",
953 "mds_mds_connection",
956 "alt_checksum_algorithm",
982 int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
987 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
989 ret += snprintf(page + ret, count - ret, "%s%s",
990 ret ? sep : "", obd_connect_names[i]);
992 if (flags & ~(mask - 1))
993 ret += snprintf(page + ret, count - ret,
994 "%sunknown flags "LPX64,
995 ret ? sep : "", flags & ~(mask - 1));
998 EXPORT_SYMBOL(obd_connect_flags2str);
1000 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
1001 int *eof, void *data)
1003 struct lprocfs_counter ret;
1004 struct lprocfs_counter_header *header;
1005 struct obd_device *obd = (struct obd_device *)data;
1006 struct obd_import *imp;
1007 struct obd_import_conn *conn;
1013 LASSERT(obd != NULL);
1014 LPROCFS_CLIMP_CHECK(obd);
1015 imp = obd->u.cli.cl_import;
1018 i = snprintf(page, count,
1024 " connect_flags: [",
1027 ptlrpc_import_state_name(imp->imp_state),
1028 imp->imp_connect_data.ocd_instance);
1029 i += obd_connect_flags2str(page + i, count - i,
1030 imp->imp_connect_data.ocd_connect_flags,
1032 i += snprintf(page + i, count - i,
1034 " import_flags: [");
1035 i += obd_import_flags2str(imp, page + i, count - i);
1037 i += snprintf(page + i, count - i,
1040 " failover_nids: [");
1041 spin_lock(&imp->imp_lock);
1043 cfs_list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
1044 i += snprintf(page + i, count - i, "%s%s", j ? ", " : "",
1045 libcfs_nid2str(conn->oic_conn->c_peer.nid));
1048 i += snprintf(page + i, count - i,
1050 " current_connection: %s\n"
1051 " connection_attempts: %u\n"
1053 " in-progress_invalidations: %u\n",
1054 imp->imp_connection == NULL ? "<none>" :
1055 libcfs_nid2str(imp->imp_connection->c_peer.nid),
1057 imp->imp_generation,
1058 cfs_atomic_read(&imp->imp_inval_count));
1059 spin_unlock(&imp->imp_lock);
1061 if (obd->obd_svc_stats == NULL)
1064 header = &obd->obd_svc_stats->ls_cnt_header[PTLRPC_REQWAIT_CNTR];
1065 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
1066 if (ret.lc_count != 0) {
1067 /* first argument to do_div MUST be __u64 */
1068 __u64 sum = ret.lc_sum;
1069 do_div(sum, ret.lc_count);
1073 i += snprintf(page + i, count - i,
1076 " unregistering: %u\n"
1078 " avg_waittime: "LPU64" %s\n",
1079 cfs_atomic_read(&imp->imp_inflight),
1080 cfs_atomic_read(&imp->imp_unregistering),
1081 cfs_atomic_read(&imp->imp_timeouts),
1082 ret.lc_sum, header->lc_units);
1085 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
1086 if (imp->imp_at.iat_portal[j] == 0)
1088 k = max_t(unsigned int, k,
1089 at_get(&imp->imp_at.iat_service_estimate[j]));
1091 i += snprintf(page + i, count - i,
1092 " service_estimates:\n"
1093 " services: %u sec\n"
1094 " network: %u sec\n",
1096 at_get(&imp->imp_at.iat_net_latency));
1098 i += snprintf(page + i, count - i,
1100 " last_replay: "LPU64"\n"
1101 " peer_committed: "LPU64"\n"
1102 " last_checked: "LPU64"\n",
1103 imp->imp_last_replay_transno,
1104 imp->imp_peer_committed_transno,
1105 imp->imp_last_transno_checked);
1107 /* avg data rates */
1108 for (rw = 0; rw <= 1; rw++) {
1109 lprocfs_stats_collect(obd->obd_svc_stats,
1110 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
1112 if (ret.lc_sum > 0 && ret.lc_count > 0) {
1113 /* first argument to do_div MUST be __u64 */
1114 __u64 sum = ret.lc_sum;
1115 do_div(sum, ret.lc_count);
1117 i += snprintf(page + i, count - i,
1118 " %s_data_averages:\n"
1119 " bytes_per_rpc: "LPU64"\n",
1120 rw ? "write" : "read",
1123 k = (int)ret.lc_sum;
1124 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
1125 header = &obd->obd_svc_stats->ls_cnt_header[j];
1126 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
1127 if (ret.lc_sum > 0 && ret.lc_count != 0) {
1128 /* first argument to do_div MUST be __u64 */
1129 __u64 sum = ret.lc_sum;
1130 do_div(sum, ret.lc_count);
1132 i += snprintf(page + i, count - i,
1133 " %s_per_rpc: "LPU64"\n",
1134 header->lc_units, ret.lc_sum);
1135 j = (int)ret.lc_sum;
1137 i += snprintf(page + i, count - i,
1138 " MB_per_sec: %u.%.02u\n",
1139 k / j, (100 * k / j) % 100);
1144 LPROCFS_CLIMP_EXIT(obd);
1147 EXPORT_SYMBOL(lprocfs_rd_import);
1149 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
1150 int *eof, void *data)
1152 struct obd_device *obd = (struct obd_device *)data;
1153 struct obd_import *imp;
1156 LASSERT(obd != NULL);
1157 LPROCFS_CLIMP_CHECK(obd);
1158 imp = obd->u.cli.cl_import;
1161 i = snprintf(page, count, "current_state: %s\n",
1162 ptlrpc_import_state_name(imp->imp_state));
1163 i += snprintf(page + i, count - i,
1164 "state_history:\n");
1165 k = imp->imp_state_hist_idx;
1166 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
1167 struct import_state_hist *ish =
1168 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
1169 if (ish->ish_state == 0)
1171 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
1173 ptlrpc_import_state_name(ish->ish_state));
1176 LPROCFS_CLIMP_EXIT(obd);
1179 EXPORT_SYMBOL(lprocfs_rd_state);
1181 int lprocfs_at_hist_helper(char *page, int count, int rc,
1182 struct adaptive_timeout *at)
1185 for (i = 0; i < AT_BINS; i++)
1186 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
1187 rc += snprintf(page + rc, count - rc, "\n");
1190 EXPORT_SYMBOL(lprocfs_at_hist_helper);
1192 /* See also ptlrpc_lprocfs_rd_timeouts */
1193 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
1194 int *eof, void *data)
1196 struct obd_device *obd = (struct obd_device *)data;
1197 struct obd_import *imp;
1198 unsigned int cur, worst;
1203 LASSERT(obd != NULL);
1204 LPROCFS_CLIMP_CHECK(obd);
1205 imp = obd->u.cli.cl_import;
1208 now = cfs_time_current_sec();
1210 /* Some network health info for kicks */
1211 s2dhms(&ts, now - imp->imp_last_reply_time);
1212 rc += snprintf(page + rc, count - rc,
1213 "%-10s : %ld, "DHMS_FMT" ago\n",
1214 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
1216 cur = at_get(&imp->imp_at.iat_net_latency);
1217 worst = imp->imp_at.iat_net_latency.at_worst_ever;
1218 worstt = imp->imp_at.iat_net_latency.at_worst_time;
1219 s2dhms(&ts, now - worstt);
1220 rc += snprintf(page + rc, count - rc,
1221 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
1222 "network", cur, worst, worstt, DHMS_VARS(&ts));
1223 rc = lprocfs_at_hist_helper(page, count, rc,
1224 &imp->imp_at.iat_net_latency);
1226 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
1227 if (imp->imp_at.iat_portal[i] == 0)
1229 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
1230 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
1231 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
1232 s2dhms(&ts, now - worstt);
1233 rc += snprintf(page + rc, count - rc,
1234 "portal %-2d : cur %3u worst %3u (at %ld, "
1235 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
1236 cur, worst, worstt, DHMS_VARS(&ts));
1237 rc = lprocfs_at_hist_helper(page, count, rc,
1238 &imp->imp_at.iat_service_estimate[i]);
1241 LPROCFS_CLIMP_EXIT(obd);
1244 EXPORT_SYMBOL(lprocfs_rd_timeouts);
1246 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1247 int count, int *eof, void *data)
1249 struct obd_device *obd = data;
1253 LPROCFS_CLIMP_CHECK(obd);
1254 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1255 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1256 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1257 ret += snprintf(page + ret, count - ret, "\n");
1258 LPROCFS_CLIMP_EXIT(obd);
1261 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1263 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1264 int *eof, void *data)
1266 struct obd_device *obd = data;
1268 LASSERT(obd != NULL);
1270 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1272 EXPORT_SYMBOL(lprocfs_rd_num_exports);
1274 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1275 int *eof, void *data)
1277 struct obd_type *class = (struct obd_type*) data;
1279 LASSERT(class != NULL);
1281 return snprintf(page, count, "%d\n", class->typ_refcnt);
1283 EXPORT_SYMBOL(lprocfs_rd_numrefs);
1285 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1289 LASSERT(obd != NULL);
1290 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1291 LASSERT(obd->obd_type->typ_procroot != NULL);
1293 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1294 obd->obd_type->typ_procroot,
1296 if (IS_ERR(obd->obd_proc_entry)) {
1297 rc = PTR_ERR(obd->obd_proc_entry);
1298 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1299 obd->obd_proc_entry = NULL;
1303 EXPORT_SYMBOL(lprocfs_obd_setup);
1305 int lprocfs_obd_cleanup(struct obd_device *obd)
1309 if (obd->obd_proc_exports_entry) {
1310 /* Should be no exports left */
1311 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1312 lprocfs_remove(&obd->obd_proc_exports_entry);
1313 obd->obd_proc_exports_entry = NULL;
1315 if (obd->obd_proc_entry) {
1316 lprocfs_remove(&obd->obd_proc_entry);
1317 obd->obd_proc_entry = NULL;
1321 EXPORT_SYMBOL(lprocfs_obd_cleanup);
1323 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1325 CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
1326 client_stat->nid_proc, client_stat->nid_stats,
1327 client_stat->nid_brw_stats);
1329 LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
1330 "nid %s:count %d\n", libcfs_nid2str(client_stat->nid),
1331 atomic_read(&client_stat->nid_exp_ref_count));
1333 if (client_stat->nid_proc)
1334 lprocfs_remove(&client_stat->nid_proc);
1336 if (client_stat->nid_stats)
1337 lprocfs_free_stats(&client_stat->nid_stats);
1339 if (client_stat->nid_brw_stats)
1340 OBD_FREE_PTR(client_stat->nid_brw_stats);
1342 if (client_stat->nid_ldlm_stats)
1343 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1345 OBD_FREE_PTR(client_stat);
1350 void lprocfs_free_per_client_stats(struct obd_device *obd)
1352 cfs_hash_t *hash = obd->obd_nid_stats_hash;
1353 struct nid_stat *stat;
1356 /* we need extra list - because hash_exit called to early */
1357 /* not need locking because all clients is died */
1358 while (!cfs_list_empty(&obd->obd_nid_stats)) {
1359 stat = cfs_list_entry(obd->obd_nid_stats.next,
1360 struct nid_stat, nid_list);
1361 cfs_list_del_init(&stat->nid_list);
1362 cfs_hash_del(hash, &stat->nid, &stat->nid_hash);
1363 lprocfs_free_client_stats(stat);
1367 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
1369 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1370 enum lprocfs_stats_flags flags)
1372 struct lprocfs_stats *stats;
1373 unsigned int num_entry;
1374 unsigned int percpusize = 0;
1380 if (lprocfs_no_percpu_stats != 0)
1381 flags |= LPROCFS_STATS_FLAG_NOPERCPU;
1383 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1386 num_entry = cfs_num_possible_cpus();
1388 /* alloc percpu pointers for all possible cpu slots */
1389 LIBCFS_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1393 stats->ls_num = num;
1394 stats->ls_flags = flags;
1395 spin_lock_init(&stats->ls_lock);
1397 /* alloc num of counter headers */
1398 LIBCFS_ALLOC(stats->ls_cnt_header,
1399 stats->ls_num * sizeof(struct lprocfs_counter_header));
1400 if (stats->ls_cnt_header == NULL)
1403 if ((flags & LPROCFS_STATS_FLAG_NOPERCPU) != 0) {
1404 /* contains only one set counters */
1405 percpusize = lprocfs_stats_counter_size(stats);
1406 LIBCFS_ALLOC_ATOMIC(stats->ls_percpu[0], percpusize);
1407 if (stats->ls_percpu[0] == NULL)
1409 stats->ls_biggest_alloc_num = 1;
1410 } else if ((flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0) {
1411 /* alloc all percpu data, currently only obd_memory use this */
1412 for (i = 0; i < num_entry; ++i)
1413 if (lprocfs_stats_alloc_one(stats, i) < 0)
1420 lprocfs_free_stats(&stats);
1423 EXPORT_SYMBOL(lprocfs_alloc_stats);
1425 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1427 struct lprocfs_stats *stats = *statsh;
1428 unsigned int num_entry;
1429 unsigned int percpusize;
1432 if (stats == NULL || stats->ls_num == 0)
1436 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1439 num_entry = cfs_num_possible_cpus();
1441 percpusize = lprocfs_stats_counter_size(stats);
1442 for (i = 0; i < num_entry; i++)
1443 if (stats->ls_percpu[i] != NULL)
1444 LIBCFS_FREE(stats->ls_percpu[i], percpusize);
1445 if (stats->ls_cnt_header != NULL)
1446 LIBCFS_FREE(stats->ls_cnt_header, stats->ls_num *
1447 sizeof(struct lprocfs_counter_header));
1448 LIBCFS_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1450 EXPORT_SYMBOL(lprocfs_free_stats);
1452 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1454 struct lprocfs_counter *percpu_cntr;
1455 struct lprocfs_counter_header *header;
1458 unsigned int num_entry;
1459 unsigned long flags = 0;
1461 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1463 for (i = 0; i < num_entry; i++) {
1464 if (stats->ls_percpu[i] == NULL)
1466 for (j = 0; j < stats->ls_num; j++) {
1467 header = &stats->ls_cnt_header[j];
1468 percpu_cntr = lprocfs_stats_counter_get(stats, i, j);
1469 percpu_cntr->lc_count = 0;
1470 percpu_cntr->lc_min = LC_MIN_INIT;
1471 percpu_cntr->lc_max = 0;
1472 percpu_cntr->lc_sumsquare = 0;
1473 percpu_cntr->lc_sum = 0;
1474 if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
1475 percpu_cntr->lc_sum_irq = 0;
1479 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1481 EXPORT_SYMBOL(lprocfs_clear_stats);
1483 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1484 size_t len, loff_t *off)
1486 struct seq_file *seq = file->private_data;
1487 struct lprocfs_stats *stats = seq->private;
1489 lprocfs_clear_stats(stats);
1494 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1496 struct lprocfs_stats *stats = p->private;
1497 /* return 1st cpu location */
1498 return (*pos >= stats->ls_num) ? NULL :
1499 lprocfs_stats_counter_get(stats, 0, *pos);
1502 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1506 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1508 struct lprocfs_stats *stats = p->private;
1510 return (*pos >= stats->ls_num) ? NULL :
1511 lprocfs_stats_counter_get(stats, 0, *pos);
1514 /* seq file export of one lprocfs counter */
1515 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1517 struct lprocfs_stats *stats = p->private;
1518 struct lprocfs_counter *cntr = v;
1519 struct lprocfs_counter ret;
1520 struct lprocfs_counter_header *header;
1525 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
1527 cfs_gettimeofday(&now);
1528 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1529 "snapshot_time", now.tv_sec, now.tv_usec);
1533 entry_size = sizeof(*cntr);
1534 if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
1535 entry_size += sizeof(__s64);
1536 idx = ((void *)cntr - (void *)&(stats->ls_percpu[0])->lp_cntr[0]) /
1539 header = &stats->ls_cnt_header[idx];
1540 lprocfs_stats_collect(stats, idx, &ret);
1542 if (ret.lc_count == 0)
1545 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", header->lc_name,
1546 ret.lc_count, header->lc_units);
1551 if ((header->lc_config & LPROCFS_CNTR_AVGMINMAX) &&
1552 (ret.lc_count > 0)) {
1553 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1554 ret.lc_min, ret.lc_max, ret.lc_sum);
1557 if (header->lc_config & LPROCFS_CNTR_STDDEV)
1558 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1562 rc = seq_printf(p, "\n");
1564 return (rc < 0) ? rc : 0;
1567 struct seq_operations lprocfs_stats_seq_sops = {
1568 start: lprocfs_stats_seq_start,
1569 stop: lprocfs_stats_seq_stop,
1570 next: lprocfs_stats_seq_next,
1571 show: lprocfs_stats_seq_show,
1574 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1576 struct proc_dir_entry *dp = PDE(inode);
1577 struct seq_file *seq;
1580 if (LPROCFS_ENTRY_AND_CHECK(dp))
1583 rc = seq_open(file, &lprocfs_stats_seq_sops);
1588 seq = file->private_data;
1589 seq->private = dp->data;
1593 struct file_operations lprocfs_stats_seq_fops = {
1594 .owner = THIS_MODULE,
1595 .open = lprocfs_stats_seq_open,
1597 .write = lprocfs_stats_seq_write,
1598 .llseek = seq_lseek,
1599 .release = lprocfs_seq_release,
1602 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1603 struct lprocfs_stats *stats)
1605 struct proc_dir_entry *entry;
1606 LASSERT(root != NULL);
1608 LPROCFS_WRITE_ENTRY();
1609 entry = create_proc_entry(name, 0644, root);
1611 entry->proc_fops = &lprocfs_stats_seq_fops;
1612 entry->data = stats;
1615 LPROCFS_WRITE_EXIT();
1622 EXPORT_SYMBOL(lprocfs_register_stats);
1624 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1625 unsigned conf, const char *name, const char *units)
1627 struct lprocfs_counter_header *header;
1628 struct lprocfs_counter *percpu_cntr;
1629 unsigned long flags = 0;
1631 unsigned int num_cpu;
1633 LASSERT(stats != NULL);
1635 header = &stats->ls_cnt_header[index];
1636 LASSERTF(header != NULL, "Failed to allocate stats header:[%d]%s/%s\n",
1637 index, name, units);
1639 header->lc_config = conf;
1640 header->lc_name = name;
1641 header->lc_units = units;
1643 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1644 for (i = 0; i < num_cpu; ++i) {
1645 if (stats->ls_percpu[i] == NULL)
1647 percpu_cntr = lprocfs_stats_counter_get(stats, i, index);
1648 percpu_cntr->lc_count = 0;
1649 percpu_cntr->lc_min = LC_MIN_INIT;
1650 percpu_cntr->lc_max = 0;
1651 percpu_cntr->lc_sumsquare = 0;
1652 percpu_cntr->lc_sum = 0;
1653 if ((stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
1654 percpu_cntr->lc_sum_irq = 0;
1656 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1658 EXPORT_SYMBOL(lprocfs_counter_init);
1660 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1662 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1663 LASSERT(coffset < stats->ls_num); \
1664 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1667 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1669 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1670 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1671 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1672 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1673 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1674 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1675 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1676 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1677 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1678 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1679 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1680 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1681 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1682 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1683 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1684 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1685 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1686 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1687 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1688 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1689 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1690 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1691 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1692 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1693 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1694 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1695 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1696 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1697 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1698 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1699 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1700 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1701 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1702 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1703 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1704 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1705 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1706 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1707 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1708 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1709 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1710 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1711 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1712 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
1713 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1714 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1715 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1716 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1717 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1718 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1719 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1720 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1721 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1722 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1723 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1724 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1725 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1726 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1727 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1728 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1729 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1730 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1731 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1732 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1733 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1734 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1735 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1737 EXPORT_SYMBOL(lprocfs_init_ops_stats);
1739 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1741 struct lprocfs_stats *stats;
1742 unsigned int num_stats;
1745 LASSERT(obd->obd_stats == NULL);
1746 LASSERT(obd->obd_proc_entry != NULL);
1747 LASSERT(obd->obd_cntr_base == 0);
1749 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1750 num_private_stats - 1 /* o_owner */;
1751 stats = lprocfs_alloc_stats(num_stats, 0);
1755 lprocfs_init_ops_stats(num_private_stats, stats);
1757 for (i = num_private_stats; i < num_stats; i++) {
1758 /* If this LBUGs, it is likely that an obd
1759 * operation was added to struct obd_ops in
1760 * <obd.h>, and that the corresponding line item
1761 * LPROCFS_OBD_OP_INIT(.., .., opname)
1762 * is missing from the list above. */
1763 LASSERTF(stats->ls_cnt_header[i].lc_name != NULL,
1764 "Missing obd_stat initializer obd_op "
1765 "operation at offset %d.\n", i - num_private_stats);
1767 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1769 lprocfs_free_stats(&stats);
1771 obd->obd_stats = stats;
1772 obd->obd_cntr_base = num_private_stats;
1776 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
1778 void lprocfs_free_obd_stats(struct obd_device *obd)
1781 lprocfs_free_stats(&obd->obd_stats);
1783 EXPORT_SYMBOL(lprocfs_free_obd_stats);
1785 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1787 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1788 LASSERT(coffset < stats->ls_num); \
1789 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1792 void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats)
1794 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1795 LPROCFS_MD_OP_INIT(num_private_stats, stats, null_inode);
1796 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
1797 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1798 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1799 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1800 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1801 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1802 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1803 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1804 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1805 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1806 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1807 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1808 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1809 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1810 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1811 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1812 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1813 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1814 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1815 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1816 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1817 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1818 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1819 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1820 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1821 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1822 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1823 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1824 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1825 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1827 EXPORT_SYMBOL(lprocfs_init_mps_stats);
1829 int lprocfs_alloc_md_stats(struct obd_device *obd,
1830 unsigned num_private_stats)
1832 struct lprocfs_stats *stats;
1833 unsigned int num_stats;
1836 LASSERT(obd->md_stats == NULL);
1837 LASSERT(obd->obd_proc_entry != NULL);
1838 LASSERT(obd->md_cntr_base == 0);
1840 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1842 stats = lprocfs_alloc_stats(num_stats, 0);
1846 lprocfs_init_mps_stats(num_private_stats, stats);
1848 for (i = num_private_stats; i < num_stats; i++) {
1849 if (stats->ls_cnt_header[i].lc_name == NULL) {
1850 CERROR("Missing md_stat initializer md_op "
1851 "operation at offset %d. Aborting.\n",
1852 i - num_private_stats);
1856 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1858 lprocfs_free_stats(&stats);
1860 obd->md_stats = stats;
1861 obd->md_cntr_base = num_private_stats;
1865 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
1867 void lprocfs_free_md_stats(struct obd_device *obd)
1869 struct lprocfs_stats *stats = obd->md_stats;
1871 if (stats != NULL) {
1872 obd->md_stats = NULL;
1873 obd->md_cntr_base = 0;
1874 lprocfs_free_stats(&stats);
1877 EXPORT_SYMBOL(lprocfs_free_md_stats);
1879 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1881 lprocfs_counter_init(ldlm_stats,
1882 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1883 0, "ldlm_enqueue", "reqs");
1884 lprocfs_counter_init(ldlm_stats,
1885 LDLM_CONVERT - LDLM_FIRST_OPC,
1886 0, "ldlm_convert", "reqs");
1887 lprocfs_counter_init(ldlm_stats,
1888 LDLM_CANCEL - LDLM_FIRST_OPC,
1889 0, "ldlm_cancel", "reqs");
1890 lprocfs_counter_init(ldlm_stats,
1891 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1892 0, "ldlm_bl_callback", "reqs");
1893 lprocfs_counter_init(ldlm_stats,
1894 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1895 0, "ldlm_cp_callback", "reqs");
1896 lprocfs_counter_init(ldlm_stats,
1897 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1898 0, "ldlm_gl_callback", "reqs");
1900 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
1902 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1903 int *eof, void *data)
1905 struct obd_export *exp = data;
1906 LASSERT(exp != NULL);
1908 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1911 struct exp_uuid_cb_data {
1919 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1920 int count, int *eof, int *len)
1922 cb_data->page = page;
1923 cb_data->count = count;
1928 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1929 cfs_hlist_node_t *hnode, void *cb_data)
1932 struct obd_export *exp = cfs_hash_object(hs, hnode);
1933 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1935 if (exp->exp_nid_stats)
1936 *data->len += snprintf((data->page + *data->len),
1937 data->count, "%s\n",
1938 obd_uuid2str(&exp->exp_client_uuid));
1942 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1943 int *eof, void *data)
1945 struct nid_stat *stats = (struct nid_stat *)data;
1946 struct exp_uuid_cb_data cb_data;
1947 struct obd_device *obd = stats->nid_obd;
1952 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1953 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1954 lprocfs_exp_print_uuid, &cb_data);
1955 return (*cb_data.len);
1958 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1959 cfs_hlist_node_t *hnode, void *cb_data)
1962 struct exp_uuid_cb_data *data = cb_data;
1963 struct obd_export *exp = cfs_hash_object(hs, hnode);
1965 if (exp->exp_lock_hash != NULL) {
1967 *data->len += cfs_hash_debug_header(data->page,
1970 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1977 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1978 int *eof, void *data)
1980 struct nid_stat *stats = (struct nid_stat *)data;
1981 struct exp_uuid_cb_data cb_data;
1982 struct obd_device *obd = stats->nid_obd;
1987 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1989 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1990 lprocfs_exp_print_hash, &cb_data);
1991 return (*cb_data.len);
1994 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1995 int count, int *eof, void *data)
1998 return snprintf(page, count, "%s\n",
1999 "Write into this file to clear all nid stats and "
2000 "stale nid entries");
2002 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
2004 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
2006 struct nid_stat *stat = obj;
2010 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
2011 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 1) {
2012 /* object has only hash references. */
2013 spin_lock(&stat->nid_obd->obd_nid_lock);
2014 cfs_list_move(&stat->nid_list, data);
2015 spin_unlock(&stat->nid_obd->obd_nid_lock);
2018 /* we has reference to object - only clear data*/
2019 if (stat->nid_stats)
2020 lprocfs_clear_stats(stat->nid_stats);
2022 if (stat->nid_brw_stats) {
2023 for (i = 0; i < BRW_LAST; i++)
2024 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
2029 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
2030 unsigned long count, void *data)
2032 struct obd_device *obd = (struct obd_device *)data;
2033 struct nid_stat *client_stat;
2034 CFS_LIST_HEAD(free_list);
2036 cfs_hash_cond_del(obd->obd_nid_stats_hash,
2037 lprocfs_nid_stats_clear_write_cb, &free_list);
2039 while (!cfs_list_empty(&free_list)) {
2040 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
2042 cfs_list_del_init(&client_stat->nid_list);
2043 lprocfs_free_client_stats(client_stat);
2048 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
2050 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
2052 struct nid_stat *new_stat, *old_stat;
2053 struct obd_device *obd = NULL;
2054 cfs_proc_dir_entry_t *entry;
2055 char *buffer = NULL;
2061 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
2062 !exp->exp_obd->obd_nid_stats_hash)
2065 /* not test against zero because eric say:
2066 * You may only test nid against another nid, or LNET_NID_ANY.
2067 * Anything else is nonsense.*/
2068 if (!nid || *nid == LNET_NID_ANY)
2073 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
2075 OBD_ALLOC_PTR(new_stat);
2076 if (new_stat == NULL)
2079 new_stat->nid = *nid;
2080 new_stat->nid_obd = exp->exp_obd;
2081 /* we need set default refcount to 1 to balance obd_disconnect */
2082 cfs_atomic_set(&new_stat->nid_exp_ref_count, 1);
2084 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
2085 nid, &new_stat->nid_hash);
2086 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
2087 old_stat, libcfs_nid2str(*nid),
2088 cfs_atomic_read(&new_stat->nid_exp_ref_count));
2090 /* We need to release old stats because lprocfs_exp_cleanup() hasn't
2091 * been and will never be called. */
2092 if (exp->exp_nid_stats) {
2093 nidstat_putref(exp->exp_nid_stats);
2094 exp->exp_nid_stats = NULL;
2097 /* Return -EALREADY here so that we know that the /proc
2098 * entry already has been created */
2099 if (old_stat != new_stat) {
2100 exp->exp_nid_stats = old_stat;
2101 GOTO(destroy_new, rc = -EALREADY);
2103 /* not found - create */
2104 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
2106 GOTO(destroy_new, rc = -ENOMEM);
2108 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
2109 new_stat->nid_proc = lprocfs_register(buffer,
2110 obd->obd_proc_exports_entry,
2112 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
2114 if (new_stat->nid_proc == NULL) {
2115 CERROR("Error making export directory for nid %s\n",
2116 libcfs_nid2str(*nid));
2117 GOTO(destroy_new_ns, rc = -ENOMEM);
2120 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
2121 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
2122 if (IS_ERR(entry)) {
2123 CWARN("Error adding the NID stats file\n");
2124 rc = PTR_ERR(entry);
2125 GOTO(destroy_new_ns, rc);
2128 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
2129 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
2130 if (IS_ERR(entry)) {
2131 CWARN("Error adding the hash file\n");
2132 rc = PTR_ERR(entry);
2133 GOTO(destroy_new_ns, rc);
2136 exp->exp_nid_stats = new_stat;
2138 /* protect competitive add to list, not need locking on destroy */
2139 spin_lock(&obd->obd_nid_lock);
2140 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
2141 spin_unlock(&obd->obd_nid_lock);
2146 if (new_stat->nid_proc != NULL)
2147 lprocfs_remove(&new_stat->nid_proc);
2148 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
2151 nidstat_putref(new_stat);
2152 OBD_FREE_PTR(new_stat);
2155 EXPORT_SYMBOL(lprocfs_exp_setup);
2157 int lprocfs_exp_cleanup(struct obd_export *exp)
2159 struct nid_stat *stat = exp->exp_nid_stats;
2161 if(!stat || !exp->exp_obd)
2164 nidstat_putref(exp->exp_nid_stats);
2165 exp->exp_nid_stats = NULL;
2169 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2171 int lprocfs_write_helper(const char *buffer, unsigned long count,
2174 return lprocfs_write_frac_helper(buffer, count, val, 1);
2176 EXPORT_SYMBOL(lprocfs_write_helper);
2178 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
2181 char kernbuf[20], *end, *pbuf;
2183 if (count > (sizeof(kernbuf) - 1))
2186 if (cfs_copy_from_user(kernbuf, buffer, count))
2189 kernbuf[count] = '\0';
2196 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2200 if (end != NULL && *end == '.') {
2201 int temp_val, pow = 1;
2205 if (strlen(pbuf) > 5)
2206 pbuf[5] = '\0'; /*only allow 5bits fractional*/
2208 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2211 for (i = 0; i < (end - pbuf); i++)
2214 *val += temp_val / pow;
2219 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2221 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
2224 long decimal_val, frac_val;
2230 decimal_val = val / mult;
2231 prtn = snprintf(buffer, count, "%ld", decimal_val);
2232 frac_val = val % mult;
2234 if (prtn < (count - 4) && frac_val > 0) {
2236 int i, temp_mult = 1, frac_bits = 0;
2238 temp_frac = frac_val * 10;
2239 buffer[prtn++] = '.';
2240 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
2241 /* only reserved 2 bits fraction */
2242 buffer[prtn++] ='0';
2247 * Need to think these cases :
2248 * 1. #echo x.00 > /proc/xxx output result : x
2249 * 2. #echo x.0x > /proc/xxx output result : x.0x
2250 * 3. #echo x.x0 > /proc/xxx output result : x.x
2251 * 4. #echo x.xx > /proc/xxx output result : x.xx
2252 * Only reserved 2 bits fraction.
2254 for (i = 0; i < (5 - prtn); i++)
2257 frac_bits = min((int)count - prtn, 3 - frac_bits);
2258 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
2259 frac_val * temp_mult / mult);
2262 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
2264 if (buffer[prtn] == '.') {
2271 buffer[prtn++] ='\n';
2274 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2276 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
2278 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
2280 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2282 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
2283 __u64 *val, int mult)
2285 char kernbuf[22], *end, *pbuf;
2286 __u64 whole, frac = 0, units;
2287 unsigned frac_d = 1;
2289 if (count > (sizeof(kernbuf) - 1))
2292 if (cfs_copy_from_user(kernbuf, buffer, count))
2295 kernbuf[count] = '\0';
2302 whole = simple_strtoull(pbuf, &end, 10);
2306 if (end != NULL && *end == '.') {
2310 /* need to limit frac_d to a __u32 */
2311 if (strlen(pbuf) > 10)
2314 frac = simple_strtoull(pbuf, &end, 10);
2315 /* count decimal places */
2316 for (i = 0; i < (end - pbuf); i++)
2333 /* Specified units override the multiplier */
2335 mult = mult < 0 ? -units : units;
2338 do_div(frac, frac_d);
2339 *val = whole * mult + frac;
2342 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2344 static char *lprocfs_strnstr(const char *s1, const char *s2, size_t len)
2353 if (!memcmp(s1, s2, l2))
2361 * Find the string \a name in the input \a buffer, and return a pointer to the
2362 * value immediately following \a name, reducing \a count appropriately.
2363 * If \a name is not found the original \a buffer is returned.
2365 char *lprocfs_find_named_value(const char *buffer, const char *name,
2366 unsigned long *count)
2369 size_t buflen = *count;
2371 /* there is no strnstr() in rhel5 and ubuntu kernels */
2372 val = lprocfs_strnstr(buffer, name, buflen);
2374 return (char *)buffer;
2376 val += strlen(name); /* skip prefix */
2377 while (val < buffer + buflen && isspace(*val)) /* skip separator */
2381 while (val < buffer + buflen && isalnum(*val)) {
2386 return val - *count;
2388 EXPORT_SYMBOL(lprocfs_find_named_value);
2390 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent,
2393 const struct file_operations *seq_fops,
2396 struct proc_dir_entry *entry;
2399 /* Disallow secretly (un)writable entries. */
2400 LASSERT((seq_fops->write == NULL) == ((mode & 0222) == 0));
2402 LPROCFS_WRITE_ENTRY();
2403 entry = create_proc_entry(name, mode, parent);
2405 entry->proc_fops = seq_fops;
2408 LPROCFS_WRITE_EXIT();
2415 EXPORT_SYMBOL(lprocfs_seq_create);
2417 int lprocfs_obd_seq_create(struct obd_device *dev,
2420 const struct file_operations *seq_fops,
2423 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2424 mode, seq_fops, data));
2426 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2428 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2430 if (value >= OBD_HIST_MAX)
2431 value = OBD_HIST_MAX - 1;
2433 spin_lock(&oh->oh_lock);
2434 oh->oh_buckets[value]++;
2435 spin_unlock(&oh->oh_lock);
2437 EXPORT_SYMBOL(lprocfs_oh_tally);
2439 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2443 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2446 lprocfs_oh_tally(oh, val);
2448 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2450 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2452 unsigned long ret = 0;
2455 for (i = 0; i < OBD_HIST_MAX; i++)
2456 ret += oh->oh_buckets[i];
2459 EXPORT_SYMBOL(lprocfs_oh_sum);
2461 void lprocfs_oh_clear(struct obd_histogram *oh)
2463 spin_lock(&oh->oh_lock);
2464 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2465 spin_unlock(&oh->oh_lock);
2467 EXPORT_SYMBOL(lprocfs_oh_clear);
2469 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2470 int count, int *eof, void *data)
2472 struct obd_device *obd = data;
2478 c += cfs_hash_debug_header(page, count);
2479 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2480 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2481 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2485 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2487 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2488 int count, int *eof, void *data)
2490 struct obd_device *obd = data;
2493 LASSERT(obd != NULL);
2494 LASSERT(count >= 0);
2496 /* Set start of user data returned to
2497 page + off since the user may have
2498 requested to read much smaller than
2499 what we need to read */
2500 *start = page + off;
2502 /* We know we are allocated a page here.
2503 Also we know that this function will
2504 not need to write more than a page
2505 so we can truncate at CFS_PAGE_SIZE. */
2506 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2508 /* Initialize the page */
2509 memset(page, 0, size);
2511 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2513 if (obd->obd_max_recoverable_clients == 0) {
2514 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2520 /* sampled unlocked, but really... */
2521 if (obd->obd_recovering == 0) {
2522 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2524 if (lprocfs_obd_snprintf(&page, size, &len,
2525 "recovery_start: %lu\n",
2526 obd->obd_recovery_start) <= 0)
2528 if (lprocfs_obd_snprintf(&page, size, &len,
2529 "recovery_duration: %lu\n",
2530 obd->obd_recovery_end -
2531 obd->obd_recovery_start) <= 0)
2533 /* Number of clients that have completed recovery */
2534 if (lprocfs_obd_snprintf(&page, size, &len,
2535 "completed_clients: %d/%d\n",
2536 obd->obd_max_recoverable_clients -
2537 obd->obd_stale_clients,
2538 obd->obd_max_recoverable_clients) <= 0)
2540 if (lprocfs_obd_snprintf(&page, size, &len,
2541 "replayed_requests: %d\n",
2542 obd->obd_replayed_requests) <= 0)
2544 if (lprocfs_obd_snprintf(&page, size, &len,
2545 "last_transno: "LPD64"\n",
2546 obd->obd_next_recovery_transno - 1)<=0)
2548 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2549 obd->obd_version_recov ?
2550 "ENABLED" : "DISABLED") <=0)
2552 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
2554 "DISABLED" : "ENABLED") <= 0)
2559 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2561 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2562 obd->obd_recovery_start) <= 0)
2564 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2565 cfs_time_current_sec() >=
2566 obd->obd_recovery_start +
2567 obd->obd_recovery_timeout ? 0 :
2568 obd->obd_recovery_start +
2569 obd->obd_recovery_timeout -
2570 cfs_time_current_sec()) <= 0)
2572 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2573 cfs_atomic_read(&obd->obd_connected_clients),
2574 obd->obd_max_recoverable_clients) <= 0)
2576 /* Number of clients that have completed recovery */
2577 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2578 cfs_atomic_read(&obd->obd_req_replay_clients))
2581 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2582 cfs_atomic_read(&obd->obd_lock_replay_clients))
2585 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2586 cfs_atomic_read(&obd->obd_connected_clients) -
2587 cfs_atomic_read(&obd->obd_lock_replay_clients))
2590 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2591 obd->obd_stale_clients) <= 0)
2593 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2594 obd->obd_replayed_requests) <= 0)
2596 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2597 obd->obd_requests_queued_for_recovery) <= 0)
2600 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2601 obd->obd_next_recovery_transno) <= 0)
2607 return min(count, len - (int)off);
2609 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2611 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
2612 int count, int *eof, void *data)
2614 struct obd_device *obd = (struct obd_device *)data;
2615 LASSERT(obd != NULL);
2617 return snprintf(page, count, "%d\n",
2618 obd->obd_recovery_ir_factor);
2620 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
2622 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
2623 unsigned long count, void *data)
2625 struct obd_device *obd = (struct obd_device *)data;
2627 LASSERT(obd != NULL);
2629 rc = lprocfs_write_helper(buffer, count, &val);
2633 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
2636 obd->obd_recovery_ir_factor = val;
2639 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
2641 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
2642 int count, int *eof, void *data)
2644 struct obd_device *obd = (struct obd_device *)data;
2645 LASSERT(obd != NULL);
2647 return snprintf(page, count, "%d\n",
2648 obd->obd_recovery_timeout);
2650 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
2652 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
2653 unsigned long count, void *data)
2655 struct obd_device *obd = (struct obd_device *)data;
2657 LASSERT(obd != NULL);
2659 rc = lprocfs_write_helper(buffer, count, &val);
2663 obd->obd_recovery_timeout = val;
2666 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
2668 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
2669 int count, int *eof, void *data)
2671 struct obd_device *obd = data;
2672 LASSERT(obd != NULL);
2674 return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
2676 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
2678 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
2679 unsigned long count, void *data)
2681 struct obd_device *obd = data;
2683 LASSERT(obd != NULL);
2685 rc = lprocfs_write_helper(buffer, count, &val);
2689 obd->obd_recovery_time_hard = val;
2692 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
2694 int lprocfs_obd_rd_mntdev(char *page, char **start, off_t off,
2695 int count, int *eof, void *data)
2697 struct obd_device *obd = (struct obd_device *)data;
2698 struct lustre_mount_info *lmi;
2699 const char *dev_name;
2701 LASSERT(obd != NULL);
2702 lmi = server_get_mount_2(obd->obd_name);
2703 dev_name = get_mntdev_name(lmi->lmi_sb);
2704 LASSERT(dev_name != NULL);
2706 server_put_mount_2(obd->obd_name, lmi->lmi_mnt);
2707 return snprintf(page, count, "%s\n", dev_name);
2709 EXPORT_SYMBOL(lprocfs_obd_rd_mntdev);
2711 int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
2712 int count, int *eof, void *data)
2714 struct obd_device *dev = data;
2715 struct client_obd *cli = &dev->u.cli;
2718 client_obd_list_lock(&cli->cl_loi_list_lock);
2719 rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
2720 client_obd_list_unlock(&cli->cl_loi_list_lock);
2723 EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
2725 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
2726 int count, int *eof, void *data)
2728 struct obd_device *obd = (struct obd_device *)data;
2729 struct obd_device_target *target = &obd->u.obt;
2731 LASSERT(obd != NULL);
2732 LASSERT(target->obt_magic == OBT_MAGIC);
2734 return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
2736 EXPORT_SYMBOL(lprocfs_target_rd_instance);