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",
811 "", /* reserved for simplified interop */
816 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
817 int count, int *eof, void *data)
819 struct obd_device *obd = data;
820 __u64 mask = 1, flags;
823 LPROCFS_CLIMP_CHECK(obd);
824 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
825 ret = snprintf(page, count, "flags="LPX64"\n", flags);
826 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
828 ret += snprintf(page + ret, count - ret, "%s\n",
829 obd_connect_names[i]);
831 if (flags & ~(mask - 1))
832 ret += snprintf(page + ret, count - ret,
833 "unknown flags "LPX64"\n", flags & ~(mask - 1));
835 LPROCFS_CLIMP_EXIT(obd);
838 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
840 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
841 int *eof, void *data)
843 struct obd_device *obd = data;
845 LASSERT(obd != NULL);
847 return snprintf(page, count, "%u\n", obd->obd_num_exports);
850 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
851 int *eof, void *data)
853 struct obd_type *class = (struct obd_type*) data;
855 LASSERT(class != NULL);
857 return snprintf(page, count, "%d\n", class->typ_refcnt);
860 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
864 LASSERT(obd != NULL);
865 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
866 LASSERT(obd->obd_type->typ_procroot != NULL);
868 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
869 obd->obd_type->typ_procroot,
871 if (IS_ERR(obd->obd_proc_entry)) {
872 rc = PTR_ERR(obd->obd_proc_entry);
873 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
874 obd->obd_proc_entry = NULL;
879 int lprocfs_obd_cleanup(struct obd_device *obd)
883 if (obd->obd_proc_exports_entry) {
884 /* Should be no exports left */
885 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
886 lprocfs_remove(&obd->obd_proc_exports_entry);
887 obd->obd_proc_exports_entry = NULL;
889 lprocfs_remove(&obd->obd_proc_entry);
893 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
895 CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
896 client_stat->nid_proc, client_stat->nid_stats,
897 client_stat->nid_brw_stats);
899 LASSERTF(client_stat->nid_exp_ref_count == 0, "count %d\n",
900 client_stat->nid_exp_ref_count);
902 hlist_del_init(&client_stat->nid_hash);
904 if (client_stat->nid_proc)
905 lprocfs_remove(&client_stat->nid_proc);
907 if (client_stat->nid_stats)
908 lprocfs_free_stats(&client_stat->nid_stats);
910 if (client_stat->nid_brw_stats)
911 OBD_FREE_PTR(client_stat->nid_brw_stats);
913 if (client_stat->nid_ldlm_stats)
914 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
916 OBD_FREE_PTR(client_stat);
921 void lprocfs_free_per_client_stats(struct obd_device *obd)
923 struct nid_stat *stat;
926 /* we need extra list - because hash_exit called to early */
927 /* not need locking because all clients is died */
928 while(!list_empty(&obd->obd_nid_stats)) {
929 stat = list_entry(obd->obd_nid_stats.next,
930 struct nid_stat, nid_list);
931 list_del_init(&stat->nid_list);
932 lprocfs_free_client_stats(stat);
938 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
939 enum lprocfs_stats_flags flags)
941 struct lprocfs_stats *stats;
942 unsigned int percpusize;
944 unsigned int num_cpu;
949 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
952 num_cpu = num_possible_cpus();
954 OBD_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
958 if (flags & LPROCFS_STATS_FLAG_NOPERCPU) {
959 stats->ls_flags = flags;
960 spin_lock_init(&stats->ls_lock);
961 /* Use this lock only if there are no percpu areas */
966 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
968 percpusize = L1_CACHE_ALIGN(percpusize);
970 for (i = 0; i < num_cpu; i++) {
971 OBD_ALLOC(stats->ls_percpu[i], percpusize);
972 if (stats->ls_percpu[i] == NULL) {
973 for (j = 0; j < i; j++) {
974 OBD_FREE(stats->ls_percpu[j], percpusize);
975 stats->ls_percpu[j] = NULL;
980 if (stats->ls_percpu[0] == NULL) {
981 OBD_FREE(stats, offsetof(typeof(*stats),
982 ls_percpu[num_cpu]));
990 void lprocfs_free_stats(struct lprocfs_stats **statsh)
992 struct lprocfs_stats *stats = *statsh;
993 unsigned int num_cpu;
994 unsigned int percpusize;
997 if (stats == NULL || stats->ls_num == 0)
1001 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1004 num_cpu = num_possible_cpus();
1006 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
1008 percpusize = L1_CACHE_ALIGN(percpusize);
1009 for (i = 0; i < num_cpu; i++)
1010 OBD_FREE(stats->ls_percpu[i], percpusize);
1011 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
1014 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1016 struct lprocfs_counter *percpu_cntr;
1018 unsigned int num_cpu;
1020 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1022 for (i = 0; i < num_cpu; i++) {
1023 for (j = 0; j < stats->ls_num; j++) {
1024 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
1025 atomic_inc(&percpu_cntr->lc_cntl.la_entry);
1026 percpu_cntr->lc_count = 0;
1027 percpu_cntr->lc_sum = 0;
1028 percpu_cntr->lc_min = LC_MIN_INIT;
1029 percpu_cntr->lc_max = 0;
1030 percpu_cntr->lc_sumsquare = 0;
1031 atomic_inc(&percpu_cntr->lc_cntl.la_exit);
1035 lprocfs_stats_unlock(stats);
1038 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1039 size_t len, loff_t *off)
1041 struct seq_file *seq = file->private_data;
1042 struct lprocfs_stats *stats = seq->private;
1044 lprocfs_clear_stats(stats);
1049 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1051 struct lprocfs_stats *stats = p->private;
1052 /* return 1st cpu location */
1053 return (*pos >= stats->ls_num) ? NULL :
1054 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1057 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1061 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1063 struct lprocfs_stats *stats = p->private;
1065 return (*pos >= stats->ls_num) ? NULL :
1066 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1069 /* seq file export of one lprocfs counter */
1070 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1072 struct lprocfs_stats *stats = p->private;
1073 struct lprocfs_counter *cntr = v;
1074 struct lprocfs_counter t, ret = { .lc_min = LC_MIN_INIT };
1076 unsigned int num_cpu;
1078 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
1080 do_gettimeofday(&now);
1081 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1082 "snapshot_time", now.tv_sec, now.tv_usec);
1086 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
1088 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1091 num_cpu = num_possible_cpus();
1093 for (i = 0; i < num_cpu; i++) {
1094 struct lprocfs_counter *percpu_cntr =
1095 &(stats->ls_percpu[i])->lp_cntr[idx];
1099 centry = atomic_read(&percpu_cntr->lc_cntl.la_entry);
1100 t.lc_count = percpu_cntr->lc_count;
1101 t.lc_sum = percpu_cntr->lc_sum;
1102 t.lc_min = percpu_cntr->lc_min;
1103 t.lc_max = percpu_cntr->lc_max;
1104 t.lc_sumsquare = percpu_cntr->lc_sumsquare;
1105 } while (centry != atomic_read(&percpu_cntr->lc_cntl.la_entry) &&
1106 centry != atomic_read(&percpu_cntr->lc_cntl.la_exit));
1107 ret.lc_count += t.lc_count;
1108 ret.lc_sum += t.lc_sum;
1109 if (t.lc_min < ret.lc_min)
1110 ret.lc_min = t.lc_min;
1111 if (t.lc_max > ret.lc_max)
1112 ret.lc_max = t.lc_max;
1113 ret.lc_sumsquare += t.lc_sumsquare;
1116 if (ret.lc_count == 0)
1119 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", cntr->lc_name,
1120 ret.lc_count, cntr->lc_units);
1124 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
1125 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1126 ret.lc_min, ret.lc_max, ret.lc_sum);
1129 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
1130 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1134 rc = seq_printf(p, "\n");
1136 return (rc < 0) ? rc : 0;
1139 struct seq_operations lprocfs_stats_seq_sops = {
1140 start: lprocfs_stats_seq_start,
1141 stop: lprocfs_stats_seq_stop,
1142 next: lprocfs_stats_seq_next,
1143 show: lprocfs_stats_seq_show,
1146 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1148 struct proc_dir_entry *dp = PDE(inode);
1149 struct seq_file *seq;
1152 LPROCFS_ENTRY_AND_CHECK(dp);
1153 rc = seq_open(file, &lprocfs_stats_seq_sops);
1158 seq = file->private_data;
1159 seq->private = dp->data;
1163 struct file_operations lprocfs_stats_seq_fops = {
1164 .owner = THIS_MODULE,
1165 .open = lprocfs_stats_seq_open,
1167 .write = lprocfs_stats_seq_write,
1168 .llseek = seq_lseek,
1169 .release = lprocfs_seq_release,
1172 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1173 struct lprocfs_stats *stats)
1175 struct proc_dir_entry *entry;
1176 LASSERT(root != NULL);
1178 entry = create_proc_entry(name, 0644, root);
1181 entry->proc_fops = &lprocfs_stats_seq_fops;
1182 entry->data = stats;
1186 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1187 unsigned conf, const char *name, const char *units)
1189 struct lprocfs_counter *c;
1191 unsigned int num_cpu;
1193 LASSERT(stats != NULL);
1195 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1197 for (i = 0; i < num_cpu; i++) {
1198 c = &(stats->ls_percpu[i]->lp_cntr[index]);
1199 c->lc_config = conf;
1202 c->lc_min = LC_MIN_INIT;
1205 c->lc_units = units;
1208 lprocfs_stats_unlock(stats);
1210 EXPORT_SYMBOL(lprocfs_counter_init);
1212 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1214 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1215 LASSERT(coffset < stats->ls_num); \
1216 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1219 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1221 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1222 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1223 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1224 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1225 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1226 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1227 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1228 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1229 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1230 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1231 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1232 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1233 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1234 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1235 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1236 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1237 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1238 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1239 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
1240 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1241 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1242 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1243 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1244 LPROCFS_OBD_OP_INIT(num_private_stats, stats, checkmd);
1245 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1246 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1247 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1248 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1249 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1250 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1251 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1252 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1253 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1254 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1255 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1256 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1257 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1258 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1259 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1260 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1261 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1262 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1263 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1264 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1265 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1266 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1267 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1268 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1269 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1270 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1271 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1272 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1273 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1274 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1275 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1276 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1277 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1278 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1279 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1280 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1281 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quota_adjust_qunit);
1282 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1283 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1284 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1285 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1286 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1289 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1291 struct lprocfs_stats *stats;
1292 unsigned int num_stats;
1295 LASSERT(obd->obd_stats == NULL);
1296 LASSERT(obd->obd_proc_entry != NULL);
1297 LASSERT(obd->obd_cntr_base == 0);
1299 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1300 num_private_stats - 1 /* o_owner */;
1301 stats = lprocfs_alloc_stats(num_stats, 0);
1305 lprocfs_init_ops_stats(num_private_stats, stats);
1307 for (i = num_private_stats; i < num_stats; i++) {
1308 /* If this LBUGs, it is likely that an obd
1309 * operation was added to struct obd_ops in
1310 * <obd.h>, and that the corresponding line item
1311 * LPROCFS_OBD_OP_INIT(.., .., opname)
1312 * is missing from the list above. */
1313 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1314 "Missing obd_stat initializer obd_op "
1315 "operation at offset %d.\n", i - num_private_stats);
1317 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1319 lprocfs_free_stats(&stats);
1321 obd->obd_stats = stats;
1322 obd->obd_cntr_base = num_private_stats;
1327 void lprocfs_free_obd_stats(struct obd_device *obd)
1330 lprocfs_free_stats(&obd->obd_stats);
1333 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1335 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1336 LASSERT(coffset < stats->ls_num); \
1337 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1340 int lprocfs_alloc_md_stats(struct obd_device *obd,
1341 unsigned num_private_stats)
1343 struct lprocfs_stats *stats;
1344 unsigned int num_stats;
1347 LASSERT(obd->md_stats == NULL);
1348 LASSERT(obd->obd_proc_entry != NULL);
1349 LASSERT(obd->md_cntr_base == 0);
1351 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1353 stats = lprocfs_alloc_stats(num_stats, 0);
1357 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1358 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1359 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1360 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1361 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1362 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1363 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1364 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1365 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1366 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1367 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1368 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1369 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1370 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1371 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1372 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1373 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1374 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1375 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1376 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1377 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1378 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1379 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1380 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1381 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1382 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1383 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1384 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1385 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1386 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1387 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1389 for (i = num_private_stats; i < num_stats; i++) {
1390 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1391 CERROR("Missing md_stat initializer md_op "
1392 "operation at offset %d. Aborting.\n",
1393 i - num_private_stats);
1397 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1399 lprocfs_free_stats(&stats);
1401 obd->md_stats = stats;
1402 obd->md_cntr_base = num_private_stats;
1407 void lprocfs_free_md_stats(struct obd_device *obd)
1409 struct lprocfs_stats *stats = obd->md_stats;
1411 if (stats != NULL) {
1412 obd->md_stats = NULL;
1413 obd->md_cntr_base = 0;
1414 lprocfs_free_stats(&stats);
1418 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1420 lprocfs_counter_init(ldlm_stats,
1421 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1422 0, "ldlm_enqueue", "reqs");
1423 lprocfs_counter_init(ldlm_stats,
1424 LDLM_CONVERT - LDLM_FIRST_OPC,
1425 0, "ldlm_convert", "reqs");
1426 lprocfs_counter_init(ldlm_stats,
1427 LDLM_CANCEL - LDLM_FIRST_OPC,
1428 0, "ldlm_cancel", "reqs");
1429 lprocfs_counter_init(ldlm_stats,
1430 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1431 0, "ldlm_bl_callback", "reqs");
1432 lprocfs_counter_init(ldlm_stats,
1433 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1434 0, "ldlm_cp_callback", "reqs");
1435 lprocfs_counter_init(ldlm_stats,
1436 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1437 0, "ldlm_gl_callback", "reqs");
1440 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1441 int *eof, void *data)
1443 struct obd_export *exp = data;
1444 LASSERT(exp != NULL);
1446 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1449 struct exp_uuid_cb_data {
1457 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1458 int count, int *eof, int *len)
1460 cb_data->page = page;
1461 cb_data->count = count;
1466 void lprocfs_exp_print_uuid(void *obj, void *cb_data)
1468 struct obd_export *exp = (struct obd_export *)obj;
1469 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1471 if (exp->exp_nid_stats)
1472 *data->len += snprintf((data->page + *data->len),
1473 data->count, "%s\n",
1474 obd_uuid2str(&exp->exp_client_uuid));
1477 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1478 int *eof, void *data)
1480 struct nid_stat *stats = (struct nid_stat *)data;
1481 struct exp_uuid_cb_data cb_data;
1482 struct obd_device *obd = stats->nid_obd;
1487 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1488 lustre_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1489 lprocfs_exp_print_uuid, &cb_data);
1490 return (*cb_data.len);
1493 void lprocfs_exp_print_hash(void *obj, void *cb_data)
1495 struct exp_uuid_cb_data *data = cb_data;
1496 struct obd_export *exp = obj;
1499 lh = exp->exp_lock_hash;
1502 *data->len += lustre_hash_debug_header(data->page,
1505 *data->len += lustre_hash_debug_str(lh, data->page + *data->len,
1510 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1511 int *eof, void *data)
1513 struct nid_stat *stats = (struct nid_stat *)data;
1514 struct exp_uuid_cb_data cb_data;
1515 struct obd_device *obd = stats->nid_obd;
1520 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1522 lustre_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1523 lprocfs_exp_print_hash, &cb_data);
1524 return (*cb_data.len);
1527 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1528 int count, int *eof, void *data)
1531 return snprintf(page, count, "%s\n",
1532 "Write into this file to clear all nid stats and "
1533 "stale nid entries");
1535 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1537 void lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1539 struct nid_stat *stat = obj;
1542 /* object has only hash + iterate_all references.
1543 * add/delete blocked by hash bucket lock */
1544 CDEBUG(D_INFO,"refcnt %d\n", stat->nid_exp_ref_count);
1545 if (stat->nid_exp_ref_count == 2) {
1546 hlist_del_init(&stat->nid_hash);
1547 stat->nid_exp_ref_count--;
1548 spin_lock(&stat->nid_obd->obd_nid_lock);
1549 list_move(&stat->nid_list, data);
1550 spin_unlock(&stat->nid_obd->obd_nid_lock);
1554 /* we has reference to object - only clear data*/
1555 if (stat->nid_stats)
1556 lprocfs_clear_stats(stat->nid_stats);
1558 if (stat->nid_brw_stats) {
1559 for (i = 0; i < BRW_LAST; i++)
1560 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
1566 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1567 unsigned long count, void *data)
1569 struct obd_device *obd = (struct obd_device *)data;
1570 struct nid_stat *client_stat;
1571 CFS_LIST_HEAD(free_list);
1573 lustre_hash_for_each(obd->obd_nid_stats_hash,
1574 lprocfs_nid_stats_clear_write_cb, &free_list);
1576 while (!list_empty(&free_list)) {
1577 client_stat = list_entry(free_list.next, struct nid_stat,
1579 list_del_init(&client_stat->nid_list);
1580 lprocfs_free_client_stats(client_stat);
1585 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1587 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1589 struct nid_stat *new_stat, *old_stat;
1590 struct nid_stat_uuid *new_ns_uuid;
1591 struct obd_device *obd = NULL;
1592 cfs_proc_dir_entry_t *entry;
1598 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1599 !exp->exp_obd->obd_nid_stats_hash)
1602 /* not test against zero because eric say:
1603 * You may only test nid against another nid, or LNET_NID_ANY.
1604 * Anything else is nonsense.*/
1605 if (!nid || *nid == LNET_NID_ANY)
1610 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
1612 OBD_ALLOC_PTR(new_stat);
1613 if (new_stat == NULL)
1616 OBD_ALLOC_PTR(new_ns_uuid);
1617 if (new_ns_uuid == NULL) {
1618 OBD_FREE_PTR(new_stat);
1621 CFS_INIT_LIST_HEAD(&new_ns_uuid->ns_uuid_list);
1622 strncpy(new_ns_uuid->ns_uuid.uuid, exp->exp_client_uuid.uuid,
1623 sizeof(struct obd_uuid));
1625 CFS_INIT_LIST_HEAD(&new_stat->nid_uuid_list);
1626 new_stat->nid = *nid;
1627 new_stat->nid_obd = exp->exp_obd;
1628 new_stat->nid_exp_ref_count = 1; /* live in hash after destroy export */
1630 old_stat = lustre_hash_findadd_unique(obd->obd_nid_stats_hash,
1631 nid, &new_stat->nid_hash);
1632 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
1633 old_stat, libcfs_nid2str(*nid), new_stat->nid_exp_ref_count);
1635 /* Return -EALREADY here so that we know that the /proc
1636 * entry already has been created */
1637 if (old_stat != new_stat) {
1638 struct nid_stat_uuid *tmp_uuid;
1641 exp->exp_nid_stats = old_stat;
1642 /* We need to decrement the refcount if the uuid was
1643 * already in our list */
1644 spin_lock(&obd->obd_nid_lock);
1645 list_for_each_entry(tmp_uuid, &old_stat->nid_uuid_list,
1647 if (tmp_uuid && obd_uuid_equals(&tmp_uuid->ns_uuid,
1648 &exp->exp_client_uuid)){
1650 --old_stat->nid_exp_ref_count;
1656 list_add(&new_ns_uuid->ns_uuid_list,
1657 &old_stat->nid_uuid_list);
1659 OBD_FREE_PTR(new_ns_uuid);
1661 spin_unlock(&obd->obd_nid_lock);
1663 GOTO(destroy_new, rc = -EALREADY);
1665 /* not found - create */
1666 new_stat->nid_proc = lprocfs_register(libcfs_nid2str(*nid),
1667 obd->obd_proc_exports_entry,
1669 if (new_stat->nid_proc == NULL) {
1670 CERROR("Error making export directory for nid %s\n",
1671 libcfs_nid2str(*nid));
1672 GOTO(destroy_new_ns, rc = -ENOMEM);
1675 /* Add in uuid to our nid_stats list */
1676 spin_lock(&obd->obd_nid_lock);
1677 list_add(&new_ns_uuid->ns_uuid_list, &new_stat->nid_uuid_list);
1678 spin_unlock(&obd->obd_nid_lock);
1680 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
1681 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
1682 if (IS_ERR(entry)) {
1683 CWARN("Error adding the NID stats file\n");
1684 rc = PTR_ERR(entry);
1685 GOTO(destroy_new_ns, rc);
1688 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
1689 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
1690 if (IS_ERR(entry)) {
1691 CWARN("Error adding the hash file\n");
1692 lprocfs_remove(&new_stat->nid_proc);
1693 rc = PTR_ERR(entry);
1694 GOTO(destroy_new_ns, rc);
1697 exp->exp_nid_stats = new_stat;
1699 /* protect competitive add to list, not need locking on destroy */
1700 spin_lock(&obd->obd_nid_lock);
1701 list_add(&new_stat->nid_list, &obd->obd_nid_stats);
1702 spin_unlock(&obd->obd_nid_lock);
1707 lustre_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
1708 OBD_FREE_PTR(new_ns_uuid);
1711 OBD_FREE_PTR(new_stat);
1715 int lprocfs_exp_cleanup(struct obd_export *exp)
1717 struct nid_stat *stat = exp->exp_nid_stats;
1718 struct nid_stat_uuid *cursor, *tmp;
1721 if(!stat || !exp->exp_obd)
1724 spin_lock(&exp->exp_obd->obd_nid_lock);
1725 list_for_each_entry_safe(cursor, tmp,
1726 &stat->nid_uuid_list,
1728 if (cursor && obd_uuid_equals(&cursor->ns_uuid,
1729 &exp->exp_client_uuid)) {
1731 list_del(&cursor->ns_uuid_list);
1732 OBD_FREE_PTR(cursor);
1733 --stat->nid_exp_ref_count;
1734 CDEBUG(D_INFO, "Put stat %p - %d\n", stat,
1735 stat->nid_exp_ref_count);
1739 spin_unlock(&exp->exp_obd->obd_nid_lock);
1741 CERROR("obd_export's client uuid %s are not found in its "
1742 "nid_stats list\n", exp->exp_client_uuid.uuid);
1744 exp->exp_nid_stats = NULL;
1745 lprocfs_free_md_stats(exp->exp_obd);
1750 int lprocfs_write_helper(const char *buffer, unsigned long count,
1753 return lprocfs_write_frac_helper(buffer, count, val, 1);
1756 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
1759 char kernbuf[20], *end, *pbuf;
1761 if (count > (sizeof(kernbuf) - 1))
1764 if (copy_from_user(kernbuf, buffer, count))
1767 kernbuf[count] = '\0';
1774 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1778 if (end != NULL && *end == '.') {
1779 int temp_val, pow = 1;
1783 if (strlen(pbuf) > 5)
1784 pbuf[5] = '\0'; /*only allow 5bits fractional*/
1786 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1789 for (i = 0; i < (end - pbuf); i++)
1792 *val += temp_val / pow;
1798 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
1801 long decimal_val, frac_val;
1807 decimal_val = val / mult;
1808 prtn = snprintf(buffer, count, "%ld", decimal_val);
1809 frac_val = val % mult;
1811 if (prtn < (count - 4) && frac_val > 0) {
1813 int i, temp_mult = 1, frac_bits = 0;
1815 temp_frac = frac_val * 10;
1816 buffer[prtn++] = '.';
1817 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
1818 /* only reserved 2 bits fraction */
1819 buffer[prtn++] ='0';
1824 * Need to think these cases :
1825 * 1. #echo x.00 > /proc/xxx output result : x
1826 * 2. #echo x.0x > /proc/xxx output result : x.0x
1827 * 3. #echo x.x0 > /proc/xxx output result : x.x
1828 * 4. #echo x.xx > /proc/xxx output result : x.xx
1829 * Only reserved 2 bits fraction.
1831 for (i = 0; i < (5 - prtn); i++)
1834 frac_bits = min((int)count - prtn, 3 - frac_bits);
1835 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
1836 frac_val * temp_mult / mult);
1839 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
1841 if (buffer[prtn] == '.') {
1848 buffer[prtn++] ='\n';
1852 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
1854 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
1857 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
1858 __u64 *val, int mult)
1860 char kernbuf[22], *end, *pbuf;
1861 __u64 whole, frac = 0, units;
1862 unsigned frac_d = 1;
1864 if (count > (sizeof(kernbuf) - 1))
1867 if (copy_from_user(kernbuf, buffer, count))
1870 kernbuf[count] = '\0';
1877 whole = simple_strtoull(pbuf, &end, 10);
1881 if (end != NULL && *end == '.') {
1885 /* need to limit frac_d to a __u32 */
1886 if (strlen(pbuf) > 10)
1889 frac = simple_strtoull(pbuf, &end, 10);
1890 /* count decimal places */
1891 for (i = 0; i < (end - pbuf); i++)
1908 /* Specified units override the multiplier */
1910 mult = mult < 0 ? -units : units;
1913 do_div(frac, frac_d);
1914 *val = whole * mult + frac;
1918 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent, char *name, mode_t mode,
1919 struct file_operations *seq_fops, void *data)
1921 struct proc_dir_entry *entry;
1924 entry = create_proc_entry(name, mode, parent);
1927 entry->proc_fops = seq_fops;
1932 EXPORT_SYMBOL(lprocfs_seq_create);
1934 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
1936 struct file_operations *seq_fops,
1939 return (lprocfs_seq_create(dev->obd_proc_entry, name,
1940 mode, seq_fops, data));
1942 EXPORT_SYMBOL(lprocfs_obd_seq_create);
1944 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
1946 if (value >= OBD_HIST_MAX)
1947 value = OBD_HIST_MAX - 1;
1949 spin_lock(&oh->oh_lock);
1950 oh->oh_buckets[value]++;
1951 spin_unlock(&oh->oh_lock);
1953 EXPORT_SYMBOL(lprocfs_oh_tally);
1955 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
1959 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
1962 lprocfs_oh_tally(oh, val);
1964 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
1966 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
1968 unsigned long ret = 0;
1971 for (i = 0; i < OBD_HIST_MAX; i++)
1972 ret += oh->oh_buckets[i];
1975 EXPORT_SYMBOL(lprocfs_oh_sum);
1977 void lprocfs_oh_clear(struct obd_histogram *oh)
1979 spin_lock(&oh->oh_lock);
1980 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
1981 spin_unlock(&oh->oh_lock);
1983 EXPORT_SYMBOL(lprocfs_oh_clear);
1985 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
1986 int count, int *eof, void *data)
1988 struct obd_device *obd = data;
1994 c += lustre_hash_debug_header(page, count);
1995 c += lustre_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
1996 c += lustre_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
1997 c += lustre_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2001 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2003 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2004 int count, int *eof, void *data)
2006 struct obd_device *obd = data;
2009 LASSERT(obd != NULL);
2010 LASSERT(count >= 0);
2012 /* Set start of user data returned to
2013 page + off since the user may have
2014 requested to read much smaller than
2015 what we need to read */
2016 *start = page + off;
2018 /* We know we are allocated a page here.
2019 Also we know that this function will
2020 not need to write more than a page
2021 so we can truncate at CFS_PAGE_SIZE. */
2022 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2024 /* Initialize the page */
2025 memset(page, 0, size);
2027 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2029 if (obd->obd_max_recoverable_clients == 0) {
2030 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2036 /* sampled unlocked, but really... */
2037 if (obd->obd_recovering == 0) {
2038 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2040 if (lprocfs_obd_snprintf(&page, size, &len,
2041 "recovery_start: %lu\n",
2042 obd->obd_recovery_start) <= 0)
2044 if (lprocfs_obd_snprintf(&page, size, &len,
2045 "recovery_duration: %lu\n",
2046 obd->obd_recovery_end -
2047 obd->obd_recovery_start) <= 0)
2049 /* Number of clients that have completed recovery */
2050 if (lprocfs_obd_snprintf(&page, size, &len,
2051 "completed_clients: %d/%d\n",
2052 obd->obd_max_recoverable_clients -
2053 obd->obd_recoverable_clients,
2054 obd->obd_max_recoverable_clients) <= 0)
2056 if (lprocfs_obd_snprintf(&page, size, &len,
2057 "replayed_requests: %d\n",
2058 obd->obd_replayed_requests) <= 0)
2060 if (lprocfs_obd_snprintf(&page, size, &len,
2061 "last_transno: "LPD64"\n",
2062 obd->obd_next_recovery_transno - 1)<=0)
2067 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2069 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2070 obd->obd_recovery_start) <= 0)
2072 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2073 cfs_time_current_sec() >= obd->obd_recovery_end ? 0 :
2074 obd->obd_recovery_end - cfs_time_current_sec()) <= 0)
2076 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2077 obd->obd_connected_clients,
2078 obd->obd_max_recoverable_clients) <= 0)
2080 /* Number of clients that have completed recovery */
2081 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d/%d\n",
2082 obd->obd_max_recoverable_clients -
2083 obd->obd_recoverable_clients,
2084 obd->obd_max_recoverable_clients) <= 0)
2086 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d/??\n",
2087 obd->obd_replayed_requests) <= 0)
2089 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2090 obd->obd_requests_queued_for_recovery) <= 0)
2093 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2094 obd->obd_next_recovery_transno) <= 0)
2100 return min(count, len - (int)off);
2102 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2104 int lprocfs_obd_rd_recovery_maxtime(char *page, char **start, off_t off,
2105 int count, int *eof, void *data)
2107 struct obd_device *obd = data;
2108 LASSERT(obd != NULL);
2110 return snprintf(page, count, "%lu\n", obd->obd_recovery_max_time);
2112 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_maxtime);
2114 int lprocfs_obd_wr_recovery_maxtime(struct file *file, const char *buffer,
2115 unsigned long count, void *data)
2117 struct obd_device *obd = data;
2119 LASSERT(obd != NULL);
2121 rc = lprocfs_write_helper(buffer, count, &val);
2125 obd->obd_recovery_max_time = val;
2128 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_maxtime);
2130 EXPORT_SYMBOL(lprocfs_register);
2131 EXPORT_SYMBOL(lprocfs_srch);
2132 EXPORT_SYMBOL(lprocfs_remove);
2133 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
2134 EXPORT_SYMBOL(lprocfs_add_vars);
2135 EXPORT_SYMBOL(lprocfs_obd_setup);
2136 EXPORT_SYMBOL(lprocfs_obd_cleanup);
2137 EXPORT_SYMBOL(lprocfs_add_simple);
2138 EXPORT_SYMBOL(lprocfs_add_symlink);
2139 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
2140 EXPORT_SYMBOL(lprocfs_alloc_stats);
2141 EXPORT_SYMBOL(lprocfs_free_stats);
2142 EXPORT_SYMBOL(lprocfs_clear_stats);
2143 EXPORT_SYMBOL(lprocfs_register_stats);
2144 EXPORT_SYMBOL(lprocfs_init_ops_stats);
2145 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
2146 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
2147 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
2148 EXPORT_SYMBOL(lprocfs_free_obd_stats);
2149 EXPORT_SYMBOL(lprocfs_exp_setup);
2150 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2152 EXPORT_SYMBOL(lprocfs_rd_u64);
2153 EXPORT_SYMBOL(lprocfs_rd_atomic);
2154 EXPORT_SYMBOL(lprocfs_wr_atomic);
2155 EXPORT_SYMBOL(lprocfs_rd_uint);
2156 EXPORT_SYMBOL(lprocfs_wr_uint);
2157 EXPORT_SYMBOL(lprocfs_rd_uuid);
2158 EXPORT_SYMBOL(lprocfs_rd_name);
2159 EXPORT_SYMBOL(lprocfs_rd_fstype);
2160 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
2161 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
2162 EXPORT_SYMBOL(lprocfs_rd_num_exports);
2163 EXPORT_SYMBOL(lprocfs_rd_numrefs);
2164 EXPORT_SYMBOL(lprocfs_at_hist_helper);
2165 EXPORT_SYMBOL(lprocfs_rd_import);
2166 EXPORT_SYMBOL(lprocfs_rd_timeouts);
2167 EXPORT_SYMBOL(lprocfs_rd_blksize);
2168 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
2169 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
2170 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
2171 EXPORT_SYMBOL(lprocfs_rd_filestotal);
2172 EXPORT_SYMBOL(lprocfs_rd_filesfree);
2174 EXPORT_SYMBOL(lprocfs_write_helper);
2175 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2176 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2177 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2178 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);