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);
253 * \param root [in] The parent proc entry on which new entry will be added.
254 * \param list [in] Array of proc entries to be added.
255 * \param data [in] The argument to be passed when entries read/write routines
256 * are called through /proc file.
258 * \retval 0 on success
261 int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list,
264 if (root == NULL || list == NULL)
267 while (list->name != NULL) {
268 struct proc_dir_entry *cur_root, *proc;
269 char *pathcopy, *cur, *next, pathbuf[64];
270 int pathsize = strlen(list->name) + 1;
275 /* need copy of path for strsep */
276 if (strlen(list->name) > sizeof(pathbuf) - 1) {
277 OBD_ALLOC(pathcopy, pathsize);
278 if (pathcopy == NULL)
285 strcpy(pathcopy, list->name);
287 while (cur_root != NULL && (cur = strsep(&next, "/"))) {
288 if (*cur =='\0') /* skip double/trailing "/" */
291 proc = lprocfs_srch(cur_root, cur);
292 CDEBUG(D_OTHER, "cur_root=%s, cur=%s, next=%s, (%s)\n",
293 cur_root->name, cur, next,
294 (proc ? "exists" : "new"));
296 cur_root = (proc ? proc :
297 proc_mkdir(cur, cur_root));
298 } else if (proc == NULL) {
300 if (list->proc_mode != 0000) {
301 mode = list->proc_mode;
305 if (list->write_fptr)
308 proc = create_proc_entry(cur, mode, cur_root);
312 if (pathcopy != pathbuf)
313 OBD_FREE(pathcopy, pathsize);
315 if (cur_root == NULL || proc == NULL) {
316 CERROR("LprocFS: No memory to create /proc entry %s",
322 proc->proc_fops = list->fops;
324 proc->proc_fops = &lprocfs_generic_fops;
325 proc->read_proc = list->read_fptr;
326 proc->write_proc = list->write_fptr;
327 proc->data = (list->data ? list->data : data);
333 void lprocfs_remove(struct proc_dir_entry **rooth)
335 struct proc_dir_entry *root = *rooth;
336 struct proc_dir_entry *temp = root;
337 struct proc_dir_entry *rm_entry;
338 struct proc_dir_entry *parent;
344 parent = root->parent;
345 LASSERT(parent != NULL);
346 LPROCFS_WRITE_ENTRY(); /* search vs remove race */
349 while (temp->subdir != NULL)
355 /* Memory corruption once caused this to fail, and
356 without this LASSERT we would loop here forever. */
357 LASSERTF(strlen(rm_entry->name) == rm_entry->namelen,
358 "0x%p %s/%s len %d\n", rm_entry, temp->name,
359 rm_entry->name, (int)strlen(rm_entry->name));
361 /* Now, the rm_entry->deleted flags is protected
362 * by _lprocfs_lock. */
363 rm_entry->data = NULL;
364 remove_proc_entry(rm_entry->name, temp);
368 LPROCFS_WRITE_EXIT();
371 void lprocfs_remove_proc_entry(const char *name, struct proc_dir_entry *parent)
373 LASSERT(parent != NULL);
374 remove_proc_entry(name, parent);
377 struct proc_dir_entry *lprocfs_register(const char *name,
378 struct proc_dir_entry *parent,
379 struct lprocfs_vars *list, void *data)
381 struct proc_dir_entry *newchild;
383 newchild = lprocfs_srch(parent, name);
384 if (newchild != NULL) {
385 CERROR(" Lproc: Attempting to register %s more than once \n",
387 return ERR_PTR(-EALREADY);
390 newchild = proc_mkdir(name, parent);
391 if (newchild != NULL && list != NULL) {
392 int rc = lprocfs_add_vars(newchild, list, data);
394 lprocfs_remove(&newchild);
401 /* Generic callbacks */
402 int lprocfs_rd_uint(char *page, char **start, off_t off,
403 int count, int *eof, void *data)
405 unsigned int *temp = (unsigned int *)data;
406 return snprintf(page, count, "%u\n", *temp);
409 int lprocfs_wr_uint(struct file *file, const char *buffer,
410 unsigned long count, void *data)
413 char dummy[MAX_STRING_SIZE + 1], *end;
416 dummy[MAX_STRING_SIZE] = '\0';
417 if (copy_from_user(dummy, buffer, MAX_STRING_SIZE))
420 tmp = simple_strtoul(dummy, &end, 0);
424 *p = (unsigned int)tmp;
428 int lprocfs_rd_u64(char *page, char **start, off_t off,
429 int count, int *eof, void *data)
431 LASSERT(data != NULL);
433 return snprintf(page, count, LPU64"\n", *(__u64 *)data);
436 int lprocfs_rd_atomic(char *page, char **start, off_t off,
437 int count, int *eof, void *data)
439 atomic_t *atom = (atomic_t *)data;
440 LASSERT(atom != NULL);
442 return snprintf(page, count, "%d\n", atomic_read(atom));
445 int lprocfs_wr_atomic(struct file *file, const char *buffer,
446 unsigned long count, void *data)
448 atomic_t *atm = data;
452 rc = lprocfs_write_helper(buffer, count, &val);
459 atomic_set(atm, val);
463 int lprocfs_rd_uuid(char *page, char **start, off_t off, int count,
464 int *eof, void *data)
466 struct obd_device *obd = (struct obd_device*)data;
468 LASSERT(obd != NULL);
470 return snprintf(page, count, "%s\n", obd->obd_uuid.uuid);
473 int lprocfs_rd_name(char *page, char **start, off_t off, int count,
474 int *eof, void* data)
476 struct obd_device *dev = (struct obd_device *)data;
478 LASSERT(dev != NULL);
479 LASSERT(dev->obd_name != NULL);
481 return snprintf(page, count, "%s\n", dev->obd_name);
484 int lprocfs_rd_fstype(char *page, char **start, off_t off, int count, int *eof,
487 struct obd_device *obd = (struct obd_device *)data;
489 LASSERT(obd != NULL);
490 LASSERT(obd->obd_fsops != NULL);
491 LASSERT(obd->obd_fsops->fs_type != NULL);
492 return snprintf(page, count, "%s\n", obd->obd_fsops->fs_type);
495 int lprocfs_rd_blksize(char *page, char **start, off_t off, int count,
496 int *eof, void *data)
498 struct obd_statfs osfs;
499 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ,
503 rc = snprintf(page, count, "%u\n", osfs.os_bsize);
508 int lprocfs_rd_kbytestotal(char *page, char **start, off_t off, int count,
509 int *eof, void *data)
511 struct obd_statfs osfs;
512 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ,
515 __u32 blk_size = osfs.os_bsize >> 10;
516 __u64 result = osfs.os_blocks;
518 while (blk_size >>= 1)
522 rc = snprintf(page, count, LPU64"\n", result);
527 int lprocfs_rd_kbytesfree(char *page, char **start, off_t off, int count,
528 int *eof, void *data)
530 struct obd_statfs osfs;
531 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ,
534 __u32 blk_size = osfs.os_bsize >> 10;
535 __u64 result = osfs.os_bfree;
537 while (blk_size >>= 1)
541 rc = snprintf(page, count, LPU64"\n", result);
546 int lprocfs_rd_kbytesavail(char *page, char **start, off_t off, int count,
547 int *eof, void *data)
549 struct obd_statfs osfs;
550 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ,
553 __u32 blk_size = osfs.os_bsize >> 10;
554 __u64 result = osfs.os_bavail;
556 while (blk_size >>= 1)
560 rc = snprintf(page, count, LPU64"\n", result);
565 int lprocfs_rd_filestotal(char *page, char **start, off_t off, int count,
566 int *eof, void *data)
568 struct obd_statfs osfs;
569 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ,
573 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
579 int lprocfs_rd_filesfree(char *page, char **start, off_t off, int count,
580 int *eof, void *data)
582 struct obd_statfs osfs;
583 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ,
587 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
592 int lprocfs_rd_server_uuid(char *page, char **start, off_t off, int count,
593 int *eof, void *data)
595 struct obd_device *obd = (struct obd_device *)data;
596 struct obd_import *imp;
597 char *imp_state_name = NULL;
600 LASSERT(obd != NULL);
601 LPROCFS_CLIMP_CHECK(obd);
602 imp = obd->u.cli.cl_import;
603 imp_state_name = ptlrpc_import_state_name(imp->imp_state);
605 rc = snprintf(page, count, "%s\t%s%s\n",
606 obd2cli_tgt(obd), imp_state_name,
607 imp->imp_deactive ? "\tDEACTIVATED" : "");
609 LPROCFS_CLIMP_EXIT(obd);
613 int lprocfs_rd_conn_uuid(char *page, char **start, off_t off, int count,
614 int *eof, void *data)
616 struct obd_device *obd = (struct obd_device*)data;
617 struct ptlrpc_connection *conn;
620 LASSERT(obd != NULL);
622 LPROCFS_CLIMP_CHECK(obd);
623 conn = obd->u.cli.cl_import->imp_connection;
624 LASSERT(conn != NULL);
626 if (obd->u.cli.cl_import) {
627 rc = snprintf(page, count, "%s\n",
628 conn->c_remote_uuid.uuid);
630 rc = snprintf(page, count, "%s\n", "<none>");
633 LPROCFS_CLIMP_EXIT(obd);
637 int lprocfs_at_hist_helper(char *page, int count, int rc,
638 struct adaptive_timeout *at)
641 for (i = 0; i < AT_BINS; i++)
642 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
643 rc += snprintf(page + rc, count - rc, "\n");
647 /* See also ptlrpc_lprocfs_rd_timeouts */
648 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
649 int *eof, void *data)
651 struct obd_device *obd = (struct obd_device *)data;
652 struct obd_import *imp;
653 unsigned int cur, worst;
658 LASSERT(obd != NULL);
659 LPROCFS_CLIMP_CHECK(obd);
660 imp = obd->u.cli.cl_import;
663 now = cfs_time_current_sec();
665 /* Some network health info for kicks */
666 s2dhms(&ts, now - imp->imp_last_reply_time);
667 rc += snprintf(page + rc, count - rc,
668 "%-10s : %ld, "DHMS_FMT" ago\n",
669 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
672 cur = at_get(&imp->imp_at.iat_net_latency);
673 worst = imp->imp_at.iat_net_latency.at_worst_ever;
674 worstt = imp->imp_at.iat_net_latency.at_worst_time;
675 s2dhms(&ts, now - worstt);
676 rc += snprintf(page + rc, count - rc,
677 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
678 "network", cur, worst, worstt, DHMS_VARS(&ts));
679 rc = lprocfs_at_hist_helper(page, count, rc,
680 &imp->imp_at.iat_net_latency);
682 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
683 if (imp->imp_at.iat_portal[i] == 0)
685 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
686 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
687 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
688 s2dhms(&ts, now - worstt);
689 rc += snprintf(page + rc, count - rc,
690 "portal %-2d : cur %3u worst %3u (at %ld, "
691 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
692 cur, worst, worstt, DHMS_VARS(&ts));
693 rc = lprocfs_at_hist_helper(page, count, rc,
694 &imp->imp_at.iat_service_estimate[i]);
697 LPROCFS_CLIMP_EXIT(obd);
701 static const char *obd_connect_names[] = {
728 "mds_mds_connection",
731 "alt_checksum_algorithm",
736 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
737 int count, int *eof, void *data)
739 struct obd_device *obd = data;
740 __u64 mask = 1, flags;
743 LPROCFS_CLIMP_CHECK(obd);
744 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
745 ret = snprintf(page, count, "flags="LPX64"\n", flags);
746 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
748 ret += snprintf(page + ret, count - ret, "%s\n",
749 obd_connect_names[i]);
751 if (flags & ~(mask - 1))
752 ret += snprintf(page + ret, count - ret,
753 "unknown flags "LPX64"\n", flags & ~(mask - 1));
755 LPROCFS_CLIMP_EXIT(obd);
758 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
760 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
761 int *eof, void *data)
763 struct obd_device *obd = (struct obd_device*)data;
765 LASSERT(obd != NULL);
767 return snprintf(page, count, "%u\n", obd->obd_num_exports);
770 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
771 int *eof, void *data)
773 struct obd_type *class = (struct obd_type*) data;
775 LASSERT(class != NULL);
777 return snprintf(page, count, "%d\n", class->typ_refcnt);
780 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
784 LASSERT(obd != NULL);
785 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
786 LASSERT(obd->obd_type->typ_procroot != NULL);
788 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
789 obd->obd_type->typ_procroot,
791 if (IS_ERR(obd->obd_proc_entry)) {
792 rc = PTR_ERR(obd->obd_proc_entry);
793 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
794 obd->obd_proc_entry = NULL;
799 int lprocfs_obd_cleanup(struct obd_device *obd)
803 if (obd->obd_proc_exports_entry) {
804 /* Should be no exports left */
805 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
806 lprocfs_remove(&obd->obd_proc_exports_entry);
808 lprocfs_remove(&obd->obd_proc_entry);
812 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
814 CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
815 client_stat->nid_proc, client_stat->nid_stats,
816 client_stat->nid_brw_stats);
818 LASSERTF(client_stat->nid_exp_ref_count == 0, "count %d\n",
819 client_stat->nid_exp_ref_count);
821 hlist_del_init(&client_stat->nid_hash);
823 if (client_stat->nid_proc)
824 lprocfs_remove(&client_stat->nid_proc);
826 if (client_stat->nid_stats)
827 lprocfs_free_stats(&client_stat->nid_stats);
829 if (client_stat->nid_brw_stats)
830 OBD_FREE(client_stat->nid_brw_stats, sizeof(struct brw_stats));
832 OBD_FREE(client_stat, sizeof(*client_stat));
837 void lprocfs_free_per_client_stats(struct obd_device *obd)
839 struct nid_stat *stat;
842 /* we need extra list - because hash_exit called to early */
843 /* not need locking because all clients is died */
844 while(!list_empty(&obd->obd_nid_stats)) {
845 stat = list_entry(obd->obd_nid_stats.next,
846 struct nid_stat, nid_list);
847 list_del_init(&stat->nid_list);
848 lprocfs_free_client_stats(stat);
854 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
855 enum lprocfs_stats_flags flags)
857 struct lprocfs_stats *stats;
858 unsigned int percpusize;
860 unsigned int num_cpu;
865 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
868 num_cpu = num_possible_cpus();
870 OBD_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
874 if (flags & LPROCFS_STATS_FLAG_NOPERCPU) {
875 stats->ls_flags = flags;
876 spin_lock_init(&stats->ls_lock);
877 /* Use this lock only if there are no percpu areas */
882 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
884 percpusize = L1_CACHE_ALIGN(percpusize);
886 for (i = 0; i < num_cpu; i++) {
887 OBD_ALLOC(stats->ls_percpu[i], percpusize);
888 if (stats->ls_percpu[i] == NULL) {
889 for (j = 0; j < i; j++) {
890 OBD_FREE(stats->ls_percpu[j], percpusize);
891 stats->ls_percpu[j] = NULL;
896 if (stats->ls_percpu[0] == NULL) {
897 OBD_FREE(stats, offsetof(typeof(*stats),
898 ls_percpu[num_cpu]));
906 void lprocfs_free_stats(struct lprocfs_stats **statsh)
908 struct lprocfs_stats *stats = *statsh;
909 unsigned int num_cpu;
910 unsigned int percpusize;
913 if (stats == NULL || stats->ls_num == 0)
917 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
920 num_cpu = num_possible_cpus();
922 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
924 percpusize = L1_CACHE_ALIGN(percpusize);
925 for (i = 0; i < num_cpu; i++)
926 OBD_FREE(stats->ls_percpu[i], percpusize);
927 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
930 void lprocfs_clear_stats(struct lprocfs_stats *stats)
932 struct lprocfs_counter *percpu_cntr;
934 unsigned int num_cpu;
936 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
938 for (i = 0; i < num_cpu; i++) {
939 for (j = 0; j < stats->ls_num; j++) {
940 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
941 atomic_inc(&percpu_cntr->lc_cntl.la_entry);
942 percpu_cntr->lc_count = 0;
943 percpu_cntr->lc_sum = 0;
944 percpu_cntr->lc_min = LC_MIN_INIT;
945 percpu_cntr->lc_max = 0;
946 percpu_cntr->lc_sumsquare = 0;
947 atomic_inc(&percpu_cntr->lc_cntl.la_exit);
951 lprocfs_stats_unlock(stats);
954 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
955 size_t len, loff_t *off)
957 struct seq_file *seq = file->private_data;
958 struct lprocfs_stats *stats = seq->private;
960 lprocfs_clear_stats(stats);
965 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
967 struct lprocfs_stats *stats = p->private;
968 /* return 1st cpu location */
969 return (*pos >= stats->ls_num) ? NULL :
970 &(stats->ls_percpu[0]->lp_cntr[*pos]);
973 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
977 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
979 struct lprocfs_stats *stats = p->private;
981 return (*pos >= stats->ls_num) ? NULL :
982 &(stats->ls_percpu[0]->lp_cntr[*pos]);
985 /* seq file export of one lprocfs counter */
986 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
988 struct lprocfs_stats *stats = p->private;
989 struct lprocfs_counter *cntr = v;
990 struct lprocfs_counter t, ret = { .lc_min = LC_MIN_INIT };
992 unsigned int num_cpu;
994 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
996 do_gettimeofday(&now);
997 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
998 "snapshot_time", now.tv_sec, now.tv_usec);
1002 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
1004 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1007 num_cpu = num_possible_cpus();
1009 for (i = 0; i < num_cpu; i++) {
1010 struct lprocfs_counter *percpu_cntr =
1011 &(stats->ls_percpu[i])->lp_cntr[idx];
1015 centry = atomic_read(&percpu_cntr->lc_cntl.la_entry);
1016 t.lc_count = percpu_cntr->lc_count;
1017 t.lc_sum = percpu_cntr->lc_sum;
1018 t.lc_min = percpu_cntr->lc_min;
1019 t.lc_max = percpu_cntr->lc_max;
1020 t.lc_sumsquare = percpu_cntr->lc_sumsquare;
1021 } while (centry != atomic_read(&percpu_cntr->lc_cntl.la_entry) &&
1022 centry != atomic_read(&percpu_cntr->lc_cntl.la_exit));
1023 ret.lc_count += t.lc_count;
1024 ret.lc_sum += t.lc_sum;
1025 if (t.lc_min < ret.lc_min)
1026 ret.lc_min = t.lc_min;
1027 if (t.lc_max > ret.lc_max)
1028 ret.lc_max = t.lc_max;
1029 ret.lc_sumsquare += t.lc_sumsquare;
1032 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", cntr->lc_name,
1033 ret.lc_count, cntr->lc_units);
1037 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
1038 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1039 ret.lc_min, ret.lc_max, ret.lc_sum);
1042 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
1043 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1047 rc = seq_printf(p, "\n");
1049 return (rc < 0) ? rc : 0;
1052 struct seq_operations lprocfs_stats_seq_sops = {
1053 start: lprocfs_stats_seq_start,
1054 stop: lprocfs_stats_seq_stop,
1055 next: lprocfs_stats_seq_next,
1056 show: lprocfs_stats_seq_show,
1059 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1061 struct proc_dir_entry *dp = PDE(inode);
1062 struct seq_file *seq;
1065 LPROCFS_ENTRY_AND_CHECK(dp);
1066 rc = seq_open(file, &lprocfs_stats_seq_sops);
1071 seq = file->private_data;
1072 seq->private = dp->data;
1076 struct file_operations lprocfs_stats_seq_fops = {
1077 .owner = THIS_MODULE,
1078 .open = lprocfs_stats_seq_open,
1080 .write = lprocfs_stats_seq_write,
1081 .llseek = seq_lseek,
1082 .release = lprocfs_seq_release,
1085 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1086 struct lprocfs_stats *stats)
1088 struct proc_dir_entry *entry;
1089 LASSERT(root != NULL);
1091 entry = create_proc_entry(name, 0644, root);
1094 entry->proc_fops = &lprocfs_stats_seq_fops;
1095 entry->data = (void *)stats;
1099 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1100 unsigned conf, const char *name, const char *units)
1102 struct lprocfs_counter *c;
1104 unsigned int num_cpu;
1106 LASSERT(stats != NULL);
1108 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1110 for (i = 0; i < num_cpu; i++) {
1111 c = &(stats->ls_percpu[i]->lp_cntr[index]);
1112 c->lc_config = conf;
1115 c->lc_min = LC_MIN_INIT;
1118 c->lc_units = units;
1121 lprocfs_stats_unlock(stats);
1123 EXPORT_SYMBOL(lprocfs_counter_init);
1125 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1127 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1128 LASSERT(coffset < stats->ls_num); \
1129 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1132 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1134 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1135 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1136 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1137 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1138 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1139 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1140 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1141 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1142 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1143 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1144 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1145 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1146 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1147 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1148 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1149 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1150 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1151 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1152 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
1153 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1154 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1155 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1156 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1157 LPROCFS_OBD_OP_INIT(num_private_stats, stats, checkmd);
1158 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1159 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1160 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1161 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1162 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1163 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1164 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1165 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1166 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1167 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw_async);
1168 LPROCFS_OBD_OP_INIT(num_private_stats, stats, prep_async_page);
1169 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reget_short_lock);
1170 LPROCFS_OBD_OP_INIT(num_private_stats, stats, release_short_lock);
1171 LPROCFS_OBD_OP_INIT(num_private_stats, stats, queue_async_io);
1172 LPROCFS_OBD_OP_INIT(num_private_stats, stats, queue_group_io);
1173 LPROCFS_OBD_OP_INIT(num_private_stats, stats, trigger_group_io);
1174 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_async_flags);
1175 LPROCFS_OBD_OP_INIT(num_private_stats, stats, teardown_async_page);
1176 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1177 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1178 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1179 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1180 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1181 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1182 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1183 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1184 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1185 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1186 LPROCFS_OBD_OP_INIT(num_private_stats, stats, match);
1187 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1188 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1189 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1190 LPROCFS_OBD_OP_INIT(num_private_stats, stats, join_lru);
1191 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1192 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1193 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1194 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1195 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1196 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1197 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1198 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1199 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1200 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1201 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1202 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1203 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1204 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1205 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1206 LPROCFS_OBD_OP_INIT(num_private_stats, stats, register_page_removal_cb);
1207 LPROCFS_OBD_OP_INIT(num_private_stats,stats,unregister_page_removal_cb);
1208 LPROCFS_OBD_OP_INIT(num_private_stats, stats, register_lock_cancel_cb);
1209 LPROCFS_OBD_OP_INIT(num_private_stats, stats,unregister_lock_cancel_cb);
1212 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1214 struct lprocfs_stats *stats;
1215 unsigned int num_stats;
1218 LASSERT(obd->obd_stats == NULL);
1219 LASSERT(obd->obd_proc_entry != NULL);
1220 LASSERT(obd->obd_cntr_base == 0);
1222 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1223 num_private_stats - 1 /* o_owner */;
1224 stats = lprocfs_alloc_stats(num_stats, 0);
1228 lprocfs_init_ops_stats(num_private_stats, stats);
1230 for (i = num_private_stats; i < num_stats; i++) {
1231 /* If this LBUGs, it is likely that an obd
1232 * operation was added to struct obd_ops in
1233 * <obd.h>, and that the corresponding line item
1234 * LPROCFS_OBD_OP_INIT(.., .., opname)
1235 * is missing from the list above. */
1236 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1237 "Missing obd_stat initializer obd_op "
1238 "operation at offset %d.\n", i - num_private_stats);
1240 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1242 lprocfs_free_stats(&stats);
1244 obd->obd_stats = stats;
1245 obd->obd_cntr_base = num_private_stats;
1250 void lprocfs_free_obd_stats(struct obd_device *obd)
1253 lprocfs_free_stats(&obd->obd_stats);
1256 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1258 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1259 LASSERT(coffset < stats->ls_num); \
1260 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1263 int lprocfs_alloc_md_stats(struct obd_device *obd,
1264 unsigned num_private_stats)
1266 struct lprocfs_stats *stats;
1267 unsigned int num_stats;
1270 LASSERT(obd->md_stats == NULL);
1271 LASSERT(obd->obd_proc_entry != NULL);
1272 LASSERT(obd->md_cntr_base == 0);
1274 num_stats = 1 + MD_COUNTER_OFFSET(get_remote_perm) +
1276 stats = lprocfs_alloc_stats(num_stats, 0);
1280 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1281 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1282 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1283 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1284 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1285 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1286 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1287 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1288 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1289 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1290 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1291 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1292 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1293 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1294 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1295 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1296 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1297 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1298 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1299 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1300 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1301 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1302 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1303 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1304 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1305 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1306 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1307 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1308 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1309 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1311 for (i = num_private_stats; i < num_stats; i++) {
1312 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1313 CERROR("Missing md_stat initializer md_op "
1314 "operation at offset %d. Aborting.\n",
1315 i - num_private_stats);
1319 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1321 lprocfs_free_stats(&stats);
1323 obd->md_stats = stats;
1324 obd->md_cntr_base = num_private_stats;
1329 void lprocfs_free_md_stats(struct obd_device *obd)
1331 struct lprocfs_stats *stats = obd->md_stats;
1333 if (stats != NULL) {
1334 obd->md_stats = NULL;
1335 lprocfs_free_stats(&stats);
1339 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1340 int *eof, void *data)
1342 struct obd_export *exp = (struct obd_export*)data;
1343 LASSERT(exp != NULL);
1345 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1348 struct exp_uuid_cb_data {
1355 void lprocfs_exp_print_uuid(void *obj, void *cb_data)
1357 struct obd_export *exp = (struct obd_export *)obj;
1358 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1360 if (exp->exp_nid_stats)
1361 *data->len += snprintf((data->page + *data->len),
1362 data->count, "%s\n",
1363 obd_uuid2str(&exp->exp_client_uuid));
1366 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1367 int *eof, void *data)
1369 struct nid_stat *stats = (struct nid_stat *)data;
1370 struct exp_uuid_cb_data cb_data;
1371 struct obd_device *obd = stats->nid_obd;
1376 LASSERT(obd != NULL);
1378 cb_data.page = page;
1379 cb_data.count = count;
1382 lustre_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1383 lprocfs_exp_print_uuid, &cb_data);
1384 return (*cb_data.len);
1387 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1388 int count, int *eof, void *data)
1391 return snprintf(page, count, "%s\n",
1392 "Write into this file to clear all nid stats and "
1393 "stale nid entries");
1395 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1397 void lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1399 struct nid_stat *stat = obj;
1402 /* object has only hash + iterate_all references.
1403 * add/delete blocked by hash bucket lock */
1404 CDEBUG(D_INFO,"refcnt %d\n", stat->nid_exp_ref_count);
1405 if(stat->nid_exp_ref_count == 2) {
1406 hlist_del_init(&stat->nid_hash);
1407 stat->nid_exp_ref_count--;
1408 spin_lock(&stat->nid_obd->obd_nid_lock);
1409 list_del_init(&stat->nid_list);
1410 spin_unlock(&stat->nid_obd->obd_nid_lock);
1411 list_add(&stat->nid_list, data);
1415 /* we has reference to object - only clear data*/
1416 if (stat->nid_stats)
1417 lprocfs_clear_stats(stat->nid_stats);
1419 if (stat->nid_brw_stats) {
1420 for (i = 0; i < BRW_LAST; i++)
1421 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
1427 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1428 unsigned long count, void *data)
1430 struct obd_device *obd = (struct obd_device *)data;
1431 struct nid_stat *client_stat;
1432 CFS_LIST_HEAD(free_list);
1434 lustre_hash_for_each(obd->obd_nid_stats_hash,
1435 lprocfs_nid_stats_clear_write_cb, &free_list);
1437 while (!list_empty(&free_list)) {
1438 client_stat = list_entry(free_list.next, struct nid_stat, nid_list);
1439 list_del_init(&client_stat->nid_list);
1440 lprocfs_free_client_stats(client_stat);
1445 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1447 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1450 struct nid_stat *tmp = NULL, *tmp1;
1451 struct obd_device *obd = NULL;
1456 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1457 !exp->exp_obd->obd_nid_stats_hash)
1460 /* not test against zero because eric say:
1461 * You may only test nid against another nid, or LNET_NID_ANY. Anything else is
1463 if (!nid || *nid == LNET_NID_ANY)
1468 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
1470 OBD_ALLOC(tmp, sizeof(struct nid_stat));
1475 tmp->nid_obd = exp->exp_obd;
1476 tmp->nid_exp_ref_count = 1; /* need live in hash after destroy export */
1478 /* protect competitive add to list, not need locking on destroy */
1479 spin_lock(&obd->obd_nid_lock);
1480 list_add(&tmp->nid_list, &obd->obd_nid_stats);
1481 spin_unlock(&obd->obd_nid_lock);
1483 tmp1 = lustre_hash_findadd_unique(obd->obd_nid_stats_hash,
1484 nid, &tmp->nid_hash);
1485 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
1486 tmp1, libcfs_nid2str(*nid), tmp->nid_exp_ref_count);
1489 exp->exp_nid_stats = tmp1;
1490 GOTO(destroy_new, rc = 0);
1492 /* not found - create */
1493 tmp->nid_proc = lprocfs_register(libcfs_nid2str(*nid),
1494 obd->obd_proc_exports_entry, NULL, NULL);
1495 if (!tmp->nid_proc) {
1496 CERROR("Error making export directory for"
1497 " nid %s\n", libcfs_nid2str(*nid));
1498 lustre_hash_del(obd->obd_nid_stats_hash, nid, &tmp->nid_hash);
1499 GOTO(destroy_new, rc = -ENOMEM);
1502 rc = lprocfs_add_simple(tmp->nid_proc, "uuid",
1503 lprocfs_exp_rd_uuid, NULL, tmp);
1505 CWARN("Error adding the uuid file\n");
1507 exp->exp_nid_stats = tmp;
1512 spin_lock(&obd->obd_nid_lock);
1513 list_del(&tmp->nid_list);
1514 spin_unlock(&obd->obd_nid_lock);
1515 OBD_FREE(tmp, sizeof(struct nid_stat));
1519 int lprocfs_exp_cleanup(struct obd_export *exp)
1521 struct nid_stat *stat = exp->exp_nid_stats;
1526 stat->nid_exp_ref_count--;
1527 CDEBUG(D_INFO, "Put stat %p - %d\n", stat, stat->nid_exp_ref_count);
1529 exp->exp_nid_stats = NULL;
1533 int lprocfs_write_helper(const char *buffer, unsigned long count,
1536 return lprocfs_write_frac_helper(buffer, count, val, 1);
1539 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
1542 char kernbuf[20], *end, *pbuf;
1544 if (count > (sizeof(kernbuf) - 1))
1547 if (copy_from_user(kernbuf, buffer, count))
1550 kernbuf[count] = '\0';
1557 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1561 if (end != NULL && *end == '.') {
1562 int temp_val, pow = 1;
1566 if (strlen(pbuf) > 5)
1567 pbuf[5] = '\0'; /*only allow 5bits fractional*/
1569 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1572 for (i = 0; i < (end - pbuf); i++)
1575 *val += temp_val / pow;
1581 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val, int mult)
1583 long decimal_val, frac_val;
1589 decimal_val = val / mult;
1590 prtn = snprintf(buffer, count, "%ld", decimal_val);
1591 frac_val = val % mult;
1593 if (prtn < (count - 4) && frac_val > 0) {
1595 int i, temp_mult = 1, frac_bits = 0;
1597 temp_frac = frac_val * 10;
1598 buffer[prtn++] = '.';
1599 while (frac_bits < 2 && (temp_frac / mult) < 1 ) { /*only reserved 2bits fraction*/
1600 buffer[prtn++] ='0';
1605 Need to think these cases :
1606 1. #echo x.00 > /proc/xxx output result : x
1607 2. #echo x.0x > /proc/xxx output result : x.0x
1608 3. #echo x.x0 > /proc/xxx output result : x.x
1609 4. #echo x.xx > /proc/xxx output result : x.xx
1610 Only reserved 2bits fraction.
1612 for (i = 0; i < (5 - prtn); i++)
1615 frac_bits = min((int)count - prtn, 3 - frac_bits);
1616 prtn += snprintf(buffer + prtn, frac_bits, "%ld", frac_val * temp_mult / mult);
1619 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
1621 if (buffer[prtn] == '.') {
1628 buffer[prtn++] ='\n';
1632 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
1634 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
1637 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
1638 __u64 *val, int mult)
1640 char kernbuf[22], *end, *pbuf;
1641 __u64 whole, frac = 0, units;
1642 unsigned frac_d = 1;
1644 if (count > (sizeof(kernbuf) - 1) )
1647 if (copy_from_user(kernbuf, buffer, count))
1650 kernbuf[count] = '\0';
1657 whole = simple_strtoull(pbuf, &end, 10);
1661 if (end != NULL && *end == '.') {
1665 /* need to limit frac_d to a __u32 */
1666 if (strlen(pbuf) > 10)
1669 frac = simple_strtoull(pbuf, &end, 10);
1670 /* count decimal places */
1671 for (i = 0; i < (end - pbuf); i++)
1688 /* Specified units override the multiplier */
1690 mult = mult < 0 ? -units : units;
1693 do_div(frac, frac_d);
1694 *val = whole * mult + frac;
1698 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent,
1699 char *name, mode_t mode,
1700 struct file_operations *seq_fops, void *data)
1702 struct proc_dir_entry *entry;
1705 entry = create_proc_entry(name, mode, parent);
1708 entry->proc_fops = seq_fops;
1713 EXPORT_SYMBOL(lprocfs_seq_create);
1715 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
1717 struct file_operations *seq_fops,
1720 return (lprocfs_seq_create(dev->obd_proc_entry, name,
1721 mode, seq_fops, data));
1723 EXPORT_SYMBOL(lprocfs_obd_seq_create);
1725 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
1727 if (value >= OBD_HIST_MAX)
1728 value = OBD_HIST_MAX - 1;
1730 spin_lock(&oh->oh_lock);
1731 oh->oh_buckets[value]++;
1732 spin_unlock(&oh->oh_lock);
1734 EXPORT_SYMBOL(lprocfs_oh_tally);
1736 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
1740 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
1743 lprocfs_oh_tally(oh, val);
1745 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
1747 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
1749 unsigned long ret = 0;
1752 for (i = 0; i < OBD_HIST_MAX; i++)
1753 ret += oh->oh_buckets[i];
1756 EXPORT_SYMBOL(lprocfs_oh_sum);
1758 void lprocfs_oh_clear(struct obd_histogram *oh)
1760 spin_lock(&oh->oh_lock);
1761 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
1762 spin_unlock(&oh->oh_lock);
1764 EXPORT_SYMBOL(lprocfs_oh_clear);
1766 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
1767 int count, int *eof, void *data)
1769 struct obd_device *obd = data;
1775 c += lustre_hash_debug_header(page, count);
1776 c += lustre_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
1777 c += lustre_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
1778 c += lustre_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
1782 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
1784 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
1785 int count, int *eof, void *data)
1787 struct obd_device *obd = data;
1790 LASSERT(obd != NULL);
1791 LASSERT(count >= 0);
1793 /* Set start of user data returned to
1794 page + off since the user may have
1795 requested to read much smaller than
1796 what we need to read */
1797 *start = page + off;
1799 /* We know we are allocated a page here.
1800 Also we know that this function will
1801 not need to write more than a page
1802 so we can truncate at CFS_PAGE_SIZE. */
1803 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
1805 /* Initialize the page */
1806 memset(page, 0, size);
1808 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
1810 if (obd->obd_max_recoverable_clients == 0) {
1811 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
1817 /* sampled unlocked, but really... */
1818 if (obd->obd_recovering == 0) {
1819 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
1821 if (lprocfs_obd_snprintf(&page, size, &len,
1822 "recovery_start: %lu\n",
1823 obd->obd_recovery_start) <= 0)
1825 if (lprocfs_obd_snprintf(&page, size, &len,
1826 "recovery_duration: %lu\n",
1827 obd->obd_recovery_end -
1828 obd->obd_recovery_start) <= 0)
1830 /* Number of clients that have completed recovery */
1831 if (lprocfs_obd_snprintf(&page, size, &len,
1832 "completed_clients: %d/%d\n",
1833 obd->obd_max_recoverable_clients -
1834 obd->obd_recoverable_clients,
1835 obd->obd_max_recoverable_clients) <= 0)
1837 if (lprocfs_obd_snprintf(&page, size, &len,
1838 "replayed_requests: %d\n",
1839 obd->obd_replayed_requests) <= 0)
1841 if (lprocfs_obd_snprintf(&page, size, &len,
1842 "last_transno: "LPD64"\n",
1843 obd->obd_next_recovery_transno - 1)<=0)
1848 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
1850 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
1851 obd->obd_recovery_start) <= 0)
1853 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
1854 cfs_time_current_sec() >= obd->obd_recovery_end ? 0 :
1855 obd->obd_recovery_end - cfs_time_current_sec()) <= 0)
1857 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
1858 obd->obd_connected_clients,
1859 obd->obd_max_recoverable_clients) <= 0)
1861 /* Number of clients that have completed recovery */
1862 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d/%d\n",
1863 obd->obd_max_recoverable_clients -
1864 obd->obd_recoverable_clients,
1865 obd->obd_max_recoverable_clients) <= 0)
1867 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d/??\n",
1868 obd->obd_replayed_requests) <= 0)
1870 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
1871 obd->obd_requests_queued_for_recovery) <= 0)
1874 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
1875 obd->obd_next_recovery_transno) <= 0)
1881 return min(count, len - (int)off);
1883 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
1885 int lprocfs_obd_rd_recovery_maxtime(char *page, char **start, off_t off,
1886 int count, int *eof, void *data)
1888 struct obd_device *obd = (struct obd_device *)data;
1889 LASSERT(obd != NULL);
1891 return snprintf(page, count, "%lu\n",
1892 obd->obd_recovery_max_time);
1894 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_maxtime);
1896 int lprocfs_obd_wr_recovery_maxtime(struct file *file, const char *buffer,
1897 unsigned long count, void *data)
1899 struct obd_device *obd = (struct obd_device *)data;
1901 LASSERT(obd != NULL);
1903 rc = lprocfs_write_helper(buffer, count, &val);
1907 obd->obd_recovery_max_time = val;
1910 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_maxtime);
1912 EXPORT_SYMBOL(lprocfs_register);
1913 EXPORT_SYMBOL(lprocfs_srch);
1914 EXPORT_SYMBOL(lprocfs_remove);
1915 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
1916 EXPORT_SYMBOL(lprocfs_add_vars);
1917 EXPORT_SYMBOL(lprocfs_obd_setup);
1918 EXPORT_SYMBOL(lprocfs_obd_cleanup);
1919 EXPORT_SYMBOL(lprocfs_add_simple);
1920 EXPORT_SYMBOL(lprocfs_add_symlink);
1921 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
1922 EXPORT_SYMBOL(lprocfs_alloc_stats);
1923 EXPORT_SYMBOL(lprocfs_free_stats);
1924 EXPORT_SYMBOL(lprocfs_clear_stats);
1925 EXPORT_SYMBOL(lprocfs_register_stats);
1926 EXPORT_SYMBOL(lprocfs_init_ops_stats);
1927 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
1928 EXPORT_SYMBOL(lprocfs_free_obd_stats);
1929 EXPORT_SYMBOL(lprocfs_exp_setup);
1930 EXPORT_SYMBOL(lprocfs_exp_cleanup);
1932 EXPORT_SYMBOL(lprocfs_rd_u64);
1933 EXPORT_SYMBOL(lprocfs_rd_atomic);
1934 EXPORT_SYMBOL(lprocfs_wr_atomic);
1935 EXPORT_SYMBOL(lprocfs_rd_uint);
1936 EXPORT_SYMBOL(lprocfs_wr_uint);
1937 EXPORT_SYMBOL(lprocfs_rd_uuid);
1938 EXPORT_SYMBOL(lprocfs_rd_name);
1939 EXPORT_SYMBOL(lprocfs_rd_fstype);
1940 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
1941 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
1942 EXPORT_SYMBOL(lprocfs_rd_num_exports);
1943 EXPORT_SYMBOL(lprocfs_rd_numrefs);
1944 EXPORT_SYMBOL(lprocfs_at_hist_helper);
1945 EXPORT_SYMBOL(lprocfs_rd_timeouts);
1946 EXPORT_SYMBOL(lprocfs_rd_blksize);
1947 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
1948 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
1949 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
1950 EXPORT_SYMBOL(lprocfs_rd_filestotal);
1951 EXPORT_SYMBOL(lprocfs_rd_filesfree);
1953 EXPORT_SYMBOL(lprocfs_write_helper);
1954 EXPORT_SYMBOL(lprocfs_write_frac_helper);
1955 EXPORT_SYMBOL(lprocfs_read_frac_helper);
1956 EXPORT_SYMBOL(lprocfs_write_u64_helper);
1957 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);