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 void lprocfs_free_client_stats(void *obj, void *data)
716 struct nid_stat *client_stat = obj;
718 CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
719 client_stat->nid_proc, client_stat->nid_stats,
720 client_stat->nid_brw_stats);
722 LASSERTF(client_stat->nid_exp_ref_count == 0, "count %d\n",
723 client_stat->nid_exp_ref_count);
725 hlist_del_init(&client_stat->nid_hash);
726 list_del(&client_stat->nid_list);
728 if (client_stat->nid_proc)
729 lprocfs_remove(&client_stat->nid_proc);
731 if (client_stat->nid_stats)
732 lprocfs_free_stats(&client_stat->nid_stats);
734 if (client_stat->nid_brw_stats)
735 OBD_FREE(client_stat->nid_brw_stats, sizeof(struct brw_stats));
737 OBD_FREE(client_stat, sizeof(*client_stat));
742 void lprocfs_free_per_client_stats(struct obd_device *obd)
744 struct nid_stat *stat;
747 /* we need extra list - because hash_exit called to early */
748 while(!list_empty(&obd->obd_nid_stats)) {
749 stat = list_entry(obd->obd_nid_stats.next,
750 struct nid_stat, nid_list);
751 lprocfs_free_client_stats(stat, NULL);
757 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
758 enum lprocfs_stats_flags flags)
760 struct lprocfs_stats *stats;
761 unsigned int percpusize;
763 unsigned int num_cpu;
768 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
771 num_cpu = num_possible_cpus();
773 OBD_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
777 if (flags & LPROCFS_STATS_FLAG_NOPERCPU) {
778 stats->ls_flags = flags;
779 spin_lock_init(&stats->ls_lock);
780 /* Use this lock only if there are no percpu areas */
785 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]);
787 percpusize = L1_CACHE_ALIGN(percpusize);
789 for (i = 0; i < num_cpu; i++) {
790 OBD_ALLOC(stats->ls_percpu[i], percpusize);
791 if (stats->ls_percpu[i] == NULL) {
792 for (j = 0; j < i; j++) {
793 OBD_FREE(stats->ls_percpu[j], percpusize);
794 stats->ls_percpu[j] = NULL;
799 if (stats->ls_percpu[0] == NULL) {
800 OBD_FREE(stats, offsetof(typeof(*stats),
801 ls_percpu[num_cpu]));
809 void lprocfs_free_stats(struct lprocfs_stats **statsh)
811 struct lprocfs_stats *stats = *statsh;
812 unsigned int num_cpu;
813 unsigned int percpusize;
816 if (stats == NULL || stats->ls_num == 0)
820 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
823 num_cpu = num_possible_cpus();
825 percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]);
827 percpusize = L1_CACHE_ALIGN(percpusize);
828 for (i = 0; i < num_cpu; i++)
829 OBD_FREE(stats->ls_percpu[i], percpusize);
830 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
833 void lprocfs_clear_stats(struct lprocfs_stats *stats)
835 struct lprocfs_counter *percpu_cntr;
837 unsigned int num_cpu;
839 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
841 for (i = 0; i < num_cpu; i++) {
842 for (j = 0; j < stats->ls_num; j++) {
843 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
844 atomic_inc(&percpu_cntr->lc_cntl.la_entry);
845 percpu_cntr->lc_count = 0;
846 percpu_cntr->lc_sum = 0;
847 percpu_cntr->lc_min = LC_MIN_INIT;
848 percpu_cntr->lc_max = 0;
849 percpu_cntr->lc_sumsquare = 0;
850 atomic_inc(&percpu_cntr->lc_cntl.la_exit);
854 lprocfs_stats_unlock(stats);
857 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
858 size_t len, loff_t *off)
860 struct seq_file *seq = file->private_data;
861 struct lprocfs_stats *stats = seq->private;
863 lprocfs_clear_stats(stats);
868 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
870 struct lprocfs_stats *stats = p->private;
871 /* return 1st cpu location */
872 return (*pos >= stats->ls_num) ? NULL :
873 &(stats->ls_percpu[0]->lp_cntr[*pos]);
876 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
880 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
882 struct lprocfs_stats *stats = p->private;
884 return (*pos >= stats->ls_num) ? NULL :
885 &(stats->ls_percpu[0]->lp_cntr[*pos]);
888 /* seq file export of one lprocfs counter */
889 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
891 struct lprocfs_stats *stats = p->private;
892 struct lprocfs_counter *cntr = v;
893 struct lprocfs_counter t, ret = { .lc_min = LC_MIN_INIT };
895 unsigned int num_cpu;
897 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
899 do_gettimeofday(&now);
900 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
901 "snapshot_time", now.tv_sec, now.tv_usec);
905 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
907 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
910 num_cpu = num_possible_cpus();
912 for (i = 0; i < num_cpu; i++) {
913 struct lprocfs_counter *percpu_cntr =
914 &(stats->ls_percpu[i])->lp_cntr[idx];
918 centry = atomic_read(&percpu_cntr->lc_cntl.la_entry);
919 t.lc_count = percpu_cntr->lc_count;
920 t.lc_sum = percpu_cntr->lc_sum;
921 t.lc_min = percpu_cntr->lc_min;
922 t.lc_max = percpu_cntr->lc_max;
923 t.lc_sumsquare = percpu_cntr->lc_sumsquare;
924 } while (centry != atomic_read(&percpu_cntr->lc_cntl.la_entry) &&
925 centry != atomic_read(&percpu_cntr->lc_cntl.la_exit));
926 ret.lc_count += t.lc_count;
927 ret.lc_sum += t.lc_sum;
928 if (t.lc_min < ret.lc_min)
929 ret.lc_min = t.lc_min;
930 if (t.lc_max > ret.lc_max)
931 ret.lc_max = t.lc_max;
932 ret.lc_sumsquare += t.lc_sumsquare;
935 rc = seq_printf(p, "%-25s "LPD64" samples [%s]", cntr->lc_name,
936 ret.lc_count, cntr->lc_units);
940 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
941 rc = seq_printf(p, " "LPD64" "LPD64" "LPD64,
942 ret.lc_min, ret.lc_max, ret.lc_sum);
945 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
946 rc = seq_printf(p, " "LPD64, ret.lc_sumsquare);
950 rc = seq_printf(p, "\n");
952 return (rc < 0) ? rc : 0;
955 struct seq_operations lprocfs_stats_seq_sops = {
956 start: lprocfs_stats_seq_start,
957 stop: lprocfs_stats_seq_stop,
958 next: lprocfs_stats_seq_next,
959 show: lprocfs_stats_seq_show,
962 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
964 struct proc_dir_entry *dp = PDE(inode);
965 struct seq_file *seq;
968 LPROCFS_ENTRY_AND_CHECK(dp);
969 rc = seq_open(file, &lprocfs_stats_seq_sops);
974 seq = file->private_data;
975 seq->private = dp->data;
979 struct file_operations lprocfs_stats_seq_fops = {
980 .owner = THIS_MODULE,
981 .open = lprocfs_stats_seq_open,
983 .write = lprocfs_stats_seq_write,
985 .release = lprocfs_seq_release,
988 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
989 struct lprocfs_stats *stats)
991 struct proc_dir_entry *entry;
992 LASSERT(root != NULL);
994 entry = create_proc_entry(name, 0644, root);
997 entry->proc_fops = &lprocfs_stats_seq_fops;
998 entry->data = (void *)stats;
1002 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1003 unsigned conf, const char *name, const char *units)
1005 struct lprocfs_counter *c;
1007 unsigned int num_cpu;
1009 LASSERT(stats != NULL);
1011 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
1013 for (i = 0; i < num_cpu; i++) {
1014 c = &(stats->ls_percpu[i]->lp_cntr[index]);
1015 c->lc_config = conf;
1018 c->lc_min = LC_MIN_INIT;
1021 c->lc_units = units;
1024 lprocfs_stats_unlock(stats);
1026 EXPORT_SYMBOL(lprocfs_counter_init);
1028 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
1030 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
1031 LASSERT(coffset < stats->ls_num); \
1032 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1035 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
1037 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
1038 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
1039 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
1040 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
1041 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
1042 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
1043 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
1044 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
1045 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
1046 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
1047 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
1048 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
1049 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
1050 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
1051 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
1052 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
1053 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
1054 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
1055 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
1056 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
1057 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
1058 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
1059 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
1060 LPROCFS_OBD_OP_INIT(num_private_stats, stats, checkmd);
1061 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
1062 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
1063 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
1064 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
1065 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
1066 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
1067 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
1068 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
1069 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
1070 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw_async);
1071 LPROCFS_OBD_OP_INIT(num_private_stats, stats, prep_async_page);
1072 LPROCFS_OBD_OP_INIT(num_private_stats, stats, queue_async_io);
1073 LPROCFS_OBD_OP_INIT(num_private_stats, stats, queue_group_io);
1074 LPROCFS_OBD_OP_INIT(num_private_stats, stats, trigger_group_io);
1075 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_async_flags);
1076 LPROCFS_OBD_OP_INIT(num_private_stats, stats, teardown_async_page);
1077 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
1078 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1079 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1080 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1081 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1082 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1083 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1084 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1085 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1086 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1087 LPROCFS_OBD_OP_INIT(num_private_stats, stats, match);
1088 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1089 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1090 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1091 LPROCFS_OBD_OP_INIT(num_private_stats, stats, join_lru);
1092 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1093 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1094 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1095 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1096 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1097 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1098 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1099 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1100 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1101 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1102 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1103 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1104 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1105 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1108 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1110 struct lprocfs_stats *stats;
1111 unsigned int num_stats;
1114 LASSERT(obd->obd_stats == NULL);
1115 LASSERT(obd->obd_proc_entry != NULL);
1116 LASSERT(obd->obd_cntr_base == 0);
1118 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1119 num_private_stats - 1 /* o_owner */;
1120 stats = lprocfs_alloc_stats(num_stats, 0);
1124 lprocfs_init_ops_stats(num_private_stats, stats);
1126 for (i = num_private_stats; i < num_stats; i++) {
1127 /* If this LBUGs, it is likely that an obd
1128 * operation was added to struct obd_ops in
1129 * <obd.h>, and that the corresponding line item
1130 * LPROCFS_OBD_OP_INIT(.., .., opname)
1131 * is missing from the list above. */
1132 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1133 "Missing obd_stat initializer obd_op "
1134 "operation at offset %d.\n", i - num_private_stats);
1136 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1138 lprocfs_free_stats(&stats);
1140 obd->obd_stats = stats;
1141 obd->obd_cntr_base = num_private_stats;
1146 void lprocfs_free_obd_stats(struct obd_device *obd)
1149 lprocfs_free_stats(&obd->obd_stats);
1152 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1154 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1155 LASSERT(coffset < stats->ls_num); \
1156 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1159 int lprocfs_alloc_md_stats(struct obd_device *obd,
1160 unsigned num_private_stats)
1162 struct lprocfs_stats *stats;
1163 unsigned int num_stats;
1166 LASSERT(obd->md_stats == NULL);
1167 LASSERT(obd->obd_proc_entry != NULL);
1168 LASSERT(obd->md_cntr_base == 0);
1170 num_stats = 1 + MD_COUNTER_OFFSET(get_remote_perm) +
1172 stats = lprocfs_alloc_stats(num_stats, 0);
1176 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1177 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1178 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1179 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1180 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1181 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1182 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1183 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1184 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1185 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1186 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1187 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1188 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1189 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1190 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1191 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1192 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1193 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1194 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1195 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1196 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1197 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1198 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1199 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1200 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1201 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1202 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1203 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1205 for (i = num_private_stats; i < num_stats; i++) {
1206 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1207 CERROR("Missing md_stat initializer md_op "
1208 "operation at offset %d. Aborting.\n",
1209 i - num_private_stats);
1213 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1215 lprocfs_free_stats(&stats);
1217 obd->md_stats = stats;
1218 obd->md_cntr_base = num_private_stats;
1223 void lprocfs_free_md_stats(struct obd_device *obd)
1225 struct lprocfs_stats *stats = obd->md_stats;
1227 if (stats != NULL) {
1228 obd->md_stats = NULL;
1229 lprocfs_free_stats(&stats);
1233 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1234 int *eof, void *data)
1236 struct obd_export *exp = (struct obd_export*)data;
1237 LASSERT(exp != NULL);
1239 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1242 struct exp_uuid_cb_data {
1249 void lprocfs_exp_print_uuid(void *obj, void *cb_data)
1251 struct obd_export *exp = (struct obd_export *)obj;
1252 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1254 if (exp->exp_nid_stats)
1255 *data->len += snprintf((data->page + *data->len),
1256 data->count, "%s\n",
1257 obd_uuid2str(&exp->exp_client_uuid));
1260 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1261 int *eof, void *data)
1263 struct nid_stat *stats = (struct nid_stat *)data;
1264 struct exp_uuid_cb_data cb_data;
1265 struct obd_device *obd = stats->nid_obd;
1270 LASSERT(obd != NULL);
1272 cb_data.page = page;
1273 cb_data.count = count;
1276 lustre_hash_bucket_iterate(obd->obd_nid_hash_body,
1277 &stats->nid, lprocfs_exp_print_uuid,
1279 return (*cb_data.len);
1282 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1283 int count, int *eof, void *data)
1286 return snprintf(page, count, "%s\n",
1287 "Write into this file to clear all nid stats and "
1288 "stale nid entries");
1290 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1292 void lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1294 struct nid_stat *client_stat = obj;
1296 if(client_stat->nid_exp_ref_count == 1) {
1297 hlist_del_init(&client_stat->nid_hash);
1298 lprocfs_free_client_stats(client_stat, data);
1299 OBD_FREE(client_stat, sizeof(struct nid_stat));
1304 /* we has reference to object - only clear data*/
1305 if (client_stat->nid_stats) {
1306 lprocfs_clear_stats(client_stat->nid_stats);
1308 if (client_stat->nid_brw_stats) {
1309 for (i = 0; i < BRW_LAST; i++)
1310 lprocfs_oh_clear(&client_stat->nid_brw_stats->hist[i]);
1316 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1317 unsigned long count, void *data)
1319 struct obd_device *obd = (struct obd_device *)data;
1320 lustre_hash_iterate_all(obd->obd_nid_stats_hash_body,
1321 lprocfs_free_client_stats, NULL);
1324 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1326 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1329 struct nid_stat *tmp = NULL, *tmp1;
1330 struct obd_device *obd = NULL;
1335 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1336 !exp->exp_obd->obd_nid_stats_hash_body)
1339 /* not test against zero because eric say:
1340 * You may only test nid against another nid, or LNET_NID_ANY. Anything else is
1342 if (!nid || *nid == LNET_NID_ANY)
1347 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash_body);
1349 OBD_ALLOC(tmp, sizeof(struct nid_stat));
1354 tmp->nid_obd = exp->exp_obd;
1355 tmp->nid_exp_ref_count = 1; /* need live in hash after destroy export */
1357 tmp1= lustre_hash_findadd_unique(obd->obd_nid_stats_hash_body, nid,
1359 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
1360 tmp1, libcfs_nid2str(*nid), tmp->nid_exp_ref_count);
1363 exp->exp_nid_stats = tmp1;
1364 GOTO(destroy_new, rc = 0);
1366 /* not found - create */
1367 tmp->nid_proc = lprocfs_register(libcfs_nid2str(*nid),
1368 obd->obd_proc_exports_entry, NULL, NULL);
1369 if (!tmp->nid_proc) {
1370 CERROR("Error making export directory for"
1371 " nid %s\n", libcfs_nid2str(*nid));
1372 lustre_hash_delitem(obd->obd_nid_stats_hash_body, nid,
1374 GOTO(destroy_new, rc = -ENOMEM);
1377 rc = lprocfs_add_simple(tmp->nid_proc, "uuid",
1378 lprocfs_exp_rd_uuid, NULL, tmp);
1380 CWARN("Error adding the uuid file\n");
1382 spin_lock(&obd->obd_nid_lock);
1383 list_add(&tmp->nid_list, &obd->obd_nid_stats);
1384 spin_unlock(&obd->obd_nid_lock);
1386 exp->exp_nid_stats = tmp;
1391 OBD_FREE(tmp, sizeof(struct nid_stat));
1395 int lprocfs_exp_cleanup(struct obd_export *exp)
1397 struct nid_stat *stat = exp->exp_nid_stats;
1402 stat->nid_exp_ref_count--;
1403 CDEBUG(D_INFO, "Put stat %p - %d\n", stat, stat->nid_exp_ref_count);
1405 exp->exp_nid_stats = NULL;
1409 int lprocfs_write_helper(const char *buffer, unsigned long count,
1412 return lprocfs_write_frac_helper(buffer, count, val, 1);
1415 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
1418 char kernbuf[20], *end, *pbuf;
1420 if (count > (sizeof(kernbuf) - 1))
1423 if (copy_from_user(kernbuf, buffer, count))
1426 kernbuf[count] = '\0';
1433 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1437 if (end != NULL && *end == '.') {
1438 int temp_val, pow = 1;
1442 if (strlen(pbuf) > 5)
1443 pbuf[5] = '\0'; /*only allow 5bits fractional*/
1445 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1448 for (i = 0; i < (end - pbuf); i++)
1451 *val += temp_val / pow;
1457 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val, int mult)
1459 long decimal_val, frac_val;
1465 decimal_val = val / mult;
1466 prtn = snprintf(buffer, count, "%ld", decimal_val);
1467 frac_val = val % mult;
1469 if (prtn < (count - 4) && frac_val > 0) {
1471 int i, temp_mult = 1, frac_bits = 0;
1473 temp_frac = frac_val * 10;
1474 buffer[prtn++] = '.';
1475 while (frac_bits < 2 && (temp_frac / mult) < 1 ) { /*only reserved 2bits fraction*/
1476 buffer[prtn++] ='0';
1481 Need to think these cases :
1482 1. #echo x.00 > /proc/xxx output result : x
1483 2. #echo x.0x > /proc/xxx output result : x.0x
1484 3. #echo x.x0 > /proc/xxx output result : x.x
1485 4. #echo x.xx > /proc/xxx output result : x.xx
1486 Only reserved 2bits fraction.
1488 for (i = 0; i < (5 - prtn); i++)
1491 frac_bits = min((int)count - prtn, 3 - frac_bits);
1492 prtn += snprintf(buffer + prtn, frac_bits, "%ld", frac_val * temp_mult / mult);
1495 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
1497 if (buffer[prtn] == '.') {
1504 buffer[prtn++] ='\n';
1508 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
1510 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
1513 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
1514 __u64 *val, int mult)
1516 char kernbuf[22], *end, *pbuf;
1517 __u64 whole, frac = 0, units;
1518 unsigned frac_d = 1;
1520 if (count > (sizeof(kernbuf) - 1) )
1523 if (copy_from_user(kernbuf, buffer, count))
1526 kernbuf[count] = '\0';
1533 whole = simple_strtoull(pbuf, &end, 10);
1537 if (end != NULL && *end == '.') {
1541 /* need to limit frac_d to a __u32 */
1542 if (strlen(pbuf) > 10)
1545 frac = simple_strtoull(pbuf, &end, 10);
1546 /* count decimal places */
1547 for (i = 0; i < (end - pbuf); i++)
1564 /* Specified units override the multiplier */
1566 mult = mult < 0 ? -units : units;
1569 do_div(frac, frac_d);
1570 *val = whole * mult + frac;
1574 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent,
1575 char *name, mode_t mode,
1576 struct file_operations *seq_fops, void *data)
1578 struct proc_dir_entry *entry;
1581 entry = create_proc_entry(name, mode, parent);
1584 entry->proc_fops = seq_fops;
1589 EXPORT_SYMBOL(lprocfs_seq_create);
1591 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
1593 struct file_operations *seq_fops,
1596 return (lprocfs_seq_create(dev->obd_proc_entry, name,
1597 mode, seq_fops, data));
1599 EXPORT_SYMBOL(lprocfs_obd_seq_create);
1601 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
1603 if (value >= OBD_HIST_MAX)
1604 value = OBD_HIST_MAX - 1;
1606 spin_lock(&oh->oh_lock);
1607 oh->oh_buckets[value]++;
1608 spin_unlock(&oh->oh_lock);
1610 EXPORT_SYMBOL(lprocfs_oh_tally);
1612 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
1616 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
1619 lprocfs_oh_tally(oh, val);
1621 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
1623 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
1625 unsigned long ret = 0;
1628 for (i = 0; i < OBD_HIST_MAX; i++)
1629 ret += oh->oh_buckets[i];
1632 EXPORT_SYMBOL(lprocfs_oh_sum);
1634 void lprocfs_oh_clear(struct obd_histogram *oh)
1636 spin_lock(&oh->oh_lock);
1637 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
1638 spin_unlock(&oh->oh_lock);
1640 EXPORT_SYMBOL(lprocfs_oh_clear);
1642 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
1643 int count, int *eof, void *data)
1645 struct obd_device *obd = data;
1648 LASSERT(obd != NULL);
1649 LASSERT(count >= 0);
1651 /* Set start of user data returned to
1652 page + off since the user may have
1653 requested to read much smaller than
1654 what we need to read */
1655 *start = page + off;
1657 /* We know we are allocated a page here.
1658 Also we know that this function will
1659 not need to write more than a page
1660 so we can truncate at CFS_PAGE_SIZE. */
1661 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
1663 /* Initialize the page */
1664 memset(page, 0, size);
1666 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
1669 if (obd->obd_max_recoverable_clients == 0) {
1670 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
1676 /* sampled unlocked, but really... */
1677 if (obd->obd_recovering == 0) {
1678 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
1681 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
1682 obd->obd_recovery_start) <= 0)
1685 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_end: %lu\n",
1686 obd->obd_recovery_end) <= 0)
1689 /* Number of clients have have completed recovery */
1690 if (lprocfs_obd_snprintf(&page, size, &len, "recovered_clients: %d\n",
1691 obd->obd_max_recoverable_clients - obd->obd_recoverable_clients) <= 0)
1694 if (lprocfs_obd_snprintf(&page, size, &len, "unrecovered_clients: %d\n",
1695 obd->obd_recoverable_clients) <= 0)
1698 if (lprocfs_obd_snprintf(&page, size, &len, "last_transno: "LPD64"\n",
1699 obd->obd_next_recovery_transno - 1) <= 0)
1702 lprocfs_obd_snprintf(&page, size, &len, "replayed_requests: %d\n", obd->obd_replayed_requests);
1706 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
1709 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
1710 obd->obd_recovery_start) <= 0)
1713 if (lprocfs_obd_snprintf(&page, size, &len, "time remaining: %lu\n",
1714 cfs_time_current_sec() >= obd->obd_recovery_end ? 0 :
1715 obd->obd_recovery_end - cfs_time_current_sec()) <= 0)
1718 if(lprocfs_obd_snprintf(&page, size, &len, "connected_clients: %d/%d\n",
1719 obd->obd_connected_clients,
1720 obd->obd_max_recoverable_clients) <= 0)
1723 /* Number of clients have have completed recovery */
1724 if (lprocfs_obd_snprintf(&page, size, &len, "completed_clients: %d/%d\n",
1725 obd->obd_max_recoverable_clients - obd->obd_recoverable_clients,
1726 obd->obd_max_recoverable_clients) <= 0)
1729 if (lprocfs_obd_snprintf(&page, size, &len, "replayed_requests: %d/??\n",
1730 obd->obd_replayed_requests) <= 0)
1733 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
1734 obd->obd_requests_queued_for_recovery) <= 0)
1737 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
1738 obd->obd_next_recovery_transno) <= 0)
1744 return min(count, len - (int)off);
1746 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
1748 int lprocfs_obd_rd_recovery_maxtime(char *page, char **start, off_t off,
1749 int count, int *eof, void *data)
1751 struct obd_device *obd = (struct obd_device *)data;
1752 LASSERT(obd != NULL);
1754 return snprintf(page, count, "%lu\n",
1755 obd->obd_recovery_max_time);
1757 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_maxtime);
1759 int lprocfs_obd_wr_recovery_maxtime(struct file *file, const char *buffer,
1760 unsigned long count, void *data)
1762 struct obd_device *obd = (struct obd_device *)data;
1764 LASSERT(obd != NULL);
1766 rc = lprocfs_write_helper(buffer, count, &val);
1770 obd->obd_recovery_max_time = val;
1773 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_maxtime);
1775 EXPORT_SYMBOL(lprocfs_register);
1776 EXPORT_SYMBOL(lprocfs_srch);
1777 EXPORT_SYMBOL(lprocfs_remove);
1778 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
1779 EXPORT_SYMBOL(lprocfs_add_vars);
1780 EXPORT_SYMBOL(lprocfs_obd_setup);
1781 EXPORT_SYMBOL(lprocfs_obd_cleanup);
1782 EXPORT_SYMBOL(lprocfs_add_simple);
1783 EXPORT_SYMBOL(lprocfs_add_symlink);
1784 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
1785 EXPORT_SYMBOL(lprocfs_alloc_stats);
1786 EXPORT_SYMBOL(lprocfs_free_stats);
1787 EXPORT_SYMBOL(lprocfs_clear_stats);
1788 EXPORT_SYMBOL(lprocfs_register_stats);
1789 EXPORT_SYMBOL(lprocfs_init_ops_stats);
1790 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
1791 EXPORT_SYMBOL(lprocfs_free_obd_stats);
1792 EXPORT_SYMBOL(lprocfs_exp_setup);
1793 EXPORT_SYMBOL(lprocfs_exp_cleanup);
1795 EXPORT_SYMBOL(lprocfs_rd_u64);
1796 EXPORT_SYMBOL(lprocfs_rd_atomic);
1797 EXPORT_SYMBOL(lprocfs_wr_atomic);
1798 EXPORT_SYMBOL(lprocfs_rd_uint);
1799 EXPORT_SYMBOL(lprocfs_wr_uint);
1800 EXPORT_SYMBOL(lprocfs_rd_uuid);
1801 EXPORT_SYMBOL(lprocfs_rd_name);
1802 EXPORT_SYMBOL(lprocfs_rd_fstype);
1803 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
1804 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
1805 EXPORT_SYMBOL(lprocfs_rd_num_exports);
1806 EXPORT_SYMBOL(lprocfs_rd_numrefs);
1808 EXPORT_SYMBOL(lprocfs_rd_blksize);
1809 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
1810 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
1811 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
1812 EXPORT_SYMBOL(lprocfs_rd_filestotal);
1813 EXPORT_SYMBOL(lprocfs_rd_filesfree);
1815 EXPORT_SYMBOL(lprocfs_write_helper);
1816 EXPORT_SYMBOL(lprocfs_write_frac_helper);
1817 EXPORT_SYMBOL(lprocfs_read_frac_helper);
1818 EXPORT_SYMBOL(lprocfs_write_u64_helper);
1819 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);