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, quota_adjust_qunit);
1713 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1714 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1715 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1716 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1717 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1718 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1719 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1721 EXPORT_SYMBOL(lprocfs_init_ops_stats);
1723 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1725 struct lprocfs_stats *stats;
1726 unsigned int num_stats;
1729 LASSERT(obd->obd_stats == NULL);
1730 LASSERT(obd->obd_proc_entry != NULL);
1731 LASSERT(obd->obd_cntr_base == 0);
1733 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1734 num_private_stats - 1 /* o_owner */;
1735 stats = lprocfs_alloc_stats(num_stats, 0);
1739 lprocfs_init_ops_stats(num_private_stats, stats);
1741 for (i = num_private_stats; i < num_stats; i++) {
1742 /* If this LBUGs, it is likely that an obd
1743 * operation was added to struct obd_ops in
1744 * <obd.h>, and that the corresponding line item
1745 * LPROCFS_OBD_OP_INIT(.., .., opname)
1746 * is missing from the list above. */
1747 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1748 "Missing obd_stat initializer obd_op "
1749 "operation at offset %d.\n", i - num_private_stats);
1751 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1753 lprocfs_free_stats(&stats);
1755 obd->obd_stats = stats;
1756 obd->obd_cntr_base = num_private_stats;
1760 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
1762 void lprocfs_free_obd_stats(struct obd_device *obd)
1765 lprocfs_free_stats(&obd->obd_stats);
1767 EXPORT_SYMBOL(lprocfs_free_obd_stats);
1769 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1771 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1772 LASSERT(coffset < stats->ls_num); \
1773 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1776 void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats)
1778 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1779 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1780 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
1781 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1782 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1783 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1784 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1785 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1786 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1787 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1788 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1789 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1790 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1791 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1792 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1793 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1794 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1795 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1796 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1797 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1798 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1799 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1800 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1801 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1802 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1803 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1804 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1805 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1806 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1807 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1808 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1809 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1811 EXPORT_SYMBOL(lprocfs_init_mps_stats);
1813 int lprocfs_alloc_md_stats(struct obd_device *obd,
1814 unsigned num_private_stats)
1816 struct lprocfs_stats *stats;
1817 unsigned int num_stats;
1820 LASSERT(obd->md_stats == NULL);
1821 LASSERT(obd->obd_proc_entry != NULL);
1822 LASSERT(obd->md_cntr_base == 0);
1824 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1826 stats = lprocfs_alloc_stats(num_stats, 0);
1830 lprocfs_init_mps_stats(num_private_stats, stats);
1832 for (i = num_private_stats; i < num_stats; i++) {
1833 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1834 CERROR("Missing md_stat initializer md_op "
1835 "operation at offset %d. Aborting.\n",
1836 i - num_private_stats);
1840 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1842 lprocfs_free_stats(&stats);
1844 obd->md_stats = stats;
1845 obd->md_cntr_base = num_private_stats;
1849 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
1851 void lprocfs_free_md_stats(struct obd_device *obd)
1853 struct lprocfs_stats *stats = obd->md_stats;
1855 if (stats != NULL) {
1856 obd->md_stats = NULL;
1857 obd->md_cntr_base = 0;
1858 lprocfs_free_stats(&stats);
1861 EXPORT_SYMBOL(lprocfs_free_md_stats);
1863 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1865 lprocfs_counter_init(ldlm_stats,
1866 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1867 0, "ldlm_enqueue", "reqs");
1868 lprocfs_counter_init(ldlm_stats,
1869 LDLM_CONVERT - LDLM_FIRST_OPC,
1870 0, "ldlm_convert", "reqs");
1871 lprocfs_counter_init(ldlm_stats,
1872 LDLM_CANCEL - LDLM_FIRST_OPC,
1873 0, "ldlm_cancel", "reqs");
1874 lprocfs_counter_init(ldlm_stats,
1875 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1876 0, "ldlm_bl_callback", "reqs");
1877 lprocfs_counter_init(ldlm_stats,
1878 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1879 0, "ldlm_cp_callback", "reqs");
1880 lprocfs_counter_init(ldlm_stats,
1881 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1882 0, "ldlm_gl_callback", "reqs");
1884 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
1886 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1887 int *eof, void *data)
1889 struct obd_export *exp = data;
1890 LASSERT(exp != NULL);
1892 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1895 struct exp_uuid_cb_data {
1903 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1904 int count, int *eof, int *len)
1906 cb_data->page = page;
1907 cb_data->count = count;
1912 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1913 cfs_hlist_node_t *hnode, void *cb_data)
1916 struct obd_export *exp = cfs_hash_object(hs, hnode);
1917 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1919 if (exp->exp_nid_stats)
1920 *data->len += snprintf((data->page + *data->len),
1921 data->count, "%s\n",
1922 obd_uuid2str(&exp->exp_client_uuid));
1926 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1927 int *eof, void *data)
1929 struct nid_stat *stats = (struct nid_stat *)data;
1930 struct exp_uuid_cb_data cb_data;
1931 struct obd_device *obd = stats->nid_obd;
1936 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1937 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1938 lprocfs_exp_print_uuid, &cb_data);
1939 return (*cb_data.len);
1942 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1943 cfs_hlist_node_t *hnode, void *cb_data)
1946 struct exp_uuid_cb_data *data = cb_data;
1947 struct obd_export *exp = cfs_hash_object(hs, hnode);
1949 if (exp->exp_lock_hash != NULL) {
1951 *data->len += cfs_hash_debug_header(data->page,
1954 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1961 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1962 int *eof, void *data)
1964 struct nid_stat *stats = (struct nid_stat *)data;
1965 struct exp_uuid_cb_data cb_data;
1966 struct obd_device *obd = stats->nid_obd;
1971 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1973 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1974 lprocfs_exp_print_hash, &cb_data);
1975 return (*cb_data.len);
1978 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1979 int count, int *eof, void *data)
1982 return snprintf(page, count, "%s\n",
1983 "Write into this file to clear all nid stats and "
1984 "stale nid entries");
1986 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1988 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1990 struct nid_stat *stat = obj;
1994 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
1995 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 1) {
1996 /* object has only hash references. */
1997 cfs_spin_lock(&stat->nid_obd->obd_nid_lock);
1998 cfs_list_move(&stat->nid_list, data);
1999 cfs_spin_unlock(&stat->nid_obd->obd_nid_lock);
2002 /* we has reference to object - only clear data*/
2003 if (stat->nid_stats)
2004 lprocfs_clear_stats(stat->nid_stats);
2006 if (stat->nid_brw_stats) {
2007 for (i = 0; i < BRW_LAST; i++)
2008 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
2013 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
2014 unsigned long count, void *data)
2016 struct obd_device *obd = (struct obd_device *)data;
2017 struct nid_stat *client_stat;
2018 CFS_LIST_HEAD(free_list);
2020 cfs_hash_cond_del(obd->obd_nid_stats_hash,
2021 lprocfs_nid_stats_clear_write_cb, &free_list);
2023 while (!cfs_list_empty(&free_list)) {
2024 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
2026 cfs_list_del_init(&client_stat->nid_list);
2027 lprocfs_free_client_stats(client_stat);
2032 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
2034 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
2036 struct nid_stat *new_stat, *old_stat;
2037 struct obd_device *obd = NULL;
2038 cfs_proc_dir_entry_t *entry;
2039 char *buffer = NULL;
2045 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
2046 !exp->exp_obd->obd_nid_stats_hash)
2049 /* not test against zero because eric say:
2050 * You may only test nid against another nid, or LNET_NID_ANY.
2051 * Anything else is nonsense.*/
2052 if (!nid || *nid == LNET_NID_ANY)
2057 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
2059 OBD_ALLOC_PTR(new_stat);
2060 if (new_stat == NULL)
2063 new_stat->nid = *nid;
2064 new_stat->nid_obd = exp->exp_obd;
2065 /* we need set default refcount to 1 to balance obd_disconnect */
2066 cfs_atomic_set(&new_stat->nid_exp_ref_count, 1);
2068 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
2069 nid, &new_stat->nid_hash);
2070 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
2071 old_stat, libcfs_nid2str(*nid),
2072 cfs_atomic_read(&new_stat->nid_exp_ref_count));
2074 /* We need to release old stats because lprocfs_exp_cleanup() hasn't
2075 * been and will never be called. */
2076 if (exp->exp_nid_stats) {
2077 nidstat_putref(exp->exp_nid_stats);
2078 exp->exp_nid_stats = NULL;
2081 /* Return -EALREADY here so that we know that the /proc
2082 * entry already has been created */
2083 if (old_stat != new_stat) {
2084 exp->exp_nid_stats = old_stat;
2085 GOTO(destroy_new, rc = -EALREADY);
2087 /* not found - create */
2088 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
2090 GOTO(destroy_new, rc = -ENOMEM);
2092 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
2093 new_stat->nid_proc = lprocfs_register(buffer,
2094 obd->obd_proc_exports_entry,
2096 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
2098 if (new_stat->nid_proc == NULL) {
2099 CERROR("Error making export directory for nid %s\n",
2100 libcfs_nid2str(*nid));
2101 GOTO(destroy_new_ns, rc = -ENOMEM);
2104 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
2105 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
2106 if (IS_ERR(entry)) {
2107 CWARN("Error adding the NID stats file\n");
2108 rc = PTR_ERR(entry);
2109 GOTO(destroy_new_ns, rc);
2112 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
2113 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
2114 if (IS_ERR(entry)) {
2115 CWARN("Error adding the hash file\n");
2116 rc = PTR_ERR(entry);
2117 GOTO(destroy_new_ns, rc);
2120 exp->exp_nid_stats = new_stat;
2122 /* protect competitive add to list, not need locking on destroy */
2123 cfs_spin_lock(&obd->obd_nid_lock);
2124 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
2125 cfs_spin_unlock(&obd->obd_nid_lock);
2130 if (new_stat->nid_proc != NULL)
2131 lprocfs_remove(&new_stat->nid_proc);
2132 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
2135 nidstat_putref(new_stat);
2136 OBD_FREE_PTR(new_stat);
2139 EXPORT_SYMBOL(lprocfs_exp_setup);
2141 int lprocfs_exp_cleanup(struct obd_export *exp)
2143 struct nid_stat *stat = exp->exp_nid_stats;
2145 if(!stat || !exp->exp_obd)
2148 nidstat_putref(exp->exp_nid_stats);
2149 exp->exp_nid_stats = NULL;
2153 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2155 int lprocfs_write_helper(const char *buffer, unsigned long count,
2158 return lprocfs_write_frac_helper(buffer, count, val, 1);
2160 EXPORT_SYMBOL(lprocfs_write_helper);
2162 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
2165 char kernbuf[20], *end, *pbuf;
2167 if (count > (sizeof(kernbuf) - 1))
2170 if (cfs_copy_from_user(kernbuf, buffer, count))
2173 kernbuf[count] = '\0';
2180 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2184 if (end != NULL && *end == '.') {
2185 int temp_val, pow = 1;
2189 if (strlen(pbuf) > 5)
2190 pbuf[5] = '\0'; /*only allow 5bits fractional*/
2192 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2195 for (i = 0; i < (end - pbuf); i++)
2198 *val += temp_val / pow;
2203 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2205 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
2208 long decimal_val, frac_val;
2214 decimal_val = val / mult;
2215 prtn = snprintf(buffer, count, "%ld", decimal_val);
2216 frac_val = val % mult;
2218 if (prtn < (count - 4) && frac_val > 0) {
2220 int i, temp_mult = 1, frac_bits = 0;
2222 temp_frac = frac_val * 10;
2223 buffer[prtn++] = '.';
2224 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
2225 /* only reserved 2 bits fraction */
2226 buffer[prtn++] ='0';
2231 * Need to think these cases :
2232 * 1. #echo x.00 > /proc/xxx output result : x
2233 * 2. #echo x.0x > /proc/xxx output result : x.0x
2234 * 3. #echo x.x0 > /proc/xxx output result : x.x
2235 * 4. #echo x.xx > /proc/xxx output result : x.xx
2236 * Only reserved 2 bits fraction.
2238 for (i = 0; i < (5 - prtn); i++)
2241 frac_bits = min((int)count - prtn, 3 - frac_bits);
2242 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
2243 frac_val * temp_mult / mult);
2246 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
2248 if (buffer[prtn] == '.') {
2255 buffer[prtn++] ='\n';
2258 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2260 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
2262 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
2264 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2266 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
2267 __u64 *val, int mult)
2269 char kernbuf[22], *end, *pbuf;
2270 __u64 whole, frac = 0, units;
2271 unsigned frac_d = 1;
2273 if (count > (sizeof(kernbuf) - 1))
2276 if (cfs_copy_from_user(kernbuf, buffer, count))
2279 kernbuf[count] = '\0';
2286 whole = simple_strtoull(pbuf, &end, 10);
2290 if (end != NULL && *end == '.') {
2294 /* need to limit frac_d to a __u32 */
2295 if (strlen(pbuf) > 10)
2298 frac = simple_strtoull(pbuf, &end, 10);
2299 /* count decimal places */
2300 for (i = 0; i < (end - pbuf); i++)
2317 /* Specified units override the multiplier */
2319 mult = mult < 0 ? -units : units;
2322 do_div(frac, frac_d);
2323 *val = whole * mult + frac;
2326 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2328 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent, char *name, mode_t mode,
2329 struct file_operations *seq_fops, void *data)
2331 struct proc_dir_entry *entry;
2334 LPROCFS_WRITE_ENTRY();
2335 entry = create_proc_entry(name, mode, parent);
2337 entry->proc_fops = seq_fops;
2340 LPROCFS_WRITE_EXIT();
2347 EXPORT_SYMBOL(lprocfs_seq_create);
2349 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
2351 struct file_operations *seq_fops,
2354 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2355 mode, seq_fops, data));
2357 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2359 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2361 if (value >= OBD_HIST_MAX)
2362 value = OBD_HIST_MAX - 1;
2364 cfs_spin_lock(&oh->oh_lock);
2365 oh->oh_buckets[value]++;
2366 cfs_spin_unlock(&oh->oh_lock);
2368 EXPORT_SYMBOL(lprocfs_oh_tally);
2370 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2374 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2377 lprocfs_oh_tally(oh, val);
2379 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2381 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2383 unsigned long ret = 0;
2386 for (i = 0; i < OBD_HIST_MAX; i++)
2387 ret += oh->oh_buckets[i];
2390 EXPORT_SYMBOL(lprocfs_oh_sum);
2392 void lprocfs_oh_clear(struct obd_histogram *oh)
2394 cfs_spin_lock(&oh->oh_lock);
2395 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2396 cfs_spin_unlock(&oh->oh_lock);
2398 EXPORT_SYMBOL(lprocfs_oh_clear);
2400 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2401 int count, int *eof, void *data)
2403 struct obd_device *obd = data;
2409 c += cfs_hash_debug_header(page, count);
2410 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2411 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2412 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2413 #ifdef HAVE_QUOTA_SUPPORT
2414 if (obd->u.obt.obt_qctxt.lqc_lqs_hash)
2415 c += cfs_hash_debug_str(obd->u.obt.obt_qctxt.lqc_lqs_hash,
2416 page + c, count - c);
2421 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2423 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2424 int count, int *eof, void *data)
2426 struct obd_device *obd = data;
2429 LASSERT(obd != NULL);
2430 LASSERT(count >= 0);
2432 /* Set start of user data returned to
2433 page + off since the user may have
2434 requested to read much smaller than
2435 what we need to read */
2436 *start = page + off;
2438 /* We know we are allocated a page here.
2439 Also we know that this function will
2440 not need to write more than a page
2441 so we can truncate at CFS_PAGE_SIZE. */
2442 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2444 /* Initialize the page */
2445 memset(page, 0, size);
2447 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2449 if (obd->obd_max_recoverable_clients == 0) {
2450 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2456 /* sampled unlocked, but really... */
2457 if (obd->obd_recovering == 0) {
2458 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2460 if (lprocfs_obd_snprintf(&page, size, &len,
2461 "recovery_start: %lu\n",
2462 obd->obd_recovery_start) <= 0)
2464 if (lprocfs_obd_snprintf(&page, size, &len,
2465 "recovery_duration: %lu\n",
2466 obd->obd_recovery_end -
2467 obd->obd_recovery_start) <= 0)
2469 /* Number of clients that have completed recovery */
2470 if (lprocfs_obd_snprintf(&page, size, &len,
2471 "completed_clients: %d/%d\n",
2472 obd->obd_max_recoverable_clients -
2473 obd->obd_stale_clients,
2474 obd->obd_max_recoverable_clients) <= 0)
2476 if (lprocfs_obd_snprintf(&page, size, &len,
2477 "replayed_requests: %d\n",
2478 obd->obd_replayed_requests) <= 0)
2480 if (lprocfs_obd_snprintf(&page, size, &len,
2481 "last_transno: "LPD64"\n",
2482 obd->obd_next_recovery_transno - 1)<=0)
2484 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2485 obd->obd_version_recov ?
2486 "ENABLED" : "DISABLED") <=0)
2488 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
2490 "DISABLED" : "ENABLED") <= 0)
2495 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2497 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2498 obd->obd_recovery_start) <= 0)
2500 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2501 cfs_time_current_sec() >=
2502 obd->obd_recovery_start +
2503 obd->obd_recovery_timeout ? 0 :
2504 obd->obd_recovery_start +
2505 obd->obd_recovery_timeout -
2506 cfs_time_current_sec()) <= 0)
2508 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2509 cfs_atomic_read(&obd->obd_connected_clients),
2510 obd->obd_max_recoverable_clients) <= 0)
2512 /* Number of clients that have completed recovery */
2513 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2514 cfs_atomic_read(&obd->obd_req_replay_clients))
2517 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2518 cfs_atomic_read(&obd->obd_lock_replay_clients))
2521 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2522 cfs_atomic_read(&obd->obd_connected_clients) -
2523 cfs_atomic_read(&obd->obd_lock_replay_clients))
2526 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2527 obd->obd_stale_clients) <= 0)
2529 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2530 obd->obd_replayed_requests) <= 0)
2532 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2533 obd->obd_requests_queued_for_recovery) <= 0)
2536 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2537 obd->obd_next_recovery_transno) <= 0)
2543 return min(count, len - (int)off);
2545 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2547 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
2548 int count, int *eof, void *data)
2550 struct obd_device *obd = (struct obd_device *)data;
2551 LASSERT(obd != NULL);
2553 return snprintf(page, count, "%d\n",
2554 obd->obd_recovery_ir_factor);
2556 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
2558 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
2559 unsigned long count, void *data)
2561 struct obd_device *obd = (struct obd_device *)data;
2563 LASSERT(obd != NULL);
2565 rc = lprocfs_write_helper(buffer, count, &val);
2569 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
2572 obd->obd_recovery_ir_factor = val;
2575 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
2577 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
2578 int count, int *eof, void *data)
2580 struct obd_device *obd = (struct obd_device *)data;
2581 LASSERT(obd != NULL);
2583 return snprintf(page, count, "%d\n",
2584 obd->obd_recovery_timeout);
2586 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
2588 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
2589 unsigned long count, void *data)
2591 struct obd_device *obd = (struct obd_device *)data;
2593 LASSERT(obd != NULL);
2595 rc = lprocfs_write_helper(buffer, count, &val);
2599 obd->obd_recovery_timeout = val;
2602 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
2604 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
2605 int count, int *eof, void *data)
2607 struct obd_device *obd = data;
2608 LASSERT(obd != NULL);
2610 return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
2612 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
2614 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
2615 unsigned long count, void *data)
2617 struct obd_device *obd = data;
2619 LASSERT(obd != NULL);
2621 rc = lprocfs_write_helper(buffer, count, &val);
2625 obd->obd_recovery_time_hard = val;
2628 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
2630 int lprocfs_obd_rd_mntdev(char *page, char **start, off_t off,
2631 int count, int *eof, void *data)
2633 struct obd_device *obd = (struct obd_device *)data;
2635 LASSERT(obd != NULL);
2636 LASSERT(mnt_get_devname(obd->u.obt.obt_vfsmnt));
2638 return snprintf(page, count, "%s\n",
2639 mnt_get_devname(obd->u.obt.obt_vfsmnt));
2641 EXPORT_SYMBOL(lprocfs_obd_rd_mntdev);
2643 int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
2644 int count, int *eof, void *data)
2646 struct obd_device *dev = data;
2647 struct client_obd *cli = &dev->u.cli;
2650 client_obd_list_lock(&cli->cl_loi_list_lock);
2651 rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
2652 client_obd_list_unlock(&cli->cl_loi_list_lock);
2655 EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
2657 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
2658 int count, int *eof, void *data)
2660 struct obd_device *obd = (struct obd_device *)data;
2661 struct obd_device_target *target = &obd->u.obt;
2663 LASSERT(obd != NULL);
2664 LASSERT(target->obt_magic == OBT_MAGIC);
2666 return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
2668 EXPORT_SYMBOL(lprocfs_target_rd_instance);