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 static ssize_t lprocfs_fops_read(struct file *f, char __user *buf,
120 size_t size, loff_t *ppos)
122 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
123 char *page, *start = NULL;
124 int rc = 0, eof = 1, count;
126 if (*ppos >= CFS_PAGE_SIZE)
129 page = (char *)__get_free_page(GFP_KERNEL);
134 OBD_FAIL_TIMEOUT(OBD_FAIL_LPROC_REMOVE, 10);
135 if (!dp->deleted && dp->read_proc)
136 rc = dp->read_proc(page, &start, *ppos, CFS_PAGE_SIZE,
142 /* for lustre proc read, the read count must be less than PAGE_SIZE */
151 start = page + *ppos;
152 } else if (start < page) {
156 count = (rc < size) ? rc : size;
157 if (copy_to_user(buf, start, count)) {
164 free_page((unsigned long)page);
168 static ssize_t lprocfs_fops_write(struct file *f, const char __user *buf, size_t size, loff_t *ppos)
170 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
174 if (!dp->deleted && dp->write_proc)
175 rc = dp->write_proc(f, buf, size, dp->data);
180 static struct file_operations lprocfs_generic_fops = {
181 .owner = THIS_MODULE,
182 .read = lprocfs_fops_read,
183 .write = lprocfs_fops_write,
186 int lprocfs_evict_client_open(struct inode *inode, struct file *f)
188 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
189 struct obd_device *obd = dp->data;
191 atomic_inc(&obd->obd_evict_inprogress);
196 int lprocfs_evict_client_release(struct inode *inode, struct file *f)
198 struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
199 struct obd_device *obd = dp->data;
201 atomic_dec(&obd->obd_evict_inprogress);
202 wake_up(&obd->obd_evict_inprogress_waitq);
207 struct file_operations lprocfs_evict_client_fops = {
208 .owner = THIS_MODULE,
209 .read = lprocfs_fops_read,
210 .write = lprocfs_fops_write,
211 .open = lprocfs_evict_client_open,
212 .release = lprocfs_evict_client_release,
214 EXPORT_SYMBOL(lprocfs_evict_client_fops);
216 int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list,
219 if (root == NULL || list == NULL)
222 while (list->name != NULL) {
223 struct proc_dir_entry *cur_root, *proc;
224 char *pathcopy, *cur, *next, pathbuf[64];
225 int pathsize = strlen(list->name) + 1;
230 /* need copy of path for strsep */
231 if (strlen(list->name) > sizeof(pathbuf) - 1) {
232 OBD_ALLOC(pathcopy, pathsize);
233 if (pathcopy == NULL)
240 strcpy(pathcopy, list->name);
242 while (cur_root != NULL && (cur = strsep(&next, "/"))) {
243 if (*cur =='\0') /* skip double/trailing "/" */
246 proc = lprocfs_srch(cur_root, cur);
247 CDEBUG(D_OTHER, "cur_root=%s, cur=%s, next=%s, (%s)\n",
248 cur_root->name, cur, next,
249 (proc ? "exists" : "new"));
251 cur_root = (proc ? proc :
252 proc_mkdir(cur, cur_root));
253 } else if (proc == NULL) {
257 if (list->write_fptr)
259 proc = create_proc_entry(cur, mode, cur_root);
263 if (pathcopy != pathbuf)
264 OBD_FREE(pathcopy, pathsize);
266 if (cur_root == NULL || proc == NULL) {
267 CERROR("LprocFS: No memory to create /proc entry %s",
273 proc->proc_fops = list->fops;
275 proc->proc_fops = &lprocfs_generic_fops;
276 proc->read_proc = list->read_fptr;
277 proc->write_proc = list->write_fptr;
278 proc->data = (list->data ? list->data : data);
284 void lprocfs_remove(struct proc_dir_entry **rooth)
286 struct proc_dir_entry *root = *rooth;
287 struct proc_dir_entry *temp = root;
288 struct proc_dir_entry *rm_entry;
289 struct proc_dir_entry *parent;
295 parent = root->parent;
296 LASSERT(parent != NULL);
299 while (temp->subdir != NULL)
305 /* Memory corruption once caused this to fail, and
306 without this LASSERT we would loop here forever. */
307 LASSERTF(strlen(rm_entry->name) == rm_entry->namelen,
308 "0x%p %s/%s len %d\n", rm_entry, temp->name,
309 rm_entry->name, (int)strlen(rm_entry->name));
311 /* Now, the rm_entry->deleted flags is protected
312 * by _lprocfs_lock. */
313 down_write(&_lprocfs_lock);
314 rm_entry->data = NULL;
315 remove_proc_entry(rm_entry->name, rm_entry->parent);
316 up_write(&_lprocfs_lock);
322 struct proc_dir_entry *lprocfs_register(const char *name,
323 struct proc_dir_entry *parent,
324 struct lprocfs_vars *list, void *data)
326 struct proc_dir_entry *newchild;
328 newchild = lprocfs_srch(parent, name);
329 if (newchild != NULL) {
330 CERROR(" Lproc: Attempting to register %s more than once \n",
332 return ERR_PTR(-EALREADY);
335 newchild = proc_mkdir(name, parent);
336 if (newchild != NULL && list != NULL) {
337 int rc = lprocfs_add_vars(newchild, list, data);
339 lprocfs_remove(&newchild);
346 /* Generic callbacks */
347 int lprocfs_rd_uint(char *page, char **start, off_t off,
348 int count, int *eof, void *data)
350 unsigned int *temp = (unsigned int *)data;
351 return snprintf(page, count, "%u\n", *temp);
354 int lprocfs_wr_uint(struct file *file, const char *buffer,
355 unsigned long count, void *data)
358 char dummy[MAX_STRING_SIZE + 1], *end;
361 dummy[MAX_STRING_SIZE] = '\0';
362 if (copy_from_user(dummy, buffer, MAX_STRING_SIZE))
365 tmp = simple_strtoul(dummy, &end, 0);
369 *p = (unsigned int)tmp;
373 int lprocfs_rd_u64(char *page, char **start, off_t off,
374 int count, int *eof, void *data)
376 LASSERT(data != NULL);
378 return snprintf(page, count, LPU64"\n", *(__u64 *)data);
381 int lprocfs_rd_atomic(char *page, char **start, off_t off,
382 int count, int *eof, void *data)
384 atomic_t *atom = (atomic_t *)data;
385 LASSERT(atom != NULL);
387 return snprintf(page, count, "%d\n", atomic_read(atom));
390 int lprocfs_wr_atomic(struct file *file, const char *buffer,
391 unsigned long count, void *data)
393 atomic_t *atm = data;
397 rc = lprocfs_write_helper(buffer, count, &val);
404 atomic_set(atm, val);
408 int lprocfs_rd_uuid(char *page, char **start, off_t off, int count,
409 int *eof, void *data)
411 struct obd_device *obd = (struct obd_device*)data;
413 LASSERT(obd != NULL);
415 return snprintf(page, count, "%s\n", obd->obd_uuid.uuid);
418 int lprocfs_rd_name(char *page, char **start, off_t off, int count,
419 int *eof, void* data)
421 struct obd_device *dev = (struct obd_device *)data;
423 LASSERT(dev != NULL);
424 LASSERT(dev->obd_name != NULL);
426 return snprintf(page, count, "%s\n", dev->obd_name);
429 int lprocfs_rd_fstype(char *page, char **start, off_t off, int count, int *eof,
432 struct obd_device *obd = (struct obd_device *)data;
434 LASSERT(obd != NULL);
435 LASSERT(obd->obd_fsops != NULL);
436 LASSERT(obd->obd_fsops->fs_type != NULL);
437 return snprintf(page, count, "%s\n", obd->obd_fsops->fs_type);
440 int lprocfs_rd_blksize(char *page, char **start, off_t off, int count,
441 int *eof, void *data)
443 struct obd_statfs osfs;
444 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ);
447 rc = snprintf(page, count, "%u\n", osfs.os_bsize);
452 int lprocfs_rd_kbytestotal(char *page, char **start, off_t off, int count,
453 int *eof, void *data)
455 struct obd_statfs osfs;
456 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ);
458 __u32 blk_size = osfs.os_bsize >> 10;
459 __u64 result = osfs.os_blocks;
461 while (blk_size >>= 1)
465 rc = snprintf(page, count, LPU64"\n", result);
470 int lprocfs_rd_kbytesfree(char *page, char **start, off_t off, int count,
471 int *eof, void *data)
473 struct obd_statfs osfs;
474 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ);
476 __u32 blk_size = osfs.os_bsize >> 10;
477 __u64 result = osfs.os_bfree;
479 while (blk_size >>= 1)
483 rc = snprintf(page, count, LPU64"\n", result);
488 int lprocfs_rd_kbytesavail(char *page, char **start, off_t off, int count,
489 int *eof, void *data)
491 struct obd_statfs osfs;
492 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ);
494 __u32 blk_size = osfs.os_bsize >> 10;
495 __u64 result = osfs.os_bavail;
497 while (blk_size >>= 1)
501 rc = snprintf(page, count, LPU64"\n", result);
506 int lprocfs_rd_filestotal(char *page, char **start, off_t off, int count,
507 int *eof, void *data)
509 struct obd_statfs osfs;
510 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ);
513 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
519 int lprocfs_rd_filesfree(char *page, char **start, off_t off, int count,
520 int *eof, void *data)
522 struct obd_statfs osfs;
523 int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ);
526 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
531 int lprocfs_rd_server_uuid(char *page, char **start, off_t off, int count,
532 int *eof, void *data)
534 struct obd_device *obd = (struct obd_device *)data;
535 struct obd_import *imp;
536 char *imp_state_name = NULL;
539 LASSERT(obd != NULL);
540 LPROCFS_CLIMP_CHECK(obd);
541 imp = obd->u.cli.cl_import;
542 imp_state_name = ptlrpc_import_state_name(imp->imp_state);
544 rc = snprintf(page, count, "%s\t%s%s\n",
545 obd2cli_tgt(obd), imp_state_name,
546 imp->imp_deactive ? "\tDEACTIVATED" : "");
548 LPROCFS_CLIMP_EXIT(obd);
552 int lprocfs_rd_conn_uuid(char *page, char **start, off_t off, int count,
553 int *eof, void *data)
555 struct obd_device *obd = (struct obd_device*)data;
556 struct ptlrpc_connection *conn;
559 LASSERT(obd != NULL);
561 LPROCFS_CLIMP_CHECK(obd);
562 conn = obd->u.cli.cl_import->imp_connection;
563 LASSERT(conn != NULL);
565 if (obd->u.cli.cl_import) {
566 rc = snprintf(page, count, "%s\n",
567 conn->c_remote_uuid.uuid);
569 rc = snprintf(page, count, "%s\n", "<none>");
572 LPROCFS_CLIMP_EXIT(obd);
576 static const char *obd_connect_names[] = {
603 "mds_mds_connection",
608 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
609 int count, int *eof, void *data)
611 struct obd_device *obd = data;
612 __u64 mask = 1, flags;
615 LPROCFS_CLIMP_CHECK(obd);
616 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
617 ret = snprintf(page, count, "flags="LPX64"\n", flags);
618 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
620 ret += snprintf(page + ret, count - ret, "%s\n",
621 obd_connect_names[i]);
623 if (flags & ~(mask - 1))
624 ret += snprintf(page + ret, count - ret,
625 "unknown flags "LPX64"\n", flags & ~(mask - 1));
627 LPROCFS_CLIMP_EXIT(obd);
630 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
632 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
633 int *eof, void *data)
635 struct obd_device *obd = (struct obd_device*)data;
637 LASSERT(obd != NULL);
639 return snprintf(page, count, "%u\n", obd->obd_num_exports);
642 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
643 int *eof, void *data)
645 struct obd_type *class = (struct obd_type*) data;
647 LASSERT(class != NULL);
649 return snprintf(page, count, "%d\n", class->typ_refcnt);
652 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
656 LASSERT(obd != NULL);
657 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
658 LASSERT(obd->obd_type->typ_procroot != NULL);
660 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
661 obd->obd_type->typ_procroot,
663 if (IS_ERR(obd->obd_proc_entry)) {
664 rc = PTR_ERR(obd->obd_proc_entry);
665 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
666 obd->obd_proc_entry = NULL;
671 int lprocfs_obd_cleanup(struct obd_device *obd)
675 if (obd->obd_proc_exports) {
676 /* Should be no exports left */
677 LASSERT(obd->obd_proc_exports->subdir == NULL);
678 lprocfs_remove(&obd->obd_proc_exports);
680 lprocfs_remove(&obd->obd_proc_entry);
684 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
685 enum lprocfs_stats_flags flags)
687 struct lprocfs_stats *stats;
688 struct lprocfs_percpu *percpu;
689 unsigned int percpusize;
691 unsigned int num_cpu;
696 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
699 num_cpu = num_possible_cpus();
701 OBD_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
705 if (flags & LPROCFS_STATS_FLAG_NOPERCPU) {
706 stats->ls_flags = flags;
707 spin_lock_init(&stats->ls_lock);
708 /* Use this lock only if there are no percpu areas */
713 percpusize = offsetof(typeof(*percpu), lp_cntr[num]);
715 percpusize = L1_CACHE_ALIGN(percpusize);
717 stats->ls_percpu_size = num_cpu * percpusize;
718 OBD_ALLOC(stats->ls_percpu[0], stats->ls_percpu_size);
719 if (stats->ls_percpu[0] == NULL) {
720 OBD_FREE(stats, offsetof(typeof(*stats),
721 ls_percpu[num_cpu]));
726 for (i = 1; i < num_cpu; i++)
727 stats->ls_percpu[i] = (void *)(stats->ls_percpu[i - 1]) +
733 void lprocfs_free_stats(struct lprocfs_stats **statsh)
735 struct lprocfs_stats *stats = *statsh;
736 unsigned int num_cpu;
738 if (stats == NULL || stats->ls_num == 0)
742 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
745 num_cpu = num_possible_cpus();
747 OBD_FREE(stats->ls_percpu[0], stats->ls_percpu_size);
748 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
751 void lprocfs_clear_stats(struct lprocfs_stats *stats)
753 struct lprocfs_counter *percpu_cntr;
755 unsigned int num_cpu;
757 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
759 for (i = 0; i < num_cpu; i++) {
760 for (j = 0; j < stats->ls_num; j++) {
761 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
762 atomic_inc(&percpu_cntr->lc_cntl.la_entry);
763 percpu_cntr->lc_count = 0;
764 percpu_cntr->lc_sum = 0;
765 percpu_cntr->lc_min = ~(__u64)0;
766 percpu_cntr->lc_max = 0;
767 percpu_cntr->lc_sumsquare = 0;
768 atomic_inc(&percpu_cntr->lc_cntl.la_exit);
772 lprocfs_stats_unlock(stats);
775 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
776 size_t len, loff_t *off)
778 struct seq_file *seq = file->private_data;
779 struct lprocfs_stats *stats = seq->private;
781 lprocfs_clear_stats(stats);
786 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
788 struct lprocfs_stats *stats = p->private;
789 /* return 1st cpu location */
790 return (*pos >= stats->ls_num) ? NULL :
791 &(stats->ls_percpu[0]->lp_cntr[*pos]);
794 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
798 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
800 struct lprocfs_stats *stats = p->private;
802 return (*pos >= stats->ls_num) ? NULL :
803 &(stats->ls_percpu[0]->lp_cntr[*pos]);
806 /* seq file export of one lprocfs counter */
807 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
809 struct lprocfs_stats *stats = p->private;
810 struct lprocfs_counter *cntr = v;
811 struct lprocfs_counter t, ret = { .lc_min = ~(__u64)0 };
813 unsigned int num_cpu;
815 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
817 do_gettimeofday(&now);
818 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
819 "snapshot_time", now.tv_sec, now.tv_usec);
823 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
825 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
828 num_cpu = num_possible_cpus();
830 for (i = 0; i < num_cpu; i++) {
831 struct lprocfs_counter *percpu_cntr =
832 &(stats->ls_percpu[i])->lp_cntr[idx];
836 centry = atomic_read(&percpu_cntr->lc_cntl.la_entry);
837 t.lc_count = percpu_cntr->lc_count;
838 t.lc_sum = percpu_cntr->lc_sum;
839 t.lc_min = percpu_cntr->lc_min;
840 t.lc_max = percpu_cntr->lc_max;
841 t.lc_sumsquare = percpu_cntr->lc_sumsquare;
842 } while (centry != atomic_read(&percpu_cntr->lc_cntl.la_entry) &&
843 centry != atomic_read(&percpu_cntr->lc_cntl.la_exit));
844 ret.lc_count += t.lc_count;
845 ret.lc_sum += t.lc_sum;
846 if (t.lc_min < ret.lc_min)
847 ret.lc_min = t.lc_min;
848 if (t.lc_max > ret.lc_max)
849 ret.lc_max = t.lc_max;
850 ret.lc_sumsquare += t.lc_sumsquare;
853 rc = seq_printf(p, "%-25s "LPU64" samples [%s]", cntr->lc_name,
854 ret.lc_count, cntr->lc_units);
858 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
859 rc = seq_printf(p, " "LPU64" "LPU64" "LPU64,
860 ret.lc_min, ret.lc_max, ret.lc_sum);
863 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
864 rc = seq_printf(p, " "LPU64, ret.lc_sumsquare);
868 rc = seq_printf(p, "\n");
870 return (rc < 0) ? rc : 0;
873 struct seq_operations lprocfs_stats_seq_sops = {
874 start: lprocfs_stats_seq_start,
875 stop: lprocfs_stats_seq_stop,
876 next: lprocfs_stats_seq_next,
877 show: lprocfs_stats_seq_show,
880 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
882 struct proc_dir_entry *dp = PDE(inode);
883 struct seq_file *seq;
886 LPROCFS_ENTRY_AND_CHECK(dp);
887 rc = seq_open(file, &lprocfs_stats_seq_sops);
892 seq = file->private_data;
893 seq->private = dp->data;
897 struct file_operations lprocfs_stats_seq_fops = {
898 .owner = THIS_MODULE,
899 .open = lprocfs_stats_seq_open,
901 .write = lprocfs_stats_seq_write,
903 .release = lprocfs_seq_release,
906 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
907 struct lprocfs_stats *stats)
909 struct proc_dir_entry *entry;
910 LASSERT(root != NULL);
912 entry = create_proc_entry(name, 0644, root);
915 entry->proc_fops = &lprocfs_stats_seq_fops;
916 entry->data = (void *)stats;
920 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
921 unsigned conf, const char *name, const char *units)
923 struct lprocfs_counter *c;
925 unsigned int num_cpu;
927 LASSERT(stats != NULL);
929 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
931 for (i = 0; i < num_cpu; i++) {
932 c = &(stats->ls_percpu[i]->lp_cntr[index]);
936 c->lc_min = ~(__u64)0;
942 lprocfs_stats_unlock(stats);
944 EXPORT_SYMBOL(lprocfs_counter_init);
946 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
948 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
949 LASSERT(coffset < stats->ls_num); \
950 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
953 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
955 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
956 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
957 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
958 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
959 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
960 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
961 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
962 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
963 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
964 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
965 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
966 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
967 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
968 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
969 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
970 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
971 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
972 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
973 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
974 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
975 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
976 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
977 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
978 LPROCFS_OBD_OP_INIT(num_private_stats, stats, checkmd);
979 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
980 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
981 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
982 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
983 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
984 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
985 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
986 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
987 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
988 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw_async);
989 LPROCFS_OBD_OP_INIT(num_private_stats, stats, prep_async_page);
990 LPROCFS_OBD_OP_INIT(num_private_stats, stats, queue_async_io);
991 LPROCFS_OBD_OP_INIT(num_private_stats, stats, queue_group_io);
992 LPROCFS_OBD_OP_INIT(num_private_stats, stats, trigger_group_io);
993 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_async_flags);
994 LPROCFS_OBD_OP_INIT(num_private_stats, stats, teardown_async_page);
995 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
996 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
997 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
998 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
999 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1000 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1001 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1002 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1003 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1004 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1005 LPROCFS_OBD_OP_INIT(num_private_stats, stats, match);
1006 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1007 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1008 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1009 LPROCFS_OBD_OP_INIT(num_private_stats, stats, join_lru);
1010 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1011 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1012 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1013 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1014 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1015 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1016 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1017 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1018 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1019 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1020 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1021 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1022 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1023 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1026 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1028 struct lprocfs_stats *stats;
1029 unsigned int num_stats;
1032 LASSERT(obd->obd_stats == NULL);
1033 LASSERT(obd->obd_proc_entry != NULL);
1034 LASSERT(obd->obd_cntr_base == 0);
1036 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1037 num_private_stats - 1 /* o_owner */;
1038 stats = lprocfs_alloc_stats(num_stats, 0);
1042 lprocfs_init_ops_stats(num_private_stats, stats);
1044 for (i = num_private_stats; i < num_stats; i++) {
1045 /* If this LBUGs, it is likely that an obd
1046 * operation was added to struct obd_ops in
1047 * <obd.h>, and that the corresponding line item
1048 * LPROCFS_OBD_OP_INIT(.., .., opname)
1049 * is missing from the list above. */
1050 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1051 "Missing obd_stat initializer obd_op "
1052 "operation at offset %d.\n", i - num_private_stats);
1054 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1056 lprocfs_free_stats(&stats);
1058 obd->obd_stats = stats;
1059 obd->obd_cntr_base = num_private_stats;
1064 void lprocfs_free_obd_stats(struct obd_device *obd)
1067 lprocfs_free_stats(&obd->obd_stats);
1070 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1072 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1073 LASSERT(coffset < stats->ls_num); \
1074 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1077 int lprocfs_alloc_md_stats(struct obd_device *obd,
1078 unsigned num_private_stats)
1080 struct lprocfs_stats *stats;
1081 unsigned int num_stats;
1084 LASSERT(obd->md_stats == NULL);
1085 LASSERT(obd->obd_proc_entry != NULL);
1086 LASSERT(obd->md_cntr_base == 0);
1088 num_stats = 1 + MD_COUNTER_OFFSET(get_remote_perm) +
1090 stats = lprocfs_alloc_stats(num_stats, 0);
1094 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1095 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1096 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1097 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1098 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1099 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1100 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1101 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1102 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1103 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1104 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1105 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1106 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1107 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1108 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1109 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1110 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1111 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1112 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1113 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1114 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1115 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1116 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1117 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1118 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1119 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1120 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1121 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1123 for (i = num_private_stats; i < num_stats; i++) {
1124 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1125 CERROR("Missing md_stat initializer md_op "
1126 "operation at offset %d. Aborting.\n",
1127 i - num_private_stats);
1131 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1133 lprocfs_free_stats(&stats);
1135 obd->md_stats = stats;
1136 obd->md_cntr_base = num_private_stats;
1141 void lprocfs_free_md_stats(struct obd_device *obd)
1143 struct lprocfs_stats *stats = obd->md_stats;
1145 if (stats != NULL) {
1146 obd->md_stats = NULL;
1147 lprocfs_free_stats(&stats);
1151 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1152 int *eof, void *data)
1154 struct obd_export *exp = (struct obd_export*)data;
1155 LASSERT(exp != NULL);
1157 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1160 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1161 int *eof, void *data)
1163 struct obd_export *exp = (struct obd_export*)data;
1164 LASSERT(exp != NULL);
1166 return snprintf(page, count, "%s\n",
1167 obd_uuid2str(&exp->exp_client_uuid));
1170 int lprocfs_exp_setup(struct obd_export *exp)
1172 char name[sizeof (exp->exp_client_uuid.uuid) + 3];
1175 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports)
1177 mutex_down(&exp->exp_obd->obd_proc_exp_sem);
1178 sprintf(name, "%s", (char *)exp->exp_client_uuid.uuid);
1179 while (lprocfs_srch(exp->exp_obd->obd_proc_exports, name)) {
1180 /* We might add a new export before deleting the old one during
1181 an eviction (recovery-small 19a). Suckage. We
1182 could block, or come up with a new name, or just give up. */
1184 GOTO(out, rc = -EEXIST);
1185 sprintf(name, "%s:%d", (char *)exp->exp_client_uuid.uuid, i);
1188 /* Create a proc entry for this export */
1189 exp->exp_proc = proc_mkdir(name, exp->exp_obd->obd_proc_exports);
1190 if (!exp->exp_proc) {
1191 CERROR("Error making export directory for %s\n", name);
1192 GOTO(out, rc = -ENOMEM);
1195 /* Always add nid and uuid */
1196 rc = lprocfs_add_simple(exp->exp_proc, "nid",
1197 lprocfs_exp_rd_nid, NULL, exp);
1200 rc = lprocfs_add_simple(exp->exp_proc, "uuid",
1201 lprocfs_exp_rd_uuid, NULL, exp);
1204 /* Always add ldlm stats */
1205 exp->exp_ldlm_stats = lprocfs_alloc_stats(LDLM_LAST_OPC
1206 - LDLM_FIRST_OPC, 0);
1207 if (exp->exp_ldlm_stats == NULL) {
1208 lprocfs_remove(&exp->exp_proc);
1209 GOTO(out, rc = -ENOMEM);
1212 lprocfs_counter_init(exp->exp_ldlm_stats,
1213 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1214 0, "ldlm_enqueue", "reqs");
1215 lprocfs_counter_init(exp->exp_ldlm_stats,
1216 LDLM_CONVERT - LDLM_FIRST_OPC,
1217 0, "ldlm_convert", "reqs");
1218 lprocfs_counter_init(exp->exp_ldlm_stats,
1219 LDLM_CANCEL - LDLM_FIRST_OPC,
1220 0, "ldlm_cancel", "reqs");
1221 lprocfs_counter_init(exp->exp_ldlm_stats,
1222 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1223 0, "ldlm_bl_callback", "reqs");
1224 lprocfs_counter_init(exp->exp_ldlm_stats,
1225 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1226 0, "ldlm_cp_callback", "reqs");
1227 lprocfs_counter_init(exp->exp_ldlm_stats,
1228 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1229 0, "ldlm_gl_callback", "reqs");
1230 lprocfs_register_stats(exp->exp_proc, "ldlm_stats",
1231 exp->exp_ldlm_stats);
1233 mutex_up(&exp->exp_obd->obd_proc_exp_sem);
1237 int lprocfs_exp_cleanup(struct obd_export *exp)
1239 mutex_down(&exp->exp_obd->obd_proc_exp_sem);
1240 lprocfs_remove(&exp->exp_proc);
1241 lprocfs_free_stats(&exp->exp_ops_stats);
1242 lprocfs_free_stats(&exp->exp_ldlm_stats);
1243 mutex_up(&exp->exp_obd->obd_proc_exp_sem);
1247 int lprocfs_write_helper(const char *buffer, unsigned long count,
1250 return lprocfs_write_frac_helper(buffer, count, val, 1);
1253 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
1256 char kernbuf[20], *end, *pbuf;
1258 if (count > (sizeof(kernbuf) - 1))
1261 if (copy_from_user(kernbuf, buffer, count))
1264 kernbuf[count] = '\0';
1271 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1275 if (end != NULL && *end == '.') {
1276 int temp_val, pow = 1;
1280 if (strlen(pbuf) > 5)
1281 pbuf[5] = '\0'; /*only allow 5bits fractional*/
1283 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1286 for (i = 0; i < (end - pbuf); i++)
1289 *val += temp_val / pow;
1295 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val, int mult)
1297 long decimal_val, frac_val;
1303 decimal_val = val / mult;
1304 prtn = snprintf(buffer, count, "%ld", decimal_val);
1305 frac_val = val % mult;
1307 if (prtn < (count - 4) && frac_val > 0) {
1309 int i, temp_mult = 1, frac_bits = 0;
1311 temp_frac = frac_val * 10;
1312 buffer[prtn++] = '.';
1313 while (frac_bits < 2 && (temp_frac / mult) < 1 ) { /*only reserved 2bits fraction*/
1314 buffer[prtn++] ='0';
1319 Need to think these cases :
1320 1. #echo x.00 > /proc/xxx output result : x
1321 2. #echo x.0x > /proc/xxx output result : x.0x
1322 3. #echo x.x0 > /proc/xxx output result : x.x
1323 4. #echo x.xx > /proc/xxx output result : x.xx
1324 Only reserved 2bits fraction.
1326 for (i = 0; i < (5 - prtn); i++)
1329 frac_bits = min((int)count - prtn, 3 - frac_bits);
1330 prtn += snprintf(buffer + prtn, frac_bits, "%ld", frac_val * temp_mult / mult);
1333 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
1335 if (buffer[prtn] == '.') {
1342 buffer[prtn++] ='\n';
1346 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
1348 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
1351 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
1352 __u64 *val, int mult)
1354 char kernbuf[22], *end, *pbuf;
1355 __u64 whole, frac = 0, units;
1356 unsigned frac_d = 1;
1358 if (count > (sizeof(kernbuf) - 1) )
1361 if (copy_from_user(kernbuf, buffer, count))
1364 kernbuf[count] = '\0';
1371 whole = simple_strtoull(pbuf, &end, 10);
1375 if (end != NULL && *end == '.') {
1379 /* need to limit frac_d to a __u32 */
1380 if (strlen(pbuf) > 10)
1383 frac = simple_strtoull(pbuf, &end, 10);
1384 /* count decimal places */
1385 for (i = 0; i < (end - pbuf); i++)
1402 /* Specified units override the multiplier */
1404 mult = mult < 0 ? -units : units;
1407 do_div(frac, frac_d);
1408 *val = whole * mult + frac;
1412 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent,
1413 char *name, mode_t mode,
1414 struct file_operations *seq_fops, void *data)
1416 struct proc_dir_entry *entry;
1419 entry = create_proc_entry(name, mode, parent);
1422 entry->proc_fops = seq_fops;
1427 EXPORT_SYMBOL(lprocfs_seq_create);
1429 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
1431 struct file_operations *seq_fops,
1434 return (lprocfs_seq_create(dev->obd_proc_entry, name,
1435 mode, seq_fops, data));
1437 EXPORT_SYMBOL(lprocfs_obd_seq_create);
1439 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
1441 if (value >= OBD_HIST_MAX)
1442 value = OBD_HIST_MAX - 1;
1444 spin_lock(&oh->oh_lock);
1445 oh->oh_buckets[value]++;
1446 spin_unlock(&oh->oh_lock);
1448 EXPORT_SYMBOL(lprocfs_oh_tally);
1450 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
1454 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
1457 lprocfs_oh_tally(oh, val);
1459 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
1461 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
1463 unsigned long ret = 0;
1466 for (i = 0; i < OBD_HIST_MAX; i++)
1467 ret += oh->oh_buckets[i];
1470 EXPORT_SYMBOL(lprocfs_oh_sum);
1472 void lprocfs_oh_clear(struct obd_histogram *oh)
1474 spin_lock(&oh->oh_lock);
1475 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
1476 spin_unlock(&oh->oh_lock);
1478 EXPORT_SYMBOL(lprocfs_oh_clear);
1480 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
1481 int count, int *eof, void *data)
1483 struct obd_device *obd = data;
1486 LASSERT(obd != NULL);
1487 LASSERT(count >= 0);
1489 /* Set start of user data returned to
1490 page + off since the user may have
1491 requested to read much smaller than
1492 what we need to read */
1493 *start = page + off;
1495 /* We know we are allocated a page here.
1496 Also we know that this function will
1497 not need to write more than a page
1498 so we can truncate at CFS_PAGE_SIZE. */
1499 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
1501 /* Initialize the page */
1502 memset(page, 0, size);
1504 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
1507 if (obd->obd_max_recoverable_clients == 0) {
1508 lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n");
1512 /* sampled unlocked, but really... */
1513 if (obd->obd_recovering == 0) {
1514 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
1517 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
1518 obd->obd_recovery_start) <= 0)
1521 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_end: %lu\n",
1522 obd->obd_recovery_end) <= 0)
1525 /* Number of clients have have completed recovery */
1526 if (lprocfs_obd_snprintf(&page, size, &len, "recovered_clients: %d\n",
1527 obd->obd_max_recoverable_clients - obd->obd_recoverable_clients) <= 0)
1530 if (lprocfs_obd_snprintf(&page, size, &len, "unrecovered_clients: %d\n",
1531 obd->obd_recoverable_clients) <= 0)
1534 if (lprocfs_obd_snprintf(&page, size, &len, "last_transno: "LPD64"\n",
1535 obd->obd_next_recovery_transno - 1) <= 0)
1538 lprocfs_obd_snprintf(&page, size, &len, "replayed_requests: %d\n", obd->obd_replayed_requests);
1542 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
1545 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
1546 obd->obd_recovery_start) <= 0)
1549 if (lprocfs_obd_snprintf(&page, size, &len, "time remaining: %lu\n",
1550 CURRENT_SECONDS >= obd->obd_recovery_end ? 0 :
1551 obd->obd_recovery_end - CURRENT_SECONDS) <= 0)
1554 if(lprocfs_obd_snprintf(&page, size, &len, "connected_clients: %d/%d\n",
1555 obd->obd_connected_clients,
1556 obd->obd_max_recoverable_clients) <= 0)
1559 /* Number of clients have have completed recovery */
1560 if (lprocfs_obd_snprintf(&page, size, &len, "completed_clients: %d/%d\n",
1561 obd->obd_max_recoverable_clients - obd->obd_recoverable_clients,
1562 obd->obd_max_recoverable_clients) <= 0)
1565 if (lprocfs_obd_snprintf(&page, size, &len, "replayed_requests: %d/??\n",
1566 obd->obd_replayed_requests) <= 0)
1569 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
1570 obd->obd_requests_queued_for_recovery) <= 0)
1573 lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n", obd->obd_next_recovery_transno);
1578 return min(count, len - (int)off);
1580 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
1582 EXPORT_SYMBOL(lprocfs_register);
1583 EXPORT_SYMBOL(lprocfs_srch);
1584 EXPORT_SYMBOL(lprocfs_remove);
1585 EXPORT_SYMBOL(lprocfs_add_vars);
1586 EXPORT_SYMBOL(lprocfs_obd_setup);
1587 EXPORT_SYMBOL(lprocfs_obd_cleanup);
1588 EXPORT_SYMBOL(lprocfs_alloc_stats);
1589 EXPORT_SYMBOL(lprocfs_free_stats);
1590 EXPORT_SYMBOL(lprocfs_clear_stats);
1591 EXPORT_SYMBOL(lprocfs_register_stats);
1592 EXPORT_SYMBOL(lprocfs_init_ops_stats);
1593 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
1594 EXPORT_SYMBOL(lprocfs_free_obd_stats);
1595 EXPORT_SYMBOL(lprocfs_exp_setup);
1596 EXPORT_SYMBOL(lprocfs_exp_cleanup);
1598 EXPORT_SYMBOL(lprocfs_rd_u64);
1599 EXPORT_SYMBOL(lprocfs_rd_atomic);
1600 EXPORT_SYMBOL(lprocfs_wr_atomic);
1601 EXPORT_SYMBOL(lprocfs_rd_uint);
1602 EXPORT_SYMBOL(lprocfs_wr_uint);
1603 EXPORT_SYMBOL(lprocfs_rd_uuid);
1604 EXPORT_SYMBOL(lprocfs_rd_name);
1605 EXPORT_SYMBOL(lprocfs_rd_fstype);
1606 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
1607 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
1608 EXPORT_SYMBOL(lprocfs_rd_num_exports);
1609 EXPORT_SYMBOL(lprocfs_rd_numrefs);
1611 EXPORT_SYMBOL(lprocfs_rd_blksize);
1612 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
1613 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
1614 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
1615 EXPORT_SYMBOL(lprocfs_rd_filestotal);
1616 EXPORT_SYMBOL(lprocfs_rd_filesfree);
1618 EXPORT_SYMBOL(lprocfs_write_helper);
1619 EXPORT_SYMBOL(lprocfs_write_frac_helper);
1620 EXPORT_SYMBOL(lprocfs_read_frac_helper);
1621 EXPORT_SYMBOL(lprocfs_write_u64_helper);
1622 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);