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 cfs_proc_dir_entry_t *lprocfs_add_simple(struct proc_dir_entry *root,
116 read_proc_t *read_proc,
117 write_proc_t *write_proc,
119 struct file_operations *fops)
121 cfs_proc_dir_entry_t *proc;
124 if (root == NULL || name == NULL)
125 return ERR_PTR(-EINVAL);
132 proc = create_proc_entry(name, mode, root);
134 CERROR("LprocFS: No memory to create /proc entry %s", name);
135 return ERR_PTR(-ENOMEM);
137 proc->read_proc = read_proc;
138 proc->write_proc = write_proc;
141 proc->proc_fops = fops;
145 struct proc_dir_entry *lprocfs_add_symlink(const char *name,
146 struct proc_dir_entry *parent, const char *dest)
148 struct proc_dir_entry *entry;
150 if (parent == NULL || dest == NULL)
153 entry = proc_symlink(name, parent, dest);
155 CERROR("LprocFS: Could not create symbolic link from %s to %s",
160 static ssize_t lprocfs_fops_read(struct file *f, char __user *buf,
161 size_t size, loff_t *ppos)
163 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
164 char *page, *start = NULL;
165 int rc = 0, eof = 1, count;
167 if (*ppos >= CFS_PAGE_SIZE)
170 page = (char *)__get_free_page(GFP_KERNEL);
175 OBD_FAIL_TIMEOUT(OBD_FAIL_LPROC_REMOVE, 10);
176 if (!dp->deleted && dp->read_proc)
177 rc = dp->read_proc(page, &start, *ppos, CFS_PAGE_SIZE,
183 /* for lustre proc read, the read count must be less than PAGE_SIZE */
192 start = page + *ppos;
193 } else if (start < page) {
197 count = (rc < size) ? rc : size;
198 if (copy_to_user(buf, start, count)) {
205 free_page((unsigned long)page);
209 static ssize_t lprocfs_fops_write(struct file *f, const char __user *buf, size_t size, loff_t *ppos)
211 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
215 if (!dp->deleted && dp->write_proc)
216 rc = dp->write_proc(f, buf, size, dp->data);
221 static struct file_operations lprocfs_generic_fops = {
222 .owner = THIS_MODULE,
223 .read = lprocfs_fops_read,
224 .write = lprocfs_fops_write,
227 int lprocfs_evict_client_open(struct inode *inode, struct file *f)
229 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
230 struct obd_device *obd = dp->data;
232 atomic_inc(&obd->obd_evict_inprogress);
237 int lprocfs_evict_client_release(struct inode *inode, struct file *f)
239 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
240 struct obd_device *obd = dp->data;
242 atomic_dec(&obd->obd_evict_inprogress);
243 wake_up(&obd->obd_evict_inprogress_waitq);
248 struct file_operations lprocfs_evict_client_fops = {
249 .owner = THIS_MODULE,
250 .read = lprocfs_fops_read,
251 .write = lprocfs_fops_write,
252 .open = lprocfs_evict_client_open,
253 .release = lprocfs_evict_client_release,
255 EXPORT_SYMBOL(lprocfs_evict_client_fops);
260 * \param root [in] The parent proc entry on which new entry will be added.
261 * \param list [in] Array of proc entries to be added.
262 * \param data [in] The argument to be passed when entries read/write routines
263 * are called through /proc file.
265 * \retval 0 on success
268 int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list,
271 if (root == NULL || list == NULL)
274 while (list->name != NULL) {
275 struct proc_dir_entry *cur_root, *proc;
276 char *pathcopy, *cur, *next, pathbuf[64];
277 int pathsize = strlen(list->name) + 1;
282 /* need copy of path for strsep */
283 if (strlen(list->name) > sizeof(pathbuf) - 1) {
284 OBD_ALLOC(pathcopy, pathsize);
285 if (pathcopy == NULL)
292 strcpy(pathcopy, list->name);
294 while (cur_root != NULL && (cur = strsep(&next, "/"))) {
295 if (*cur =='\0') /* skip double/trailing "/" */
298 proc = lprocfs_srch(cur_root, cur);
299 CDEBUG(D_OTHER, "cur_root=%s, cur=%s, next=%s, (%s)\n",
300 cur_root->name, cur, next,
301 (proc ? "exists" : "new"));
303 cur_root = (proc ? proc :
304 proc_mkdir(cur, cur_root));
305 } else if (proc == NULL) {
307 if (list->proc_mode != 0000) {
308 mode = list->proc_mode;
312 if (list->write_fptr)
315 proc = create_proc_entry(cur, mode, cur_root);
319 if (pathcopy != pathbuf)
320 OBD_FREE(pathcopy, pathsize);
322 if (cur_root == NULL || proc == NULL) {
323 CERROR("LprocFS: No memory to create /proc entry %s",
329 proc->proc_fops = list->fops;
331 proc->proc_fops = &lprocfs_generic_fops;
332 proc->read_proc = list->read_fptr;
333 proc->write_proc = list->write_fptr;
334 proc->data = (list->data ? list->data : data);
340 void lprocfs_remove(struct proc_dir_entry **rooth)
342 struct proc_dir_entry *root = *rooth;
343 struct proc_dir_entry *temp = root;
344 struct proc_dir_entry *rm_entry;
345 struct proc_dir_entry *parent;
351 parent = root->parent;
352 LASSERT(parent != NULL);
353 LPROCFS_WRITE_ENTRY(); /* search vs remove race */
356 while (temp->subdir != NULL)
362 /* Memory corruption once caused this to fail, and
363 without this LASSERT we would loop here forever. */
364 LASSERTF(strlen(rm_entry->name) == rm_entry->namelen,
365 "0x%p %s/%s len %d\n", rm_entry, temp->name,
366 rm_entry->name, (int)strlen(rm_entry->name));
368 /* Now, the rm_entry->deleted flags is protected
369 * by _lprocfs_lock. */
370 rm_entry->data = NULL;
371 remove_proc_entry(rm_entry->name, temp);
375 LPROCFS_WRITE_EXIT();
378 void lprocfs_remove_proc_entry(const char *name, struct proc_dir_entry *parent)
380 LASSERT(parent != NULL);
381 remove_proc_entry(name, parent);
384 struct proc_dir_entry *lprocfs_register(const char *name,
385 struct proc_dir_entry *parent,
386 struct lprocfs_vars *list, void *data)
388 struct proc_dir_entry *newchild;
390 newchild = lprocfs_srch(parent, name);
391 if (newchild != NULL) {
392 CERROR(" Lproc: Attempting to register %s more than once \n",
394 return ERR_PTR(-EALREADY);
397 newchild = proc_mkdir(name, parent);
398 if (newchild != NULL && list != NULL) {
399 int rc = lprocfs_add_vars(newchild, list, data);
401 lprocfs_remove(&newchild);
408 /* Generic callbacks */
409 int lprocfs_rd_uint(char *page, char **start, off_t off,
410 int count, int *eof, void *data)
412 unsigned int *temp = (unsigned int *)data;
413 return snprintf(page, count, "%u\n", *temp);
416 int lprocfs_wr_uint(struct file *file, const char *buffer,
417 unsigned long count, void *data)
420 char dummy[MAX_STRING_SIZE + 1], *end;
423 dummy[MAX_STRING_SIZE] = '\0';
424 if (copy_from_user(dummy, buffer, MAX_STRING_SIZE))
427 tmp = simple_strtoul(dummy, &end, 0);
431 *p = (unsigned int)tmp;
435 int lprocfs_rd_u64(char *page, char **start, off_t off,
436 int count, int *eof, void *data)
438 LASSERT(data != NULL);
440 return snprintf(page, count, LPU64"\n", *(__u64 *)data);
443 int lprocfs_rd_atomic(char *page, char **start, off_t off,
444 int count, int *eof, void *data)
446 atomic_t *atom = (atomic_t *)data;
447 LASSERT(atom != NULL);
449 return snprintf(page, count, "%d\n", atomic_read(atom));
452 int lprocfs_wr_atomic(struct file *file, const char *buffer,
453 unsigned long count, void *data)
455 atomic_t *atm = data;
459 rc = lprocfs_write_helper(buffer, count, &val);
466 atomic_set(atm, val);
470 int lprocfs_rd_uuid(char *page, char **start, off_t off, int count,
471 int *eof, void *data)
473 struct obd_device *obd = (struct obd_device*)data;
475 LASSERT(obd != NULL);
477 return snprintf(page, count, "%s\n", obd->obd_uuid.uuid);
480 int lprocfs_rd_name(char *page, char **start, off_t off, int count,
481 int *eof, void* data)
483 struct obd_device *dev = (struct obd_device *)data;
485 LASSERT(dev != NULL);
486 LASSERT(dev->obd_name != NULL);
488 return snprintf(page, count, "%s\n", dev->obd_name);
491 int lprocfs_rd_fstype(char *page, char **start, off_t off, int count, int *eof,
494 struct obd_device *obd = (struct obd_device *)data;
496 LASSERT(obd != NULL);
497 LASSERT(obd->obd_fsops != NULL);
498 LASSERT(obd->obd_fsops->fs_type != NULL);
499 return snprintf(page, count, "%s\n", obd->obd_fsops->fs_type);
502 int lprocfs_rd_blksize(char *page, char **start, off_t off, int count,
503 int *eof, void *data)
505 struct obd_statfs osfs;
506 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ,
510 rc = snprintf(page, count, "%u\n", osfs.os_bsize);
515 int lprocfs_rd_kbytestotal(char *page, char **start, off_t off, int count,
516 int *eof, void *data)
518 struct obd_statfs osfs;
519 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ,
522 __u32 blk_size = osfs.os_bsize >> 10;
523 __u64 result = osfs.os_blocks;
525 while (blk_size >>= 1)
529 rc = snprintf(page, count, LPU64"\n", result);
534 int lprocfs_rd_kbytesfree(char *page, char **start, off_t off, int count,
535 int *eof, void *data)
537 struct obd_statfs osfs;
538 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ,
541 __u32 blk_size = osfs.os_bsize >> 10;
542 __u64 result = osfs.os_bfree;
544 while (blk_size >>= 1)
548 rc = snprintf(page, count, LPU64"\n", result);
553 int lprocfs_rd_kbytesavail(char *page, char **start, off_t off, int count,
554 int *eof, void *data)
556 struct obd_statfs osfs;
557 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ,
560 __u32 blk_size = osfs.os_bsize >> 10;
561 __u64 result = osfs.os_bavail;
563 while (blk_size >>= 1)
567 rc = snprintf(page, count, LPU64"\n", result);
572 int lprocfs_rd_filestotal(char *page, char **start, off_t off, int count,
573 int *eof, void *data)
575 struct obd_statfs osfs;
576 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ,
580 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
586 int lprocfs_rd_filesfree(char *page, char **start, off_t off, int count,
587 int *eof, void *data)
589 struct obd_statfs osfs;
590 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ,
594 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
599 int lprocfs_rd_server_uuid(char *page, char **start, off_t off, int count,
600 int *eof, void *data)
602 struct obd_device *obd = (struct obd_device *)data;
603 struct obd_import *imp;
604 char *imp_state_name = NULL;
607 LASSERT(obd != NULL);
608 LPROCFS_CLIMP_CHECK(obd);
609 imp = obd->u.cli.cl_import;
610 imp_state_name = ptlrpc_import_state_name(imp->imp_state);
612 rc = snprintf(page, count, "%s\t%s%s\n",
613 obd2cli_tgt(obd), imp_state_name,
614 imp->imp_deactive ? "\tDEACTIVATED" : "");
616 LPROCFS_CLIMP_EXIT(obd);
620 int lprocfs_rd_conn_uuid(char *page, char **start, off_t off, int count,
621 int *eof, void *data)
623 struct obd_device *obd = (struct obd_device*)data;
624 struct ptlrpc_connection *conn;
627 LASSERT(obd != NULL);
629 LPROCFS_CLIMP_CHECK(obd);
630 conn = obd->u.cli.cl_import->imp_connection;
631 LASSERT(conn != NULL);
633 if (obd->u.cli.cl_import) {
634 rc = snprintf(page, count, "%s\n",
635 conn->c_remote_uuid.uuid);
637 rc = snprintf(page, count, "%s\n", "<none>");
640 LPROCFS_CLIMP_EXIT(obd);
644 int lprocfs_at_hist_helper(char *page, int count, int rc,
645 struct adaptive_timeout *at)
648 for (i = 0; i < AT_BINS; i++)
649 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
650 rc += snprintf(page + rc, count - rc, "\n");
654 /* See also ptlrpc_lprocfs_rd_timeouts */
655 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
656 int *eof, void *data)
658 struct obd_device *obd = (struct obd_device *)data;
659 struct obd_import *imp;
660 unsigned int cur, worst;
665 LASSERT(obd != NULL);
666 LPROCFS_CLIMP_CHECK(obd);
667 imp = obd->u.cli.cl_import;
670 now = cfs_time_current_sec();
672 /* Some network health info for kicks */
673 s2dhms(&ts, now - imp->imp_last_reply_time);
674 rc += snprintf(page + rc, count - rc,
675 "%-10s : %ld, "DHMS_FMT" ago\n",
676 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
679 cur = at_get(&imp->imp_at.iat_net_latency);
680 worst = imp->imp_at.iat_net_latency.at_worst_ever;
681 worstt = imp->imp_at.iat_net_latency.at_worst_time;
682 s2dhms(&ts, now - worstt);
683 rc += snprintf(page + rc, count - rc,
684 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
685 "network", cur, worst, worstt, DHMS_VARS(&ts));
686 rc = lprocfs_at_hist_helper(page, count, rc,
687 &imp->imp_at.iat_net_latency);
689 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
690 if (imp->imp_at.iat_portal[i] == 0)
692 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
693 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
694 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
695 s2dhms(&ts, now - worstt);
696 rc += snprintf(page + rc, count - rc,
697 "portal %-2d : cur %3u worst %3u (at %ld, "
698 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
699 cur, worst, worstt, DHMS_VARS(&ts));
700 rc = lprocfs_at_hist_helper(page, count, rc,
701 &imp->imp_at.iat_service_estimate[i]);
704 LPROCFS_CLIMP_EXIT(obd);
708 static const char *obd_connect_names[] = {
735 "mds_mds_connection",
738 "alt_checksum_algorithm",
745 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
746 int count, int *eof, void *data)
748 struct obd_device *obd = data;
749 __u64 mask = 1, flags;
752 LPROCFS_CLIMP_CHECK(obd);
753 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
754 ret = snprintf(page, count, "flags="LPX64"\n", flags);
755 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
757 ret += snprintf(page + ret, count - ret, "%s\n",
758 obd_connect_names[i]);
760 if (flags & ~(mask - 1))
761 ret += snprintf(page + ret, count - ret,
762 "unknown flags "LPX64"\n", flags & ~(mask - 1));
764 LPROCFS_CLIMP_EXIT(obd);
767 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
769 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
770 int *eof, void *data)
772 struct obd_device *obd = (struct obd_device*)data;
774 LASSERT(obd != NULL);
776 return snprintf(page, count, "%u\n", obd->obd_num_exports);
779 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
780 int *eof, void *data)
782 struct obd_type *class = (struct obd_type*) data;
784 LASSERT(class != NULL);
786 return snprintf(page, count, "%d\n", class->typ_refcnt);
789 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
793 LASSERT(obd != NULL);
794 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
795 LASSERT(obd->obd_type->typ_procroot != NULL);
797 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
798 obd->obd_type->typ_procroot,
800 if (IS_ERR(obd->obd_proc_entry)) {
801 rc = PTR_ERR(obd->obd_proc_entry);
802 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
803 obd->obd_proc_entry = NULL;
808 int lprocfs_obd_cleanup(struct obd_device *obd)
812 if (obd->obd_proc_exports_entry) {
813 /* Should be no exports left */
814 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
815 lprocfs_remove(&obd->obd_proc_exports_entry);
817 lprocfs_remove(&obd->obd_proc_entry);
821 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
823 CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
824 client_stat->nid_proc, client_stat->nid_stats,
825 client_stat->nid_brw_stats);
827 LASSERTF(client_stat->nid_exp_ref_count == 0, "count %d\n",
828 client_stat->nid_exp_ref_count);
830 hlist_del_init(&client_stat->nid_hash);
832 if (client_stat->nid_proc)
833 lprocfs_remove(&client_stat->nid_proc);
835 if (client_stat->nid_stats)
836 lprocfs_free_stats(&client_stat->nid_stats);
838 if (client_stat->nid_brw_stats)
839 OBD_FREE(client_stat->nid_brw_stats, sizeof(struct brw_stats));
841 OBD_FREE(client_stat, sizeof(*client_stat));
846 void lprocfs_free_per_client_stats(struct obd_device *obd)
848 struct nid_stat *stat;
851 /* we need extra list - because hash_exit called to early */
852 /* not need locking because all clients is died */
853 while(!list_empty(&obd->obd_nid_stats)) {
854 stat = list_entry(obd->obd_nid_stats.next,
855 struct nid_stat, nid_list);
856 list_del_init(&stat->nid_list);
857 lprocfs_free_client_stats(stat);
863 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
864 enum lprocfs_stats_flags flags)
866 struct lprocfs_stats *stats;
867 unsigned int percpusize;
869 unsigned int num_cpu;
874 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
877 num_cpu = num_possible_cpus();
879 OBD_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
883 if (flags & LPROCFS_STATS_FLAG_NOPERCPU) {
884 stats->ls_flags = flags;
885 spin_lock_init(&stats->ls_lock);
886 /* Use this lock only if there are no percpu areas */
891 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
893 percpusize = L1_CACHE_ALIGN(percpusize);
895 for (i = 0; i < num_cpu; i++) {
896 OBD_ALLOC(stats->ls_percpu[i], percpusize);
897 if (stats->ls_percpu[i] == NULL) {
898 for (j = 0; j < i; j++) {
899 OBD_FREE(stats->ls_percpu[j], percpusize);
900 stats->ls_percpu[j] = NULL;
905 if (stats->ls_percpu[0] == NULL) {
906 OBD_FREE(stats, offsetof(typeof(*stats),
907 ls_percpu[num_cpu]));
915 void lprocfs_free_stats(struct lprocfs_stats **statsh)
917 struct lprocfs_stats *stats = *statsh;
918 unsigned int num_cpu;
919 unsigned int percpusize;
922 if (stats == NULL || stats->ls_num == 0)
926 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
929 num_cpu = num_possible_cpus();
931 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
933 percpusize = L1_CACHE_ALIGN(percpusize);
934 for (i = 0; i < num_cpu; i++)
935 OBD_FREE(stats->ls_percpu[i], percpusize);
936 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
939 void lprocfs_clear_stats(struct lprocfs_stats *stats)
941 struct lprocfs_counter *percpu_cntr;
943 unsigned int num_cpu;
945 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
947 for (i = 0; i < num_cpu; i++) {
948 for (j = 0; j < stats->ls_num; j++) {
949 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
950 atomic_inc(&percpu_cntr->lc_cntl.la_entry);
951 percpu_cntr->lc_count = 0;
952 percpu_cntr->lc_sum = 0;
953 percpu_cntr->lc_min = LC_MIN_INIT;
954 percpu_cntr->lc_max = 0;
955 percpu_cntr->lc_sumsquare = 0;
956 atomic_inc(&percpu_cntr->lc_cntl.la_exit);
960 lprocfs_stats_unlock(stats);
963 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
964 size_t len, loff_t *off)
966 struct seq_file *seq = file->private_data;
967 struct lprocfs_stats *stats = seq->private;
969 lprocfs_clear_stats(stats);
974 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
976 struct lprocfs_stats *stats = p->private;
977 /* return 1st cpu location */
978 return (*pos >= stats->ls_num) ? NULL :
979 &(stats->ls_percpu[0]->lp_cntr[*pos]);
982 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
986 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
988 struct lprocfs_stats *stats = p->private;
990 return (*pos >= stats->ls_num) ? NULL :
991 &(stats->ls_percpu[0]->lp_cntr[*pos]);
994 /* seq file export of one lprocfs counter */
995 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
997 struct lprocfs_stats *stats = p->private;
998 struct lprocfs_counter *cntr = v;
999 struct lprocfs_counter t, ret = { .lc_min = LC_MIN_INIT };
1001 unsigned int num_cpu;
1003 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
1005 do_gettimeofday(&now);
1006 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1007 "snapshot_time", now.tv_sec, now.tv_usec);
1011 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
1013 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1016 num_cpu = num_possible_cpus();
1018 for (i = 0; i < num_cpu; i++) {
1019 struct lprocfs_counter *percpu_cntr =
1020 &(stats->ls_percpu[i])->lp_cntr[idx];
1024 centry = atomic_read(&percpu_cntr->lc_cntl.la_entry);
1025 t.lc_count = percpu_cntr->lc_count;
1026 t.lc_sum = percpu_cntr->lc_sum;
1027 t.lc_min = percpu_cntr->lc_min;
1028 t.lc_max = percpu_cntr->lc_max;
1029 t.lc_sumsquare = percpu_cntr->lc_sumsquare;
1030 } while (centry != atomic_read(&percpu_cntr->lc_cntl.la_entry) &&
1031 centry != atomic_read(&percpu_cntr->lc_cntl.la_exit));
1032 ret.lc_count += t.lc_count;
1033 ret.lc_sum += t.lc_sum;
1034 if (t.lc_min < ret.lc_min)
1035 ret.lc_min = t.lc_min;
1036 if (t.lc_max > ret.lc_max)
1037 ret.lc_max = t.lc_max;
1038 ret.lc_sumsquare += t.lc_sumsquare;
1041 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", cntr->lc_name,
1042 ret.lc_count, cntr->lc_units);
1046 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
1047 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1048 ret.lc_min, ret.lc_max, ret.lc_sum);
1051 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
1052 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1056 rc = seq_printf(p, "\n");
1058 return (rc < 0) ? rc : 0;
1061 struct seq_operations lprocfs_stats_seq_sops = {
1062 start: lprocfs_stats_seq_start,
1063 stop: lprocfs_stats_seq_stop,
1064 next: lprocfs_stats_seq_next,
1065 show: lprocfs_stats_seq_show,
1068 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1070 struct proc_dir_entry *dp = PDE(inode);
1071 struct seq_file *seq;
1074 LPROCFS_ENTRY_AND_CHECK(dp);
1075 rc = seq_open(file, &lprocfs_stats_seq_sops);
1080 seq = file->private_data;
1081 seq->private = dp->data;
1085 struct file_operations lprocfs_stats_seq_fops = {
1086 .owner = THIS_MODULE,
1087 .open = lprocfs_stats_seq_open,
1089 .write = lprocfs_stats_seq_write,
1090 .llseek = seq_lseek,
1091 .release = lprocfs_seq_release,
1094 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1095 struct lprocfs_stats *stats)
1097 struct proc_dir_entry *entry;
1098 LASSERT(root != NULL);
1100 entry = create_proc_entry(name, 0644, root);
1103 entry->proc_fops = &lprocfs_stats_seq_fops;
1104 entry->data = (void *)stats;
1108 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1109 unsigned conf, const char *name, const char *units)
1111 struct lprocfs_counter *c;
1113 unsigned int num_cpu;
1115 LASSERT(stats != NULL);
1117 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1119 for (i = 0; i < num_cpu; i++) {
1120 c = &(stats->ls_percpu[i]->lp_cntr[index]);
1121 c->lc_config = conf;
1124 c->lc_min = LC_MIN_INIT;
1127 c->lc_units = units;
1130 lprocfs_stats_unlock(stats);
1132 EXPORT_SYMBOL(lprocfs_counter_init);
1134 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1136 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1137 LASSERT(coffset < stats->ls_num); \
1138 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1141 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1143 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1144 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1145 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1146 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1147 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1148 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1149 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1150 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1151 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1152 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1153 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1154 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1155 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1156 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1157 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1158 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1159 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1160 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1161 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
1162 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1163 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1164 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1165 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1166 LPROCFS_OBD_OP_INIT(num_private_stats, stats, checkmd);
1167 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1168 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1169 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1170 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1171 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1172 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1173 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1174 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1175 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1176 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw_async);
1177 LPROCFS_OBD_OP_INIT(num_private_stats, stats, prep_async_page);
1178 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reget_short_lock);
1179 LPROCFS_OBD_OP_INIT(num_private_stats, stats, release_short_lock);
1180 LPROCFS_OBD_OP_INIT(num_private_stats, stats, queue_async_io);
1181 LPROCFS_OBD_OP_INIT(num_private_stats, stats, queue_group_io);
1182 LPROCFS_OBD_OP_INIT(num_private_stats, stats, trigger_group_io);
1183 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_async_flags);
1184 LPROCFS_OBD_OP_INIT(num_private_stats, stats, teardown_async_page);
1185 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1186 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1187 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1188 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1189 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1190 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1191 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1192 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1193 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1194 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1195 LPROCFS_OBD_OP_INIT(num_private_stats, stats, match);
1196 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1197 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1198 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1199 LPROCFS_OBD_OP_INIT(num_private_stats, stats, join_lru);
1200 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1201 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1202 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1203 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1204 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1205 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1206 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1207 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1208 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1209 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1210 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1211 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1212 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1213 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1214 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1215 LPROCFS_OBD_OP_INIT(num_private_stats, stats, register_page_removal_cb);
1216 LPROCFS_OBD_OP_INIT(num_private_stats,stats,unregister_page_removal_cb);
1217 LPROCFS_OBD_OP_INIT(num_private_stats, stats, register_lock_cancel_cb);
1218 LPROCFS_OBD_OP_INIT(num_private_stats, stats,unregister_lock_cancel_cb);
1219 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1220 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1221 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1222 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1225 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1227 struct lprocfs_stats *stats;
1228 unsigned int num_stats;
1231 LASSERT(obd->obd_stats == NULL);
1232 LASSERT(obd->obd_proc_entry != NULL);
1233 LASSERT(obd->obd_cntr_base == 0);
1235 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1236 num_private_stats - 1 /* o_owner */;
1237 stats = lprocfs_alloc_stats(num_stats, 0);
1241 lprocfs_init_ops_stats(num_private_stats, stats);
1243 for (i = num_private_stats; i < num_stats; i++) {
1244 /* If this LBUGs, it is likely that an obd
1245 * operation was added to struct obd_ops in
1246 * <obd.h>, and that the corresponding line item
1247 * LPROCFS_OBD_OP_INIT(.., .., opname)
1248 * is missing from the list above. */
1249 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1250 "Missing obd_stat initializer obd_op "
1251 "operation at offset %d.\n", i - num_private_stats);
1253 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1255 lprocfs_free_stats(&stats);
1257 obd->obd_stats = stats;
1258 obd->obd_cntr_base = num_private_stats;
1263 void lprocfs_free_obd_stats(struct obd_device *obd)
1266 lprocfs_free_stats(&obd->obd_stats);
1269 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1271 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1272 LASSERT(coffset < stats->ls_num); \
1273 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1276 int lprocfs_alloc_md_stats(struct obd_device *obd,
1277 unsigned num_private_stats)
1279 struct lprocfs_stats *stats;
1280 unsigned int num_stats;
1283 LASSERT(obd->md_stats == NULL);
1284 LASSERT(obd->obd_proc_entry != NULL);
1285 LASSERT(obd->md_cntr_base == 0);
1287 num_stats = 1 + MD_COUNTER_OFFSET(get_remote_perm) +
1289 stats = lprocfs_alloc_stats(num_stats, 0);
1293 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1294 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1295 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1296 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1297 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1298 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1299 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1300 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1301 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1302 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1303 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1304 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1305 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1306 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1307 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1308 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1309 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1310 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1311 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1312 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1313 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1314 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1315 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1316 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1317 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1318 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1319 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1320 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1321 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1322 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1324 for (i = num_private_stats; i < num_stats; i++) {
1325 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1326 CERROR("Missing md_stat initializer md_op "
1327 "operation at offset %d. Aborting.\n",
1328 i - num_private_stats);
1332 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1334 lprocfs_free_stats(&stats);
1336 obd->md_stats = stats;
1337 obd->md_cntr_base = num_private_stats;
1342 void lprocfs_free_md_stats(struct obd_device *obd)
1344 struct lprocfs_stats *stats = obd->md_stats;
1346 if (stats != NULL) {
1347 obd->md_stats = NULL;
1348 lprocfs_free_stats(&stats);
1352 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1353 int *eof, void *data)
1355 struct obd_export *exp = (struct obd_export*)data;
1356 LASSERT(exp != NULL);
1358 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1361 struct exp_uuid_cb_data {
1369 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1370 int count, int *eof, int *len)
1372 cb_data->page = page;
1373 cb_data->count = count;
1378 void lprocfs_exp_print_uuid(void *obj, void *cb_data)
1380 struct obd_export *exp = (struct obd_export *)obj;
1381 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1383 if (exp->exp_nid_stats)
1384 *data->len += snprintf((data->page + *data->len),
1385 data->count, "%s\n",
1386 obd_uuid2str(&exp->exp_client_uuid));
1389 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1390 int *eof, void *data)
1392 struct nid_stat *stats = (struct nid_stat *)data;
1393 struct exp_uuid_cb_data cb_data;
1394 struct obd_device *obd = stats->nid_obd;
1399 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1400 lustre_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1401 lprocfs_exp_print_uuid, &cb_data);
1402 return (*cb_data.len);
1405 void lprocfs_exp_print_hash(void *obj, void *cb_data)
1407 struct exp_uuid_cb_data *data = cb_data;
1408 struct obd_export *exp = obj;
1411 lh = exp->exp_lock_hash;
1414 *data->len += lustre_hash_debug_header(data->page,
1417 *data->len += lustre_hash_debug_str(lh, data->page + *data->len,
1422 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1423 int *eof, void *data)
1425 struct nid_stat *stats = (struct nid_stat *)data;
1426 struct exp_uuid_cb_data cb_data;
1427 struct obd_device *obd = stats->nid_obd;
1432 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1434 lustre_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1435 lprocfs_exp_print_hash, &cb_data);
1436 return (*cb_data.len);
1439 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1440 int count, int *eof, void *data)
1443 return snprintf(page, count, "%s\n",
1444 "Write into this file to clear all nid stats and "
1445 "stale nid entries");
1447 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1449 void lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1451 struct nid_stat *stat = obj;
1454 /* object has only hash + iterate_all references.
1455 * add/delete blocked by hash bucket lock */
1456 CDEBUG(D_INFO,"refcnt %d\n", stat->nid_exp_ref_count);
1457 if(stat->nid_exp_ref_count == 2) {
1458 hlist_del_init(&stat->nid_hash);
1459 stat->nid_exp_ref_count--;
1460 spin_lock(&stat->nid_obd->obd_nid_lock);
1461 list_del_init(&stat->nid_list);
1462 spin_unlock(&stat->nid_obd->obd_nid_lock);
1463 list_add(&stat->nid_list, data);
1467 /* we has reference to object - only clear data*/
1468 if (stat->nid_stats)
1469 lprocfs_clear_stats(stat->nid_stats);
1471 if (stat->nid_brw_stats) {
1472 for (i = 0; i < BRW_LAST; i++)
1473 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
1479 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1480 unsigned long count, void *data)
1482 struct obd_device *obd = (struct obd_device *)data;
1483 struct nid_stat *client_stat;
1484 CFS_LIST_HEAD(free_list);
1486 lustre_hash_for_each(obd->obd_nid_stats_hash,
1487 lprocfs_nid_stats_clear_write_cb, &free_list);
1489 while (!list_empty(&free_list)) {
1490 client_stat = list_entry(free_list.next, struct nid_stat, nid_list);
1491 list_del_init(&client_stat->nid_list);
1492 lprocfs_free_client_stats(client_stat);
1497 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1499 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1502 struct nid_stat *tmp = NULL, *tmp1;
1503 struct obd_device *obd = NULL;
1504 cfs_proc_dir_entry_t *entry;
1509 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1510 !exp->exp_obd->obd_nid_stats_hash)
1513 /* not test against zero because eric say:
1514 * You may only test nid against another nid, or LNET_NID_ANY. Anything else is
1516 if (!nid || *nid == LNET_NID_ANY)
1521 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
1523 OBD_ALLOC(tmp, sizeof(struct nid_stat));
1528 tmp->nid_obd = exp->exp_obd;
1529 tmp->nid_exp_ref_count = 1; /* need live in hash after destroy export */
1531 /* protect competitive add to list, not need locking on destroy */
1532 spin_lock(&obd->obd_nid_lock);
1533 list_add(&tmp->nid_list, &obd->obd_nid_stats);
1534 spin_unlock(&obd->obd_nid_lock);
1536 tmp1 = lustre_hash_findadd_unique(obd->obd_nid_stats_hash,
1537 nid, &tmp->nid_hash);
1538 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
1539 tmp1, libcfs_nid2str(*nid), tmp->nid_exp_ref_count);
1542 exp->exp_nid_stats = tmp1;
1543 GOTO(destroy_new, rc = 0);
1545 /* not found - create */
1546 tmp->nid_proc = lprocfs_register(libcfs_nid2str(*nid),
1547 obd->obd_proc_exports_entry, NULL, NULL);
1548 if (!tmp->nid_proc) {
1549 CERROR("Error making export directory for"
1550 " nid %s\n", libcfs_nid2str(*nid));
1551 lustre_hash_del(obd->obd_nid_stats_hash, nid, &tmp->nid_hash);
1552 GOTO(destroy_new, rc = -ENOMEM);
1555 entry = lprocfs_add_simple(tmp->nid_proc, "uuid",
1556 lprocfs_exp_rd_uuid, NULL, tmp, NULL);
1557 if (IS_ERR(entry)) {
1558 CWARN("Error adding the uuid file\n");
1559 rc = PTR_ERR(entry);
1562 entry = lprocfs_add_simple(tmp->nid_proc, "hash",
1563 lprocfs_exp_rd_hash, NULL, tmp, NULL);
1564 if (IS_ERR(entry)) {
1565 CWARN("Error adding the hash file\n");
1566 rc = PTR_ERR(entry);
1569 exp->exp_nid_stats = tmp;
1574 spin_lock(&obd->obd_nid_lock);
1575 list_del(&tmp->nid_list);
1576 spin_unlock(&obd->obd_nid_lock);
1577 OBD_FREE(tmp, sizeof(struct nid_stat));
1581 int lprocfs_exp_cleanup(struct obd_export *exp)
1583 struct nid_stat *stat = exp->exp_nid_stats;
1588 stat->nid_exp_ref_count--;
1589 CDEBUG(D_INFO, "Put stat %p - %d\n", stat, stat->nid_exp_ref_count);
1591 exp->exp_nid_stats = NULL;
1595 int lprocfs_write_helper(const char *buffer, unsigned long count,
1598 return lprocfs_write_frac_helper(buffer, count, val, 1);
1601 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
1604 char kernbuf[20], *end, *pbuf;
1606 if (count > (sizeof(kernbuf) - 1))
1609 if (copy_from_user(kernbuf, buffer, count))
1612 kernbuf[count] = '\0';
1619 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1623 if (end != NULL && *end == '.') {
1624 int temp_val, pow = 1;
1628 if (strlen(pbuf) > 5)
1629 pbuf[5] = '\0'; /*only allow 5bits fractional*/
1631 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1634 for (i = 0; i < (end - pbuf); i++)
1637 *val += temp_val / pow;
1643 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val, int mult)
1645 long decimal_val, frac_val;
1651 decimal_val = val / mult;
1652 prtn = snprintf(buffer, count, "%ld", decimal_val);
1653 frac_val = val % mult;
1655 if (prtn < (count - 4) && frac_val > 0) {
1657 int i, temp_mult = 1, frac_bits = 0;
1659 temp_frac = frac_val * 10;
1660 buffer[prtn++] = '.';
1661 while (frac_bits < 2 && (temp_frac / mult) < 1 ) { /*only reserved 2bits fraction*/
1662 buffer[prtn++] ='0';
1667 Need to think these cases :
1668 1. #echo x.00 > /proc/xxx output result : x
1669 2. #echo x.0x > /proc/xxx output result : x.0x
1670 3. #echo x.x0 > /proc/xxx output result : x.x
1671 4. #echo x.xx > /proc/xxx output result : x.xx
1672 Only reserved 2bits fraction.
1674 for (i = 0; i < (5 - prtn); i++)
1677 frac_bits = min((int)count - prtn, 3 - frac_bits);
1678 prtn += snprintf(buffer + prtn, frac_bits, "%ld", frac_val * temp_mult / mult);
1681 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
1683 if (buffer[prtn] == '.') {
1690 buffer[prtn++] ='\n';
1694 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
1696 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
1699 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
1700 __u64 *val, int mult)
1702 char kernbuf[22], *end, *pbuf;
1703 __u64 whole, frac = 0, units;
1704 unsigned frac_d = 1;
1706 if (count > (sizeof(kernbuf) - 1) )
1709 if (copy_from_user(kernbuf, buffer, count))
1712 kernbuf[count] = '\0';
1719 whole = simple_strtoull(pbuf, &end, 10);
1723 if (end != NULL && *end == '.') {
1727 /* need to limit frac_d to a __u32 */
1728 if (strlen(pbuf) > 10)
1731 frac = simple_strtoull(pbuf, &end, 10);
1732 /* count decimal places */
1733 for (i = 0; i < (end - pbuf); i++)
1750 /* Specified units override the multiplier */
1752 mult = mult < 0 ? -units : units;
1755 do_div(frac, frac_d);
1756 *val = whole * mult + frac;
1760 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent,
1761 char *name, mode_t mode,
1762 struct file_operations *seq_fops, void *data)
1764 struct proc_dir_entry *entry;
1767 entry = create_proc_entry(name, mode, parent);
1770 entry->proc_fops = seq_fops;
1775 EXPORT_SYMBOL(lprocfs_seq_create);
1777 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
1779 struct file_operations *seq_fops,
1782 return (lprocfs_seq_create(dev->obd_proc_entry, name,
1783 mode, seq_fops, data));
1785 EXPORT_SYMBOL(lprocfs_obd_seq_create);
1787 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
1789 if (value >= OBD_HIST_MAX)
1790 value = OBD_HIST_MAX - 1;
1792 spin_lock(&oh->oh_lock);
1793 oh->oh_buckets[value]++;
1794 spin_unlock(&oh->oh_lock);
1796 EXPORT_SYMBOL(lprocfs_oh_tally);
1798 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
1802 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
1805 lprocfs_oh_tally(oh, val);
1807 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
1809 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
1811 unsigned long ret = 0;
1814 for (i = 0; i < OBD_HIST_MAX; i++)
1815 ret += oh->oh_buckets[i];
1818 EXPORT_SYMBOL(lprocfs_oh_sum);
1820 void lprocfs_oh_clear(struct obd_histogram *oh)
1822 spin_lock(&oh->oh_lock);
1823 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
1824 spin_unlock(&oh->oh_lock);
1826 EXPORT_SYMBOL(lprocfs_oh_clear);
1828 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
1829 int count, int *eof, void *data)
1831 struct obd_device *obd = data;
1837 c += lustre_hash_debug_header(page, count);
1838 c += lustre_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
1839 c += lustre_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
1840 c += lustre_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
1844 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
1846 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
1847 int count, int *eof, void *data)
1849 struct obd_device *obd = data;
1852 LASSERT(obd != NULL);
1853 LASSERT(count >= 0);
1855 /* Set start of user data returned to
1856 page + off since the user may have
1857 requested to read much smaller than
1858 what we need to read */
1859 *start = page + off;
1861 /* We know we are allocated a page here.
1862 Also we know that this function will
1863 not need to write more than a page
1864 so we can truncate at CFS_PAGE_SIZE. */
1865 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
1867 /* Initialize the page */
1868 memset(page, 0, size);
1870 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
1872 if (obd->obd_max_recoverable_clients == 0) {
1873 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
1879 /* sampled unlocked, but really... */
1880 if (obd->obd_recovering == 0) {
1881 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
1883 if (lprocfs_obd_snprintf(&page, size, &len,
1884 "recovery_start: %lu\n",
1885 obd->obd_recovery_start) <= 0)
1887 if (lprocfs_obd_snprintf(&page, size, &len,
1888 "recovery_duration: %lu\n",
1889 obd->obd_recovery_end -
1890 obd->obd_recovery_start) <= 0)
1892 /* Number of clients that have completed recovery */
1893 if (lprocfs_obd_snprintf(&page, size, &len,
1894 "completed_clients: %d/%d\n",
1895 obd->obd_max_recoverable_clients -
1896 obd->obd_recoverable_clients,
1897 obd->obd_max_recoverable_clients) <= 0)
1899 if (lprocfs_obd_snprintf(&page, size, &len,
1900 "replayed_requests: %d\n",
1901 obd->obd_replayed_requests) <= 0)
1903 if (lprocfs_obd_snprintf(&page, size, &len,
1904 "last_transno: "LPD64"\n",
1905 obd->obd_next_recovery_transno - 1)<=0)
1910 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
1912 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
1913 obd->obd_recovery_start) <= 0)
1915 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
1916 cfs_time_current_sec() >= obd->obd_recovery_end ? 0 :
1917 obd->obd_recovery_end - cfs_time_current_sec()) <= 0)
1919 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
1920 obd->obd_connected_clients,
1921 obd->obd_max_recoverable_clients) <= 0)
1923 /* Number of clients that have completed recovery */
1924 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d/%d\n",
1925 obd->obd_max_recoverable_clients -
1926 obd->obd_recoverable_clients,
1927 obd->obd_max_recoverable_clients) <= 0)
1929 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d/??\n",
1930 obd->obd_replayed_requests) <= 0)
1932 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
1933 obd->obd_requests_queued_for_recovery) <= 0)
1936 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
1937 obd->obd_next_recovery_transno) <= 0)
1943 return min(count, len - (int)off);
1945 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
1947 int lprocfs_obd_rd_recovery_maxtime(char *page, char **start, off_t off,
1948 int count, int *eof, void *data)
1950 struct obd_device *obd = (struct obd_device *)data;
1951 LASSERT(obd != NULL);
1953 return snprintf(page, count, "%lu\n",
1954 obd->obd_recovery_max_time);
1956 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_maxtime);
1958 int lprocfs_obd_wr_recovery_maxtime(struct file *file, const char *buffer,
1959 unsigned long count, void *data)
1961 struct obd_device *obd = (struct obd_device *)data;
1963 LASSERT(obd != NULL);
1965 rc = lprocfs_write_helper(buffer, count, &val);
1969 obd->obd_recovery_max_time = val;
1972 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_maxtime);
1974 EXPORT_SYMBOL(lprocfs_register);
1975 EXPORT_SYMBOL(lprocfs_srch);
1976 EXPORT_SYMBOL(lprocfs_remove);
1977 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
1978 EXPORT_SYMBOL(lprocfs_add_vars);
1979 EXPORT_SYMBOL(lprocfs_obd_setup);
1980 EXPORT_SYMBOL(lprocfs_obd_cleanup);
1981 EXPORT_SYMBOL(lprocfs_add_simple);
1982 EXPORT_SYMBOL(lprocfs_add_symlink);
1983 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
1984 EXPORT_SYMBOL(lprocfs_alloc_stats);
1985 EXPORT_SYMBOL(lprocfs_free_stats);
1986 EXPORT_SYMBOL(lprocfs_clear_stats);
1987 EXPORT_SYMBOL(lprocfs_register_stats);
1988 EXPORT_SYMBOL(lprocfs_init_ops_stats);
1989 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
1990 EXPORT_SYMBOL(lprocfs_free_obd_stats);
1991 EXPORT_SYMBOL(lprocfs_exp_setup);
1992 EXPORT_SYMBOL(lprocfs_exp_cleanup);
1994 EXPORT_SYMBOL(lprocfs_rd_u64);
1995 EXPORT_SYMBOL(lprocfs_rd_atomic);
1996 EXPORT_SYMBOL(lprocfs_wr_atomic);
1997 EXPORT_SYMBOL(lprocfs_rd_uint);
1998 EXPORT_SYMBOL(lprocfs_wr_uint);
1999 EXPORT_SYMBOL(lprocfs_rd_uuid);
2000 EXPORT_SYMBOL(lprocfs_rd_name);
2001 EXPORT_SYMBOL(lprocfs_rd_fstype);
2002 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
2003 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
2004 EXPORT_SYMBOL(lprocfs_rd_num_exports);
2005 EXPORT_SYMBOL(lprocfs_rd_numrefs);
2006 EXPORT_SYMBOL(lprocfs_at_hist_helper);
2007 EXPORT_SYMBOL(lprocfs_rd_timeouts);
2008 EXPORT_SYMBOL(lprocfs_rd_blksize);
2009 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
2010 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
2011 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
2012 EXPORT_SYMBOL(lprocfs_rd_filestotal);
2013 EXPORT_SYMBOL(lprocfs_rd_filesfree);
2015 EXPORT_SYMBOL(lprocfs_write_helper);
2016 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2017 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2018 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2019 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);