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",
606 "alt_checksum_algorithm",
610 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
611 int count, int *eof, void *data)
613 struct obd_device *obd = data;
614 __u64 mask = 1, flags;
617 LPROCFS_CLIMP_CHECK(obd);
618 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
619 ret = snprintf(page, count, "flags="LPX64"\n", flags);
620 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
622 ret += snprintf(page + ret, count - ret, "%s\n",
623 obd_connect_names[i]);
625 if (flags & ~(mask - 1))
626 ret += snprintf(page + ret, count - ret,
627 "unknown flags "LPX64"\n", flags & ~(mask - 1));
629 LPROCFS_CLIMP_EXIT(obd);
632 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
634 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
635 int *eof, void *data)
637 struct obd_device *obd = (struct obd_device*)data;
639 LASSERT(obd != NULL);
641 return snprintf(page, count, "%u\n", obd->obd_num_exports);
644 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
645 int *eof, void *data)
647 struct obd_type *class = (struct obd_type*) data;
649 LASSERT(class != NULL);
651 return snprintf(page, count, "%d\n", class->typ_refcnt);
654 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
658 LASSERT(obd != NULL);
659 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
660 LASSERT(obd->obd_type->typ_procroot != NULL);
662 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
663 obd->obd_type->typ_procroot,
665 if (IS_ERR(obd->obd_proc_entry)) {
666 rc = PTR_ERR(obd->obd_proc_entry);
667 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
668 obd->obd_proc_entry = NULL;
673 int lprocfs_obd_cleanup(struct obd_device *obd)
677 if (obd->obd_proc_exports) {
678 /* Should be no exports left */
679 LASSERT(obd->obd_proc_exports->subdir == NULL);
680 lprocfs_remove(&obd->obd_proc_exports);
682 lprocfs_remove(&obd->obd_proc_entry);
686 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
687 enum lprocfs_stats_flags flags)
689 struct lprocfs_stats *stats;
690 struct lprocfs_percpu *percpu;
691 unsigned int percpusize;
693 unsigned int num_cpu;
698 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
701 num_cpu = num_possible_cpus();
703 OBD_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
707 if (flags & LPROCFS_STATS_FLAG_NOPERCPU) {
708 stats->ls_flags = flags;
709 spin_lock_init(&stats->ls_lock);
710 /* Use this lock only if there are no percpu areas */
715 percpusize = offsetof(typeof(*percpu), lp_cntr[num]);
717 percpusize = L1_CACHE_ALIGN(percpusize);
719 stats->ls_percpu_size = num_cpu * percpusize;
720 OBD_ALLOC(stats->ls_percpu[0], stats->ls_percpu_size);
721 if (stats->ls_percpu[0] == NULL) {
722 OBD_FREE(stats, offsetof(typeof(*stats),
723 ls_percpu[num_cpu]));
728 for (i = 1; i < num_cpu; i++)
729 stats->ls_percpu[i] = (void *)(stats->ls_percpu[i - 1]) +
735 void lprocfs_free_stats(struct lprocfs_stats **statsh)
737 struct lprocfs_stats *stats = *statsh;
738 unsigned int num_cpu;
740 if (stats == NULL || stats->ls_num == 0)
744 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
747 num_cpu = num_possible_cpus();
749 OBD_FREE(stats->ls_percpu[0], stats->ls_percpu_size);
750 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
753 void lprocfs_clear_stats(struct lprocfs_stats *stats)
755 struct lprocfs_counter *percpu_cntr;
757 unsigned int num_cpu;
759 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
761 for (i = 0; i < num_cpu; i++) {
762 for (j = 0; j < stats->ls_num; j++) {
763 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
764 atomic_inc(&percpu_cntr->lc_cntl.la_entry);
765 percpu_cntr->lc_count = 0;
766 percpu_cntr->lc_sum = 0;
767 percpu_cntr->lc_min = ~(__u64)0;
768 percpu_cntr->lc_max = 0;
769 percpu_cntr->lc_sumsquare = 0;
770 atomic_inc(&percpu_cntr->lc_cntl.la_exit);
774 lprocfs_stats_unlock(stats);
777 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
778 size_t len, loff_t *off)
780 struct seq_file *seq = file->private_data;
781 struct lprocfs_stats *stats = seq->private;
783 lprocfs_clear_stats(stats);
788 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
790 struct lprocfs_stats *stats = p->private;
791 /* return 1st cpu location */
792 return (*pos >= stats->ls_num) ? NULL :
793 &(stats->ls_percpu[0]->lp_cntr[*pos]);
796 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
800 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
802 struct lprocfs_stats *stats = p->private;
804 return (*pos >= stats->ls_num) ? NULL :
805 &(stats->ls_percpu[0]->lp_cntr[*pos]);
808 /* seq file export of one lprocfs counter */
809 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
811 struct lprocfs_stats *stats = p->private;
812 struct lprocfs_counter *cntr = v;
813 struct lprocfs_counter t, ret = { .lc_min = ~(__u64)0 };
815 unsigned int num_cpu;
817 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
819 do_gettimeofday(&now);
820 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
821 "snapshot_time", now.tv_sec, now.tv_usec);
825 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
827 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
830 num_cpu = num_possible_cpus();
832 for (i = 0; i < num_cpu; i++) {
833 struct lprocfs_counter *percpu_cntr =
834 &(stats->ls_percpu[i])->lp_cntr[idx];
838 centry = atomic_read(&percpu_cntr->lc_cntl.la_entry);
839 t.lc_count = percpu_cntr->lc_count;
840 t.lc_sum = percpu_cntr->lc_sum;
841 t.lc_min = percpu_cntr->lc_min;
842 t.lc_max = percpu_cntr->lc_max;
843 t.lc_sumsquare = percpu_cntr->lc_sumsquare;
844 } while (centry != atomic_read(&percpu_cntr->lc_cntl.la_entry) &&
845 centry != atomic_read(&percpu_cntr->lc_cntl.la_exit));
846 ret.lc_count += t.lc_count;
847 ret.lc_sum += t.lc_sum;
848 if (t.lc_min < ret.lc_min)
849 ret.lc_min = t.lc_min;
850 if (t.lc_max > ret.lc_max)
851 ret.lc_max = t.lc_max;
852 ret.lc_sumsquare += t.lc_sumsquare;
855 rc = seq_printf(p, "%-25s "LPU64" samples [%s]", cntr->lc_name,
856 ret.lc_count, cntr->lc_units);
860 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
861 rc = seq_printf(p, " "LPU64" "LPU64" "LPU64,
862 ret.lc_min, ret.lc_max, ret.lc_sum);
865 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
866 rc = seq_printf(p, " "LPU64, ret.lc_sumsquare);
870 rc = seq_printf(p, "\n");
872 return (rc < 0) ? rc : 0;
875 struct seq_operations lprocfs_stats_seq_sops = {
876 start: lprocfs_stats_seq_start,
877 stop: lprocfs_stats_seq_stop,
878 next: lprocfs_stats_seq_next,
879 show: lprocfs_stats_seq_show,
882 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
884 struct proc_dir_entry *dp = PDE(inode);
885 struct seq_file *seq;
888 LPROCFS_ENTRY_AND_CHECK(dp);
889 rc = seq_open(file, &lprocfs_stats_seq_sops);
894 seq = file->private_data;
895 seq->private = dp->data;
899 struct file_operations lprocfs_stats_seq_fops = {
900 .owner = THIS_MODULE,
901 .open = lprocfs_stats_seq_open,
903 .write = lprocfs_stats_seq_write,
905 .release = lprocfs_seq_release,
908 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
909 struct lprocfs_stats *stats)
911 struct proc_dir_entry *entry;
912 LASSERT(root != NULL);
914 entry = create_proc_entry(name, 0644, root);
917 entry->proc_fops = &lprocfs_stats_seq_fops;
918 entry->data = (void *)stats;
922 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
923 unsigned conf, const char *name, const char *units)
925 struct lprocfs_counter *c;
927 unsigned int num_cpu;
929 LASSERT(stats != NULL);
931 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
933 for (i = 0; i < num_cpu; i++) {
934 c = &(stats->ls_percpu[i]->lp_cntr[index]);
938 c->lc_min = ~(__u64)0;
944 lprocfs_stats_unlock(stats);
946 EXPORT_SYMBOL(lprocfs_counter_init);
948 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
950 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
951 LASSERT(coffset < stats->ls_num); \
952 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
955 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
957 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
958 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
959 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
960 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
961 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
962 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
963 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
964 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
965 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
966 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
967 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
968 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
969 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
970 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
971 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
972 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
973 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
974 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
975 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
976 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
977 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
978 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
979 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
980 LPROCFS_OBD_OP_INIT(num_private_stats, stats, checkmd);
981 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
982 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
983 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
984 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
985 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
986 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
987 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
988 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
989 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
990 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw_async);
991 LPROCFS_OBD_OP_INIT(num_private_stats, stats, prep_async_page);
992 LPROCFS_OBD_OP_INIT(num_private_stats, stats, queue_async_io);
993 LPROCFS_OBD_OP_INIT(num_private_stats, stats, queue_group_io);
994 LPROCFS_OBD_OP_INIT(num_private_stats, stats, trigger_group_io);
995 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_async_flags);
996 LPROCFS_OBD_OP_INIT(num_private_stats, stats, teardown_async_page);
997 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
998 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
999 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1000 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1001 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1002 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1003 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1004 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1005 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1006 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1007 LPROCFS_OBD_OP_INIT(num_private_stats, stats, match);
1008 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1009 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1010 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1011 LPROCFS_OBD_OP_INIT(num_private_stats, stats, join_lru);
1012 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1013 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1014 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1015 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1016 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1017 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1018 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1019 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1020 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1021 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1022 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1023 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1024 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1025 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1028 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1030 struct lprocfs_stats *stats;
1031 unsigned int num_stats;
1034 LASSERT(obd->obd_stats == NULL);
1035 LASSERT(obd->obd_proc_entry != NULL);
1036 LASSERT(obd->obd_cntr_base == 0);
1038 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1039 num_private_stats - 1 /* o_owner */;
1040 stats = lprocfs_alloc_stats(num_stats, 0);
1044 lprocfs_init_ops_stats(num_private_stats, stats);
1046 for (i = num_private_stats; i < num_stats; i++) {
1047 /* If this LBUGs, it is likely that an obd
1048 * operation was added to struct obd_ops in
1049 * <obd.h>, and that the corresponding line item
1050 * LPROCFS_OBD_OP_INIT(.., .., opname)
1051 * is missing from the list above. */
1052 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1053 "Missing obd_stat initializer obd_op "
1054 "operation at offset %d.\n", i - num_private_stats);
1056 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1058 lprocfs_free_stats(&stats);
1060 obd->obd_stats = stats;
1061 obd->obd_cntr_base = num_private_stats;
1066 void lprocfs_free_obd_stats(struct obd_device *obd)
1069 lprocfs_free_stats(&obd->obd_stats);
1072 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1074 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1075 LASSERT(coffset < stats->ls_num); \
1076 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1079 int lprocfs_alloc_md_stats(struct obd_device *obd,
1080 unsigned num_private_stats)
1082 struct lprocfs_stats *stats;
1083 unsigned int num_stats;
1086 LASSERT(obd->md_stats == NULL);
1087 LASSERT(obd->obd_proc_entry != NULL);
1088 LASSERT(obd->md_cntr_base == 0);
1090 num_stats = 1 + MD_COUNTER_OFFSET(get_remote_perm) +
1092 stats = lprocfs_alloc_stats(num_stats, 0);
1096 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1097 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1098 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1099 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1100 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1101 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1102 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1103 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1104 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1105 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1106 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1107 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1108 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1109 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1110 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1111 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1112 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1113 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1114 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1115 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1116 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1117 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1118 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1119 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1120 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1121 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1122 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1123 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1125 for (i = num_private_stats; i < num_stats; i++) {
1126 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1127 CERROR("Missing md_stat initializer md_op "
1128 "operation at offset %d. Aborting.\n",
1129 i - num_private_stats);
1133 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1135 lprocfs_free_stats(&stats);
1137 obd->md_stats = stats;
1138 obd->md_cntr_base = num_private_stats;
1143 void lprocfs_free_md_stats(struct obd_device *obd)
1145 struct lprocfs_stats *stats = obd->md_stats;
1147 if (stats != NULL) {
1148 obd->md_stats = NULL;
1149 lprocfs_free_stats(&stats);
1153 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1154 int *eof, void *data)
1156 struct obd_export *exp = (struct obd_export*)data;
1157 LASSERT(exp != NULL);
1159 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1162 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1163 int *eof, void *data)
1165 struct obd_export *exp = (struct obd_export*)data;
1166 LASSERT(exp != NULL);
1168 return snprintf(page, count, "%s\n",
1169 obd_uuid2str(&exp->exp_client_uuid));
1172 int lprocfs_exp_setup(struct obd_export *exp)
1174 char name[sizeof (exp->exp_client_uuid.uuid) + 3];
1177 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports)
1179 mutex_down(&exp->exp_obd->obd_proc_exp_sem);
1180 sprintf(name, "%s", (char *)exp->exp_client_uuid.uuid);
1181 while (lprocfs_srch(exp->exp_obd->obd_proc_exports, name)) {
1182 /* We might add a new export before deleting the old one during
1183 an eviction (recovery-small 19a). Suckage. We
1184 could block, or come up with a new name, or just give up. */
1186 GOTO(out, rc = -EEXIST);
1187 sprintf(name, "%s:%d", (char *)exp->exp_client_uuid.uuid, i);
1190 /* Create a proc entry for this export */
1191 exp->exp_proc = proc_mkdir(name, exp->exp_obd->obd_proc_exports);
1192 if (!exp->exp_proc) {
1193 CERROR("Error making export directory for %s\n", name);
1194 GOTO(out, rc = -ENOMEM);
1197 /* Always add nid and uuid */
1198 rc = lprocfs_add_simple(exp->exp_proc, "nid",
1199 lprocfs_exp_rd_nid, NULL, exp);
1202 rc = lprocfs_add_simple(exp->exp_proc, "uuid",
1203 lprocfs_exp_rd_uuid, NULL, exp);
1206 /* Always add ldlm stats */
1207 exp->exp_ldlm_stats = lprocfs_alloc_stats(LDLM_LAST_OPC
1208 - LDLM_FIRST_OPC, 0);
1209 if (exp->exp_ldlm_stats == NULL) {
1210 lprocfs_remove(&exp->exp_proc);
1211 GOTO(out, rc = -ENOMEM);
1214 lprocfs_counter_init(exp->exp_ldlm_stats,
1215 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1216 0, "ldlm_enqueue", "reqs");
1217 lprocfs_counter_init(exp->exp_ldlm_stats,
1218 LDLM_CONVERT - LDLM_FIRST_OPC,
1219 0, "ldlm_convert", "reqs");
1220 lprocfs_counter_init(exp->exp_ldlm_stats,
1221 LDLM_CANCEL - LDLM_FIRST_OPC,
1222 0, "ldlm_cancel", "reqs");
1223 lprocfs_counter_init(exp->exp_ldlm_stats,
1224 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1225 0, "ldlm_bl_callback", "reqs");
1226 lprocfs_counter_init(exp->exp_ldlm_stats,
1227 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1228 0, "ldlm_cp_callback", "reqs");
1229 lprocfs_counter_init(exp->exp_ldlm_stats,
1230 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1231 0, "ldlm_gl_callback", "reqs");
1232 lprocfs_register_stats(exp->exp_proc, "ldlm_stats",
1233 exp->exp_ldlm_stats);
1235 mutex_up(&exp->exp_obd->obd_proc_exp_sem);
1239 int lprocfs_exp_cleanup(struct obd_export *exp)
1241 mutex_down(&exp->exp_obd->obd_proc_exp_sem);
1242 lprocfs_remove(&exp->exp_proc);
1243 lprocfs_free_stats(&exp->exp_ops_stats);
1244 lprocfs_free_stats(&exp->exp_ldlm_stats);
1245 mutex_up(&exp->exp_obd->obd_proc_exp_sem);
1249 int lprocfs_write_helper(const char *buffer, unsigned long count,
1252 return lprocfs_write_frac_helper(buffer, count, val, 1);
1255 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
1258 char kernbuf[20], *end, *pbuf;
1260 if (count > (sizeof(kernbuf) - 1))
1263 if (copy_from_user(kernbuf, buffer, count))
1266 kernbuf[count] = '\0';
1273 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1277 if (end != NULL && *end == '.') {
1278 int temp_val, pow = 1;
1282 if (strlen(pbuf) > 5)
1283 pbuf[5] = '\0'; /*only allow 5bits fractional*/
1285 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1288 for (i = 0; i < (end - pbuf); i++)
1291 *val += temp_val / pow;
1297 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val, int mult)
1299 long decimal_val, frac_val;
1305 decimal_val = val / mult;
1306 prtn = snprintf(buffer, count, "%ld", decimal_val);
1307 frac_val = val % mult;
1309 if (prtn < (count - 4) && frac_val > 0) {
1311 int i, temp_mult = 1, frac_bits = 0;
1313 temp_frac = frac_val * 10;
1314 buffer[prtn++] = '.';
1315 while (frac_bits < 2 && (temp_frac / mult) < 1 ) { /*only reserved 2bits fraction*/
1316 buffer[prtn++] ='0';
1321 Need to think these cases :
1322 1. #echo x.00 > /proc/xxx output result : x
1323 2. #echo x.0x > /proc/xxx output result : x.0x
1324 3. #echo x.x0 > /proc/xxx output result : x.x
1325 4. #echo x.xx > /proc/xxx output result : x.xx
1326 Only reserved 2bits fraction.
1328 for (i = 0; i < (5 - prtn); i++)
1331 frac_bits = min((int)count - prtn, 3 - frac_bits);
1332 prtn += snprintf(buffer + prtn, frac_bits, "%ld", frac_val * temp_mult / mult);
1335 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
1337 if (buffer[prtn] == '.') {
1344 buffer[prtn++] ='\n';
1348 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
1350 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
1353 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
1354 __u64 *val, int mult)
1356 char kernbuf[22], *end, *pbuf;
1357 __u64 whole, frac = 0, units;
1358 unsigned frac_d = 1;
1360 if (count > (sizeof(kernbuf) - 1) )
1363 if (copy_from_user(kernbuf, buffer, count))
1366 kernbuf[count] = '\0';
1373 whole = simple_strtoull(pbuf, &end, 10);
1377 if (end != NULL && *end == '.') {
1381 /* need to limit frac_d to a __u32 */
1382 if (strlen(pbuf) > 10)
1385 frac = simple_strtoull(pbuf, &end, 10);
1386 /* count decimal places */
1387 for (i = 0; i < (end - pbuf); i++)
1404 /* Specified units override the multiplier */
1406 mult = mult < 0 ? -units : units;
1409 do_div(frac, frac_d);
1410 *val = whole * mult + frac;
1414 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent,
1415 char *name, mode_t mode,
1416 struct file_operations *seq_fops, void *data)
1418 struct proc_dir_entry *entry;
1421 entry = create_proc_entry(name, mode, parent);
1424 entry->proc_fops = seq_fops;
1429 EXPORT_SYMBOL(lprocfs_seq_create);
1431 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
1433 struct file_operations *seq_fops,
1436 return (lprocfs_seq_create(dev->obd_proc_entry, name,
1437 mode, seq_fops, data));
1439 EXPORT_SYMBOL(lprocfs_obd_seq_create);
1441 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
1443 if (value >= OBD_HIST_MAX)
1444 value = OBD_HIST_MAX - 1;
1446 spin_lock(&oh->oh_lock);
1447 oh->oh_buckets[value]++;
1448 spin_unlock(&oh->oh_lock);
1450 EXPORT_SYMBOL(lprocfs_oh_tally);
1452 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
1456 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
1459 lprocfs_oh_tally(oh, val);
1461 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
1463 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
1465 unsigned long ret = 0;
1468 for (i = 0; i < OBD_HIST_MAX; i++)
1469 ret += oh->oh_buckets[i];
1472 EXPORT_SYMBOL(lprocfs_oh_sum);
1474 void lprocfs_oh_clear(struct obd_histogram *oh)
1476 spin_lock(&oh->oh_lock);
1477 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
1478 spin_unlock(&oh->oh_lock);
1480 EXPORT_SYMBOL(lprocfs_oh_clear);
1482 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
1483 int count, int *eof, void *data)
1485 struct obd_device *obd = data;
1488 LASSERT(obd != NULL);
1489 LASSERT(count >= 0);
1491 /* Set start of user data returned to
1492 page + off since the user may have
1493 requested to read much smaller than
1494 what we need to read */
1495 *start = page + off;
1497 /* We know we are allocated a page here.
1498 Also we know that this function will
1499 not need to write more than a page
1500 so we can truncate at CFS_PAGE_SIZE. */
1501 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
1503 /* Initialize the page */
1504 memset(page, 0, size);
1506 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
1509 if (obd->obd_max_recoverable_clients == 0) {
1510 lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n");
1514 /* sampled unlocked, but really... */
1515 if (obd->obd_recovering == 0) {
1516 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
1519 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
1520 obd->obd_recovery_start) <= 0)
1523 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_end: %lu\n",
1524 obd->obd_recovery_end) <= 0)
1527 /* Number of clients have have completed recovery */
1528 if (lprocfs_obd_snprintf(&page, size, &len, "recovered_clients: %d\n",
1529 obd->obd_max_recoverable_clients - obd->obd_recoverable_clients) <= 0)
1532 if (lprocfs_obd_snprintf(&page, size, &len, "unrecovered_clients: %d\n",
1533 obd->obd_recoverable_clients) <= 0)
1536 if (lprocfs_obd_snprintf(&page, size, &len, "last_transno: "LPD64"\n",
1537 obd->obd_next_recovery_transno - 1) <= 0)
1540 lprocfs_obd_snprintf(&page, size, &len, "replayed_requests: %d\n", obd->obd_replayed_requests);
1544 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
1547 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
1548 obd->obd_recovery_start) <= 0)
1551 if (lprocfs_obd_snprintf(&page, size, &len, "time remaining: %lu\n",
1552 CURRENT_SECONDS >= obd->obd_recovery_end ? 0 :
1553 obd->obd_recovery_end - CURRENT_SECONDS) <= 0)
1556 if(lprocfs_obd_snprintf(&page, size, &len, "connected_clients: %d/%d\n",
1557 obd->obd_connected_clients,
1558 obd->obd_max_recoverable_clients) <= 0)
1561 /* Number of clients have have completed recovery */
1562 if (lprocfs_obd_snprintf(&page, size, &len, "completed_clients: %d/%d\n",
1563 obd->obd_max_recoverable_clients - obd->obd_recoverable_clients,
1564 obd->obd_max_recoverable_clients) <= 0)
1567 if (lprocfs_obd_snprintf(&page, size, &len, "replayed_requests: %d/??\n",
1568 obd->obd_replayed_requests) <= 0)
1571 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
1572 obd->obd_requests_queued_for_recovery) <= 0)
1575 lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n", obd->obd_next_recovery_transno);
1580 return min(count, len - (int)off);
1582 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
1584 int lprocfs_obd_rd_recovery_maxtime(char *page, char **start, off_t off,
1585 int count, int *eof, void *data)
1587 struct obd_device *obd = (struct obd_device *)data;
1588 LASSERT(obd != NULL);
1590 return snprintf(page, count, "%lu\n",
1591 obd->obd_recovery_max_time);
1593 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_maxtime);
1595 int lprocfs_obd_wr_recovery_maxtime(struct file *file, const char *buffer,
1596 unsigned long count, void *data)
1598 struct obd_device *obd = (struct obd_device *)data;
1600 LASSERT(obd != NULL);
1602 rc = lprocfs_write_helper(buffer, count, &val);
1606 obd->obd_recovery_max_time = val;
1609 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_maxtime);
1611 EXPORT_SYMBOL(lprocfs_register);
1612 EXPORT_SYMBOL(lprocfs_srch);
1613 EXPORT_SYMBOL(lprocfs_remove);
1614 EXPORT_SYMBOL(lprocfs_add_vars);
1615 EXPORT_SYMBOL(lprocfs_obd_setup);
1616 EXPORT_SYMBOL(lprocfs_obd_cleanup);
1617 EXPORT_SYMBOL(lprocfs_alloc_stats);
1618 EXPORT_SYMBOL(lprocfs_free_stats);
1619 EXPORT_SYMBOL(lprocfs_clear_stats);
1620 EXPORT_SYMBOL(lprocfs_register_stats);
1621 EXPORT_SYMBOL(lprocfs_init_ops_stats);
1622 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
1623 EXPORT_SYMBOL(lprocfs_free_obd_stats);
1624 EXPORT_SYMBOL(lprocfs_exp_setup);
1625 EXPORT_SYMBOL(lprocfs_exp_cleanup);
1627 EXPORT_SYMBOL(lprocfs_rd_u64);
1628 EXPORT_SYMBOL(lprocfs_rd_atomic);
1629 EXPORT_SYMBOL(lprocfs_wr_atomic);
1630 EXPORT_SYMBOL(lprocfs_rd_uint);
1631 EXPORT_SYMBOL(lprocfs_wr_uint);
1632 EXPORT_SYMBOL(lprocfs_rd_uuid);
1633 EXPORT_SYMBOL(lprocfs_rd_name);
1634 EXPORT_SYMBOL(lprocfs_rd_fstype);
1635 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
1636 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
1637 EXPORT_SYMBOL(lprocfs_rd_num_exports);
1638 EXPORT_SYMBOL(lprocfs_rd_numrefs);
1640 EXPORT_SYMBOL(lprocfs_rd_blksize);
1641 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
1642 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
1643 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
1644 EXPORT_SYMBOL(lprocfs_rd_filestotal);
1645 EXPORT_SYMBOL(lprocfs_rd_filesfree);
1647 EXPORT_SYMBOL(lprocfs_write_helper);
1648 EXPORT_SYMBOL(lprocfs_write_frac_helper);
1649 EXPORT_SYMBOL(lprocfs_read_frac_helper);
1650 EXPORT_SYMBOL(lprocfs_write_u64_helper);
1651 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);