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",
1015 "nanoseconds_times",
1022 int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
1027 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
1029 ret += snprintf(page + ret, count - ret, "%s%s",
1030 ret ? sep : "", obd_connect_names[i]);
1032 if (flags & ~(mask - 1))
1033 ret += snprintf(page + ret, count - ret,
1034 "%sunknown flags "LPX64,
1035 ret ? sep : "", flags & ~(mask - 1));
1038 EXPORT_SYMBOL(obd_connect_flags2str);
1040 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
1041 int *eof, void *data)
1043 struct lprocfs_counter ret;
1044 struct obd_device *obd = (struct obd_device *)data;
1045 struct obd_import *imp;
1046 struct obd_import_conn *conn;
1047 int i, j, k, rw = 0;
1049 LASSERT(obd != NULL);
1050 LPROCFS_CLIMP_CHECK(obd);
1051 imp = obd->u.cli.cl_import;
1054 i = snprintf(page, count,
1060 " connect_flags: [",
1063 ptlrpc_import_state_name(imp->imp_state),
1064 imp->imp_connect_data.ocd_instance);
1065 i += obd_connect_flags2str(page + i, count - i,
1066 imp->imp_connect_data.ocd_connect_flags,
1068 i += snprintf(page + i, count - i,
1070 " import_flags: [");
1071 i += obd_import_flags2str(imp, page + i, count - i);
1073 i += snprintf(page + i, count - i,
1076 " failover_nids: [");
1077 cfs_spin_lock(&imp->imp_lock);
1079 cfs_list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
1080 i += snprintf(page + i, count - i, "%s%s", j ? ", " : "",
1081 libcfs_nid2str(conn->oic_conn->c_peer.nid));
1084 i += snprintf(page + i, count - i,
1086 " current_connection: %s\n"
1087 " connection_attempts: %u\n"
1089 " in-progress_invalidations: %u\n",
1090 imp->imp_connection == NULL ? "<none>" :
1091 libcfs_nid2str(imp->imp_connection->c_peer.nid),
1093 imp->imp_generation,
1094 cfs_atomic_read(&imp->imp_inval_count));
1095 cfs_spin_unlock(&imp->imp_lock);
1097 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
1098 if (ret.lc_count != 0) {
1099 /* first argument to do_div MUST be __u64 */
1100 __u64 sum = ret.lc_sum;
1101 do_div(sum, ret.lc_count);
1105 i += snprintf(page + i, count - i,
1108 " unregistering: %u\n"
1110 " avg_waittime: "LPU64" %s\n",
1111 cfs_atomic_read(&imp->imp_inflight),
1112 cfs_atomic_read(&imp->imp_unregistering),
1113 cfs_atomic_read(&imp->imp_timeouts),
1114 ret.lc_sum, ret.lc_units);
1117 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
1118 if (imp->imp_at.iat_portal[j] == 0)
1120 k = max_t(unsigned int, k,
1121 at_get(&imp->imp_at.iat_service_estimate[j]));
1123 i += snprintf(page + i, count - i,
1124 " service_estimates:\n"
1125 " services: %u sec\n"
1126 " network: %u sec\n",
1128 at_get(&imp->imp_at.iat_net_latency));
1130 i += snprintf(page + i, count - i,
1132 " last_replay: "LPU64"\n"
1133 " peer_committed: "LPU64"\n"
1134 " last_checked: "LPU64"\n",
1135 imp->imp_last_replay_transno,
1136 imp->imp_peer_committed_transno,
1137 imp->imp_last_transno_checked);
1139 /* avg data rates */
1140 for (rw = 0; rw <= 1; rw++) {
1141 lprocfs_stats_collect(obd->obd_svc_stats,
1142 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
1144 if (ret.lc_sum > 0 && ret.lc_count > 0) {
1145 /* first argument to do_div MUST be __u64 */
1146 __u64 sum = ret.lc_sum;
1147 do_div(sum, ret.lc_count);
1149 i += snprintf(page + i, count - i,
1150 " %s_data_averages:\n"
1151 " bytes_per_rpc: "LPU64"\n",
1152 rw ? "write" : "read",
1155 k = (int)ret.lc_sum;
1156 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
1157 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
1158 if (ret.lc_sum > 0 && ret.lc_count != 0) {
1159 /* first argument to do_div MUST be __u64 */
1160 __u64 sum = ret.lc_sum;
1161 do_div(sum, ret.lc_count);
1163 i += snprintf(page + i, count - i,
1164 " %s_per_rpc: "LPU64"\n",
1165 ret.lc_units, ret.lc_sum);
1166 j = (int)ret.lc_sum;
1168 i += snprintf(page + i, count - i,
1169 " MB_per_sec: %u.%.02u\n",
1170 k / j, (100 * k / j) % 100);
1174 LPROCFS_CLIMP_EXIT(obd);
1177 EXPORT_SYMBOL(lprocfs_rd_import);
1179 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
1180 int *eof, void *data)
1182 struct obd_device *obd = (struct obd_device *)data;
1183 struct obd_import *imp;
1186 LASSERT(obd != NULL);
1187 LPROCFS_CLIMP_CHECK(obd);
1188 imp = obd->u.cli.cl_import;
1191 i = snprintf(page, count, "current_state: %s\n",
1192 ptlrpc_import_state_name(imp->imp_state));
1193 i += snprintf(page + i, count - i,
1194 "state_history:\n");
1195 k = imp->imp_state_hist_idx;
1196 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
1197 struct import_state_hist *ish =
1198 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
1199 if (ish->ish_state == 0)
1201 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
1203 ptlrpc_import_state_name(ish->ish_state));
1206 LPROCFS_CLIMP_EXIT(obd);
1209 EXPORT_SYMBOL(lprocfs_rd_state);
1211 int lprocfs_at_hist_helper(char *page, int count, int rc,
1212 struct adaptive_timeout *at)
1215 for (i = 0; i < AT_BINS; i++)
1216 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
1217 rc += snprintf(page + rc, count - rc, "\n");
1220 EXPORT_SYMBOL(lprocfs_at_hist_helper);
1222 /* See also ptlrpc_lprocfs_rd_timeouts */
1223 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
1224 int *eof, void *data)
1226 struct obd_device *obd = (struct obd_device *)data;
1227 struct obd_import *imp;
1228 unsigned int cur, worst;
1233 LASSERT(obd != NULL);
1234 LPROCFS_CLIMP_CHECK(obd);
1235 imp = obd->u.cli.cl_import;
1238 now = cfs_time_current_sec();
1240 /* Some network health info for kicks */
1241 s2dhms(&ts, now - imp->imp_last_reply_time);
1242 rc += snprintf(page + rc, count - rc,
1243 "%-10s : %ld, "DHMS_FMT" ago\n",
1244 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
1246 cur = at_get(&imp->imp_at.iat_net_latency);
1247 worst = imp->imp_at.iat_net_latency.at_worst_ever;
1248 worstt = imp->imp_at.iat_net_latency.at_worst_time;
1249 s2dhms(&ts, now - worstt);
1250 rc += snprintf(page + rc, count - rc,
1251 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
1252 "network", cur, worst, worstt, DHMS_VARS(&ts));
1253 rc = lprocfs_at_hist_helper(page, count, rc,
1254 &imp->imp_at.iat_net_latency);
1256 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
1257 if (imp->imp_at.iat_portal[i] == 0)
1259 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
1260 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
1261 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
1262 s2dhms(&ts, now - worstt);
1263 rc += snprintf(page + rc, count - rc,
1264 "portal %-2d : cur %3u worst %3u (at %ld, "
1265 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
1266 cur, worst, worstt, DHMS_VARS(&ts));
1267 rc = lprocfs_at_hist_helper(page, count, rc,
1268 &imp->imp_at.iat_service_estimate[i]);
1271 LPROCFS_CLIMP_EXIT(obd);
1274 EXPORT_SYMBOL(lprocfs_rd_timeouts);
1276 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1277 int count, int *eof, void *data)
1279 struct obd_device *obd = data;
1283 LPROCFS_CLIMP_CHECK(obd);
1284 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1285 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1286 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1287 ret += snprintf(page + ret, count - ret, "\n");
1288 LPROCFS_CLIMP_EXIT(obd);
1291 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1293 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1294 int *eof, void *data)
1296 struct obd_device *obd = data;
1298 LASSERT(obd != NULL);
1300 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1302 EXPORT_SYMBOL(lprocfs_rd_num_exports);
1304 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1305 int *eof, void *data)
1307 struct obd_type *class = (struct obd_type*) data;
1309 LASSERT(class != NULL);
1311 return snprintf(page, count, "%d\n", class->typ_refcnt);
1313 EXPORT_SYMBOL(lprocfs_rd_numrefs);
1315 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1319 LASSERT(obd != NULL);
1320 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1321 LASSERT(obd->obd_type->typ_procroot != NULL);
1323 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1324 obd->obd_type->typ_procroot,
1326 if (IS_ERR(obd->obd_proc_entry)) {
1327 rc = PTR_ERR(obd->obd_proc_entry);
1328 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1329 obd->obd_proc_entry = NULL;
1333 EXPORT_SYMBOL(lprocfs_obd_setup);
1335 int lprocfs_obd_cleanup(struct obd_device *obd)
1339 if (obd->obd_proc_exports_entry) {
1340 /* Should be no exports left */
1341 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1342 lprocfs_remove(&obd->obd_proc_exports_entry);
1343 obd->obd_proc_exports_entry = NULL;
1345 if (obd->obd_proc_entry) {
1346 lprocfs_remove(&obd->obd_proc_entry);
1347 obd->obd_proc_entry = NULL;
1351 EXPORT_SYMBOL(lprocfs_obd_cleanup);
1353 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1355 CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
1356 client_stat->nid_proc, client_stat->nid_stats,
1357 client_stat->nid_brw_stats);
1359 LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
1360 "nid %s:count %d\n", libcfs_nid2str(client_stat->nid),
1361 atomic_read(&client_stat->nid_exp_ref_count));
1363 if (client_stat->nid_proc)
1364 lprocfs_remove(&client_stat->nid_proc);
1366 if (client_stat->nid_stats)
1367 lprocfs_free_stats(&client_stat->nid_stats);
1369 if (client_stat->nid_brw_stats)
1370 OBD_FREE_PTR(client_stat->nid_brw_stats);
1372 if (client_stat->nid_ldlm_stats)
1373 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1375 OBD_FREE_PTR(client_stat);
1380 void lprocfs_free_per_client_stats(struct obd_device *obd)
1382 cfs_hash_t *hash = obd->obd_nid_stats_hash;
1383 struct nid_stat *stat;
1386 /* we need extra list - because hash_exit called to early */
1387 /* not need locking because all clients is died */
1388 while (!cfs_list_empty(&obd->obd_nid_stats)) {
1389 stat = cfs_list_entry(obd->obd_nid_stats.next,
1390 struct nid_stat, nid_list);
1391 cfs_list_del_init(&stat->nid_list);
1392 cfs_hash_del(hash, &stat->nid, &stat->nid_hash);
1393 lprocfs_free_client_stats(stat);
1397 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
1399 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1400 enum lprocfs_stats_flags flags)
1402 struct lprocfs_stats *stats;
1403 unsigned int percpusize;
1404 unsigned int num_entry;
1409 if (lprocfs_no_percpu_stats != 0)
1410 flags |= LPROCFS_STATS_FLAG_NOPERCPU;
1412 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1415 num_entry = cfs_num_possible_cpus() + 1;
1417 /* alloc percpu pointers for all possible cpu slots */
1418 OBD_ALLOC(stats, offsetof(struct lprocfs_stats, ls_percpu[num_entry]));
1422 stats->ls_num = num;
1423 stats->ls_biggest_alloc_num = 1;
1424 stats->ls_flags = flags;
1425 cfs_spin_lock_init(&stats->ls_lock);
1427 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
1429 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1431 /* for no percpu area, the 0th entry is for real use,
1432 * for percpu area, the 0th entry is for intialized entry template */
1433 OBD_ALLOC(stats->ls_percpu[0], percpusize);
1434 if (stats->ls_percpu[0] == NULL) {
1436 offsetof(struct lprocfs_stats, ls_percpu[num_entry]));
1441 EXPORT_SYMBOL(lprocfs_alloc_stats);
1443 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1445 struct lprocfs_stats *stats = *statsh;
1446 unsigned int num_entry;
1447 unsigned int percpusize;
1450 if (stats == NULL || stats->ls_num == 0)
1454 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1457 num_entry = cfs_num_possible_cpus() + 1;
1459 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
1461 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1462 for (i = 0; i < num_entry; i++)
1463 if (stats->ls_percpu[i] != NULL)
1464 OBD_FREE(stats->ls_percpu[i], percpusize);
1465 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1467 EXPORT_SYMBOL(lprocfs_free_stats);
1469 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1471 struct lprocfs_counter *percpu_cntr;
1474 unsigned int num_entry;
1475 unsigned long flags = 0;
1477 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1479 for (i = 0; i < num_entry; i++) {
1480 if (stats->ls_percpu[i] == NULL)
1482 for (j = 0; j < stats->ls_num; j++) {
1483 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
1484 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_entry);
1485 percpu_cntr->lc_count = 0;
1486 percpu_cntr->lc_sum = 0;
1487 percpu_cntr->lc_min = LC_MIN_INIT;
1488 percpu_cntr->lc_max = 0;
1489 percpu_cntr->lc_sumsquare = 0;
1490 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_exit);
1494 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1496 EXPORT_SYMBOL(lprocfs_clear_stats);
1498 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1499 size_t len, loff_t *off)
1501 struct seq_file *seq = file->private_data;
1502 struct lprocfs_stats *stats = seq->private;
1504 lprocfs_clear_stats(stats);
1509 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1511 struct lprocfs_stats *stats = p->private;
1512 /* return 1st cpu location */
1513 return (*pos >= stats->ls_num) ? NULL :
1514 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1517 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1521 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1523 struct lprocfs_stats *stats = p->private;
1525 return (*pos >= stats->ls_num) ? NULL :
1526 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1529 /* seq file export of one lprocfs counter */
1530 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1532 struct lprocfs_stats *stats = p->private;
1533 struct lprocfs_counter *cntr = v;
1534 struct lprocfs_counter ret;
1537 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
1539 cfs_gettimeofday(&now);
1540 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1541 "snapshot_time", now.tv_sec, now.tv_usec);
1545 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
1547 lprocfs_stats_collect(stats, idx, &ret);
1549 if (ret.lc_count == 0)
1552 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", cntr->lc_name,
1553 ret.lc_count, cntr->lc_units);
1558 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
1559 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1560 ret.lc_min, ret.lc_max, ret.lc_sum);
1563 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
1564 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1568 rc = seq_printf(p, "\n");
1570 return (rc < 0) ? rc : 0;
1573 struct seq_operations lprocfs_stats_seq_sops = {
1574 start: lprocfs_stats_seq_start,
1575 stop: lprocfs_stats_seq_stop,
1576 next: lprocfs_stats_seq_next,
1577 show: lprocfs_stats_seq_show,
1580 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1582 struct proc_dir_entry *dp = PDE(inode);
1583 struct seq_file *seq;
1586 if (LPROCFS_ENTRY_AND_CHECK(dp))
1589 rc = seq_open(file, &lprocfs_stats_seq_sops);
1594 seq = file->private_data;
1595 seq->private = dp->data;
1599 struct file_operations lprocfs_stats_seq_fops = {
1600 .owner = THIS_MODULE,
1601 .open = lprocfs_stats_seq_open,
1603 .write = lprocfs_stats_seq_write,
1604 .llseek = seq_lseek,
1605 .release = lprocfs_seq_release,
1608 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1609 struct lprocfs_stats *stats)
1611 struct proc_dir_entry *entry;
1612 LASSERT(root != NULL);
1614 LPROCFS_WRITE_ENTRY();
1615 entry = create_proc_entry(name, 0644, root);
1617 entry->proc_fops = &lprocfs_stats_seq_fops;
1618 entry->data = stats;
1621 LPROCFS_WRITE_EXIT();
1628 EXPORT_SYMBOL(lprocfs_register_stats);
1630 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1631 unsigned conf, const char *name, const char *units)
1633 struct lprocfs_counter *c = &(stats->ls_percpu[0]->lp_cntr[index]);
1634 unsigned long flags = 0;
1636 LASSERT(stats != NULL);
1637 LASSERT(stats->ls_percpu[0] != NULL);
1639 lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1640 c->lc_config = conf;
1643 c->lc_min = LC_MIN_INIT;
1646 c->lc_units = units;
1647 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1649 EXPORT_SYMBOL(lprocfs_counter_init);
1651 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1653 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1654 LASSERT(coffset < stats->ls_num); \
1655 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1658 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1660 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1661 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1662 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1663 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1664 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1665 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1666 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1667 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1668 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1669 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1670 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1671 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1672 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1673 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1674 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1675 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1676 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1677 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1678 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
1679 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1680 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1681 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1682 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1683 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1684 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1685 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1686 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1687 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1688 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1689 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1690 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1691 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1692 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1693 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1694 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1695 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1696 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1697 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1698 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1699 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1700 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1701 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1702 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1703 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1704 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
1705 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1706 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1707 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1708 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1709 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1710 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1711 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1712 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1713 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1714 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1715 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1716 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1717 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1718 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1719 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1720 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1721 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1722 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1723 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1724 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1725 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1726 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1727 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1729 EXPORT_SYMBOL(lprocfs_init_ops_stats);
1731 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1733 struct lprocfs_stats *stats;
1734 unsigned int num_stats;
1737 LASSERT(obd->obd_stats == NULL);
1738 LASSERT(obd->obd_proc_entry != NULL);
1739 LASSERT(obd->obd_cntr_base == 0);
1741 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1742 num_private_stats - 1 /* o_owner */;
1743 stats = lprocfs_alloc_stats(num_stats, 0);
1747 lprocfs_init_ops_stats(num_private_stats, stats);
1749 for (i = num_private_stats; i < num_stats; i++) {
1750 /* If this LBUGs, it is likely that an obd
1751 * operation was added to struct obd_ops in
1752 * <obd.h>, and that the corresponding line item
1753 * LPROCFS_OBD_OP_INIT(.., .., opname)
1754 * is missing from the list above. */
1755 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1756 "Missing obd_stat initializer obd_op "
1757 "operation at offset %d.\n", i - num_private_stats);
1759 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1761 lprocfs_free_stats(&stats);
1763 obd->obd_stats = stats;
1764 obd->obd_cntr_base = num_private_stats;
1768 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
1770 void lprocfs_free_obd_stats(struct obd_device *obd)
1773 lprocfs_free_stats(&obd->obd_stats);
1775 EXPORT_SYMBOL(lprocfs_free_obd_stats);
1777 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1779 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1780 LASSERT(coffset < stats->ls_num); \
1781 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1784 void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats)
1786 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1787 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1788 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
1789 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1790 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1791 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1792 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1793 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1794 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1795 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1796 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1797 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1798 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1799 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1800 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1801 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1802 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1803 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1804 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1805 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1806 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1807 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1808 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1809 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1810 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1811 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1812 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1813 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1814 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1815 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1816 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1817 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1819 EXPORT_SYMBOL(lprocfs_init_mps_stats);
1821 int lprocfs_alloc_md_stats(struct obd_device *obd,
1822 unsigned num_private_stats)
1824 struct lprocfs_stats *stats;
1825 unsigned int num_stats;
1828 LASSERT(obd->md_stats == NULL);
1829 LASSERT(obd->obd_proc_entry != NULL);
1830 LASSERT(obd->md_cntr_base == 0);
1832 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1834 stats = lprocfs_alloc_stats(num_stats, 0);
1838 lprocfs_init_mps_stats(num_private_stats, stats);
1840 for (i = num_private_stats; i < num_stats; i++) {
1841 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1842 CERROR("Missing md_stat initializer md_op "
1843 "operation at offset %d. Aborting.\n",
1844 i - num_private_stats);
1848 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1850 lprocfs_free_stats(&stats);
1852 obd->md_stats = stats;
1853 obd->md_cntr_base = num_private_stats;
1857 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
1859 void lprocfs_free_md_stats(struct obd_device *obd)
1861 struct lprocfs_stats *stats = obd->md_stats;
1863 if (stats != NULL) {
1864 obd->md_stats = NULL;
1865 obd->md_cntr_base = 0;
1866 lprocfs_free_stats(&stats);
1869 EXPORT_SYMBOL(lprocfs_free_md_stats);
1871 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1873 lprocfs_counter_init(ldlm_stats,
1874 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1875 0, "ldlm_enqueue", "reqs");
1876 lprocfs_counter_init(ldlm_stats,
1877 LDLM_CONVERT - LDLM_FIRST_OPC,
1878 0, "ldlm_convert", "reqs");
1879 lprocfs_counter_init(ldlm_stats,
1880 LDLM_CANCEL - LDLM_FIRST_OPC,
1881 0, "ldlm_cancel", "reqs");
1882 lprocfs_counter_init(ldlm_stats,
1883 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1884 0, "ldlm_bl_callback", "reqs");
1885 lprocfs_counter_init(ldlm_stats,
1886 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1887 0, "ldlm_cp_callback", "reqs");
1888 lprocfs_counter_init(ldlm_stats,
1889 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1890 0, "ldlm_gl_callback", "reqs");
1892 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
1894 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1895 int *eof, void *data)
1897 struct obd_export *exp = data;
1898 LASSERT(exp != NULL);
1900 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1903 struct exp_uuid_cb_data {
1911 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1912 int count, int *eof, int *len)
1914 cb_data->page = page;
1915 cb_data->count = count;
1920 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1921 cfs_hlist_node_t *hnode, void *cb_data)
1924 struct obd_export *exp = cfs_hash_object(hs, hnode);
1925 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1927 if (exp->exp_nid_stats)
1928 *data->len += snprintf((data->page + *data->len),
1929 data->count, "%s\n",
1930 obd_uuid2str(&exp->exp_client_uuid));
1934 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1935 int *eof, void *data)
1937 struct nid_stat *stats = (struct nid_stat *)data;
1938 struct exp_uuid_cb_data cb_data;
1939 struct obd_device *obd = stats->nid_obd;
1944 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1945 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1946 lprocfs_exp_print_uuid, &cb_data);
1947 return (*cb_data.len);
1950 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1951 cfs_hlist_node_t *hnode, void *cb_data)
1954 struct exp_uuid_cb_data *data = cb_data;
1955 struct obd_export *exp = cfs_hash_object(hs, hnode);
1957 if (exp->exp_lock_hash != NULL) {
1959 *data->len += cfs_hash_debug_header(data->page,
1962 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1969 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1970 int *eof, void *data)
1972 struct nid_stat *stats = (struct nid_stat *)data;
1973 struct exp_uuid_cb_data cb_data;
1974 struct obd_device *obd = stats->nid_obd;
1979 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1981 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1982 lprocfs_exp_print_hash, &cb_data);
1983 return (*cb_data.len);
1986 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1987 int count, int *eof, void *data)
1990 return snprintf(page, count, "%s\n",
1991 "Write into this file to clear all nid stats and "
1992 "stale nid entries");
1994 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1996 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1998 struct nid_stat *stat = obj;
2002 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
2003 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 1) {
2004 /* object has only hash references. */
2005 cfs_spin_lock(&stat->nid_obd->obd_nid_lock);
2006 cfs_list_move(&stat->nid_list, data);
2007 cfs_spin_unlock(&stat->nid_obd->obd_nid_lock);
2010 /* we has reference to object - only clear data*/
2011 if (stat->nid_stats)
2012 lprocfs_clear_stats(stat->nid_stats);
2014 if (stat->nid_brw_stats) {
2015 for (i = 0; i < BRW_LAST; i++)
2016 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
2021 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
2022 unsigned long count, void *data)
2024 struct obd_device *obd = (struct obd_device *)data;
2025 struct nid_stat *client_stat;
2026 CFS_LIST_HEAD(free_list);
2028 cfs_hash_cond_del(obd->obd_nid_stats_hash,
2029 lprocfs_nid_stats_clear_write_cb, &free_list);
2031 while (!cfs_list_empty(&free_list)) {
2032 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
2034 cfs_list_del_init(&client_stat->nid_list);
2035 lprocfs_free_client_stats(client_stat);
2040 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
2042 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
2044 struct nid_stat *new_stat, *old_stat;
2045 struct obd_device *obd = NULL;
2046 cfs_proc_dir_entry_t *entry;
2047 char *buffer = NULL;
2053 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
2054 !exp->exp_obd->obd_nid_stats_hash)
2057 /* not test against zero because eric say:
2058 * You may only test nid against another nid, or LNET_NID_ANY.
2059 * Anything else is nonsense.*/
2060 if (!nid || *nid == LNET_NID_ANY)
2065 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
2067 OBD_ALLOC_PTR(new_stat);
2068 if (new_stat == NULL)
2071 new_stat->nid = *nid;
2072 new_stat->nid_obd = exp->exp_obd;
2073 /* we need set default refcount to 1 to balance obd_disconnect */
2074 cfs_atomic_set(&new_stat->nid_exp_ref_count, 1);
2076 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
2077 nid, &new_stat->nid_hash);
2078 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
2079 old_stat, libcfs_nid2str(*nid),
2080 cfs_atomic_read(&new_stat->nid_exp_ref_count));
2082 /* We need to release old stats because lprocfs_exp_cleanup() hasn't
2083 * been and will never be called. */
2084 if (exp->exp_nid_stats) {
2085 nidstat_putref(exp->exp_nid_stats);
2086 exp->exp_nid_stats = NULL;
2089 /* Return -EALREADY here so that we know that the /proc
2090 * entry already has been created */
2091 if (old_stat != new_stat) {
2092 exp->exp_nid_stats = old_stat;
2093 GOTO(destroy_new, rc = -EALREADY);
2095 /* not found - create */
2096 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
2098 GOTO(destroy_new, rc = -ENOMEM);
2100 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
2101 new_stat->nid_proc = lprocfs_register(buffer,
2102 obd->obd_proc_exports_entry,
2104 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
2106 if (new_stat->nid_proc == NULL) {
2107 CERROR("Error making export directory for nid %s\n",
2108 libcfs_nid2str(*nid));
2109 GOTO(destroy_new_ns, rc = -ENOMEM);
2112 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
2113 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
2114 if (IS_ERR(entry)) {
2115 CWARN("Error adding the NID stats file\n");
2116 rc = PTR_ERR(entry);
2117 GOTO(destroy_new_ns, rc);
2120 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
2121 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
2122 if (IS_ERR(entry)) {
2123 CWARN("Error adding the hash file\n");
2124 rc = PTR_ERR(entry);
2125 GOTO(destroy_new_ns, rc);
2128 exp->exp_nid_stats = new_stat;
2130 /* protect competitive add to list, not need locking on destroy */
2131 cfs_spin_lock(&obd->obd_nid_lock);
2132 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
2133 cfs_spin_unlock(&obd->obd_nid_lock);
2138 if (new_stat->nid_proc != NULL)
2139 lprocfs_remove(&new_stat->nid_proc);
2140 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
2143 nidstat_putref(new_stat);
2144 OBD_FREE_PTR(new_stat);
2147 EXPORT_SYMBOL(lprocfs_exp_setup);
2149 int lprocfs_exp_cleanup(struct obd_export *exp)
2151 struct nid_stat *stat = exp->exp_nid_stats;
2153 if(!stat || !exp->exp_obd)
2156 nidstat_putref(exp->exp_nid_stats);
2157 exp->exp_nid_stats = NULL;
2161 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2163 int lprocfs_write_helper(const char *buffer, unsigned long count,
2166 return lprocfs_write_frac_helper(buffer, count, val, 1);
2168 EXPORT_SYMBOL(lprocfs_write_helper);
2170 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
2173 char kernbuf[20], *end, *pbuf;
2175 if (count > (sizeof(kernbuf) - 1))
2178 if (cfs_copy_from_user(kernbuf, buffer, count))
2181 kernbuf[count] = '\0';
2188 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2192 if (end != NULL && *end == '.') {
2193 int temp_val, pow = 1;
2197 if (strlen(pbuf) > 5)
2198 pbuf[5] = '\0'; /*only allow 5bits fractional*/
2200 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2203 for (i = 0; i < (end - pbuf); i++)
2206 *val += temp_val / pow;
2211 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2213 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
2216 long decimal_val, frac_val;
2222 decimal_val = val / mult;
2223 prtn = snprintf(buffer, count, "%ld", decimal_val);
2224 frac_val = val % mult;
2226 if (prtn < (count - 4) && frac_val > 0) {
2228 int i, temp_mult = 1, frac_bits = 0;
2230 temp_frac = frac_val * 10;
2231 buffer[prtn++] = '.';
2232 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
2233 /* only reserved 2 bits fraction */
2234 buffer[prtn++] ='0';
2239 * Need to think these cases :
2240 * 1. #echo x.00 > /proc/xxx output result : x
2241 * 2. #echo x.0x > /proc/xxx output result : x.0x
2242 * 3. #echo x.x0 > /proc/xxx output result : x.x
2243 * 4. #echo x.xx > /proc/xxx output result : x.xx
2244 * Only reserved 2 bits fraction.
2246 for (i = 0; i < (5 - prtn); i++)
2249 frac_bits = min((int)count - prtn, 3 - frac_bits);
2250 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
2251 frac_val * temp_mult / mult);
2254 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
2256 if (buffer[prtn] == '.') {
2263 buffer[prtn++] ='\n';
2266 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2268 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
2270 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
2272 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2274 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
2275 __u64 *val, int mult)
2277 char kernbuf[22], *end, *pbuf;
2278 __u64 whole, frac = 0, units;
2279 unsigned frac_d = 1;
2281 if (count > (sizeof(kernbuf) - 1))
2284 if (cfs_copy_from_user(kernbuf, buffer, count))
2287 kernbuf[count] = '\0';
2294 whole = simple_strtoull(pbuf, &end, 10);
2298 if (end != NULL && *end == '.') {
2302 /* need to limit frac_d to a __u32 */
2303 if (strlen(pbuf) > 10)
2306 frac = simple_strtoull(pbuf, &end, 10);
2307 /* count decimal places */
2308 for (i = 0; i < (end - pbuf); i++)
2325 /* Specified units override the multiplier */
2327 mult = mult < 0 ? -units : units;
2330 do_div(frac, frac_d);
2331 *val = whole * mult + frac;
2334 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2336 static char *lprocfs_strnstr(const char *s1, const char *s2, size_t len)
2345 if (!memcmp(s1, s2, l2))
2353 * Find the string \a name in the input \a buffer, and return a pointer to the
2354 * value immediately following \a name, reducing \a count appropriately.
2355 * If \a name is not found the original \a buffer is returned.
2357 char *lprocfs_find_named_value(const char *buffer, const char *name,
2358 unsigned long *count)
2361 size_t buflen = *count;
2363 /* there is no strnstr() in rhel5 and ubuntu kernels */
2364 val = lprocfs_strnstr(buffer, name, buflen);
2366 return (char *)buffer;
2368 val += strlen(name); /* skip prefix */
2369 while (val < buffer + buflen && isspace(*val)) /* skip separator */
2373 while (val < buffer + buflen && isalnum(*val)) {
2378 return val - *count;
2380 EXPORT_SYMBOL(lprocfs_find_named_value);
2382 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent, char *name, mode_t mode,
2383 struct file_operations *seq_fops, void *data)
2385 struct proc_dir_entry *entry;
2388 LPROCFS_WRITE_ENTRY();
2389 entry = create_proc_entry(name, mode, parent);
2391 entry->proc_fops = seq_fops;
2394 LPROCFS_WRITE_EXIT();
2401 EXPORT_SYMBOL(lprocfs_seq_create);
2403 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
2405 struct file_operations *seq_fops,
2408 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2409 mode, seq_fops, data));
2411 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2413 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2415 if (value >= OBD_HIST_MAX)
2416 value = OBD_HIST_MAX - 1;
2418 cfs_spin_lock(&oh->oh_lock);
2419 oh->oh_buckets[value]++;
2420 cfs_spin_unlock(&oh->oh_lock);
2422 EXPORT_SYMBOL(lprocfs_oh_tally);
2424 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2428 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2431 lprocfs_oh_tally(oh, val);
2433 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2435 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2437 unsigned long ret = 0;
2440 for (i = 0; i < OBD_HIST_MAX; i++)
2441 ret += oh->oh_buckets[i];
2444 EXPORT_SYMBOL(lprocfs_oh_sum);
2446 void lprocfs_oh_clear(struct obd_histogram *oh)
2448 cfs_spin_lock(&oh->oh_lock);
2449 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2450 cfs_spin_unlock(&oh->oh_lock);
2452 EXPORT_SYMBOL(lprocfs_oh_clear);
2454 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2455 int count, int *eof, void *data)
2457 struct obd_device *obd = data;
2463 c += cfs_hash_debug_header(page, count);
2464 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2465 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2466 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2470 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2472 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2473 int count, int *eof, void *data)
2475 struct obd_device *obd = data;
2478 LASSERT(obd != NULL);
2479 LASSERT(count >= 0);
2481 /* Set start of user data returned to
2482 page + off since the user may have
2483 requested to read much smaller than
2484 what we need to read */
2485 *start = page + off;
2487 /* We know we are allocated a page here.
2488 Also we know that this function will
2489 not need to write more than a page
2490 so we can truncate at CFS_PAGE_SIZE. */
2491 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2493 /* Initialize the page */
2494 memset(page, 0, size);
2496 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2498 if (obd->obd_max_recoverable_clients == 0) {
2499 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2505 /* sampled unlocked, but really... */
2506 if (obd->obd_recovering == 0) {
2507 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2509 if (lprocfs_obd_snprintf(&page, size, &len,
2510 "recovery_start: %lu\n",
2511 obd->obd_recovery_start) <= 0)
2513 if (lprocfs_obd_snprintf(&page, size, &len,
2514 "recovery_duration: %lu\n",
2515 obd->obd_recovery_end -
2516 obd->obd_recovery_start) <= 0)
2518 /* Number of clients that have completed recovery */
2519 if (lprocfs_obd_snprintf(&page, size, &len,
2520 "completed_clients: %d/%d\n",
2521 obd->obd_max_recoverable_clients -
2522 obd->obd_stale_clients,
2523 obd->obd_max_recoverable_clients) <= 0)
2525 if (lprocfs_obd_snprintf(&page, size, &len,
2526 "replayed_requests: %d\n",
2527 obd->obd_replayed_requests) <= 0)
2529 if (lprocfs_obd_snprintf(&page, size, &len,
2530 "last_transno: "LPD64"\n",
2531 obd->obd_next_recovery_transno - 1)<=0)
2533 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2534 obd->obd_version_recov ?
2535 "ENABLED" : "DISABLED") <=0)
2537 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
2539 "DISABLED" : "ENABLED") <= 0)
2544 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2546 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2547 obd->obd_recovery_start) <= 0)
2549 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2550 cfs_time_current_sec() >=
2551 obd->obd_recovery_start +
2552 obd->obd_recovery_timeout ? 0 :
2553 obd->obd_recovery_start +
2554 obd->obd_recovery_timeout -
2555 cfs_time_current_sec()) <= 0)
2557 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2558 cfs_atomic_read(&obd->obd_connected_clients),
2559 obd->obd_max_recoverable_clients) <= 0)
2561 /* Number of clients that have completed recovery */
2562 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2563 cfs_atomic_read(&obd->obd_req_replay_clients))
2566 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2567 cfs_atomic_read(&obd->obd_lock_replay_clients))
2570 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2571 cfs_atomic_read(&obd->obd_connected_clients) -
2572 cfs_atomic_read(&obd->obd_lock_replay_clients))
2575 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2576 obd->obd_stale_clients) <= 0)
2578 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2579 obd->obd_replayed_requests) <= 0)
2581 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2582 obd->obd_requests_queued_for_recovery) <= 0)
2585 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2586 obd->obd_next_recovery_transno) <= 0)
2592 return min(count, len - (int)off);
2594 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2596 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
2597 int count, int *eof, void *data)
2599 struct obd_device *obd = (struct obd_device *)data;
2600 LASSERT(obd != NULL);
2602 return snprintf(page, count, "%d\n",
2603 obd->obd_recovery_ir_factor);
2605 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
2607 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
2608 unsigned long count, void *data)
2610 struct obd_device *obd = (struct obd_device *)data;
2612 LASSERT(obd != NULL);
2614 rc = lprocfs_write_helper(buffer, count, &val);
2618 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
2621 obd->obd_recovery_ir_factor = val;
2624 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
2626 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
2627 int count, int *eof, void *data)
2629 struct obd_device *obd = (struct obd_device *)data;
2630 LASSERT(obd != NULL);
2632 return snprintf(page, count, "%d\n",
2633 obd->obd_recovery_timeout);
2635 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
2637 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
2638 unsigned long count, void *data)
2640 struct obd_device *obd = (struct obd_device *)data;
2642 LASSERT(obd != NULL);
2644 rc = lprocfs_write_helper(buffer, count, &val);
2648 obd->obd_recovery_timeout = val;
2651 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
2653 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
2654 int count, int *eof, void *data)
2656 struct obd_device *obd = data;
2657 LASSERT(obd != NULL);
2659 return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
2661 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
2663 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
2664 unsigned long count, void *data)
2666 struct obd_device *obd = data;
2668 LASSERT(obd != NULL);
2670 rc = lprocfs_write_helper(buffer, count, &val);
2674 obd->obd_recovery_time_hard = val;
2677 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
2679 int lprocfs_obd_rd_mntdev(char *page, char **start, off_t off,
2680 int count, int *eof, void *data)
2682 struct obd_device *obd = (struct obd_device *)data;
2684 LASSERT(obd != NULL);
2685 LASSERT(mnt_get_devname(obd->u.obt.obt_vfsmnt));
2687 return snprintf(page, count, "%s\n",
2688 mnt_get_devname(obd->u.obt.obt_vfsmnt));
2690 EXPORT_SYMBOL(lprocfs_obd_rd_mntdev);
2692 int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
2693 int count, int *eof, void *data)
2695 struct obd_device *dev = data;
2696 struct client_obd *cli = &dev->u.cli;
2699 client_obd_list_lock(&cli->cl_loi_list_lock);
2700 rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
2701 client_obd_list_unlock(&cli->cl_loi_list_lock);
2704 EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
2706 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
2707 int count, int *eof, void *data)
2709 struct obd_device *obd = (struct obd_device *)data;
2710 struct obd_device_target *target = &obd->u.obt;
2712 LASSERT(obd != NULL);
2713 LASSERT(target->obt_magic == OBT_MAGIC);
2715 return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
2717 EXPORT_SYMBOL(lprocfs_target_rd_instance);