1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 only,
10 * as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License version 2 for more details (a copy is included
16 * in the LICENSE file that accompanied this code).
18 * You should have received a copy of the GNU General Public License
19 * version 2 along with this program; If not, see
20 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
22 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23 * CA 95054 USA or visit www.sun.com if you need additional information or
29 * Copyright 2008 Sun Microsystems, Inc. All rights reserved
30 * Use is subject to license terms.
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>
42 # define EXPORT_SYMTAB
44 #define DEBUG_SUBSYSTEM S_CLASS
47 # include <liblustre.h>
50 #include <obd_class.h>
51 #include <lprocfs_status.h>
52 #include <lustre_fsfilt.h>
56 #define MAX_STRING_SIZE 128
58 /* for bug 10866, global variable */
59 DECLARE_RWSEM(_lprocfs_lock);
60 EXPORT_SYMBOL(_lprocfs_lock);
62 int lprocfs_seq_release(struct inode *inode, struct file *file)
65 return seq_release(inode, file);
67 EXPORT_SYMBOL(lprocfs_seq_release);
69 struct proc_dir_entry *lprocfs_srch(struct proc_dir_entry *head,
72 struct proc_dir_entry *temp;
79 while (temp != NULL) {
80 if (strcmp(temp->name, name) == 0) {
91 /* lprocfs API calls */
93 /* Function that emulates snprintf but also has the side effect of advancing
94 the page pointer for the next write into the buffer, incrementing the total
95 length written to the buffer, and decrementing the size left in the
97 static int lprocfs_obd_snprintf(char **page, int end, int *len,
98 const char *format, ...)
106 va_start(list, format);
107 n = vsnprintf(*page, end - *len, format, list);
110 *page += n; *len += n;
114 int lprocfs_add_simple(struct proc_dir_entry *root, char *name,
115 read_proc_t *read_proc, write_proc_t *write_proc,
118 struct proc_dir_entry *proc;
121 if (root == NULL || name == NULL)
127 proc = create_proc_entry(name, mode, root);
129 CERROR("LprocFS: No memory to create /proc entry %s", name);
132 proc->read_proc = read_proc;
133 proc->write_proc = write_proc;
138 struct proc_dir_entry *lprocfs_add_symlink(const char *name,
139 struct proc_dir_entry *parent, const char *dest)
141 struct proc_dir_entry *entry;
143 if (parent == NULL || dest == NULL)
146 entry = proc_symlink(name, parent, dest);
148 CERROR("LprocFS: Could not create symbolic link from %s to %s",
153 static ssize_t lprocfs_fops_read(struct file *f, char __user *buf,
154 size_t size, loff_t *ppos)
156 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
157 char *page, *start = NULL;
158 int rc = 0, eof = 1, count;
160 if (*ppos >= CFS_PAGE_SIZE)
163 page = (char *)__get_free_page(GFP_KERNEL);
168 OBD_FAIL_TIMEOUT(OBD_FAIL_LPROC_REMOVE, 10);
169 if (!dp->deleted && dp->read_proc)
170 rc = dp->read_proc(page, &start, *ppos, CFS_PAGE_SIZE,
176 /* for lustre proc read, the read count must be less than PAGE_SIZE */
185 start = page + *ppos;
186 } else if (start < page) {
190 count = (rc < size) ? rc : size;
191 if (copy_to_user(buf, start, count)) {
198 free_page((unsigned long)page);
202 static ssize_t lprocfs_fops_write(struct file *f, const char __user *buf, size_t size, loff_t *ppos)
204 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
208 if (!dp->deleted && dp->write_proc)
209 rc = dp->write_proc(f, buf, size, dp->data);
214 static struct file_operations lprocfs_generic_fops = {
215 .owner = THIS_MODULE,
216 .read = lprocfs_fops_read,
217 .write = lprocfs_fops_write,
220 int lprocfs_evict_client_open(struct inode *inode, struct file *f)
222 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
223 struct obd_device *obd = dp->data;
225 atomic_inc(&obd->obd_evict_inprogress);
230 int lprocfs_evict_client_release(struct inode *inode, struct file *f)
232 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
233 struct obd_device *obd = dp->data;
235 atomic_dec(&obd->obd_evict_inprogress);
236 wake_up(&obd->obd_evict_inprogress_waitq);
241 struct file_operations lprocfs_evict_client_fops = {
242 .owner = THIS_MODULE,
243 .read = lprocfs_fops_read,
244 .write = lprocfs_fops_write,
245 .open = lprocfs_evict_client_open,
246 .release = lprocfs_evict_client_release,
248 EXPORT_SYMBOL(lprocfs_evict_client_fops);
250 int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list,
253 if (root == NULL || list == NULL)
256 while (list->name != NULL) {
257 struct proc_dir_entry *cur_root, *proc;
258 char *pathcopy, *cur, *next, pathbuf[64];
259 int pathsize = strlen(list->name) + 1;
264 /* need copy of path for strsep */
265 if (strlen(list->name) > sizeof(pathbuf) - 1) {
266 OBD_ALLOC(pathcopy, pathsize);
267 if (pathcopy == NULL)
274 strcpy(pathcopy, list->name);
276 while (cur_root != NULL && (cur = strsep(&next, "/"))) {
277 if (*cur =='\0') /* skip double/trailing "/" */
280 proc = lprocfs_srch(cur_root, cur);
281 CDEBUG(D_OTHER, "cur_root=%s, cur=%s, next=%s, (%s)\n",
282 cur_root->name, cur, next,
283 (proc ? "exists" : "new"));
285 cur_root = (proc ? proc :
286 proc_mkdir(cur, cur_root));
287 } else if (proc == NULL) {
291 if (list->write_fptr)
293 proc = create_proc_entry(cur, mode, cur_root);
297 if (pathcopy != pathbuf)
298 OBD_FREE(pathcopy, pathsize);
300 if (cur_root == NULL || proc == NULL) {
301 CERROR("LprocFS: No memory to create /proc entry %s",
307 proc->proc_fops = list->fops;
309 proc->proc_fops = &lprocfs_generic_fops;
310 proc->read_proc = list->read_fptr;
311 proc->write_proc = list->write_fptr;
312 proc->data = (list->data ? list->data : data);
318 void lprocfs_remove(struct proc_dir_entry **rooth)
320 struct proc_dir_entry *root = *rooth;
321 struct proc_dir_entry *temp = root;
322 struct proc_dir_entry *rm_entry;
323 struct proc_dir_entry *parent;
329 parent = root->parent;
330 LASSERT(parent != NULL);
331 LPROCFS_WRITE_ENTRY(); /* search vs remove race */
334 while (temp->subdir != NULL)
340 /* Memory corruption once caused this to fail, and
341 without this LASSERT we would loop here forever. */
342 LASSERTF(strlen(rm_entry->name) == rm_entry->namelen,
343 "0x%p %s/%s len %d\n", rm_entry, temp->name,
344 rm_entry->name, (int)strlen(rm_entry->name));
346 /* Now, the rm_entry->deleted flags is protected
347 * by _lprocfs_lock. */
348 rm_entry->data = NULL;
349 remove_proc_entry(rm_entry->name, temp);
353 LPROCFS_WRITE_EXIT();
356 void lprocfs_remove_proc_entry(const char *name, struct proc_dir_entry *parent)
358 LASSERT(parent != NULL);
359 remove_proc_entry(name, parent);
362 struct proc_dir_entry *lprocfs_register(const char *name,
363 struct proc_dir_entry *parent,
364 struct lprocfs_vars *list, void *data)
366 struct proc_dir_entry *newchild;
368 newchild = lprocfs_srch(parent, name);
369 if (newchild != NULL) {
370 CERROR(" Lproc: Attempting to register %s more than once \n",
372 return ERR_PTR(-EALREADY);
375 newchild = proc_mkdir(name, parent);
376 if (newchild != NULL && list != NULL) {
377 int rc = lprocfs_add_vars(newchild, list, data);
379 lprocfs_remove(&newchild);
386 /* Generic callbacks */
387 int lprocfs_rd_uint(char *page, char **start, off_t off,
388 int count, int *eof, void *data)
390 unsigned int *temp = (unsigned int *)data;
391 return snprintf(page, count, "%u\n", *temp);
394 int lprocfs_wr_uint(struct file *file, const char *buffer,
395 unsigned long count, void *data)
398 char dummy[MAX_STRING_SIZE + 1], *end;
401 dummy[MAX_STRING_SIZE] = '\0';
402 if (copy_from_user(dummy, buffer, MAX_STRING_SIZE))
405 tmp = simple_strtoul(dummy, &end, 0);
409 *p = (unsigned int)tmp;
413 int lprocfs_rd_u64(char *page, char **start, off_t off,
414 int count, int *eof, void *data)
416 LASSERT(data != NULL);
418 return snprintf(page, count, LPU64"\n", *(__u64 *)data);
421 int lprocfs_rd_atomic(char *page, char **start, off_t off,
422 int count, int *eof, void *data)
424 atomic_t *atom = (atomic_t *)data;
425 LASSERT(atom != NULL);
427 return snprintf(page, count, "%d\n", atomic_read(atom));
430 int lprocfs_wr_atomic(struct file *file, const char *buffer,
431 unsigned long count, void *data)
433 atomic_t *atm = data;
437 rc = lprocfs_write_helper(buffer, count, &val);
444 atomic_set(atm, val);
448 int lprocfs_rd_uuid(char *page, char **start, off_t off, int count,
449 int *eof, void *data)
451 struct obd_device *obd = (struct obd_device*)data;
453 LASSERT(obd != NULL);
455 return snprintf(page, count, "%s\n", obd->obd_uuid.uuid);
458 int lprocfs_rd_name(char *page, char **start, off_t off, int count,
459 int *eof, void* data)
461 struct obd_device *dev = (struct obd_device *)data;
463 LASSERT(dev != NULL);
464 LASSERT(dev->obd_name != NULL);
466 return snprintf(page, count, "%s\n", dev->obd_name);
469 int lprocfs_rd_fstype(char *page, char **start, off_t off, int count, int *eof,
472 struct obd_device *obd = (struct obd_device *)data;
474 LASSERT(obd != NULL);
475 LASSERT(obd->obd_fsops != NULL);
476 LASSERT(obd->obd_fsops->fs_type != NULL);
477 return snprintf(page, count, "%s\n", obd->obd_fsops->fs_type);
480 int lprocfs_rd_blksize(char *page, char **start, off_t off, int count,
481 int *eof, void *data)
483 struct obd_statfs osfs;
484 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ,
488 rc = snprintf(page, count, "%u\n", osfs.os_bsize);
493 int lprocfs_rd_kbytestotal(char *page, char **start, off_t off, int count,
494 int *eof, void *data)
496 struct obd_statfs osfs;
497 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ,
500 __u32 blk_size = osfs.os_bsize >> 10;
501 __u64 result = osfs.os_blocks;
503 while (blk_size >>= 1)
507 rc = snprintf(page, count, LPU64"\n", result);
512 int lprocfs_rd_kbytesfree(char *page, char **start, off_t off, int count,
513 int *eof, void *data)
515 struct obd_statfs osfs;
516 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ,
519 __u32 blk_size = osfs.os_bsize >> 10;
520 __u64 result = osfs.os_bfree;
522 while (blk_size >>= 1)
526 rc = snprintf(page, count, LPU64"\n", result);
531 int lprocfs_rd_kbytesavail(char *page, char **start, off_t off, int count,
532 int *eof, void *data)
534 struct obd_statfs osfs;
535 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ,
538 __u32 blk_size = osfs.os_bsize >> 10;
539 __u64 result = osfs.os_bavail;
541 while (blk_size >>= 1)
545 rc = snprintf(page, count, LPU64"\n", result);
550 int lprocfs_rd_filestotal(char *page, char **start, off_t off, int count,
551 int *eof, void *data)
553 struct obd_statfs osfs;
554 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ,
558 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
564 int lprocfs_rd_filesfree(char *page, char **start, off_t off, int count,
565 int *eof, void *data)
567 struct obd_statfs osfs;
568 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ,
572 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
577 int lprocfs_rd_server_uuid(char *page, char **start, off_t off, int count,
578 int *eof, void *data)
580 struct obd_device *obd = (struct obd_device *)data;
581 struct obd_import *imp;
582 char *imp_state_name = NULL;
585 LASSERT(obd != NULL);
586 LPROCFS_CLIMP_CHECK(obd);
587 imp = obd->u.cli.cl_import;
588 imp_state_name = ptlrpc_import_state_name(imp->imp_state);
590 rc = snprintf(page, count, "%s\t%s%s\n",
591 obd2cli_tgt(obd), imp_state_name,
592 imp->imp_deactive ? "\tDEACTIVATED" : "");
594 LPROCFS_CLIMP_EXIT(obd);
598 int lprocfs_rd_conn_uuid(char *page, char **start, off_t off, int count,
599 int *eof, void *data)
601 struct obd_device *obd = (struct obd_device*)data;
602 struct ptlrpc_connection *conn;
605 LASSERT(obd != NULL);
607 LPROCFS_CLIMP_CHECK(obd);
608 conn = obd->u.cli.cl_import->imp_connection;
609 LASSERT(conn != NULL);
611 if (obd->u.cli.cl_import) {
612 rc = snprintf(page, count, "%s\n",
613 conn->c_remote_uuid.uuid);
615 rc = snprintf(page, count, "%s\n", "<none>");
618 LPROCFS_CLIMP_EXIT(obd);
622 int lprocfs_at_hist_helper(char *page, int count, int rc,
623 struct adaptive_timeout *at)
626 for (i = 0; i < AT_BINS; i++)
627 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
628 rc += snprintf(page + rc, count - rc, "\n");
632 /* See also ptlrpc_lprocfs_rd_timeouts */
633 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
634 int *eof, void *data)
636 struct obd_device *obd = (struct obd_device *)data;
637 struct obd_import *imp;
638 unsigned int cur, worst;
643 LASSERT(obd != NULL);
644 LPROCFS_CLIMP_CHECK(obd);
645 imp = obd->u.cli.cl_import;
648 now = cfs_time_current_sec();
650 /* Some network health info for kicks */
651 s2dhms(&ts, now - imp->imp_last_reply_time);
652 rc += snprintf(page + rc, count - rc,
653 "%-10s : %ld, "DHMS_FMT" ago\n",
654 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
657 cur = at_get(&imp->imp_at.iat_net_latency);
658 worst = imp->imp_at.iat_net_latency.at_worst_ever;
659 worstt = imp->imp_at.iat_net_latency.at_worst_time;
660 s2dhms(&ts, now - worstt);
661 rc += snprintf(page + rc, count - rc,
662 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
663 "network", cur, worst, worstt, DHMS_VARS(&ts));
664 rc = lprocfs_at_hist_helper(page, count, rc,
665 &imp->imp_at.iat_net_latency);
667 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
668 if (imp->imp_at.iat_portal[i] == 0)
670 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
671 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
672 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
673 s2dhms(&ts, now - worstt);
674 rc += snprintf(page + rc, count - rc,
675 "portal %-2d : cur %3u worst %3u (at %ld, "
676 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
677 cur, worst, worstt, DHMS_VARS(&ts));
678 rc = lprocfs_at_hist_helper(page, count, rc,
679 &imp->imp_at.iat_service_estimate[i]);
682 LPROCFS_CLIMP_EXIT(obd);
686 static const char *obd_connect_names[] = {
713 "mds_mds_connection",
716 "alt_checksum_algorithm",
721 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
722 int count, int *eof, void *data)
724 struct obd_device *obd = data;
725 __u64 mask = 1, flags;
728 LPROCFS_CLIMP_CHECK(obd);
729 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
730 ret = snprintf(page, count, "flags="LPX64"\n", flags);
731 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
733 ret += snprintf(page + ret, count - ret, "%s\n",
734 obd_connect_names[i]);
736 if (flags & ~(mask - 1))
737 ret += snprintf(page + ret, count - ret,
738 "unknown flags "LPX64"\n", flags & ~(mask - 1));
740 LPROCFS_CLIMP_EXIT(obd);
743 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
745 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
746 int *eof, void *data)
748 struct obd_device *obd = (struct obd_device*)data;
750 LASSERT(obd != NULL);
752 return snprintf(page, count, "%u\n", obd->obd_num_exports);
755 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
756 int *eof, void *data)
758 struct obd_type *class = (struct obd_type*) data;
760 LASSERT(class != NULL);
762 return snprintf(page, count, "%d\n", class->typ_refcnt);
765 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
769 LASSERT(obd != NULL);
770 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
771 LASSERT(obd->obd_type->typ_procroot != NULL);
773 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
774 obd->obd_type->typ_procroot,
776 if (IS_ERR(obd->obd_proc_entry)) {
777 rc = PTR_ERR(obd->obd_proc_entry);
778 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
779 obd->obd_proc_entry = NULL;
784 int lprocfs_obd_cleanup(struct obd_device *obd)
788 if (obd->obd_proc_exports_entry) {
789 /* Should be no exports left */
790 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
791 lprocfs_remove(&obd->obd_proc_exports_entry);
793 lprocfs_remove(&obd->obd_proc_entry);
797 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
799 CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
800 client_stat->nid_proc, client_stat->nid_stats,
801 client_stat->nid_brw_stats);
803 LASSERTF(client_stat->nid_exp_ref_count == 0, "count %d\n",
804 client_stat->nid_exp_ref_count);
806 hlist_del_init(&client_stat->nid_hash);
808 if (client_stat->nid_proc)
809 lprocfs_remove(&client_stat->nid_proc);
811 if (client_stat->nid_stats)
812 lprocfs_free_stats(&client_stat->nid_stats);
814 if (client_stat->nid_brw_stats)
815 OBD_FREE(client_stat->nid_brw_stats, sizeof(struct brw_stats));
817 OBD_FREE(client_stat, sizeof(*client_stat));
822 void lprocfs_free_per_client_stats(struct obd_device *obd)
824 struct nid_stat *stat;
827 /* we need extra list - because hash_exit called to early */
828 /* not need locking because all clients is died */
829 while(!list_empty(&obd->obd_nid_stats)) {
830 stat = list_entry(obd->obd_nid_stats.next,
831 struct nid_stat, nid_list);
832 list_del_init(&stat->nid_list);
833 lprocfs_free_client_stats(stat);
839 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
840 enum lprocfs_stats_flags flags)
842 struct lprocfs_stats *stats;
843 unsigned int percpusize;
845 unsigned int num_cpu;
850 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
853 num_cpu = num_possible_cpus();
855 OBD_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
859 if (flags & LPROCFS_STATS_FLAG_NOPERCPU) {
860 stats->ls_flags = flags;
861 spin_lock_init(&stats->ls_lock);
862 /* Use this lock only if there are no percpu areas */
867 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
869 percpusize = L1_CACHE_ALIGN(percpusize);
871 for (i = 0; i < num_cpu; i++) {
872 OBD_ALLOC(stats->ls_percpu[i], percpusize);
873 if (stats->ls_percpu[i] == NULL) {
874 for (j = 0; j < i; j++) {
875 OBD_FREE(stats->ls_percpu[j], percpusize);
876 stats->ls_percpu[j] = NULL;
881 if (stats->ls_percpu[0] == NULL) {
882 OBD_FREE(stats, offsetof(typeof(*stats),
883 ls_percpu[num_cpu]));
891 void lprocfs_free_stats(struct lprocfs_stats **statsh)
893 struct lprocfs_stats *stats = *statsh;
894 unsigned int num_cpu;
895 unsigned int percpusize;
898 if (stats == NULL || stats->ls_num == 0)
902 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
905 num_cpu = num_possible_cpus();
907 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
909 percpusize = L1_CACHE_ALIGN(percpusize);
910 for (i = 0; i < num_cpu; i++)
911 OBD_FREE(stats->ls_percpu[i], percpusize);
912 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
915 void lprocfs_clear_stats(struct lprocfs_stats *stats)
917 struct lprocfs_counter *percpu_cntr;
919 unsigned int num_cpu;
921 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
923 for (i = 0; i < num_cpu; i++) {
924 for (j = 0; j < stats->ls_num; j++) {
925 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
926 atomic_inc(&percpu_cntr->lc_cntl.la_entry);
927 percpu_cntr->lc_count = 0;
928 percpu_cntr->lc_sum = 0;
929 percpu_cntr->lc_min = LC_MIN_INIT;
930 percpu_cntr->lc_max = 0;
931 percpu_cntr->lc_sumsquare = 0;
932 atomic_inc(&percpu_cntr->lc_cntl.la_exit);
936 lprocfs_stats_unlock(stats);
939 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
940 size_t len, loff_t *off)
942 struct seq_file *seq = file->private_data;
943 struct lprocfs_stats *stats = seq->private;
945 lprocfs_clear_stats(stats);
950 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
952 struct lprocfs_stats *stats = p->private;
953 /* return 1st cpu location */
954 return (*pos >= stats->ls_num) ? NULL :
955 &(stats->ls_percpu[0]->lp_cntr[*pos]);
958 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
962 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
964 struct lprocfs_stats *stats = p->private;
966 return (*pos >= stats->ls_num) ? NULL :
967 &(stats->ls_percpu[0]->lp_cntr[*pos]);
970 /* seq file export of one lprocfs counter */
971 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
973 struct lprocfs_stats *stats = p->private;
974 struct lprocfs_counter *cntr = v;
975 struct lprocfs_counter t, ret = { .lc_min = LC_MIN_INIT };
977 unsigned int num_cpu;
979 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
981 do_gettimeofday(&now);
982 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
983 "snapshot_time", now.tv_sec, now.tv_usec);
987 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
989 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
992 num_cpu = num_possible_cpus();
994 for (i = 0; i < num_cpu; i++) {
995 struct lprocfs_counter *percpu_cntr =
996 &(stats->ls_percpu[i])->lp_cntr[idx];
1000 centry = atomic_read(&percpu_cntr->lc_cntl.la_entry);
1001 t.lc_count = percpu_cntr->lc_count;
1002 t.lc_sum = percpu_cntr->lc_sum;
1003 t.lc_min = percpu_cntr->lc_min;
1004 t.lc_max = percpu_cntr->lc_max;
1005 t.lc_sumsquare = percpu_cntr->lc_sumsquare;
1006 } while (centry != atomic_read(&percpu_cntr->lc_cntl.la_entry) &&
1007 centry != atomic_read(&percpu_cntr->lc_cntl.la_exit));
1008 ret.lc_count += t.lc_count;
1009 ret.lc_sum += t.lc_sum;
1010 if (t.lc_min < ret.lc_min)
1011 ret.lc_min = t.lc_min;
1012 if (t.lc_max > ret.lc_max)
1013 ret.lc_max = t.lc_max;
1014 ret.lc_sumsquare += t.lc_sumsquare;
1017 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", cntr->lc_name,
1018 ret.lc_count, cntr->lc_units);
1022 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
1023 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1024 ret.lc_min, ret.lc_max, ret.lc_sum);
1027 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
1028 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1032 rc = seq_printf(p, "\n");
1034 return (rc < 0) ? rc : 0;
1037 struct seq_operations lprocfs_stats_seq_sops = {
1038 start: lprocfs_stats_seq_start,
1039 stop: lprocfs_stats_seq_stop,
1040 next: lprocfs_stats_seq_next,
1041 show: lprocfs_stats_seq_show,
1044 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1046 struct proc_dir_entry *dp = PDE(inode);
1047 struct seq_file *seq;
1050 LPROCFS_ENTRY_AND_CHECK(dp);
1051 rc = seq_open(file, &lprocfs_stats_seq_sops);
1056 seq = file->private_data;
1057 seq->private = dp->data;
1061 struct file_operations lprocfs_stats_seq_fops = {
1062 .owner = THIS_MODULE,
1063 .open = lprocfs_stats_seq_open,
1065 .write = lprocfs_stats_seq_write,
1066 .llseek = seq_lseek,
1067 .release = lprocfs_seq_release,
1070 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1071 struct lprocfs_stats *stats)
1073 struct proc_dir_entry *entry;
1074 LASSERT(root != NULL);
1076 entry = create_proc_entry(name, 0644, root);
1079 entry->proc_fops = &lprocfs_stats_seq_fops;
1080 entry->data = (void *)stats;
1084 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1085 unsigned conf, const char *name, const char *units)
1087 struct lprocfs_counter *c;
1089 unsigned int num_cpu;
1091 LASSERT(stats != NULL);
1093 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1095 for (i = 0; i < num_cpu; i++) {
1096 c = &(stats->ls_percpu[i]->lp_cntr[index]);
1097 c->lc_config = conf;
1100 c->lc_min = LC_MIN_INIT;
1103 c->lc_units = units;
1106 lprocfs_stats_unlock(stats);
1108 EXPORT_SYMBOL(lprocfs_counter_init);
1110 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1112 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1113 LASSERT(coffset < stats->ls_num); \
1114 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1117 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1119 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1120 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1121 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1122 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1123 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1124 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1125 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1126 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1127 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1128 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1129 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1130 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1131 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1132 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1133 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1134 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1135 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1136 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1137 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
1138 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1139 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1140 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1141 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1142 LPROCFS_OBD_OP_INIT(num_private_stats, stats, checkmd);
1143 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1144 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1145 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1146 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1147 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1148 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1149 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1150 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1151 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1152 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw_async);
1153 LPROCFS_OBD_OP_INIT(num_private_stats, stats, prep_async_page);
1154 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reget_short_lock);
1155 LPROCFS_OBD_OP_INIT(num_private_stats, stats, release_short_lock);
1156 LPROCFS_OBD_OP_INIT(num_private_stats, stats, queue_async_io);
1157 LPROCFS_OBD_OP_INIT(num_private_stats, stats, queue_group_io);
1158 LPROCFS_OBD_OP_INIT(num_private_stats, stats, trigger_group_io);
1159 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_async_flags);
1160 LPROCFS_OBD_OP_INIT(num_private_stats, stats, teardown_async_page);
1161 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1162 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1163 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1164 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1165 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1166 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1167 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1168 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1169 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1170 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1171 LPROCFS_OBD_OP_INIT(num_private_stats, stats, match);
1172 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1173 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1174 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1175 LPROCFS_OBD_OP_INIT(num_private_stats, stats, join_lru);
1176 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1177 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1178 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1179 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1180 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1181 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1182 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1183 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1184 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1185 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1186 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1187 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1188 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1189 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1190 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1191 LPROCFS_OBD_OP_INIT(num_private_stats, stats, register_page_removal_cb);
1192 LPROCFS_OBD_OP_INIT(num_private_stats,stats,unregister_page_removal_cb);
1193 LPROCFS_OBD_OP_INIT(num_private_stats, stats, register_lock_cancel_cb);
1194 LPROCFS_OBD_OP_INIT(num_private_stats, stats,unregister_lock_cancel_cb);
1197 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1199 struct lprocfs_stats *stats;
1200 unsigned int num_stats;
1203 LASSERT(obd->obd_stats == NULL);
1204 LASSERT(obd->obd_proc_entry != NULL);
1205 LASSERT(obd->obd_cntr_base == 0);
1207 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1208 num_private_stats - 1 /* o_owner */;
1209 stats = lprocfs_alloc_stats(num_stats, 0);
1213 lprocfs_init_ops_stats(num_private_stats, stats);
1215 for (i = num_private_stats; i < num_stats; i++) {
1216 /* If this LBUGs, it is likely that an obd
1217 * operation was added to struct obd_ops in
1218 * <obd.h>, and that the corresponding line item
1219 * LPROCFS_OBD_OP_INIT(.., .., opname)
1220 * is missing from the list above. */
1221 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1222 "Missing obd_stat initializer obd_op "
1223 "operation at offset %d.\n", i - num_private_stats);
1225 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1227 lprocfs_free_stats(&stats);
1229 obd->obd_stats = stats;
1230 obd->obd_cntr_base = num_private_stats;
1235 void lprocfs_free_obd_stats(struct obd_device *obd)
1238 lprocfs_free_stats(&obd->obd_stats);
1241 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1243 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1244 LASSERT(coffset < stats->ls_num); \
1245 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1248 int lprocfs_alloc_md_stats(struct obd_device *obd,
1249 unsigned num_private_stats)
1251 struct lprocfs_stats *stats;
1252 unsigned int num_stats;
1255 LASSERT(obd->md_stats == NULL);
1256 LASSERT(obd->obd_proc_entry != NULL);
1257 LASSERT(obd->md_cntr_base == 0);
1259 num_stats = 1 + MD_COUNTER_OFFSET(get_remote_perm) +
1261 stats = lprocfs_alloc_stats(num_stats, 0);
1265 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1266 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1267 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1268 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1269 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1270 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1271 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1272 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1273 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1274 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1275 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1276 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1277 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1278 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1279 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1280 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1281 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1282 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1283 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1284 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1285 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1286 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1287 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1288 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1289 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1290 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1291 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1292 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1293 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1294 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1296 for (i = num_private_stats; i < num_stats; i++) {
1297 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1298 CERROR("Missing md_stat initializer md_op "
1299 "operation at offset %d. Aborting.\n",
1300 i - num_private_stats);
1304 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1306 lprocfs_free_stats(&stats);
1308 obd->md_stats = stats;
1309 obd->md_cntr_base = num_private_stats;
1314 void lprocfs_free_md_stats(struct obd_device *obd)
1316 struct lprocfs_stats *stats = obd->md_stats;
1318 if (stats != NULL) {
1319 obd->md_stats = NULL;
1320 lprocfs_free_stats(&stats);
1324 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1325 int *eof, void *data)
1327 struct obd_export *exp = (struct obd_export*)data;
1328 LASSERT(exp != NULL);
1330 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1333 struct exp_uuid_cb_data {
1340 void lprocfs_exp_print_uuid(void *obj, void *cb_data)
1342 struct obd_export *exp = (struct obd_export *)obj;
1343 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1345 if (exp->exp_nid_stats)
1346 *data->len += snprintf((data->page + *data->len),
1347 data->count, "%s\n",
1348 obd_uuid2str(&exp->exp_client_uuid));
1351 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1352 int *eof, void *data)
1354 struct nid_stat *stats = (struct nid_stat *)data;
1355 struct exp_uuid_cb_data cb_data;
1356 struct obd_device *obd = stats->nid_obd;
1361 LASSERT(obd != NULL);
1363 cb_data.page = page;
1364 cb_data.count = count;
1367 lustre_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1368 lprocfs_exp_print_uuid, &cb_data);
1369 return (*cb_data.len);
1372 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1373 int count, int *eof, void *data)
1376 return snprintf(page, count, "%s\n",
1377 "Write into this file to clear all nid stats and "
1378 "stale nid entries");
1380 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1382 void lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1384 struct nid_stat *stat = obj;
1387 /* object has only hash + iterate_all references.
1388 * add/delete blocked by hash bucket lock */
1389 CDEBUG(D_INFO,"refcnt %d\n", stat->nid_exp_ref_count);
1390 if(stat->nid_exp_ref_count == 2) {
1391 hlist_del_init(&stat->nid_hash);
1392 stat->nid_exp_ref_count--;
1393 spin_lock(&stat->nid_obd->obd_nid_lock);
1394 list_del_init(&stat->nid_list);
1395 spin_unlock(&stat->nid_obd->obd_nid_lock);
1396 list_add(&stat->nid_list, data);
1400 /* we has reference to object - only clear data*/
1401 if (stat->nid_stats)
1402 lprocfs_clear_stats(stat->nid_stats);
1404 if (stat->nid_brw_stats) {
1405 for (i = 0; i < BRW_LAST; i++)
1406 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
1412 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1413 unsigned long count, void *data)
1415 struct obd_device *obd = (struct obd_device *)data;
1416 struct nid_stat *client_stat;
1417 CFS_LIST_HEAD(free_list);
1419 lustre_hash_for_each(obd->obd_nid_stats_hash,
1420 lprocfs_nid_stats_clear_write_cb, &free_list);
1422 while (!list_empty(&free_list)) {
1423 client_stat = list_entry(free_list.next, struct nid_stat, nid_list);
1424 list_del_init(&client_stat->nid_list);
1425 lprocfs_free_client_stats(client_stat);
1430 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1432 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1435 struct nid_stat *tmp = NULL, *tmp1;
1436 struct obd_device *obd = NULL;
1441 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1442 !exp->exp_obd->obd_nid_stats_hash)
1445 /* not test against zero because eric say:
1446 * You may only test nid against another nid, or LNET_NID_ANY. Anything else is
1448 if (!nid || *nid == LNET_NID_ANY)
1453 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
1455 OBD_ALLOC(tmp, sizeof(struct nid_stat));
1460 tmp->nid_obd = exp->exp_obd;
1461 tmp->nid_exp_ref_count = 1; /* need live in hash after destroy export */
1463 /* protect competitive add to list, not need locking on destroy */
1464 spin_lock(&obd->obd_nid_lock);
1465 list_add(&tmp->nid_list, &obd->obd_nid_stats);
1466 spin_unlock(&obd->obd_nid_lock);
1468 tmp1 = lustre_hash_findadd_unique(obd->obd_nid_stats_hash,
1469 nid, &tmp->nid_hash);
1470 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
1471 tmp1, libcfs_nid2str(*nid), tmp->nid_exp_ref_count);
1474 exp->exp_nid_stats = tmp1;
1475 GOTO(destroy_new, rc = 0);
1477 /* not found - create */
1478 tmp->nid_proc = lprocfs_register(libcfs_nid2str(*nid),
1479 obd->obd_proc_exports_entry, NULL, NULL);
1480 if (!tmp->nid_proc) {
1481 CERROR("Error making export directory for"
1482 " nid %s\n", libcfs_nid2str(*nid));
1483 lustre_hash_del(obd->obd_nid_stats_hash, nid, &tmp->nid_hash);
1484 GOTO(destroy_new, rc = -ENOMEM);
1487 rc = lprocfs_add_simple(tmp->nid_proc, "uuid",
1488 lprocfs_exp_rd_uuid, NULL, tmp);
1490 CWARN("Error adding the uuid file\n");
1492 exp->exp_nid_stats = tmp;
1497 spin_lock(&obd->obd_nid_lock);
1498 list_del(&tmp->nid_list);
1499 spin_unlock(&obd->obd_nid_lock);
1500 OBD_FREE(tmp, sizeof(struct nid_stat));
1504 int lprocfs_exp_cleanup(struct obd_export *exp)
1506 struct nid_stat *stat = exp->exp_nid_stats;
1511 stat->nid_exp_ref_count--;
1512 CDEBUG(D_INFO, "Put stat %p - %d\n", stat, stat->nid_exp_ref_count);
1514 exp->exp_nid_stats = NULL;
1518 int lprocfs_write_helper(const char *buffer, unsigned long count,
1521 return lprocfs_write_frac_helper(buffer, count, val, 1);
1524 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
1527 char kernbuf[20], *end, *pbuf;
1529 if (count > (sizeof(kernbuf) - 1))
1532 if (copy_from_user(kernbuf, buffer, count))
1535 kernbuf[count] = '\0';
1542 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1546 if (end != NULL && *end == '.') {
1547 int temp_val, pow = 1;
1551 if (strlen(pbuf) > 5)
1552 pbuf[5] = '\0'; /*only allow 5bits fractional*/
1554 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1557 for (i = 0; i < (end - pbuf); i++)
1560 *val += temp_val / pow;
1566 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val, int mult)
1568 long decimal_val, frac_val;
1574 decimal_val = val / mult;
1575 prtn = snprintf(buffer, count, "%ld", decimal_val);
1576 frac_val = val % mult;
1578 if (prtn < (count - 4) && frac_val > 0) {
1580 int i, temp_mult = 1, frac_bits = 0;
1582 temp_frac = frac_val * 10;
1583 buffer[prtn++] = '.';
1584 while (frac_bits < 2 && (temp_frac / mult) < 1 ) { /*only reserved 2bits fraction*/
1585 buffer[prtn++] ='0';
1590 Need to think these cases :
1591 1. #echo x.00 > /proc/xxx output result : x
1592 2. #echo x.0x > /proc/xxx output result : x.0x
1593 3. #echo x.x0 > /proc/xxx output result : x.x
1594 4. #echo x.xx > /proc/xxx output result : x.xx
1595 Only reserved 2bits fraction.
1597 for (i = 0; i < (5 - prtn); i++)
1600 frac_bits = min((int)count - prtn, 3 - frac_bits);
1601 prtn += snprintf(buffer + prtn, frac_bits, "%ld", frac_val * temp_mult / mult);
1604 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
1606 if (buffer[prtn] == '.') {
1613 buffer[prtn++] ='\n';
1617 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
1619 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
1622 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
1623 __u64 *val, int mult)
1625 char kernbuf[22], *end, *pbuf;
1626 __u64 whole, frac = 0, units;
1627 unsigned frac_d = 1;
1629 if (count > (sizeof(kernbuf) - 1) )
1632 if (copy_from_user(kernbuf, buffer, count))
1635 kernbuf[count] = '\0';
1642 whole = simple_strtoull(pbuf, &end, 10);
1646 if (end != NULL && *end == '.') {
1650 /* need to limit frac_d to a __u32 */
1651 if (strlen(pbuf) > 10)
1654 frac = simple_strtoull(pbuf, &end, 10);
1655 /* count decimal places */
1656 for (i = 0; i < (end - pbuf); i++)
1673 /* Specified units override the multiplier */
1675 mult = mult < 0 ? -units : units;
1678 do_div(frac, frac_d);
1679 *val = whole * mult + frac;
1683 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent,
1684 char *name, mode_t mode,
1685 struct file_operations *seq_fops, void *data)
1687 struct proc_dir_entry *entry;
1690 entry = create_proc_entry(name, mode, parent);
1693 entry->proc_fops = seq_fops;
1698 EXPORT_SYMBOL(lprocfs_seq_create);
1700 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
1702 struct file_operations *seq_fops,
1705 return (lprocfs_seq_create(dev->obd_proc_entry, name,
1706 mode, seq_fops, data));
1708 EXPORT_SYMBOL(lprocfs_obd_seq_create);
1710 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
1712 if (value >= OBD_HIST_MAX)
1713 value = OBD_HIST_MAX - 1;
1715 spin_lock(&oh->oh_lock);
1716 oh->oh_buckets[value]++;
1717 spin_unlock(&oh->oh_lock);
1719 EXPORT_SYMBOL(lprocfs_oh_tally);
1721 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
1725 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
1728 lprocfs_oh_tally(oh, val);
1730 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
1732 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
1734 unsigned long ret = 0;
1737 for (i = 0; i < OBD_HIST_MAX; i++)
1738 ret += oh->oh_buckets[i];
1741 EXPORT_SYMBOL(lprocfs_oh_sum);
1743 void lprocfs_oh_clear(struct obd_histogram *oh)
1745 spin_lock(&oh->oh_lock);
1746 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
1747 spin_unlock(&oh->oh_lock);
1749 EXPORT_SYMBOL(lprocfs_oh_clear);
1751 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
1752 int count, int *eof, void *data)
1754 struct obd_device *obd = data;
1760 c += lustre_hash_debug_header(page, count);
1761 c += lustre_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
1762 c += lustre_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
1763 c += lustre_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
1767 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
1769 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
1770 int count, int *eof, void *data)
1772 struct obd_device *obd = data;
1775 LASSERT(obd != NULL);
1776 LASSERT(count >= 0);
1778 /* Set start of user data returned to
1779 page + off since the user may have
1780 requested to read much smaller than
1781 what we need to read */
1782 *start = page + off;
1784 /* We know we are allocated a page here.
1785 Also we know that this function will
1786 not need to write more than a page
1787 so we can truncate at CFS_PAGE_SIZE. */
1788 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
1790 /* Initialize the page */
1791 memset(page, 0, size);
1793 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
1795 if (obd->obd_max_recoverable_clients == 0) {
1796 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
1802 /* sampled unlocked, but really... */
1803 if (obd->obd_recovering == 0) {
1804 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
1806 if (lprocfs_obd_snprintf(&page, size, &len,
1807 "recovery_start: %lu\n",
1808 obd->obd_recovery_start) <= 0)
1810 if (lprocfs_obd_snprintf(&page, size, &len,
1811 "recovery_duration: %lu\n",
1812 obd->obd_recovery_end -
1813 obd->obd_recovery_start) <= 0)
1815 /* Number of clients that have completed recovery */
1816 if (lprocfs_obd_snprintf(&page, size, &len,
1817 "completed_clients: %d/%d\n",
1818 obd->obd_max_recoverable_clients -
1819 obd->obd_recoverable_clients,
1820 obd->obd_max_recoverable_clients) <= 0)
1822 if (lprocfs_obd_snprintf(&page, size, &len,
1823 "replayed_requests: %d\n",
1824 obd->obd_replayed_requests) <= 0)
1826 if (lprocfs_obd_snprintf(&page, size, &len,
1827 "last_transno: "LPD64"\n",
1828 obd->obd_next_recovery_transno - 1)<=0)
1833 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
1835 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
1836 obd->obd_recovery_start) <= 0)
1838 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
1839 cfs_time_current_sec() >= obd->obd_recovery_end ? 0 :
1840 obd->obd_recovery_end - cfs_time_current_sec()) <= 0)
1842 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
1843 obd->obd_connected_clients,
1844 obd->obd_max_recoverable_clients) <= 0)
1846 /* Number of clients that have completed recovery */
1847 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d/%d\n",
1848 obd->obd_max_recoverable_clients -
1849 obd->obd_recoverable_clients,
1850 obd->obd_max_recoverable_clients) <= 0)
1852 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d/??\n",
1853 obd->obd_replayed_requests) <= 0)
1855 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
1856 obd->obd_requests_queued_for_recovery) <= 0)
1859 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
1860 obd->obd_next_recovery_transno) <= 0)
1866 return min(count, len - (int)off);
1868 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
1870 int lprocfs_obd_rd_recovery_maxtime(char *page, char **start, off_t off,
1871 int count, int *eof, void *data)
1873 struct obd_device *obd = (struct obd_device *)data;
1874 LASSERT(obd != NULL);
1876 return snprintf(page, count, "%lu\n",
1877 obd->obd_recovery_max_time);
1879 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_maxtime);
1881 int lprocfs_obd_wr_recovery_maxtime(struct file *file, const char *buffer,
1882 unsigned long count, void *data)
1884 struct obd_device *obd = (struct obd_device *)data;
1886 LASSERT(obd != NULL);
1888 rc = lprocfs_write_helper(buffer, count, &val);
1892 obd->obd_recovery_max_time = val;
1895 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_maxtime);
1897 EXPORT_SYMBOL(lprocfs_register);
1898 EXPORT_SYMBOL(lprocfs_srch);
1899 EXPORT_SYMBOL(lprocfs_remove);
1900 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
1901 EXPORT_SYMBOL(lprocfs_add_vars);
1902 EXPORT_SYMBOL(lprocfs_obd_setup);
1903 EXPORT_SYMBOL(lprocfs_obd_cleanup);
1904 EXPORT_SYMBOL(lprocfs_add_simple);
1905 EXPORT_SYMBOL(lprocfs_add_symlink);
1906 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
1907 EXPORT_SYMBOL(lprocfs_alloc_stats);
1908 EXPORT_SYMBOL(lprocfs_free_stats);
1909 EXPORT_SYMBOL(lprocfs_clear_stats);
1910 EXPORT_SYMBOL(lprocfs_register_stats);
1911 EXPORT_SYMBOL(lprocfs_init_ops_stats);
1912 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
1913 EXPORT_SYMBOL(lprocfs_free_obd_stats);
1914 EXPORT_SYMBOL(lprocfs_exp_setup);
1915 EXPORT_SYMBOL(lprocfs_exp_cleanup);
1917 EXPORT_SYMBOL(lprocfs_rd_u64);
1918 EXPORT_SYMBOL(lprocfs_rd_atomic);
1919 EXPORT_SYMBOL(lprocfs_wr_atomic);
1920 EXPORT_SYMBOL(lprocfs_rd_uint);
1921 EXPORT_SYMBOL(lprocfs_wr_uint);
1922 EXPORT_SYMBOL(lprocfs_rd_uuid);
1923 EXPORT_SYMBOL(lprocfs_rd_name);
1924 EXPORT_SYMBOL(lprocfs_rd_fstype);
1925 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
1926 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
1927 EXPORT_SYMBOL(lprocfs_rd_num_exports);
1928 EXPORT_SYMBOL(lprocfs_rd_numrefs);
1929 EXPORT_SYMBOL(lprocfs_at_hist_helper);
1930 EXPORT_SYMBOL(lprocfs_rd_timeouts);
1931 EXPORT_SYMBOL(lprocfs_rd_blksize);
1932 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
1933 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
1934 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
1935 EXPORT_SYMBOL(lprocfs_rd_filestotal);
1936 EXPORT_SYMBOL(lprocfs_rd_filesfree);
1938 EXPORT_SYMBOL(lprocfs_write_helper);
1939 EXPORT_SYMBOL(lprocfs_write_frac_helper);
1940 EXPORT_SYMBOL(lprocfs_read_frac_helper);
1941 EXPORT_SYMBOL(lprocfs_write_u64_helper);
1942 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);