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 static ssize_t lprocfs_fops_read(struct file *f, char __user *buf, size_t size,
148 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
149 char *page, *start = NULL;
150 int rc = 0, eof = 1, count;
152 if (*ppos >= PAGE_SIZE)
155 page = (char *)__get_free_page(GFP_KERNEL);
160 OBD_FAIL_TIMEOUT(OBD_FAIL_LPROC_REMOVE, 10);
161 if (!LPROCFS_CHECK_DELETED(dp) && dp->read_proc)
162 rc = dp->read_proc(page, &start, *ppos, PAGE_SIZE,
168 /* for lustre proc read, the read count must be less than PAGE_SIZE */
177 start = page + *ppos;
178 } else if (start < page) {
182 count = (rc < size) ? rc : size;
183 if (copy_to_user(buf, start, count)) {
190 free_page((unsigned long)page);
194 static ssize_t lprocfs_fops_write(struct file *f, const char __user *buf,
195 size_t size, loff_t *ppos)
197 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
201 if (!LPROCFS_CHECK_DELETED(dp) && dp->write_proc)
202 rc = dp->write_proc(f, buf, size, dp->data);
207 static struct file_operations lprocfs_generic_fops = {
208 .owner = THIS_MODULE,
209 .read = lprocfs_fops_read,
210 .write = lprocfs_fops_write,
213 int lprocfs_evict_client_open(struct inode *inode, struct file *f)
215 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
216 struct obd_device *obd = dp->data;
218 atomic_inc(&obd->obd_evict_inprogress);
223 int lprocfs_evict_client_release(struct inode *inode, struct file *f)
225 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
226 struct obd_device *obd = dp->data;
228 atomic_dec(&obd->obd_evict_inprogress);
229 wake_up(&obd->obd_evict_inprogress_waitq);
234 struct file_operations lprocfs_evict_client_fops = {
235 .owner = THIS_MODULE,
236 .read = lprocfs_fops_read,
237 .write = lprocfs_fops_write,
238 .open = lprocfs_evict_client_open,
239 .release = lprocfs_evict_client_release,
241 EXPORT_SYMBOL(lprocfs_evict_client_fops);
246 * \param root [in] The parent proc entry on which new entry will be added.
247 * \param list [in] Array of proc entries to be added.
248 * \param data [in] The argument to be passed when entries read/write routines
249 * are called through /proc file.
251 * \retval 0 on success
254 int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list,
257 if (root == NULL || list == NULL)
260 while (list->name != NULL) {
261 struct proc_dir_entry *cur_root, *proc;
262 char *pathcopy, *cur, *next, pathbuf[64];
263 int pathsize = strlen(list->name) + 1;
268 /* need copy of path for strsep */
269 if (strlen(list->name) > sizeof(pathbuf) - 1) {
270 OBD_ALLOC(pathcopy, pathsize);
271 if (pathcopy == NULL)
278 strcpy(pathcopy, list->name);
280 while (cur_root != NULL && (cur = strsep(&next, "/"))) {
281 if (*cur =='\0') /* skip double/trailing "/" */
284 proc = lprocfs_srch(cur_root, cur);
285 CDEBUG(D_OTHER, "cur_root=%s, cur=%s, next=%s, (%s)\n",
286 cur_root->name, cur, next,
287 (proc ? "exists" : "new"));
289 cur_root = (proc ? proc :
290 proc_mkdir(cur, cur_root));
291 } else if (proc == NULL) {
293 if (list->proc_mode != 0000) {
294 mode = list->proc_mode;
298 if (list->write_fptr)
301 proc = create_proc_entry(cur, mode, cur_root);
305 if (pathcopy != pathbuf)
306 OBD_FREE(pathcopy, pathsize);
308 if (cur_root == NULL || proc == NULL) {
309 CERROR("LprocFS: No memory to create /proc entry %s",
315 proc->proc_fops = list->fops;
317 proc->proc_fops = &lprocfs_generic_fops;
318 proc->read_proc = list->read_fptr;
319 proc->write_proc = list->write_fptr;
320 proc->data = (list->data ? list->data : data);
326 void lprocfs_remove(struct proc_dir_entry **rooth)
328 struct proc_dir_entry *root = *rooth;
329 struct proc_dir_entry *temp = root;
330 struct proc_dir_entry *rm_entry;
331 struct proc_dir_entry *parent;
337 parent = root->parent;
338 LASSERT(parent != NULL);
339 LPROCFS_WRITE_ENTRY(); /* search vs remove race */
342 while (temp->subdir != NULL)
348 /* Memory corruption once caused this to fail, and
349 without this LASSERT we would loop here forever. */
350 LASSERTF(strlen(rm_entry->name) == rm_entry->namelen,
351 "0x%p %s/%s len %d\n", rm_entry, temp->name,
352 rm_entry->name, (int)strlen(rm_entry->name));
354 #ifdef HAVE_PROCFS_USERS
355 /* if procfs uses user count to synchronize deletion of
356 * proc entry, there is no protection for rm_entry->data,
357 * then lprocfs_fops_read and lprocfs_fops_write maybe
358 * call proc_dir_entry->read_proc (or write_proc) with
359 * proc_dir_entry->data == NULL, then cause kernel Oops.
360 * see bug19706 for detailed information */
362 /* procfs won't free rm_entry->data if it isn't a LINK,
363 * and Lustre won't use rm_entry->data if it is a LINK */
364 if (S_ISLNK(rm_entry->mode))
365 rm_entry->data = NULL;
367 /* Now, the rm_entry->deleted flags is protected
368 * by _lprocfs_lock. */
369 rm_entry->data = NULL;
371 remove_proc_entry(rm_entry->name, temp);
375 LPROCFS_WRITE_EXIT();
378 struct proc_dir_entry *lprocfs_register(const char *name,
379 struct proc_dir_entry *parent,
380 struct lprocfs_vars *list, void *data)
382 struct proc_dir_entry *newchild;
384 newchild = lprocfs_srch(parent, name);
385 if (newchild != NULL) {
386 CERROR(" Lproc: Attempting to register %s more than once \n",
388 return ERR_PTR(-EALREADY);
391 newchild = proc_mkdir(name, parent);
392 if (newchild != NULL && list != NULL) {
393 int rc = lprocfs_add_vars(newchild, list, data);
395 lprocfs_remove(&newchild);
402 /* Generic callbacks */
403 int lprocfs_rd_uint(char *page, char **start, off_t off,
404 int count, int *eof, void *data)
406 unsigned int *temp = (unsigned int *)data;
407 return snprintf(page, count, "%u\n", *temp);
410 int lprocfs_wr_uint(struct file *file, const char *buffer,
411 unsigned long count, void *data)
414 char dummy[MAX_STRING_SIZE + 1] = { '\0' }, *end;
417 if (count >= sizeof(dummy) || count == 0)
420 if (copy_from_user(dummy, buffer, count))
423 tmp = simple_strtoul(dummy, &end, 0);
427 *p = (unsigned int)tmp;
431 int lprocfs_rd_u64(char *page, char **start, off_t off,
432 int count, int *eof, void *data)
434 LASSERT(data != NULL);
436 return snprintf(page, count, LPU64"\n", *(__u64 *)data);
439 int lprocfs_rd_atomic(char *page, char **start, off_t off,
440 int count, int *eof, void *data)
442 atomic_t *atom = (atomic_t *)data;
443 LASSERT(atom != NULL);
445 return snprintf(page, count, "%d\n", atomic_read(atom));
448 int lprocfs_wr_atomic(struct file *file, const char *buffer,
449 unsigned long count, void *data)
451 atomic_t *atm = data;
455 rc = lprocfs_write_helper(buffer, count, &val);
462 atomic_set(atm, val);
466 int lprocfs_rd_uuid(char *page, char **start, off_t off, int count,
467 int *eof, void *data)
469 struct obd_device *obd = (struct obd_device*)data;
471 LASSERT(obd != NULL);
473 return snprintf(page, count, "%s\n", obd->obd_uuid.uuid);
476 int lprocfs_rd_name(char *page, char **start, off_t off, int count,
477 int *eof, void* data)
479 struct obd_device *dev = (struct obd_device *)data;
481 LASSERT(dev != NULL);
482 LASSERT(dev->obd_name != NULL);
484 return snprintf(page, count, "%s\n", dev->obd_name);
487 int lprocfs_rd_fstype(char *page, char **start, off_t off, int count, int *eof,
490 struct obd_device *obd = (struct obd_device *)data;
492 LASSERT(obd != NULL);
493 LASSERT(obd->obd_fsops != NULL);
494 LASSERT(obd->obd_fsops->fs_type != NULL);
495 return snprintf(page, count, "%s\n", obd->obd_fsops->fs_type);
498 int lprocfs_rd_blksize(char *page, char **start, off_t off, int count,
499 int *eof, void *data)
501 struct obd_statfs osfs;
502 int rc = obd_statfs(data, &osfs,
503 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
507 rc = snprintf(page, count, "%u\n", osfs.os_bsize);
512 int lprocfs_rd_kbytestotal(char *page, char **start, off_t off, int count,
513 int *eof, void *data)
515 struct obd_statfs osfs;
516 int rc = obd_statfs(data, &osfs,
517 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
520 __u32 blk_size = osfs.os_bsize >> 10;
521 __u64 result = osfs.os_blocks;
523 while (blk_size >>= 1)
527 rc = snprintf(page, count, LPU64"\n", result);
532 int lprocfs_rd_kbytesfree(char *page, char **start, off_t off, int count,
533 int *eof, void *data)
535 struct obd_statfs osfs;
536 int rc = obd_statfs(data, &osfs,
537 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
540 __u32 blk_size = osfs.os_bsize >> 10;
541 __u64 result = osfs.os_bfree;
543 while (blk_size >>= 1)
547 rc = snprintf(page, count, LPU64"\n", result);
552 int lprocfs_rd_kbytesavail(char *page, char **start, off_t off, int count,
553 int *eof, void *data)
555 struct obd_statfs osfs;
556 int rc = obd_statfs(data, &osfs,
557 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
560 __u32 blk_size = osfs.os_bsize >> 10;
561 __u64 result = osfs.os_bavail;
563 while (blk_size >>= 1)
567 rc = snprintf(page, count, LPU64"\n", result);
572 int lprocfs_rd_filestotal(char *page, char **start, off_t off, int count,
573 int *eof, void *data)
575 struct obd_statfs osfs;
576 int rc = obd_statfs(data, &osfs,
577 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
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,
592 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
596 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
601 int lprocfs_rd_server_uuid(char *page, char **start, off_t off, int count,
602 int *eof, void *data)
604 struct obd_device *obd = (struct obd_device *)data;
605 struct obd_import *imp;
606 char *imp_state_name = NULL;
609 LASSERT(obd != NULL);
610 LPROCFS_CLIMP_CHECK(obd);
611 imp = obd->u.cli.cl_import;
612 imp_state_name = ptlrpc_import_state_name(imp->imp_state);
614 rc = snprintf(page, count, "%s\t%s%s\n",
615 obd2cli_tgt(obd), imp_state_name,
616 imp->imp_deactive ? "\tDEACTIVATED" : "");
618 LPROCFS_CLIMP_EXIT(obd);
622 int lprocfs_rd_conn_uuid(char *page, char **start, off_t off, int count,
623 int *eof, void *data)
625 struct obd_device *obd = (struct obd_device*)data;
626 struct ptlrpc_connection *conn;
629 LASSERT(obd != NULL);
630 LPROCFS_CLIMP_CHECK(obd);
631 conn = obd->u.cli.cl_import->imp_connection;
632 LASSERT(conn != NULL);
634 rc = snprintf(page, count, "%s\n", conn->c_remote_uuid.uuid);
636 LPROCFS_CLIMP_EXIT(obd);
640 /** add up per-cpu counters */
641 void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
642 struct lprocfs_counter *cnt)
644 unsigned int num_cpu;
645 struct lprocfs_counter t;
646 struct lprocfs_counter *percpu_cntr;
649 memset(cnt, 0, sizeof(*cnt));
652 /* set count to 1 to avoid divide-by-zero errs in callers */
657 cnt->lc_min = LC_MIN_INIT;
659 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
662 num_cpu = num_possible_cpus();
664 for (i = 0; i < num_cpu; i++) {
665 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[idx];
668 centry = atomic_read(&percpu_cntr->lc_cntl.la_entry);
669 t.lc_count = percpu_cntr->lc_count;
670 t.lc_sum = percpu_cntr->lc_sum;
671 t.lc_min = percpu_cntr->lc_min;
672 t.lc_max = percpu_cntr->lc_max;
673 t.lc_sumsquare = percpu_cntr->lc_sumsquare;
674 } while (centry != atomic_read(&percpu_cntr->lc_cntl.la_entry) &&
675 centry != atomic_read(&percpu_cntr->lc_cntl.la_exit));
676 cnt->lc_count += t.lc_count;
677 cnt->lc_sum += t.lc_sum;
678 if (t.lc_min < cnt->lc_min)
679 cnt->lc_min = t.lc_min;
680 if (t.lc_max > cnt->lc_max)
681 cnt->lc_max = t.lc_max;
682 cnt->lc_sumsquare += t.lc_sumsquare;
685 cnt->lc_units = stats->ls_percpu[0]->lp_cntr[idx].lc_units;
689 * Append a space separated list of current set flags to str.
691 #define flag2str(flag) \
692 if (imp->imp_##flag && max - len > 0) \
693 len += snprintf(str + len, max - len, "%s" #flag, len ? ", " : "");
694 static int obd_import_flags2str(struct obd_import *imp, char *str, int max)
698 if (imp->imp_obd->obd_no_recov)
699 len += snprintf(str, max - len, " no_recov");
703 flag2str(replayable);
706 flag2str(last_recon);
711 static const char *obd_connect_names[] = {
738 "mds_mds_connection",
741 "alt_checksum_algorithm",
750 static int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
755 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
757 ret += snprintf(page + ret, count - ret, "%s%s",
758 ret ? sep : "", obd_connect_names[i]);
760 if (flags & ~(mask - 1))
761 ret += snprintf(page + ret, count - ret,
762 "%sunknown flags "LPX64,
763 ret ? sep : "", flags & ~(mask - 1));
767 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
768 int *eof, void *data)
770 struct lprocfs_counter ret;
771 struct obd_device *obd = (struct obd_device *)data;
772 struct obd_import *imp;
775 LASSERT(obd != NULL);
776 LPROCFS_CLIMP_CHECK(obd);
777 imp = obd->u.cli.cl_import;
780 i = snprintf(page, count,
784 " current_connection: %s\n"
789 imp->imp_connection->c_remote_uuid.uuid,
790 ptlrpc_import_state_name(imp->imp_state));
791 i += obd_connect_flags2str(page + i, count - i,
792 imp->imp_connect_data.ocd_connect_flags,
794 i += snprintf(page + i, count - i,
797 i += obd_import_flags2str(imp, page + i, count - i);
799 i += snprintf(page + i, count - i,
802 " connection_attempts: %u\n"
804 " in-progress_invalidations: %u\n",
807 atomic_read(&imp->imp_inval_count));
809 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
810 if (ret.lc_count != 0)
811 do_div(ret.lc_sum, ret.lc_count);
814 i += snprintf(page + i, count - i,
817 " unregistering: %u\n"
819 " avg_waittime: "LPU64" %s\n",
820 atomic_read(&imp->imp_inflight),
821 atomic_read(&imp->imp_unregistering),
822 atomic_read(&imp->imp_timeouts),
823 ret.lc_sum, ret.lc_units);
826 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
827 if (imp->imp_at.iat_portal[j] == 0)
829 k = max_t(unsigned int, k,
830 at_get(&imp->imp_at.iat_service_estimate[j]));
832 i += snprintf(page + i, count - i,
833 " service_estimates:\n"
834 " services: %u sec\n"
835 " network: %u sec\n",
837 at_get(&imp->imp_at.iat_net_latency));
839 i += snprintf(page + i, count - i,
841 " last_replay: "LPU64"\n"
842 " peer_committed: "LPU64"\n"
843 " last_checked: "LPU64"\n",
844 imp->imp_last_replay_transno,
845 imp->imp_peer_committed_transno,
846 imp->imp_last_transno_checked);
849 for (rw = 0; rw <= 1; rw++) {
850 lprocfs_stats_collect(obd->obd_svc_stats,
851 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
853 if (ret.lc_sum > 0 && ret.lc_count > 0) {
854 do_div(ret.lc_sum, ret.lc_count);
855 i += snprintf(page + i, count - i,
856 " %s_data_averages:\n"
857 " bytes_per_rpc: "LPU64"\n",
858 rw ? "write" : "read",
862 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
863 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
864 if (ret.lc_sum > 0 && ret.lc_count != 0) {
865 do_div(ret.lc_sum, ret.lc_count);
866 i += snprintf(page + i, count - i,
867 " %s_per_rpc: "LPU64"\n",
868 ret.lc_units, ret.lc_sum);
871 i += snprintf(page + i, count - i,
872 " MB_per_sec: %u.%.02u\n",
873 k / j, (100 * k / j) % 100);
877 LPROCFS_CLIMP_EXIT(obd);
881 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
882 int *eof, void *data)
884 struct obd_device *obd = (struct obd_device *)data;
885 struct obd_import *imp;
888 LASSERT(obd != NULL);
889 LPROCFS_CLIMP_CHECK(obd);
890 imp = obd->u.cli.cl_import;
893 i = snprintf(page, count, "current_state: %s\n",
894 ptlrpc_import_state_name(imp->imp_state));
895 i += snprintf(page + i, count - i,
897 k = imp->imp_state_hist_idx;
898 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
899 struct import_state_hist *ish =
900 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
901 if (ish->ish_state == 0)
903 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
905 ptlrpc_import_state_name(ish->ish_state));
908 LPROCFS_CLIMP_EXIT(obd);
912 int lprocfs_at_hist_helper(char *page, int count, int rc,
913 struct adaptive_timeout *at)
916 for (i = 0; i < AT_BINS; i++)
917 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
918 rc += snprintf(page + rc, count - rc, "\n");
922 /* See also ptlrpc_lprocfs_rd_timeouts */
923 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
924 int *eof, void *data)
926 struct obd_device *obd = (struct obd_device *)data;
927 struct obd_import *imp;
928 unsigned int cur, worst;
933 LASSERT(obd != NULL);
934 LPROCFS_CLIMP_CHECK(obd);
935 imp = obd->u.cli.cl_import;
938 now = cfs_time_current_sec();
940 /* Some network health info for kicks */
941 s2dhms(&ts, now - imp->imp_last_reply_time);
942 rc += snprintf(page + rc, count - rc,
943 "%-10s : %ld, "DHMS_FMT" ago\n",
944 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
946 cur = at_get(&imp->imp_at.iat_net_latency);
947 worst = imp->imp_at.iat_net_latency.at_worst_ever;
948 worstt = imp->imp_at.iat_net_latency.at_worst_time;
949 s2dhms(&ts, now - worstt);
950 rc += snprintf(page + rc, count - rc,
951 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
952 "network", cur, worst, worstt, DHMS_VARS(&ts));
953 rc = lprocfs_at_hist_helper(page, count, rc,
954 &imp->imp_at.iat_net_latency);
956 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
957 if (imp->imp_at.iat_portal[i] == 0)
959 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
960 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
961 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
962 s2dhms(&ts, now - worstt);
963 rc += snprintf(page + rc, count - rc,
964 "portal %-2d : cur %3u worst %3u (at %ld, "
965 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
966 cur, worst, worstt, DHMS_VARS(&ts));
967 rc = lprocfs_at_hist_helper(page, count, rc,
968 &imp->imp_at.iat_service_estimate[i]);
971 LPROCFS_CLIMP_EXIT(obd);
975 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
976 int count, int *eof, void *data)
978 struct obd_device *obd = data;
982 LPROCFS_CLIMP_CHECK(obd);
983 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
984 ret = snprintf(page, count, "flags="LPX64"\n", flags);
985 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
986 ret += snprintf(page + ret, count - ret, "\n");
987 LPROCFS_CLIMP_EXIT(obd);
990 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
992 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
993 int *eof, void *data)
995 struct obd_device *obd = (struct obd_device*)data;
997 LASSERT(obd != NULL);
999 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1002 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1003 int *eof, void *data)
1005 struct obd_type *class = (struct obd_type*) data;
1007 LASSERT(class != NULL);
1009 return snprintf(page, count, "%d\n", class->typ_refcnt);
1012 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1016 LASSERT(obd != NULL);
1017 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1018 LASSERT(obd->obd_type->typ_procroot != NULL);
1020 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1021 obd->obd_type->typ_procroot,
1023 if (IS_ERR(obd->obd_proc_entry)) {
1024 rc = PTR_ERR(obd->obd_proc_entry);
1025 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1026 obd->obd_proc_entry = NULL;
1031 int lprocfs_obd_cleanup(struct obd_device *obd)
1035 if (obd->obd_proc_exports_entry) {
1036 /* Should be no exports left */
1037 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1038 lprocfs_remove(&obd->obd_proc_exports_entry);
1040 lprocfs_remove(&obd->obd_proc_entry);
1044 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1046 CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
1047 client_stat->nid_proc, client_stat->nid_stats,
1048 client_stat->nid_brw_stats);
1050 LASSERTF(atomic_read(&client_stat->nid_exp_ref_count) == 0,
1051 "count %d\n", atomic_read(&client_stat->nid_exp_ref_count));
1053 hlist_del_init(&client_stat->nid_hash);
1055 if (client_stat->nid_proc)
1056 lprocfs_remove(&client_stat->nid_proc);
1058 if (client_stat->nid_stats)
1059 lprocfs_free_stats(&client_stat->nid_stats);
1061 if (client_stat->nid_brw_stats)
1062 OBD_FREE_PTR(client_stat->nid_brw_stats);
1064 if (client_stat->nid_ldlm_stats)
1065 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1067 OBD_FREE_PTR(client_stat);
1072 void lprocfs_free_per_client_stats(struct obd_device *obd)
1074 struct nid_stat *stat;
1077 /* we need extra list - because hash_exit called to early */
1078 /* not need locking because all clients is died */
1079 while(!list_empty(&obd->obd_nid_stats)) {
1080 stat = list_entry(obd->obd_nid_stats.next,
1081 struct nid_stat, nid_list);
1082 list_del_init(&stat->nid_list);
1083 lprocfs_free_client_stats(stat);
1089 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1090 enum lprocfs_stats_flags flags)
1092 struct lprocfs_stats *stats;
1093 unsigned int percpusize;
1095 unsigned int num_cpu;
1100 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1103 num_cpu = num_possible_cpus();
1105 OBD_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
1109 if (flags & LPROCFS_STATS_FLAG_NOPERCPU) {
1110 stats->ls_flags = flags;
1111 spin_lock_init(&stats->ls_lock);
1112 /* Use this lock only if there are no percpu areas */
1114 stats->ls_flags = 0;
1117 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
1119 percpusize = L1_CACHE_ALIGN(percpusize);
1121 for (i = 0; i < num_cpu; i++) {
1122 OBD_ALLOC(stats->ls_percpu[i], percpusize);
1123 if (stats->ls_percpu[i] == NULL) {
1124 for (j = 0; j < i; j++) {
1125 OBD_FREE(stats->ls_percpu[j], percpusize);
1126 stats->ls_percpu[j] = NULL;
1131 if (stats->ls_percpu[0] == NULL) {
1132 OBD_FREE(stats, offsetof(typeof(*stats),
1133 ls_percpu[num_cpu]));
1137 stats->ls_num = num;
1141 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1143 struct lprocfs_stats *stats = *statsh;
1144 unsigned int num_cpu;
1145 unsigned int percpusize;
1148 if (!stats || (stats->ls_num == 0))
1151 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1154 num_cpu = num_possible_cpus();
1156 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
1158 percpusize = L1_CACHE_ALIGN(percpusize);
1159 for (i = 0; i < num_cpu; i++)
1160 OBD_FREE(stats->ls_percpu[i], percpusize);
1161 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
1164 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1166 struct lprocfs_counter *percpu_cntr;
1168 unsigned int num_cpu;
1170 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1172 for (i = 0; i < num_cpu; i++) {
1173 for (j = 0; j < stats->ls_num; j++) {
1174 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
1175 atomic_inc(&percpu_cntr->lc_cntl.la_entry);
1176 percpu_cntr->lc_count = 0;
1177 percpu_cntr->lc_sum = 0;
1178 percpu_cntr->lc_min = LC_MIN_INIT;
1179 percpu_cntr->lc_max = 0;
1180 percpu_cntr->lc_sumsquare = 0;
1181 atomic_inc(&percpu_cntr->lc_cntl.la_exit);
1185 lprocfs_stats_unlock(stats);
1188 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1189 size_t len, loff_t *off)
1191 struct seq_file *seq = file->private_data;
1192 struct lprocfs_stats *stats = seq->private;
1194 lprocfs_clear_stats(stats);
1199 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1201 struct lprocfs_stats *stats = p->private;
1202 /* return 1st cpu location */
1203 return (*pos >= stats->ls_num) ? NULL :
1204 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1207 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1211 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1213 struct lprocfs_stats *stats = p->private;
1215 return (*pos >= stats->ls_num) ? NULL :
1216 &(stats->ls_percpu[0]->lp_cntr[*pos]);
1219 /* seq file export of one lprocfs counter */
1220 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1222 struct lprocfs_stats *stats = p->private;
1223 struct lprocfs_counter *cntr = v;
1224 struct lprocfs_counter ret;
1227 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
1229 do_gettimeofday(&now);
1230 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1231 "snapshot_time", now.tv_sec, now.tv_usec);
1235 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
1237 lprocfs_stats_collect(stats, idx, &ret);
1239 if (ret.lc_count == 0)
1242 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", cntr->lc_name,
1243 ret.lc_count, cntr->lc_units);
1248 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
1249 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1250 ret.lc_min, ret.lc_max, ret.lc_sum);
1253 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
1254 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1258 rc = seq_printf(p, "\n");
1260 return (rc < 0) ? rc : 0;
1263 struct seq_operations lprocfs_stats_seq_sops = {
1264 start: lprocfs_stats_seq_start,
1265 stop: lprocfs_stats_seq_stop,
1266 next: lprocfs_stats_seq_next,
1267 show: lprocfs_stats_seq_show,
1270 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1272 struct proc_dir_entry *dp = PDE(inode);
1273 struct seq_file *seq;
1276 LPROCFS_ENTRY_AND_CHECK(dp);
1277 rc = seq_open(file, &lprocfs_stats_seq_sops);
1283 seq = file->private_data;
1284 seq->private = dp->data;
1288 struct file_operations lprocfs_stats_seq_fops = {
1289 .owner = THIS_MODULE,
1290 .open = lprocfs_stats_seq_open,
1292 .write = lprocfs_stats_seq_write,
1293 .llseek = seq_lseek,
1294 .release = lprocfs_seq_release,
1297 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1298 struct lprocfs_stats *stats)
1300 struct proc_dir_entry *entry;
1301 LASSERT(root != NULL);
1303 entry = create_proc_entry(name, 0644, root);
1306 entry->proc_fops = &lprocfs_stats_seq_fops;
1307 entry->data = (void *)stats;
1311 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1312 unsigned conf, const char *name, const char *units)
1314 struct lprocfs_counter *c;
1316 unsigned int num_cpu;
1318 LASSERT(stats != NULL);
1320 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1322 for (i = 0; i < num_cpu; i++) {
1323 c = &(stats->ls_percpu[i]->lp_cntr[index]);
1324 c->lc_config = conf;
1327 c->lc_min = LC_MIN_INIT;
1330 c->lc_units = units;
1333 lprocfs_stats_unlock(stats);
1335 EXPORT_SYMBOL(lprocfs_counter_init);
1337 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1339 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1340 LASSERT(coffset < stats->ls_num); \
1341 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1344 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1346 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1347 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1348 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1349 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1350 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1351 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1352 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1353 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1354 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1355 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1356 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1357 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1358 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1359 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1360 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1361 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1362 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1363 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1364 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1365 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1366 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1367 LPROCFS_OBD_OP_INIT(num_private_stats, stats, checkmd);
1368 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1369 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1370 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1371 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1372 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1373 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1374 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1375 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1376 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1377 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1378 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw_async);
1379 LPROCFS_OBD_OP_INIT(num_private_stats, stats, prep_async_page);
1380 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_lock);
1381 LPROCFS_OBD_OP_INIT(num_private_stats, stats, queue_async_io);
1382 LPROCFS_OBD_OP_INIT(num_private_stats, stats, queue_group_io);
1383 LPROCFS_OBD_OP_INIT(num_private_stats, stats, trigger_group_io);
1384 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_async_flags);
1385 LPROCFS_OBD_OP_INIT(num_private_stats, stats, teardown_async_page);
1386 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1387 LPROCFS_OBD_OP_INIT(num_private_stats, stats, update_lvb);
1388 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1389 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1390 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1391 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1392 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1393 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1394 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1395 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1396 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1397 LPROCFS_OBD_OP_INIT(num_private_stats, stats, match);
1398 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1399 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
1400 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1401 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1402 LPROCFS_OBD_OP_INIT(num_private_stats, stats, join_lru);
1403 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1404 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1405 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1406 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1407 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1408 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1409 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1410 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1411 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1412 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1413 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1414 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1415 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quota_adjust_qunit);
1416 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1417 LPROCFS_OBD_OP_INIT(num_private_stats, stats, register_page_removal_cb);
1418 LPROCFS_OBD_OP_INIT(num_private_stats,stats,unregister_page_removal_cb);
1419 LPROCFS_OBD_OP_INIT(num_private_stats, stats, register_lock_cancel_cb);
1420 LPROCFS_OBD_OP_INIT(num_private_stats, stats,unregister_lock_cancel_cb);
1421 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1422 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1423 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1424 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1425 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1426 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1429 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1431 lprocfs_counter_init(ldlm_stats,
1432 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1433 0, "ldlm_enqueue", "reqs");
1434 lprocfs_counter_init(ldlm_stats,
1435 LDLM_CONVERT - LDLM_FIRST_OPC,
1436 0, "ldlm_convert", "reqs");
1437 lprocfs_counter_init(ldlm_stats,
1438 LDLM_CANCEL - LDLM_FIRST_OPC,
1439 0, "ldlm_cancel", "reqs");
1440 lprocfs_counter_init(ldlm_stats,
1441 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1442 0, "ldlm_bl_callback", "reqs");
1443 lprocfs_counter_init(ldlm_stats,
1444 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1445 0, "ldlm_cp_callback", "reqs");
1446 lprocfs_counter_init(ldlm_stats,
1447 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1448 0, "ldlm_gl_callback", "reqs");
1451 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1453 struct lprocfs_stats *stats;
1454 unsigned int num_stats;
1457 LASSERT(obd->obd_stats == NULL);
1458 LASSERT(obd->obd_proc_entry != NULL);
1459 LASSERT(obd->obd_cntr_base == 0);
1461 num_stats = ((int)sizeof(*obd->obd_type->typ_ops) / sizeof(void *)) +
1462 num_private_stats - 1 /* o_owner */;
1463 stats = lprocfs_alloc_stats(num_stats, 0);
1467 lprocfs_init_ops_stats(num_private_stats, stats);
1469 for (i = num_private_stats; i < num_stats; i++) {
1470 /* If this LBUGs, it is likely that an obd
1471 * operation was added to struct obd_ops in
1472 * <obd.h>, and that the corresponding line item
1473 * LPROCFS_OBD_OP_INIT(.., .., opname)
1474 * is missing from the list above. */
1475 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1476 "Missing obd_stat initializer obd_op "
1477 "operation at offset %d.\n", i - num_private_stats);
1479 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1481 lprocfs_free_stats(&stats);
1483 obd->obd_stats = stats;
1484 obd->obd_cntr_base = num_private_stats;
1489 void lprocfs_free_obd_stats(struct obd_device *obd)
1492 lprocfs_free_stats(&obd->obd_stats);
1495 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1496 int *eof, void *data)
1498 struct obd_export *exp = (struct obd_export*)data;
1499 LASSERT(exp != NULL);
1501 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1504 struct exp_uuid_cb_data {
1512 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1513 int count, int *eof, int *len)
1515 cb_data->page = page;
1516 cb_data->count = count;
1521 void lprocfs_exp_print_uuid(void *obj, void *cb_data)
1523 struct obd_export *exp = (struct obd_export *)obj;
1524 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1526 if (exp->exp_nid_stats)
1527 *data->len += snprintf((data->page + *data->len),
1528 data->count, "%s\n",
1529 obd_uuid2str(&exp->exp_client_uuid));
1532 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1533 int *eof, void *data)
1535 struct nid_stat *stats = (struct nid_stat *)data;
1536 struct exp_uuid_cb_data cb_data;
1537 struct obd_device *obd = stats->nid_obd;
1542 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1543 lustre_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1544 lprocfs_exp_print_uuid, &cb_data);
1545 return (*cb_data.len);
1548 void lprocfs_exp_print_hash(void *obj, void *cb_data)
1550 struct obd_export *exp = (struct obd_export *)obj;
1551 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1554 lh = exp->exp_lock_hash;
1557 *data->len += lustre_hash_debug_header(data->page,
1560 *data->len += lustre_hash_debug_str(lh, data->page +
1566 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1567 int *eof, void *data)
1569 struct nid_stat *stats = (struct nid_stat *)data;
1570 struct exp_uuid_cb_data cb_data;
1571 struct obd_device *obd = stats->nid_obd;
1576 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1577 lustre_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1578 lprocfs_exp_print_hash, &cb_data);
1579 return (*cb_data.len);
1582 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1583 int count, int *eof, void *data)
1586 return snprintf(page, count, "%s\n",
1587 "Write into this file to clear all nid stats and "
1588 "stale nid entries");
1590 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1592 void lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1594 struct nid_stat *stat = obj;
1597 /* object has only hash + iterate_all references.
1598 * add/delete blocked by hash bucket lock */
1599 CDEBUG(D_INFO,"refcnt %d\n", atomic_read(&stat->nid_exp_ref_count));
1600 if (atomic_read(&stat->nid_exp_ref_count) == 2) {
1601 hlist_del_init(&stat->nid_hash);
1602 nidstat_putref(stat);
1603 spin_lock(&stat->nid_obd->obd_nid_lock);
1604 list_move(&stat->nid_list, data);
1605 spin_unlock(&stat->nid_obd->obd_nid_lock);
1609 /* we has reference to object - only clear data*/
1610 if (stat->nid_stats)
1611 lprocfs_clear_stats(stat->nid_stats);
1613 if (stat->nid_brw_stats) {
1614 for (i = 0; i < BRW_LAST; i++)
1615 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
1621 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1622 unsigned long count, void *data)
1624 struct obd_device *obd = (struct obd_device *)data;
1625 struct nid_stat *client_stat;
1626 CFS_LIST_HEAD(free_list);
1628 lustre_hash_for_each(obd->obd_nid_stats_hash,
1629 lprocfs_nid_stats_clear_write_cb, &free_list);
1631 while (!list_empty(&free_list)) {
1632 client_stat = list_entry(free_list.next, struct nid_stat,
1634 list_del_init(&client_stat->nid_list);
1635 lprocfs_free_client_stats(client_stat);
1640 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1642 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int reconnect,
1646 struct nid_stat *new_stat, *old_stat;
1647 struct obd_device *obd;
1648 cfs_proc_dir_entry_t *entry;
1649 char *buffer = NULL;
1654 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1655 !exp->exp_obd->obd_nid_stats_hash)
1658 /* not test against zero because eric say:
1659 * You may only test nid against another nid, or LNET_NID_ANY.
1660 * Anything else is nonsense.*/
1661 if (!nid || *nid == LNET_NID_ANY)
1666 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
1668 OBD_ALLOC_PTR(new_stat);
1669 if (new_stat == NULL)
1672 new_stat->nid = *nid;
1673 new_stat->nid_obd = exp->exp_obd;
1674 /* we need set default refcount to 1 to balance obd_disconnect() */
1675 atomic_set(&new_stat->nid_exp_ref_count, 1);
1677 old_stat = lustre_hash_findadd_unique(obd->obd_nid_stats_hash,
1678 nid, &new_stat->nid_hash);
1679 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
1680 old_stat, libcfs_nid2str(*nid),
1681 atomic_read(&new_stat->nid_exp_ref_count));
1683 /* Return -EALREADY here so that we know that the /proc
1684 * entry already has been created */
1685 if (old_stat != new_stat) {
1686 /* if this reconnect to live export from diffrent nid, we need
1687 * to release old stats because disconnect will be never called.
1689 if (reconnect && exp->exp_nid_stats)
1690 nidstat_putref(exp->exp_nid_stats);
1692 exp->exp_nid_stats = old_stat;
1693 GOTO(destroy_new, rc = -EALREADY);
1696 /* not found - create */
1697 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
1699 GOTO(destroy_new_ns, rc = -ENOMEM);
1701 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
1702 new_stat->nid_proc = proc_mkdir(buffer, obd->obd_proc_exports_entry);
1703 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
1705 if (!new_stat->nid_proc) {
1706 CERROR("Error making export directory for"
1707 " nid %s\n", libcfs_nid2str(*nid));
1708 GOTO(destroy_new_ns, rc = -ENOMEM);
1711 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
1712 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
1713 if (IS_ERR(entry)) {
1714 CWARN("Error adding the uuid file\n");
1715 rc = PTR_ERR(entry);
1716 GOTO(destroy_new_ns, rc);
1719 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
1720 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
1721 if (IS_ERR(entry)) {
1722 CWARN("Error adding the hash file\n");
1723 rc = PTR_ERR(entry);
1724 GOTO(destroy_new_ns, rc);
1727 exp->exp_nid_stats = new_stat;
1729 /* protect competitive add to list, not need locking on destroy */
1730 spin_lock(&obd->obd_nid_lock);
1731 list_add(&new_stat->nid_list, &obd->obd_nid_stats);
1732 spin_unlock(&obd->obd_nid_lock);
1737 if (new_stat->nid_proc != NULL)
1738 lprocfs_remove(&new_stat->nid_proc);
1739 lustre_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
1742 nidstat_putref(new_stat);
1743 OBD_FREE_PTR(new_stat);
1747 int lprocfs_exp_cleanup(struct obd_export *exp)
1749 struct nid_stat *stat = exp->exp_nid_stats;
1751 if(!stat || !exp->exp_obd)
1754 nidstat_putref(exp->exp_nid_stats);
1755 exp->exp_nid_stats = NULL;
1760 int lprocfs_write_helper(const char *buffer, unsigned long count,
1763 return lprocfs_write_frac_helper(buffer, count, val, 1);
1766 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
1769 char kernbuf[20], *end, *pbuf;
1771 if (count > (sizeof(kernbuf) - 1))
1774 if (copy_from_user(kernbuf, buffer, count))
1777 kernbuf[count] = '\0';
1784 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1788 if (end != NULL && *end == '.') {
1789 int temp_val, pow = 1;
1793 if (strlen(pbuf) > 5)
1794 pbuf[5] = '\0'; /*only allow 5bits fractional*/
1796 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1799 for (i = 0; i < (end - pbuf); i++)
1802 *val += temp_val / pow;
1808 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
1811 long decimal_val, frac_val;
1817 decimal_val = val / mult;
1818 prtn = snprintf(buffer, count, "%ld", decimal_val);
1819 frac_val = val % mult;
1821 if (prtn < (count - 4) && frac_val > 0) {
1823 int i, temp_mult = 1, frac_bits = 0;
1825 temp_frac = frac_val * 10;
1826 buffer[prtn++] = '.';
1827 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
1828 /*only reserved 2bits fraction*/
1829 buffer[prtn++] ='0';
1834 Need to think these cases :
1835 1. #echo x.00 > /proc/xxx output result : x
1836 2. #echo x.0x > /proc/xxx output result : x.0x
1837 3. #echo x.x0 > /proc/xxx output result : x.x
1838 4. #echo x.xx > /proc/xxx output result : x.xx
1839 Only reserved 2bits fraction.
1841 for (i = 0; i < (5 - prtn); i++)
1844 frac_bits = min((int)count - prtn, 3 - frac_bits);
1845 prtn += snprintf(buffer + prtn, frac_bits, "%ld", frac_val * temp_mult / mult);
1848 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
1850 if (buffer[prtn] == '.') {
1857 buffer[prtn++] ='\n';
1861 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
1863 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
1866 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
1867 __u64 *val, int mult)
1869 char kernbuf[22], *end, *pbuf;
1870 __u64 whole, frac = 0, units;
1871 unsigned frac_d = 1;
1873 if (count > (sizeof(kernbuf) - 1))
1876 if (copy_from_user(kernbuf, buffer, count))
1879 kernbuf[count] = '\0';
1886 whole = simple_strtoull(pbuf, &end, 10);
1890 if (end != NULL && *end == '.') {
1894 /* need to limit frac_d to a __u32 */
1895 if (strlen(pbuf) > 10)
1898 frac = simple_strtoull(pbuf, &end, 10);
1899 /* count decimal places */
1900 for (i = 0; i < (end - pbuf); i++)
1917 /* Specified units override the multiplier */
1919 mult = mult < 0 ? -units : units;
1922 do_div(frac, frac_d);
1923 *val = whole * mult + frac;
1927 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent,
1928 char *name, mode_t mode,
1929 struct file_operations *seq_fops, void *data)
1931 struct proc_dir_entry *entry;
1934 entry = create_proc_entry(name, mode, parent);
1937 entry->proc_fops = seq_fops;
1942 EXPORT_SYMBOL(lprocfs_seq_create);
1944 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
1946 struct file_operations *seq_fops,
1949 return (lprocfs_seq_create(dev->obd_proc_entry, name,
1950 mode, seq_fops, data));
1952 EXPORT_SYMBOL(lprocfs_obd_seq_create);
1954 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
1956 if (value >= OBD_HIST_MAX)
1957 value = OBD_HIST_MAX - 1;
1959 spin_lock(&oh->oh_lock);
1960 oh->oh_buckets[value]++;
1961 spin_unlock(&oh->oh_lock);
1963 EXPORT_SYMBOL(lprocfs_oh_tally);
1965 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
1969 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
1972 lprocfs_oh_tally(oh, val);
1974 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
1976 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
1978 unsigned long ret = 0;
1981 for (i = 0; i < OBD_HIST_MAX; i++)
1982 ret += oh->oh_buckets[i];
1985 EXPORT_SYMBOL(lprocfs_oh_sum);
1987 void lprocfs_oh_clear(struct obd_histogram *oh)
1989 spin_lock(&oh->oh_lock);
1990 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
1991 spin_unlock(&oh->oh_lock);
1993 EXPORT_SYMBOL(lprocfs_oh_clear);
1995 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
1996 int count, int *eof, void *data)
1998 struct obd_device *obd = data;
2001 LASSERT(obd != NULL);
2002 LASSERT(count >= 0);
2004 /* Set start of user data returned to
2005 page + off since the user may have
2006 requested to read much smaller than
2007 what we need to read */
2008 *start = page + off;
2010 /* We know we are allocated a page here.
2011 Also we know that this function will
2012 not need to write more than a page
2013 so we can truncate at CFS_PAGE_SIZE. */
2014 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2016 /* Initialize the page */
2017 memset(page, 0, size);
2019 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2021 if (obd->obd_max_recoverable_clients == 0) {
2022 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2028 /* sampled unlocked, but really... */
2029 if (obd->obd_recovering == 0) {
2030 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2032 if (lprocfs_obd_snprintf(&page, size, &len,
2033 "recovery_start: %lu\n",
2034 obd->obd_recovery_start) <= 0)
2036 if (lprocfs_obd_snprintf(&page, size, &len,
2037 "recovery_duration: %lu\n",
2038 obd->obd_recovery_end -
2039 obd->obd_recovery_start) <= 0)
2041 if (lprocfs_obd_snprintf(&page, size, &len,
2042 "delayed_clients: %d/%d\n",
2043 obd->obd_delayed_clients,
2044 obd->obd_max_recoverable_clients) <= 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_delayed_clients -
2052 obd->obd_stale_clients,
2053 obd->obd_max_recoverable_clients) <= 0)
2055 if (lprocfs_obd_snprintf(&page, size, &len,
2056 "replayed_requests: %d\n",
2057 obd->obd_replayed_requests) <= 0)
2059 if (lprocfs_obd_snprintf(&page, size, &len,
2060 "last_transno: "LPD64"\n",
2061 obd->obd_next_recovery_transno - 1)<=0)
2066 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2068 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2069 obd->obd_recovery_start) <= 0)
2071 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2072 cfs_time_current_sec() >= obd->obd_recovery_end ? 0 :
2073 obd->obd_recovery_end - cfs_time_current_sec()) <= 0)
2075 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2076 obd->obd_connected_clients,
2077 obd->obd_max_recoverable_clients) <= 0)
2079 if (lprocfs_obd_snprintf(&page, size, &len,"delayed_clients: %d/%d\n",
2080 obd->obd_delayed_clients,
2081 obd->obd_max_recoverable_clients) <= 0)
2083 /* Number of clients that have completed recovery */
2084 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d/%d\n",
2085 obd->obd_max_recoverable_clients -
2086 obd->obd_recoverable_clients -
2087 obd->obd_delayed_clients,
2088 obd->obd_max_recoverable_clients) <= 0)
2090 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d/??\n",
2091 obd->obd_replayed_requests) <= 0)
2093 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2094 obd->obd_requests_queued_for_recovery) <= 0)
2096 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2097 obd->obd_next_recovery_transno) <= 0)
2103 return min(count, len - (int)off);
2105 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2107 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2108 int count, int *eof, void *data)
2110 struct obd_device *obd = data;
2116 c += lustre_hash_debug_header(page, count);
2117 c += lustre_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2118 c += lustre_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2119 c += lustre_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2123 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2125 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
2126 int count, int *eof, void *data)
2128 struct obd_device *obd = (struct obd_device *)data;
2129 LASSERT(obd != NULL);
2131 return snprintf(page, count, "%d\n",
2132 obd->obd_recovery_timeout);
2134 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
2136 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
2137 unsigned long count, void *data)
2139 struct obd_device *obd = (struct obd_device *)data;
2141 LASSERT(obd != NULL);
2143 rc = lprocfs_write_helper(buffer, count, &val);
2147 obd->obd_recovery_timeout = val;
2150 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
2152 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
2153 int count, int *eof, void *data)
2155 struct obd_device *obd = (struct obd_device *)data;
2156 LASSERT(obd != NULL);
2158 return snprintf(page, count, "%lu\n",
2159 obd->obd_recovery_time_hard);
2161 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
2163 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
2164 unsigned long count, void *data)
2166 struct obd_device *obd = (struct obd_device *)data;
2168 LASSERT(obd != NULL);
2170 rc = lprocfs_write_helper(buffer, count, &val);
2174 obd->obd_recovery_time_hard = val;
2177 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
2179 #ifdef HAVE_DELAYED_RECOVERY
2180 int lprocfs_obd_rd_stale_export_age(char *page, char **start, off_t off,
2181 int count, int *eof, void *data)
2183 struct obd_device *obd = (struct obd_device *)data;
2184 LASSERT(obd != NULL);
2186 return snprintf(page, count, "%u\n",
2187 obd->u.obt.obt_stale_export_age);
2189 EXPORT_SYMBOL(lprocfs_obd_rd_stale_export_age);
2191 int lprocfs_obd_wr_stale_export_age(struct file *file, const char *buffer,
2192 unsigned long count, void *data)
2194 struct obd_device *obd = (struct obd_device *)data;
2196 LASSERT(obd != NULL);
2198 rc = lprocfs_write_helper(buffer, count, &val);
2202 target_trans_table_recalc(obd, val);
2203 obd->u.obt.obt_stale_export_age = val;
2206 EXPORT_SYMBOL(lprocfs_obd_wr_stale_export_age);
2208 static int obd_stale_exports_seq_show(struct seq_file *seq, void *v)
2210 struct obd_device *obd = seq->private;
2211 struct obd_export *exp;
2213 spin_lock(&obd->obd_dev_lock);
2214 list_for_each_entry(exp, &obd->obd_delayed_exports,
2216 seq_printf(seq, "%s: %ld seconds ago%s\n",
2217 obd_uuid2str(&exp->exp_client_uuid),
2218 cfs_time_current_sec() - exp->exp_last_request_time,
2219 exp_expired(exp, obd->u.obt.obt_stale_export_age) ?
2222 spin_unlock(&obd->obd_dev_lock);
2226 LPROC_SEQ_FOPS_RO(obd_stale_exports);
2228 int lprocfs_obd_attach_stale_exports(struct obd_device *dev)
2230 return lprocfs_obd_seq_create(dev, "stale_exports", 0444,
2231 &obd_stale_exports_fops, dev);
2233 EXPORT_SYMBOL(lprocfs_obd_attach_stale_exports);
2235 int lprocfs_obd_wr_flush_stale_exports(struct file *file, const char *buffer,
2236 unsigned long count, void *data)
2238 struct obd_device *obd = (struct obd_device *)data;
2240 LASSERT(obd != NULL);
2242 rc = lprocfs_write_helper(buffer, count, &val);
2246 class_disconnect_expired_exports(obd);
2249 EXPORT_SYMBOL(lprocfs_obd_wr_flush_stale_exports);
2252 EXPORT_SYMBOL(lprocfs_register);
2253 EXPORT_SYMBOL(lprocfs_srch);
2254 EXPORT_SYMBOL(lprocfs_remove);
2255 EXPORT_SYMBOL(lprocfs_add_vars);
2256 EXPORT_SYMBOL(lprocfs_obd_setup);
2257 EXPORT_SYMBOL(lprocfs_obd_cleanup);
2258 EXPORT_SYMBOL(lprocfs_add_simple);
2259 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
2260 EXPORT_SYMBOL(lprocfs_alloc_stats);
2261 EXPORT_SYMBOL(lprocfs_free_stats);
2262 EXPORT_SYMBOL(lprocfs_clear_stats);
2263 EXPORT_SYMBOL(lprocfs_register_stats);
2264 EXPORT_SYMBOL(lprocfs_init_ops_stats);
2265 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
2266 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
2267 EXPORT_SYMBOL(lprocfs_free_obd_stats);
2268 EXPORT_SYMBOL(lprocfs_exp_setup);
2269 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2271 EXPORT_SYMBOL(lprocfs_rd_u64);
2272 EXPORT_SYMBOL(lprocfs_rd_atomic);
2273 EXPORT_SYMBOL(lprocfs_wr_atomic);
2274 EXPORT_SYMBOL(lprocfs_rd_uint);
2275 EXPORT_SYMBOL(lprocfs_wr_uint);
2276 EXPORT_SYMBOL(lprocfs_rd_uuid);
2277 EXPORT_SYMBOL(lprocfs_rd_name);
2278 EXPORT_SYMBOL(lprocfs_rd_fstype);
2279 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
2280 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
2281 EXPORT_SYMBOL(lprocfs_rd_num_exports);
2282 EXPORT_SYMBOL(lprocfs_rd_numrefs);
2283 EXPORT_SYMBOL(lprocfs_at_hist_helper);
2284 EXPORT_SYMBOL(lprocfs_rd_import);
2285 EXPORT_SYMBOL(lprocfs_rd_state);
2286 EXPORT_SYMBOL(lprocfs_rd_timeouts);
2287 EXPORT_SYMBOL(lprocfs_rd_blksize);
2288 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
2289 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
2290 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
2291 EXPORT_SYMBOL(lprocfs_rd_filestotal);
2292 EXPORT_SYMBOL(lprocfs_rd_filesfree);
2294 EXPORT_SYMBOL(lprocfs_write_helper);
2295 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2296 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2297 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2298 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2299 EXPORT_SYMBOL(lprocfs_stats_collect);