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,
210 size_t size, loff_t *ppos)
212 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
216 if (!dp->deleted && dp->write_proc)
217 rc = dp->write_proc(f, buf, size, dp->data);
222 static struct file_operations lprocfs_generic_fops = {
223 .owner = THIS_MODULE,
224 .read = lprocfs_fops_read,
225 .write = lprocfs_fops_write,
228 int lprocfs_evict_client_open(struct inode *inode, struct file *f)
230 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
231 struct obd_device *obd = dp->data;
233 atomic_inc(&obd->obd_evict_inprogress);
238 int lprocfs_evict_client_release(struct inode *inode, struct file *f)
240 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
241 struct obd_device *obd = dp->data;
243 atomic_dec(&obd->obd_evict_inprogress);
244 wake_up(&obd->obd_evict_inprogress_waitq);
249 struct file_operations lprocfs_evict_client_fops = {
250 .owner = THIS_MODULE,
251 .read = lprocfs_fops_read,
252 .write = lprocfs_fops_write,
253 .open = lprocfs_evict_client_open,
254 .release = lprocfs_evict_client_release,
256 EXPORT_SYMBOL(lprocfs_evict_client_fops);
261 * \param root [in] The parent proc entry on which new entry will be added.
262 * \param list [in] Array of proc entries to be added.
263 * \param data [in] The argument to be passed when entries read/write routines
264 * are called through /proc file.
266 * \retval 0 on success
269 int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list,
272 if (root == NULL || list == NULL)
275 while (list->name != NULL) {
276 struct proc_dir_entry *cur_root, *proc;
277 char *pathcopy, *cur, *next, pathbuf[64];
278 int pathsize = strlen(list->name) + 1;
283 /* need copy of path for strsep */
284 if (strlen(list->name) > sizeof(pathbuf) - 1) {
285 OBD_ALLOC(pathcopy, pathsize);
286 if (pathcopy == NULL)
293 strcpy(pathcopy, list->name);
295 while (cur_root != NULL && (cur = strsep(&next, "/"))) {
296 if (*cur =='\0') /* skip double/trailing "/" */
299 proc = lprocfs_srch(cur_root, cur);
300 CDEBUG(D_OTHER, "cur_root=%s, cur=%s, next=%s, (%s)\n",
301 cur_root->name, cur, next,
302 (proc ? "exists" : "new"));
304 cur_root = (proc ? proc :
305 proc_mkdir(cur, cur_root));
306 } else if (proc == NULL) {
308 if (list->proc_mode != 0000) {
309 mode = list->proc_mode;
313 if (list->write_fptr)
316 proc = create_proc_entry(cur, mode, cur_root);
320 if (pathcopy != pathbuf)
321 OBD_FREE(pathcopy, pathsize);
323 if (cur_root == NULL || proc == NULL) {
324 CERROR("LprocFS: No memory to create /proc entry %s",
330 proc->proc_fops = list->fops;
332 proc->proc_fops = &lprocfs_generic_fops;
333 proc->read_proc = list->read_fptr;
334 proc->write_proc = list->write_fptr;
335 proc->data = (list->data ? list->data : data);
341 void lprocfs_remove(struct proc_dir_entry **rooth)
343 struct proc_dir_entry *root = *rooth;
344 struct proc_dir_entry *temp = root;
345 struct proc_dir_entry *rm_entry;
346 struct proc_dir_entry *parent;
352 parent = root->parent;
353 LASSERT(parent != NULL);
354 LPROCFS_WRITE_ENTRY(); /* search vs remove race */
357 while (temp->subdir != NULL)
363 /* Memory corruption once caused this to fail, and
364 without this LASSERT we would loop here forever. */
365 LASSERTF(strlen(rm_entry->name) == rm_entry->namelen,
366 "0x%p %s/%s len %d\n", rm_entry, temp->name,
367 rm_entry->name, (int)strlen(rm_entry->name));
369 /* Now, the rm_entry->deleted flags is protected
370 * by _lprocfs_lock. */
371 rm_entry->data = NULL;
372 remove_proc_entry(rm_entry->name, temp);
376 LPROCFS_WRITE_EXIT();
379 void lprocfs_remove_proc_entry(const char *name, struct proc_dir_entry *parent)
381 LASSERT(parent != NULL);
382 remove_proc_entry(name, parent);
385 struct proc_dir_entry *lprocfs_register(const char *name,
386 struct proc_dir_entry *parent,
387 struct lprocfs_vars *list, void *data)
389 struct proc_dir_entry *newchild;
391 newchild = lprocfs_srch(parent, name);
392 if (newchild != NULL) {
393 CERROR(" Lproc: Attempting to register %s more than once \n",
395 return ERR_PTR(-EALREADY);
398 newchild = proc_mkdir(name, parent);
399 if (newchild != NULL && list != NULL) {
400 int rc = lprocfs_add_vars(newchild, list, data);
402 lprocfs_remove(&newchild);
409 /* Generic callbacks */
410 int lprocfs_rd_uint(char *page, char **start, off_t off,
411 int count, int *eof, void *data)
413 unsigned int *temp = data;
414 return snprintf(page, count, "%u\n", *temp);
417 int lprocfs_wr_uint(struct file *file, const char *buffer,
418 unsigned long count, void *data)
421 char dummy[MAX_STRING_SIZE + 1], *end;
424 dummy[MAX_STRING_SIZE] = '\0';
425 if (copy_from_user(dummy, buffer, MAX_STRING_SIZE))
428 tmp = simple_strtoul(dummy, &end, 0);
432 *p = (unsigned int)tmp;
436 int lprocfs_rd_u64(char *page, char **start, off_t off,
437 int count, int *eof, void *data)
439 LASSERT(data != NULL);
441 return snprintf(page, count, LPU64"\n", *(__u64 *)data);
444 int lprocfs_rd_atomic(char *page, char **start, off_t off,
445 int count, int *eof, void *data)
447 atomic_t *atom = data;
448 LASSERT(atom != NULL);
450 return snprintf(page, count, "%d\n", atomic_read(atom));
453 int lprocfs_wr_atomic(struct file *file, const char *buffer,
454 unsigned long count, void *data)
456 atomic_t *atm = data;
460 rc = lprocfs_write_helper(buffer, count, &val);
467 atomic_set(atm, val);
471 int lprocfs_rd_uuid(char *page, char **start, off_t off, int count,
472 int *eof, void *data)
474 struct obd_device *obd = data;
476 LASSERT(obd != NULL);
478 return snprintf(page, count, "%s\n", obd->obd_uuid.uuid);
481 int lprocfs_rd_name(char *page, char **start, off_t off, int count,
482 int *eof, void *data)
484 struct obd_device *dev = data;
486 LASSERT(dev != NULL);
487 LASSERT(dev->obd_name != NULL);
489 return snprintf(page, count, "%s\n", dev->obd_name);
492 int lprocfs_rd_fstype(char *page, char **start, off_t off, int count, int *eof,
495 struct obd_device *obd = data;
497 LASSERT(obd != NULL);
498 LASSERT(obd->obd_fsops != NULL);
499 LASSERT(obd->obd_fsops->fs_type != NULL);
500 return snprintf(page, count, "%s\n", obd->obd_fsops->fs_type);
503 int lprocfs_rd_blksize(char *page, char **start, off_t off, int count,
504 int *eof, void *data)
506 struct obd_statfs osfs;
507 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ,
511 rc = snprintf(page, count, "%u\n", osfs.os_bsize);
516 int lprocfs_rd_kbytestotal(char *page, char **start, off_t off, int count,
517 int *eof, void *data)
519 struct obd_statfs osfs;
520 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ,
523 __u32 blk_size = osfs.os_bsize >> 10;
524 __u64 result = osfs.os_blocks;
526 while (blk_size >>= 1)
530 rc = snprintf(page, count, LPU64"\n", result);
535 int lprocfs_rd_kbytesfree(char *page, char **start, off_t off, int count,
536 int *eof, void *data)
538 struct obd_statfs osfs;
539 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ,
542 __u32 blk_size = osfs.os_bsize >> 10;
543 __u64 result = osfs.os_bfree;
545 while (blk_size >>= 1)
549 rc = snprintf(page, count, LPU64"\n", result);
554 int lprocfs_rd_kbytesavail(char *page, char **start, off_t off, int count,
555 int *eof, void *data)
557 struct obd_statfs osfs;
558 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ,
561 __u32 blk_size = osfs.os_bsize >> 10;
562 __u64 result = osfs.os_bavail;
564 while (blk_size >>= 1)
568 rc = snprintf(page, count, LPU64"\n", result);
573 int lprocfs_rd_filestotal(char *page, char **start, off_t off, int count,
574 int *eof, void *data)
576 struct obd_statfs osfs;
577 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ,
581 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
587 int lprocfs_rd_filesfree(char *page, char **start, off_t off, int count,
588 int *eof, void *data)
590 struct obd_statfs osfs;
591 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ,
595 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
600 int lprocfs_rd_server_uuid(char *page, char **start, off_t off, int count,
601 int *eof, void *data)
603 struct obd_device *obd = data;
604 struct obd_import *imp;
605 char *imp_state_name = NULL;
608 LASSERT(obd != NULL);
609 LPROCFS_CLIMP_CHECK(obd);
610 imp = obd->u.cli.cl_import;
611 imp_state_name = ptlrpc_import_state_name(imp->imp_state);
613 rc = snprintf(page, count, "%s\t%s%s\n",
614 obd2cli_tgt(obd), imp_state_name,
615 imp->imp_deactive ? "\tDEACTIVATED" : "");
617 LPROCFS_CLIMP_EXIT(obd);
621 int lprocfs_rd_conn_uuid(char *page, char **start, off_t off, int count,
622 int *eof, void *data)
624 struct obd_device *obd = data;
625 struct ptlrpc_connection *conn;
628 LASSERT(obd != NULL);
630 LPROCFS_CLIMP_CHECK(obd);
631 conn = obd->u.cli.cl_import->imp_connection;
632 LASSERT(conn != NULL);
634 if (obd->u.cli.cl_import) {
635 rc = snprintf(page, count, "%s\n",
636 conn->c_remote_uuid.uuid);
638 rc = snprintf(page, count, "%s\n", "<none>");
641 LPROCFS_CLIMP_EXIT(obd);
645 #define flag2str(flag) \
646 if (imp->imp_##flag && max - len > 0) \
647 len += snprintf(str + len, max - len, " " #flag);
650 * Append a space separated list of current set flags to str.
652 static int obd_import_flags2str(struct obd_import *imp, char *str,
657 if (imp->imp_obd->obd_no_recov)
658 len += snprintf(str, max - len, " no_recov");
662 flag2str(replayable);
665 flag2str(last_recon);
670 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
671 int *eof, void *data)
673 struct obd_device *obd = (struct obd_device *)data;
674 struct obd_import *imp;
675 char *imp_state_name = NULL;
678 LASSERT(obd != NULL);
679 LPROCFS_CLIMP_CHECK(obd);
680 imp = obd->u.cli.cl_import;
681 imp_state_name = ptlrpc_import_state_name(imp->imp_state);
684 rc = snprintf(page, count,
689 " unregistering: %u\n"
693 " last_replay_transno: "LPU64"\n"
694 " peer_committed_transno: "LPU64"\n"
695 " last_trasno_checked: "LPU64"\n"
698 obd2cli_tgt(obd), imp->imp_connection->c_remote_uuid.uuid,
700 atomic_read(&imp->imp_inflight),
701 atomic_read(&imp->imp_unregistering),
704 atomic_read(&imp->imp_inval_count),
705 imp->imp_last_replay_transno,
706 imp->imp_peer_committed_transno,
707 imp->imp_last_transno_checked);
708 rc += obd_import_flags2str(imp, page + rc, count - rc);
709 rc += snprintf(page+rc, count - rc, "\n");
710 LPROCFS_CLIMP_EXIT(obd);
714 int lprocfs_at_hist_helper(char *page, int count, int rc,
715 struct adaptive_timeout *at)
718 for (i = 0; i < AT_BINS; i++)
719 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
720 rc += snprintf(page + rc, count - rc, "\n");
724 /* See also ptlrpc_lprocfs_rd_timeouts */
725 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
726 int *eof, void *data)
728 struct obd_device *obd = (struct obd_device *)data;
729 struct obd_import *imp;
730 unsigned int cur, worst;
735 LASSERT(obd != NULL);
736 LPROCFS_CLIMP_CHECK(obd);
737 imp = obd->u.cli.cl_import;
740 now = cfs_time_current_sec();
742 /* Some network health info for kicks */
743 s2dhms(&ts, now - imp->imp_last_reply_time);
744 rc += snprintf(page + rc, count - rc,
745 "%-10s : %ld, "DHMS_FMT" ago\n",
746 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
748 cur = at_get(&imp->imp_at.iat_net_latency);
749 worst = imp->imp_at.iat_net_latency.at_worst_ever;
750 worstt = imp->imp_at.iat_net_latency.at_worst_time;
751 s2dhms(&ts, now - worstt);
752 rc += snprintf(page + rc, count - rc,
753 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
754 "network", cur, worst, worstt, DHMS_VARS(&ts));
755 rc = lprocfs_at_hist_helper(page, count, rc,
756 &imp->imp_at.iat_net_latency);
758 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
759 if (imp->imp_at.iat_portal[i] == 0)
761 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
762 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
763 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
764 s2dhms(&ts, now - worstt);
765 rc += snprintf(page + rc, count - rc,
766 "portal %-2d : cur %3u worst %3u (at %ld, "
767 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
768 cur, worst, worstt, DHMS_VARS(&ts));
769 rc = lprocfs_at_hist_helper(page, count, rc,
770 &imp->imp_at.iat_service_estimate[i]);
773 LPROCFS_CLIMP_EXIT(obd);
777 static const char *obd_connect_names[] = {
804 "mds_mds_connection",
807 "alt_checksum_algorithm",
814 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
815 int count, int *eof, void *data)
817 struct obd_device *obd = data;
818 __u64 mask = 1, flags;
821 LPROCFS_CLIMP_CHECK(obd);
822 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
823 ret = snprintf(page, count, "flags="LPX64"\n", flags);
824 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
826 ret += snprintf(page + ret, count - ret, "%s\n",
827 obd_connect_names[i]);
829 if (flags & ~(mask - 1))
830 ret += snprintf(page + ret, count - ret,
831 "unknown flags "LPX64"\n", flags & ~(mask - 1));
833 LPROCFS_CLIMP_EXIT(obd);
836 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
838 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
839 int *eof, void *data)
841 struct obd_device *obd = data;
843 LASSERT(obd != NULL);
845 return snprintf(page, count, "%u\n", obd->obd_num_exports);
848 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
849 int *eof, void *data)
851 struct obd_type *class = (struct obd_type*) data;
853 LASSERT(class != NULL);
855 return snprintf(page, count, "%d\n", class->typ_refcnt);
858 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
862 LASSERT(obd != NULL);
863 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
864 LASSERT(obd->obd_type->typ_procroot != NULL);
866 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
867 obd->obd_type->typ_procroot,
869 if (IS_ERR(obd->obd_proc_entry)) {
870 rc = PTR_ERR(obd->obd_proc_entry);
871 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
872 obd->obd_proc_entry = NULL;
877 int lprocfs_obd_cleanup(struct obd_device *obd)
881 if (obd->obd_proc_exports_entry) {
882 /* Should be no exports left */
883 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
884 lprocfs_remove(&obd->obd_proc_exports_entry);
886 lprocfs_remove(&obd->obd_proc_entry);
890 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
892 CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
893 client_stat->nid_proc, client_stat->nid_stats,
894 client_stat->nid_brw_stats);
896 LASSERTF(client_stat->nid_exp_ref_count == 0, "count %d\n",
897 client_stat->nid_exp_ref_count);
899 hlist_del_init(&client_stat->nid_hash);
901 if (client_stat->nid_proc)
902 lprocfs_remove(&client_stat->nid_proc);
904 if (client_stat->nid_stats)
905 lprocfs_free_stats(&client_stat->nid_stats);
907 if (client_stat->nid_brw_stats)
908 OBD_FREE_PTR(client_stat->nid_brw_stats);
910 if (client_stat->nid_ldlm_stats)
911 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
913 OBD_FREE_PTR(client_stat);
918 void lprocfs_free_per_client_stats(struct obd_device *obd)
920 struct nid_stat *stat;
923 /* we need extra list - because hash_exit called to early */
924 /* not need locking because all clients is died */
925 while(!list_empty(&obd->obd_nid_stats)) {
926 stat = list_entry(obd->obd_nid_stats.next,
927 struct nid_stat, nid_list);
928 list_del_init(&stat->nid_list);
929 lprocfs_free_client_stats(stat);
935 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
936 enum lprocfs_stats_flags flags)
938 struct lprocfs_stats *stats;
939 unsigned int percpusize;
941 unsigned int num_cpu;
946 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
949 num_cpu = num_possible_cpus();
951 OBD_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
955 if (flags & LPROCFS_STATS_FLAG_NOPERCPU) {
956 stats->ls_flags = flags;
957 spin_lock_init(&stats->ls_lock);
958 /* Use this lock only if there are no percpu areas */
963 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
965 percpusize = L1_CACHE_ALIGN(percpusize);
967 for (i = 0; i < num_cpu; i++) {
968 OBD_ALLOC(stats->ls_percpu[i], percpusize);
969 if (stats->ls_percpu[i] == NULL) {
970 for (j = 0; j < i; j++) {
971 OBD_FREE(stats->ls_percpu[j], percpusize);
972 stats->ls_percpu[j] = NULL;
977 if (stats->ls_percpu[0] == NULL) {
978 OBD_FREE(stats, offsetof(typeof(*stats),
979 ls_percpu[num_cpu]));
987 void lprocfs_free_stats(struct lprocfs_stats **statsh)
989 struct lprocfs_stats *stats = *statsh;
990 unsigned int num_cpu;
991 unsigned int percpusize;
994 if (stats == NULL || stats->ls_num == 0)
998 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1001 num_cpu = num_possible_cpus();
1003 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
1005 percpusize = L1_CACHE_ALIGN(percpusize);
1006 for (i = 0; i < num_cpu; i++)
1007 OBD_FREE(stats->ls_percpu[i], percpusize);
1008 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
1011 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1013 struct lprocfs_counter *percpu_cntr;
1015 unsigned int num_cpu;
1017 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1019 for (i = 0; i < num_cpu; i++) {
1020 for (j = 0; j < stats->ls_num; j++) {
1021 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
1022 atomic_inc(&percpu_cntr->lc_cntl.la_entry);
1023 percpu_cntr->lc_count = 0;
1024 percpu_cntr->lc_sum = 0;
1025 percpu_cntr->lc_min = LC_MIN_INIT;
1026 percpu_cntr->lc_max = 0;
1027 percpu_cntr->lc_sumsquare = 0;
1028 atomic_inc(&percpu_cntr->lc_cntl.la_exit);
1032 lprocfs_stats_unlock(stats);
1035 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1036 size_t len, loff_t *off)
1038 struct seq_file *seq = file->private_data;
1039 struct lprocfs_stats *stats = seq->private;
1041 lprocfs_clear_stats(stats);
1046 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1048 struct lprocfs_stats *stats = p->private;
1049 /* return 1st cpu location */
1050 return (*pos >= stats->ls_num) ? NULL :
1051 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1054 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1058 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1060 struct lprocfs_stats *stats = p->private;
1062 return (*pos >= stats->ls_num) ? NULL :
1063 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1066 /* seq file export of one lprocfs counter */
1067 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1069 struct lprocfs_stats *stats = p->private;
1070 struct lprocfs_counter *cntr = v;
1071 struct lprocfs_counter t, ret = { .lc_min = LC_MIN_INIT };
1073 unsigned int num_cpu;
1075 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
1077 do_gettimeofday(&now);
1078 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1079 "snapshot_time", now.tv_sec, now.tv_usec);
1083 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
1085 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1088 num_cpu = num_possible_cpus();
1090 for (i = 0; i < num_cpu; i++) {
1091 struct lprocfs_counter *percpu_cntr =
1092 &(stats->ls_percpu[i])->lp_cntr[idx];
1096 centry = atomic_read(&percpu_cntr->lc_cntl.la_entry);
1097 t.lc_count = percpu_cntr->lc_count;
1098 t.lc_sum = percpu_cntr->lc_sum;
1099 t.lc_min = percpu_cntr->lc_min;
1100 t.lc_max = percpu_cntr->lc_max;
1101 t.lc_sumsquare = percpu_cntr->lc_sumsquare;
1102 } while (centry != atomic_read(&percpu_cntr->lc_cntl.la_entry) &&
1103 centry != atomic_read(&percpu_cntr->lc_cntl.la_exit));
1104 ret.lc_count += t.lc_count;
1105 ret.lc_sum += t.lc_sum;
1106 if (t.lc_min < ret.lc_min)
1107 ret.lc_min = t.lc_min;
1108 if (t.lc_max > ret.lc_max)
1109 ret.lc_max = t.lc_max;
1110 ret.lc_sumsquare += t.lc_sumsquare;
1113 if (ret.lc_count == 0)
1116 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", cntr->lc_name,
1117 ret.lc_count, cntr->lc_units);
1121 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
1122 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1123 ret.lc_min, ret.lc_max, ret.lc_sum);
1126 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
1127 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1131 rc = seq_printf(p, "\n");
1133 return (rc < 0) ? rc : 0;
1136 struct seq_operations lprocfs_stats_seq_sops = {
1137 start: lprocfs_stats_seq_start,
1138 stop: lprocfs_stats_seq_stop,
1139 next: lprocfs_stats_seq_next,
1140 show: lprocfs_stats_seq_show,
1143 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1145 struct proc_dir_entry *dp = PDE(inode);
1146 struct seq_file *seq;
1149 LPROCFS_ENTRY_AND_CHECK(dp);
1150 rc = seq_open(file, &lprocfs_stats_seq_sops);
1155 seq = file->private_data;
1156 seq->private = dp->data;
1160 struct file_operations lprocfs_stats_seq_fops = {
1161 .owner = THIS_MODULE,
1162 .open = lprocfs_stats_seq_open,
1164 .write = lprocfs_stats_seq_write,
1165 .llseek = seq_lseek,
1166 .release = lprocfs_seq_release,
1169 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1170 struct lprocfs_stats *stats)
1172 struct proc_dir_entry *entry;
1173 LASSERT(root != NULL);
1175 entry = create_proc_entry(name, 0644, root);
1178 entry->proc_fops = &lprocfs_stats_seq_fops;
1179 entry->data = stats;
1183 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1184 unsigned conf, const char *name, const char *units)
1186 struct lprocfs_counter *c;
1188 unsigned int num_cpu;
1190 LASSERT(stats != NULL);
1192 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1194 for (i = 0; i < num_cpu; i++) {
1195 c = &(stats->ls_percpu[i]->lp_cntr[index]);
1196 c->lc_config = conf;
1199 c->lc_min = LC_MIN_INIT;
1202 c->lc_units = units;
1205 lprocfs_stats_unlock(stats);
1207 EXPORT_SYMBOL(lprocfs_counter_init);
1209 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1211 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1212 LASSERT(coffset < stats->ls_num); \
1213 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1216 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1218 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1219 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1220 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1221 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1222 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1223 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1224 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1225 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1226 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1227 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1228 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1229 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1230 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1231 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1232 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1233 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1234 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1235 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1236 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
1237 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1238 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1239 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1240 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1241 LPROCFS_OBD_OP_INIT(num_private_stats, stats, checkmd);
1242 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1243 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1244 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1245 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1246 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1247 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1248 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1249 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1250 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1251 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1252 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1253 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1254 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1255 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1256 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1257 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1258 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1259 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1260 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1261 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1262 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1263 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1264 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1265 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1266 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1267 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1268 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1269 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1270 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1271 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1272 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1273 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1274 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1275 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1276 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1277 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1278 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quota_adjust_qunit);
1279 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1280 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1281 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1282 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1283 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1286 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1288 struct lprocfs_stats *stats;
1289 unsigned int num_stats;
1292 LASSERT(obd->obd_stats == NULL);
1293 LASSERT(obd->obd_proc_entry != NULL);
1294 LASSERT(obd->obd_cntr_base == 0);
1296 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1297 num_private_stats - 1 /* o_owner */;
1298 stats = lprocfs_alloc_stats(num_stats, 0);
1302 lprocfs_init_ops_stats(num_private_stats, stats);
1304 for (i = num_private_stats; i < num_stats; i++) {
1305 /* If this LBUGs, it is likely that an obd
1306 * operation was added to struct obd_ops in
1307 * <obd.h>, and that the corresponding line item
1308 * LPROCFS_OBD_OP_INIT(.., .., opname)
1309 * is missing from the list above. */
1310 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1311 "Missing obd_stat initializer obd_op "
1312 "operation at offset %d.\n", i - num_private_stats);
1314 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1316 lprocfs_free_stats(&stats);
1318 obd->obd_stats = stats;
1319 obd->obd_cntr_base = num_private_stats;
1324 void lprocfs_free_obd_stats(struct obd_device *obd)
1327 lprocfs_free_stats(&obd->obd_stats);
1330 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1332 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1333 LASSERT(coffset < stats->ls_num); \
1334 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1337 int lprocfs_alloc_md_stats(struct obd_device *obd,
1338 unsigned num_private_stats)
1340 struct lprocfs_stats *stats;
1341 unsigned int num_stats;
1344 LASSERT(obd->md_stats == NULL);
1345 LASSERT(obd->obd_proc_entry != NULL);
1346 LASSERT(obd->md_cntr_base == 0);
1348 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1350 stats = lprocfs_alloc_stats(num_stats, 0);
1354 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1355 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1356 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1357 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1358 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1359 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1360 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1361 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1362 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1363 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1364 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1365 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1366 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1367 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1368 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1369 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1370 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1371 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1372 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1373 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1374 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1375 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1376 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1377 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1378 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1379 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1380 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1381 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1382 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1383 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1384 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1386 for (i = num_private_stats; i < num_stats; i++) {
1387 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1388 CERROR("Missing md_stat initializer md_op "
1389 "operation at offset %d. Aborting.\n",
1390 i - num_private_stats);
1394 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1396 lprocfs_free_stats(&stats);
1398 obd->md_stats = stats;
1399 obd->md_cntr_base = num_private_stats;
1404 void lprocfs_free_md_stats(struct obd_device *obd)
1406 struct lprocfs_stats *stats = obd->md_stats;
1408 if (stats != NULL) {
1409 obd->md_stats = NULL;
1410 obd->md_cntr_base = 0;
1411 lprocfs_free_stats(&stats);
1415 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1417 lprocfs_counter_init(ldlm_stats,
1418 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1419 0, "ldlm_enqueue", "reqs");
1420 lprocfs_counter_init(ldlm_stats,
1421 LDLM_CONVERT - LDLM_FIRST_OPC,
1422 0, "ldlm_convert", "reqs");
1423 lprocfs_counter_init(ldlm_stats,
1424 LDLM_CANCEL - LDLM_FIRST_OPC,
1425 0, "ldlm_cancel", "reqs");
1426 lprocfs_counter_init(ldlm_stats,
1427 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1428 0, "ldlm_bl_callback", "reqs");
1429 lprocfs_counter_init(ldlm_stats,
1430 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1431 0, "ldlm_cp_callback", "reqs");
1432 lprocfs_counter_init(ldlm_stats,
1433 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1434 0, "ldlm_gl_callback", "reqs");
1437 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1438 int *eof, void *data)
1440 struct obd_export *exp = data;
1441 LASSERT(exp != NULL);
1443 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1446 struct exp_uuid_cb_data {
1454 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1455 int count, int *eof, int *len)
1457 cb_data->page = page;
1458 cb_data->count = count;
1463 void lprocfs_exp_print_uuid(void *obj, void *cb_data)
1465 struct obd_export *exp = (struct obd_export *)obj;
1466 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1468 if (exp->exp_nid_stats)
1469 *data->len += snprintf((data->page + *data->len),
1470 data->count, "%s\n",
1471 obd_uuid2str(&exp->exp_client_uuid));
1474 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1475 int *eof, void *data)
1477 struct nid_stat *stats = (struct nid_stat *)data;
1478 struct exp_uuid_cb_data cb_data;
1479 struct obd_device *obd = stats->nid_obd;
1484 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1485 lustre_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1486 lprocfs_exp_print_uuid, &cb_data);
1487 return (*cb_data.len);
1490 void lprocfs_exp_print_hash(void *obj, void *cb_data)
1492 struct exp_uuid_cb_data *data = cb_data;
1493 struct obd_export *exp = obj;
1496 lh = exp->exp_lock_hash;
1499 *data->len += lustre_hash_debug_header(data->page,
1502 *data->len += lustre_hash_debug_str(lh, data->page + *data->len,
1507 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1508 int *eof, void *data)
1510 struct nid_stat *stats = (struct nid_stat *)data;
1511 struct exp_uuid_cb_data cb_data;
1512 struct obd_device *obd = stats->nid_obd;
1517 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1519 lustre_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1520 lprocfs_exp_print_hash, &cb_data);
1521 return (*cb_data.len);
1524 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1525 int count, int *eof, void *data)
1528 return snprintf(page, count, "%s\n",
1529 "Write into this file to clear all nid stats and "
1530 "stale nid entries");
1532 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1534 void lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1536 struct nid_stat *stat = obj;
1539 /* object has only hash + iterate_all references.
1540 * add/delete blocked by hash bucket lock */
1541 CDEBUG(D_INFO,"refcnt %d\n", stat->nid_exp_ref_count);
1542 if (stat->nid_exp_ref_count == 2) {
1543 hlist_del_init(&stat->nid_hash);
1544 stat->nid_exp_ref_count--;
1545 spin_lock(&stat->nid_obd->obd_nid_lock);
1546 list_move(&stat->nid_list, data);
1547 spin_unlock(&stat->nid_obd->obd_nid_lock);
1551 /* we has reference to object - only clear data*/
1552 if (stat->nid_stats)
1553 lprocfs_clear_stats(stat->nid_stats);
1555 if (stat->nid_brw_stats) {
1556 for (i = 0; i < BRW_LAST; i++)
1557 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
1563 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1564 unsigned long count, void *data)
1566 struct obd_device *obd = (struct obd_device *)data;
1567 struct nid_stat *client_stat;
1568 CFS_LIST_HEAD(free_list);
1570 lustre_hash_for_each(obd->obd_nid_stats_hash,
1571 lprocfs_nid_stats_clear_write_cb, &free_list);
1573 while (!list_empty(&free_list)) {
1574 client_stat = list_entry(free_list.next, struct nid_stat,
1576 list_del_init(&client_stat->nid_list);
1577 lprocfs_free_client_stats(client_stat);
1582 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1584 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1586 struct nid_stat *new_stat, *old_stat;
1587 struct nid_stat_uuid *new_ns_uuid;
1588 struct obd_device *obd = NULL;
1589 cfs_proc_dir_entry_t *entry;
1595 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1596 !exp->exp_obd->obd_nid_stats_hash)
1599 /* not test against zero because eric say:
1600 * You may only test nid against another nid, or LNET_NID_ANY.
1601 * Anything else is nonsense.*/
1602 if (!nid || *nid == LNET_NID_ANY)
1607 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
1609 OBD_ALLOC_PTR(new_stat);
1610 if (new_stat == NULL)
1613 OBD_ALLOC_PTR(new_ns_uuid);
1614 if (new_ns_uuid == NULL) {
1615 OBD_FREE_PTR(new_stat);
1618 CFS_INIT_LIST_HEAD(&new_ns_uuid->ns_uuid_list);
1619 strncpy(new_ns_uuid->ns_uuid.uuid, exp->exp_client_uuid.uuid,
1620 sizeof(struct obd_uuid));
1622 CFS_INIT_LIST_HEAD(&new_stat->nid_uuid_list);
1623 new_stat->nid = *nid;
1624 new_stat->nid_obd = exp->exp_obd;
1625 new_stat->nid_exp_ref_count = 1; /* live in hash after destroy export */
1627 old_stat = lustre_hash_findadd_unique(obd->obd_nid_stats_hash,
1628 nid, &new_stat->nid_hash);
1629 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
1630 old_stat, libcfs_nid2str(*nid), new_stat->nid_exp_ref_count);
1632 /* Return -EALREADY here so that we know that the /proc
1633 * entry already has been created */
1634 if (old_stat != new_stat) {
1635 struct nid_stat_uuid *tmp_uuid;
1638 exp->exp_nid_stats = old_stat;
1639 /* We need to decrement the refcount if the uuid was
1640 * already in our list */
1641 spin_lock(&obd->obd_nid_lock);
1642 list_for_each_entry(tmp_uuid, &old_stat->nid_uuid_list,
1644 if (tmp_uuid && obd_uuid_equals(&tmp_uuid->ns_uuid,
1645 &exp->exp_client_uuid)){
1647 --old_stat->nid_exp_ref_count;
1653 list_add(&new_ns_uuid->ns_uuid_list,
1654 &old_stat->nid_uuid_list);
1656 OBD_FREE_PTR(new_ns_uuid);
1658 spin_unlock(&obd->obd_nid_lock);
1660 GOTO(destroy_new, rc = -EALREADY);
1662 /* not found - create */
1663 new_stat->nid_proc = lprocfs_register(libcfs_nid2str(*nid),
1664 obd->obd_proc_exports_entry,
1666 if (new_stat->nid_proc == NULL) {
1667 CERROR("Error making export directory for nid %s\n",
1668 libcfs_nid2str(*nid));
1669 GOTO(destroy_new_ns, rc = -ENOMEM);
1672 /* Add in uuid to our nid_stats list */
1673 spin_lock(&obd->obd_nid_lock);
1674 list_add(&new_ns_uuid->ns_uuid_list, &new_stat->nid_uuid_list);
1675 spin_unlock(&obd->obd_nid_lock);
1677 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
1678 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
1679 if (IS_ERR(entry)) {
1680 CWARN("Error adding the NID stats file\n");
1681 rc = PTR_ERR(entry);
1682 GOTO(destroy_new_ns, rc);
1685 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
1686 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
1687 if (IS_ERR(entry)) {
1688 CWARN("Error adding the hash file\n");
1689 lprocfs_remove(&new_stat->nid_proc);
1690 rc = PTR_ERR(entry);
1691 GOTO(destroy_new_ns, rc);
1694 exp->exp_nid_stats = new_stat;
1696 /* protect competitive add to list, not need locking on destroy */
1697 spin_lock(&obd->obd_nid_lock);
1698 list_add(&new_stat->nid_list, &obd->obd_nid_stats);
1699 spin_unlock(&obd->obd_nid_lock);
1704 lustre_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
1705 OBD_FREE_PTR(new_ns_uuid);
1708 OBD_FREE_PTR(new_stat);
1712 int lprocfs_exp_cleanup(struct obd_export *exp)
1714 struct nid_stat *stat = exp->exp_nid_stats;
1715 struct nid_stat_uuid *cursor, *tmp;
1718 if(!stat || !exp->exp_obd)
1721 spin_lock(&exp->exp_obd->obd_nid_lock);
1722 list_for_each_entry_safe(cursor, tmp,
1723 &stat->nid_uuid_list,
1725 if (cursor && obd_uuid_equals(&cursor->ns_uuid,
1726 &exp->exp_client_uuid)) {
1728 list_del(&cursor->ns_uuid_list);
1729 OBD_FREE_PTR(cursor);
1730 --stat->nid_exp_ref_count;
1731 CDEBUG(D_INFO, "Put stat %p - %d\n", stat,
1732 stat->nid_exp_ref_count);
1736 spin_unlock(&exp->exp_obd->obd_nid_lock);
1738 CERROR("obd_export's client uuid %s are not found in its "
1739 "nid_stats list\n", exp->exp_client_uuid.uuid);
1741 exp->exp_nid_stats = NULL;
1742 lprocfs_free_md_stats(exp->exp_obd);
1747 int lprocfs_write_helper(const char *buffer, unsigned long count,
1750 return lprocfs_write_frac_helper(buffer, count, val, 1);
1753 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
1756 char kernbuf[20], *end, *pbuf;
1758 if (count > (sizeof(kernbuf) - 1))
1761 if (copy_from_user(kernbuf, buffer, count))
1764 kernbuf[count] = '\0';
1771 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1775 if (end != NULL && *end == '.') {
1776 int temp_val, pow = 1;
1780 if (strlen(pbuf) > 5)
1781 pbuf[5] = '\0'; /*only allow 5bits fractional*/
1783 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1786 for (i = 0; i < (end - pbuf); i++)
1789 *val += temp_val / pow;
1795 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
1798 long decimal_val, frac_val;
1804 decimal_val = val / mult;
1805 prtn = snprintf(buffer, count, "%ld", decimal_val);
1806 frac_val = val % mult;
1808 if (prtn < (count - 4) && frac_val > 0) {
1810 int i, temp_mult = 1, frac_bits = 0;
1812 temp_frac = frac_val * 10;
1813 buffer[prtn++] = '.';
1814 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
1815 /* only reserved 2 bits fraction */
1816 buffer[prtn++] ='0';
1821 * Need to think these cases :
1822 * 1. #echo x.00 > /proc/xxx output result : x
1823 * 2. #echo x.0x > /proc/xxx output result : x.0x
1824 * 3. #echo x.x0 > /proc/xxx output result : x.x
1825 * 4. #echo x.xx > /proc/xxx output result : x.xx
1826 * Only reserved 2 bits fraction.
1828 for (i = 0; i < (5 - prtn); i++)
1831 frac_bits = min((int)count - prtn, 3 - frac_bits);
1832 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
1833 frac_val * temp_mult / mult);
1836 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
1838 if (buffer[prtn] == '.') {
1845 buffer[prtn++] ='\n';
1849 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
1851 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
1854 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
1855 __u64 *val, int mult)
1857 char kernbuf[22], *end, *pbuf;
1858 __u64 whole, frac = 0, units;
1859 unsigned frac_d = 1;
1861 if (count > (sizeof(kernbuf) - 1))
1864 if (copy_from_user(kernbuf, buffer, count))
1867 kernbuf[count] = '\0';
1874 whole = simple_strtoull(pbuf, &end, 10);
1878 if (end != NULL && *end == '.') {
1882 /* need to limit frac_d to a __u32 */
1883 if (strlen(pbuf) > 10)
1886 frac = simple_strtoull(pbuf, &end, 10);
1887 /* count decimal places */
1888 for (i = 0; i < (end - pbuf); i++)
1905 /* Specified units override the multiplier */
1907 mult = mult < 0 ? -units : units;
1910 do_div(frac, frac_d);
1911 *val = whole * mult + frac;
1915 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent, char *name, mode_t mode,
1916 struct file_operations *seq_fops, void *data)
1918 struct proc_dir_entry *entry;
1921 entry = create_proc_entry(name, mode, parent);
1924 entry->proc_fops = seq_fops;
1929 EXPORT_SYMBOL(lprocfs_seq_create);
1931 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
1933 struct file_operations *seq_fops,
1936 return (lprocfs_seq_create(dev->obd_proc_entry, name,
1937 mode, seq_fops, data));
1939 EXPORT_SYMBOL(lprocfs_obd_seq_create);
1941 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
1943 if (value >= OBD_HIST_MAX)
1944 value = OBD_HIST_MAX - 1;
1946 spin_lock(&oh->oh_lock);
1947 oh->oh_buckets[value]++;
1948 spin_unlock(&oh->oh_lock);
1950 EXPORT_SYMBOL(lprocfs_oh_tally);
1952 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
1956 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
1959 lprocfs_oh_tally(oh, val);
1961 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
1963 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
1965 unsigned long ret = 0;
1968 for (i = 0; i < OBD_HIST_MAX; i++)
1969 ret += oh->oh_buckets[i];
1972 EXPORT_SYMBOL(lprocfs_oh_sum);
1974 void lprocfs_oh_clear(struct obd_histogram *oh)
1976 spin_lock(&oh->oh_lock);
1977 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
1978 spin_unlock(&oh->oh_lock);
1980 EXPORT_SYMBOL(lprocfs_oh_clear);
1982 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
1983 int count, int *eof, void *data)
1985 struct obd_device *obd = data;
1991 c += lustre_hash_debug_header(page, count);
1992 c += lustre_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
1993 c += lustre_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
1994 c += lustre_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
1998 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2000 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2001 int count, int *eof, void *data)
2003 struct obd_device *obd = data;
2006 LASSERT(obd != NULL);
2007 LASSERT(count >= 0);
2009 /* Set start of user data returned to
2010 page + off since the user may have
2011 requested to read much smaller than
2012 what we need to read */
2013 *start = page + off;
2015 /* We know we are allocated a page here.
2016 Also we know that this function will
2017 not need to write more than a page
2018 so we can truncate at CFS_PAGE_SIZE. */
2019 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2021 /* Initialize the page */
2022 memset(page, 0, size);
2024 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2026 if (obd->obd_max_recoverable_clients == 0) {
2027 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2033 /* sampled unlocked, but really... */
2034 if (obd->obd_recovering == 0) {
2035 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2037 if (lprocfs_obd_snprintf(&page, size, &len,
2038 "recovery_start: %lu\n",
2039 obd->obd_recovery_start) <= 0)
2041 if (lprocfs_obd_snprintf(&page, size, &len,
2042 "recovery_duration: %lu\n",
2043 obd->obd_recovery_end -
2044 obd->obd_recovery_start) <= 0)
2046 /* Number of clients that have completed recovery */
2047 if (lprocfs_obd_snprintf(&page, size, &len,
2048 "completed_clients: %d/%d\n",
2049 obd->obd_max_recoverable_clients -
2050 obd->obd_recoverable_clients,
2051 obd->obd_max_recoverable_clients) <= 0)
2053 if (lprocfs_obd_snprintf(&page, size, &len,
2054 "replayed_requests: %d\n",
2055 obd->obd_replayed_requests) <= 0)
2057 if (lprocfs_obd_snprintf(&page, size, &len,
2058 "last_transno: "LPD64"\n",
2059 obd->obd_next_recovery_transno - 1)<=0)
2064 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2066 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2067 obd->obd_recovery_start) <= 0)
2069 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2070 cfs_time_current_sec() >= obd->obd_recovery_end ? 0 :
2071 obd->obd_recovery_end - cfs_time_current_sec()) <= 0)
2073 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2074 obd->obd_connected_clients,
2075 obd->obd_max_recoverable_clients) <= 0)
2077 /* Number of clients that have completed recovery */
2078 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d/%d\n",
2079 obd->obd_max_recoverable_clients -
2080 obd->obd_recoverable_clients,
2081 obd->obd_max_recoverable_clients) <= 0)
2083 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d/??\n",
2084 obd->obd_replayed_requests) <= 0)
2086 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2087 obd->obd_requests_queued_for_recovery) <= 0)
2090 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2091 obd->obd_next_recovery_transno) <= 0)
2097 return min(count, len - (int)off);
2099 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2101 int lprocfs_obd_rd_recovery_maxtime(char *page, char **start, off_t off,
2102 int count, int *eof, void *data)
2104 struct obd_device *obd = data;
2105 LASSERT(obd != NULL);
2107 return snprintf(page, count, "%lu\n", obd->obd_recovery_max_time);
2109 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_maxtime);
2111 int lprocfs_obd_wr_recovery_maxtime(struct file *file, const char *buffer,
2112 unsigned long count, void *data)
2114 struct obd_device *obd = data;
2116 LASSERT(obd != NULL);
2118 rc = lprocfs_write_helper(buffer, count, &val);
2122 obd->obd_recovery_max_time = val;
2125 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_maxtime);
2127 EXPORT_SYMBOL(lprocfs_register);
2128 EXPORT_SYMBOL(lprocfs_srch);
2129 EXPORT_SYMBOL(lprocfs_remove);
2130 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
2131 EXPORT_SYMBOL(lprocfs_add_vars);
2132 EXPORT_SYMBOL(lprocfs_obd_setup);
2133 EXPORT_SYMBOL(lprocfs_obd_cleanup);
2134 EXPORT_SYMBOL(lprocfs_add_simple);
2135 EXPORT_SYMBOL(lprocfs_add_symlink);
2136 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
2137 EXPORT_SYMBOL(lprocfs_alloc_stats);
2138 EXPORT_SYMBOL(lprocfs_free_stats);
2139 EXPORT_SYMBOL(lprocfs_clear_stats);
2140 EXPORT_SYMBOL(lprocfs_register_stats);
2141 EXPORT_SYMBOL(lprocfs_init_ops_stats);
2142 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
2143 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
2144 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
2145 EXPORT_SYMBOL(lprocfs_free_obd_stats);
2146 EXPORT_SYMBOL(lprocfs_exp_setup);
2147 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2149 EXPORT_SYMBOL(lprocfs_rd_u64);
2150 EXPORT_SYMBOL(lprocfs_rd_atomic);
2151 EXPORT_SYMBOL(lprocfs_wr_atomic);
2152 EXPORT_SYMBOL(lprocfs_rd_uint);
2153 EXPORT_SYMBOL(lprocfs_wr_uint);
2154 EXPORT_SYMBOL(lprocfs_rd_uuid);
2155 EXPORT_SYMBOL(lprocfs_rd_name);
2156 EXPORT_SYMBOL(lprocfs_rd_fstype);
2157 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
2158 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
2159 EXPORT_SYMBOL(lprocfs_rd_num_exports);
2160 EXPORT_SYMBOL(lprocfs_rd_numrefs);
2161 EXPORT_SYMBOL(lprocfs_at_hist_helper);
2162 EXPORT_SYMBOL(lprocfs_rd_import);
2163 EXPORT_SYMBOL(lprocfs_rd_timeouts);
2164 EXPORT_SYMBOL(lprocfs_rd_blksize);
2165 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
2166 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
2167 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
2168 EXPORT_SYMBOL(lprocfs_rd_filestotal);
2169 EXPORT_SYMBOL(lprocfs_rd_filesfree);
2171 EXPORT_SYMBOL(lprocfs_write_helper);
2172 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2173 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2174 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2175 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);