4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; If not, see
18 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21 * CA 95054 USA or visit www.sun.com if you need additional information or
27 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Use is subject to license terms.
30 * Copyright (c) 2011, 2012, Intel Corporation.
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>
41 #define DEBUG_SUBSYSTEM S_CLASS
44 # include <liblustre.h>
47 #include <obd_class.h>
48 #include <lprocfs_status.h>
49 #include <lustre_fsfilt.h>
50 #include <lustre_log.h>
51 #include <lustre_disk.h>
52 #include <lustre/lustre_idl.h>
53 #include <dt_object.h>
57 static int lprocfs_no_percpu_stats = 0;
58 CFS_MODULE_PARM(lprocfs_no_percpu_stats, "i", int, 0644,
59 "Do not alloc percpu data for lprocfs stats");
61 #define MAX_STRING_SIZE 128
63 /* for bug 10866, global variable */
64 DECLARE_RWSEM(_lprocfs_lock);
65 EXPORT_SYMBOL(_lprocfs_lock);
67 int lprocfs_single_release(struct inode *inode, struct file *file)
70 return single_release(inode, file);
72 EXPORT_SYMBOL(lprocfs_single_release);
74 int lprocfs_seq_release(struct inode *inode, struct file *file)
77 return seq_release(inode, file);
79 EXPORT_SYMBOL(lprocfs_seq_release);
81 static struct proc_dir_entry *__lprocfs_srch(struct proc_dir_entry *head,
84 struct proc_dir_entry *temp;
90 while (temp != NULL) {
91 if (strcmp(temp->name, name) == 0) {
100 struct proc_dir_entry *lprocfs_srch(struct proc_dir_entry *head,
103 struct proc_dir_entry *temp;
105 LPROCFS_SRCH_ENTRY();
106 temp = __lprocfs_srch(head, name);
110 EXPORT_SYMBOL(lprocfs_srch);
112 /* lprocfs API calls */
114 /* Function that emulates snprintf but also has the side effect of advancing
115 the page pointer for the next write into the buffer, incrementing the total
116 length written to the buffer, and decrementing the size left in the
118 static int lprocfs_obd_snprintf(char **page, int end, int *len,
119 const char *format, ...)
127 va_start(list, format);
128 n = vsnprintf(*page, end - *len, format, list);
131 *page += n; *len += n;
135 cfs_proc_dir_entry_t *lprocfs_add_simple(struct proc_dir_entry *root,
137 read_proc_t *read_proc,
138 write_proc_t *write_proc,
140 struct file_operations *fops)
142 cfs_proc_dir_entry_t *proc;
145 if (root == NULL || name == NULL)
146 return ERR_PTR(-EINVAL);
153 LPROCFS_WRITE_ENTRY();
154 proc = create_proc_entry(name, mode, root);
156 CERROR("LprocFS: No memory to create /proc entry %s", name);
157 LPROCFS_WRITE_EXIT();
158 return ERR_PTR(-ENOMEM);
160 proc->read_proc = read_proc;
161 proc->write_proc = write_proc;
164 proc->proc_fops = fops;
165 LPROCFS_WRITE_EXIT();
168 EXPORT_SYMBOL(lprocfs_add_simple);
170 struct proc_dir_entry *lprocfs_add_symlink(const char *name,
171 struct proc_dir_entry *parent, const char *format, ...)
173 struct proc_dir_entry *entry;
177 if (parent == NULL || format == NULL)
180 OBD_ALLOC_WAIT(dest, MAX_STRING_SIZE + 1);
184 va_start(ap, format);
185 vsnprintf(dest, MAX_STRING_SIZE, format, ap);
188 entry = proc_symlink(name, parent, dest);
190 CERROR("LprocFS: Could not create symbolic link from %s to %s",
193 OBD_FREE(dest, MAX_STRING_SIZE + 1);
196 EXPORT_SYMBOL(lprocfs_add_symlink);
198 static ssize_t lprocfs_fops_read(struct file *f, char __user *buf,
199 size_t size, loff_t *ppos)
201 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
202 char *page, *start = NULL;
203 int rc = 0, eof = 1, count;
205 if (*ppos >= CFS_PAGE_SIZE)
208 page = (char *)__get_free_page(GFP_KERNEL);
212 if (LPROCFS_ENTRY_AND_CHECK(dp)) {
217 OBD_FAIL_TIMEOUT(OBD_FAIL_LPROC_REMOVE, 10);
219 rc = dp->read_proc(page, &start, *ppos, CFS_PAGE_SIZE,
225 /* for lustre proc read, the read count must be less than PAGE_SIZE */
234 start = page + *ppos;
235 } else if (start < page) {
239 count = (rc < size) ? rc : size;
240 if (cfs_copy_to_user(buf, start, count)) {
247 free_page((unsigned long)page);
251 static ssize_t lprocfs_fops_write(struct file *f, const char __user *buf,
252 size_t size, loff_t *ppos)
254 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
257 if (LPROCFS_ENTRY_AND_CHECK(dp))
260 rc = dp->write_proc(f, buf, size, dp->data);
265 static struct file_operations lprocfs_generic_fops = {
266 .owner = THIS_MODULE,
267 .read = lprocfs_fops_read,
268 .write = lprocfs_fops_write,
271 int lprocfs_evict_client_open(struct inode *inode, struct file *f)
273 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
274 struct obd_device *obd = dp->data;
276 cfs_atomic_inc(&obd->obd_evict_inprogress);
281 int lprocfs_evict_client_release(struct inode *inode, struct file *f)
283 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
284 struct obd_device *obd = dp->data;
286 cfs_atomic_dec(&obd->obd_evict_inprogress);
287 cfs_waitq_signal(&obd->obd_evict_inprogress_waitq);
292 struct file_operations lprocfs_evict_client_fops = {
293 .owner = THIS_MODULE,
294 .read = lprocfs_fops_read,
295 .write = lprocfs_fops_write,
296 .open = lprocfs_evict_client_open,
297 .release = lprocfs_evict_client_release,
299 EXPORT_SYMBOL(lprocfs_evict_client_fops);
304 * \param root [in] The parent proc entry on which new entry will be added.
305 * \param list [in] Array of proc entries to be added.
306 * \param data [in] The argument to be passed when entries read/write routines
307 * are called through /proc file.
309 * \retval 0 on success
312 int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list,
317 if (root == NULL || list == NULL)
320 LPROCFS_WRITE_ENTRY();
321 while (list->name != NULL) {
322 struct proc_dir_entry *cur_root, *proc;
323 char *pathcopy, *cur, *next, pathbuf[64];
324 int pathsize = strlen(list->name) + 1;
329 /* need copy of path for strsep */
330 if (strlen(list->name) > sizeof(pathbuf) - 1) {
331 OBD_ALLOC(pathcopy, pathsize);
332 if (pathcopy == NULL)
333 GOTO(out, rc = -ENOMEM);
339 strcpy(pathcopy, list->name);
341 while (cur_root != NULL && (cur = strsep(&next, "/"))) {
342 if (*cur =='\0') /* skip double/trailing "/" */
345 proc = __lprocfs_srch(cur_root, cur);
346 CDEBUG(D_OTHER, "cur_root=%s, cur=%s, next=%s, (%s)\n",
347 cur_root->name, cur, next,
348 (proc ? "exists" : "new"));
350 cur_root = (proc ? proc :
351 proc_mkdir(cur, cur_root));
352 } else if (proc == NULL) {
354 if (list->proc_mode != 0000) {
355 mode = list->proc_mode;
359 if (list->write_fptr)
362 proc = create_proc_entry(cur, mode, cur_root);
366 if (pathcopy != pathbuf)
367 OBD_FREE(pathcopy, pathsize);
369 if (cur_root == NULL || proc == NULL) {
370 CERROR("LprocFS: No memory to create /proc entry %s",
372 GOTO(out, rc = -ENOMEM);
376 proc->proc_fops = list->fops;
378 proc->proc_fops = &lprocfs_generic_fops;
379 proc->read_proc = list->read_fptr;
380 proc->write_proc = list->write_fptr;
381 proc->data = (list->data ? list->data : data);
385 LPROCFS_WRITE_EXIT();
388 EXPORT_SYMBOL(lprocfs_add_vars);
390 void lprocfs_remove_nolock(struct proc_dir_entry **rooth)
392 struct proc_dir_entry *root = *rooth;
393 struct proc_dir_entry *temp = root;
394 struct proc_dir_entry *rm_entry;
395 struct proc_dir_entry *parent;
401 parent = root->parent;
402 LASSERT(parent != NULL);
405 while (temp->subdir != NULL)
411 /* Memory corruption once caused this to fail, and
412 without this LASSERT we would loop here forever. */
413 LASSERTF(strlen(rm_entry->name) == rm_entry->namelen,
414 "0x%p %s/%s len %d\n", rm_entry, temp->name,
415 rm_entry->name, (int)strlen(rm_entry->name));
417 remove_proc_entry(rm_entry->name, temp);
423 void lprocfs_remove(struct proc_dir_entry **rooth)
425 LPROCFS_WRITE_ENTRY(); /* search vs remove race */
426 lprocfs_remove_nolock(rooth);
427 LPROCFS_WRITE_EXIT();
429 EXPORT_SYMBOL(lprocfs_remove);
431 void lprocfs_remove_proc_entry(const char *name, struct proc_dir_entry *parent)
433 LASSERT(parent != NULL);
434 remove_proc_entry(name, parent);
436 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
438 void lprocfs_try_remove_proc_entry(const char *name,
439 struct proc_dir_entry *parent)
441 struct proc_dir_entry *t = NULL;
442 struct proc_dir_entry **p;
445 LASSERT(parent != NULL);
448 LPROCFS_WRITE_ENTRY();
450 /* lookup target name */
451 for (p = &parent->subdir; *p; p = &(*p)->next) {
452 if ((*p)->namelen != len)
454 if (memcmp(name, (*p)->name, len))
461 /* verify it's empty: do not count "num_refs" */
462 for (p = &t->subdir; *p; p = &(*p)->next) {
463 if ((*p)->namelen != strlen("num_refs")) {
467 if (memcmp("num_refs", (*p)->name,
468 strlen("num_refs"))) {
476 lprocfs_remove_nolock(&t);
478 LPROCFS_WRITE_EXIT();
482 EXPORT_SYMBOL(lprocfs_try_remove_proc_entry);
484 struct proc_dir_entry *lprocfs_register(const char *name,
485 struct proc_dir_entry *parent,
486 struct lprocfs_vars *list, void *data)
488 struct proc_dir_entry *newchild;
490 newchild = lprocfs_srch(parent, name);
491 if (newchild != NULL) {
492 CERROR(" Lproc: Attempting to register %s more than once \n",
494 return ERR_PTR(-EALREADY);
497 newchild = proc_mkdir(name, parent);
498 if (newchild != NULL && list != NULL) {
499 int rc = lprocfs_add_vars(newchild, list, data);
501 lprocfs_remove(&newchild);
507 EXPORT_SYMBOL(lprocfs_register);
509 /* Generic callbacks */
510 int lprocfs_rd_uint(char *page, char **start, off_t off,
511 int count, int *eof, void *data)
513 unsigned int *temp = data;
514 return snprintf(page, count, "%u\n", *temp);
516 EXPORT_SYMBOL(lprocfs_rd_uint);
518 int lprocfs_wr_uint(struct file *file, const char *buffer,
519 unsigned long count, void *data)
522 char dummy[MAX_STRING_SIZE + 1], *end;
525 dummy[MAX_STRING_SIZE] = '\0';
526 if (cfs_copy_from_user(dummy, buffer, MAX_STRING_SIZE))
529 tmp = simple_strtoul(dummy, &end, 0);
533 *p = (unsigned int)tmp;
536 EXPORT_SYMBOL(lprocfs_wr_uint);
538 int lprocfs_rd_u64(char *page, char **start, off_t off,
539 int count, int *eof, void *data)
541 LASSERT(data != NULL);
543 return snprintf(page, count, LPU64"\n", *(__u64 *)data);
545 EXPORT_SYMBOL(lprocfs_rd_u64);
547 int lprocfs_rd_atomic(char *page, char **start, off_t off,
548 int count, int *eof, void *data)
550 cfs_atomic_t *atom = data;
551 LASSERT(atom != NULL);
553 return snprintf(page, count, "%d\n", cfs_atomic_read(atom));
555 EXPORT_SYMBOL(lprocfs_rd_atomic);
557 int lprocfs_wr_atomic(struct file *file, const char *buffer,
558 unsigned long count, void *data)
560 cfs_atomic_t *atm = data;
564 rc = lprocfs_write_helper(buffer, count, &val);
571 cfs_atomic_set(atm, val);
574 EXPORT_SYMBOL(lprocfs_wr_atomic);
576 int lprocfs_rd_uuid(char *page, char **start, off_t off, int count,
577 int *eof, void *data)
579 struct obd_device *obd = data;
581 LASSERT(obd != NULL);
583 return snprintf(page, count, "%s\n", obd->obd_uuid.uuid);
585 EXPORT_SYMBOL(lprocfs_rd_uuid);
587 int lprocfs_rd_name(char *page, char **start, off_t off, int count,
588 int *eof, void *data)
590 struct obd_device *dev = data;
592 LASSERT(dev != NULL);
593 LASSERT(dev->obd_name != NULL);
595 return snprintf(page, count, "%s\n", dev->obd_name);
597 EXPORT_SYMBOL(lprocfs_rd_name);
599 int lprocfs_rd_blksize(char *page, char **start, off_t off, int count,
600 int *eof, void *data)
602 struct obd_device *obd = data;
603 struct obd_statfs osfs;
604 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
605 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
609 rc = snprintf(page, count, "%u\n", osfs.os_bsize);
613 EXPORT_SYMBOL(lprocfs_rd_blksize);
615 int lprocfs_osd_rd_blksize(char *page, char **start, off_t off,
616 int count, int *eof, void *data)
618 struct dt_device *dt = data;
619 struct obd_statfs osfs;
620 int rc = dt_statfs(NULL, dt, &osfs);
623 rc = snprintf(page, count, "%d\n",
624 (unsigned) osfs.os_bsize);
628 EXPORT_SYMBOL(lprocfs_osd_rd_blksize);
630 int lprocfs_rd_kbytestotal(char *page, char **start, off_t off, int count,
631 int *eof, void *data)
633 struct obd_device *obd = data;
634 struct obd_statfs osfs;
635 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
636 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
639 __u32 blk_size = osfs.os_bsize >> 10;
640 __u64 result = osfs.os_blocks;
642 while (blk_size >>= 1)
646 rc = snprintf(page, count, LPU64"\n", result);
650 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
652 int lprocfs_osd_rd_kbytestotal(char *page, char **start, off_t off,
653 int count, int *eof, void *data)
655 struct dt_device *dt = data;
656 struct obd_statfs osfs;
657 int rc = dt_statfs(NULL, dt, &osfs);
659 __u32 blk_size = osfs.os_bsize >> 10;
660 __u64 result = osfs.os_blocks;
662 while (blk_size >>= 1)
666 rc = snprintf(page, count, LPU64"\n", result);
670 EXPORT_SYMBOL(lprocfs_osd_rd_kbytestotal);
672 int lprocfs_rd_kbytesfree(char *page, char **start, off_t off, int count,
673 int *eof, void *data)
675 struct obd_device *obd = data;
676 struct obd_statfs osfs;
677 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
678 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
681 __u32 blk_size = osfs.os_bsize >> 10;
682 __u64 result = osfs.os_bfree;
684 while (blk_size >>= 1)
688 rc = snprintf(page, count, LPU64"\n", result);
692 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
694 int lprocfs_osd_rd_kbytesfree(char *page, char **start, off_t off,
695 int count, int *eof, void *data)
697 struct dt_device *dt = data;
698 struct obd_statfs osfs;
699 int rc = dt_statfs(NULL, dt, &osfs);
701 __u32 blk_size = osfs.os_bsize >> 10;
702 __u64 result = osfs.os_bfree;
704 while (blk_size >>= 1)
708 rc = snprintf(page, count, LPU64"\n", result);
712 EXPORT_SYMBOL(lprocfs_osd_rd_kbytesfree);
714 int lprocfs_rd_kbytesavail(char *page, char **start, off_t off, int count,
715 int *eof, void *data)
717 struct obd_device *obd = data;
718 struct obd_statfs osfs;
719 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
720 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
723 __u32 blk_size = osfs.os_bsize >> 10;
724 __u64 result = osfs.os_bavail;
726 while (blk_size >>= 1)
730 rc = snprintf(page, count, LPU64"\n", result);
734 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
736 int lprocfs_osd_rd_kbytesavail(char *page, char **start, off_t off,
737 int count, int *eof, void *data)
739 struct dt_device *dt = data;
740 struct obd_statfs osfs;
741 int rc = dt_statfs(NULL, dt, &osfs);
743 __u32 blk_size = osfs.os_bsize >> 10;
744 __u64 result = osfs.os_bavail;
746 while (blk_size >>= 1)
750 rc = snprintf(page, count, LPU64"\n", result);
754 EXPORT_SYMBOL(lprocfs_osd_rd_kbytesavail);
756 int lprocfs_rd_filestotal(char *page, char **start, off_t off, int count,
757 int *eof, void *data)
759 struct obd_device *obd = data;
760 struct obd_statfs osfs;
761 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
762 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
766 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
771 EXPORT_SYMBOL(lprocfs_rd_filestotal);
773 int lprocfs_osd_rd_filestotal(char *page, char **start, off_t off,
774 int count, int *eof, void *data)
776 struct dt_device *dt = data;
777 struct obd_statfs osfs;
778 int rc = dt_statfs(NULL, dt, &osfs);
781 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
786 EXPORT_SYMBOL(lprocfs_osd_rd_filestotal);
788 int lprocfs_rd_filesfree(char *page, char **start, off_t off, int count,
789 int *eof, void *data)
791 struct obd_device *obd = data;
792 struct obd_statfs osfs;
793 int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
794 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
798 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
802 EXPORT_SYMBOL(lprocfs_rd_filesfree);
804 int lprocfs_osd_rd_filesfree(char *page, char **start, off_t off,
805 int count, int *eof, void *data)
807 struct dt_device *dt = data;
808 struct obd_statfs osfs;
809 int rc = dt_statfs(NULL, dt, &osfs);
812 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
816 EXPORT_SYMBOL(lprocfs_osd_rd_filesfree);
818 int lprocfs_rd_server_uuid(char *page, char **start, off_t off, int count,
819 int *eof, void *data)
821 struct obd_device *obd = data;
822 struct obd_import *imp;
823 char *imp_state_name = NULL;
826 LASSERT(obd != NULL);
827 LPROCFS_CLIMP_CHECK(obd);
828 imp = obd->u.cli.cl_import;
829 imp_state_name = ptlrpc_import_state_name(imp->imp_state);
831 rc = snprintf(page, count, "%s\t%s%s\n",
832 obd2cli_tgt(obd), imp_state_name,
833 imp->imp_deactive ? "\tDEACTIVATED" : "");
835 LPROCFS_CLIMP_EXIT(obd);
838 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
840 int lprocfs_rd_conn_uuid(char *page, char **start, off_t off, int count,
841 int *eof, void *data)
843 struct obd_device *obd = data;
844 struct ptlrpc_connection *conn;
847 LASSERT(obd != NULL);
849 LPROCFS_CLIMP_CHECK(obd);
850 conn = obd->u.cli.cl_import->imp_connection;
852 if (conn && obd->u.cli.cl_import) {
853 rc = snprintf(page, count, "%s\n",
854 conn->c_remote_uuid.uuid);
856 rc = snprintf(page, count, "%s\n", "<none>");
859 LPROCFS_CLIMP_EXIT(obd);
862 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
864 /** add up per-cpu counters */
865 void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
866 struct lprocfs_counter *cnt)
868 unsigned int num_entry;
869 struct lprocfs_counter *percpu_cntr;
870 struct lprocfs_counter_header *cntr_header;
872 unsigned long flags = 0;
874 memset(cnt, 0, sizeof(*cnt));
877 /* set count to 1 to avoid divide-by-zero errs in callers */
882 cnt->lc_min = LC_MIN_INIT;
884 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
886 for (i = 0; i < num_entry; i++) {
887 if (stats->ls_percpu[i] == NULL)
889 cntr_header = &stats->ls_cnt_header[idx];
890 percpu_cntr = lprocfs_stats_counter_get(stats, i, idx);
892 cnt->lc_count += percpu_cntr->lc_count;
893 cnt->lc_sum += percpu_cntr->lc_sum;
894 if (percpu_cntr->lc_min < cnt->lc_min)
895 cnt->lc_min = percpu_cntr->lc_min;
896 if (percpu_cntr->lc_max > cnt->lc_max)
897 cnt->lc_max = percpu_cntr->lc_max;
898 cnt->lc_sumsquare += percpu_cntr->lc_sumsquare;
901 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
903 EXPORT_SYMBOL(lprocfs_stats_collect);
906 * Append a space separated list of current set flags to str.
908 #define flag2str(flag) \
909 if (imp->imp_##flag && max - len > 0) \
910 len += snprintf(str + len, max - len, "%s" #flag, len ? ", " : "");
911 static int obd_import_flags2str(struct obd_import *imp, char *str, int max)
915 if (imp->imp_obd->obd_no_recov)
916 len += snprintf(str, max - len, "no_recov");
920 flag2str(replayable);
926 static const char *obd_connect_names[] = {
940 "join_file(obsolete)",
944 "remote_client_by_force",
953 "mds_mds_connection",
956 "alt_checksum_algorithm",
982 int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
987 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
989 ret += snprintf(page + ret, count - ret, "%s%s",
990 ret ? sep : "", obd_connect_names[i]);
992 if (flags & ~(mask - 1))
993 ret += snprintf(page + ret, count - ret,
994 "%sunknown flags "LPX64,
995 ret ? sep : "", flags & ~(mask - 1));
998 EXPORT_SYMBOL(obd_connect_flags2str);
1000 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
1001 int *eof, void *data)
1003 struct lprocfs_counter ret;
1004 struct lprocfs_counter_header *header;
1005 struct obd_device *obd = (struct obd_device *)data;
1006 struct obd_import *imp;
1007 struct obd_import_conn *conn;
1013 LASSERT(obd != NULL);
1014 LPROCFS_CLIMP_CHECK(obd);
1015 imp = obd->u.cli.cl_import;
1018 i = snprintf(page, count,
1024 " connect_flags: [",
1027 ptlrpc_import_state_name(imp->imp_state),
1028 imp->imp_connect_data.ocd_instance);
1029 i += obd_connect_flags2str(page + i, count - i,
1030 imp->imp_connect_data.ocd_connect_flags,
1032 i += snprintf(page + i, count - i,
1034 " import_flags: [");
1035 i += obd_import_flags2str(imp, page + i, count - i);
1037 i += snprintf(page + i, count - i,
1040 " failover_nids: [");
1041 spin_lock(&imp->imp_lock);
1043 cfs_list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
1044 i += snprintf(page + i, count - i, "%s%s", j ? ", " : "",
1045 libcfs_nid2str(conn->oic_conn->c_peer.nid));
1048 i += snprintf(page + i, count - i,
1050 " current_connection: %s\n"
1051 " connection_attempts: %u\n"
1053 " in-progress_invalidations: %u\n",
1054 imp->imp_connection == NULL ? "<none>" :
1055 libcfs_nid2str(imp->imp_connection->c_peer.nid),
1057 imp->imp_generation,
1058 cfs_atomic_read(&imp->imp_inval_count));
1059 spin_unlock(&imp->imp_lock);
1061 if (obd->obd_svc_stats == NULL)
1064 header = &obd->obd_svc_stats->ls_cnt_header[PTLRPC_REQWAIT_CNTR];
1065 lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
1066 if (ret.lc_count != 0) {
1067 /* first argument to do_div MUST be __u64 */
1068 __u64 sum = ret.lc_sum;
1069 do_div(sum, ret.lc_count);
1073 i += snprintf(page + i, count - i,
1076 " unregistering: %u\n"
1078 " avg_waittime: "LPU64" %s\n",
1079 cfs_atomic_read(&imp->imp_inflight),
1080 cfs_atomic_read(&imp->imp_unregistering),
1081 cfs_atomic_read(&imp->imp_timeouts),
1082 ret.lc_sum, header->lc_units);
1085 for(j = 0; j < IMP_AT_MAX_PORTALS; j++) {
1086 if (imp->imp_at.iat_portal[j] == 0)
1088 k = max_t(unsigned int, k,
1089 at_get(&imp->imp_at.iat_service_estimate[j]));
1091 i += snprintf(page + i, count - i,
1092 " service_estimates:\n"
1093 " services: %u sec\n"
1094 " network: %u sec\n",
1096 at_get(&imp->imp_at.iat_net_latency));
1098 i += snprintf(page + i, count - i,
1100 " last_replay: "LPU64"\n"
1101 " peer_committed: "LPU64"\n"
1102 " last_checked: "LPU64"\n",
1103 imp->imp_last_replay_transno,
1104 imp->imp_peer_committed_transno,
1105 imp->imp_last_transno_checked);
1107 /* avg data rates */
1108 for (rw = 0; rw <= 1; rw++) {
1109 lprocfs_stats_collect(obd->obd_svc_stats,
1110 PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
1112 if (ret.lc_sum > 0 && ret.lc_count > 0) {
1113 /* first argument to do_div MUST be __u64 */
1114 __u64 sum = ret.lc_sum;
1115 do_div(sum, ret.lc_count);
1117 i += snprintf(page + i, count - i,
1118 " %s_data_averages:\n"
1119 " bytes_per_rpc: "LPU64"\n",
1120 rw ? "write" : "read",
1123 k = (int)ret.lc_sum;
1124 j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
1125 header = &obd->obd_svc_stats->ls_cnt_header[j];
1126 lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
1127 if (ret.lc_sum > 0 && ret.lc_count != 0) {
1128 /* first argument to do_div MUST be __u64 */
1129 __u64 sum = ret.lc_sum;
1130 do_div(sum, ret.lc_count);
1132 i += snprintf(page + i, count - i,
1133 " %s_per_rpc: "LPU64"\n",
1134 header->lc_units, ret.lc_sum);
1135 j = (int)ret.lc_sum;
1137 i += snprintf(page + i, count - i,
1138 " MB_per_sec: %u.%.02u\n",
1139 k / j, (100 * k / j) % 100);
1144 LPROCFS_CLIMP_EXIT(obd);
1147 EXPORT_SYMBOL(lprocfs_rd_import);
1149 int lprocfs_rd_state(char *page, char **start, off_t off, int count,
1150 int *eof, void *data)
1152 struct obd_device *obd = (struct obd_device *)data;
1153 struct obd_import *imp;
1156 LASSERT(obd != NULL);
1157 LPROCFS_CLIMP_CHECK(obd);
1158 imp = obd->u.cli.cl_import;
1161 i = snprintf(page, count, "current_state: %s\n",
1162 ptlrpc_import_state_name(imp->imp_state));
1163 i += snprintf(page + i, count - i,
1164 "state_history:\n");
1165 k = imp->imp_state_hist_idx;
1166 for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
1167 struct import_state_hist *ish =
1168 &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
1169 if (ish->ish_state == 0)
1171 i += snprintf(page + i, count - i, " - ["CFS_TIME_T", %s]\n",
1173 ptlrpc_import_state_name(ish->ish_state));
1176 LPROCFS_CLIMP_EXIT(obd);
1179 EXPORT_SYMBOL(lprocfs_rd_state);
1181 int lprocfs_at_hist_helper(char *page, int count, int rc,
1182 struct adaptive_timeout *at)
1185 for (i = 0; i < AT_BINS; i++)
1186 rc += snprintf(page + rc, count - rc, "%3u ", at->at_hist[i]);
1187 rc += snprintf(page + rc, count - rc, "\n");
1190 EXPORT_SYMBOL(lprocfs_at_hist_helper);
1192 /* See also ptlrpc_lprocfs_rd_timeouts */
1193 int lprocfs_rd_timeouts(char *page, char **start, off_t off, int count,
1194 int *eof, void *data)
1196 struct obd_device *obd = (struct obd_device *)data;
1197 struct obd_import *imp;
1198 unsigned int cur, worst;
1203 LASSERT(obd != NULL);
1204 LPROCFS_CLIMP_CHECK(obd);
1205 imp = obd->u.cli.cl_import;
1208 now = cfs_time_current_sec();
1210 /* Some network health info for kicks */
1211 s2dhms(&ts, now - imp->imp_last_reply_time);
1212 rc += snprintf(page + rc, count - rc,
1213 "%-10s : %ld, "DHMS_FMT" ago\n",
1214 "last reply", imp->imp_last_reply_time, DHMS_VARS(&ts));
1216 cur = at_get(&imp->imp_at.iat_net_latency);
1217 worst = imp->imp_at.iat_net_latency.at_worst_ever;
1218 worstt = imp->imp_at.iat_net_latency.at_worst_time;
1219 s2dhms(&ts, now - worstt);
1220 rc += snprintf(page + rc, count - rc,
1221 "%-10s : cur %3u worst %3u (at %ld, "DHMS_FMT" ago) ",
1222 "network", cur, worst, worstt, DHMS_VARS(&ts));
1223 rc = lprocfs_at_hist_helper(page, count, rc,
1224 &imp->imp_at.iat_net_latency);
1226 for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
1227 if (imp->imp_at.iat_portal[i] == 0)
1229 cur = at_get(&imp->imp_at.iat_service_estimate[i]);
1230 worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
1231 worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
1232 s2dhms(&ts, now - worstt);
1233 rc += snprintf(page + rc, count - rc,
1234 "portal %-2d : cur %3u worst %3u (at %ld, "
1235 DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
1236 cur, worst, worstt, DHMS_VARS(&ts));
1237 rc = lprocfs_at_hist_helper(page, count, rc,
1238 &imp->imp_at.iat_service_estimate[i]);
1241 LPROCFS_CLIMP_EXIT(obd);
1244 EXPORT_SYMBOL(lprocfs_rd_timeouts);
1246 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
1247 int count, int *eof, void *data)
1249 struct obd_device *obd = data;
1253 LPROCFS_CLIMP_CHECK(obd);
1254 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
1255 ret = snprintf(page, count, "flags="LPX64"\n", flags);
1256 ret += obd_connect_flags2str(page + ret, count - ret, flags, "\n");
1257 ret += snprintf(page + ret, count - ret, "\n");
1258 LPROCFS_CLIMP_EXIT(obd);
1261 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
1263 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
1264 int *eof, void *data)
1266 struct obd_device *obd = data;
1268 LASSERT(obd != NULL);
1270 return snprintf(page, count, "%u\n", obd->obd_num_exports);
1272 EXPORT_SYMBOL(lprocfs_rd_num_exports);
1274 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
1275 int *eof, void *data)
1277 struct obd_type *class = (struct obd_type*) data;
1279 LASSERT(class != NULL);
1281 return snprintf(page, count, "%d\n", class->typ_refcnt);
1283 EXPORT_SYMBOL(lprocfs_rd_numrefs);
1285 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
1289 LASSERT(obd != NULL);
1290 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
1291 LASSERT(obd->obd_type->typ_procroot != NULL);
1293 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
1294 obd->obd_type->typ_procroot,
1296 if (IS_ERR(obd->obd_proc_entry)) {
1297 rc = PTR_ERR(obd->obd_proc_entry);
1298 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
1299 obd->obd_proc_entry = NULL;
1303 EXPORT_SYMBOL(lprocfs_obd_setup);
1305 int lprocfs_obd_cleanup(struct obd_device *obd)
1309 if (obd->obd_proc_exports_entry) {
1310 /* Should be no exports left */
1311 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
1312 lprocfs_remove(&obd->obd_proc_exports_entry);
1313 obd->obd_proc_exports_entry = NULL;
1315 if (obd->obd_proc_entry) {
1316 lprocfs_remove(&obd->obd_proc_entry);
1317 obd->obd_proc_entry = NULL;
1321 EXPORT_SYMBOL(lprocfs_obd_cleanup);
1323 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
1325 CDEBUG(D_CONFIG, "stat %p - data %p/%p\n", client_stat,
1326 client_stat->nid_proc, client_stat->nid_stats);
1328 LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
1329 "nid %s:count %d\n", libcfs_nid2str(client_stat->nid),
1330 atomic_read(&client_stat->nid_exp_ref_count));
1332 if (client_stat->nid_proc)
1333 lprocfs_remove(&client_stat->nid_proc);
1335 if (client_stat->nid_stats)
1336 lprocfs_free_stats(&client_stat->nid_stats);
1338 if (client_stat->nid_ldlm_stats)
1339 lprocfs_free_stats(&client_stat->nid_ldlm_stats);
1341 OBD_FREE_PTR(client_stat);
1346 void lprocfs_free_per_client_stats(struct obd_device *obd)
1348 cfs_hash_t *hash = obd->obd_nid_stats_hash;
1349 struct nid_stat *stat;
1352 /* we need extra list - because hash_exit called to early */
1353 /* not need locking because all clients is died */
1354 while (!cfs_list_empty(&obd->obd_nid_stats)) {
1355 stat = cfs_list_entry(obd->obd_nid_stats.next,
1356 struct nid_stat, nid_list);
1357 cfs_list_del_init(&stat->nid_list);
1358 cfs_hash_del(hash, &stat->nid, &stat->nid_hash);
1359 lprocfs_free_client_stats(stat);
1363 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
1365 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
1366 enum lprocfs_stats_flags flags)
1368 struct lprocfs_stats *stats;
1369 unsigned int num_entry;
1370 unsigned int percpusize = 0;
1376 if (lprocfs_no_percpu_stats != 0)
1377 flags |= LPROCFS_STATS_FLAG_NOPERCPU;
1379 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1382 num_entry = cfs_num_possible_cpus();
1384 /* alloc percpu pointers for all possible cpu slots */
1385 LIBCFS_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1389 stats->ls_num = num;
1390 stats->ls_flags = flags;
1391 spin_lock_init(&stats->ls_lock);
1393 /* alloc num of counter headers */
1394 LIBCFS_ALLOC(stats->ls_cnt_header,
1395 stats->ls_num * sizeof(struct lprocfs_counter_header));
1396 if (stats->ls_cnt_header == NULL)
1399 if ((flags & LPROCFS_STATS_FLAG_NOPERCPU) != 0) {
1400 /* contains only one set counters */
1401 percpusize = lprocfs_stats_counter_size(stats);
1402 LIBCFS_ALLOC_ATOMIC(stats->ls_percpu[0], percpusize);
1403 if (stats->ls_percpu[0] == NULL)
1405 stats->ls_biggest_alloc_num = 1;
1406 } else if ((flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0) {
1407 /* alloc all percpu data, currently only obd_memory use this */
1408 for (i = 0; i < num_entry; ++i)
1409 if (lprocfs_stats_alloc_one(stats, i) < 0)
1416 lprocfs_free_stats(&stats);
1419 EXPORT_SYMBOL(lprocfs_alloc_stats);
1421 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1423 struct lprocfs_stats *stats = *statsh;
1424 unsigned int num_entry;
1425 unsigned int percpusize;
1428 if (stats == NULL || stats->ls_num == 0)
1432 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1435 num_entry = cfs_num_possible_cpus();
1437 percpusize = lprocfs_stats_counter_size(stats);
1438 for (i = 0; i < num_entry; i++)
1439 if (stats->ls_percpu[i] != NULL)
1440 LIBCFS_FREE(stats->ls_percpu[i], percpusize);
1441 if (stats->ls_cnt_header != NULL)
1442 LIBCFS_FREE(stats->ls_cnt_header, stats->ls_num *
1443 sizeof(struct lprocfs_counter_header));
1444 LIBCFS_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1446 EXPORT_SYMBOL(lprocfs_free_stats);
1448 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1450 struct lprocfs_counter *percpu_cntr;
1451 struct lprocfs_counter_header *header;
1454 unsigned int num_entry;
1455 unsigned long flags = 0;
1457 num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1459 for (i = 0; i < num_entry; i++) {
1460 if (stats->ls_percpu[i] == NULL)
1462 for (j = 0; j < stats->ls_num; j++) {
1463 header = &stats->ls_cnt_header[j];
1464 percpu_cntr = lprocfs_stats_counter_get(stats, i, j);
1465 percpu_cntr->lc_count = 0;
1466 percpu_cntr->lc_min = LC_MIN_INIT;
1467 percpu_cntr->lc_max = 0;
1468 percpu_cntr->lc_sumsquare = 0;
1469 percpu_cntr->lc_sum = 0;
1470 if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
1471 percpu_cntr->lc_sum_irq = 0;
1475 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1477 EXPORT_SYMBOL(lprocfs_clear_stats);
1479 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
1480 size_t len, loff_t *off)
1482 struct seq_file *seq = file->private_data;
1483 struct lprocfs_stats *stats = seq->private;
1485 lprocfs_clear_stats(stats);
1490 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1492 struct lprocfs_stats *stats = p->private;
1493 /* return 1st cpu location */
1494 return (*pos >= stats->ls_num) ? NULL :
1495 lprocfs_stats_counter_get(stats, 0, *pos);
1498 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1502 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1504 struct lprocfs_stats *stats = p->private;
1506 return (*pos >= stats->ls_num) ? NULL :
1507 lprocfs_stats_counter_get(stats, 0, *pos);
1510 /* seq file export of one lprocfs counter */
1511 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1513 struct lprocfs_stats *stats = p->private;
1514 struct lprocfs_counter *cntr = v;
1515 struct lprocfs_counter ret;
1516 struct lprocfs_counter_header *header;
1521 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
1523 cfs_gettimeofday(&now);
1524 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
1525 "snapshot_time", now.tv_sec, now.tv_usec);
1529 entry_size = sizeof(*cntr);
1530 if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
1531 entry_size += sizeof(__s64);
1532 idx = ((void *)cntr - (void *)&(stats->ls_percpu[0])->lp_cntr[0]) /
1535 header = &stats->ls_cnt_header[idx];
1536 lprocfs_stats_collect(stats, idx, &ret);
1538 if (ret.lc_count == 0)
1541 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", header->lc_name,
1542 ret.lc_count, header->lc_units);
1547 if ((header->lc_config & LPROCFS_CNTR_AVGMINMAX) &&
1548 (ret.lc_count > 0)) {
1549 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
1550 ret.lc_min, ret.lc_max, ret.lc_sum);
1553 if (header->lc_config & LPROCFS_CNTR_STDDEV)
1554 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
1558 rc = seq_printf(p, "\n");
1560 return (rc < 0) ? rc : 0;
1563 struct seq_operations lprocfs_stats_seq_sops = {
1564 start: lprocfs_stats_seq_start,
1565 stop: lprocfs_stats_seq_stop,
1566 next: lprocfs_stats_seq_next,
1567 show: lprocfs_stats_seq_show,
1570 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1572 struct proc_dir_entry *dp = PDE(inode);
1573 struct seq_file *seq;
1576 if (LPROCFS_ENTRY_AND_CHECK(dp))
1579 rc = seq_open(file, &lprocfs_stats_seq_sops);
1584 seq = file->private_data;
1585 seq->private = dp->data;
1589 struct file_operations lprocfs_stats_seq_fops = {
1590 .owner = THIS_MODULE,
1591 .open = lprocfs_stats_seq_open,
1593 .write = lprocfs_stats_seq_write,
1594 .llseek = seq_lseek,
1595 .release = lprocfs_seq_release,
1598 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
1599 struct lprocfs_stats *stats)
1601 struct proc_dir_entry *entry;
1602 LASSERT(root != NULL);
1604 LPROCFS_WRITE_ENTRY();
1605 entry = create_proc_entry(name, 0644, root);
1607 entry->proc_fops = &lprocfs_stats_seq_fops;
1608 entry->data = stats;
1611 LPROCFS_WRITE_EXIT();
1618 EXPORT_SYMBOL(lprocfs_register_stats);
1620 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1621 unsigned conf, const char *name, const char *units)
1623 struct lprocfs_counter_header *header;
1624 struct lprocfs_counter *percpu_cntr;
1625 unsigned long flags = 0;
1627 unsigned int num_cpu;
1629 LASSERT(stats != NULL);
1631 header = &stats->ls_cnt_header[index];
1632 LASSERTF(header != NULL, "Failed to allocate stats header:[%d]%s/%s\n",
1633 index, name, units);
1635 header->lc_config = conf;
1636 header->lc_name = name;
1637 header->lc_units = units;
1639 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1640 for (i = 0; i < num_cpu; ++i) {
1641 if (stats->ls_percpu[i] == NULL)
1643 percpu_cntr = lprocfs_stats_counter_get(stats, i, index);
1644 percpu_cntr->lc_count = 0;
1645 percpu_cntr->lc_min = LC_MIN_INIT;
1646 percpu_cntr->lc_max = 0;
1647 percpu_cntr->lc_sumsquare = 0;
1648 percpu_cntr->lc_sum = 0;
1649 if ((stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
1650 percpu_cntr->lc_sum_irq = 0;
1652 lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1654 EXPORT_SYMBOL(lprocfs_counter_init);
1656 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1658 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1659 LASSERT(coffset < stats->ls_num); \
1660 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1663 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1665 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1666 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1667 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1668 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1669 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1670 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1671 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1672 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1673 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1674 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1675 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1676 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1677 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1678 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1679 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1680 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1681 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1682 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1683 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1684 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1685 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1686 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1687 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1688 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1689 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1690 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
1691 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1692 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1693 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1694 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1695 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1696 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1697 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1698 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1699 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1700 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1701 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1702 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1703 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1704 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1705 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1706 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1707 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1708 LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
1709 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1710 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1711 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1712 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1713 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1714 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1715 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1716 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1717 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1718 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1719 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1720 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1721 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1722 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
1723 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1724 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1725 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1726 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
1727 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
1728 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
1729 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
1730 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
1731 LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
1733 EXPORT_SYMBOL(lprocfs_init_ops_stats);
1735 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1737 struct lprocfs_stats *stats;
1738 unsigned int num_stats;
1741 LASSERT(obd->obd_stats == NULL);
1742 LASSERT(obd->obd_proc_entry != NULL);
1743 LASSERT(obd->obd_cntr_base == 0);
1745 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1746 num_private_stats - 1 /* o_owner */;
1747 stats = lprocfs_alloc_stats(num_stats, 0);
1751 lprocfs_init_ops_stats(num_private_stats, stats);
1753 for (i = num_private_stats; i < num_stats; i++) {
1754 /* If this LBUGs, it is likely that an obd
1755 * operation was added to struct obd_ops in
1756 * <obd.h>, and that the corresponding line item
1757 * LPROCFS_OBD_OP_INIT(.., .., opname)
1758 * is missing from the list above. */
1759 LASSERTF(stats->ls_cnt_header[i].lc_name != NULL,
1760 "Missing obd_stat initializer obd_op "
1761 "operation at offset %d.\n", i - num_private_stats);
1763 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1765 lprocfs_free_stats(&stats);
1767 obd->obd_stats = stats;
1768 obd->obd_cntr_base = num_private_stats;
1772 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
1774 void lprocfs_free_obd_stats(struct obd_device *obd)
1777 lprocfs_free_stats(&obd->obd_stats);
1779 EXPORT_SYMBOL(lprocfs_free_obd_stats);
1781 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1783 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1784 LASSERT(coffset < stats->ls_num); \
1785 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1788 void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats)
1790 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1791 LPROCFS_MD_OP_INIT(num_private_stats, stats, null_inode);
1792 LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata);
1793 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1794 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1795 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1796 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1797 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1798 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1799 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1800 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1801 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1802 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1803 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1804 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1805 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1806 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1807 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1808 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1809 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1810 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1811 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1812 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1813 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1814 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1815 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1816 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1817 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1818 LPROCFS_MD_OP_INIT(num_private_stats, stats, unpack_capa);
1819 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1820 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1821 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1823 EXPORT_SYMBOL(lprocfs_init_mps_stats);
1825 int lprocfs_alloc_md_stats(struct obd_device *obd,
1826 unsigned num_private_stats)
1828 struct lprocfs_stats *stats;
1829 unsigned int num_stats;
1832 LASSERT(obd->md_stats == NULL);
1833 LASSERT(obd->obd_proc_entry != NULL);
1834 LASSERT(obd->md_cntr_base == 0);
1836 num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) +
1838 stats = lprocfs_alloc_stats(num_stats, 0);
1842 lprocfs_init_mps_stats(num_private_stats, stats);
1844 for (i = num_private_stats; i < num_stats; i++) {
1845 if (stats->ls_cnt_header[i].lc_name == NULL) {
1846 CERROR("Missing md_stat initializer md_op "
1847 "operation at offset %d. Aborting.\n",
1848 i - num_private_stats);
1852 rc = lprocfs_register_stats(obd->obd_proc_entry, "md_stats", stats);
1854 lprocfs_free_stats(&stats);
1856 obd->md_stats = stats;
1857 obd->md_cntr_base = num_private_stats;
1861 EXPORT_SYMBOL(lprocfs_alloc_md_stats);
1863 void lprocfs_free_md_stats(struct obd_device *obd)
1865 struct lprocfs_stats *stats = obd->md_stats;
1867 if (stats != NULL) {
1868 obd->md_stats = NULL;
1869 obd->md_cntr_base = 0;
1870 lprocfs_free_stats(&stats);
1873 EXPORT_SYMBOL(lprocfs_free_md_stats);
1875 void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
1877 lprocfs_counter_init(ldlm_stats,
1878 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1879 0, "ldlm_enqueue", "reqs");
1880 lprocfs_counter_init(ldlm_stats,
1881 LDLM_CONVERT - LDLM_FIRST_OPC,
1882 0, "ldlm_convert", "reqs");
1883 lprocfs_counter_init(ldlm_stats,
1884 LDLM_CANCEL - LDLM_FIRST_OPC,
1885 0, "ldlm_cancel", "reqs");
1886 lprocfs_counter_init(ldlm_stats,
1887 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1888 0, "ldlm_bl_callback", "reqs");
1889 lprocfs_counter_init(ldlm_stats,
1890 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1891 0, "ldlm_cp_callback", "reqs");
1892 lprocfs_counter_init(ldlm_stats,
1893 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1894 0, "ldlm_gl_callback", "reqs");
1896 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
1898 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1899 int *eof, void *data)
1901 struct obd_export *exp = data;
1902 LASSERT(exp != NULL);
1904 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1907 struct exp_uuid_cb_data {
1915 lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
1916 int count, int *eof, int *len)
1918 cb_data->page = page;
1919 cb_data->count = count;
1924 int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1925 cfs_hlist_node_t *hnode, void *cb_data)
1928 struct obd_export *exp = cfs_hash_object(hs, hnode);
1929 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1931 if (exp->exp_nid_stats)
1932 *data->len += snprintf((data->page + *data->len),
1933 data->count, "%s\n",
1934 obd_uuid2str(&exp->exp_client_uuid));
1938 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1939 int *eof, void *data)
1941 struct nid_stat *stats = (struct nid_stat *)data;
1942 struct exp_uuid_cb_data cb_data;
1943 struct obd_device *obd = stats->nid_obd;
1948 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1949 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1950 lprocfs_exp_print_uuid, &cb_data);
1951 return (*cb_data.len);
1954 int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1955 cfs_hlist_node_t *hnode, void *cb_data)
1958 struct exp_uuid_cb_data *data = cb_data;
1959 struct obd_export *exp = cfs_hash_object(hs, hnode);
1961 if (exp->exp_lock_hash != NULL) {
1963 *data->len += cfs_hash_debug_header(data->page,
1966 *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
1973 int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
1974 int *eof, void *data)
1976 struct nid_stat *stats = (struct nid_stat *)data;
1977 struct exp_uuid_cb_data cb_data;
1978 struct obd_device *obd = stats->nid_obd;
1983 lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
1985 cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
1986 lprocfs_exp_print_hash, &cb_data);
1987 return (*cb_data.len);
1990 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1991 int count, int *eof, void *data)
1994 return snprintf(page, count, "%s\n",
1995 "Write into this file to clear all nid stats and "
1996 "stale nid entries");
1998 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
2000 static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
2002 struct nid_stat *stat = obj;
2005 CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
2006 if (cfs_atomic_read(&stat->nid_exp_ref_count) == 1) {
2007 /* object has only hash references. */
2008 spin_lock(&stat->nid_obd->obd_nid_lock);
2009 cfs_list_move(&stat->nid_list, data);
2010 spin_unlock(&stat->nid_obd->obd_nid_lock);
2013 /* we has reference to object - only clear data*/
2014 if (stat->nid_stats)
2015 lprocfs_clear_stats(stat->nid_stats);
2020 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
2021 unsigned long count, void *data)
2023 struct obd_device *obd = (struct obd_device *)data;
2024 struct nid_stat *client_stat;
2025 CFS_LIST_HEAD(free_list);
2027 cfs_hash_cond_del(obd->obd_nid_stats_hash,
2028 lprocfs_nid_stats_clear_write_cb, &free_list);
2030 while (!cfs_list_empty(&free_list)) {
2031 client_stat = cfs_list_entry(free_list.next, struct nid_stat,
2033 cfs_list_del_init(&client_stat->nid_list);
2034 lprocfs_free_client_stats(client_stat);
2039 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
2041 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
2043 struct nid_stat *new_stat, *old_stat;
2044 struct obd_device *obd = NULL;
2045 cfs_proc_dir_entry_t *entry;
2046 char *buffer = NULL;
2052 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
2053 !exp->exp_obd->obd_nid_stats_hash)
2056 /* not test against zero because eric say:
2057 * You may only test nid against another nid, or LNET_NID_ANY.
2058 * Anything else is nonsense.*/
2059 if (!nid || *nid == LNET_NID_ANY)
2064 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
2066 OBD_ALLOC_PTR(new_stat);
2067 if (new_stat == NULL)
2070 new_stat->nid = *nid;
2071 new_stat->nid_obd = exp->exp_obd;
2072 /* we need set default refcount to 1 to balance obd_disconnect */
2073 cfs_atomic_set(&new_stat->nid_exp_ref_count, 1);
2075 old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
2076 nid, &new_stat->nid_hash);
2077 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
2078 old_stat, libcfs_nid2str(*nid),
2079 cfs_atomic_read(&new_stat->nid_exp_ref_count));
2081 /* We need to release old stats because lprocfs_exp_cleanup() hasn't
2082 * been and will never be called. */
2083 if (exp->exp_nid_stats) {
2084 nidstat_putref(exp->exp_nid_stats);
2085 exp->exp_nid_stats = NULL;
2088 /* Return -EALREADY here so that we know that the /proc
2089 * entry already has been created */
2090 if (old_stat != new_stat) {
2091 exp->exp_nid_stats = old_stat;
2092 GOTO(destroy_new, rc = -EALREADY);
2094 /* not found - create */
2095 OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
2097 GOTO(destroy_new, rc = -ENOMEM);
2099 memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
2100 new_stat->nid_proc = lprocfs_register(buffer,
2101 obd->obd_proc_exports_entry,
2103 OBD_FREE(buffer, LNET_NIDSTR_SIZE);
2105 if (new_stat->nid_proc == NULL) {
2106 CERROR("Error making export directory for nid %s\n",
2107 libcfs_nid2str(*nid));
2108 GOTO(destroy_new_ns, rc = -ENOMEM);
2111 entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
2112 lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
2113 if (IS_ERR(entry)) {
2114 CWARN("Error adding the NID stats file\n");
2115 rc = PTR_ERR(entry);
2116 GOTO(destroy_new_ns, rc);
2119 entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
2120 lprocfs_exp_rd_hash, NULL, new_stat, NULL);
2121 if (IS_ERR(entry)) {
2122 CWARN("Error adding the hash file\n");
2123 rc = PTR_ERR(entry);
2124 GOTO(destroy_new_ns, rc);
2127 exp->exp_nid_stats = new_stat;
2129 /* protect competitive add to list, not need locking on destroy */
2130 spin_lock(&obd->obd_nid_lock);
2131 cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
2132 spin_unlock(&obd->obd_nid_lock);
2137 if (new_stat->nid_proc != NULL)
2138 lprocfs_remove(&new_stat->nid_proc);
2139 cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
2142 nidstat_putref(new_stat);
2143 OBD_FREE_PTR(new_stat);
2146 EXPORT_SYMBOL(lprocfs_exp_setup);
2148 int lprocfs_exp_cleanup(struct obd_export *exp)
2150 struct nid_stat *stat = exp->exp_nid_stats;
2152 if(!stat || !exp->exp_obd)
2155 nidstat_putref(exp->exp_nid_stats);
2156 exp->exp_nid_stats = NULL;
2160 EXPORT_SYMBOL(lprocfs_exp_cleanup);
2162 int lprocfs_write_helper(const char *buffer, unsigned long count,
2165 return lprocfs_write_frac_helper(buffer, count, val, 1);
2167 EXPORT_SYMBOL(lprocfs_write_helper);
2169 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
2172 char kernbuf[20], *end, *pbuf;
2174 if (count > (sizeof(kernbuf) - 1))
2177 if (cfs_copy_from_user(kernbuf, buffer, count))
2180 kernbuf[count] = '\0';
2187 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2191 if (end != NULL && *end == '.') {
2192 int temp_val, pow = 1;
2196 if (strlen(pbuf) > 5)
2197 pbuf[5] = '\0'; /*only allow 5bits fractional*/
2199 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
2202 for (i = 0; i < (end - pbuf); i++)
2205 *val += temp_val / pow;
2210 EXPORT_SYMBOL(lprocfs_write_frac_helper);
2212 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
2215 long decimal_val, frac_val;
2221 decimal_val = val / mult;
2222 prtn = snprintf(buffer, count, "%ld", decimal_val);
2223 frac_val = val % mult;
2225 if (prtn < (count - 4) && frac_val > 0) {
2227 int i, temp_mult = 1, frac_bits = 0;
2229 temp_frac = frac_val * 10;
2230 buffer[prtn++] = '.';
2231 while (frac_bits < 2 && (temp_frac / mult) < 1 ) {
2232 /* only reserved 2 bits fraction */
2233 buffer[prtn++] ='0';
2238 * Need to think these cases :
2239 * 1. #echo x.00 > /proc/xxx output result : x
2240 * 2. #echo x.0x > /proc/xxx output result : x.0x
2241 * 3. #echo x.x0 > /proc/xxx output result : x.x
2242 * 4. #echo x.xx > /proc/xxx output result : x.xx
2243 * Only reserved 2 bits fraction.
2245 for (i = 0; i < (5 - prtn); i++)
2248 frac_bits = min((int)count - prtn, 3 - frac_bits);
2249 prtn += snprintf(buffer + prtn, frac_bits, "%ld",
2250 frac_val * temp_mult / mult);
2253 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
2255 if (buffer[prtn] == '.') {
2262 buffer[prtn++] ='\n';
2265 EXPORT_SYMBOL(lprocfs_read_frac_helper);
2267 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
2269 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
2271 EXPORT_SYMBOL(lprocfs_write_u64_helper);
2273 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
2274 __u64 *val, int mult)
2276 char kernbuf[22], *end, *pbuf;
2277 __u64 whole, frac = 0, units;
2278 unsigned frac_d = 1;
2280 if (count > (sizeof(kernbuf) - 1))
2283 if (cfs_copy_from_user(kernbuf, buffer, count))
2286 kernbuf[count] = '\0';
2293 whole = simple_strtoull(pbuf, &end, 10);
2297 if (end != NULL && *end == '.') {
2301 /* need to limit frac_d to a __u32 */
2302 if (strlen(pbuf) > 10)
2305 frac = simple_strtoull(pbuf, &end, 10);
2306 /* count decimal places */
2307 for (i = 0; i < (end - pbuf); i++)
2324 /* Specified units override the multiplier */
2326 mult = mult < 0 ? -units : units;
2329 do_div(frac, frac_d);
2330 *val = whole * mult + frac;
2333 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
2335 static char *lprocfs_strnstr(const char *s1, const char *s2, size_t len)
2344 if (!memcmp(s1, s2, l2))
2352 * Find the string \a name in the input \a buffer, and return a pointer to the
2353 * value immediately following \a name, reducing \a count appropriately.
2354 * If \a name is not found the original \a buffer is returned.
2356 char *lprocfs_find_named_value(const char *buffer, const char *name,
2357 unsigned long *count)
2360 size_t buflen = *count;
2362 /* there is no strnstr() in rhel5 and ubuntu kernels */
2363 val = lprocfs_strnstr(buffer, name, buflen);
2365 return (char *)buffer;
2367 val += strlen(name); /* skip prefix */
2368 while (val < buffer + buflen && isspace(*val)) /* skip separator */
2372 while (val < buffer + buflen && isalnum(*val)) {
2377 return val - *count;
2379 EXPORT_SYMBOL(lprocfs_find_named_value);
2381 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent,
2384 const struct file_operations *seq_fops,
2387 struct proc_dir_entry *entry;
2390 /* Disallow secretly (un)writable entries. */
2391 LASSERT((seq_fops->write == NULL) == ((mode & 0222) == 0));
2393 LPROCFS_WRITE_ENTRY();
2394 entry = create_proc_entry(name, mode, parent);
2396 entry->proc_fops = seq_fops;
2399 LPROCFS_WRITE_EXIT();
2406 EXPORT_SYMBOL(lprocfs_seq_create);
2408 int lprocfs_obd_seq_create(struct obd_device *dev,
2411 const struct file_operations *seq_fops,
2414 return (lprocfs_seq_create(dev->obd_proc_entry, name,
2415 mode, seq_fops, data));
2417 EXPORT_SYMBOL(lprocfs_obd_seq_create);
2419 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
2421 if (value >= OBD_HIST_MAX)
2422 value = OBD_HIST_MAX - 1;
2424 spin_lock(&oh->oh_lock);
2425 oh->oh_buckets[value]++;
2426 spin_unlock(&oh->oh_lock);
2428 EXPORT_SYMBOL(lprocfs_oh_tally);
2430 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
2434 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
2437 lprocfs_oh_tally(oh, val);
2439 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
2441 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
2443 unsigned long ret = 0;
2446 for (i = 0; i < OBD_HIST_MAX; i++)
2447 ret += oh->oh_buckets[i];
2450 EXPORT_SYMBOL(lprocfs_oh_sum);
2452 void lprocfs_oh_clear(struct obd_histogram *oh)
2454 spin_lock(&oh->oh_lock);
2455 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
2456 spin_unlock(&oh->oh_lock);
2458 EXPORT_SYMBOL(lprocfs_oh_clear);
2460 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
2461 int count, int *eof, void *data)
2463 struct obd_device *obd = data;
2469 c += cfs_hash_debug_header(page, count);
2470 c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
2471 c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
2472 c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
2476 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
2478 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
2479 int count, int *eof, void *data)
2481 struct obd_device *obd = data;
2484 LASSERT(obd != NULL);
2485 LASSERT(count >= 0);
2487 /* Set start of user data returned to
2488 page + off since the user may have
2489 requested to read much smaller than
2490 what we need to read */
2491 *start = page + off;
2493 /* We know we are allocated a page here.
2494 Also we know that this function will
2495 not need to write more than a page
2496 so we can truncate at CFS_PAGE_SIZE. */
2497 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
2499 /* Initialize the page */
2500 memset(page, 0, size);
2502 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
2504 if (obd->obd_max_recoverable_clients == 0) {
2505 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
2511 /* sampled unlocked, but really... */
2512 if (obd->obd_recovering == 0) {
2513 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
2515 if (lprocfs_obd_snprintf(&page, size, &len,
2516 "recovery_start: %lu\n",
2517 obd->obd_recovery_start) <= 0)
2519 if (lprocfs_obd_snprintf(&page, size, &len,
2520 "recovery_duration: %lu\n",
2521 obd->obd_recovery_end -
2522 obd->obd_recovery_start) <= 0)
2524 /* Number of clients that have completed recovery */
2525 if (lprocfs_obd_snprintf(&page, size, &len,
2526 "completed_clients: %d/%d\n",
2527 obd->obd_max_recoverable_clients -
2528 obd->obd_stale_clients,
2529 obd->obd_max_recoverable_clients) <= 0)
2531 if (lprocfs_obd_snprintf(&page, size, &len,
2532 "replayed_requests: %d\n",
2533 obd->obd_replayed_requests) <= 0)
2535 if (lprocfs_obd_snprintf(&page, size, &len,
2536 "last_transno: "LPD64"\n",
2537 obd->obd_next_recovery_transno - 1)<=0)
2539 if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
2540 obd->obd_version_recov ?
2541 "ENABLED" : "DISABLED") <=0)
2543 if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
2545 "DISABLED" : "ENABLED") <= 0)
2550 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
2552 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
2553 obd->obd_recovery_start) <= 0)
2555 if (lprocfs_obd_snprintf(&page, size, &len, "time_remaining: %lu\n",
2556 cfs_time_current_sec() >=
2557 obd->obd_recovery_start +
2558 obd->obd_recovery_timeout ? 0 :
2559 obd->obd_recovery_start +
2560 obd->obd_recovery_timeout -
2561 cfs_time_current_sec()) <= 0)
2563 if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
2564 cfs_atomic_read(&obd->obd_connected_clients),
2565 obd->obd_max_recoverable_clients) <= 0)
2567 /* Number of clients that have completed recovery */
2568 if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
2569 cfs_atomic_read(&obd->obd_req_replay_clients))
2572 if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
2573 cfs_atomic_read(&obd->obd_lock_replay_clients))
2576 if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
2577 cfs_atomic_read(&obd->obd_connected_clients) -
2578 cfs_atomic_read(&obd->obd_lock_replay_clients))
2581 if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
2582 obd->obd_stale_clients) <= 0)
2584 if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
2585 obd->obd_replayed_requests) <= 0)
2587 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
2588 obd->obd_requests_queued_for_recovery) <= 0)
2591 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
2592 obd->obd_next_recovery_transno) <= 0)
2598 return min(count, len - (int)off);
2600 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
2602 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
2603 int count, int *eof, void *data)
2605 struct obd_device *obd = (struct obd_device *)data;
2606 LASSERT(obd != NULL);
2608 return snprintf(page, count, "%d\n",
2609 obd->obd_recovery_ir_factor);
2611 EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
2613 int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
2614 unsigned long count, void *data)
2616 struct obd_device *obd = (struct obd_device *)data;
2618 LASSERT(obd != NULL);
2620 rc = lprocfs_write_helper(buffer, count, &val);
2624 if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
2627 obd->obd_recovery_ir_factor = val;
2630 EXPORT_SYMBOL(lprocfs_obd_wr_ir_factor);
2632 int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
2633 int count, int *eof, void *data)
2635 struct obd_device *obd = (struct obd_device *)data;
2636 LASSERT(obd != NULL);
2638 return snprintf(page, count, "%d\n",
2639 obd->obd_recovery_timeout);
2641 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
2643 int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
2644 unsigned long count, void *data)
2646 struct obd_device *obd = (struct obd_device *)data;
2648 LASSERT(obd != NULL);
2650 rc = lprocfs_write_helper(buffer, count, &val);
2654 obd->obd_recovery_timeout = val;
2657 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft);
2659 int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
2660 int count, int *eof, void *data)
2662 struct obd_device *obd = data;
2663 LASSERT(obd != NULL);
2665 return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
2667 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
2669 int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
2670 unsigned long count, void *data)
2672 struct obd_device *obd = data;
2674 LASSERT(obd != NULL);
2676 rc = lprocfs_write_helper(buffer, count, &val);
2680 obd->obd_recovery_time_hard = val;
2683 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
2685 int lprocfs_obd_rd_mntdev(char *page, char **start, off_t off,
2686 int count, int *eof, void *data)
2688 struct obd_device *obd = (struct obd_device *)data;
2689 struct lustre_mount_info *lmi;
2690 const char *dev_name;
2692 LASSERT(obd != NULL);
2693 lmi = server_get_mount_2(obd->obd_name);
2694 dev_name = get_mntdev_name(lmi->lmi_sb);
2695 LASSERT(dev_name != NULL);
2697 server_put_mount_2(obd->obd_name, lmi->lmi_mnt);
2698 return snprintf(page, count, "%s\n", dev_name);
2700 EXPORT_SYMBOL(lprocfs_obd_rd_mntdev);
2702 int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
2703 int count, int *eof, void *data)
2705 struct obd_device *dev = data;
2706 struct client_obd *cli = &dev->u.cli;
2709 client_obd_list_lock(&cli->cl_loi_list_lock);
2710 rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
2711 client_obd_list_unlock(&cli->cl_loi_list_lock);
2714 EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
2716 int lprocfs_target_rd_instance(char *page, char **start, off_t off,
2717 int count, int *eof, void *data)
2719 struct obd_device *obd = (struct obd_device *)data;
2720 struct obd_device_target *target = &obd->u.obt;
2722 LASSERT(obd != NULL);
2723 LASSERT(target->obt_magic == OBT_MAGIC);
2725 return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
2727 EXPORT_SYMBOL(lprocfs_target_rd_instance);