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);
1105 LPROCFS_OBD_OP_INIT(num_private_stats, stats, register_page_removal_cb);
1106 LPROCFS_OBD_OP_INIT(num_private_stats,stats,unregister_page_removal_cb);
1107 LPROCFS_OBD_OP_INIT(num_private_stats, stats, register_lock_cancel_cb);
1108 LPROCFS_OBD_OP_INIT(num_private_stats, stats,unregister_lock_cancel_cb);
1111 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1113 struct lprocfs_stats *stats;
1114 unsigned int num_stats;
1117 LASSERT(obd->obd_stats == NULL);
1118 LASSERT(obd->obd_proc_entry != NULL);
1119 LASSERT(obd->obd_cntr_base == 0);
1121 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1122 num_private_stats - 1 /* o_owner */;
1123 stats = lprocfs_alloc_stats(num_stats, 0);
1127 lprocfs_init_ops_stats(num_private_stats, stats);
1129 for (i = num_private_stats; i < num_stats; i++) {
1130 /* If this LBUGs, it is likely that an obd
1131 * operation was added to struct obd_ops in
1132 * <obd.h>, and that the corresponding line item
1133 * LPROCFS_OBD_OP_INIT(.., .., opname)
1134 * is missing from the list above. */
1135 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1136 "Missing obd_stat initializer obd_op "
1137 "operation at offset %d.\n", i - num_private_stats);
1139 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1141 lprocfs_free_stats(&stats);
1143 obd->obd_stats = stats;
1144 obd->obd_cntr_base = num_private_stats;
1149 void lprocfs_free_obd_stats(struct obd_device *obd)
1152 lprocfs_free_stats(&obd->obd_stats);
1155 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1157 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1158 LASSERT(coffset < stats->ls_num); \
1159 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1162 int lprocfs_alloc_md_stats(struct obd_device *obd,
1163 unsigned num_private_stats)
1165 struct lprocfs_stats *stats;
1166 unsigned int num_stats;
1169 LASSERT(obd->md_stats == NULL);
1170 LASSERT(obd->obd_proc_entry != NULL);
1171 LASSERT(obd->md_cntr_base == 0);
1173 num_stats = 1 + MD_COUNTER_OFFSET(get_remote_perm) +
1175 stats = lprocfs_alloc_stats(num_stats, 0);
1179 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1180 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1181 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1182 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1183 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1184 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1185 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1186 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1187 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1188 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1189 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1190 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1191 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1192 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1193 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1194 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1195 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1196 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1197 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1198 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1199 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1200 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1201 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1202 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1203 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1204 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1205 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1206 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1207 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async);
1208 LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock);
1210 for (i = num_private_stats; i < num_stats; i++) {
1211 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1212 CERROR("Missing md_stat initializer md_op "
1213 "operation at offset %d. Aborting.\n",
1214 i - num_private_stats);
1218 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1220 lprocfs_free_stats(&stats);
1222 obd->md_stats = stats;
1223 obd->md_cntr_base = num_private_stats;
1228 void lprocfs_free_md_stats(struct obd_device *obd)
1230 struct lprocfs_stats *stats = obd->md_stats;
1232 if (stats != NULL) {
1233 obd->md_stats = NULL;
1234 lprocfs_free_stats(&stats);
1238 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1239 int *eof, void *data)
1241 struct obd_export *exp = (struct obd_export*)data;
1242 LASSERT(exp != NULL);
1244 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1247 struct exp_uuid_cb_data {
1254 void lprocfs_exp_print_uuid(void *obj, void *cb_data)
1256 struct obd_export *exp = (struct obd_export *)obj;
1257 struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
1259 if (exp->exp_nid_stats)
1260 *data->len += snprintf((data->page + *data->len),
1261 data->count, "%s\n",
1262 obd_uuid2str(&exp->exp_client_uuid));
1265 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1266 int *eof, void *data)
1268 struct nid_stat *stats = (struct nid_stat *)data;
1269 struct exp_uuid_cb_data cb_data;
1270 struct obd_device *obd = stats->nid_obd;
1275 LASSERT(obd != NULL);
1277 cb_data.page = page;
1278 cb_data.count = count;
1281 lustre_hash_bucket_iterate(obd->obd_nid_hash_body,
1282 &stats->nid, lprocfs_exp_print_uuid,
1284 return (*cb_data.len);
1287 int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
1288 int count, int *eof, void *data)
1291 return snprintf(page, count, "%s\n",
1292 "Write into this file to clear all nid stats and "
1293 "stale nid entries");
1295 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
1297 void lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
1299 struct nid_stat *stat = obj;
1302 /* object has only hash + iterate_all references.
1303 * add/delete blocked by hash bucket lock */
1304 CDEBUG(D_INFO,"refcnt %d\n", stat->nid_exp_ref_count);
1305 if(stat->nid_exp_ref_count == 2) {
1306 hlist_del_init(&stat->nid_hash);
1307 stat->nid_exp_ref_count--;
1308 spin_lock(&stat->nid_obd->obd_nid_lock);
1309 list_del_init(&stat->nid_list);
1310 spin_unlock(&stat->nid_obd->obd_nid_lock);
1311 list_add(&stat->nid_list, data);
1315 /* we has reference to object - only clear data*/
1316 if (stat->nid_stats)
1317 lprocfs_clear_stats(stat->nid_stats);
1319 if (stat->nid_brw_stats) {
1320 for (i = 0; i < BRW_LAST; i++)
1321 lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]);
1327 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
1328 unsigned long count, void *data)
1330 struct obd_device *obd = (struct obd_device *)data;
1331 struct nid_stat *client_stat;
1332 CFS_LIST_HEAD(free_list);
1334 lustre_hash_iterate_all(obd->obd_nid_stats_hash_body,
1335 lprocfs_nid_stats_clear_write_cb, &free_list);
1337 while (!list_empty(&free_list)) {
1338 client_stat = list_entry(free_list.next, struct nid_stat, nid_list);
1339 list_del_init(&client_stat->nid_list);
1340 lprocfs_free_client_stats(client_stat);
1345 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
1347 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
1350 struct nid_stat *tmp = NULL, *tmp1;
1351 struct obd_device *obd = NULL;
1356 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
1357 !exp->exp_obd->obd_nid_stats_hash_body)
1360 /* not test against zero because eric say:
1361 * You may only test nid against another nid, or LNET_NID_ANY. Anything else is
1363 if (!nid || *nid == LNET_NID_ANY)
1368 CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash_body);
1370 OBD_ALLOC(tmp, sizeof(struct nid_stat));
1375 tmp->nid_obd = exp->exp_obd;
1376 tmp->nid_exp_ref_count = 1; /* need live in hash after destroy export */
1378 /* protect competitive add to list, not need locking on destroy */
1379 spin_lock(&obd->obd_nid_lock);
1380 list_add(&tmp->nid_list, &obd->obd_nid_stats);
1381 spin_unlock(&obd->obd_nid_lock);
1383 tmp1= lustre_hash_findadd_unique(obd->obd_nid_stats_hash_body, nid,
1385 CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
1386 tmp1, libcfs_nid2str(*nid), tmp->nid_exp_ref_count);
1389 exp->exp_nid_stats = tmp1;
1390 GOTO(destroy_new, rc = 0);
1392 /* not found - create */
1393 tmp->nid_proc = lprocfs_register(libcfs_nid2str(*nid),
1394 obd->obd_proc_exports_entry, NULL, NULL);
1395 if (!tmp->nid_proc) {
1396 CERROR("Error making export directory for"
1397 " nid %s\n", libcfs_nid2str(*nid));
1398 lustre_hash_delitem(obd->obd_nid_stats_hash_body, nid,
1400 GOTO(destroy_new, rc = -ENOMEM);
1403 rc = lprocfs_add_simple(tmp->nid_proc, "uuid",
1404 lprocfs_exp_rd_uuid, NULL, tmp);
1406 CWARN("Error adding the uuid file\n");
1408 exp->exp_nid_stats = tmp;
1413 spin_lock(&obd->obd_nid_lock);
1414 list_del(&tmp->nid_list);
1415 spin_unlock(&obd->obd_nid_lock);
1416 OBD_FREE(tmp, sizeof(struct nid_stat));
1420 int lprocfs_exp_cleanup(struct obd_export *exp)
1422 struct nid_stat *stat = exp->exp_nid_stats;
1427 stat->nid_exp_ref_count--;
1428 CDEBUG(D_INFO, "Put stat %p - %d\n", stat, stat->nid_exp_ref_count);
1430 exp->exp_nid_stats = NULL;
1434 int lprocfs_write_helper(const char *buffer, unsigned long count,
1437 return lprocfs_write_frac_helper(buffer, count, val, 1);
1440 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
1443 char kernbuf[20], *end, *pbuf;
1445 if (count > (sizeof(kernbuf) - 1))
1448 if (copy_from_user(kernbuf, buffer, count))
1451 kernbuf[count] = '\0';
1458 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1462 if (end != NULL && *end == '.') {
1463 int temp_val, pow = 1;
1467 if (strlen(pbuf) > 5)
1468 pbuf[5] = '\0'; /*only allow 5bits fractional*/
1470 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1473 for (i = 0; i < (end - pbuf); i++)
1476 *val += temp_val / pow;
1482 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val, int mult)
1484 long decimal_val, frac_val;
1490 decimal_val = val / mult;
1491 prtn = snprintf(buffer, count, "%ld", decimal_val);
1492 frac_val = val % mult;
1494 if (prtn < (count - 4) && frac_val > 0) {
1496 int i, temp_mult = 1, frac_bits = 0;
1498 temp_frac = frac_val * 10;
1499 buffer[prtn++] = '.';
1500 while (frac_bits < 2 && (temp_frac / mult) < 1 ) { /*only reserved 2bits fraction*/
1501 buffer[prtn++] ='0';
1506 Need to think these cases :
1507 1. #echo x.00 > /proc/xxx output result : x
1508 2. #echo x.0x > /proc/xxx output result : x.0x
1509 3. #echo x.x0 > /proc/xxx output result : x.x
1510 4. #echo x.xx > /proc/xxx output result : x.xx
1511 Only reserved 2bits fraction.
1513 for (i = 0; i < (5 - prtn); i++)
1516 frac_bits = min((int)count - prtn, 3 - frac_bits);
1517 prtn += snprintf(buffer + prtn, frac_bits, "%ld", frac_val * temp_mult / mult);
1520 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
1522 if (buffer[prtn] == '.') {
1529 buffer[prtn++] ='\n';
1533 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
1535 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
1538 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
1539 __u64 *val, int mult)
1541 char kernbuf[22], *end, *pbuf;
1542 __u64 whole, frac = 0, units;
1543 unsigned frac_d = 1;
1545 if (count > (sizeof(kernbuf) - 1) )
1548 if (copy_from_user(kernbuf, buffer, count))
1551 kernbuf[count] = '\0';
1558 whole = simple_strtoull(pbuf, &end, 10);
1562 if (end != NULL && *end == '.') {
1566 /* need to limit frac_d to a __u32 */
1567 if (strlen(pbuf) > 10)
1570 frac = simple_strtoull(pbuf, &end, 10);
1571 /* count decimal places */
1572 for (i = 0; i < (end - pbuf); i++)
1589 /* Specified units override the multiplier */
1591 mult = mult < 0 ? -units : units;
1594 do_div(frac, frac_d);
1595 *val = whole * mult + frac;
1599 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent,
1600 char *name, mode_t mode,
1601 struct file_operations *seq_fops, void *data)
1603 struct proc_dir_entry *entry;
1606 entry = create_proc_entry(name, mode, parent);
1609 entry->proc_fops = seq_fops;
1614 EXPORT_SYMBOL(lprocfs_seq_create);
1616 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
1618 struct file_operations *seq_fops,
1621 return (lprocfs_seq_create(dev->obd_proc_entry, name,
1622 mode, seq_fops, data));
1624 EXPORT_SYMBOL(lprocfs_obd_seq_create);
1626 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
1628 if (value >= OBD_HIST_MAX)
1629 value = OBD_HIST_MAX - 1;
1631 spin_lock(&oh->oh_lock);
1632 oh->oh_buckets[value]++;
1633 spin_unlock(&oh->oh_lock);
1635 EXPORT_SYMBOL(lprocfs_oh_tally);
1637 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
1641 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
1644 lprocfs_oh_tally(oh, val);
1646 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
1648 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
1650 unsigned long ret = 0;
1653 for (i = 0; i < OBD_HIST_MAX; i++)
1654 ret += oh->oh_buckets[i];
1657 EXPORT_SYMBOL(lprocfs_oh_sum);
1659 void lprocfs_oh_clear(struct obd_histogram *oh)
1661 spin_lock(&oh->oh_lock);
1662 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
1663 spin_unlock(&oh->oh_lock);
1665 EXPORT_SYMBOL(lprocfs_oh_clear);
1667 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
1668 int count, int *eof, void *data)
1670 struct obd_device *obd = data;
1673 LASSERT(obd != NULL);
1674 LASSERT(count >= 0);
1676 /* Set start of user data returned to
1677 page + off since the user may have
1678 requested to read much smaller than
1679 what we need to read */
1680 *start = page + off;
1682 /* We know we are allocated a page here.
1683 Also we know that this function will
1684 not need to write more than a page
1685 so we can truncate at CFS_PAGE_SIZE. */
1686 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
1688 /* Initialize the page */
1689 memset(page, 0, size);
1691 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
1694 if (obd->obd_max_recoverable_clients == 0) {
1695 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
1701 /* sampled unlocked, but really... */
1702 if (obd->obd_recovering == 0) {
1703 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
1706 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
1707 obd->obd_recovery_start) <= 0)
1710 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_end: %lu\n",
1711 obd->obd_recovery_end) <= 0)
1714 /* Number of clients have have completed recovery */
1715 if (lprocfs_obd_snprintf(&page, size, &len, "recovered_clients: %d\n",
1716 obd->obd_max_recoverable_clients - obd->obd_recoverable_clients) <= 0)
1719 if (lprocfs_obd_snprintf(&page, size, &len, "unrecovered_clients: %d\n",
1720 obd->obd_recoverable_clients) <= 0)
1723 if (lprocfs_obd_snprintf(&page, size, &len, "last_transno: "LPD64"\n",
1724 obd->obd_next_recovery_transno - 1) <= 0)
1727 lprocfs_obd_snprintf(&page, size, &len, "replayed_requests: %d\n", obd->obd_replayed_requests);
1731 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
1734 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
1735 obd->obd_recovery_start) <= 0)
1738 if (lprocfs_obd_snprintf(&page, size, &len, "time remaining: %lu\n",
1739 cfs_time_current_sec() >= obd->obd_recovery_end ? 0 :
1740 obd->obd_recovery_end - cfs_time_current_sec()) <= 0)
1743 if(lprocfs_obd_snprintf(&page, size, &len, "connected_clients: %d/%d\n",
1744 obd->obd_connected_clients,
1745 obd->obd_max_recoverable_clients) <= 0)
1748 /* Number of clients have have completed recovery */
1749 if (lprocfs_obd_snprintf(&page, size, &len, "completed_clients: %d/%d\n",
1750 obd->obd_max_recoverable_clients - obd->obd_recoverable_clients,
1751 obd->obd_max_recoverable_clients) <= 0)
1754 if (lprocfs_obd_snprintf(&page, size, &len, "replayed_requests: %d/??\n",
1755 obd->obd_replayed_requests) <= 0)
1758 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
1759 obd->obd_requests_queued_for_recovery) <= 0)
1762 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
1763 obd->obd_next_recovery_transno) <= 0)
1769 return min(count, len - (int)off);
1771 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
1773 int lprocfs_obd_rd_recovery_maxtime(char *page, char **start, off_t off,
1774 int count, int *eof, void *data)
1776 struct obd_device *obd = (struct obd_device *)data;
1777 LASSERT(obd != NULL);
1779 return snprintf(page, count, "%lu\n",
1780 obd->obd_recovery_max_time);
1782 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_maxtime);
1784 int lprocfs_obd_wr_recovery_maxtime(struct file *file, const char *buffer,
1785 unsigned long count, void *data)
1787 struct obd_device *obd = (struct obd_device *)data;
1789 LASSERT(obd != NULL);
1791 rc = lprocfs_write_helper(buffer, count, &val);
1795 obd->obd_recovery_max_time = val;
1798 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_maxtime);
1800 EXPORT_SYMBOL(lprocfs_register);
1801 EXPORT_SYMBOL(lprocfs_srch);
1802 EXPORT_SYMBOL(lprocfs_remove);
1803 EXPORT_SYMBOL(lprocfs_remove_proc_entry);
1804 EXPORT_SYMBOL(lprocfs_add_vars);
1805 EXPORT_SYMBOL(lprocfs_obd_setup);
1806 EXPORT_SYMBOL(lprocfs_obd_cleanup);
1807 EXPORT_SYMBOL(lprocfs_add_simple);
1808 EXPORT_SYMBOL(lprocfs_add_symlink);
1809 EXPORT_SYMBOL(lprocfs_free_per_client_stats);
1810 EXPORT_SYMBOL(lprocfs_alloc_stats);
1811 EXPORT_SYMBOL(lprocfs_free_stats);
1812 EXPORT_SYMBOL(lprocfs_clear_stats);
1813 EXPORT_SYMBOL(lprocfs_register_stats);
1814 EXPORT_SYMBOL(lprocfs_init_ops_stats);
1815 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
1816 EXPORT_SYMBOL(lprocfs_free_obd_stats);
1817 EXPORT_SYMBOL(lprocfs_exp_setup);
1818 EXPORT_SYMBOL(lprocfs_exp_cleanup);
1820 EXPORT_SYMBOL(lprocfs_rd_u64);
1821 EXPORT_SYMBOL(lprocfs_rd_atomic);
1822 EXPORT_SYMBOL(lprocfs_wr_atomic);
1823 EXPORT_SYMBOL(lprocfs_rd_uint);
1824 EXPORT_SYMBOL(lprocfs_wr_uint);
1825 EXPORT_SYMBOL(lprocfs_rd_uuid);
1826 EXPORT_SYMBOL(lprocfs_rd_name);
1827 EXPORT_SYMBOL(lprocfs_rd_fstype);
1828 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
1829 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
1830 EXPORT_SYMBOL(lprocfs_rd_num_exports);
1831 EXPORT_SYMBOL(lprocfs_rd_numrefs);
1833 EXPORT_SYMBOL(lprocfs_rd_blksize);
1834 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
1835 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
1836 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
1837 EXPORT_SYMBOL(lprocfs_rd_filestotal);
1838 EXPORT_SYMBOL(lprocfs_rd_filesfree);
1840 EXPORT_SYMBOL(lprocfs_write_helper);
1841 EXPORT_SYMBOL(lprocfs_write_frac_helper);
1842 EXPORT_SYMBOL(lprocfs_read_frac_helper);
1843 EXPORT_SYMBOL(lprocfs_write_u64_helper);
1844 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);