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",
1020 int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
1025 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
1027 ret += snprintf(page + ret, count - ret, "%s%s",
1028 ret ? sep : "", obd_connect_names[i]);
1030 if (flags & ~(mask - 1))
1031 ret += snprintf(page + ret, count - ret,
1032 "%sunknown flags "LPX64,
1033 ret ? sep : "", flags & ~(mask - 1));
1036 EXPORT_SYMBOL(obd_connect_flags2str);
1038 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
1039 int *eof, void *data)
1041 struct lprocfs_counter ret;
1042 struct obd_device *obd = (struct obd_device *)data;
1043 struct obd_import *imp;
1044 struct obd_import_conn *conn;
1045 int i, j, k, rw = 0;
1047 LASSERT(obd != NULL);
1048 LPROCFS_CLIMP_CHECK(obd);
1049 imp = obd->u.cli.cl_import;
1052 i = snprintf(page, count,
1058 " connect_flags: [",
1061 ptlrpc_import_state_name(imp->imp_state),
1062 imp->imp_connect_data.ocd_instance);
1063 i += obd_connect_flags2str(page + i, count - i,
1064 imp->imp_connect_data.ocd_connect_flags,
1066 i += snprintf(page + i, count - i,
1068 " import_flags: [");
1069 i += obd_import_flags2str(imp, page + i, count - i);
1071 i += snprintf(page + i, count - i,
1074 " failover_nids: [");
1075 cfs_spin_lock(&imp->imp_lock);
1077 cfs_list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
1078 i += snprintf(page + i, count - i, "%s%s", j ? ", " : "",
1079 libcfs_nid2str(conn->oic_conn->c_peer.nid));
1082 i += snprintf(page + i, count - i,
1084 " current_connection: %s\n"
1085 " connection_attempts: %u\n"
1087 " in-progress_invalidations: %u\n",
1088 imp->imp_connection == NULL ? "<none>" :
1089 libcfs_nid2str(imp->imp_connection->c_peer.nid),
1091 imp->imp_generation,
1092 cfs_atomic_read(&imp->imp_inval_count));
1093 cfs_spin_unlock(&imp->imp_lock);
1095 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
1096 if (ret.lc_count != 0) {
1097 /* first argument to do_div MUST be __u64 */
1098 __u64 sum = ret.lc_sum;
1099 do_div(sum, ret.lc_count);
1103 i += snprintf(page + i, count - i,
1106 " unregistering: %u\n"
1108 " avg_waittime: "LPU64" %s\n",
1109 cfs_atomic_read(&imp->imp_inflight),
1110 cfs_atomic_read(&imp->imp_unregistering),
1111 cfs_atomic_read(&imp->imp_timeouts),
1112 ret.lc_sum, ret.lc_units);
1115 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
1116 if (imp->imp_at.iat_portal[j] == 0)
1118 k = max_t(unsigned int, k,
1119 at_get(&imp->imp_at.iat_service_estimate[j]));
1121 i += snprintf(page + i, count - i,
1122 " service_estimates:\n"
1123 " services: %u sec\n"
1124 " network: %u sec\n",
1126 at_get(&imp->imp_at.iat_net_latency));
1128 i += snprintf(page + i, count - i,
1130 " last_replay: "LPU64"\n"
1131 " peer_committed: "LPU64"\n"
1132 " last_checked: "LPU64"\n",
1133 imp->imp_last_replay_transno,
1134 imp->imp_peer_committed_transno,
1135 imp->imp_last_transno_checked);
1137 /* avg data rates */
1138 for (rw = 0; rw <= 1; rw++) {
1139 lprocfs_stats_collect(obd->obd_svc_stats,
1140 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
1142 if (ret.lc_sum > 0 && ret.lc_count > 0) {
1143 /* first argument to do_div MUST be __u64 */
1144 __u64 sum = ret.lc_sum;
1145 do_div(sum, ret.lc_count);
1147 i += snprintf(page + i, count - i,
1148 " %s_data_averages:\n"
1149 " bytes_per_rpc: "LPU64"\n",
1150 rw ? "write" : "read",
1153 k = (int)ret.lc_sum;
1154 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
1155 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
1156 if (ret.lc_sum > 0 && ret.lc_count != 0) {
1157 /* first argument to do_div MUST be __u64 */
1158 __u64 sum = ret.lc_sum;
1159 do_div(sum, ret.lc_count);
1161 i += snprintf(page + i, count - i,
1162 " %s_per_rpc: "LPU64"\n",
1163 ret.lc_units, ret.lc_sum);
1164 j = (int)ret.lc_sum;
1166 i += snprintf(page + i, count - i,
1167 " MB_per_sec: %u.%.02u\n",
1168 k / j, (100 * k / j) % 100);
1172 LPROCFS_CLIMP_EXIT(obd);
1175 EXPORT_SYMBOL(lprocfs_rd_import);
1177 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
1178 int *eof, void *data)
1180 struct obd_device *obd = (struct obd_device *)data;
1181 struct obd_import *imp;
1184 LASSERT(obd != NULL);
1185 LPROCFS_CLIMP_CHECK(obd);
1186 imp = obd->u.cli.cl_import;
1189 i = snprintf(page, count, "current_state: %s\n",
1190 ptlrpc_import_state_name(imp->imp_state));
1191 i += snprintf(page + i, count - i,
1192 "state_history:\n");
1193 k = imp->imp_state_hist_idx;
1194 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
1195 struct import_state_hist *ish =
1196 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
1197 if (ish->ish_state == 0)
1199 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
1201 ptlrpc_import_state_name(ish->ish_state));
1204 LPROCFS_CLIMP_EXIT(obd);
1207 EXPORT_SYMBOL(lprocfs_rd_state);
1209 int lprocfs_at_hist_helper(char *page, int count, int rc,
1210 struct adaptive_timeout *at)
1213 for (i = 0; i < AT_BINS; i++)
1214 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
1215 rc += snprintf(page + rc, count - rc, "\n");
1218 EXPORT_SYMBOL(lprocfs_at_hist_helper);
1220 /* See also ptlrpc_lprocfs_rd_timeouts */
1221 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
1222 int *eof, void *data)
1224 struct obd_device *obd = (struct obd_device *)data;
1225 struct obd_import *imp;
1226 unsigned int cur, worst;
1231 LASSERT(obd != NULL);
1232 LPROCFS_CLIMP_CHECK(obd);
1233 imp = obd->u.cli.cl_import;
1236 now = cfs_time_current_sec();
1238 /* Some network health info for kicks */
1239 s2dhms(&ts, now - imp->imp_last_reply_time);
1240 rc += snprintf(page + rc, count - rc,
1241 "%-10s : %ld, "DHMS_FMT" ago\n",
1242 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
1244 cur = at_get(&imp->imp_at.iat_net_latency);
1245 worst = imp->imp_at.iat_net_latency.at_worst_ever;
1246 worstt = imp->imp_at.iat_net_latency.at_worst_time;
1247 s2dhms(&ts, now - worstt);
1248 rc += snprintf(page + rc, count - rc,
1249 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
1250 "network", cur, worst, worstt, DHMS_VARS(&ts));
1251 rc = lprocfs_at_hist_helper(page, count, rc,
1252 &imp->imp_at.iat_net_latency);
1254 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
1255 if (imp->imp_at.iat_portal[i] == 0)
1257 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
1258 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
1259 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
1260 s2dhms(&ts, now - worstt);
1261 rc += snprintf(page + rc, count - rc,
1262 "portal %-2d : cur %3u worst %3u (at %ld, "
1263 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
1264 cur, worst, worstt, DHMS_VARS(&ts));
1265 rc = lprocfs_at_hist_helper(page, count, rc,
1266 &imp->imp_at.iat_service_estimate[i]);
1269 LPROCFS_CLIMP_EXIT(obd);
1272 EXPORT_SYMBOL(lprocfs_rd_timeouts);
1274 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1275 int count, int *eof, void *data)
1277 struct obd_device *obd = data;
1281 LPROCFS_CLIMP_CHECK(obd);
1282 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1283 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1284 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1285 ret += snprintf(page + ret, count - ret, "\n");
1286 LPROCFS_CLIMP_EXIT(obd);
1289 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1291 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1292 int *eof, void *data)
1294 struct obd_device *obd = data;
1296 LASSERT(obd != NULL);
1298 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1300 EXPORT_SYMBOL(lprocfs_rd_num_exports);
1302 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1303 int *eof, void *data)
1305 struct obd_type *class = (struct obd_type*) data;
1307 LASSERT(class != NULL);
1309 return snprintf(page, count, "%d\n", class->typ_refcnt);
1311 EXPORT_SYMBOL(lprocfs_rd_numrefs);
1313 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1317 LASSERT(obd != NULL);
1318 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1319 LASSERT(obd->obd_type->typ_procroot != NULL);
1321 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1322 obd->obd_type->typ_procroot,
1324 if (IS_ERR(obd->obd_proc_entry)) {
1325 rc = PTR_ERR(obd->obd_proc_entry);
1326 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1327 obd->obd_proc_entry = NULL;
1331 EXPORT_SYMBOL(lprocfs_obd_setup);
1333 int lprocfs_obd_cleanup(struct obd_device *obd)
1337 if (obd->obd_proc_exports_entry) {
1338 /* Should be no exports left */
1339 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1340 lprocfs_remove(&obd->obd_proc_exports_entry);
1341 obd->obd_proc_exports_entry = NULL;
1343 if (obd->obd_proc_entry) {
1344 lprocfs_remove(&obd->obd_proc_entry);
1345 obd->obd_proc_entry = NULL;
1349 EXPORT_SYMBOL(lprocfs_obd_cleanup);
1351 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1353 CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
1354 client_stat->nid_proc, client_stat->nid_stats,
1355 client_stat->nid_brw_stats);
1357 LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
1358 "nid %s:count %d\n", libcfs_nid2str(client_stat->nid),
1359 atomic_read(&client_stat->nid_exp_ref_count));
1361 if (client_stat->nid_proc)
1362 lprocfs_remove(&client_stat->nid_proc);
1364 if (client_stat->nid_stats)
1365 lprocfs_free_stats(&client_stat->nid_stats);
1367 if (client_stat->nid_brw_stats)
1368 OBD_FREE_PTR(client_stat->nid_brw_stats);
1370 if (client_stat->nid_ldlm_stats)
1371 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1373 OBD_FREE_PTR(client_stat);
1378 void lprocfs_free_per_client_stats(struct obd_device *obd)
1380 cfs_hash_t *hash = obd->obd_nid_stats_hash;
1381 struct nid_stat *stat;
1384 /* we need extra list - because hash_exit called to early */
1385 /* not need locking because all clients is died */
1386 while (!cfs_list_empty(&obd->obd_nid_stats)) {
1387 stat = cfs_list_entry(obd->obd_nid_stats.next,
1388 struct nid_stat, nid_list);
1389 cfs_list_del_init(&stat->nid_list);
1390 cfs_hash_del(hash, &stat->nid, &stat->nid_hash);
1391 lprocfs_free_client_stats(stat);
1395 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
1397 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1398 enum lprocfs_stats_flags flags)
1400 struct lprocfs_stats *stats;
1401 unsigned int percpusize;
1402 unsigned int num_entry;
1407 if (lprocfs_no_percpu_stats != 0)
1408 flags |= LPROCFS_STATS_FLAG_NOPERCPU;
1410 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1413 num_entry = cfs_num_possible_cpus() + 1;
1415 /* alloc percpu pointers for all possible cpu slots */
1416 OBD_ALLOC(stats, offsetof(struct lprocfs_stats, ls_percpu[num_entry]));
1420 stats->ls_num = num;
1421 stats->ls_biggest_alloc_num = 1;
1422 stats->ls_flags = flags;
1423 cfs_spin_lock_init(&stats->ls_lock);
1425 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
1427 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1429 /* for no percpu area, the 0th entry is for real use,
1430 * for percpu area, the 0th entry is for intialized entry template */
1431 OBD_ALLOC(stats->ls_percpu[0], percpusize);
1432 if (stats->ls_percpu[0] == NULL) {
1434 offsetof(struct lprocfs_stats, ls_percpu[num_entry]));
1439 EXPORT_SYMBOL(lprocfs_alloc_stats);
1441 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1443 struct lprocfs_stats *stats = *statsh;
1444 unsigned int num_entry;
1445 unsigned int percpusize;
1448 if (stats == NULL || stats->ls_num == 0)
1452 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1455 num_entry = cfs_num_possible_cpus() + 1;
1457 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
1459 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1460 for (i = 0; i < num_entry; i++)
1461 if (stats->ls_percpu[i] != NULL)
1462 OBD_FREE(stats->ls_percpu[i], percpusize);
1463 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1465 EXPORT_SYMBOL(lprocfs_free_stats);
1467 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1469 struct lprocfs_counter *percpu_cntr;
1472 unsigned int num_entry;
1473 unsigned long flags = 0;
1475 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1477 for (i = 0; i < num_entry; i++) {
1478 if (stats->ls_percpu[i] == NULL)
1480 for (j = 0; j < stats->ls_num; j++) {
1481 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
1482 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_entry);
1483 percpu_cntr->lc_count = 0;
1484 percpu_cntr->lc_sum = 0;
1485 percpu_cntr->lc_min = LC_MIN_INIT;
1486 percpu_cntr->lc_max = 0;
1487 percpu_cntr->lc_sumsquare = 0;
1488 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_exit);
1492 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1494 EXPORT_SYMBOL(lprocfs_clear_stats);
1496 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1497 size_t len, loff_t *off)
1499 struct seq_file *seq = file->private_data;
1500 struct lprocfs_stats *stats = seq->private;
1502 lprocfs_clear_stats(stats);
1507 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1509 struct lprocfs_stats *stats = p->private;
1510 /* return 1st cpu location */
1511 return (*pos >= stats->ls_num) ? NULL :
1512 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1515 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1519 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1521 struct lprocfs_stats *stats = p->private;
1523 return (*pos >= stats->ls_num) ? NULL :
1524 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1527 /* seq file export of one lprocfs counter */
1528 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1530 struct lprocfs_stats *stats = p->private;
1531 struct lprocfs_counter *cntr = v;
1532 struct lprocfs_counter ret;
1535 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
1537 cfs_gettimeofday(&now);
1538 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1539 "snapshot_time", now.tv_sec, now.tv_usec);
1543 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
1545 lprocfs_stats_collect(stats, idx, &ret);
1547 if (ret.lc_count == 0)
1550 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", cntr->lc_name,
1551 ret.lc_count, cntr->lc_units);
1556 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
1557 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1558 ret.lc_min, ret.lc_max, ret.lc_sum);
1561 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
1562 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1566 rc = seq_printf(p, "\n");
1568 return (rc < 0) ? rc : 0;
1571 struct seq_operations lprocfs_stats_seq_sops = {
1572 start: lprocfs_stats_seq_start,
1573 stop: lprocfs_stats_seq_stop,
1574 next: lprocfs_stats_seq_next,
1575 show: lprocfs_stats_seq_show,
1578 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1580 struct proc_dir_entry *dp = PDE(inode);
1581 struct seq_file *seq;
1584 if (LPROCFS_ENTRY_AND_CHECK(dp))
1587 rc = seq_open(file, &lprocfs_stats_seq_sops);
1592 seq = file->private_data;
1593 seq->private = dp->data;
1597 struct file_operations lprocfs_stats_seq_fops = {
1598 .owner = THIS_MODULE,
1599 .open = lprocfs_stats_seq_open,
1601 .write = lprocfs_stats_seq_write,
1602 .llseek = seq_lseek,
1603 .release = lprocfs_seq_release,
1606 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1607 struct lprocfs_stats *stats)
1609 struct proc_dir_entry *entry;
1610 LASSERT(root != NULL);
1612 LPROCFS_WRITE_ENTRY();
1613 entry = create_proc_entry(name, 0644, root);
1615 entry->proc_fops = &lprocfs_stats_seq_fops;
1616 entry->data = stats;
1619 LPROCFS_WRITE_EXIT();
1626 EXPORT_SYMBOL(lprocfs_register_stats);
1628 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1629 unsigned conf, const char *name, const char *units)
1631 struct lprocfs_counter *c = &(stats->ls_percpu[0]->lp_cntr[index]);
1632 unsigned long flags = 0;
1634 LASSERT(stats != NULL);
1635 LASSERT(stats->ls_percpu[0] != NULL);
1637 lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1638 c->lc_config = conf;
1641 c->lc_min = LC_MIN_INIT;
1644 c->lc_units = units;
1645 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1647 EXPORT_SYMBOL(lprocfs_counter_init);
1649 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1651 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1652 LASSERT(coffset < stats->ls_num); \
1653 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1656 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1658 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1659 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1660 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1661 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1662 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1663 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1664 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1665 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1666 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1667 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1668 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1669 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1670 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1671 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1672 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1673 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1674 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1675 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1676 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
1677 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1678 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1679 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1680 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1681 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1682 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1683 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1684 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1685 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1686 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1687 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1688 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1689 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1690 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1691 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1692 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1693 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1694 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1695 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1696 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1697 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1698 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1699 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1700 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1701 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1702 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
1703 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1704 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1705 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1706 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1707 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1708 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1709 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1710 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1711 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1712 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1713 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1714 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1715 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1716 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1717 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1718 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1719 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1720 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1721 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1722 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1723 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1724 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1725 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1727 EXPORT_SYMBOL(lprocfs_init_ops_stats);
1729 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1731 struct lprocfs_stats *stats;
1732 unsigned int num_stats;
1735 LASSERT(obd->obd_stats == NULL);
1736 LASSERT(obd->obd_proc_entry != NULL);
1737 LASSERT(obd->obd_cntr_base == 0);
1739 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1740 num_private_stats - 1 /* o_owner */;
1741 stats = lprocfs_alloc_stats(num_stats, 0);
1745 lprocfs_init_ops_stats(num_private_stats, stats);
1747 for (i = num_private_stats; i < num_stats; i++) {
1748 /* If this LBUGs, it is likely that an obd
1749 * operation was added to struct obd_ops in
1750 * <obd.h>, and that the corresponding line item
1751 * LPROCFS_OBD_OP_INIT(.., .., opname)
1752 * is missing from the list above. */
1753 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1754 "Missing obd_stat initializer obd_op "
1755 "operation at offset %d.\n", i - num_private_stats);
1757 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1759 lprocfs_free_stats(&stats);
1761 obd->obd_stats = stats;
1762 obd->obd_cntr_base = num_private_stats;
1766 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
1768 void lprocfs_free_obd_stats(struct obd_device *obd)
1771 lprocfs_free_stats(&obd->obd_stats);
1773 EXPORT_SYMBOL(lprocfs_free_obd_stats);
1775 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1777 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1778 LASSERT(coffset < stats->ls_num); \
1779 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1782 void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats)
1784 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1785 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1786 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
1787 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1788 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1789 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1790 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1791 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1792 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1793 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1794 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1795 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1796 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1797 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1798 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1799 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1800 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1801 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1802 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1803 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1804 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1805 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1806 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1807 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1808 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1809 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1810 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1811 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1812 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1813 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1814 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1815 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1817 EXPORT_SYMBOL(lprocfs_init_mps_stats);
1819 int lprocfs_alloc_md_stats(struct obd_device *obd,
1820 unsigned num_private_stats)
1822 struct lprocfs_stats *stats;
1823 unsigned int num_stats;
1826 LASSERT(obd->md_stats == NULL);
1827 LASSERT(obd->obd_proc_entry != NULL);
1828 LASSERT(obd->md_cntr_base == 0);
1830 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1832 stats = lprocfs_alloc_stats(num_stats, 0);
1836 lprocfs_init_mps_stats(num_private_stats, stats);
1838 for (i = num_private_stats; i < num_stats; i++) {
1839 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1840 CERROR("Missing md_stat initializer md_op "
1841 "operation at offset %d. Aborting.\n",
1842 i - num_private_stats);
1846 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1848 lprocfs_free_stats(&stats);
1850 obd->md_stats = stats;
1851 obd->md_cntr_base = num_private_stats;
1855 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
1857 void lprocfs_free_md_stats(struct obd_device *obd)
1859 struct lprocfs_stats *stats = obd->md_stats;
1861 if (stats != NULL) {
1862 obd->md_stats = NULL;
1863 obd->md_cntr_base = 0;
1864 lprocfs_free_stats(&stats);
1867 EXPORT_SYMBOL(lprocfs_free_md_stats);
1869 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1871 lprocfs_counter_init(ldlm_stats,
1872 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1873 0, "ldlm_enqueue", "reqs");
1874 lprocfs_counter_init(ldlm_stats,
1875 LDLM_CONVERT - LDLM_FIRST_OPC,
1876 0, "ldlm_convert", "reqs");
1877 lprocfs_counter_init(ldlm_stats,
1878 LDLM_CANCEL - LDLM_FIRST_OPC,
1879 0, "ldlm_cancel", "reqs");
1880 lprocfs_counter_init(ldlm_stats,
1881 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1882 0, "ldlm_bl_callback", "reqs");
1883 lprocfs_counter_init(ldlm_stats,
1884 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1885 0, "ldlm_cp_callback", "reqs");
1886 lprocfs_counter_init(ldlm_stats,
1887 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1888 0, "ldlm_gl_callback", "reqs");
1890 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
1892 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1893 int *eof, void *data)
1895 struct obd_export *exp = data;
1896 LASSERT(exp != NULL);
1898 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1901 struct exp_uuid_cb_data {
1909 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1910 int count, int *eof, int *len)
1912 cb_data->page = page;
1913 cb_data->count = count;
1918 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1919 cfs_hlist_node_t *hnode, void *cb_data)
1922 struct obd_export *exp = cfs_hash_object(hs, hnode);
1923 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1925 if (exp->exp_nid_stats)
1926 *data->len += snprintf((data->page + *data->len),
1927 data->count, "%s\n",
1928 obd_uuid2str(&exp->exp_client_uuid));
1932 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1933 int *eof, void *data)
1935 struct nid_stat *stats = (struct nid_stat *)data;
1936 struct exp_uuid_cb_data cb_data;
1937 struct obd_device *obd = stats->nid_obd;
1942 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1943 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1944 lprocfs_exp_print_uuid, &cb_data);
1945 return (*cb_data.len);
1948 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1949 cfs_hlist_node_t *hnode, void *cb_data)
1952 struct exp_uuid_cb_data *data = cb_data;
1953 struct obd_export *exp = cfs_hash_object(hs, hnode);
1955 if (exp->exp_lock_hash != NULL) {
1957 *data->len += cfs_hash_debug_header(data->page,
1960 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1967 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1968 int *eof, void *data)
1970 struct nid_stat *stats = (struct nid_stat *)data;
1971 struct exp_uuid_cb_data cb_data;
1972 struct obd_device *obd = stats->nid_obd;
1977 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1979 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1980 lprocfs_exp_print_hash, &cb_data);
1981 return (*cb_data.len);
1984 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1985 int count, int *eof, void *data)
1988 return snprintf(page, count, "%s\n",
1989 "Write into this file to clear all nid stats and "
1990 "stale nid entries");
1992 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1994 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1996 struct nid_stat *stat = obj;
2000 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
2001 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 1) {
2002 /* object has only hash references. */
2003 cfs_spin_lock(&stat->nid_obd->obd_nid_lock);
2004 cfs_list_move(&stat->nid_list, data);
2005 cfs_spin_unlock(&stat->nid_obd->obd_nid_lock);
2008 /* we has reference to object - only clear data*/
2009 if (stat->nid_stats)
2010 lprocfs_clear_stats(stat->nid_stats);
2012 if (stat->nid_brw_stats) {
2013 for (i = 0; i < BRW_LAST; i++)
2014 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
2019 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
2020 unsigned long count, void *data)
2022 struct obd_device *obd = (struct obd_device *)data;
2023 struct nid_stat *client_stat;
2024 CFS_LIST_HEAD(free_list);
2026 cfs_hash_cond_del(obd->obd_nid_stats_hash,
2027 lprocfs_nid_stats_clear_write_cb, &free_list);
2029 while (!cfs_list_empty(&free_list)) {
2030 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
2032 cfs_list_del_init(&client_stat->nid_list);
2033 lprocfs_free_client_stats(client_stat);
2038 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
2040 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
2042 struct nid_stat *new_stat, *old_stat;
2043 struct obd_device *obd = NULL;
2044 cfs_proc_dir_entry_t *entry;
2045 char *buffer = NULL;
2051 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
2052 !exp->exp_obd->obd_nid_stats_hash)
2055 /* not test against zero because eric say:
2056 * You may only test nid against another nid, or LNET_NID_ANY.
2057 * Anything else is nonsense.*/
2058 if (!nid || *nid == LNET_NID_ANY)
2063 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
2065 OBD_ALLOC_PTR(new_stat);
2066 if (new_stat == NULL)
2069 new_stat->nid = *nid;
2070 new_stat->nid_obd = exp->exp_obd;
2071 /* we need set default refcount to 1 to balance obd_disconnect */
2072 cfs_atomic_set(&new_stat->nid_exp_ref_count, 1);
2074 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
2075 nid, &new_stat->nid_hash);
2076 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
2077 old_stat, libcfs_nid2str(*nid),
2078 cfs_atomic_read(&new_stat->nid_exp_ref_count));
2080 /* We need to release old stats because lprocfs_exp_cleanup() hasn't
2081 * been and will never be called. */
2082 if (exp->exp_nid_stats) {
2083 nidstat_putref(exp->exp_nid_stats);
2084 exp->exp_nid_stats = NULL;
2087 /* Return -EALREADY here so that we know that the /proc
2088 * entry already has been created */
2089 if (old_stat != new_stat) {
2090 exp->exp_nid_stats = old_stat;
2091 GOTO(destroy_new, rc = -EALREADY);
2093 /* not found - create */
2094 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
2096 GOTO(destroy_new, rc = -ENOMEM);
2098 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
2099 new_stat->nid_proc = lprocfs_register(buffer,
2100 obd->obd_proc_exports_entry,
2102 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
2104 if (new_stat->nid_proc == NULL) {
2105 CERROR("Error making export directory for nid %s\n",
2106 libcfs_nid2str(*nid));
2107 GOTO(destroy_new_ns, rc = -ENOMEM);
2110 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
2111 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
2112 if (IS_ERR(entry)) {
2113 CWARN("Error adding the NID stats file\n");
2114 rc = PTR_ERR(entry);
2115 GOTO(destroy_new_ns, rc);
2118 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
2119 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
2120 if (IS_ERR(entry)) {
2121 CWARN("Error adding the hash file\n");
2122 rc = PTR_ERR(entry);
2123 GOTO(destroy_new_ns, rc);
2126 exp->exp_nid_stats = new_stat;
2128 /* protect competitive add to list, not need locking on destroy */
2129 cfs_spin_lock(&obd->obd_nid_lock);
2130 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
2131 cfs_spin_unlock(&obd->obd_nid_lock);
2136 if (new_stat->nid_proc != NULL)
2137 lprocfs_remove(&new_stat->nid_proc);
2138 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
2141 nidstat_putref(new_stat);
2142 OBD_FREE_PTR(new_stat);
2145 EXPORT_SYMBOL(lprocfs_exp_setup);
2147 int lprocfs_exp_cleanup(struct obd_export *exp)
2149 struct nid_stat *stat = exp->exp_nid_stats;
2151 if(!stat || !exp->exp_obd)
2154 nidstat_putref(exp->exp_nid_stats);
2155 exp->exp_nid_stats = NULL;
2159 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2161 int lprocfs_write_helper(const char *buffer, unsigned long count,
2164 return lprocfs_write_frac_helper(buffer, count, val, 1);
2166 EXPORT_SYMBOL(lprocfs_write_helper);
2168 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
2171 char kernbuf[20], *end, *pbuf;
2173 if (count > (sizeof(kernbuf) - 1))
2176 if (cfs_copy_from_user(kernbuf, buffer, count))
2179 kernbuf[count] = '\0';
2186 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2190 if (end != NULL && *end == '.') {
2191 int temp_val, pow = 1;
2195 if (strlen(pbuf) > 5)
2196 pbuf[5] = '\0'; /*only allow 5bits fractional*/
2198 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2201 for (i = 0; i < (end - pbuf); i++)
2204 *val += temp_val / pow;
2209 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2211 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
2214 long decimal_val, frac_val;
2220 decimal_val = val / mult;
2221 prtn = snprintf(buffer, count, "%ld", decimal_val);
2222 frac_val = val % mult;
2224 if (prtn < (count - 4) && frac_val > 0) {
2226 int i, temp_mult = 1, frac_bits = 0;
2228 temp_frac = frac_val * 10;
2229 buffer[prtn++] = '.';
2230 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
2231 /* only reserved 2 bits fraction */
2232 buffer[prtn++] ='0';
2237 * Need to think these cases :
2238 * 1. #echo x.00 > /proc/xxx output result : x
2239 * 2. #echo x.0x > /proc/xxx output result : x.0x
2240 * 3. #echo x.x0 > /proc/xxx output result : x.x
2241 * 4. #echo x.xx > /proc/xxx output result : x.xx
2242 * Only reserved 2 bits fraction.
2244 for (i = 0; i < (5 - prtn); i++)
2247 frac_bits = min((int)count - prtn, 3 - frac_bits);
2248 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
2249 frac_val * temp_mult / mult);
2252 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
2254 if (buffer[prtn] == '.') {
2261 buffer[prtn++] ='\n';
2264 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2266 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
2268 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
2270 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2272 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
2273 __u64 *val, int mult)
2275 char kernbuf[22], *end, *pbuf;
2276 __u64 whole, frac = 0, units;
2277 unsigned frac_d = 1;
2279 if (count > (sizeof(kernbuf) - 1))
2282 if (cfs_copy_from_user(kernbuf, buffer, count))
2285 kernbuf[count] = '\0';
2292 whole = simple_strtoull(pbuf, &end, 10);
2296 if (end != NULL && *end == '.') {
2300 /* need to limit frac_d to a __u32 */
2301 if (strlen(pbuf) > 10)
2304 frac = simple_strtoull(pbuf, &end, 10);
2305 /* count decimal places */
2306 for (i = 0; i < (end - pbuf); i++)
2323 /* Specified units override the multiplier */
2325 mult = mult < 0 ? -units : units;
2328 do_div(frac, frac_d);
2329 *val = whole * mult + frac;
2332 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2334 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent, char *name, mode_t mode,
2335 struct file_operations *seq_fops, void *data)
2337 struct proc_dir_entry *entry;
2340 LPROCFS_WRITE_ENTRY();
2341 entry = create_proc_entry(name, mode, parent);
2343 entry->proc_fops = seq_fops;
2346 LPROCFS_WRITE_EXIT();
2353 EXPORT_SYMBOL(lprocfs_seq_create);
2355 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
2357 struct file_operations *seq_fops,
2360 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2361 mode, seq_fops, data));
2363 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2365 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2367 if (value >= OBD_HIST_MAX)
2368 value = OBD_HIST_MAX - 1;
2370 cfs_spin_lock(&oh->oh_lock);
2371 oh->oh_buckets[value]++;
2372 cfs_spin_unlock(&oh->oh_lock);
2374 EXPORT_SYMBOL(lprocfs_oh_tally);
2376 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2380 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2383 lprocfs_oh_tally(oh, val);
2385 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2387 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2389 unsigned long ret = 0;
2392 for (i = 0; i < OBD_HIST_MAX; i++)
2393 ret += oh->oh_buckets[i];
2396 EXPORT_SYMBOL(lprocfs_oh_sum);
2398 void lprocfs_oh_clear(struct obd_histogram *oh)
2400 cfs_spin_lock(&oh->oh_lock);
2401 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2402 cfs_spin_unlock(&oh->oh_lock);
2404 EXPORT_SYMBOL(lprocfs_oh_clear);
2406 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2407 int count, int *eof, void *data)
2409 struct obd_device *obd = data;
2415 c += cfs_hash_debug_header(page, count);
2416 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2417 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2418 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2422 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2424 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2425 int count, int *eof, void *data)
2427 struct obd_device *obd = data;
2430 LASSERT(obd != NULL);
2431 LASSERT(count >= 0);
2433 /* Set start of user data returned to
2434 page + off since the user may have
2435 requested to read much smaller than
2436 what we need to read */
2437 *start = page + off;
2439 /* We know we are allocated a page here.
2440 Also we know that this function will
2441 not need to write more than a page
2442 so we can truncate at CFS_PAGE_SIZE. */
2443 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2445 /* Initialize the page */
2446 memset(page, 0, size);
2448 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2450 if (obd->obd_max_recoverable_clients == 0) {
2451 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2457 /* sampled unlocked, but really... */
2458 if (obd->obd_recovering == 0) {
2459 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2461 if (lprocfs_obd_snprintf(&page, size, &len,
2462 "recovery_start: %lu\n",
2463 obd->obd_recovery_start) <= 0)
2465 if (lprocfs_obd_snprintf(&page, size, &len,
2466 "recovery_duration: %lu\n",
2467 obd->obd_recovery_end -
2468 obd->obd_recovery_start) <= 0)
2470 /* Number of clients that have completed recovery */
2471 if (lprocfs_obd_snprintf(&page, size, &len,
2472 "completed_clients: %d/%d\n",
2473 obd->obd_max_recoverable_clients -
2474 obd->obd_stale_clients,
2475 obd->obd_max_recoverable_clients) <= 0)
2477 if (lprocfs_obd_snprintf(&page, size, &len,
2478 "replayed_requests: %d\n",
2479 obd->obd_replayed_requests) <= 0)
2481 if (lprocfs_obd_snprintf(&page, size, &len,
2482 "last_transno: "LPD64"\n",
2483 obd->obd_next_recovery_transno - 1)<=0)
2485 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2486 obd->obd_version_recov ?
2487 "ENABLED" : "DISABLED") <=0)
2489 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
2491 "DISABLED" : "ENABLED") <= 0)
2496 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2498 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2499 obd->obd_recovery_start) <= 0)
2501 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2502 cfs_time_current_sec() >=
2503 obd->obd_recovery_start +
2504 obd->obd_recovery_timeout ? 0 :
2505 obd->obd_recovery_start +
2506 obd->obd_recovery_timeout -
2507 cfs_time_current_sec()) <= 0)
2509 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2510 cfs_atomic_read(&obd->obd_connected_clients),
2511 obd->obd_max_recoverable_clients) <= 0)
2513 /* Number of clients that have completed recovery */
2514 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2515 cfs_atomic_read(&obd->obd_req_replay_clients))
2518 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2519 cfs_atomic_read(&obd->obd_lock_replay_clients))
2522 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2523 cfs_atomic_read(&obd->obd_connected_clients) -
2524 cfs_atomic_read(&obd->obd_lock_replay_clients))
2527 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2528 obd->obd_stale_clients) <= 0)
2530 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2531 obd->obd_replayed_requests) <= 0)
2533 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2534 obd->obd_requests_queued_for_recovery) <= 0)
2537 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2538 obd->obd_next_recovery_transno) <= 0)
2544 return min(count, len - (int)off);
2546 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2548 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
2549 int count, int *eof, void *data)
2551 struct obd_device *obd = (struct obd_device *)data;
2552 LASSERT(obd != NULL);
2554 return snprintf(page, count, "%d\n",
2555 obd->obd_recovery_ir_factor);
2557 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
2559 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
2560 unsigned long count, void *data)
2562 struct obd_device *obd = (struct obd_device *)data;
2564 LASSERT(obd != NULL);
2566 rc = lprocfs_write_helper(buffer, count, &val);
2570 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
2573 obd->obd_recovery_ir_factor = val;
2576 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
2578 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
2579 int count, int *eof, void *data)
2581 struct obd_device *obd = (struct obd_device *)data;
2582 LASSERT(obd != NULL);
2584 return snprintf(page, count, "%d\n",
2585 obd->obd_recovery_timeout);
2587 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
2589 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
2590 unsigned long count, void *data)
2592 struct obd_device *obd = (struct obd_device *)data;
2594 LASSERT(obd != NULL);
2596 rc = lprocfs_write_helper(buffer, count, &val);
2600 obd->obd_recovery_timeout = val;
2603 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
2605 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
2606 int count, int *eof, void *data)
2608 struct obd_device *obd = data;
2609 LASSERT(obd != NULL);
2611 return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
2613 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
2615 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
2616 unsigned long count, void *data)
2618 struct obd_device *obd = data;
2620 LASSERT(obd != NULL);
2622 rc = lprocfs_write_helper(buffer, count, &val);
2626 obd->obd_recovery_time_hard = val;
2629 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
2631 int lprocfs_obd_rd_mntdev(char *page, char **start, off_t off,
2632 int count, int *eof, void *data)
2634 struct obd_device *obd = (struct obd_device *)data;
2636 LASSERT(obd != NULL);
2637 LASSERT(mnt_get_devname(obd->u.obt.obt_vfsmnt));
2639 return snprintf(page, count, "%s\n",
2640 mnt_get_devname(obd->u.obt.obt_vfsmnt));
2642 EXPORT_SYMBOL(lprocfs_obd_rd_mntdev);
2644 int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
2645 int count, int *eof, void *data)
2647 struct obd_device *dev = data;
2648 struct client_obd *cli = &dev->u.cli;
2651 client_obd_list_lock(&cli->cl_loi_list_lock);
2652 rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
2653 client_obd_list_unlock(&cli->cl_loi_list_lock);
2656 EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
2658 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
2659 int count, int *eof, void *data)
2661 struct obd_device *obd = (struct obd_device *)data;
2662 struct obd_device_target *target = &obd->u.obt;
2664 LASSERT(obd != NULL);
2665 LASSERT(target->obt_magic == OBT_MAGIC);
2667 return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
2669 EXPORT_SYMBOL(lprocfs_target_rd_instance);