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, Whamcloud, Inc.
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/lustre_idl.h>
52 #include <dt_object.h>
56 static int lprocfs_no_percpu_stats = 0;
57 CFS_MODULE_PARM(lprocfs_no_percpu_stats, "i", int, 0644,
58 "Do not alloc percpu data for lprocfs stats");
60 #define MAX_STRING_SIZE 128
62 /* for bug 10866, global variable */
63 CFS_DECLARE_RWSEM(_lprocfs_lock);
64 EXPORT_SYMBOL(_lprocfs_lock);
66 int lprocfs_single_release(struct inode *inode, struct file *file)
69 return single_release(inode, file);
71 EXPORT_SYMBOL(lprocfs_single_release);
73 int lprocfs_seq_release(struct inode *inode, struct file *file)
76 return seq_release(inode, file);
78 EXPORT_SYMBOL(lprocfs_seq_release);
80 static struct proc_dir_entry *__lprocfs_srch(struct proc_dir_entry *head,
83 struct proc_dir_entry *temp;
89 while (temp != NULL) {
90 if (strcmp(temp->name, name) == 0) {
99 struct proc_dir_entry *lprocfs_srch(struct proc_dir_entry *head,
102 struct proc_dir_entry *temp;
104 LPROCFS_SRCH_ENTRY();
105 temp = __lprocfs_srch(head, name);
109 EXPORT_SYMBOL(lprocfs_srch);
111 /* lprocfs API calls */
113 /* Function that emulates snprintf but also has the side effect of advancing
114 the page pointer for the next write into the buffer, incrementing the total
115 length written to the buffer, and decrementing the size left in the
117 static int lprocfs_obd_snprintf(char **page, int end, int *len,
118 const char *format, ...)
126 va_start(list, format);
127 n = vsnprintf(*page, end - *len, format, list);
130 *page += n; *len += n;
134 cfs_proc_dir_entry_t *lprocfs_add_simple(struct proc_dir_entry *root,
136 read_proc_t *read_proc,
137 write_proc_t *write_proc,
139 struct file_operations *fops)
141 cfs_proc_dir_entry_t *proc;
144 if (root == NULL || name == NULL)
145 return ERR_PTR(-EINVAL);
152 LPROCFS_WRITE_ENTRY();
153 proc = create_proc_entry(name, mode, root);
155 CERROR("LprocFS: No memory to create /proc entry %s", name);
156 LPROCFS_WRITE_EXIT();
157 return ERR_PTR(-ENOMEM);
159 proc->read_proc = read_proc;
160 proc->write_proc = write_proc;
163 proc->proc_fops = fops;
164 LPROCFS_WRITE_EXIT();
167 EXPORT_SYMBOL(lprocfs_add_simple);
169 struct proc_dir_entry *lprocfs_add_symlink(const char *name,
170 struct proc_dir_entry *parent, const char *format, ...)
172 struct proc_dir_entry *entry;
176 if (parent == NULL || format == NULL)
179 OBD_ALLOC_WAIT(dest, MAX_STRING_SIZE + 1);
183 va_start(ap, format);
184 vsnprintf(dest, MAX_STRING_SIZE, format, ap);
187 entry = proc_symlink(name, parent, dest);
189 CERROR("LprocFS: Could not create symbolic link from %s to %s",
192 OBD_FREE(dest, MAX_STRING_SIZE + 1);
195 EXPORT_SYMBOL(lprocfs_add_symlink);
197 static ssize_t lprocfs_fops_read(struct file *f, char __user *buf,
198 size_t size, loff_t *ppos)
200 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
201 char *page, *start = NULL;
202 int rc = 0, eof = 1, count;
204 if (*ppos >= CFS_PAGE_SIZE)
207 page = (char *)__get_free_page(GFP_KERNEL);
211 if (LPROCFS_ENTRY_AND_CHECK(dp)) {
216 OBD_FAIL_TIMEOUT(OBD_FAIL_LPROC_REMOVE, 10);
218 rc = dp->read_proc(page, &start, *ppos, CFS_PAGE_SIZE,
224 /* for lustre proc read, the read count must be less than PAGE_SIZE */
233 start = page + *ppos;
234 } else if (start < page) {
238 count = (rc < size) ? rc : size;
239 if (cfs_copy_to_user(buf, start, count)) {
246 free_page((unsigned long)page);
250 static ssize_t lprocfs_fops_write(struct file *f, const char __user *buf,
251 size_t size, loff_t *ppos)
253 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
256 if (LPROCFS_ENTRY_AND_CHECK(dp))
259 rc = dp->write_proc(f, buf, size, dp->data);
264 static struct file_operations lprocfs_generic_fops = {
265 .owner = THIS_MODULE,
266 .read = lprocfs_fops_read,
267 .write = lprocfs_fops_write,
270 int lprocfs_evict_client_open(struct inode *inode, struct file *f)
272 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
273 struct obd_device *obd = dp->data;
275 cfs_atomic_inc(&obd->obd_evict_inprogress);
280 int lprocfs_evict_client_release(struct inode *inode, struct file *f)
282 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
283 struct obd_device *obd = dp->data;
285 cfs_atomic_dec(&obd->obd_evict_inprogress);
286 cfs_waitq_signal(&obd->obd_evict_inprogress_waitq);
291 struct file_operations lprocfs_evict_client_fops = {
292 .owner = THIS_MODULE,
293 .read = lprocfs_fops_read,
294 .write = lprocfs_fops_write,
295 .open = lprocfs_evict_client_open,
296 .release = lprocfs_evict_client_release,
298 EXPORT_SYMBOL(lprocfs_evict_client_fops);
303 * \param root [in] The parent proc entry on which new entry will be added.
304 * \param list [in] Array of proc entries to be added.
305 * \param data [in] The argument to be passed when entries read/write routines
306 * are called through /proc file.
308 * \retval 0 on success
311 int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list,
316 if (root == NULL || list == NULL)
319 LPROCFS_WRITE_ENTRY();
320 while (list->name != NULL) {
321 struct proc_dir_entry *cur_root, *proc;
322 char *pathcopy, *cur, *next, pathbuf[64];
323 int pathsize = strlen(list->name) + 1;
328 /* need copy of path for strsep */
329 if (strlen(list->name) > sizeof(pathbuf) - 1) {
330 OBD_ALLOC(pathcopy, pathsize);
331 if (pathcopy == NULL)
332 GOTO(out, rc = -ENOMEM);
338 strcpy(pathcopy, list->name);
340 while (cur_root != NULL && (cur = strsep(&next, "/"))) {
341 if (*cur =='\0') /* skip double/trailing "/" */
344 proc = __lprocfs_srch(cur_root, cur);
345 CDEBUG(D_OTHER, "cur_root=%s, cur=%s, next=%s, (%s)\n",
346 cur_root->name, cur, next,
347 (proc ? "exists" : "new"));
349 cur_root = (proc ? proc :
350 proc_mkdir(cur, cur_root));
351 } else if (proc == NULL) {
353 if (list->proc_mode != 0000) {
354 mode = list->proc_mode;
358 if (list->write_fptr)
361 proc = create_proc_entry(cur, mode, cur_root);
365 if (pathcopy != pathbuf)
366 OBD_FREE(pathcopy, pathsize);
368 if (cur_root == NULL || proc == NULL) {
369 CERROR("LprocFS: No memory to create /proc entry %s",
371 GOTO(out, rc = -ENOMEM);
375 proc->proc_fops = list->fops;
377 proc->proc_fops = &lprocfs_generic_fops;
378 proc->read_proc = list->read_fptr;
379 proc->write_proc = list->write_fptr;
380 proc->data = (list->data ? list->data : data);
384 LPROCFS_WRITE_EXIT();
387 EXPORT_SYMBOL(lprocfs_add_vars);
389 void lprocfs_remove_nolock(struct proc_dir_entry **rooth)
391 struct proc_dir_entry *root = *rooth;
392 struct proc_dir_entry *temp = root;
393 struct proc_dir_entry *rm_entry;
394 struct proc_dir_entry *parent;
400 parent = root->parent;
401 LASSERT(parent != NULL);
404 while (temp->subdir != NULL)
410 /* Memory corruption once caused this to fail, and
411 without this LASSERT we would loop here forever. */
412 LASSERTF(strlen(rm_entry->name) == rm_entry->namelen,
413 "0x%p %s/%s len %d\n", rm_entry, temp->name,
414 rm_entry->name, (int)strlen(rm_entry->name));
416 #ifdef HAVE_PROCFS_USERS
417 /* if procfs uses user count to synchronize deletion of
418 * proc entry, there is no protection for rm_entry->data,
419 * then lprocfs_fops_read and lprocfs_fops_write maybe
420 * call proc_dir_entry->read_proc (or write_proc) with
421 * proc_dir_entry->data == NULL, then cause kernel Oops.
422 * see bug19706 for detailed information */
424 /* procfs won't free rm_entry->data if it isn't a LINK,
425 * and Lustre won't use rm_entry->data if it is a LINK */
426 if (S_ISLNK(rm_entry->mode))
427 rm_entry->data = NULL;
429 /* Now, the rm_entry->deleted flags is protected
430 * by _lprocfs_lock. */
431 rm_entry->data = NULL;
433 remove_proc_entry(rm_entry->name, temp);
439 void lprocfs_remove(struct proc_dir_entry **rooth)
441 LPROCFS_WRITE_ENTRY(); /* search vs remove race */
442 lprocfs_remove_nolock(rooth);
443 LPROCFS_WRITE_EXIT();
445 EXPORT_SYMBOL(lprocfs_remove);
447 void lprocfs_remove_proc_entry(const char *name, struct proc_dir_entry *parent)
449 LASSERT(parent != NULL);
450 remove_proc_entry(name, parent);
452 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
454 void lprocfs_try_remove_proc_entry(const char *name,
455 struct proc_dir_entry *parent)
457 struct proc_dir_entry *t = NULL;
458 struct proc_dir_entry **p;
461 LASSERT(parent != NULL);
464 LPROCFS_WRITE_ENTRY();
466 /* lookup target name */
467 for (p = &parent->subdir; *p; p = &(*p)->next) {
468 if ((*p)->namelen != len)
470 if (memcmp(name, (*p)->name, len))
477 /* verify it's empty: do not count "num_refs" */
478 for (p = &t->subdir; *p; p = &(*p)->next) {
479 if ((*p)->namelen != strlen("num_refs")) {
483 if (memcmp("num_refs", (*p)->name,
484 strlen("num_refs"))) {
492 lprocfs_remove_nolock(&t);
494 LPROCFS_WRITE_EXIT();
498 EXPORT_SYMBOL(lprocfs_try_remove_proc_entry);
500 struct proc_dir_entry *lprocfs_register(const char *name,
501 struct proc_dir_entry *parent,
502 struct lprocfs_vars *list, void *data)
504 struct proc_dir_entry *newchild;
506 newchild = lprocfs_srch(parent, name);
507 if (newchild != NULL) {
508 CERROR(" Lproc: Attempting to register %s more than once \n",
510 return ERR_PTR(-EALREADY);
513 newchild = proc_mkdir(name, parent);
514 if (newchild != NULL && list != NULL) {
515 int rc = lprocfs_add_vars(newchild, list, data);
517 lprocfs_remove(&newchild);
523 EXPORT_SYMBOL(lprocfs_register);
525 /* Generic callbacks */
526 int lprocfs_rd_uint(char *page, char **start, off_t off,
527 int count, int *eof, void *data)
529 unsigned int *temp = data;
530 return snprintf(page, count, "%u\n", *temp);
532 EXPORT_SYMBOL(lprocfs_rd_uint);
534 int lprocfs_wr_uint(struct file *file, const char *buffer,
535 unsigned long count, void *data)
538 char dummy[MAX_STRING_SIZE + 1], *end;
541 dummy[MAX_STRING_SIZE] = '\0';
542 if (cfs_copy_from_user(dummy, buffer, MAX_STRING_SIZE))
545 tmp = simple_strtoul(dummy, &end, 0);
549 *p = (unsigned int)tmp;
552 EXPORT_SYMBOL(lprocfs_wr_uint);
554 int lprocfs_rd_u64(char *page, char **start, off_t off,
555 int count, int *eof, void *data)
557 LASSERT(data != NULL);
559 return snprintf(page, count, LPU64"\n", *(__u64 *)data);
561 EXPORT_SYMBOL(lprocfs_rd_u64);
563 int lprocfs_rd_atomic(char *page, char **start, off_t off,
564 int count, int *eof, void *data)
566 cfs_atomic_t *atom = data;
567 LASSERT(atom != NULL);
569 return snprintf(page, count, "%d\n", cfs_atomic_read(atom));
571 EXPORT_SYMBOL(lprocfs_rd_atomic);
573 int lprocfs_wr_atomic(struct file *file, const char *buffer,
574 unsigned long count, void *data)
576 cfs_atomic_t *atm = data;
580 rc = lprocfs_write_helper(buffer, count, &val);
587 cfs_atomic_set(atm, val);
590 EXPORT_SYMBOL(lprocfs_wr_atomic);
592 int lprocfs_rd_uuid(char *page, char **start, off_t off, int count,
593 int *eof, void *data)
595 struct obd_device *obd = data;
597 LASSERT(obd != NULL);
599 return snprintf(page, count, "%s\n", obd->obd_uuid.uuid);
601 EXPORT_SYMBOL(lprocfs_rd_uuid);
603 int lprocfs_rd_name(char *page, char **start, off_t off, int count,
604 int *eof, void *data)
606 struct obd_device *dev = data;
608 LASSERT(dev != NULL);
609 LASSERT(dev->obd_name != NULL);
611 return snprintf(page, count, "%s\n", dev->obd_name);
613 EXPORT_SYMBOL(lprocfs_rd_name);
615 int lprocfs_rd_fstype(char *page, char **start, off_t off, int count, int *eof,
618 struct obd_device *obd = data;
620 LASSERT(obd != NULL);
621 LASSERT(obd->obd_fsops != NULL);
622 LASSERT(obd->obd_fsops->fs_type != NULL);
623 return snprintf(page, count, "%s\n", obd->obd_fsops->fs_type);
625 EXPORT_SYMBOL(lprocfs_rd_fstype);
627 int lprocfs_rd_blksize(char *page, char **start, off_t off, int count,
628 int *eof, void *data)
630 struct obd_device *obd = data;
631 struct obd_statfs osfs;
632 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
633 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
637 rc = snprintf(page, count, "%u\n", osfs.os_bsize);
641 EXPORT_SYMBOL(lprocfs_rd_blksize);
643 int lprocfs_osd_rd_blksize(char *page, char **start, off_t off,
644 int count, int *eof, void *data)
646 struct dt_device *dt = data;
647 struct obd_statfs osfs;
648 int rc = dt_statfs(NULL, dt, &osfs);
651 rc = snprintf(page, count, "%d\n",
652 (unsigned) osfs.os_bsize);
656 EXPORT_SYMBOL(lprocfs_osd_rd_blksize);
658 int lprocfs_rd_kbytestotal(char *page, char **start, off_t off, int count,
659 int *eof, void *data)
661 struct obd_device *obd = data;
662 struct obd_statfs osfs;
663 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
664 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
667 __u32 blk_size = osfs.os_bsize >> 10;
668 __u64 result = osfs.os_blocks;
670 while (blk_size >>= 1)
674 rc = snprintf(page, count, LPU64"\n", result);
678 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
680 int lprocfs_osd_rd_kbytestotal(char *page, char **start, off_t off,
681 int count, int *eof, void *data)
683 struct dt_device *dt = data;
684 struct obd_statfs osfs;
685 int rc = dt_statfs(NULL, dt, &osfs);
687 __u32 blk_size = osfs.os_bsize >> 10;
688 __u64 result = osfs.os_blocks;
690 while (blk_size >>= 1)
694 rc = snprintf(page, count, LPU64"\n", result);
698 EXPORT_SYMBOL(lprocfs_osd_rd_kbytestotal);
700 int lprocfs_rd_kbytesfree(char *page, char **start, off_t off, int count,
701 int *eof, void *data)
703 struct obd_device *obd = data;
704 struct obd_statfs osfs;
705 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
706 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
709 __u32 blk_size = osfs.os_bsize >> 10;
710 __u64 result = osfs.os_bfree;
712 while (blk_size >>= 1)
716 rc = snprintf(page, count, LPU64"\n", result);
720 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
722 int lprocfs_osd_rd_kbytesfree(char *page, char **start, off_t off,
723 int count, int *eof, void *data)
725 struct dt_device *dt = data;
726 struct obd_statfs osfs;
727 int rc = dt_statfs(NULL, dt, &osfs);
729 __u32 blk_size = osfs.os_bsize >> 10;
730 __u64 result = osfs.os_bfree;
732 while (blk_size >>= 1)
736 rc = snprintf(page, count, LPU64"\n", result);
740 EXPORT_SYMBOL(lprocfs_osd_rd_kbytesfree);
742 int lprocfs_rd_kbytesavail(char *page, char **start, off_t off, int count,
743 int *eof, void *data)
745 struct obd_device *obd = data;
746 struct obd_statfs osfs;
747 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
748 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
751 __u32 blk_size = osfs.os_bsize >> 10;
752 __u64 result = osfs.os_bavail;
754 while (blk_size >>= 1)
758 rc = snprintf(page, count, LPU64"\n", result);
762 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
764 int lprocfs_osd_rd_kbytesavail(char *page, char **start, off_t off,
765 int count, int *eof, void *data)
767 struct dt_device *dt = data;
768 struct obd_statfs osfs;
769 int rc = dt_statfs(NULL, dt, &osfs);
771 __u32 blk_size = osfs.os_bsize >> 10;
772 __u64 result = osfs.os_bavail;
774 while (blk_size >>= 1)
778 rc = snprintf(page, count, LPU64"\n", result);
782 EXPORT_SYMBOL(lprocfs_osd_rd_kbytesavail);
784 int lprocfs_rd_filestotal(char *page, char **start, off_t off, int count,
785 int *eof, void *data)
787 struct obd_device *obd = data;
788 struct obd_statfs osfs;
789 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
790 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
794 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
799 EXPORT_SYMBOL(lprocfs_rd_filestotal);
801 int lprocfs_osd_rd_filestotal(char *page, char **start, off_t off,
802 int count, int *eof, void *data)
804 struct dt_device *dt = data;
805 struct obd_statfs osfs;
806 int rc = dt_statfs(NULL, dt, &osfs);
809 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
814 EXPORT_SYMBOL(lprocfs_osd_rd_filestotal);
816 int lprocfs_rd_filesfree(char *page, char **start, off_t off, int count,
817 int *eof, void *data)
819 struct obd_device *obd = data;
820 struct obd_statfs osfs;
821 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
822 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
826 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
830 EXPORT_SYMBOL(lprocfs_rd_filesfree);
832 int lprocfs_osd_rd_filesfree(char *page, char **start, off_t off,
833 int count, int *eof, void *data)
835 struct dt_device *dt = data;
836 struct obd_statfs osfs;
837 int rc = dt_statfs(NULL, dt, &osfs);
840 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
844 EXPORT_SYMBOL(lprocfs_osd_rd_filesfree);
846 int lprocfs_rd_server_uuid(char *page, char **start, off_t off, int count,
847 int *eof, void *data)
849 struct obd_device *obd = data;
850 struct obd_import *imp;
851 char *imp_state_name = NULL;
854 LASSERT(obd != NULL);
855 LPROCFS_CLIMP_CHECK(obd);
856 imp = obd->u.cli.cl_import;
857 imp_state_name = ptlrpc_import_state_name(imp->imp_state);
859 rc = snprintf(page, count, "%s\t%s%s\n",
860 obd2cli_tgt(obd), imp_state_name,
861 imp->imp_deactive ? "\tDEACTIVATED" : "");
863 LPROCFS_CLIMP_EXIT(obd);
866 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
868 int lprocfs_rd_conn_uuid(char *page, char **start, off_t off, int count,
869 int *eof, void *data)
871 struct obd_device *obd = data;
872 struct ptlrpc_connection *conn;
875 LASSERT(obd != NULL);
877 LPROCFS_CLIMP_CHECK(obd);
878 conn = obd->u.cli.cl_import->imp_connection;
880 if (conn && obd->u.cli.cl_import) {
881 rc = snprintf(page, count, "%s\n",
882 conn->c_remote_uuid.uuid);
884 rc = snprintf(page, count, "%s\n", "<none>");
887 LPROCFS_CLIMP_EXIT(obd);
890 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
892 /** add up per-cpu counters */
893 void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
894 struct lprocfs_counter *cnt)
896 unsigned int num_entry;
897 struct lprocfs_counter t;
898 struct lprocfs_counter *percpu_cntr;
901 unsigned long flags = 0;
903 memset(cnt, 0, sizeof(*cnt));
906 /* set count to 1 to avoid divide-by-zero errs in callers */
911 cnt->lc_min = LC_MIN_INIT;
913 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
915 for (i = 0; i < num_entry; i++) {
916 if (stats->ls_percpu[i] == NULL)
918 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[idx];
921 centry = cfs_atomic_read(&percpu_cntr-> \
923 t.lc_count = percpu_cntr->lc_count;
924 t.lc_sum = percpu_cntr->lc_sum;
925 t.lc_min = percpu_cntr->lc_min;
926 t.lc_max = percpu_cntr->lc_max;
927 t.lc_sumsquare = percpu_cntr->lc_sumsquare;
928 } while (centry != cfs_atomic_read(&percpu_cntr->lc_cntl. \
930 centry != cfs_atomic_read(&percpu_cntr->lc_cntl. \
932 cnt->lc_count += t.lc_count;
933 cnt->lc_sum += t.lc_sum;
934 if (t.lc_min < cnt->lc_min)
935 cnt->lc_min = t.lc_min;
936 if (t.lc_max > cnt->lc_max)
937 cnt->lc_max = t.lc_max;
938 cnt->lc_sumsquare += t.lc_sumsquare;
941 cnt->lc_units = stats->ls_percpu[0]->lp_cntr[idx].lc_units;
942 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
944 EXPORT_SYMBOL(lprocfs_stats_collect);
947 * Append a space separated list of current set flags to str.
949 #define flag2str(flag) \
950 if (imp->imp_##flag && max - len > 0) \
951 len += snprintf(str + len, max - len, "%s" #flag, len ? ", " : "");
952 static int obd_import_flags2str(struct obd_import *imp, char *str, int max)
956 if (imp->imp_obd->obd_no_recov)
957 len += snprintf(str, max - len, "no_recov");
961 flag2str(replayable);
967 static const char *obd_connect_names[] = {
981 "join_file(obsolete)",
985 "remote_client_by_force",
994 "mds_mds_connection",
997 "alt_checksum_algorithm",
1013 "nanoseconds_times",
1021 int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
1026 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
1028 ret += snprintf(page + ret, count - ret, "%s%s",
1029 ret ? sep : "", obd_connect_names[i]);
1031 if (flags & ~(mask - 1))
1032 ret += snprintf(page + ret, count - ret,
1033 "%sunknown flags "LPX64,
1034 ret ? sep : "", flags & ~(mask - 1));
1037 EXPORT_SYMBOL(obd_connect_flags2str);
1039 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
1040 int *eof, void *data)
1042 struct lprocfs_counter ret;
1043 struct obd_device *obd = (struct obd_device *)data;
1044 struct obd_import *imp;
1045 struct obd_import_conn *conn;
1046 int i, j, k, rw = 0;
1048 LASSERT(obd != NULL);
1049 LPROCFS_CLIMP_CHECK(obd);
1050 imp = obd->u.cli.cl_import;
1053 i = snprintf(page, count,
1059 " connect_flags: [",
1062 ptlrpc_import_state_name(imp->imp_state),
1063 imp->imp_connect_data.ocd_instance);
1064 i += obd_connect_flags2str(page + i, count - i,
1065 imp->imp_connect_data.ocd_connect_flags,
1067 i += snprintf(page + i, count - i,
1069 " import_flags: [");
1070 i += obd_import_flags2str(imp, page + i, count - i);
1072 i += snprintf(page + i, count - i,
1075 " failover_nids: [");
1076 cfs_spin_lock(&imp->imp_lock);
1078 cfs_list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
1079 i += snprintf(page + i, count - i, "%s%s", j ? ", " : "",
1080 libcfs_nid2str(conn->oic_conn->c_peer.nid));
1083 i += snprintf(page + i, count - i,
1085 " current_connection: %s\n"
1086 " connection_attempts: %u\n"
1088 " in-progress_invalidations: %u\n",
1089 imp->imp_connection == NULL ? "<none>" :
1090 libcfs_nid2str(imp->imp_connection->c_peer.nid),
1092 imp->imp_generation,
1093 cfs_atomic_read(&imp->imp_inval_count));
1094 cfs_spin_unlock(&imp->imp_lock);
1096 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
1097 if (ret.lc_count != 0) {
1098 /* first argument to do_div MUST be __u64 */
1099 __u64 sum = ret.lc_sum;
1100 do_div(sum, ret.lc_count);
1104 i += snprintf(page + i, count - i,
1107 " unregistering: %u\n"
1109 " avg_waittime: "LPU64" %s\n",
1110 cfs_atomic_read(&imp->imp_inflight),
1111 cfs_atomic_read(&imp->imp_unregistering),
1112 cfs_atomic_read(&imp->imp_timeouts),
1113 ret.lc_sum, ret.lc_units);
1116 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
1117 if (imp->imp_at.iat_portal[j] == 0)
1119 k = max_t(unsigned int, k,
1120 at_get(&imp->imp_at.iat_service_estimate[j]));
1122 i += snprintf(page + i, count - i,
1123 " service_estimates:\n"
1124 " services: %u sec\n"
1125 " network: %u sec\n",
1127 at_get(&imp->imp_at.iat_net_latency));
1129 i += snprintf(page + i, count - i,
1131 " last_replay: "LPU64"\n"
1132 " peer_committed: "LPU64"\n"
1133 " last_checked: "LPU64"\n",
1134 imp->imp_last_replay_transno,
1135 imp->imp_peer_committed_transno,
1136 imp->imp_last_transno_checked);
1138 /* avg data rates */
1139 for (rw = 0; rw <= 1; rw++) {
1140 lprocfs_stats_collect(obd->obd_svc_stats,
1141 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
1143 if (ret.lc_sum > 0 && ret.lc_count > 0) {
1144 /* first argument to do_div MUST be __u64 */
1145 __u64 sum = ret.lc_sum;
1146 do_div(sum, ret.lc_count);
1148 i += snprintf(page + i, count - i,
1149 " %s_data_averages:\n"
1150 " bytes_per_rpc: "LPU64"\n",
1151 rw ? "write" : "read",
1154 k = (int)ret.lc_sum;
1155 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
1156 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
1157 if (ret.lc_sum > 0 && ret.lc_count != 0) {
1158 /* first argument to do_div MUST be __u64 */
1159 __u64 sum = ret.lc_sum;
1160 do_div(sum, ret.lc_count);
1162 i += snprintf(page + i, count - i,
1163 " %s_per_rpc: "LPU64"\n",
1164 ret.lc_units, ret.lc_sum);
1165 j = (int)ret.lc_sum;
1167 i += snprintf(page + i, count - i,
1168 " MB_per_sec: %u.%.02u\n",
1169 k / j, (100 * k / j) % 100);
1173 LPROCFS_CLIMP_EXIT(obd);
1176 EXPORT_SYMBOL(lprocfs_rd_import);
1178 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
1179 int *eof, void *data)
1181 struct obd_device *obd = (struct obd_device *)data;
1182 struct obd_import *imp;
1185 LASSERT(obd != NULL);
1186 LPROCFS_CLIMP_CHECK(obd);
1187 imp = obd->u.cli.cl_import;
1190 i = snprintf(page, count, "current_state: %s\n",
1191 ptlrpc_import_state_name(imp->imp_state));
1192 i += snprintf(page + i, count - i,
1193 "state_history:\n");
1194 k = imp->imp_state_hist_idx;
1195 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
1196 struct import_state_hist *ish =
1197 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
1198 if (ish->ish_state == 0)
1200 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
1202 ptlrpc_import_state_name(ish->ish_state));
1205 LPROCFS_CLIMP_EXIT(obd);
1208 EXPORT_SYMBOL(lprocfs_rd_state);
1210 int lprocfs_at_hist_helper(char *page, int count, int rc,
1211 struct adaptive_timeout *at)
1214 for (i = 0; i < AT_BINS; i++)
1215 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
1216 rc += snprintf(page + rc, count - rc, "\n");
1219 EXPORT_SYMBOL(lprocfs_at_hist_helper);
1221 /* See also ptlrpc_lprocfs_rd_timeouts */
1222 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
1223 int *eof, void *data)
1225 struct obd_device *obd = (struct obd_device *)data;
1226 struct obd_import *imp;
1227 unsigned int cur, worst;
1232 LASSERT(obd != NULL);
1233 LPROCFS_CLIMP_CHECK(obd);
1234 imp = obd->u.cli.cl_import;
1237 now = cfs_time_current_sec();
1239 /* Some network health info for kicks */
1240 s2dhms(&ts, now - imp->imp_last_reply_time);
1241 rc += snprintf(page + rc, count - rc,
1242 "%-10s : %ld, "DHMS_FMT" ago\n",
1243 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
1245 cur = at_get(&imp->imp_at.iat_net_latency);
1246 worst = imp->imp_at.iat_net_latency.at_worst_ever;
1247 worstt = imp->imp_at.iat_net_latency.at_worst_time;
1248 s2dhms(&ts, now - worstt);
1249 rc += snprintf(page + rc, count - rc,
1250 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
1251 "network", cur, worst, worstt, DHMS_VARS(&ts));
1252 rc = lprocfs_at_hist_helper(page, count, rc,
1253 &imp->imp_at.iat_net_latency);
1255 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
1256 if (imp->imp_at.iat_portal[i] == 0)
1258 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
1259 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
1260 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
1261 s2dhms(&ts, now - worstt);
1262 rc += snprintf(page + rc, count - rc,
1263 "portal %-2d : cur %3u worst %3u (at %ld, "
1264 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
1265 cur, worst, worstt, DHMS_VARS(&ts));
1266 rc = lprocfs_at_hist_helper(page, count, rc,
1267 &imp->imp_at.iat_service_estimate[i]);
1270 LPROCFS_CLIMP_EXIT(obd);
1273 EXPORT_SYMBOL(lprocfs_rd_timeouts);
1275 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1276 int count, int *eof, void *data)
1278 struct obd_device *obd = data;
1282 LPROCFS_CLIMP_CHECK(obd);
1283 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1284 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1285 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1286 ret += snprintf(page + ret, count - ret, "\n");
1287 LPROCFS_CLIMP_EXIT(obd);
1290 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1292 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1293 int *eof, void *data)
1295 struct obd_device *obd = data;
1297 LASSERT(obd != NULL);
1299 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1301 EXPORT_SYMBOL(lprocfs_rd_num_exports);
1303 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1304 int *eof, void *data)
1306 struct obd_type *class = (struct obd_type*) data;
1308 LASSERT(class != NULL);
1310 return snprintf(page, count, "%d\n", class->typ_refcnt);
1312 EXPORT_SYMBOL(lprocfs_rd_numrefs);
1314 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1318 LASSERT(obd != NULL);
1319 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1320 LASSERT(obd->obd_type->typ_procroot != NULL);
1322 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1323 obd->obd_type->typ_procroot,
1325 if (IS_ERR(obd->obd_proc_entry)) {
1326 rc = PTR_ERR(obd->obd_proc_entry);
1327 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1328 obd->obd_proc_entry = NULL;
1332 EXPORT_SYMBOL(lprocfs_obd_setup);
1334 int lprocfs_obd_cleanup(struct obd_device *obd)
1338 if (obd->obd_proc_exports_entry) {
1339 /* Should be no exports left */
1340 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1341 lprocfs_remove(&obd->obd_proc_exports_entry);
1342 obd->obd_proc_exports_entry = NULL;
1344 if (obd->obd_proc_entry) {
1345 lprocfs_remove(&obd->obd_proc_entry);
1346 obd->obd_proc_entry = NULL;
1350 EXPORT_SYMBOL(lprocfs_obd_cleanup);
1352 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1354 CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
1355 client_stat->nid_proc, client_stat->nid_stats,
1356 client_stat->nid_brw_stats);
1358 LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
1359 "nid %s:count %d\n", libcfs_nid2str(client_stat->nid),
1360 atomic_read(&client_stat->nid_exp_ref_count));
1362 if (client_stat->nid_proc)
1363 lprocfs_remove(&client_stat->nid_proc);
1365 if (client_stat->nid_stats)
1366 lprocfs_free_stats(&client_stat->nid_stats);
1368 if (client_stat->nid_brw_stats)
1369 OBD_FREE_PTR(client_stat->nid_brw_stats);
1371 if (client_stat->nid_ldlm_stats)
1372 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1374 OBD_FREE_PTR(client_stat);
1379 void lprocfs_free_per_client_stats(struct obd_device *obd)
1381 cfs_hash_t *hash = obd->obd_nid_stats_hash;
1382 struct nid_stat *stat;
1385 /* we need extra list - because hash_exit called to early */
1386 /* not need locking because all clients is died */
1387 while (!cfs_list_empty(&obd->obd_nid_stats)) {
1388 stat = cfs_list_entry(obd->obd_nid_stats.next,
1389 struct nid_stat, nid_list);
1390 cfs_list_del_init(&stat->nid_list);
1391 cfs_hash_del(hash, &stat->nid, &stat->nid_hash);
1392 lprocfs_free_client_stats(stat);
1396 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
1398 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1399 enum lprocfs_stats_flags flags)
1401 struct lprocfs_stats *stats;
1402 unsigned int percpusize;
1403 unsigned int num_entry;
1408 if (lprocfs_no_percpu_stats != 0)
1409 flags |= LPROCFS_STATS_FLAG_NOPERCPU;
1411 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1414 num_entry = cfs_num_possible_cpus() + 1;
1416 /* alloc percpu pointers for all possible cpu slots */
1417 OBD_ALLOC(stats, offsetof(struct lprocfs_stats, ls_percpu[num_entry]));
1421 stats->ls_num = num;
1422 stats->ls_biggest_alloc_num = 1;
1423 stats->ls_flags = flags;
1424 cfs_spin_lock_init(&stats->ls_lock);
1426 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
1428 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1430 /* for no percpu area, the 0th entry is for real use,
1431 * for percpu area, the 0th entry is for intialized entry template */
1432 OBD_ALLOC(stats->ls_percpu[0], percpusize);
1433 if (stats->ls_percpu[0] == NULL) {
1435 offsetof(struct lprocfs_stats, ls_percpu[num_entry]));
1440 EXPORT_SYMBOL(lprocfs_alloc_stats);
1442 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1444 struct lprocfs_stats *stats = *statsh;
1445 unsigned int num_entry;
1446 unsigned int percpusize;
1449 if (stats == NULL || stats->ls_num == 0)
1453 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1456 num_entry = cfs_num_possible_cpus() + 1;
1458 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
1460 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1461 for (i = 0; i < num_entry; i++)
1462 if (stats->ls_percpu[i] != NULL)
1463 OBD_FREE(stats->ls_percpu[i], percpusize);
1464 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1466 EXPORT_SYMBOL(lprocfs_free_stats);
1468 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1470 struct lprocfs_counter *percpu_cntr;
1473 unsigned int num_entry;
1474 unsigned long flags = 0;
1476 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1478 for (i = 0; i < num_entry; i++) {
1479 if (stats->ls_percpu[i] == NULL)
1481 for (j = 0; j < stats->ls_num; j++) {
1482 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
1483 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_entry);
1484 percpu_cntr->lc_count = 0;
1485 percpu_cntr->lc_sum = 0;
1486 percpu_cntr->lc_min = LC_MIN_INIT;
1487 percpu_cntr->lc_max = 0;
1488 percpu_cntr->lc_sumsquare = 0;
1489 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_exit);
1493 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1495 EXPORT_SYMBOL(lprocfs_clear_stats);
1497 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1498 size_t len, loff_t *off)
1500 struct seq_file *seq = file->private_data;
1501 struct lprocfs_stats *stats = seq->private;
1503 lprocfs_clear_stats(stats);
1508 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1510 struct lprocfs_stats *stats = p->private;
1511 /* return 1st cpu location */
1512 return (*pos >= stats->ls_num) ? NULL :
1513 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1516 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1520 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1522 struct lprocfs_stats *stats = p->private;
1524 return (*pos >= stats->ls_num) ? NULL :
1525 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1528 /* seq file export of one lprocfs counter */
1529 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1531 struct lprocfs_stats *stats = p->private;
1532 struct lprocfs_counter *cntr = v;
1533 struct lprocfs_counter ret;
1536 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
1538 cfs_gettimeofday(&now);
1539 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1540 "snapshot_time", now.tv_sec, now.tv_usec);
1544 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
1546 lprocfs_stats_collect(stats, idx, &ret);
1548 if (ret.lc_count == 0)
1551 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", cntr->lc_name,
1552 ret.lc_count, cntr->lc_units);
1557 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
1558 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1559 ret.lc_min, ret.lc_max, ret.lc_sum);
1562 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
1563 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1567 rc = seq_printf(p, "\n");
1569 return (rc < 0) ? rc : 0;
1572 struct seq_operations lprocfs_stats_seq_sops = {
1573 start: lprocfs_stats_seq_start,
1574 stop: lprocfs_stats_seq_stop,
1575 next: lprocfs_stats_seq_next,
1576 show: lprocfs_stats_seq_show,
1579 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1581 struct proc_dir_entry *dp = PDE(inode);
1582 struct seq_file *seq;
1585 if (LPROCFS_ENTRY_AND_CHECK(dp))
1588 rc = seq_open(file, &lprocfs_stats_seq_sops);
1593 seq = file->private_data;
1594 seq->private = dp->data;
1598 struct file_operations lprocfs_stats_seq_fops = {
1599 .owner = THIS_MODULE,
1600 .open = lprocfs_stats_seq_open,
1602 .write = lprocfs_stats_seq_write,
1603 .llseek = seq_lseek,
1604 .release = lprocfs_seq_release,
1607 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1608 struct lprocfs_stats *stats)
1610 struct proc_dir_entry *entry;
1611 LASSERT(root != NULL);
1613 LPROCFS_WRITE_ENTRY();
1614 entry = create_proc_entry(name, 0644, root);
1616 entry->proc_fops = &lprocfs_stats_seq_fops;
1617 entry->data = stats;
1620 LPROCFS_WRITE_EXIT();
1627 EXPORT_SYMBOL(lprocfs_register_stats);
1629 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1630 unsigned conf, const char *name, const char *units)
1632 struct lprocfs_counter *c = &(stats->ls_percpu[0]->lp_cntr[index]);
1633 unsigned long flags = 0;
1635 LASSERT(stats != NULL);
1636 LASSERT(stats->ls_percpu[0] != NULL);
1638 lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1639 c->lc_config = conf;
1642 c->lc_min = LC_MIN_INIT;
1645 c->lc_units = units;
1646 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1648 EXPORT_SYMBOL(lprocfs_counter_init);
1650 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1652 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1653 LASSERT(coffset < stats->ls_num); \
1654 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1657 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1659 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1660 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1661 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1662 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1663 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1664 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1665 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1666 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1667 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1668 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1669 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1670 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1671 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1672 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1673 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1674 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1675 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1676 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1677 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
1678 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1679 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1680 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1681 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1682 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1683 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1684 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1685 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1686 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1687 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1688 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1689 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1690 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1691 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1692 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1693 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1694 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1695 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1696 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1697 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1698 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1699 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1700 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1701 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1702 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1703 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
1704 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1705 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1706 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1707 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1708 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1709 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1710 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1711 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1712 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1713 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1714 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1715 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1716 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1717 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1718 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1719 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1720 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1721 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1722 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1723 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1724 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1725 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1726 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1728 EXPORT_SYMBOL(lprocfs_init_ops_stats);
1730 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1732 struct lprocfs_stats *stats;
1733 unsigned int num_stats;
1736 LASSERT(obd->obd_stats == NULL);
1737 LASSERT(obd->obd_proc_entry != NULL);
1738 LASSERT(obd->obd_cntr_base == 0);
1740 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1741 num_private_stats - 1 /* o_owner */;
1742 stats = lprocfs_alloc_stats(num_stats, 0);
1746 lprocfs_init_ops_stats(num_private_stats, stats);
1748 for (i = num_private_stats; i < num_stats; i++) {
1749 /* If this LBUGs, it is likely that an obd
1750 * operation was added to struct obd_ops in
1751 * <obd.h>, and that the corresponding line item
1752 * LPROCFS_OBD_OP_INIT(.., .., opname)
1753 * is missing from the list above. */
1754 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1755 "Missing obd_stat initializer obd_op "
1756 "operation at offset %d.\n", i - num_private_stats);
1758 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1760 lprocfs_free_stats(&stats);
1762 obd->obd_stats = stats;
1763 obd->obd_cntr_base = num_private_stats;
1767 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
1769 void lprocfs_free_obd_stats(struct obd_device *obd)
1772 lprocfs_free_stats(&obd->obd_stats);
1774 EXPORT_SYMBOL(lprocfs_free_obd_stats);
1776 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1778 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1779 LASSERT(coffset < stats->ls_num); \
1780 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1783 void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats)
1785 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1786 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1787 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
1788 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1789 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1790 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1791 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1792 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1793 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1794 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1795 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1796 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1797 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1798 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1799 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1800 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1801 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1802 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1803 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1804 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1805 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1806 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1807 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1808 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1809 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1810 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1811 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1812 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1813 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1814 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1815 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1816 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1818 EXPORT_SYMBOL(lprocfs_init_mps_stats);
1820 int lprocfs_alloc_md_stats(struct obd_device *obd,
1821 unsigned num_private_stats)
1823 struct lprocfs_stats *stats;
1824 unsigned int num_stats;
1827 LASSERT(obd->md_stats == NULL);
1828 LASSERT(obd->obd_proc_entry != NULL);
1829 LASSERT(obd->md_cntr_base == 0);
1831 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1833 stats = lprocfs_alloc_stats(num_stats, 0);
1837 lprocfs_init_mps_stats(num_private_stats, stats);
1839 for (i = num_private_stats; i < num_stats; i++) {
1840 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1841 CERROR("Missing md_stat initializer md_op "
1842 "operation at offset %d. Aborting.\n",
1843 i - num_private_stats);
1847 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1849 lprocfs_free_stats(&stats);
1851 obd->md_stats = stats;
1852 obd->md_cntr_base = num_private_stats;
1856 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
1858 void lprocfs_free_md_stats(struct obd_device *obd)
1860 struct lprocfs_stats *stats = obd->md_stats;
1862 if (stats != NULL) {
1863 obd->md_stats = NULL;
1864 obd->md_cntr_base = 0;
1865 lprocfs_free_stats(&stats);
1868 EXPORT_SYMBOL(lprocfs_free_md_stats);
1870 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1872 lprocfs_counter_init(ldlm_stats,
1873 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1874 0, "ldlm_enqueue", "reqs");
1875 lprocfs_counter_init(ldlm_stats,
1876 LDLM_CONVERT - LDLM_FIRST_OPC,
1877 0, "ldlm_convert", "reqs");
1878 lprocfs_counter_init(ldlm_stats,
1879 LDLM_CANCEL - LDLM_FIRST_OPC,
1880 0, "ldlm_cancel", "reqs");
1881 lprocfs_counter_init(ldlm_stats,
1882 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1883 0, "ldlm_bl_callback", "reqs");
1884 lprocfs_counter_init(ldlm_stats,
1885 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1886 0, "ldlm_cp_callback", "reqs");
1887 lprocfs_counter_init(ldlm_stats,
1888 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1889 0, "ldlm_gl_callback", "reqs");
1891 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
1893 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1894 int *eof, void *data)
1896 struct obd_export *exp = data;
1897 LASSERT(exp != NULL);
1899 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1902 struct exp_uuid_cb_data {
1910 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1911 int count, int *eof, int *len)
1913 cb_data->page = page;
1914 cb_data->count = count;
1919 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1920 cfs_hlist_node_t *hnode, void *cb_data)
1923 struct obd_export *exp = cfs_hash_object(hs, hnode);
1924 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1926 if (exp->exp_nid_stats)
1927 *data->len += snprintf((data->page + *data->len),
1928 data->count, "%s\n",
1929 obd_uuid2str(&exp->exp_client_uuid));
1933 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1934 int *eof, void *data)
1936 struct nid_stat *stats = (struct nid_stat *)data;
1937 struct exp_uuid_cb_data cb_data;
1938 struct obd_device *obd = stats->nid_obd;
1943 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1944 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1945 lprocfs_exp_print_uuid, &cb_data);
1946 return (*cb_data.len);
1949 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1950 cfs_hlist_node_t *hnode, void *cb_data)
1953 struct exp_uuid_cb_data *data = cb_data;
1954 struct obd_export *exp = cfs_hash_object(hs, hnode);
1956 if (exp->exp_lock_hash != NULL) {
1958 *data->len += cfs_hash_debug_header(data->page,
1961 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1968 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1969 int *eof, void *data)
1971 struct nid_stat *stats = (struct nid_stat *)data;
1972 struct exp_uuid_cb_data cb_data;
1973 struct obd_device *obd = stats->nid_obd;
1978 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1980 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1981 lprocfs_exp_print_hash, &cb_data);
1982 return (*cb_data.len);
1985 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1986 int count, int *eof, void *data)
1989 return snprintf(page, count, "%s\n",
1990 "Write into this file to clear all nid stats and "
1991 "stale nid entries");
1993 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1995 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1997 struct nid_stat *stat = obj;
2001 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
2002 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 1) {
2003 /* object has only hash references. */
2004 cfs_spin_lock(&stat->nid_obd->obd_nid_lock);
2005 cfs_list_move(&stat->nid_list, data);
2006 cfs_spin_unlock(&stat->nid_obd->obd_nid_lock);
2009 /* we has reference to object - only clear data*/
2010 if (stat->nid_stats)
2011 lprocfs_clear_stats(stat->nid_stats);
2013 if (stat->nid_brw_stats) {
2014 for (i = 0; i < BRW_LAST; i++)
2015 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
2020 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
2021 unsigned long count, void *data)
2023 struct obd_device *obd = (struct obd_device *)data;
2024 struct nid_stat *client_stat;
2025 CFS_LIST_HEAD(free_list);
2027 cfs_hash_cond_del(obd->obd_nid_stats_hash,
2028 lprocfs_nid_stats_clear_write_cb, &free_list);
2030 while (!cfs_list_empty(&free_list)) {
2031 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
2033 cfs_list_del_init(&client_stat->nid_list);
2034 lprocfs_free_client_stats(client_stat);
2039 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
2041 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
2043 struct nid_stat *new_stat, *old_stat;
2044 struct obd_device *obd = NULL;
2045 cfs_proc_dir_entry_t *entry;
2046 char *buffer = NULL;
2052 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
2053 !exp->exp_obd->obd_nid_stats_hash)
2056 /* not test against zero because eric say:
2057 * You may only test nid against another nid, or LNET_NID_ANY.
2058 * Anything else is nonsense.*/
2059 if (!nid || *nid == LNET_NID_ANY)
2064 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
2066 OBD_ALLOC_PTR(new_stat);
2067 if (new_stat == NULL)
2070 new_stat->nid = *nid;
2071 new_stat->nid_obd = exp->exp_obd;
2072 /* we need set default refcount to 1 to balance obd_disconnect */
2073 cfs_atomic_set(&new_stat->nid_exp_ref_count, 1);
2075 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
2076 nid, &new_stat->nid_hash);
2077 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
2078 old_stat, libcfs_nid2str(*nid),
2079 cfs_atomic_read(&new_stat->nid_exp_ref_count));
2081 /* We need to release old stats because lprocfs_exp_cleanup() hasn't
2082 * been and will never be called. */
2083 if (exp->exp_nid_stats) {
2084 nidstat_putref(exp->exp_nid_stats);
2085 exp->exp_nid_stats = NULL;
2088 /* Return -EALREADY here so that we know that the /proc
2089 * entry already has been created */
2090 if (old_stat != new_stat) {
2091 exp->exp_nid_stats = old_stat;
2092 GOTO(destroy_new, rc = -EALREADY);
2094 /* not found - create */
2095 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
2097 GOTO(destroy_new, rc = -ENOMEM);
2099 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
2100 new_stat->nid_proc = lprocfs_register(buffer,
2101 obd->obd_proc_exports_entry,
2103 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
2105 if (new_stat->nid_proc == NULL) {
2106 CERROR("Error making export directory for nid %s\n",
2107 libcfs_nid2str(*nid));
2108 GOTO(destroy_new_ns, rc = -ENOMEM);
2111 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
2112 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
2113 if (IS_ERR(entry)) {
2114 CWARN("Error adding the NID stats file\n");
2115 rc = PTR_ERR(entry);
2116 GOTO(destroy_new_ns, rc);
2119 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
2120 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
2121 if (IS_ERR(entry)) {
2122 CWARN("Error adding the hash file\n");
2123 rc = PTR_ERR(entry);
2124 GOTO(destroy_new_ns, rc);
2127 exp->exp_nid_stats = new_stat;
2129 /* protect competitive add to list, not need locking on destroy */
2130 cfs_spin_lock(&obd->obd_nid_lock);
2131 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
2132 cfs_spin_unlock(&obd->obd_nid_lock);
2137 if (new_stat->nid_proc != NULL)
2138 lprocfs_remove(&new_stat->nid_proc);
2139 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
2142 nidstat_putref(new_stat);
2143 OBD_FREE_PTR(new_stat);
2146 EXPORT_SYMBOL(lprocfs_exp_setup);
2148 int lprocfs_exp_cleanup(struct obd_export *exp)
2150 struct nid_stat *stat = exp->exp_nid_stats;
2152 if(!stat || !exp->exp_obd)
2155 nidstat_putref(exp->exp_nid_stats);
2156 exp->exp_nid_stats = NULL;
2160 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2162 int lprocfs_write_helper(const char *buffer, unsigned long count,
2165 return lprocfs_write_frac_helper(buffer, count, val, 1);
2167 EXPORT_SYMBOL(lprocfs_write_helper);
2169 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
2172 char kernbuf[20], *end, *pbuf;
2174 if (count > (sizeof(kernbuf) - 1))
2177 if (cfs_copy_from_user(kernbuf, buffer, count))
2180 kernbuf[count] = '\0';
2187 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2191 if (end != NULL && *end == '.') {
2192 int temp_val, pow = 1;
2196 if (strlen(pbuf) > 5)
2197 pbuf[5] = '\0'; /*only allow 5bits fractional*/
2199 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2202 for (i = 0; i < (end - pbuf); i++)
2205 *val += temp_val / pow;
2210 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2212 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
2215 long decimal_val, frac_val;
2221 decimal_val = val / mult;
2222 prtn = snprintf(buffer, count, "%ld", decimal_val);
2223 frac_val = val % mult;
2225 if (prtn < (count - 4) && frac_val > 0) {
2227 int i, temp_mult = 1, frac_bits = 0;
2229 temp_frac = frac_val * 10;
2230 buffer[prtn++] = '.';
2231 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
2232 /* only reserved 2 bits fraction */
2233 buffer[prtn++] ='0';
2238 * Need to think these cases :
2239 * 1. #echo x.00 > /proc/xxx output result : x
2240 * 2. #echo x.0x > /proc/xxx output result : x.0x
2241 * 3. #echo x.x0 > /proc/xxx output result : x.x
2242 * 4. #echo x.xx > /proc/xxx output result : x.xx
2243 * Only reserved 2 bits fraction.
2245 for (i = 0; i < (5 - prtn); i++)
2248 frac_bits = min((int)count - prtn, 3 - frac_bits);
2249 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
2250 frac_val * temp_mult / mult);
2253 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
2255 if (buffer[prtn] == '.') {
2262 buffer[prtn++] ='\n';
2265 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2267 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
2269 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
2271 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2273 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
2274 __u64 *val, int mult)
2276 char kernbuf[22], *end, *pbuf;
2277 __u64 whole, frac = 0, units;
2278 unsigned frac_d = 1;
2280 if (count > (sizeof(kernbuf) - 1))
2283 if (cfs_copy_from_user(kernbuf, buffer, count))
2286 kernbuf[count] = '\0';
2293 whole = simple_strtoull(pbuf, &end, 10);
2297 if (end != NULL && *end == '.') {
2301 /* need to limit frac_d to a __u32 */
2302 if (strlen(pbuf) > 10)
2305 frac = simple_strtoull(pbuf, &end, 10);
2306 /* count decimal places */
2307 for (i = 0; i < (end - pbuf); i++)
2324 /* Specified units override the multiplier */
2326 mult = mult < 0 ? -units : units;
2329 do_div(frac, frac_d);
2330 *val = whole * mult + frac;
2333 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2335 static char *lprocfs_strnstr(const char *s1, const char *s2, size_t len)
2344 if (!memcmp(s1, s2, l2))
2352 * Find the string \a name in the input \a buffer, and return a pointer to the
2353 * value immediately following \a name, reducing \a count appropriately.
2354 * If \a name is not found the original \a buffer is returned.
2356 char *lprocfs_find_named_value(const char *buffer, const char *name,
2357 unsigned long *count)
2360 size_t buflen = *count;
2362 /* there is no strnstr() in rhel5 and ubuntu kernels */
2363 val = lprocfs_strnstr(buffer, name, buflen);
2365 return (char *)buffer;
2367 val += strlen(name); /* skip prefix */
2368 while (val < buffer + buflen && isspace(*val)) /* skip separator */
2372 while (val < buffer + buflen && isalnum(*val)) {
2377 return val - *count;
2379 EXPORT_SYMBOL(lprocfs_find_named_value);
2381 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent, char *name, mode_t mode,
2382 struct file_operations *seq_fops, void *data)
2384 struct proc_dir_entry *entry;
2387 LPROCFS_WRITE_ENTRY();
2388 entry = create_proc_entry(name, mode, parent);
2390 entry->proc_fops = seq_fops;
2393 LPROCFS_WRITE_EXIT();
2400 EXPORT_SYMBOL(lprocfs_seq_create);
2402 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
2404 struct file_operations *seq_fops,
2407 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2408 mode, seq_fops, data));
2410 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2412 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2414 if (value >= OBD_HIST_MAX)
2415 value = OBD_HIST_MAX - 1;
2417 cfs_spin_lock(&oh->oh_lock);
2418 oh->oh_buckets[value]++;
2419 cfs_spin_unlock(&oh->oh_lock);
2421 EXPORT_SYMBOL(lprocfs_oh_tally);
2423 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2427 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2430 lprocfs_oh_tally(oh, val);
2432 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2434 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2436 unsigned long ret = 0;
2439 for (i = 0; i < OBD_HIST_MAX; i++)
2440 ret += oh->oh_buckets[i];
2443 EXPORT_SYMBOL(lprocfs_oh_sum);
2445 void lprocfs_oh_clear(struct obd_histogram *oh)
2447 cfs_spin_lock(&oh->oh_lock);
2448 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2449 cfs_spin_unlock(&oh->oh_lock);
2451 EXPORT_SYMBOL(lprocfs_oh_clear);
2453 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2454 int count, int *eof, void *data)
2456 struct obd_device *obd = data;
2462 c += cfs_hash_debug_header(page, count);
2463 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2464 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2465 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2469 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2471 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2472 int count, int *eof, void *data)
2474 struct obd_device *obd = data;
2477 LASSERT(obd != NULL);
2478 LASSERT(count >= 0);
2480 /* Set start of user data returned to
2481 page + off since the user may have
2482 requested to read much smaller than
2483 what we need to read */
2484 *start = page + off;
2486 /* We know we are allocated a page here.
2487 Also we know that this function will
2488 not need to write more than a page
2489 so we can truncate at CFS_PAGE_SIZE. */
2490 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2492 /* Initialize the page */
2493 memset(page, 0, size);
2495 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2497 if (obd->obd_max_recoverable_clients == 0) {
2498 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2504 /* sampled unlocked, but really... */
2505 if (obd->obd_recovering == 0) {
2506 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2508 if (lprocfs_obd_snprintf(&page, size, &len,
2509 "recovery_start: %lu\n",
2510 obd->obd_recovery_start) <= 0)
2512 if (lprocfs_obd_snprintf(&page, size, &len,
2513 "recovery_duration: %lu\n",
2514 obd->obd_recovery_end -
2515 obd->obd_recovery_start) <= 0)
2517 /* Number of clients that have completed recovery */
2518 if (lprocfs_obd_snprintf(&page, size, &len,
2519 "completed_clients: %d/%d\n",
2520 obd->obd_max_recoverable_clients -
2521 obd->obd_stale_clients,
2522 obd->obd_max_recoverable_clients) <= 0)
2524 if (lprocfs_obd_snprintf(&page, size, &len,
2525 "replayed_requests: %d\n",
2526 obd->obd_replayed_requests) <= 0)
2528 if (lprocfs_obd_snprintf(&page, size, &len,
2529 "last_transno: "LPD64"\n",
2530 obd->obd_next_recovery_transno - 1)<=0)
2532 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2533 obd->obd_version_recov ?
2534 "ENABLED" : "DISABLED") <=0)
2536 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
2538 "DISABLED" : "ENABLED") <= 0)
2543 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2545 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2546 obd->obd_recovery_start) <= 0)
2548 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2549 cfs_time_current_sec() >=
2550 obd->obd_recovery_start +
2551 obd->obd_recovery_timeout ? 0 :
2552 obd->obd_recovery_start +
2553 obd->obd_recovery_timeout -
2554 cfs_time_current_sec()) <= 0)
2556 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2557 cfs_atomic_read(&obd->obd_connected_clients),
2558 obd->obd_max_recoverable_clients) <= 0)
2560 /* Number of clients that have completed recovery */
2561 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2562 cfs_atomic_read(&obd->obd_req_replay_clients))
2565 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2566 cfs_atomic_read(&obd->obd_lock_replay_clients))
2569 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2570 cfs_atomic_read(&obd->obd_connected_clients) -
2571 cfs_atomic_read(&obd->obd_lock_replay_clients))
2574 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2575 obd->obd_stale_clients) <= 0)
2577 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2578 obd->obd_replayed_requests) <= 0)
2580 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2581 obd->obd_requests_queued_for_recovery) <= 0)
2584 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2585 obd->obd_next_recovery_transno) <= 0)
2591 return min(count, len - (int)off);
2593 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2595 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
2596 int count, int *eof, void *data)
2598 struct obd_device *obd = (struct obd_device *)data;
2599 LASSERT(obd != NULL);
2601 return snprintf(page, count, "%d\n",
2602 obd->obd_recovery_ir_factor);
2604 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
2606 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
2607 unsigned long count, void *data)
2609 struct obd_device *obd = (struct obd_device *)data;
2611 LASSERT(obd != NULL);
2613 rc = lprocfs_write_helper(buffer, count, &val);
2617 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
2620 obd->obd_recovery_ir_factor = val;
2623 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
2625 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
2626 int count, int *eof, void *data)
2628 struct obd_device *obd = (struct obd_device *)data;
2629 LASSERT(obd != NULL);
2631 return snprintf(page, count, "%d\n",
2632 obd->obd_recovery_timeout);
2634 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
2636 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
2637 unsigned long count, void *data)
2639 struct obd_device *obd = (struct obd_device *)data;
2641 LASSERT(obd != NULL);
2643 rc = lprocfs_write_helper(buffer, count, &val);
2647 obd->obd_recovery_timeout = val;
2650 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
2652 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
2653 int count, int *eof, void *data)
2655 struct obd_device *obd = data;
2656 LASSERT(obd != NULL);
2658 return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
2660 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
2662 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
2663 unsigned long count, void *data)
2665 struct obd_device *obd = data;
2667 LASSERT(obd != NULL);
2669 rc = lprocfs_write_helper(buffer, count, &val);
2673 obd->obd_recovery_time_hard = val;
2676 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
2678 int lprocfs_obd_rd_mntdev(char *page, char **start, off_t off,
2679 int count, int *eof, void *data)
2681 struct obd_device *obd = (struct obd_device *)data;
2683 LASSERT(obd != NULL);
2684 LASSERT(mnt_get_devname(obd->u.obt.obt_vfsmnt));
2686 return snprintf(page, count, "%s\n",
2687 mnt_get_devname(obd->u.obt.obt_vfsmnt));
2689 EXPORT_SYMBOL(lprocfs_obd_rd_mntdev);
2691 int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
2692 int count, int *eof, void *data)
2694 struct obd_device *dev = data;
2695 struct client_obd *cli = &dev->u.cli;
2698 client_obd_list_lock(&cli->cl_loi_list_lock);
2699 rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
2700 client_obd_list_unlock(&cli->cl_loi_list_lock);
2703 EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
2705 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
2706 int count, int *eof, void *data)
2708 struct obd_device *obd = (struct obd_device *)data;
2709 struct obd_device_target *target = &obd->u.obt;
2711 LASSERT(obd != NULL);
2712 LASSERT(target->obt_magic == OBT_MAGIC);
2714 return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
2716 EXPORT_SYMBOL(lprocfs_target_rd_instance);