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_PTR(client_stat->nid_brw_stats);
841 if (client_stat->nid_ldlm_stats)
842 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
844 OBD_FREE_PTR(client_stat);
849 void lprocfs_free_per_client_stats(struct obd_device *obd)
851 struct nid_stat *stat;
854 /* we need extra list - because hash_exit called to early */
855 /* not need locking because all clients is died */
856 while(!list_empty(&obd->obd_nid_stats)) {
857 stat = list_entry(obd->obd_nid_stats.next,
858 struct nid_stat, nid_list);
859 list_del_init(&stat->nid_list);
860 lprocfs_free_client_stats(stat);
866 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
867 enum lprocfs_stats_flags flags)
869 struct lprocfs_stats *stats;
870 unsigned int percpusize;
872 unsigned int num_cpu;
877 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
880 num_cpu = num_possible_cpus();
882 OBD_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
886 if (flags & LPROCFS_STATS_FLAG_NOPERCPU) {
887 stats->ls_flags = flags;
888 spin_lock_init(&stats->ls_lock);
889 /* Use this lock only if there are no percpu areas */
894 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
896 percpusize = L1_CACHE_ALIGN(percpusize);
898 for (i = 0; i < num_cpu; i++) {
899 OBD_ALLOC(stats->ls_percpu[i], percpusize);
900 if (stats->ls_percpu[i] == NULL) {
901 for (j = 0; j < i; j++) {
902 OBD_FREE(stats->ls_percpu[j], percpusize);
903 stats->ls_percpu[j] = NULL;
908 if (stats->ls_percpu[0] == NULL) {
909 OBD_FREE(stats, offsetof(typeof(*stats),
910 ls_percpu[num_cpu]));
918 void lprocfs_free_stats(struct lprocfs_stats **statsh)
920 struct lprocfs_stats *stats = *statsh;
921 unsigned int num_cpu;
922 unsigned int percpusize;
925 if (stats == NULL || stats->ls_num == 0)
929 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
932 num_cpu = num_possible_cpus();
934 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
936 percpusize = L1_CACHE_ALIGN(percpusize);
937 for (i = 0; i < num_cpu; i++)
938 OBD_FREE(stats->ls_percpu[i], percpusize);
939 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
942 void lprocfs_clear_stats(struct lprocfs_stats *stats)
944 struct lprocfs_counter *percpu_cntr;
946 unsigned int num_cpu;
948 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
950 for (i = 0; i < num_cpu; i++) {
951 for (j = 0; j < stats->ls_num; j++) {
952 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
953 atomic_inc(&percpu_cntr->lc_cntl.la_entry);
954 percpu_cntr->lc_count = 0;
955 percpu_cntr->lc_sum = 0;
956 percpu_cntr->lc_min = LC_MIN_INIT;
957 percpu_cntr->lc_max = 0;
958 percpu_cntr->lc_sumsquare = 0;
959 atomic_inc(&percpu_cntr->lc_cntl.la_exit);
963 lprocfs_stats_unlock(stats);
966 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
967 size_t len, loff_t *off)
969 struct seq_file *seq = file->private_data;
970 struct lprocfs_stats *stats = seq->private;
972 lprocfs_clear_stats(stats);
977 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
979 struct lprocfs_stats *stats = p->private;
980 /* return 1st cpu location */
981 return (*pos >= stats->ls_num) ? NULL :
982 &(stats->ls_percpu[0]->lp_cntr[*pos]);
985 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
989 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
991 struct lprocfs_stats *stats = p->private;
993 return (*pos >= stats->ls_num) ? NULL :
994 &(stats->ls_percpu[0]->lp_cntr[*pos]);
997 /* seq file export of one lprocfs counter */
998 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1000 struct lprocfs_stats *stats = p->private;
1001 struct lprocfs_counter *cntr = v;
1002 struct lprocfs_counter t, ret = { .lc_min = LC_MIN_INIT };
1004 unsigned int num_cpu;
1006 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
1008 do_gettimeofday(&now);
1009 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1010 "snapshot_time", now.tv_sec, now.tv_usec);
1014 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
1016 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1019 num_cpu = num_possible_cpus();
1021 for (i = 0; i < num_cpu; i++) {
1022 struct lprocfs_counter *percpu_cntr =
1023 &(stats->ls_percpu[i])->lp_cntr[idx];
1027 centry = atomic_read(&percpu_cntr->lc_cntl.la_entry);
1028 t.lc_count = percpu_cntr->lc_count;
1029 t.lc_sum = percpu_cntr->lc_sum;
1030 t.lc_min = percpu_cntr->lc_min;
1031 t.lc_max = percpu_cntr->lc_max;
1032 t.lc_sumsquare = percpu_cntr->lc_sumsquare;
1033 } while (centry != atomic_read(&percpu_cntr->lc_cntl.la_entry) &&
1034 centry != atomic_read(&percpu_cntr->lc_cntl.la_exit));
1035 ret.lc_count += t.lc_count;
1036 ret.lc_sum += t.lc_sum;
1037 if (t.lc_min < ret.lc_min)
1038 ret.lc_min = t.lc_min;
1039 if (t.lc_max > ret.lc_max)
1040 ret.lc_max = t.lc_max;
1041 ret.lc_sumsquare += t.lc_sumsquare;
1044 if (ret.lc_count == 0)
1047 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", cntr->lc_name,
1048 ret.lc_count, cntr->lc_units);
1052 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
1053 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1054 ret.lc_min, ret.lc_max, ret.lc_sum);
1057 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
1058 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1062 rc = seq_printf(p, "\n");
1064 return (rc < 0) ? rc : 0;
1067 struct seq_operations lprocfs_stats_seq_sops = {
1068 start: lprocfs_stats_seq_start,
1069 stop: lprocfs_stats_seq_stop,
1070 next: lprocfs_stats_seq_next,
1071 show: lprocfs_stats_seq_show,
1074 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1076 struct proc_dir_entry *dp = PDE(inode);
1077 struct seq_file *seq;
1080 LPROCFS_ENTRY_AND_CHECK(dp);
1081 rc = seq_open(file, &lprocfs_stats_seq_sops);
1086 seq = file->private_data;
1087 seq->private = dp->data;
1091 struct file_operations lprocfs_stats_seq_fops = {
1092 .owner = THIS_MODULE,
1093 .open = lprocfs_stats_seq_open,
1095 .write = lprocfs_stats_seq_write,
1096 .llseek = seq_lseek,
1097 .release = lprocfs_seq_release,
1100 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1101 struct lprocfs_stats *stats)
1103 struct proc_dir_entry *entry;
1104 LASSERT(root != NULL);
1106 entry = create_proc_entry(name, 0644, root);
1109 entry->proc_fops = &lprocfs_stats_seq_fops;
1110 entry->data = (void *)stats;
1114 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1115 unsigned conf, const char *name, const char *units)
1117 struct lprocfs_counter *c;
1119 unsigned int num_cpu;
1121 LASSERT(stats != NULL);
1123 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1125 for (i = 0; i < num_cpu; i++) {
1126 c = &(stats->ls_percpu[i]->lp_cntr[index]);
1127 c->lc_config = conf;
1130 c->lc_min = LC_MIN_INIT;
1133 c->lc_units = units;
1136 lprocfs_stats_unlock(stats);
1138 EXPORT_SYMBOL(lprocfs_counter_init);
1140 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1142 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1143 LASSERT(coffset < stats->ls_num); \
1144 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1147 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1149 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1150 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1151 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1152 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1153 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1154 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1155 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1156 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1157 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1158 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1159 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1160 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1161 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1162 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1163 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1164 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1165 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1166 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1167 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
1168 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1169 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1170 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1171 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1172 LPROCFS_OBD_OP_INIT(num_private_stats, stats, checkmd);
1173 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1174 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1175 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1176 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1177 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1178 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1179 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1180 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1181 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1182 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw_async);
1183 LPROCFS_OBD_OP_INIT(num_private_stats, stats, prep_async_page);
1184 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reget_short_lock);
1185 LPROCFS_OBD_OP_INIT(num_private_stats, stats, release_short_lock);
1186 LPROCFS_OBD_OP_INIT(num_private_stats, stats, queue_async_io);
1187 LPROCFS_OBD_OP_INIT(num_private_stats, stats, queue_group_io);
1188 LPROCFS_OBD_OP_INIT(num_private_stats, stats, trigger_group_io);
1189 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_async_flags);
1190 LPROCFS_OBD_OP_INIT(num_private_stats, stats, teardown_async_page);
1191 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1192 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1193 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1194 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1195 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1196 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1197 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1198 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1199 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1200 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1201 LPROCFS_OBD_OP_INIT(num_private_stats, stats, match);
1202 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1203 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1204 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1205 LPROCFS_OBD_OP_INIT(num_private_stats, stats, join_lru);
1206 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1207 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1208 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1209 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1210 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1211 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1212 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1213 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1214 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1215 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1216 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1217 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1218 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1219 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1220 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1221 LPROCFS_OBD_OP_INIT(num_private_stats, stats, register_page_removal_cb);
1222 LPROCFS_OBD_OP_INIT(num_private_stats,stats,unregister_page_removal_cb);
1223 LPROCFS_OBD_OP_INIT(num_private_stats, stats, register_lock_cancel_cb);
1224 LPROCFS_OBD_OP_INIT(num_private_stats, stats,unregister_lock_cancel_cb);
1225 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1226 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1227 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1228 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1231 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1233 struct lprocfs_stats *stats;
1234 unsigned int num_stats;
1237 LASSERT(obd->obd_stats == NULL);
1238 LASSERT(obd->obd_proc_entry != NULL);
1239 LASSERT(obd->obd_cntr_base == 0);
1241 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1242 num_private_stats - 1 /* o_owner */;
1243 stats = lprocfs_alloc_stats(num_stats, 0);
1247 lprocfs_init_ops_stats(num_private_stats, stats);
1249 for (i = num_private_stats; i < num_stats; i++) {
1250 /* If this LBUGs, it is likely that an obd
1251 * operation was added to struct obd_ops in
1252 * <obd.h>, and that the corresponding line item
1253 * LPROCFS_OBD_OP_INIT(.., .., opname)
1254 * is missing from the list above. */
1255 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1256 "Missing obd_stat initializer obd_op "
1257 "operation at offset %d.\n", i - num_private_stats);
1259 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1261 lprocfs_free_stats(&stats);
1263 obd->obd_stats = stats;
1264 obd->obd_cntr_base = num_private_stats;
1269 void lprocfs_free_obd_stats(struct obd_device *obd)
1272 lprocfs_free_stats(&obd->obd_stats);
1275 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1277 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1278 LASSERT(coffset < stats->ls_num); \
1279 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1282 int lprocfs_alloc_md_stats(struct obd_device *obd,
1283 unsigned num_private_stats)
1285 struct lprocfs_stats *stats;
1286 unsigned int num_stats;
1289 LASSERT(obd->md_stats == NULL);
1290 LASSERT(obd->obd_proc_entry != NULL);
1291 LASSERT(obd->md_cntr_base == 0);
1293 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1295 stats = lprocfs_alloc_stats(num_stats, 0);
1299 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1300 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1301 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1302 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1303 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1304 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1305 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1306 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1307 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1308 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1309 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1310 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1311 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1312 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1313 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1314 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1315 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1316 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1317 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1318 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1319 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1320 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1321 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1322 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1323 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1324 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1325 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1326 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1327 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1328 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1330 for (i = num_private_stats; i < num_stats; i++) {
1331 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1332 CERROR("Missing md_stat initializer md_op "
1333 "operation at offset %d. Aborting.\n",
1334 i - num_private_stats);
1338 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1340 lprocfs_free_stats(&stats);
1342 obd->md_stats = stats;
1343 obd->md_cntr_base = num_private_stats;
1348 void lprocfs_free_md_stats(struct obd_device *obd)
1350 struct lprocfs_stats *stats = obd->md_stats;
1352 if (stats != NULL) {
1353 obd->md_stats = NULL;
1354 lprocfs_free_stats(&stats);
1358 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1360 lprocfs_counter_init(ldlm_stats,
1361 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1362 0, "ldlm_enqueue", "reqs");
1363 lprocfs_counter_init(ldlm_stats,
1364 LDLM_CONVERT - LDLM_FIRST_OPC,
1365 0, "ldlm_convert", "reqs");
1366 lprocfs_counter_init(ldlm_stats,
1367 LDLM_CANCEL - LDLM_FIRST_OPC,
1368 0, "ldlm_cancel", "reqs");
1369 lprocfs_counter_init(ldlm_stats,
1370 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1371 0, "ldlm_bl_callback", "reqs");
1372 lprocfs_counter_init(ldlm_stats,
1373 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1374 0, "ldlm_cp_callback", "reqs");
1375 lprocfs_counter_init(ldlm_stats,
1376 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1377 0, "ldlm_gl_callback", "reqs");
1380 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1381 int *eof, void *data)
1383 struct obd_export *exp = (struct obd_export*)data;
1384 LASSERT(exp != NULL);
1386 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1389 struct exp_uuid_cb_data {
1397 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1398 int count, int *eof, int *len)
1400 cb_data->page = page;
1401 cb_data->count = count;
1406 void lprocfs_exp_print_uuid(void *obj, void *cb_data)
1408 struct obd_export *exp = (struct obd_export *)obj;
1409 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1411 if (exp->exp_nid_stats)
1412 *data->len += snprintf((data->page + *data->len),
1413 data->count, "%s\n",
1414 obd_uuid2str(&exp->exp_client_uuid));
1417 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1418 int *eof, void *data)
1420 struct nid_stat *stats = (struct nid_stat *)data;
1421 struct exp_uuid_cb_data cb_data;
1422 struct obd_device *obd = stats->nid_obd;
1427 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1428 lustre_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1429 lprocfs_exp_print_uuid, &cb_data);
1430 return (*cb_data.len);
1433 void lprocfs_exp_print_hash(void *obj, void *cb_data)
1435 struct exp_uuid_cb_data *data = cb_data;
1436 struct obd_export *exp = obj;
1439 lh = exp->exp_lock_hash;
1442 *data->len += lustre_hash_debug_header(data->page,
1445 *data->len += lustre_hash_debug_str(lh, data->page + *data->len,
1450 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1451 int *eof, void *data)
1453 struct nid_stat *stats = (struct nid_stat *)data;
1454 struct exp_uuid_cb_data cb_data;
1455 struct obd_device *obd = stats->nid_obd;
1460 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1462 lustre_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1463 lprocfs_exp_print_hash, &cb_data);
1464 return (*cb_data.len);
1467 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1468 int count, int *eof, void *data)
1471 return snprintf(page, count, "%s\n",
1472 "Write into this file to clear all nid stats and "
1473 "stale nid entries");
1475 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1477 void lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1479 struct nid_stat *stat = obj;
1482 /* object has only hash + iterate_all references.
1483 * add/delete blocked by hash bucket lock */
1484 CDEBUG(D_INFO,"refcnt %d\n", stat->nid_exp_ref_count);
1485 if (stat->nid_exp_ref_count == 2) {
1486 hlist_del_init(&stat->nid_hash);
1487 stat->nid_exp_ref_count--;
1488 spin_lock(&stat->nid_obd->obd_nid_lock);
1489 list_move(&stat->nid_list, data);
1490 spin_unlock(&stat->nid_obd->obd_nid_lock);
1494 /* we has reference to object - only clear data*/
1495 if (stat->nid_stats)
1496 lprocfs_clear_stats(stat->nid_stats);
1498 if (stat->nid_brw_stats) {
1499 for (i = 0; i < BRW_LAST; i++)
1500 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
1506 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1507 unsigned long count, void *data)
1509 struct obd_device *obd = (struct obd_device *)data;
1510 struct nid_stat *client_stat;
1511 CFS_LIST_HEAD(free_list);
1513 lustre_hash_for_each(obd->obd_nid_stats_hash,
1514 lprocfs_nid_stats_clear_write_cb, &free_list);
1516 while (!list_empty(&free_list)) {
1517 client_stat = list_entry(free_list.next, struct nid_stat, nid_list);
1518 list_del_init(&client_stat->nid_list);
1519 lprocfs_free_client_stats(client_stat);
1524 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1526 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1528 struct nid_stat *new_stat, *old_stat;
1529 struct nid_stat_uuid *new_ns_uuid;
1530 struct obd_device *obd = NULL;
1531 cfs_proc_dir_entry_t *entry;
1537 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1538 !exp->exp_obd->obd_nid_stats_hash)
1541 /* not test against zero because eric say:
1542 * You may only test nid against another nid, or LNET_NID_ANY.
1543 * Anything else is nonsense.*/
1544 if (!nid || *nid == LNET_NID_ANY)
1549 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
1551 OBD_ALLOC_PTR(new_stat);
1552 if (new_stat == NULL)
1555 OBD_ALLOC_PTR(new_ns_uuid);
1556 if (new_ns_uuid == NULL) {
1557 OBD_FREE_PTR(new_stat);
1560 CFS_INIT_LIST_HEAD(&new_ns_uuid->ns_uuid_list);
1561 strncpy(new_ns_uuid->ns_uuid.uuid, exp->exp_client_uuid.uuid,
1562 sizeof(struct obd_uuid));
1564 CFS_INIT_LIST_HEAD(&new_stat->nid_uuid_list);
1565 new_stat->nid = *nid;
1566 new_stat->nid_obd = exp->exp_obd;
1567 new_stat->nid_exp_ref_count = 1; /* live in hash after destroy export */
1569 /* protect competitive add to list, not need locking on destroy */
1570 spin_lock(&obd->obd_nid_lock);
1571 list_add(&new_stat->nid_list, &obd->obd_nid_stats);
1572 spin_unlock(&obd->obd_nid_lock);
1574 old_stat = lustre_hash_findadd_unique(obd->obd_nid_stats_hash,
1575 nid, &new_stat->nid_hash);
1576 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
1577 old_stat, libcfs_nid2str(*nid), new_stat->nid_exp_ref_count);
1579 /* Return -EALREADY here so that we know that the /proc
1580 * entry already has been created */
1581 if (old_stat != new_stat) {
1582 struct nid_stat_uuid *tmp_uuid;
1585 exp->exp_nid_stats = old_stat;
1586 /* We need to decrement the refcount if the uuid was
1587 * already in our list */
1588 spin_lock(&obd->obd_nid_lock);
1589 list_for_each_entry(tmp_uuid, &old_stat->nid_uuid_list,
1591 if (tmp_uuid && obd_uuid_equals(&tmp_uuid->ns_uuid,
1592 &exp->exp_client_uuid)){
1594 --old_stat->nid_exp_ref_count;
1600 list_add(&new_ns_uuid->ns_uuid_list,
1601 &old_stat->nid_uuid_list);
1603 OBD_FREE_PTR(new_ns_uuid);
1605 spin_unlock(&obd->obd_nid_lock);
1607 GOTO(destroy_new, rc = -EALREADY);
1609 /* not found - create */
1610 new_stat->nid_proc = lprocfs_register(libcfs_nid2str(*nid),
1611 obd->obd_proc_exports_entry,
1613 if (new_stat->nid_proc == NULL) {
1614 CERROR("Error making export directory for nid %s\n",
1615 libcfs_nid2str(*nid));
1616 GOTO(destroy_new_ns, rc = -ENOMEM);
1619 /* Add in uuid to our nid_stats list */
1620 spin_lock(&obd->obd_nid_lock);
1621 list_add(&new_ns_uuid->ns_uuid_list, &new_stat->nid_uuid_list);
1622 spin_unlock(&obd->obd_nid_lock);
1624 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
1625 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
1626 if (IS_ERR(entry)) {
1627 CWARN("Error adding the NID stats file\n");
1628 rc = PTR_ERR(entry);
1629 GOTO(destroy_new_ns, rc);
1632 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
1633 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
1634 if (IS_ERR(entry)) {
1635 CWARN("Error adding the hash file\n");
1636 lprocfs_remove(&new_stat->nid_proc);
1637 rc = PTR_ERR(entry);
1638 GOTO(destroy_new_ns, rc);
1641 exp->exp_nid_stats = new_stat;
1646 lustre_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
1647 OBD_FREE_PTR(new_ns_uuid);
1650 spin_lock(&obd->obd_nid_lock);
1651 list_del(&new_stat->nid_list);
1652 spin_unlock(&obd->obd_nid_lock);
1653 OBD_FREE_PTR(new_stat);
1657 int lprocfs_exp_cleanup(struct obd_export *exp)
1659 struct nid_stat *stat = exp->exp_nid_stats;
1660 struct nid_stat_uuid *cursor, *tmp;
1663 if(!stat || !exp->exp_obd)
1666 spin_lock(&exp->exp_obd->obd_nid_lock);
1667 list_for_each_entry_safe(cursor, tmp,
1668 &stat->nid_uuid_list,
1670 if (cursor && obd_uuid_equals(&cursor->ns_uuid,
1671 &exp->exp_client_uuid)) {
1673 list_del(&cursor->ns_uuid_list);
1674 OBD_FREE_PTR(cursor);
1678 spin_unlock(&exp->exp_obd->obd_nid_lock);
1680 CERROR("obd_export's client uuid %s are not found in its "
1681 "nid_stats list\n", exp->exp_client_uuid.uuid);
1683 stat->nid_exp_ref_count--;
1684 CDEBUG(D_INFO, "Put stat %p - %d\n", stat, stat->nid_exp_ref_count);
1686 exp->exp_nid_stats = NULL;
1687 lprocfs_free_md_stats(exp->exp_obd);
1692 int lprocfs_write_helper(const char *buffer, unsigned long count,
1695 return lprocfs_write_frac_helper(buffer, count, val, 1);
1698 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
1701 char kernbuf[20], *end, *pbuf;
1703 if (count > (sizeof(kernbuf) - 1))
1706 if (copy_from_user(kernbuf, buffer, count))
1709 kernbuf[count] = '\0';
1716 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1720 if (end != NULL && *end == '.') {
1721 int temp_val, pow = 1;
1725 if (strlen(pbuf) > 5)
1726 pbuf[5] = '\0'; /*only allow 5bits fractional*/
1728 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1731 for (i = 0; i < (end - pbuf); i++)
1734 *val += temp_val / pow;
1740 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val, int mult)
1742 long decimal_val, frac_val;
1748 decimal_val = val / mult;
1749 prtn = snprintf(buffer, count, "%ld", decimal_val);
1750 frac_val = val % mult;
1752 if (prtn < (count - 4) && frac_val > 0) {
1754 int i, temp_mult = 1, frac_bits = 0;
1756 temp_frac = frac_val * 10;
1757 buffer[prtn++] = '.';
1758 while (frac_bits < 2 && (temp_frac / mult) < 1 ) { /*only reserved 2bits fraction*/
1759 buffer[prtn++] ='0';
1764 Need to think these cases :
1765 1. #echo x.00 > /proc/xxx output result : x
1766 2. #echo x.0x > /proc/xxx output result : x.0x
1767 3. #echo x.x0 > /proc/xxx output result : x.x
1768 4. #echo x.xx > /proc/xxx output result : x.xx
1769 Only reserved 2bits fraction.
1771 for (i = 0; i < (5 - prtn); i++)
1774 frac_bits = min((int)count - prtn, 3 - frac_bits);
1775 prtn += snprintf(buffer + prtn, frac_bits, "%ld", frac_val * temp_mult / mult);
1778 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
1780 if (buffer[prtn] == '.') {
1787 buffer[prtn++] ='\n';
1791 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
1793 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
1796 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
1797 __u64 *val, int mult)
1799 char kernbuf[22], *end, *pbuf;
1800 __u64 whole, frac = 0, units;
1801 unsigned frac_d = 1;
1803 if (count > (sizeof(kernbuf) - 1) )
1806 if (copy_from_user(kernbuf, buffer, count))
1809 kernbuf[count] = '\0';
1816 whole = simple_strtoull(pbuf, &end, 10);
1820 if (end != NULL && *end == '.') {
1824 /* need to limit frac_d to a __u32 */
1825 if (strlen(pbuf) > 10)
1828 frac = simple_strtoull(pbuf, &end, 10);
1829 /* count decimal places */
1830 for (i = 0; i < (end - pbuf); i++)
1847 /* Specified units override the multiplier */
1849 mult = mult < 0 ? -units : units;
1852 do_div(frac, frac_d);
1853 *val = whole * mult + frac;
1857 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent,
1858 char *name, mode_t mode,
1859 struct file_operations *seq_fops, void *data)
1861 struct proc_dir_entry *entry;
1864 entry = create_proc_entry(name, mode, parent);
1867 entry->proc_fops = seq_fops;
1872 EXPORT_SYMBOL(lprocfs_seq_create);
1874 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
1876 struct file_operations *seq_fops,
1879 return (lprocfs_seq_create(dev->obd_proc_entry, name,
1880 mode, seq_fops, data));
1882 EXPORT_SYMBOL(lprocfs_obd_seq_create);
1884 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
1886 if (value >= OBD_HIST_MAX)
1887 value = OBD_HIST_MAX - 1;
1889 spin_lock(&oh->oh_lock);
1890 oh->oh_buckets[value]++;
1891 spin_unlock(&oh->oh_lock);
1893 EXPORT_SYMBOL(lprocfs_oh_tally);
1895 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
1899 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
1902 lprocfs_oh_tally(oh, val);
1904 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
1906 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
1908 unsigned long ret = 0;
1911 for (i = 0; i < OBD_HIST_MAX; i++)
1912 ret += oh->oh_buckets[i];
1915 EXPORT_SYMBOL(lprocfs_oh_sum);
1917 void lprocfs_oh_clear(struct obd_histogram *oh)
1919 spin_lock(&oh->oh_lock);
1920 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
1921 spin_unlock(&oh->oh_lock);
1923 EXPORT_SYMBOL(lprocfs_oh_clear);
1925 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
1926 int count, int *eof, void *data)
1928 struct obd_device *obd = data;
1934 c += lustre_hash_debug_header(page, count);
1935 c += lustre_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
1936 c += lustre_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
1937 c += lustre_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
1941 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
1943 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
1944 int count, int *eof, void *data)
1946 struct obd_device *obd = data;
1949 LASSERT(obd != NULL);
1950 LASSERT(count >= 0);
1952 /* Set start of user data returned to
1953 page + off since the user may have
1954 requested to read much smaller than
1955 what we need to read */
1956 *start = page + off;
1958 /* We know we are allocated a page here.
1959 Also we know that this function will
1960 not need to write more than a page
1961 so we can truncate at CFS_PAGE_SIZE. */
1962 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
1964 /* Initialize the page */
1965 memset(page, 0, size);
1967 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
1969 if (obd->obd_max_recoverable_clients == 0) {
1970 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
1976 /* sampled unlocked, but really... */
1977 if (obd->obd_recovering == 0) {
1978 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
1980 if (lprocfs_obd_snprintf(&page, size, &len,
1981 "recovery_start: %lu\n",
1982 obd->obd_recovery_start) <= 0)
1984 if (lprocfs_obd_snprintf(&page, size, &len,
1985 "recovery_duration: %lu\n",
1986 obd->obd_recovery_end -
1987 obd->obd_recovery_start) <= 0)
1989 /* Number of clients that have completed recovery */
1990 if (lprocfs_obd_snprintf(&page, size, &len,
1991 "completed_clients: %d/%d\n",
1992 obd->obd_max_recoverable_clients -
1993 obd->obd_recoverable_clients,
1994 obd->obd_max_recoverable_clients) <= 0)
1996 if (lprocfs_obd_snprintf(&page, size, &len,
1997 "replayed_requests: %d\n",
1998 obd->obd_replayed_requests) <= 0)
2000 if (lprocfs_obd_snprintf(&page, size, &len,
2001 "last_transno: "LPD64"\n",
2002 obd->obd_next_recovery_transno - 1)<=0)
2007 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2009 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2010 obd->obd_recovery_start) <= 0)
2012 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2013 cfs_time_current_sec() >= obd->obd_recovery_end ? 0 :
2014 obd->obd_recovery_end - cfs_time_current_sec()) <= 0)
2016 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2017 obd->obd_connected_clients,
2018 obd->obd_max_recoverable_clients) <= 0)
2020 /* Number of clients that have completed recovery */
2021 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d/%d\n",
2022 obd->obd_max_recoverable_clients -
2023 obd->obd_recoverable_clients,
2024 obd->obd_max_recoverable_clients) <= 0)
2026 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d/??\n",
2027 obd->obd_replayed_requests) <= 0)
2029 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2030 obd->obd_requests_queued_for_recovery) <= 0)
2033 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2034 obd->obd_next_recovery_transno) <= 0)
2040 return min(count, len - (int)off);
2042 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2044 int lprocfs_obd_rd_recovery_maxtime(char *page, char **start, off_t off,
2045 int count, int *eof, void *data)
2047 struct obd_device *obd = (struct obd_device *)data;
2048 LASSERT(obd != NULL);
2050 return snprintf(page, count, "%lu\n",
2051 obd->obd_recovery_max_time);
2053 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_maxtime);
2055 int lprocfs_obd_wr_recovery_maxtime(struct file *file, const char *buffer,
2056 unsigned long count, void *data)
2058 struct obd_device *obd = (struct obd_device *)data;
2060 LASSERT(obd != NULL);
2062 rc = lprocfs_write_helper(buffer, count, &val);
2066 obd->obd_recovery_max_time = val;
2069 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_maxtime);
2071 EXPORT_SYMBOL(lprocfs_register);
2072 EXPORT_SYMBOL(lprocfs_srch);
2073 EXPORT_SYMBOL(lprocfs_remove);
2074 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
2075 EXPORT_SYMBOL(lprocfs_add_vars);
2076 EXPORT_SYMBOL(lprocfs_obd_setup);
2077 EXPORT_SYMBOL(lprocfs_obd_cleanup);
2078 EXPORT_SYMBOL(lprocfs_add_simple);
2079 EXPORT_SYMBOL(lprocfs_add_symlink);
2080 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
2081 EXPORT_SYMBOL(lprocfs_alloc_stats);
2082 EXPORT_SYMBOL(lprocfs_free_stats);
2083 EXPORT_SYMBOL(lprocfs_clear_stats);
2084 EXPORT_SYMBOL(lprocfs_register_stats);
2085 EXPORT_SYMBOL(lprocfs_init_ops_stats);
2086 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
2087 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
2088 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
2089 EXPORT_SYMBOL(lprocfs_free_obd_stats);
2090 EXPORT_SYMBOL(lprocfs_exp_setup);
2091 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2093 EXPORT_SYMBOL(lprocfs_rd_u64);
2094 EXPORT_SYMBOL(lprocfs_rd_atomic);
2095 EXPORT_SYMBOL(lprocfs_wr_atomic);
2096 EXPORT_SYMBOL(lprocfs_rd_uint);
2097 EXPORT_SYMBOL(lprocfs_wr_uint);
2098 EXPORT_SYMBOL(lprocfs_rd_uuid);
2099 EXPORT_SYMBOL(lprocfs_rd_name);
2100 EXPORT_SYMBOL(lprocfs_rd_fstype);
2101 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
2102 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
2103 EXPORT_SYMBOL(lprocfs_rd_num_exports);
2104 EXPORT_SYMBOL(lprocfs_rd_numrefs);
2105 EXPORT_SYMBOL(lprocfs_at_hist_helper);
2106 EXPORT_SYMBOL(lprocfs_rd_timeouts);
2107 EXPORT_SYMBOL(lprocfs_rd_blksize);
2108 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
2109 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
2110 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
2111 EXPORT_SYMBOL(lprocfs_rd_filestotal);
2112 EXPORT_SYMBOL(lprocfs_rd_filesfree);
2114 EXPORT_SYMBOL(lprocfs_write_helper);
2115 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2116 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2117 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2118 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);