1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2002, 2003 Cluster File Systems, Inc.
5 * Author: Hariharan Thantry <thantry@users.sourceforge.net>
7 * This file is part of the Lustre file system, http://www.lustre.org
8 * Lustre is a trademark of Cluster File Systems, Inc.
10 * You may have signed or agreed to another license before downloading
11 * this software. If so, you are bound by the terms and conditions
12 * of that agreement, and the following does not apply to you. See the
13 * LICENSE file included with this distribution for more information.
15 * If you did not agree to a different license, then this copy of Lustre
16 * is open source software; you can redistribute it and/or modify it
17 * under the terms of version 2 of the GNU General Public License as
18 * published by the Free Software Foundation.
20 * In either case, Lustre is distributed in the hope that it will be
21 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
22 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * license text for more details.
27 # define EXPORT_SYMTAB
29 #define DEBUG_SUBSYSTEM S_CLASS
32 # include <liblustre.h>
35 #include <obd_class.h>
36 #include <lprocfs_status.h>
37 #include <lustre_fsfilt.h>
41 #define MAX_STRING_SIZE 128
43 /* for bug 10866, global variable */
44 DECLARE_RWSEM(_lprocfs_lock);
45 EXPORT_SYMBOL(_lprocfs_lock);
47 int lprocfs_seq_release(struct inode *inode, struct file *file)
50 return seq_release(inode, file);
52 EXPORT_SYMBOL(lprocfs_seq_release);
54 struct proc_dir_entry *lprocfs_srch(struct proc_dir_entry *head,
57 struct proc_dir_entry *temp;
63 while (temp != NULL) {
64 if (strcmp(temp->name, name) == 0)
72 /* lprocfs API calls */
74 /* Function that emulates snprintf but also has the side effect of advancing
75 the page pointer for the next write into the buffer, incrementing the total
76 length written to the buffer, and decrementing the size left in the
78 static int lprocfs_obd_snprintf(char **page, int end, int *len,
79 const char *format, ...)
87 va_start(list, format);
88 n = vsnprintf(*page, end - *len, format, list);
91 *page += n; *len += n;
95 int lprocfs_add_simple(struct proc_dir_entry *root, char *name,
96 read_proc_t *read_proc, write_proc_t *write_proc,
99 struct proc_dir_entry *proc;
102 if (root == NULL || name == NULL)
108 proc = create_proc_entry(name, mode, root);
110 CERROR("LprocFS: No memory to create /proc entry %s", name);
113 proc->read_proc = read_proc;
114 proc->write_proc = write_proc;
119 struct proc_dir_entry *lprocfs_add_symlink(const char *name,
120 struct proc_dir_entry *parent, const char *dest)
122 struct proc_dir_entry *entry;
124 if (parent == NULL || dest == NULL)
127 entry = proc_symlink(name, parent, dest);
129 CERROR("LprocFS: Could not create symbolic link from %s to %s",
134 static ssize_t lprocfs_fops_read(struct file *f, char __user *buf,
135 size_t size, loff_t *ppos)
137 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
138 char *page, *start = NULL;
139 int rc = 0, eof = 1, count;
141 if (*ppos >= CFS_PAGE_SIZE)
144 page = (char *)__get_free_page(GFP_KERNEL);
149 OBD_FAIL_TIMEOUT(OBD_FAIL_LPROC_REMOVE, 10);
150 if (!dp->deleted && dp->read_proc)
151 rc = dp->read_proc(page, &start, *ppos, CFS_PAGE_SIZE,
157 /* for lustre proc read, the read count must be less than PAGE_SIZE */
166 start = page + *ppos;
167 } else if (start < page) {
171 count = (rc < size) ? rc : size;
172 if (copy_to_user(buf, start, count)) {
179 free_page((unsigned long)page);
183 static ssize_t lprocfs_fops_write(struct file *f, const char __user *buf, size_t size, loff_t *ppos)
185 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
189 if (!dp->deleted && dp->write_proc)
190 rc = dp->write_proc(f, buf, size, dp->data);
195 static struct file_operations lprocfs_generic_fops = {
196 .owner = THIS_MODULE,
197 .read = lprocfs_fops_read,
198 .write = lprocfs_fops_write,
201 int lprocfs_evict_client_open(struct inode *inode, struct file *f)
203 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
204 struct obd_device *obd = dp->data;
206 atomic_inc(&obd->obd_evict_inprogress);
211 int lprocfs_evict_client_release(struct inode *inode, struct file *f)
213 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
214 struct obd_device *obd = dp->data;
216 atomic_dec(&obd->obd_evict_inprogress);
217 wake_up(&obd->obd_evict_inprogress_waitq);
222 struct file_operations lprocfs_evict_client_fops = {
223 .owner = THIS_MODULE,
224 .read = lprocfs_fops_read,
225 .write = lprocfs_fops_write,
226 .open = lprocfs_evict_client_open,
227 .release = lprocfs_evict_client_release,
229 EXPORT_SYMBOL(lprocfs_evict_client_fops);
231 int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list,
234 if (root == NULL || list == NULL)
237 while (list->name != NULL) {
238 struct proc_dir_entry *cur_root, *proc;
239 char *pathcopy, *cur, *next, pathbuf[64];
240 int pathsize = strlen(list->name) + 1;
245 /* need copy of path for strsep */
246 if (strlen(list->name) > sizeof(pathbuf) - 1) {
247 OBD_ALLOC(pathcopy, pathsize);
248 if (pathcopy == NULL)
255 strcpy(pathcopy, list->name);
257 while (cur_root != NULL && (cur = strsep(&next, "/"))) {
258 if (*cur =='\0') /* skip double/trailing "/" */
261 proc = lprocfs_srch(cur_root, cur);
262 CDEBUG(D_OTHER, "cur_root=%s, cur=%s, next=%s, (%s)\n",
263 cur_root->name, cur, next,
264 (proc ? "exists" : "new"));
266 cur_root = (proc ? proc :
267 proc_mkdir(cur, cur_root));
268 } else if (proc == NULL) {
272 if (list->write_fptr)
274 proc = create_proc_entry(cur, mode, cur_root);
278 if (pathcopy != pathbuf)
279 OBD_FREE(pathcopy, pathsize);
281 if (cur_root == NULL || proc == NULL) {
282 CERROR("LprocFS: No memory to create /proc entry %s",
288 proc->proc_fops = list->fops;
290 proc->proc_fops = &lprocfs_generic_fops;
291 proc->read_proc = list->read_fptr;
292 proc->write_proc = list->write_fptr;
293 proc->data = (list->data ? list->data : data);
299 void lprocfs_remove(struct proc_dir_entry **rooth)
301 struct proc_dir_entry *root = *rooth;
302 struct proc_dir_entry *temp = root;
303 struct proc_dir_entry *rm_entry;
304 struct proc_dir_entry *parent;
310 parent = root->parent;
311 LASSERT(parent != NULL);
314 while (temp->subdir != NULL)
320 /* Memory corruption once caused this to fail, and
321 without this LASSERT we would loop here forever. */
322 LASSERTF(strlen(rm_entry->name) == rm_entry->namelen,
323 "0x%p %s/%s len %d\n", rm_entry, temp->name,
324 rm_entry->name, (int)strlen(rm_entry->name));
326 /* Now, the rm_entry->deleted flags is protected
327 * by _lprocfs_lock. */
328 down_write(&_lprocfs_lock);
329 rm_entry->data = NULL;
330 remove_proc_entry(rm_entry->name, temp);
331 up_write(&_lprocfs_lock);
337 void lprocfs_remove_proc_entry(const char *name, struct proc_dir_entry *parent)
339 LASSERT(parent != NULL);
340 remove_proc_entry(name, parent);
343 struct proc_dir_entry *lprocfs_register(const char *name,
344 struct proc_dir_entry *parent,
345 struct lprocfs_vars *list, void *data)
347 struct proc_dir_entry *newchild;
349 newchild = lprocfs_srch(parent, name);
350 if (newchild != NULL) {
351 CERROR(" Lproc: Attempting to register %s more than once \n",
353 return ERR_PTR(-EALREADY);
356 newchild = proc_mkdir(name, parent);
357 if (newchild != NULL && list != NULL) {
358 int rc = lprocfs_add_vars(newchild, list, data);
360 lprocfs_remove(&newchild);
367 /* Generic callbacks */
368 int lprocfs_rd_uint(char *page, char **start, off_t off,
369 int count, int *eof, void *data)
371 unsigned int *temp = (unsigned int *)data;
372 return snprintf(page, count, "%u\n", *temp);
375 int lprocfs_wr_uint(struct file *file, const char *buffer,
376 unsigned long count, void *data)
379 char dummy[MAX_STRING_SIZE + 1], *end;
382 dummy[MAX_STRING_SIZE] = '\0';
383 if (copy_from_user(dummy, buffer, MAX_STRING_SIZE))
386 tmp = simple_strtoul(dummy, &end, 0);
390 *p = (unsigned int)tmp;
394 int lprocfs_rd_u64(char *page, char **start, off_t off,
395 int count, int *eof, void *data)
397 LASSERT(data != NULL);
399 return snprintf(page, count, LPU64"\n", *(__u64 *)data);
402 int lprocfs_rd_atomic(char *page, char **start, off_t off,
403 int count, int *eof, void *data)
405 atomic_t *atom = (atomic_t *)data;
406 LASSERT(atom != NULL);
408 return snprintf(page, count, "%d\n", atomic_read(atom));
411 int lprocfs_wr_atomic(struct file *file, const char *buffer,
412 unsigned long count, void *data)
414 atomic_t *atm = data;
418 rc = lprocfs_write_helper(buffer, count, &val);
425 atomic_set(atm, val);
429 int lprocfs_rd_uuid(char *page, char **start, off_t off, int count,
430 int *eof, void *data)
432 struct obd_device *obd = (struct obd_device*)data;
434 LASSERT(obd != NULL);
436 return snprintf(page, count, "%s\n", obd->obd_uuid.uuid);
439 int lprocfs_rd_name(char *page, char **start, off_t off, int count,
440 int *eof, void* data)
442 struct obd_device *dev = (struct obd_device *)data;
444 LASSERT(dev != NULL);
445 LASSERT(dev->obd_name != NULL);
447 return snprintf(page, count, "%s\n", dev->obd_name);
450 int lprocfs_rd_fstype(char *page, char **start, off_t off, int count, int *eof,
453 struct obd_device *obd = (struct obd_device *)data;
455 LASSERT(obd != NULL);
456 LASSERT(obd->obd_fsops != NULL);
457 LASSERT(obd->obd_fsops->fs_type != NULL);
458 return snprintf(page, count, "%s\n", obd->obd_fsops->fs_type);
461 int lprocfs_rd_blksize(char *page, char **start, off_t off, int count,
462 int *eof, void *data)
464 struct obd_statfs osfs;
465 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ,
469 rc = snprintf(page, count, "%u\n", osfs.os_bsize);
474 int lprocfs_rd_kbytestotal(char *page, char **start, off_t off, int count,
475 int *eof, void *data)
477 struct obd_statfs osfs;
478 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ,
481 __u32 blk_size = osfs.os_bsize >> 10;
482 __u64 result = osfs.os_blocks;
484 while (blk_size >>= 1)
488 rc = snprintf(page, count, LPU64"\n", result);
493 int lprocfs_rd_kbytesfree(char *page, char **start, off_t off, int count,
494 int *eof, void *data)
496 struct obd_statfs osfs;
497 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ,
500 __u32 blk_size = osfs.os_bsize >> 10;
501 __u64 result = osfs.os_bfree;
503 while (blk_size >>= 1)
507 rc = snprintf(page, count, LPU64"\n", result);
512 int lprocfs_rd_kbytesavail(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, cfs_time_current_64() - HZ,
519 __u32 blk_size = osfs.os_bsize >> 10;
520 __u64 result = osfs.os_bavail;
522 while (blk_size >>= 1)
526 rc = snprintf(page, count, LPU64"\n", result);
531 int lprocfs_rd_filestotal(char *page, char **start, off_t off, int count,
532 int *eof, void *data)
534 struct obd_statfs osfs;
535 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ,
539 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
545 int lprocfs_rd_filesfree(char *page, char **start, off_t off, int count,
546 int *eof, void *data)
548 struct obd_statfs osfs;
549 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ,
553 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
558 int lprocfs_rd_server_uuid(char *page, char **start, off_t off, int count,
559 int *eof, void *data)
561 struct obd_device *obd = (struct obd_device *)data;
562 struct obd_import *imp;
563 char *imp_state_name = NULL;
566 LASSERT(obd != NULL);
567 LPROCFS_CLIMP_CHECK(obd);
568 imp = obd->u.cli.cl_import;
569 imp_state_name = ptlrpc_import_state_name(imp->imp_state);
571 rc = snprintf(page, count, "%s\t%s%s\n",
572 obd2cli_tgt(obd), imp_state_name,
573 imp->imp_deactive ? "\tDEACTIVATED" : "");
575 LPROCFS_CLIMP_EXIT(obd);
579 int lprocfs_rd_conn_uuid(char *page, char **start, off_t off, int count,
580 int *eof, void *data)
582 struct obd_device *obd = (struct obd_device*)data;
583 struct ptlrpc_connection *conn;
586 LASSERT(obd != NULL);
588 LPROCFS_CLIMP_CHECK(obd);
589 conn = obd->u.cli.cl_import->imp_connection;
590 LASSERT(conn != NULL);
592 if (obd->u.cli.cl_import) {
593 rc = snprintf(page, count, "%s\n",
594 conn->c_remote_uuid.uuid);
596 rc = snprintf(page, count, "%s\n", "<none>");
599 LPROCFS_CLIMP_EXIT(obd);
603 static const char *obd_connect_names[] = {
630 "mds_mds_connection",
633 "alt_checksum_algorithm",
638 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
639 int count, int *eof, void *data)
641 struct obd_device *obd = data;
642 __u64 mask = 1, flags;
645 LPROCFS_CLIMP_CHECK(obd);
646 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
647 ret = snprintf(page, count, "flags="LPX64"\n", flags);
648 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
650 ret += snprintf(page + ret, count - ret, "%s\n",
651 obd_connect_names[i]);
653 if (flags & ~(mask - 1))
654 ret += snprintf(page + ret, count - ret,
655 "unknown flags "LPX64"\n", flags & ~(mask - 1));
657 LPROCFS_CLIMP_EXIT(obd);
660 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
662 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
663 int *eof, void *data)
665 struct obd_device *obd = (struct obd_device*)data;
667 LASSERT(obd != NULL);
669 return snprintf(page, count, "%u\n", obd->obd_num_exports);
672 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
673 int *eof, void *data)
675 struct obd_type *class = (struct obd_type*) data;
677 LASSERT(class != NULL);
679 return snprintf(page, count, "%d\n", class->typ_refcnt);
682 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
686 LASSERT(obd != NULL);
687 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
688 LASSERT(obd->obd_type->typ_procroot != NULL);
690 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
691 obd->obd_type->typ_procroot,
693 if (IS_ERR(obd->obd_proc_entry)) {
694 rc = PTR_ERR(obd->obd_proc_entry);
695 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
696 obd->obd_proc_entry = NULL;
701 int lprocfs_obd_cleanup(struct obd_device *obd)
705 if (obd->obd_proc_exports_entry) {
706 /* Should be no exports left */
707 LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
708 lprocfs_remove(&obd->obd_proc_exports_entry);
710 lprocfs_remove(&obd->obd_proc_entry);
714 static void lprocfs_free_client_stats(struct nid_stat *client_stat)
716 CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
717 client_stat->nid_proc, client_stat->nid_stats,
718 client_stat->nid_brw_stats);
720 LASSERTF(client_stat->nid_exp_ref_count == 0, "count %d\n",
721 client_stat->nid_exp_ref_count);
723 hlist_del_init(&client_stat->nid_hash);
725 if (client_stat->nid_proc)
726 lprocfs_remove(&client_stat->nid_proc);
728 if (client_stat->nid_stats)
729 lprocfs_free_stats(&client_stat->nid_stats);
731 if (client_stat->nid_brw_stats)
732 OBD_FREE(client_stat->nid_brw_stats, sizeof(struct brw_stats));
734 OBD_FREE(client_stat, sizeof(*client_stat));
739 void lprocfs_free_per_client_stats(struct obd_device *obd)
741 struct nid_stat *stat;
744 /* we need extra list - because hash_exit called to early */
745 /* not need locking because all clients is died */
746 while(!list_empty(&obd->obd_nid_stats)) {
747 stat = list_entry(obd->obd_nid_stats.next,
748 struct nid_stat, nid_list);
749 list_del_init(&stat->nid_list);
750 lprocfs_free_client_stats(stat);
756 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
757 enum lprocfs_stats_flags flags)
759 struct lprocfs_stats *stats;
760 unsigned int percpusize;
762 unsigned int num_cpu;
767 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
770 num_cpu = num_possible_cpus();
772 OBD_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
776 if (flags & LPROCFS_STATS_FLAG_NOPERCPU) {
777 stats->ls_flags = flags;
778 spin_lock_init(&stats->ls_lock);
779 /* Use this lock only if there are no percpu areas */
784 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
786 percpusize = L1_CACHE_ALIGN(percpusize);
788 for (i = 0; i < num_cpu; i++) {
789 OBD_ALLOC(stats->ls_percpu[i], percpusize);
790 if (stats->ls_percpu[i] == NULL) {
791 for (j = 0; j < i; j++) {
792 OBD_FREE(stats->ls_percpu[j], percpusize);
793 stats->ls_percpu[j] = NULL;
798 if (stats->ls_percpu[0] == NULL) {
799 OBD_FREE(stats, offsetof(typeof(*stats),
800 ls_percpu[num_cpu]));
808 void lprocfs_free_stats(struct lprocfs_stats **statsh)
810 struct lprocfs_stats *stats = *statsh;
811 unsigned int num_cpu;
812 unsigned int percpusize;
815 if (stats == NULL || stats->ls_num == 0)
819 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
822 num_cpu = num_possible_cpus();
824 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
826 percpusize = L1_CACHE_ALIGN(percpusize);
827 for (i = 0; i < num_cpu; i++)
828 OBD_FREE(stats->ls_percpu[i], percpusize);
829 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
832 void lprocfs_clear_stats(struct lprocfs_stats *stats)
834 struct lprocfs_counter *percpu_cntr;
836 unsigned int num_cpu;
838 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
840 for (i = 0; i < num_cpu; i++) {
841 for (j = 0; j < stats->ls_num; j++) {
842 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
843 atomic_inc(&percpu_cntr->lc_cntl.la_entry);
844 percpu_cntr->lc_count = 0;
845 percpu_cntr->lc_sum = 0;
846 percpu_cntr->lc_min = LC_MIN_INIT;
847 percpu_cntr->lc_max = 0;
848 percpu_cntr->lc_sumsquare = 0;
849 atomic_inc(&percpu_cntr->lc_cntl.la_exit);
853 lprocfs_stats_unlock(stats);
856 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
857 size_t len, loff_t *off)
859 struct seq_file *seq = file->private_data;
860 struct lprocfs_stats *stats = seq->private;
862 lprocfs_clear_stats(stats);
867 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
869 struct lprocfs_stats *stats = p->private;
870 /* return 1st cpu location */
871 return (*pos >= stats->ls_num) ? NULL :
872 &(stats->ls_percpu[0]->lp_cntr[*pos]);
875 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
879 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
881 struct lprocfs_stats *stats = p->private;
883 return (*pos >= stats->ls_num) ? NULL :
884 &(stats->ls_percpu[0]->lp_cntr[*pos]);
887 /* seq file export of one lprocfs counter */
888 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
890 struct lprocfs_stats *stats = p->private;
891 struct lprocfs_counter *cntr = v;
892 struct lprocfs_counter t, ret = { .lc_min = LC_MIN_INIT };
894 unsigned int num_cpu;
896 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
898 do_gettimeofday(&now);
899 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
900 "snapshot_time", now.tv_sec, now.tv_usec);
904 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
906 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
909 num_cpu = num_possible_cpus();
911 for (i = 0; i < num_cpu; i++) {
912 struct lprocfs_counter *percpu_cntr =
913 &(stats->ls_percpu[i])->lp_cntr[idx];
917 centry = atomic_read(&percpu_cntr->lc_cntl.la_entry);
918 t.lc_count = percpu_cntr->lc_count;
919 t.lc_sum = percpu_cntr->lc_sum;
920 t.lc_min = percpu_cntr->lc_min;
921 t.lc_max = percpu_cntr->lc_max;
922 t.lc_sumsquare = percpu_cntr->lc_sumsquare;
923 } while (centry != atomic_read(&percpu_cntr->lc_cntl.la_entry) &&
924 centry != atomic_read(&percpu_cntr->lc_cntl.la_exit));
925 ret.lc_count += t.lc_count;
926 ret.lc_sum += t.lc_sum;
927 if (t.lc_min < ret.lc_min)
928 ret.lc_min = t.lc_min;
929 if (t.lc_max > ret.lc_max)
930 ret.lc_max = t.lc_max;
931 ret.lc_sumsquare += t.lc_sumsquare;
934 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", cntr->lc_name,
935 ret.lc_count, cntr->lc_units);
939 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
940 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
941 ret.lc_min, ret.lc_max, ret.lc_sum);
944 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
945 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
949 rc = seq_printf(p, "\n");
951 return (rc < 0) ? rc : 0;
954 struct seq_operations lprocfs_stats_seq_sops = {
955 start: lprocfs_stats_seq_start,
956 stop: lprocfs_stats_seq_stop,
957 next: lprocfs_stats_seq_next,
958 show: lprocfs_stats_seq_show,
961 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
963 struct proc_dir_entry *dp = PDE(inode);
964 struct seq_file *seq;
967 LPROCFS_ENTRY_AND_CHECK(dp);
968 rc = seq_open(file, &lprocfs_stats_seq_sops);
973 seq = file->private_data;
974 seq->private = dp->data;
978 struct file_operations lprocfs_stats_seq_fops = {
979 .owner = THIS_MODULE,
980 .open = lprocfs_stats_seq_open,
982 .write = lprocfs_stats_seq_write,
984 .release = lprocfs_seq_release,
987 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
988 struct lprocfs_stats *stats)
990 struct proc_dir_entry *entry;
991 LASSERT(root != NULL);
993 entry = create_proc_entry(name, 0644, root);
996 entry->proc_fops = &lprocfs_stats_seq_fops;
997 entry->data = (void *)stats;
1001 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1002 unsigned conf, const char *name, const char *units)
1004 struct lprocfs_counter *c;
1006 unsigned int num_cpu;
1008 LASSERT(stats != NULL);
1010 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1012 for (i = 0; i < num_cpu; i++) {
1013 c = &(stats->ls_percpu[i]->lp_cntr[index]);
1014 c->lc_config = conf;
1017 c->lc_min = LC_MIN_INIT;
1020 c->lc_units = units;
1023 lprocfs_stats_unlock(stats);
1025 EXPORT_SYMBOL(lprocfs_counter_init);
1027 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1029 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1030 LASSERT(coffset < stats->ls_num); \
1031 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1034 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1036 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1037 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1038 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1039 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1040 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1041 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1042 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1043 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1044 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1045 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1046 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1047 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1048 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1049 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1050 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1051 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1052 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1053 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1054 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
1055 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1056 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1057 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1058 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1059 LPROCFS_OBD_OP_INIT(num_private_stats, stats, checkmd);
1060 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1061 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1062 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1063 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1064 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1065 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1066 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1067 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1068 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1069 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw_async);
1070 LPROCFS_OBD_OP_INIT(num_private_stats, stats, prep_async_page);
1071 LPROCFS_OBD_OP_INIT(num_private_stats, stats, queue_async_io);
1072 LPROCFS_OBD_OP_INIT(num_private_stats, stats, queue_group_io);
1073 LPROCFS_OBD_OP_INIT(num_private_stats, stats, trigger_group_io);
1074 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_async_flags);
1075 LPROCFS_OBD_OP_INIT(num_private_stats, stats, teardown_async_page);
1076 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1077 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1078 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1079 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1080 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1081 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1082 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1083 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1084 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1085 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1086 LPROCFS_OBD_OP_INIT(num_private_stats, stats, match);
1087 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1088 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1089 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1090 LPROCFS_OBD_OP_INIT(num_private_stats, stats, join_lru);
1091 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1092 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1093 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1094 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1095 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1096 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1097 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1098 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1099 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1100 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1101 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1102 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1103 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1104 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1107 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1109 struct lprocfs_stats *stats;
1110 unsigned int num_stats;
1113 LASSERT(obd->obd_stats == NULL);
1114 LASSERT(obd->obd_proc_entry != NULL);
1115 LASSERT(obd->obd_cntr_base == 0);
1117 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1118 num_private_stats - 1 /* o_owner */;
1119 stats = lprocfs_alloc_stats(num_stats, 0);
1123 lprocfs_init_ops_stats(num_private_stats, stats);
1125 for (i = num_private_stats; i < num_stats; i++) {
1126 /* If this LBUGs, it is likely that an obd
1127 * operation was added to struct obd_ops in
1128 * <obd.h>, and that the corresponding line item
1129 * LPROCFS_OBD_OP_INIT(.., .., opname)
1130 * is missing from the list above. */
1131 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1132 "Missing obd_stat initializer obd_op "
1133 "operation at offset %d.\n", i - num_private_stats);
1135 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1137 lprocfs_free_stats(&stats);
1139 obd->obd_stats = stats;
1140 obd->obd_cntr_base = num_private_stats;
1145 void lprocfs_free_obd_stats(struct obd_device *obd)
1148 lprocfs_free_stats(&obd->obd_stats);
1151 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1153 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1154 LASSERT(coffset < stats->ls_num); \
1155 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1158 int lprocfs_alloc_md_stats(struct obd_device *obd,
1159 unsigned num_private_stats)
1161 struct lprocfs_stats *stats;
1162 unsigned int num_stats;
1165 LASSERT(obd->md_stats == NULL);
1166 LASSERT(obd->obd_proc_entry != NULL);
1167 LASSERT(obd->md_cntr_base == 0);
1169 num_stats = 1 + MD_COUNTER_OFFSET(get_remote_perm) +
1171 stats = lprocfs_alloc_stats(num_stats, 0);
1175 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1176 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1177 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1178 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1179 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1180 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1181 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1182 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1183 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1184 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1185 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1186 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1187 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1188 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1189 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1190 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1191 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1192 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1193 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1194 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1195 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1196 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1197 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1198 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1199 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1200 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1201 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1202 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1204 for (i = num_private_stats; i < num_stats; i++) {
1205 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1206 CERROR("Missing md_stat initializer md_op "
1207 "operation at offset %d. Aborting.\n",
1208 i - num_private_stats);
1212 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1214 lprocfs_free_stats(&stats);
1216 obd->md_stats = stats;
1217 obd->md_cntr_base = num_private_stats;
1222 void lprocfs_free_md_stats(struct obd_device *obd)
1224 struct lprocfs_stats *stats = obd->md_stats;
1226 if (stats != NULL) {
1227 obd->md_stats = NULL;
1228 lprocfs_free_stats(&stats);
1232 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1233 int *eof, void *data)
1235 struct obd_export *exp = (struct obd_export*)data;
1236 LASSERT(exp != NULL);
1238 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1241 struct exp_uuid_cb_data {
1248 void lprocfs_exp_print_uuid(void *obj, void *cb_data)
1250 struct obd_export *exp = (struct obd_export *)obj;
1251 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1253 if (exp->exp_nid_stats)
1254 *data->len += snprintf((data->page + *data->len),
1255 data->count, "%s\n",
1256 obd_uuid2str(&exp->exp_client_uuid));
1259 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1260 int *eof, void *data)
1262 struct nid_stat *stats = (struct nid_stat *)data;
1263 struct exp_uuid_cb_data cb_data;
1264 struct obd_device *obd = stats->nid_obd;
1269 LASSERT(obd != NULL);
1271 cb_data.page = page;
1272 cb_data.count = count;
1275 lustre_hash_bucket_iterate(obd->obd_nid_hash_body,
1276 &stats->nid, lprocfs_exp_print_uuid,
1278 return (*cb_data.len);
1281 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1282 int count, int *eof, void *data)
1285 return snprintf(page, count, "%s\n",
1286 "Write into this file to clear all nid stats and "
1287 "stale nid entries");
1289 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1291 void lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1293 struct nid_stat *stat = obj;
1296 /* object has only hash + iterate_all references.
1297 * add/delete blocked by hash bucket lock */
1298 CDEBUG(D_INFO,"refcnt %d\n", stat->nid_exp_ref_count);
1299 if(stat->nid_exp_ref_count == 2) {
1300 hlist_del_init(&stat->nid_hash);
1301 stat->nid_exp_ref_count--;
1302 spin_lock(&stat->nid_obd->obd_nid_lock);
1303 list_del_init(&stat->nid_list);
1304 spin_unlock(&stat->nid_obd->obd_nid_lock);
1305 list_add(&stat->nid_list, data);
1309 /* we has reference to object - only clear data*/
1310 if (stat->nid_stats)
1311 lprocfs_clear_stats(stat->nid_stats);
1313 if (stat->nid_brw_stats) {
1314 for (i = 0; i < BRW_LAST; i++)
1315 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
1321 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1322 unsigned long count, void *data)
1324 struct obd_device *obd = (struct obd_device *)data;
1325 struct nid_stat *client_stat;
1326 CFS_LIST_HEAD(free_list);
1328 lustre_hash_iterate_all(obd->obd_nid_stats_hash_body,
1329 lprocfs_nid_stats_clear_write_cb, &free_list);
1331 while (!list_empty(&free_list)) {
1332 client_stat = list_entry(free_list.next, struct nid_stat, nid_list);
1333 list_del_init(&client_stat->nid_list);
1334 lprocfs_free_client_stats(client_stat);
1339 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1341 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1344 struct nid_stat *tmp = NULL, *tmp1;
1345 struct obd_device *obd = NULL;
1350 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1351 !exp->exp_obd->obd_nid_stats_hash_body)
1354 /* not test against zero because eric say:
1355 * You may only test nid against another nid, or LNET_NID_ANY. Anything else is
1357 if (!nid || *nid == LNET_NID_ANY)
1362 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash_body);
1364 OBD_ALLOC(tmp, sizeof(struct nid_stat));
1369 tmp->nid_obd = exp->exp_obd;
1370 tmp->nid_exp_ref_count = 1; /* need live in hash after destroy export */
1372 /* protect competitive add to list, not need locking on destroy */
1373 spin_lock(&obd->obd_nid_lock);
1374 list_add(&tmp->nid_list, &obd->obd_nid_stats);
1375 spin_unlock(&obd->obd_nid_lock);
1377 tmp1= lustre_hash_findadd_unique(obd->obd_nid_stats_hash_body, nid,
1379 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
1380 tmp1, libcfs_nid2str(*nid), tmp->nid_exp_ref_count);
1383 exp->exp_nid_stats = tmp1;
1384 GOTO(destroy_new, rc = 0);
1386 /* not found - create */
1387 tmp->nid_proc = lprocfs_register(libcfs_nid2str(*nid),
1388 obd->obd_proc_exports_entry, NULL, NULL);
1389 if (!tmp->nid_proc) {
1390 CERROR("Error making export directory for"
1391 " nid %s\n", libcfs_nid2str(*nid));
1392 lustre_hash_delitem(obd->obd_nid_stats_hash_body, nid,
1394 GOTO(destroy_new, rc = -ENOMEM);
1397 rc = lprocfs_add_simple(tmp->nid_proc, "uuid",
1398 lprocfs_exp_rd_uuid, NULL, tmp);
1400 CWARN("Error adding the uuid file\n");
1402 exp->exp_nid_stats = tmp;
1407 spin_lock(&obd->obd_nid_lock);
1408 list_del(&tmp->nid_list);
1409 spin_unlock(&obd->obd_nid_lock);
1410 OBD_FREE(tmp, sizeof(struct nid_stat));
1414 int lprocfs_exp_cleanup(struct obd_export *exp)
1416 struct nid_stat *stat = exp->exp_nid_stats;
1421 stat->nid_exp_ref_count--;
1422 CDEBUG(D_INFO, "Put stat %p - %d\n", stat, stat->nid_exp_ref_count);
1424 exp->exp_nid_stats = NULL;
1428 int lprocfs_write_helper(const char *buffer, unsigned long count,
1431 return lprocfs_write_frac_helper(buffer, count, val, 1);
1434 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
1437 char kernbuf[20], *end, *pbuf;
1439 if (count > (sizeof(kernbuf) - 1))
1442 if (copy_from_user(kernbuf, buffer, count))
1445 kernbuf[count] = '\0';
1452 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1456 if (end != NULL && *end == '.') {
1457 int temp_val, pow = 1;
1461 if (strlen(pbuf) > 5)
1462 pbuf[5] = '\0'; /*only allow 5bits fractional*/
1464 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1467 for (i = 0; i < (end - pbuf); i++)
1470 *val += temp_val / pow;
1476 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val, int mult)
1478 long decimal_val, frac_val;
1484 decimal_val = val / mult;
1485 prtn = snprintf(buffer, count, "%ld", decimal_val);
1486 frac_val = val % mult;
1488 if (prtn < (count - 4) && frac_val > 0) {
1490 int i, temp_mult = 1, frac_bits = 0;
1492 temp_frac = frac_val * 10;
1493 buffer[prtn++] = '.';
1494 while (frac_bits < 2 && (temp_frac / mult) < 1 ) { /*only reserved 2bits fraction*/
1495 buffer[prtn++] ='0';
1500 Need to think these cases :
1501 1. #echo x.00 > /proc/xxx output result : x
1502 2. #echo x.0x > /proc/xxx output result : x.0x
1503 3. #echo x.x0 > /proc/xxx output result : x.x
1504 4. #echo x.xx > /proc/xxx output result : x.xx
1505 Only reserved 2bits fraction.
1507 for (i = 0; i < (5 - prtn); i++)
1510 frac_bits = min((int)count - prtn, 3 - frac_bits);
1511 prtn += snprintf(buffer + prtn, frac_bits, "%ld", frac_val * temp_mult / mult);
1514 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
1516 if (buffer[prtn] == '.') {
1523 buffer[prtn++] ='\n';
1527 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
1529 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
1532 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
1533 __u64 *val, int mult)
1535 char kernbuf[22], *end, *pbuf;
1536 __u64 whole, frac = 0, units;
1537 unsigned frac_d = 1;
1539 if (count > (sizeof(kernbuf) - 1) )
1542 if (copy_from_user(kernbuf, buffer, count))
1545 kernbuf[count] = '\0';
1552 whole = simple_strtoull(pbuf, &end, 10);
1556 if (end != NULL && *end == '.') {
1560 /* need to limit frac_d to a __u32 */
1561 if (strlen(pbuf) > 10)
1564 frac = simple_strtoull(pbuf, &end, 10);
1565 /* count decimal places */
1566 for (i = 0; i < (end - pbuf); i++)
1583 /* Specified units override the multiplier */
1585 mult = mult < 0 ? -units : units;
1588 do_div(frac, frac_d);
1589 *val = whole * mult + frac;
1593 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent,
1594 char *name, mode_t mode,
1595 struct file_operations *seq_fops, void *data)
1597 struct proc_dir_entry *entry;
1600 entry = create_proc_entry(name, mode, parent);
1603 entry->proc_fops = seq_fops;
1608 EXPORT_SYMBOL(lprocfs_seq_create);
1610 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
1612 struct file_operations *seq_fops,
1615 return (lprocfs_seq_create(dev->obd_proc_entry, name,
1616 mode, seq_fops, data));
1618 EXPORT_SYMBOL(lprocfs_obd_seq_create);
1620 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
1622 if (value >= OBD_HIST_MAX)
1623 value = OBD_HIST_MAX - 1;
1625 spin_lock(&oh->oh_lock);
1626 oh->oh_buckets[value]++;
1627 spin_unlock(&oh->oh_lock);
1629 EXPORT_SYMBOL(lprocfs_oh_tally);
1631 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
1635 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
1638 lprocfs_oh_tally(oh, val);
1640 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
1642 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
1644 unsigned long ret = 0;
1647 for (i = 0; i < OBD_HIST_MAX; i++)
1648 ret += oh->oh_buckets[i];
1651 EXPORT_SYMBOL(lprocfs_oh_sum);
1653 void lprocfs_oh_clear(struct obd_histogram *oh)
1655 spin_lock(&oh->oh_lock);
1656 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
1657 spin_unlock(&oh->oh_lock);
1659 EXPORT_SYMBOL(lprocfs_oh_clear);
1661 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
1662 int count, int *eof, void *data)
1664 struct obd_device *obd = data;
1667 LASSERT(obd != NULL);
1668 LASSERT(count >= 0);
1670 /* Set start of user data returned to
1671 page + off since the user may have
1672 requested to read much smaller than
1673 what we need to read */
1674 *start = page + off;
1676 /* We know we are allocated a page here.
1677 Also we know that this function will
1678 not need to write more than a page
1679 so we can truncate at CFS_PAGE_SIZE. */
1680 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
1682 /* Initialize the page */
1683 memset(page, 0, size);
1685 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
1688 if (obd->obd_max_recoverable_clients == 0) {
1689 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
1695 /* sampled unlocked, but really... */
1696 if (obd->obd_recovering == 0) {
1697 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
1700 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
1701 obd->obd_recovery_start) <= 0)
1704 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_end: %lu\n",
1705 obd->obd_recovery_end) <= 0)
1708 /* Number of clients have have completed recovery */
1709 if (lprocfs_obd_snprintf(&page, size, &len, "recovered_clients: %d\n",
1710 obd->obd_max_recoverable_clients - obd->obd_recoverable_clients) <= 0)
1713 if (lprocfs_obd_snprintf(&page, size, &len, "unrecovered_clients: %d\n",
1714 obd->obd_recoverable_clients) <= 0)
1717 if (lprocfs_obd_snprintf(&page, size, &len, "last_transno: "LPD64"\n",
1718 obd->obd_next_recovery_transno - 1) <= 0)
1721 lprocfs_obd_snprintf(&page, size, &len, "replayed_requests: %d\n", obd->obd_replayed_requests);
1725 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
1728 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
1729 obd->obd_recovery_start) <= 0)
1732 if (lprocfs_obd_snprintf(&page, size, &len, "time remaining: %lu\n",
1733 cfs_time_current_sec() >= obd->obd_recovery_end ? 0 :
1734 obd->obd_recovery_end - cfs_time_current_sec()) <= 0)
1737 if(lprocfs_obd_snprintf(&page, size, &len, "connected_clients: %d/%d\n",
1738 obd->obd_connected_clients,
1739 obd->obd_max_recoverable_clients) <= 0)
1742 /* Number of clients have have completed recovery */
1743 if (lprocfs_obd_snprintf(&page, size, &len, "completed_clients: %d/%d\n",
1744 obd->obd_max_recoverable_clients - obd->obd_recoverable_clients,
1745 obd->obd_max_recoverable_clients) <= 0)
1748 if (lprocfs_obd_snprintf(&page, size, &len, "replayed_requests: %d/??\n",
1749 obd->obd_replayed_requests) <= 0)
1752 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
1753 obd->obd_requests_queued_for_recovery) <= 0)
1756 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
1757 obd->obd_next_recovery_transno) <= 0)
1763 return min(count, len - (int)off);
1765 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
1767 int lprocfs_obd_rd_recovery_maxtime(char *page, char **start, off_t off,
1768 int count, int *eof, void *data)
1770 struct obd_device *obd = (struct obd_device *)data;
1771 LASSERT(obd != NULL);
1773 return snprintf(page, count, "%lu\n",
1774 obd->obd_recovery_max_time);
1776 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_maxtime);
1778 int lprocfs_obd_wr_recovery_maxtime(struct file *file, const char *buffer,
1779 unsigned long count, void *data)
1781 struct obd_device *obd = (struct obd_device *)data;
1783 LASSERT(obd != NULL);
1785 rc = lprocfs_write_helper(buffer, count, &val);
1789 obd->obd_recovery_max_time = val;
1792 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_maxtime);
1794 EXPORT_SYMBOL(lprocfs_register);
1795 EXPORT_SYMBOL(lprocfs_srch);
1796 EXPORT_SYMBOL(lprocfs_remove);
1797 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
1798 EXPORT_SYMBOL(lprocfs_add_vars);
1799 EXPORT_SYMBOL(lprocfs_obd_setup);
1800 EXPORT_SYMBOL(lprocfs_obd_cleanup);
1801 EXPORT_SYMBOL(lprocfs_add_simple);
1802 EXPORT_SYMBOL(lprocfs_add_symlink);
1803 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
1804 EXPORT_SYMBOL(lprocfs_alloc_stats);
1805 EXPORT_SYMBOL(lprocfs_free_stats);
1806 EXPORT_SYMBOL(lprocfs_clear_stats);
1807 EXPORT_SYMBOL(lprocfs_register_stats);
1808 EXPORT_SYMBOL(lprocfs_init_ops_stats);
1809 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
1810 EXPORT_SYMBOL(lprocfs_free_obd_stats);
1811 EXPORT_SYMBOL(lprocfs_exp_setup);
1812 EXPORT_SYMBOL(lprocfs_exp_cleanup);
1814 EXPORT_SYMBOL(lprocfs_rd_u64);
1815 EXPORT_SYMBOL(lprocfs_rd_atomic);
1816 EXPORT_SYMBOL(lprocfs_wr_atomic);
1817 EXPORT_SYMBOL(lprocfs_rd_uint);
1818 EXPORT_SYMBOL(lprocfs_wr_uint);
1819 EXPORT_SYMBOL(lprocfs_rd_uuid);
1820 EXPORT_SYMBOL(lprocfs_rd_name);
1821 EXPORT_SYMBOL(lprocfs_rd_fstype);
1822 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
1823 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
1824 EXPORT_SYMBOL(lprocfs_rd_num_exports);
1825 EXPORT_SYMBOL(lprocfs_rd_numrefs);
1827 EXPORT_SYMBOL(lprocfs_rd_blksize);
1828 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
1829 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
1830 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
1831 EXPORT_SYMBOL(lprocfs_rd_filestotal);
1832 EXPORT_SYMBOL(lprocfs_rd_filesfree);
1834 EXPORT_SYMBOL(lprocfs_write_helper);
1835 EXPORT_SYMBOL(lprocfs_write_frac_helper);
1836 EXPORT_SYMBOL(lprocfs_read_frac_helper);
1837 EXPORT_SYMBOL(lprocfs_write_u64_helper);
1838 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);