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_seq_release(struct inode *inode, struct file *file)
69 return seq_release(inode, file);
71 EXPORT_SYMBOL(lprocfs_seq_release);
73 static struct proc_dir_entry *__lprocfs_srch(struct proc_dir_entry *head,
76 struct proc_dir_entry *temp;
82 while (temp != NULL) {
83 if (strcmp(temp->name, name) == 0) {
92 struct proc_dir_entry *lprocfs_srch(struct proc_dir_entry *head,
95 struct proc_dir_entry *temp;
98 temp = __lprocfs_srch(head, name);
102 EXPORT_SYMBOL(lprocfs_srch);
104 /* lprocfs API calls */
106 /* Function that emulates snprintf but also has the side effect of advancing
107 the page pointer for the next write into the buffer, incrementing the total
108 length written to the buffer, and decrementing the size left in the
110 static int lprocfs_obd_snprintf(char **page, int end, int *len,
111 const char *format, ...)
119 va_start(list, format);
120 n = vsnprintf(*page, end - *len, format, list);
123 *page += n; *len += n;
127 cfs_proc_dir_entry_t *lprocfs_add_simple(struct proc_dir_entry *root,
129 read_proc_t *read_proc,
130 write_proc_t *write_proc,
132 struct file_operations *fops)
134 cfs_proc_dir_entry_t *proc;
137 if (root == NULL || name == NULL)
138 return ERR_PTR(-EINVAL);
145 LPROCFS_WRITE_ENTRY();
146 proc = create_proc_entry(name, mode, root);
148 CERROR("LprocFS: No memory to create /proc entry %s", name);
149 LPROCFS_WRITE_EXIT();
150 return ERR_PTR(-ENOMEM);
152 proc->read_proc = read_proc;
153 proc->write_proc = write_proc;
156 proc->proc_fops = fops;
157 LPROCFS_WRITE_EXIT();
160 EXPORT_SYMBOL(lprocfs_add_simple);
162 struct proc_dir_entry *lprocfs_add_symlink(const char *name,
163 struct proc_dir_entry *parent, const char *format, ...)
165 struct proc_dir_entry *entry;
169 if (parent == NULL || format == NULL)
172 OBD_ALLOC_WAIT(dest, MAX_STRING_SIZE + 1);
176 va_start(ap, format);
177 vsnprintf(dest, MAX_STRING_SIZE, format, ap);
180 entry = proc_symlink(name, parent, dest);
182 CERROR("LprocFS: Could not create symbolic link from %s to %s",
185 OBD_FREE(dest, MAX_STRING_SIZE + 1);
188 EXPORT_SYMBOL(lprocfs_add_symlink);
190 static ssize_t lprocfs_fops_read(struct file *f, char __user *buf,
191 size_t size, loff_t *ppos)
193 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
194 char *page, *start = NULL;
195 int rc = 0, eof = 1, count;
197 if (*ppos >= CFS_PAGE_SIZE)
200 page = (char *)__get_free_page(GFP_KERNEL);
204 if (LPROCFS_ENTRY_AND_CHECK(dp)) {
209 OBD_FAIL_TIMEOUT(OBD_FAIL_LPROC_REMOVE, 10);
211 rc = dp->read_proc(page, &start, *ppos, CFS_PAGE_SIZE,
217 /* for lustre proc read, the read count must be less than PAGE_SIZE */
226 start = page + *ppos;
227 } else if (start < page) {
231 count = (rc < size) ? rc : size;
232 if (cfs_copy_to_user(buf, start, count)) {
239 free_page((unsigned long)page);
243 static ssize_t lprocfs_fops_write(struct file *f, const char __user *buf,
244 size_t size, loff_t *ppos)
246 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
249 if (LPROCFS_ENTRY_AND_CHECK(dp))
252 rc = dp->write_proc(f, buf, size, dp->data);
257 static struct file_operations lprocfs_generic_fops = {
258 .owner = THIS_MODULE,
259 .read = lprocfs_fops_read,
260 .write = lprocfs_fops_write,
263 int lprocfs_evict_client_open(struct inode *inode, struct file *f)
265 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
266 struct obd_device *obd = dp->data;
268 cfs_atomic_inc(&obd->obd_evict_inprogress);
273 int lprocfs_evict_client_release(struct inode *inode, struct file *f)
275 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
276 struct obd_device *obd = dp->data;
278 cfs_atomic_dec(&obd->obd_evict_inprogress);
279 cfs_waitq_signal(&obd->obd_evict_inprogress_waitq);
284 struct file_operations lprocfs_evict_client_fops = {
285 .owner = THIS_MODULE,
286 .read = lprocfs_fops_read,
287 .write = lprocfs_fops_write,
288 .open = lprocfs_evict_client_open,
289 .release = lprocfs_evict_client_release,
291 EXPORT_SYMBOL(lprocfs_evict_client_fops);
296 * \param root [in] The parent proc entry on which new entry will be added.
297 * \param list [in] Array of proc entries to be added.
298 * \param data [in] The argument to be passed when entries read/write routines
299 * are called through /proc file.
301 * \retval 0 on success
304 int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list,
309 if (root == NULL || list == NULL)
312 LPROCFS_WRITE_ENTRY();
313 while (list->name != NULL) {
314 struct proc_dir_entry *cur_root, *proc;
315 char *pathcopy, *cur, *next, pathbuf[64];
316 int pathsize = strlen(list->name) + 1;
321 /* need copy of path for strsep */
322 if (strlen(list->name) > sizeof(pathbuf) - 1) {
323 OBD_ALLOC(pathcopy, pathsize);
324 if (pathcopy == NULL)
325 GOTO(out, rc = -ENOMEM);
331 strcpy(pathcopy, list->name);
333 while (cur_root != NULL && (cur = strsep(&next, "/"))) {
334 if (*cur =='\0') /* skip double/trailing "/" */
337 proc = __lprocfs_srch(cur_root, cur);
338 CDEBUG(D_OTHER, "cur_root=%s, cur=%s, next=%s, (%s)\n",
339 cur_root->name, cur, next,
340 (proc ? "exists" : "new"));
342 cur_root = (proc ? proc :
343 proc_mkdir(cur, cur_root));
344 } else if (proc == NULL) {
346 if (list->proc_mode != 0000) {
347 mode = list->proc_mode;
351 if (list->write_fptr)
354 proc = create_proc_entry(cur, mode, cur_root);
358 if (pathcopy != pathbuf)
359 OBD_FREE(pathcopy, pathsize);
361 if (cur_root == NULL || proc == NULL) {
362 CERROR("LprocFS: No memory to create /proc entry %s",
364 GOTO(out, rc = -ENOMEM);
368 proc->proc_fops = list->fops;
370 proc->proc_fops = &lprocfs_generic_fops;
371 proc->read_proc = list->read_fptr;
372 proc->write_proc = list->write_fptr;
373 proc->data = (list->data ? list->data : data);
377 LPROCFS_WRITE_EXIT();
380 EXPORT_SYMBOL(lprocfs_add_vars);
382 void lprocfs_remove_nolock(struct proc_dir_entry **rooth)
384 struct proc_dir_entry *root = *rooth;
385 struct proc_dir_entry *temp = root;
386 struct proc_dir_entry *rm_entry;
387 struct proc_dir_entry *parent;
393 parent = root->parent;
394 LASSERT(parent != NULL);
397 while (temp->subdir != NULL)
403 /* Memory corruption once caused this to fail, and
404 without this LASSERT we would loop here forever. */
405 LASSERTF(strlen(rm_entry->name) == rm_entry->namelen,
406 "0x%p %s/%s len %d\n", rm_entry, temp->name,
407 rm_entry->name, (int)strlen(rm_entry->name));
409 #ifdef HAVE_PROCFS_USERS
410 /* if procfs uses user count to synchronize deletion of
411 * proc entry, there is no protection for rm_entry->data,
412 * then lprocfs_fops_read and lprocfs_fops_write maybe
413 * call proc_dir_entry->read_proc (or write_proc) with
414 * proc_dir_entry->data == NULL, then cause kernel Oops.
415 * see bug19706 for detailed information */
417 /* procfs won't free rm_entry->data if it isn't a LINK,
418 * and Lustre won't use rm_entry->data if it is a LINK */
419 if (S_ISLNK(rm_entry->mode))
420 rm_entry->data = NULL;
422 /* Now, the rm_entry->deleted flags is protected
423 * by _lprocfs_lock. */
424 rm_entry->data = NULL;
426 remove_proc_entry(rm_entry->name, temp);
432 void lprocfs_remove(struct proc_dir_entry **rooth)
434 LPROCFS_WRITE_ENTRY(); /* search vs remove race */
435 lprocfs_remove_nolock(rooth);
436 LPROCFS_WRITE_EXIT();
438 EXPORT_SYMBOL(lprocfs_remove);
440 void lprocfs_remove_proc_entry(const char *name, struct proc_dir_entry *parent)
442 LASSERT(parent != NULL);
443 remove_proc_entry(name, parent);
445 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
447 void lprocfs_try_remove_proc_entry(const char *name,
448 struct proc_dir_entry *parent)
450 struct proc_dir_entry *t = NULL;
451 struct proc_dir_entry **p;
454 LASSERT(parent != NULL);
457 LPROCFS_WRITE_ENTRY();
459 /* lookup target name */
460 for (p = &parent->subdir; *p; p = &(*p)->next) {
461 if ((*p)->namelen != len)
463 if (memcmp(name, (*p)->name, len))
470 /* verify it's empty: do not count "num_refs" */
471 for (p = &t->subdir; *p; p = &(*p)->next) {
472 if ((*p)->namelen != strlen("num_refs")) {
476 if (memcmp("num_refs", (*p)->name,
477 strlen("num_refs"))) {
485 lprocfs_remove_nolock(&t);
487 LPROCFS_WRITE_EXIT();
491 EXPORT_SYMBOL(lprocfs_try_remove_proc_entry);
493 struct proc_dir_entry *lprocfs_register(const char *name,
494 struct proc_dir_entry *parent,
495 struct lprocfs_vars *list, void *data)
497 struct proc_dir_entry *newchild;
499 newchild = lprocfs_srch(parent, name);
500 if (newchild != NULL) {
501 CERROR(" Lproc: Attempting to register %s more than once \n",
503 return ERR_PTR(-EALREADY);
506 newchild = proc_mkdir(name, parent);
507 if (newchild != NULL && list != NULL) {
508 int rc = lprocfs_add_vars(newchild, list, data);
510 lprocfs_remove(&newchild);
516 EXPORT_SYMBOL(lprocfs_register);
518 /* Generic callbacks */
519 int lprocfs_rd_uint(char *page, char **start, off_t off,
520 int count, int *eof, void *data)
522 unsigned int *temp = data;
523 return snprintf(page, count, "%u\n", *temp);
525 EXPORT_SYMBOL(lprocfs_rd_uint);
527 int lprocfs_wr_uint(struct file *file, const char *buffer,
528 unsigned long count, void *data)
531 char dummy[MAX_STRING_SIZE + 1], *end;
534 dummy[MAX_STRING_SIZE] = '\0';
535 if (cfs_copy_from_user(dummy, buffer, MAX_STRING_SIZE))
538 tmp = simple_strtoul(dummy, &end, 0);
542 *p = (unsigned int)tmp;
545 EXPORT_SYMBOL(lprocfs_wr_uint);
547 int lprocfs_rd_u64(char *page, char **start, off_t off,
548 int count, int *eof, void *data)
550 LASSERT(data != NULL);
552 return snprintf(page, count, LPU64"\n", *(__u64 *)data);
554 EXPORT_SYMBOL(lprocfs_rd_u64);
556 int lprocfs_rd_atomic(char *page, char **start, off_t off,
557 int count, int *eof, void *data)
559 cfs_atomic_t *atom = data;
560 LASSERT(atom != NULL);
562 return snprintf(page, count, "%d\n", cfs_atomic_read(atom));
564 EXPORT_SYMBOL(lprocfs_rd_atomic);
566 int lprocfs_wr_atomic(struct file *file, const char *buffer,
567 unsigned long count, void *data)
569 cfs_atomic_t *atm = data;
573 rc = lprocfs_write_helper(buffer, count, &val);
580 cfs_atomic_set(atm, val);
583 EXPORT_SYMBOL(lprocfs_wr_atomic);
585 int lprocfs_rd_uuid(char *page, char **start, off_t off, int count,
586 int *eof, void *data)
588 struct obd_device *obd = data;
590 LASSERT(obd != NULL);
592 return snprintf(page, count, "%s\n", obd->obd_uuid.uuid);
594 EXPORT_SYMBOL(lprocfs_rd_uuid);
596 int lprocfs_rd_name(char *page, char **start, off_t off, int count,
597 int *eof, void *data)
599 struct obd_device *dev = data;
601 LASSERT(dev != NULL);
602 LASSERT(dev->obd_name != NULL);
604 return snprintf(page, count, "%s\n", dev->obd_name);
606 EXPORT_SYMBOL(lprocfs_rd_name);
608 int lprocfs_rd_fstype(char *page, char **start, off_t off, int count, int *eof,
611 struct obd_device *obd = data;
613 LASSERT(obd != NULL);
614 LASSERT(obd->obd_fsops != NULL);
615 LASSERT(obd->obd_fsops->fs_type != NULL);
616 return snprintf(page, count, "%s\n", obd->obd_fsops->fs_type);
618 EXPORT_SYMBOL(lprocfs_rd_fstype);
620 int lprocfs_rd_blksize(char *page, char **start, off_t off, int count,
621 int *eof, void *data)
623 struct obd_device *obd = data;
624 struct obd_statfs osfs;
625 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
626 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
630 rc = snprintf(page, count, "%u\n", osfs.os_bsize);
634 EXPORT_SYMBOL(lprocfs_rd_blksize);
636 int lprocfs_osd_rd_blksize(char *page, char **start, off_t off,
637 int count, int *eof, void *data)
639 struct dt_device *dt = data;
640 struct obd_statfs osfs;
641 int rc = dt_statfs(NULL, dt, &osfs);
644 rc = snprintf(page, count, "%d\n",
645 (unsigned) osfs.os_bsize);
649 EXPORT_SYMBOL(lprocfs_osd_rd_blksize);
651 int lprocfs_rd_kbytestotal(char *page, char **start, off_t off, int count,
652 int *eof, void *data)
654 struct obd_device *obd = data;
655 struct obd_statfs osfs;
656 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
657 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
660 __u32 blk_size = osfs.os_bsize >> 10;
661 __u64 result = osfs.os_blocks;
663 while (blk_size >>= 1)
667 rc = snprintf(page, count, LPU64"\n", result);
671 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
673 int lprocfs_osd_rd_kbytestotal(char *page, char **start, off_t off,
674 int count, int *eof, void *data)
676 struct dt_device *dt = data;
677 struct obd_statfs osfs;
678 int rc = dt_statfs(NULL, dt, &osfs);
680 __u32 blk_size = osfs.os_bsize >> 10;
681 __u64 result = osfs.os_blocks;
683 while (blk_size >>= 1)
687 rc = snprintf(page, count, LPU64"\n", result);
691 EXPORT_SYMBOL(lprocfs_osd_rd_kbytestotal);
693 int lprocfs_rd_kbytesfree(char *page, char **start, off_t off, int count,
694 int *eof, void *data)
696 struct obd_device *obd = data;
697 struct obd_statfs osfs;
698 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
699 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
702 __u32 blk_size = osfs.os_bsize >> 10;
703 __u64 result = osfs.os_bfree;
705 while (blk_size >>= 1)
709 rc = snprintf(page, count, LPU64"\n", result);
713 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
715 int lprocfs_osd_rd_kbytesfree(char *page, char **start, off_t off,
716 int count, int *eof, void *data)
718 struct dt_device *dt = data;
719 struct obd_statfs osfs;
720 int rc = dt_statfs(NULL, dt, &osfs);
722 __u32 blk_size = osfs.os_bsize >> 10;
723 __u64 result = osfs.os_bfree;
725 while (blk_size >>= 1)
729 rc = snprintf(page, count, LPU64"\n", result);
733 EXPORT_SYMBOL(lprocfs_osd_rd_kbytesfree);
735 int lprocfs_rd_kbytesavail(char *page, char **start, off_t off, int count,
736 int *eof, void *data)
738 struct obd_device *obd = data;
739 struct obd_statfs osfs;
740 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
741 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
744 __u32 blk_size = osfs.os_bsize >> 10;
745 __u64 result = osfs.os_bavail;
747 while (blk_size >>= 1)
751 rc = snprintf(page, count, LPU64"\n", result);
755 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
757 int lprocfs_osd_rd_kbytesavail(char *page, char **start, off_t off,
758 int count, int *eof, void *data)
760 struct dt_device *dt = data;
761 struct obd_statfs osfs;
762 int rc = dt_statfs(NULL, dt, &osfs);
764 __u32 blk_size = osfs.os_bsize >> 10;
765 __u64 result = osfs.os_bavail;
767 while (blk_size >>= 1)
771 rc = snprintf(page, count, LPU64"\n", result);
775 EXPORT_SYMBOL(lprocfs_osd_rd_kbytesavail);
777 int lprocfs_rd_filestotal(char *page, char **start, off_t off, int count,
778 int *eof, void *data)
780 struct obd_device *obd = data;
781 struct obd_statfs osfs;
782 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
783 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
787 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
792 EXPORT_SYMBOL(lprocfs_rd_filestotal);
794 int lprocfs_osd_rd_filestotal(char *page, char **start, off_t off,
795 int count, int *eof, void *data)
797 struct dt_device *dt = data;
798 struct obd_statfs osfs;
799 int rc = dt_statfs(NULL, dt, &osfs);
802 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
807 EXPORT_SYMBOL(lprocfs_osd_rd_filestotal);
809 int lprocfs_rd_filesfree(char *page, char **start, off_t off, int count,
810 int *eof, void *data)
812 struct obd_device *obd = data;
813 struct obd_statfs osfs;
814 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
815 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
819 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
823 EXPORT_SYMBOL(lprocfs_rd_filesfree);
825 int lprocfs_osd_rd_filesfree(char *page, char **start, off_t off,
826 int count, int *eof, void *data)
828 struct dt_device *dt = data;
829 struct obd_statfs osfs;
830 int rc = dt_statfs(NULL, dt, &osfs);
833 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
837 EXPORT_SYMBOL(lprocfs_osd_rd_filesfree);
839 int lprocfs_rd_server_uuid(char *page, char **start, off_t off, int count,
840 int *eof, void *data)
842 struct obd_device *obd = data;
843 struct obd_import *imp;
844 char *imp_state_name = NULL;
847 LASSERT(obd != NULL);
848 LPROCFS_CLIMP_CHECK(obd);
849 imp = obd->u.cli.cl_import;
850 imp_state_name = ptlrpc_import_state_name(imp->imp_state);
852 rc = snprintf(page, count, "%s\t%s%s\n",
853 obd2cli_tgt(obd), imp_state_name,
854 imp->imp_deactive ? "\tDEACTIVATED" : "");
856 LPROCFS_CLIMP_EXIT(obd);
859 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
861 int lprocfs_rd_conn_uuid(char *page, char **start, off_t off, int count,
862 int *eof, void *data)
864 struct obd_device *obd = data;
865 struct ptlrpc_connection *conn;
868 LASSERT(obd != NULL);
870 LPROCFS_CLIMP_CHECK(obd);
871 conn = obd->u.cli.cl_import->imp_connection;
873 if (conn && obd->u.cli.cl_import) {
874 rc = snprintf(page, count, "%s\n",
875 conn->c_remote_uuid.uuid);
877 rc = snprintf(page, count, "%s\n", "<none>");
880 LPROCFS_CLIMP_EXIT(obd);
883 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
885 /** add up per-cpu counters */
886 void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
887 struct lprocfs_counter *cnt)
889 unsigned int num_entry;
890 struct lprocfs_counter t;
891 struct lprocfs_counter *percpu_cntr;
894 unsigned long flags = 0;
896 memset(cnt, 0, sizeof(*cnt));
899 /* set count to 1 to avoid divide-by-zero errs in callers */
904 cnt->lc_min = LC_MIN_INIT;
906 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
908 for (i = 0; i < num_entry; i++) {
909 if (stats->ls_percpu[i] == NULL)
911 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[idx];
914 centry = cfs_atomic_read(&percpu_cntr-> \
916 t.lc_count = percpu_cntr->lc_count;
917 t.lc_sum = percpu_cntr->lc_sum;
918 t.lc_min = percpu_cntr->lc_min;
919 t.lc_max = percpu_cntr->lc_max;
920 t.lc_sumsquare = percpu_cntr->lc_sumsquare;
921 } while (centry != cfs_atomic_read(&percpu_cntr->lc_cntl. \
923 centry != cfs_atomic_read(&percpu_cntr->lc_cntl. \
925 cnt->lc_count += t.lc_count;
926 cnt->lc_sum += t.lc_sum;
927 if (t.lc_min < cnt->lc_min)
928 cnt->lc_min = t.lc_min;
929 if (t.lc_max > cnt->lc_max)
930 cnt->lc_max = t.lc_max;
931 cnt->lc_sumsquare += t.lc_sumsquare;
934 cnt->lc_units = stats->ls_percpu[0]->lp_cntr[idx].lc_units;
935 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
937 EXPORT_SYMBOL(lprocfs_stats_collect);
940 * Append a space separated list of current set flags to str.
942 #define flag2str(flag) \
943 if (imp->imp_##flag && max - len > 0) \
944 len += snprintf(str + len, max - len, "%s" #flag, len ? ", " : "");
945 static int obd_import_flags2str(struct obd_import *imp, char *str, int max)
949 if (imp->imp_obd->obd_no_recov)
950 len += snprintf(str, max - len, "no_recov");
954 flag2str(replayable);
960 static const char *obd_connect_names[] = {
974 "join_file(obsolete)",
978 "remote_client_by_force",
987 "mds_mds_connection",
990 "alt_checksum_algorithm",
1006 "nanoseconds_times",
1013 int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
1018 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
1020 ret += snprintf(page + ret, count - ret, "%s%s",
1021 ret ? sep : "", obd_connect_names[i]);
1023 if (flags & ~(mask - 1))
1024 ret += snprintf(page + ret, count - ret,
1025 "%sunknown flags "LPX64,
1026 ret ? sep : "", flags & ~(mask - 1));
1029 EXPORT_SYMBOL(obd_connect_flags2str);
1031 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
1032 int *eof, void *data)
1034 struct lprocfs_counter ret;
1035 struct obd_device *obd = (struct obd_device *)data;
1036 struct obd_import *imp;
1037 struct obd_import_conn *conn;
1038 int i, j, k, rw = 0;
1040 LASSERT(obd != NULL);
1041 LPROCFS_CLIMP_CHECK(obd);
1042 imp = obd->u.cli.cl_import;
1045 i = snprintf(page, count,
1051 " connect_flags: [",
1054 ptlrpc_import_state_name(imp->imp_state),
1055 imp->imp_connect_data.ocd_instance);
1056 i += obd_connect_flags2str(page + i, count - i,
1057 imp->imp_connect_data.ocd_connect_flags,
1059 i += snprintf(page + i, count - i,
1061 " import_flags: [");
1062 i += obd_import_flags2str(imp, page + i, count - i);
1064 i += snprintf(page + i, count - i,
1067 " failover_nids: [");
1068 cfs_spin_lock(&imp->imp_lock);
1070 cfs_list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
1071 i += snprintf(page + i, count - i, "%s%s", j ? ", " : "",
1072 libcfs_nid2str(conn->oic_conn->c_peer.nid));
1075 i += snprintf(page + i, count - i,
1077 " current_connection: %s\n"
1078 " connection_attempts: %u\n"
1080 " in-progress_invalidations: %u\n",
1081 imp->imp_connection == NULL ? "<none>" :
1082 libcfs_nid2str(imp->imp_connection->c_peer.nid),
1084 imp->imp_generation,
1085 cfs_atomic_read(&imp->imp_inval_count));
1086 cfs_spin_unlock(&imp->imp_lock);
1088 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
1089 if (ret.lc_count != 0) {
1090 /* first argument to do_div MUST be __u64 */
1091 __u64 sum = ret.lc_sum;
1092 do_div(sum, ret.lc_count);
1096 i += snprintf(page + i, count - i,
1099 " unregistering: %u\n"
1101 " avg_waittime: "LPU64" %s\n",
1102 cfs_atomic_read(&imp->imp_inflight),
1103 cfs_atomic_read(&imp->imp_unregistering),
1104 cfs_atomic_read(&imp->imp_timeouts),
1105 ret.lc_sum, ret.lc_units);
1108 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
1109 if (imp->imp_at.iat_portal[j] == 0)
1111 k = max_t(unsigned int, k,
1112 at_get(&imp->imp_at.iat_service_estimate[j]));
1114 i += snprintf(page + i, count - i,
1115 " service_estimates:\n"
1116 " services: %u sec\n"
1117 " network: %u sec\n",
1119 at_get(&imp->imp_at.iat_net_latency));
1121 i += snprintf(page + i, count - i,
1123 " last_replay: "LPU64"\n"
1124 " peer_committed: "LPU64"\n"
1125 " last_checked: "LPU64"\n",
1126 imp->imp_last_replay_transno,
1127 imp->imp_peer_committed_transno,
1128 imp->imp_last_transno_checked);
1130 /* avg data rates */
1131 for (rw = 0; rw <= 1; rw++) {
1132 lprocfs_stats_collect(obd->obd_svc_stats,
1133 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
1135 if (ret.lc_sum > 0 && ret.lc_count > 0) {
1136 /* first argument to do_div MUST be __u64 */
1137 __u64 sum = ret.lc_sum;
1138 do_div(sum, ret.lc_count);
1140 i += snprintf(page + i, count - i,
1141 " %s_data_averages:\n"
1142 " bytes_per_rpc: "LPU64"\n",
1143 rw ? "write" : "read",
1146 k = (int)ret.lc_sum;
1147 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
1148 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
1149 if (ret.lc_sum > 0 && ret.lc_count != 0) {
1150 /* first argument to do_div MUST be __u64 */
1151 __u64 sum = ret.lc_sum;
1152 do_div(sum, ret.lc_count);
1154 i += snprintf(page + i, count - i,
1155 " %s_per_rpc: "LPU64"\n",
1156 ret.lc_units, ret.lc_sum);
1157 j = (int)ret.lc_sum;
1159 i += snprintf(page + i, count - i,
1160 " MB_per_sec: %u.%.02u\n",
1161 k / j, (100 * k / j) % 100);
1165 LPROCFS_CLIMP_EXIT(obd);
1168 EXPORT_SYMBOL(lprocfs_rd_import);
1170 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
1171 int *eof, void *data)
1173 struct obd_device *obd = (struct obd_device *)data;
1174 struct obd_import *imp;
1177 LASSERT(obd != NULL);
1178 LPROCFS_CLIMP_CHECK(obd);
1179 imp = obd->u.cli.cl_import;
1182 i = snprintf(page, count, "current_state: %s\n",
1183 ptlrpc_import_state_name(imp->imp_state));
1184 i += snprintf(page + i, count - i,
1185 "state_history:\n");
1186 k = imp->imp_state_hist_idx;
1187 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
1188 struct import_state_hist *ish =
1189 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
1190 if (ish->ish_state == 0)
1192 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
1194 ptlrpc_import_state_name(ish->ish_state));
1197 LPROCFS_CLIMP_EXIT(obd);
1200 EXPORT_SYMBOL(lprocfs_rd_state);
1202 int lprocfs_at_hist_helper(char *page, int count, int rc,
1203 struct adaptive_timeout *at)
1206 for (i = 0; i < AT_BINS; i++)
1207 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
1208 rc += snprintf(page + rc, count - rc, "\n");
1211 EXPORT_SYMBOL(lprocfs_at_hist_helper);
1213 /* See also ptlrpc_lprocfs_rd_timeouts */
1214 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
1215 int *eof, void *data)
1217 struct obd_device *obd = (struct obd_device *)data;
1218 struct obd_import *imp;
1219 unsigned int cur, worst;
1224 LASSERT(obd != NULL);
1225 LPROCFS_CLIMP_CHECK(obd);
1226 imp = obd->u.cli.cl_import;
1229 now = cfs_time_current_sec();
1231 /* Some network health info for kicks */
1232 s2dhms(&ts, now - imp->imp_last_reply_time);
1233 rc += snprintf(page + rc, count - rc,
1234 "%-10s : %ld, "DHMS_FMT" ago\n",
1235 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
1237 cur = at_get(&imp->imp_at.iat_net_latency);
1238 worst = imp->imp_at.iat_net_latency.at_worst_ever;
1239 worstt = imp->imp_at.iat_net_latency.at_worst_time;
1240 s2dhms(&ts, now - worstt);
1241 rc += snprintf(page + rc, count - rc,
1242 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
1243 "network", cur, worst, worstt, DHMS_VARS(&ts));
1244 rc = lprocfs_at_hist_helper(page, count, rc,
1245 &imp->imp_at.iat_net_latency);
1247 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
1248 if (imp->imp_at.iat_portal[i] == 0)
1250 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
1251 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
1252 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
1253 s2dhms(&ts, now - worstt);
1254 rc += snprintf(page + rc, count - rc,
1255 "portal %-2d : cur %3u worst %3u (at %ld, "
1256 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
1257 cur, worst, worstt, DHMS_VARS(&ts));
1258 rc = lprocfs_at_hist_helper(page, count, rc,
1259 &imp->imp_at.iat_service_estimate[i]);
1262 LPROCFS_CLIMP_EXIT(obd);
1265 EXPORT_SYMBOL(lprocfs_rd_timeouts);
1267 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1268 int count, int *eof, void *data)
1270 struct obd_device *obd = data;
1274 LPROCFS_CLIMP_CHECK(obd);
1275 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1276 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1277 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1278 ret += snprintf(page + ret, count - ret, "\n");
1279 LPROCFS_CLIMP_EXIT(obd);
1282 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1284 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1285 int *eof, void *data)
1287 struct obd_device *obd = data;
1289 LASSERT(obd != NULL);
1291 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1293 EXPORT_SYMBOL(lprocfs_rd_num_exports);
1295 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1296 int *eof, void *data)
1298 struct obd_type *class = (struct obd_type*) data;
1300 LASSERT(class != NULL);
1302 return snprintf(page, count, "%d\n", class->typ_refcnt);
1304 EXPORT_SYMBOL(lprocfs_rd_numrefs);
1306 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1310 LASSERT(obd != NULL);
1311 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1312 LASSERT(obd->obd_type->typ_procroot != NULL);
1314 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1315 obd->obd_type->typ_procroot,
1317 if (IS_ERR(obd->obd_proc_entry)) {
1318 rc = PTR_ERR(obd->obd_proc_entry);
1319 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1320 obd->obd_proc_entry = NULL;
1324 EXPORT_SYMBOL(lprocfs_obd_setup);
1326 int lprocfs_obd_cleanup(struct obd_device *obd)
1330 if (obd->obd_proc_exports_entry) {
1331 /* Should be no exports left */
1332 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1333 lprocfs_remove(&obd->obd_proc_exports_entry);
1334 obd->obd_proc_exports_entry = NULL;
1336 if (obd->obd_proc_entry) {
1337 lprocfs_remove(&obd->obd_proc_entry);
1338 obd->obd_proc_entry = NULL;
1342 EXPORT_SYMBOL(lprocfs_obd_cleanup);
1344 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1346 CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
1347 client_stat->nid_proc, client_stat->nid_stats,
1348 client_stat->nid_brw_stats);
1350 LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
1351 "nid %s:count %d\n", libcfs_nid2str(client_stat->nid),
1352 atomic_read(&client_stat->nid_exp_ref_count));
1354 if (client_stat->nid_proc)
1355 lprocfs_remove(&client_stat->nid_proc);
1357 if (client_stat->nid_stats)
1358 lprocfs_free_stats(&client_stat->nid_stats);
1360 if (client_stat->nid_brw_stats)
1361 OBD_FREE_PTR(client_stat->nid_brw_stats);
1363 if (client_stat->nid_ldlm_stats)
1364 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1366 OBD_FREE_PTR(client_stat);
1371 void lprocfs_free_per_client_stats(struct obd_device *obd)
1373 cfs_hash_t *hash = obd->obd_nid_stats_hash;
1374 struct nid_stat *stat;
1377 /* we need extra list - because hash_exit called to early */
1378 /* not need locking because all clients is died */
1379 while (!cfs_list_empty(&obd->obd_nid_stats)) {
1380 stat = cfs_list_entry(obd->obd_nid_stats.next,
1381 struct nid_stat, nid_list);
1382 cfs_list_del_init(&stat->nid_list);
1383 cfs_hash_del(hash, &stat->nid, &stat->nid_hash);
1384 lprocfs_free_client_stats(stat);
1388 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
1390 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1391 enum lprocfs_stats_flags flags)
1393 struct lprocfs_stats *stats;
1394 unsigned int percpusize;
1395 unsigned int num_entry;
1400 if (lprocfs_no_percpu_stats != 0)
1401 flags |= LPROCFS_STATS_FLAG_NOPERCPU;
1403 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1406 num_entry = cfs_num_possible_cpus() + 1;
1408 /* alloc percpu pointers for all possible cpu slots */
1409 OBD_ALLOC(stats, offsetof(struct lprocfs_stats, ls_percpu[num_entry]));
1413 stats->ls_num = num;
1414 stats->ls_biggest_alloc_num = 1;
1415 stats->ls_flags = flags;
1416 cfs_spin_lock_init(&stats->ls_lock);
1418 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
1420 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1422 /* for no percpu area, the 0th entry is for real use,
1423 * for percpu area, the 0th entry is for intialized entry template */
1424 OBD_ALLOC(stats->ls_percpu[0], percpusize);
1425 if (stats->ls_percpu[0] == NULL) {
1427 offsetof(struct lprocfs_stats, ls_percpu[num_entry]));
1432 EXPORT_SYMBOL(lprocfs_alloc_stats);
1434 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1436 struct lprocfs_stats *stats = *statsh;
1437 unsigned int num_entry;
1438 unsigned int percpusize;
1441 if (stats == NULL || stats->ls_num == 0)
1445 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1448 num_entry = cfs_num_possible_cpus() + 1;
1450 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
1452 percpusize = CFS_L1_CACHE_ALIGN(percpusize);
1453 for (i = 0; i < num_entry; i++)
1454 if (stats->ls_percpu[i] != NULL)
1455 OBD_FREE(stats->ls_percpu[i], percpusize);
1456 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1458 EXPORT_SYMBOL(lprocfs_free_stats);
1460 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1462 struct lprocfs_counter *percpu_cntr;
1465 unsigned int num_entry;
1466 unsigned long flags = 0;
1468 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1470 for (i = 0; i < num_entry; i++) {
1471 if (stats->ls_percpu[i] == NULL)
1473 for (j = 0; j < stats->ls_num; j++) {
1474 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
1475 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_entry);
1476 percpu_cntr->lc_count = 0;
1477 percpu_cntr->lc_sum = 0;
1478 percpu_cntr->lc_min = LC_MIN_INIT;
1479 percpu_cntr->lc_max = 0;
1480 percpu_cntr->lc_sumsquare = 0;
1481 cfs_atomic_inc(&percpu_cntr->lc_cntl.la_exit);
1485 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1487 EXPORT_SYMBOL(lprocfs_clear_stats);
1489 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1490 size_t len, loff_t *off)
1492 struct seq_file *seq = file->private_data;
1493 struct lprocfs_stats *stats = seq->private;
1495 lprocfs_clear_stats(stats);
1500 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1502 struct lprocfs_stats *stats = p->private;
1503 /* return 1st cpu location */
1504 return (*pos >= stats->ls_num) ? NULL :
1505 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1508 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1512 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1514 struct lprocfs_stats *stats = p->private;
1516 return (*pos >= stats->ls_num) ? NULL :
1517 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1520 /* seq file export of one lprocfs counter */
1521 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1523 struct lprocfs_stats *stats = p->private;
1524 struct lprocfs_counter *cntr = v;
1525 struct lprocfs_counter ret;
1528 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
1530 cfs_gettimeofday(&now);
1531 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1532 "snapshot_time", now.tv_sec, now.tv_usec);
1536 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
1538 lprocfs_stats_collect(stats, idx, &ret);
1540 if (ret.lc_count == 0)
1543 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", cntr->lc_name,
1544 ret.lc_count, cntr->lc_units);
1549 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
1550 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1551 ret.lc_min, ret.lc_max, ret.lc_sum);
1554 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
1555 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1559 rc = seq_printf(p, "\n");
1561 return (rc < 0) ? rc : 0;
1564 struct seq_operations lprocfs_stats_seq_sops = {
1565 start: lprocfs_stats_seq_start,
1566 stop: lprocfs_stats_seq_stop,
1567 next: lprocfs_stats_seq_next,
1568 show: lprocfs_stats_seq_show,
1571 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1573 struct proc_dir_entry *dp = PDE(inode);
1574 struct seq_file *seq;
1577 if (LPROCFS_ENTRY_AND_CHECK(dp))
1580 rc = seq_open(file, &lprocfs_stats_seq_sops);
1585 seq = file->private_data;
1586 seq->private = dp->data;
1590 struct file_operations lprocfs_stats_seq_fops = {
1591 .owner = THIS_MODULE,
1592 .open = lprocfs_stats_seq_open,
1594 .write = lprocfs_stats_seq_write,
1595 .llseek = seq_lseek,
1596 .release = lprocfs_seq_release,
1599 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1600 struct lprocfs_stats *stats)
1602 struct proc_dir_entry *entry;
1603 LASSERT(root != NULL);
1605 LPROCFS_WRITE_ENTRY();
1606 entry = create_proc_entry(name, 0644, root);
1608 entry->proc_fops = &lprocfs_stats_seq_fops;
1609 entry->data = stats;
1612 LPROCFS_WRITE_EXIT();
1619 EXPORT_SYMBOL(lprocfs_register_stats);
1621 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1622 unsigned conf, const char *name, const char *units)
1624 struct lprocfs_counter *c = &(stats->ls_percpu[0]->lp_cntr[index]);
1625 unsigned long flags = 0;
1627 LASSERT(stats != NULL);
1628 LASSERT(stats->ls_percpu[0] != NULL);
1630 lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1631 c->lc_config = conf;
1634 c->lc_min = LC_MIN_INIT;
1637 c->lc_units = units;
1638 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1640 EXPORT_SYMBOL(lprocfs_counter_init);
1642 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1644 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1645 LASSERT(coffset < stats->ls_num); \
1646 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1649 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1651 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1652 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1653 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1654 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1655 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1656 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1657 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1658 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1659 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1660 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1661 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1662 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1663 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1664 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1665 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1666 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1667 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1668 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1669 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
1670 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1671 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1672 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1673 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1674 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1675 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1676 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1677 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1678 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1679 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1680 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1681 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1682 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1683 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1684 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1685 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1686 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1687 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1688 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1689 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1690 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1691 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1692 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1693 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1694 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1695 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
1696 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1697 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1698 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1699 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1700 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1701 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1702 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1703 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1704 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1705 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1706 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1707 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1708 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1709 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1710 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1711 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1712 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1713 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1714 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1715 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1716 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1717 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1718 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1720 EXPORT_SYMBOL(lprocfs_init_ops_stats);
1722 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1724 struct lprocfs_stats *stats;
1725 unsigned int num_stats;
1728 LASSERT(obd->obd_stats == NULL);
1729 LASSERT(obd->obd_proc_entry != NULL);
1730 LASSERT(obd->obd_cntr_base == 0);
1732 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1733 num_private_stats - 1 /* o_owner */;
1734 stats = lprocfs_alloc_stats(num_stats, 0);
1738 lprocfs_init_ops_stats(num_private_stats, stats);
1740 for (i = num_private_stats; i < num_stats; i++) {
1741 /* If this LBUGs, it is likely that an obd
1742 * operation was added to struct obd_ops in
1743 * <obd.h>, and that the corresponding line item
1744 * LPROCFS_OBD_OP_INIT(.., .., opname)
1745 * is missing from the list above. */
1746 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1747 "Missing obd_stat initializer obd_op "
1748 "operation at offset %d.\n", i - num_private_stats);
1750 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1752 lprocfs_free_stats(&stats);
1754 obd->obd_stats = stats;
1755 obd->obd_cntr_base = num_private_stats;
1759 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
1761 void lprocfs_free_obd_stats(struct obd_device *obd)
1764 lprocfs_free_stats(&obd->obd_stats);
1766 EXPORT_SYMBOL(lprocfs_free_obd_stats);
1768 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1770 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1771 LASSERT(coffset < stats->ls_num); \
1772 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1775 void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats)
1777 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1778 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1779 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
1780 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1781 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1782 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1783 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1784 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1785 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1786 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1787 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1788 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1789 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1790 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1791 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1792 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1793 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1794 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1795 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1796 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1797 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1798 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1799 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1800 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1801 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1802 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1803 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1804 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1805 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1806 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1807 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1808 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1810 EXPORT_SYMBOL(lprocfs_init_mps_stats);
1812 int lprocfs_alloc_md_stats(struct obd_device *obd,
1813 unsigned num_private_stats)
1815 struct lprocfs_stats *stats;
1816 unsigned int num_stats;
1819 LASSERT(obd->md_stats == NULL);
1820 LASSERT(obd->obd_proc_entry != NULL);
1821 LASSERT(obd->md_cntr_base == 0);
1823 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1825 stats = lprocfs_alloc_stats(num_stats, 0);
1829 lprocfs_init_mps_stats(num_private_stats, stats);
1831 for (i = num_private_stats; i < num_stats; i++) {
1832 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1833 CERROR("Missing md_stat initializer md_op "
1834 "operation at offset %d. Aborting.\n",
1835 i - num_private_stats);
1839 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1841 lprocfs_free_stats(&stats);
1843 obd->md_stats = stats;
1844 obd->md_cntr_base = num_private_stats;
1848 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
1850 void lprocfs_free_md_stats(struct obd_device *obd)
1852 struct lprocfs_stats *stats = obd->md_stats;
1854 if (stats != NULL) {
1855 obd->md_stats = NULL;
1856 obd->md_cntr_base = 0;
1857 lprocfs_free_stats(&stats);
1860 EXPORT_SYMBOL(lprocfs_free_md_stats);
1862 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1864 lprocfs_counter_init(ldlm_stats,
1865 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1866 0, "ldlm_enqueue", "reqs");
1867 lprocfs_counter_init(ldlm_stats,
1868 LDLM_CONVERT - LDLM_FIRST_OPC,
1869 0, "ldlm_convert", "reqs");
1870 lprocfs_counter_init(ldlm_stats,
1871 LDLM_CANCEL - LDLM_FIRST_OPC,
1872 0, "ldlm_cancel", "reqs");
1873 lprocfs_counter_init(ldlm_stats,
1874 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1875 0, "ldlm_bl_callback", "reqs");
1876 lprocfs_counter_init(ldlm_stats,
1877 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1878 0, "ldlm_cp_callback", "reqs");
1879 lprocfs_counter_init(ldlm_stats,
1880 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1881 0, "ldlm_gl_callback", "reqs");
1883 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
1885 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1886 int *eof, void *data)
1888 struct obd_export *exp = data;
1889 LASSERT(exp != NULL);
1891 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1894 struct exp_uuid_cb_data {
1902 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1903 int count, int *eof, int *len)
1905 cb_data->page = page;
1906 cb_data->count = count;
1911 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1912 cfs_hlist_node_t *hnode, void *cb_data)
1915 struct obd_export *exp = cfs_hash_object(hs, hnode);
1916 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1918 if (exp->exp_nid_stats)
1919 *data->len += snprintf((data->page + *data->len),
1920 data->count, "%s\n",
1921 obd_uuid2str(&exp->exp_client_uuid));
1925 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1926 int *eof, void *data)
1928 struct nid_stat *stats = (struct nid_stat *)data;
1929 struct exp_uuid_cb_data cb_data;
1930 struct obd_device *obd = stats->nid_obd;
1935 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1936 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1937 lprocfs_exp_print_uuid, &cb_data);
1938 return (*cb_data.len);
1941 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1942 cfs_hlist_node_t *hnode, void *cb_data)
1945 struct exp_uuid_cb_data *data = cb_data;
1946 struct obd_export *exp = cfs_hash_object(hs, hnode);
1948 if (exp->exp_lock_hash != NULL) {
1950 *data->len += cfs_hash_debug_header(data->page,
1953 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1960 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1961 int *eof, void *data)
1963 struct nid_stat *stats = (struct nid_stat *)data;
1964 struct exp_uuid_cb_data cb_data;
1965 struct obd_device *obd = stats->nid_obd;
1970 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1972 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1973 lprocfs_exp_print_hash, &cb_data);
1974 return (*cb_data.len);
1977 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1978 int count, int *eof, void *data)
1981 return snprintf(page, count, "%s\n",
1982 "Write into this file to clear all nid stats and "
1983 "stale nid entries");
1985 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1987 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1989 struct nid_stat *stat = obj;
1993 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
1994 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 1) {
1995 /* object has only hash references. */
1996 cfs_spin_lock(&stat->nid_obd->obd_nid_lock);
1997 cfs_list_move(&stat->nid_list, data);
1998 cfs_spin_unlock(&stat->nid_obd->obd_nid_lock);
2001 /* we has reference to object - only clear data*/
2002 if (stat->nid_stats)
2003 lprocfs_clear_stats(stat->nid_stats);
2005 if (stat->nid_brw_stats) {
2006 for (i = 0; i < BRW_LAST; i++)
2007 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
2012 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
2013 unsigned long count, void *data)
2015 struct obd_device *obd = (struct obd_device *)data;
2016 struct nid_stat *client_stat;
2017 CFS_LIST_HEAD(free_list);
2019 cfs_hash_cond_del(obd->obd_nid_stats_hash,
2020 lprocfs_nid_stats_clear_write_cb, &free_list);
2022 while (!cfs_list_empty(&free_list)) {
2023 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
2025 cfs_list_del_init(&client_stat->nid_list);
2026 lprocfs_free_client_stats(client_stat);
2031 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
2033 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
2035 struct nid_stat *new_stat, *old_stat;
2036 struct obd_device *obd = NULL;
2037 cfs_proc_dir_entry_t *entry;
2038 char *buffer = NULL;
2044 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
2045 !exp->exp_obd->obd_nid_stats_hash)
2048 /* not test against zero because eric say:
2049 * You may only test nid against another nid, or LNET_NID_ANY.
2050 * Anything else is nonsense.*/
2051 if (!nid || *nid == LNET_NID_ANY)
2056 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
2058 OBD_ALLOC_PTR(new_stat);
2059 if (new_stat == NULL)
2062 new_stat->nid = *nid;
2063 new_stat->nid_obd = exp->exp_obd;
2064 /* we need set default refcount to 1 to balance obd_disconnect */
2065 cfs_atomic_set(&new_stat->nid_exp_ref_count, 1);
2067 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
2068 nid, &new_stat->nid_hash);
2069 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
2070 old_stat, libcfs_nid2str(*nid),
2071 cfs_atomic_read(&new_stat->nid_exp_ref_count));
2073 /* We need to release old stats because lprocfs_exp_cleanup() hasn't
2074 * been and will never be called. */
2075 if (exp->exp_nid_stats) {
2076 nidstat_putref(exp->exp_nid_stats);
2077 exp->exp_nid_stats = NULL;
2080 /* Return -EALREADY here so that we know that the /proc
2081 * entry already has been created */
2082 if (old_stat != new_stat) {
2083 exp->exp_nid_stats = old_stat;
2084 GOTO(destroy_new, rc = -EALREADY);
2086 /* not found - create */
2087 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
2089 GOTO(destroy_new, rc = -ENOMEM);
2091 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
2092 new_stat->nid_proc = lprocfs_register(buffer,
2093 obd->obd_proc_exports_entry,
2095 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
2097 if (new_stat->nid_proc == NULL) {
2098 CERROR("Error making export directory for nid %s\n",
2099 libcfs_nid2str(*nid));
2100 GOTO(destroy_new_ns, rc = -ENOMEM);
2103 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
2104 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
2105 if (IS_ERR(entry)) {
2106 CWARN("Error adding the NID stats file\n");
2107 rc = PTR_ERR(entry);
2108 GOTO(destroy_new_ns, rc);
2111 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
2112 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
2113 if (IS_ERR(entry)) {
2114 CWARN("Error adding the hash file\n");
2115 rc = PTR_ERR(entry);
2116 GOTO(destroy_new_ns, rc);
2119 exp->exp_nid_stats = new_stat;
2121 /* protect competitive add to list, not need locking on destroy */
2122 cfs_spin_lock(&obd->obd_nid_lock);
2123 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
2124 cfs_spin_unlock(&obd->obd_nid_lock);
2129 if (new_stat->nid_proc != NULL)
2130 lprocfs_remove(&new_stat->nid_proc);
2131 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
2134 nidstat_putref(new_stat);
2135 OBD_FREE_PTR(new_stat);
2138 EXPORT_SYMBOL(lprocfs_exp_setup);
2140 int lprocfs_exp_cleanup(struct obd_export *exp)
2142 struct nid_stat *stat = exp->exp_nid_stats;
2144 if(!stat || !exp->exp_obd)
2147 nidstat_putref(exp->exp_nid_stats);
2148 exp->exp_nid_stats = NULL;
2152 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2154 int lprocfs_write_helper(const char *buffer, unsigned long count,
2157 return lprocfs_write_frac_helper(buffer, count, val, 1);
2159 EXPORT_SYMBOL(lprocfs_write_helper);
2161 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
2164 char kernbuf[20], *end, *pbuf;
2166 if (count > (sizeof(kernbuf) - 1))
2169 if (cfs_copy_from_user(kernbuf, buffer, count))
2172 kernbuf[count] = '\0';
2179 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2183 if (end != NULL && *end == '.') {
2184 int temp_val, pow = 1;
2188 if (strlen(pbuf) > 5)
2189 pbuf[5] = '\0'; /*only allow 5bits fractional*/
2191 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2194 for (i = 0; i < (end - pbuf); i++)
2197 *val += temp_val / pow;
2202 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2204 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
2207 long decimal_val, frac_val;
2213 decimal_val = val / mult;
2214 prtn = snprintf(buffer, count, "%ld", decimal_val);
2215 frac_val = val % mult;
2217 if (prtn < (count - 4) && frac_val > 0) {
2219 int i, temp_mult = 1, frac_bits = 0;
2221 temp_frac = frac_val * 10;
2222 buffer[prtn++] = '.';
2223 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
2224 /* only reserved 2 bits fraction */
2225 buffer[prtn++] ='0';
2230 * Need to think these cases :
2231 * 1. #echo x.00 > /proc/xxx output result : x
2232 * 2. #echo x.0x > /proc/xxx output result : x.0x
2233 * 3. #echo x.x0 > /proc/xxx output result : x.x
2234 * 4. #echo x.xx > /proc/xxx output result : x.xx
2235 * Only reserved 2 bits fraction.
2237 for (i = 0; i < (5 - prtn); i++)
2240 frac_bits = min((int)count - prtn, 3 - frac_bits);
2241 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
2242 frac_val * temp_mult / mult);
2245 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
2247 if (buffer[prtn] == '.') {
2254 buffer[prtn++] ='\n';
2257 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2259 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
2261 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
2263 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2265 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
2266 __u64 *val, int mult)
2268 char kernbuf[22], *end, *pbuf;
2269 __u64 whole, frac = 0, units;
2270 unsigned frac_d = 1;
2272 if (count > (sizeof(kernbuf) - 1))
2275 if (cfs_copy_from_user(kernbuf, buffer, count))
2278 kernbuf[count] = '\0';
2285 whole = simple_strtoull(pbuf, &end, 10);
2289 if (end != NULL && *end == '.') {
2293 /* need to limit frac_d to a __u32 */
2294 if (strlen(pbuf) > 10)
2297 frac = simple_strtoull(pbuf, &end, 10);
2298 /* count decimal places */
2299 for (i = 0; i < (end - pbuf); i++)
2316 /* Specified units override the multiplier */
2318 mult = mult < 0 ? -units : units;
2321 do_div(frac, frac_d);
2322 *val = whole * mult + frac;
2325 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2327 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent, char *name, mode_t mode,
2328 struct file_operations *seq_fops, void *data)
2330 struct proc_dir_entry *entry;
2333 LPROCFS_WRITE_ENTRY();
2334 entry = create_proc_entry(name, mode, parent);
2336 entry->proc_fops = seq_fops;
2339 LPROCFS_WRITE_EXIT();
2346 EXPORT_SYMBOL(lprocfs_seq_create);
2348 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
2350 struct file_operations *seq_fops,
2353 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2354 mode, seq_fops, data));
2356 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2358 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2360 if (value >= OBD_HIST_MAX)
2361 value = OBD_HIST_MAX - 1;
2363 cfs_spin_lock(&oh->oh_lock);
2364 oh->oh_buckets[value]++;
2365 cfs_spin_unlock(&oh->oh_lock);
2367 EXPORT_SYMBOL(lprocfs_oh_tally);
2369 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2373 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2376 lprocfs_oh_tally(oh, val);
2378 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2380 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2382 unsigned long ret = 0;
2385 for (i = 0; i < OBD_HIST_MAX; i++)
2386 ret += oh->oh_buckets[i];
2389 EXPORT_SYMBOL(lprocfs_oh_sum);
2391 void lprocfs_oh_clear(struct obd_histogram *oh)
2393 cfs_spin_lock(&oh->oh_lock);
2394 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2395 cfs_spin_unlock(&oh->oh_lock);
2397 EXPORT_SYMBOL(lprocfs_oh_clear);
2399 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2400 int count, int *eof, void *data)
2402 struct obd_device *obd = data;
2408 c += cfs_hash_debug_header(page, count);
2409 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2410 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2411 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2415 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2417 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2418 int count, int *eof, void *data)
2420 struct obd_device *obd = data;
2423 LASSERT(obd != NULL);
2424 LASSERT(count >= 0);
2426 /* Set start of user data returned to
2427 page + off since the user may have
2428 requested to read much smaller than
2429 what we need to read */
2430 *start = page + off;
2432 /* We know we are allocated a page here.
2433 Also we know that this function will
2434 not need to write more than a page
2435 so we can truncate at CFS_PAGE_SIZE. */
2436 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2438 /* Initialize the page */
2439 memset(page, 0, size);
2441 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2443 if (obd->obd_max_recoverable_clients == 0) {
2444 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2450 /* sampled unlocked, but really... */
2451 if (obd->obd_recovering == 0) {
2452 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2454 if (lprocfs_obd_snprintf(&page, size, &len,
2455 "recovery_start: %lu\n",
2456 obd->obd_recovery_start) <= 0)
2458 if (lprocfs_obd_snprintf(&page, size, &len,
2459 "recovery_duration: %lu\n",
2460 obd->obd_recovery_end -
2461 obd->obd_recovery_start) <= 0)
2463 /* Number of clients that have completed recovery */
2464 if (lprocfs_obd_snprintf(&page, size, &len,
2465 "completed_clients: %d/%d\n",
2466 obd->obd_max_recoverable_clients -
2467 obd->obd_stale_clients,
2468 obd->obd_max_recoverable_clients) <= 0)
2470 if (lprocfs_obd_snprintf(&page, size, &len,
2471 "replayed_requests: %d\n",
2472 obd->obd_replayed_requests) <= 0)
2474 if (lprocfs_obd_snprintf(&page, size, &len,
2475 "last_transno: "LPD64"\n",
2476 obd->obd_next_recovery_transno - 1)<=0)
2478 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2479 obd->obd_version_recov ?
2480 "ENABLED" : "DISABLED") <=0)
2482 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
2484 "DISABLED" : "ENABLED") <= 0)
2489 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2491 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2492 obd->obd_recovery_start) <= 0)
2494 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2495 cfs_time_current_sec() >=
2496 obd->obd_recovery_start +
2497 obd->obd_recovery_timeout ? 0 :
2498 obd->obd_recovery_start +
2499 obd->obd_recovery_timeout -
2500 cfs_time_current_sec()) <= 0)
2502 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2503 cfs_atomic_read(&obd->obd_connected_clients),
2504 obd->obd_max_recoverable_clients) <= 0)
2506 /* Number of clients that have completed recovery */
2507 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2508 cfs_atomic_read(&obd->obd_req_replay_clients))
2511 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2512 cfs_atomic_read(&obd->obd_lock_replay_clients))
2515 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2516 cfs_atomic_read(&obd->obd_connected_clients) -
2517 cfs_atomic_read(&obd->obd_lock_replay_clients))
2520 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2521 obd->obd_stale_clients) <= 0)
2523 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2524 obd->obd_replayed_requests) <= 0)
2526 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2527 obd->obd_requests_queued_for_recovery) <= 0)
2530 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2531 obd->obd_next_recovery_transno) <= 0)
2537 return min(count, len - (int)off);
2539 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2541 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
2542 int count, int *eof, void *data)
2544 struct obd_device *obd = (struct obd_device *)data;
2545 LASSERT(obd != NULL);
2547 return snprintf(page, count, "%d\n",
2548 obd->obd_recovery_ir_factor);
2550 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
2552 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
2553 unsigned long count, void *data)
2555 struct obd_device *obd = (struct obd_device *)data;
2557 LASSERT(obd != NULL);
2559 rc = lprocfs_write_helper(buffer, count, &val);
2563 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
2566 obd->obd_recovery_ir_factor = val;
2569 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
2571 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
2572 int count, int *eof, void *data)
2574 struct obd_device *obd = (struct obd_device *)data;
2575 LASSERT(obd != NULL);
2577 return snprintf(page, count, "%d\n",
2578 obd->obd_recovery_timeout);
2580 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
2582 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
2583 unsigned long count, void *data)
2585 struct obd_device *obd = (struct obd_device *)data;
2587 LASSERT(obd != NULL);
2589 rc = lprocfs_write_helper(buffer, count, &val);
2593 obd->obd_recovery_timeout = val;
2596 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
2598 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
2599 int count, int *eof, void *data)
2601 struct obd_device *obd = data;
2602 LASSERT(obd != NULL);
2604 return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
2606 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
2608 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
2609 unsigned long count, void *data)
2611 struct obd_device *obd = data;
2613 LASSERT(obd != NULL);
2615 rc = lprocfs_write_helper(buffer, count, &val);
2619 obd->obd_recovery_time_hard = val;
2622 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
2624 int lprocfs_obd_rd_mntdev(char *page, char **start, off_t off,
2625 int count, int *eof, void *data)
2627 struct obd_device *obd = (struct obd_device *)data;
2629 LASSERT(obd != NULL);
2630 LASSERT(mnt_get_devname(obd->u.obt.obt_vfsmnt));
2632 return snprintf(page, count, "%s\n",
2633 mnt_get_devname(obd->u.obt.obt_vfsmnt));
2635 EXPORT_SYMBOL(lprocfs_obd_rd_mntdev);
2637 int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
2638 int count, int *eof, void *data)
2640 struct obd_device *dev = data;
2641 struct client_obd *cli = &dev->u.cli;
2644 client_obd_list_lock(&cli->cl_loi_list_lock);
2645 rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
2646 client_obd_list_unlock(&cli->cl_loi_list_lock);
2649 EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
2651 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
2652 int count, int *eof, void *data)
2654 struct obd_device *obd = (struct obd_device *)data;
2655 struct obd_device_target *target = &obd->u.obt;
2657 LASSERT(obd != NULL);
2658 LASSERT(target->obt_magic == OBT_MAGIC);
2660 return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
2662 EXPORT_SYMBOL(lprocfs_target_rd_instance);