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",
611 int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
612 int count, int *eof, void *data)
614 struct obd_device *obd = data;
615 __u64 mask = 1, flags;
618 LPROCFS_CLIMP_CHECK(obd);
619 flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
620 ret = snprintf(page, count, "flags="LPX64"\n", flags);
621 for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
623 ret += snprintf(page + ret, count - ret, "%s\n",
624 obd_connect_names[i]);
626 if (flags & ~(mask - 1))
627 ret += snprintf(page + ret, count - ret,
628 "unknown flags "LPX64"\n", flags & ~(mask - 1));
630 LPROCFS_CLIMP_EXIT(obd);
633 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
635 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
636 int *eof, void *data)
638 struct obd_device *obd = (struct obd_device*)data;
640 LASSERT(obd != NULL);
642 return snprintf(page, count, "%u\n", obd->obd_num_exports);
645 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
646 int *eof, void *data)
648 struct obd_type *class = (struct obd_type*) data;
650 LASSERT(class != NULL);
652 return snprintf(page, count, "%d\n", class->typ_refcnt);
655 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
659 LASSERT(obd != NULL);
660 LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
661 LASSERT(obd->obd_type->typ_procroot != NULL);
663 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
664 obd->obd_type->typ_procroot,
666 if (IS_ERR(obd->obd_proc_entry)) {
667 rc = PTR_ERR(obd->obd_proc_entry);
668 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
669 obd->obd_proc_entry = NULL;
674 int lprocfs_obd_cleanup(struct obd_device *obd)
678 if (obd->obd_proc_exports) {
679 /* Should be no exports left */
680 LASSERT(obd->obd_proc_exports->subdir == NULL);
681 lprocfs_remove(&obd->obd_proc_exports);
683 lprocfs_remove(&obd->obd_proc_entry);
687 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
688 enum lprocfs_stats_flags flags)
690 struct lprocfs_stats *stats;
691 struct lprocfs_percpu *percpu;
692 unsigned int percpusize;
694 unsigned int num_cpu;
699 if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
702 num_cpu = num_possible_cpus();
704 OBD_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
708 if (flags & LPROCFS_STATS_FLAG_NOPERCPU) {
709 stats->ls_flags = flags;
710 spin_lock_init(&stats->ls_lock);
711 /* Use this lock only if there are no percpu areas */
716 percpusize = offsetof(typeof(*percpu), lp_cntr[num]);
718 percpusize = L1_CACHE_ALIGN(percpusize);
720 stats->ls_percpu_size = num_cpu * percpusize;
721 OBD_ALLOC(stats->ls_percpu[0], stats->ls_percpu_size);
722 if (stats->ls_percpu[0] == NULL) {
723 OBD_FREE(stats, offsetof(typeof(*stats),
724 ls_percpu[num_cpu]));
729 for (i = 1; i < num_cpu; i++)
730 stats->ls_percpu[i] = (void *)(stats->ls_percpu[i - 1]) +
736 void lprocfs_free_stats(struct lprocfs_stats **statsh)
738 struct lprocfs_stats *stats = *statsh;
739 unsigned int num_cpu;
741 if (stats == NULL || stats->ls_num == 0)
745 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
748 num_cpu = num_possible_cpus();
750 OBD_FREE(stats->ls_percpu[0], stats->ls_percpu_size);
751 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_cpu]));
754 void lprocfs_clear_stats(struct lprocfs_stats *stats)
756 struct lprocfs_counter *percpu_cntr;
758 unsigned int num_cpu;
760 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
762 for (i = 0; i < num_cpu; i++) {
763 for (j = 0; j < stats->ls_num; j++) {
764 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
765 atomic_inc(&percpu_cntr->lc_cntl.la_entry);
766 percpu_cntr->lc_count = 0;
767 percpu_cntr->lc_sum = 0;
768 percpu_cntr->lc_min = ~(__u64)0;
769 percpu_cntr->lc_max = 0;
770 percpu_cntr->lc_sumsquare = 0;
771 atomic_inc(&percpu_cntr->lc_cntl.la_exit);
775 lprocfs_stats_unlock(stats);
778 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
779 size_t len, loff_t *off)
781 struct seq_file *seq = file->private_data;
782 struct lprocfs_stats *stats = seq->private;
784 lprocfs_clear_stats(stats);
789 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
791 struct lprocfs_stats *stats = p->private;
792 /* return 1st cpu location */
793 return (*pos >= stats->ls_num) ? NULL :
794 &(stats->ls_percpu[0]->lp_cntr[*pos]);
797 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
801 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
803 struct lprocfs_stats *stats = p->private;
805 return (*pos >= stats->ls_num) ? NULL :
806 &(stats->ls_percpu[0]->lp_cntr[*pos]);
809 /* seq file export of one lprocfs counter */
810 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
812 struct lprocfs_stats *stats = p->private;
813 struct lprocfs_counter *cntr = v;
814 struct lprocfs_counter t, ret = { .lc_min = ~(__u64)0 };
816 unsigned int num_cpu;
818 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
820 do_gettimeofday(&now);
821 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
822 "snapshot_time", now.tv_sec, now.tv_usec);
826 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
828 if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
831 num_cpu = num_possible_cpus();
833 for (i = 0; i < num_cpu; i++) {
834 struct lprocfs_counter *percpu_cntr =
835 &(stats->ls_percpu[i])->lp_cntr[idx];
839 centry = atomic_read(&percpu_cntr->lc_cntl.la_entry);
840 t.lc_count = percpu_cntr->lc_count;
841 t.lc_sum = percpu_cntr->lc_sum;
842 t.lc_min = percpu_cntr->lc_min;
843 t.lc_max = percpu_cntr->lc_max;
844 t.lc_sumsquare = percpu_cntr->lc_sumsquare;
845 } while (centry != atomic_read(&percpu_cntr->lc_cntl.la_entry) &&
846 centry != atomic_read(&percpu_cntr->lc_cntl.la_exit));
847 ret.lc_count += t.lc_count;
848 ret.lc_sum += t.lc_sum;
849 if (t.lc_min < ret.lc_min)
850 ret.lc_min = t.lc_min;
851 if (t.lc_max > ret.lc_max)
852 ret.lc_max = t.lc_max;
853 ret.lc_sumsquare += t.lc_sumsquare;
856 rc = seq_printf(p, "%-25s "LPU64" samples [%s]", cntr->lc_name,
857 ret.lc_count, cntr->lc_units);
861 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
862 rc = seq_printf(p, " "LPU64" "LPU64" "LPU64,
863 ret.lc_min, ret.lc_max, ret.lc_sum);
866 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
867 rc = seq_printf(p, " "LPU64, ret.lc_sumsquare);
871 rc = seq_printf(p, "\n");
873 return (rc < 0) ? rc : 0;
876 struct seq_operations lprocfs_stats_seq_sops = {
877 start: lprocfs_stats_seq_start,
878 stop: lprocfs_stats_seq_stop,
879 next: lprocfs_stats_seq_next,
880 show: lprocfs_stats_seq_show,
883 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
885 struct proc_dir_entry *dp = PDE(inode);
886 struct seq_file *seq;
889 LPROCFS_ENTRY_AND_CHECK(dp);
890 rc = seq_open(file, &lprocfs_stats_seq_sops);
895 seq = file->private_data;
896 seq->private = dp->data;
900 struct file_operations lprocfs_stats_seq_fops = {
901 .owner = THIS_MODULE,
902 .open = lprocfs_stats_seq_open,
904 .write = lprocfs_stats_seq_write,
906 .release = lprocfs_seq_release,
909 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
910 struct lprocfs_stats *stats)
912 struct proc_dir_entry *entry;
913 LASSERT(root != NULL);
915 entry = create_proc_entry(name, 0644, root);
918 entry->proc_fops = &lprocfs_stats_seq_fops;
919 entry->data = (void *)stats;
923 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
924 unsigned conf, const char *name, const char *units)
926 struct lprocfs_counter *c;
928 unsigned int num_cpu;
930 LASSERT(stats != NULL);
932 num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
934 for (i = 0; i < num_cpu; i++) {
935 c = &(stats->ls_percpu[i]->lp_cntr[index]);
939 c->lc_min = ~(__u64)0;
945 lprocfs_stats_unlock(stats);
947 EXPORT_SYMBOL(lprocfs_counter_init);
949 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
951 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
952 LASSERT(coffset < stats->ls_num); \
953 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
956 void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
958 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
959 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
960 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
961 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
962 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
963 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
964 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
965 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
966 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
967 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
968 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
969 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
970 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
971 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
972 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
973 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
974 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
975 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
976 LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_delete);
977 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
978 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
979 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
980 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
981 LPROCFS_OBD_OP_INIT(num_private_stats, stats, checkmd);
982 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
983 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
984 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
985 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
986 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
987 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
988 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
989 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
990 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
991 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw_async);
992 LPROCFS_OBD_OP_INIT(num_private_stats, stats, prep_async_page);
993 LPROCFS_OBD_OP_INIT(num_private_stats, stats, queue_async_io);
994 LPROCFS_OBD_OP_INIT(num_private_stats, stats, queue_group_io);
995 LPROCFS_OBD_OP_INIT(num_private_stats, stats, trigger_group_io);
996 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_async_flags);
997 LPROCFS_OBD_OP_INIT(num_private_stats, stats, teardown_async_page);
998 LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
999 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
1000 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
1001 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
1002 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
1003 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
1004 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
1005 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
1006 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
1007 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
1008 LPROCFS_OBD_OP_INIT(num_private_stats, stats, match);
1009 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
1010 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
1011 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
1012 LPROCFS_OBD_OP_INIT(num_private_stats, stats, join_lru);
1013 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
1014 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
1015 LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
1016 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
1017 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
1018 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
1019 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
1020 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
1021 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
1022 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
1023 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
1024 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
1025 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
1026 LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
1029 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
1031 struct lprocfs_stats *stats;
1032 unsigned int num_stats;
1035 LASSERT(obd->obd_stats == NULL);
1036 LASSERT(obd->obd_proc_entry != NULL);
1037 LASSERT(obd->obd_cntr_base == 0);
1039 num_stats = ((int)sizeof(*obd->obd_type->typ_dt_ops) / sizeof(void *)) +
1040 num_private_stats - 1 /* o_owner */;
1041 stats = lprocfs_alloc_stats(num_stats, 0);
1045 lprocfs_init_ops_stats(num_private_stats, stats);
1047 for (i = num_private_stats; i < num_stats; i++) {
1048 /* If this LBUGs, it is likely that an obd
1049 * operation was added to struct obd_ops in
1050 * <obd.h>, and that the corresponding line item
1051 * LPROCFS_OBD_OP_INIT(.., .., opname)
1052 * is missing from the list above. */
1053 LASSERTF(stats->ls_percpu[0]->lp_cntr[i].lc_name != NULL,
1054 "Missing obd_stat initializer obd_op "
1055 "operation at offset %d.\n", i - num_private_stats);
1057 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1059 lprocfs_free_stats(&stats);
1061 obd->obd_stats = stats;
1062 obd->obd_cntr_base = num_private_stats;
1067 void lprocfs_free_obd_stats(struct obd_device *obd)
1070 lprocfs_free_stats(&obd->obd_stats);
1073 #define LPROCFS_MD_OP_INIT(base, stats, op) \
1075 unsigned int coffset = base + MD_COUNTER_OFFSET(op); \
1076 LASSERT(coffset < stats->ls_num); \
1077 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
1080 int lprocfs_alloc_md_stats(struct obd_device *obd,
1081 unsigned num_private_stats)
1083 struct lprocfs_stats *stats;
1084 unsigned int num_stats;
1087 LASSERT(obd->md_stats == NULL);
1088 LASSERT(obd->obd_proc_entry != NULL);
1089 LASSERT(obd->md_cntr_base == 0);
1091 num_stats = 1 + MD_COUNTER_OFFSET(get_remote_perm) +
1093 stats = lprocfs_alloc_stats(num_stats, 0);
1097 LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus);
1098 LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata);
1099 LPROCFS_MD_OP_INIT(num_private_stats, stats, close);
1100 LPROCFS_MD_OP_INIT(num_private_stats, stats, create);
1101 LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing);
1102 LPROCFS_MD_OP_INIT(num_private_stats, stats, enqueue);
1103 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr);
1104 LPROCFS_MD_OP_INIT(num_private_stats, stats, getattr_name);
1105 LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_lock);
1106 LPROCFS_MD_OP_INIT(num_private_stats, stats, link);
1107 LPROCFS_MD_OP_INIT(num_private_stats, stats, rename);
1108 LPROCFS_MD_OP_INIT(num_private_stats, stats, is_subdir);
1109 LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
1110 LPROCFS_MD_OP_INIT(num_private_stats, stats, sync);
1111 LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
1112 LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
1113 LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
1114 LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
1115 LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
1116 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
1117 LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
1118 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
1119 LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
1120 LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
1121 LPROCFS_MD_OP_INIT(num_private_stats, stats, lock_match);
1122 LPROCFS_MD_OP_INIT(num_private_stats, stats, cancel_unused);
1123 LPROCFS_MD_OP_INIT(num_private_stats, stats, renew_capa);
1124 LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm);
1126 for (i = num_private_stats; i < num_stats; i++) {
1127 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
1128 CERROR("Missing md_stat initializer md_op "
1129 "operation at offset %d. Aborting.\n",
1130 i - num_private_stats);
1134 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
1136 lprocfs_free_stats(&stats);
1138 obd->md_stats = stats;
1139 obd->md_cntr_base = num_private_stats;
1144 void lprocfs_free_md_stats(struct obd_device *obd)
1146 struct lprocfs_stats *stats = obd->md_stats;
1148 if (stats != NULL) {
1149 obd->md_stats = NULL;
1150 lprocfs_free_stats(&stats);
1154 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
1155 int *eof, void *data)
1157 struct obd_export *exp = (struct obd_export*)data;
1158 LASSERT(exp != NULL);
1160 return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
1163 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
1164 int *eof, void *data)
1166 struct obd_export *exp = (struct obd_export*)data;
1167 LASSERT(exp != NULL);
1169 return snprintf(page, count, "%s\n",
1170 obd_uuid2str(&exp->exp_client_uuid));
1173 int lprocfs_exp_setup(struct obd_export *exp)
1175 char name[sizeof (exp->exp_client_uuid.uuid) + 3];
1178 if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports)
1180 mutex_down(&exp->exp_obd->obd_proc_exp_sem);
1181 sprintf(name, "%s", (char *)exp->exp_client_uuid.uuid);
1182 while (lprocfs_srch(exp->exp_obd->obd_proc_exports, name)) {
1183 /* We might add a new export before deleting the old one during
1184 an eviction (recovery-small 19a). Suckage. We
1185 could block, or come up with a new name, or just give up. */
1187 GOTO(out, rc = -EEXIST);
1188 sprintf(name, "%s:%d", (char *)exp->exp_client_uuid.uuid, i);
1191 /* Create a proc entry for this export */
1192 exp->exp_proc = proc_mkdir(name, exp->exp_obd->obd_proc_exports);
1193 if (!exp->exp_proc) {
1194 CERROR("Error making export directory for %s\n", name);
1195 GOTO(out, rc = -ENOMEM);
1198 /* Always add nid and uuid */
1199 rc = lprocfs_add_simple(exp->exp_proc, "nid",
1200 lprocfs_exp_rd_nid, NULL, exp);
1203 rc = lprocfs_add_simple(exp->exp_proc, "uuid",
1204 lprocfs_exp_rd_uuid, NULL, exp);
1207 /* Always add ldlm stats */
1208 exp->exp_ldlm_stats = lprocfs_alloc_stats(LDLM_LAST_OPC
1209 - LDLM_FIRST_OPC, 0);
1210 if (exp->exp_ldlm_stats == NULL) {
1211 lprocfs_remove(&exp->exp_proc);
1212 GOTO(out, rc = -ENOMEM);
1215 lprocfs_counter_init(exp->exp_ldlm_stats,
1216 LDLM_ENQUEUE - LDLM_FIRST_OPC,
1217 0, "ldlm_enqueue", "reqs");
1218 lprocfs_counter_init(exp->exp_ldlm_stats,
1219 LDLM_CONVERT - LDLM_FIRST_OPC,
1220 0, "ldlm_convert", "reqs");
1221 lprocfs_counter_init(exp->exp_ldlm_stats,
1222 LDLM_CANCEL - LDLM_FIRST_OPC,
1223 0, "ldlm_cancel", "reqs");
1224 lprocfs_counter_init(exp->exp_ldlm_stats,
1225 LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
1226 0, "ldlm_bl_callback", "reqs");
1227 lprocfs_counter_init(exp->exp_ldlm_stats,
1228 LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
1229 0, "ldlm_cp_callback", "reqs");
1230 lprocfs_counter_init(exp->exp_ldlm_stats,
1231 LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
1232 0, "ldlm_gl_callback", "reqs");
1233 lprocfs_register_stats(exp->exp_proc, "ldlm_stats",
1234 exp->exp_ldlm_stats);
1236 mutex_up(&exp->exp_obd->obd_proc_exp_sem);
1240 int lprocfs_exp_cleanup(struct obd_export *exp)
1242 mutex_down(&exp->exp_obd->obd_proc_exp_sem);
1243 lprocfs_remove(&exp->exp_proc);
1244 lprocfs_free_stats(&exp->exp_ops_stats);
1245 lprocfs_free_stats(&exp->exp_ldlm_stats);
1246 mutex_up(&exp->exp_obd->obd_proc_exp_sem);
1250 int lprocfs_write_helper(const char *buffer, unsigned long count,
1253 return lprocfs_write_frac_helper(buffer, count, val, 1);
1256 int lprocfs_write_frac_helper(const char *buffer, unsigned long count,
1259 char kernbuf[20], *end, *pbuf;
1261 if (count > (sizeof(kernbuf) - 1))
1264 if (copy_from_user(kernbuf, buffer, count))
1267 kernbuf[count] = '\0';
1274 *val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1278 if (end != NULL && *end == '.') {
1279 int temp_val, pow = 1;
1283 if (strlen(pbuf) > 5)
1284 pbuf[5] = '\0'; /*only allow 5bits fractional*/
1286 temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
1289 for (i = 0; i < (end - pbuf); i++)
1292 *val += temp_val / pow;
1298 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val, int mult)
1300 long decimal_val, frac_val;
1306 decimal_val = val / mult;
1307 prtn = snprintf(buffer, count, "%ld", decimal_val);
1308 frac_val = val % mult;
1310 if (prtn < (count - 4) && frac_val > 0) {
1312 int i, temp_mult = 1, frac_bits = 0;
1314 temp_frac = frac_val * 10;
1315 buffer[prtn++] = '.';
1316 while (frac_bits < 2 && (temp_frac / mult) < 1 ) { /*only reserved 2bits fraction*/
1317 buffer[prtn++] ='0';
1322 Need to think these cases :
1323 1. #echo x.00 > /proc/xxx output result : x
1324 2. #echo x.0x > /proc/xxx output result : x.0x
1325 3. #echo x.x0 > /proc/xxx output result : x.x
1326 4. #echo x.xx > /proc/xxx output result : x.xx
1327 Only reserved 2bits fraction.
1329 for (i = 0; i < (5 - prtn); i++)
1332 frac_bits = min((int)count - prtn, 3 - frac_bits);
1333 prtn += snprintf(buffer + prtn, frac_bits, "%ld", frac_val * temp_mult / mult);
1336 while(buffer[prtn] < '1' || buffer[prtn] > '9') {
1338 if (buffer[prtn] == '.') {
1345 buffer[prtn++] ='\n';
1349 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
1351 return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
1354 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
1355 __u64 *val, int mult)
1357 char kernbuf[22], *end, *pbuf;
1358 __u64 whole, frac = 0, units;
1359 unsigned frac_d = 1;
1361 if (count > (sizeof(kernbuf) - 1) )
1364 if (copy_from_user(kernbuf, buffer, count))
1367 kernbuf[count] = '\0';
1374 whole = simple_strtoull(pbuf, &end, 10);
1378 if (end != NULL && *end == '.') {
1382 /* need to limit frac_d to a __u32 */
1383 if (strlen(pbuf) > 10)
1386 frac = simple_strtoull(pbuf, &end, 10);
1387 /* count decimal places */
1388 for (i = 0; i < (end - pbuf); i++)
1405 /* Specified units override the multiplier */
1407 mult = mult < 0 ? -units : units;
1410 do_div(frac, frac_d);
1411 *val = whole * mult + frac;
1415 int lprocfs_seq_create(cfs_proc_dir_entry_t *parent,
1416 char *name, mode_t mode,
1417 struct file_operations *seq_fops, void *data)
1419 struct proc_dir_entry *entry;
1422 entry = create_proc_entry(name, mode, parent);
1425 entry->proc_fops = seq_fops;
1430 EXPORT_SYMBOL(lprocfs_seq_create);
1432 __inline__ int lprocfs_obd_seq_create(struct obd_device *dev, char *name,
1434 struct file_operations *seq_fops,
1437 return (lprocfs_seq_create(dev->obd_proc_entry, name,
1438 mode, seq_fops, data));
1440 EXPORT_SYMBOL(lprocfs_obd_seq_create);
1442 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
1444 if (value >= OBD_HIST_MAX)
1445 value = OBD_HIST_MAX - 1;
1447 spin_lock(&oh->oh_lock);
1448 oh->oh_buckets[value]++;
1449 spin_unlock(&oh->oh_lock);
1451 EXPORT_SYMBOL(lprocfs_oh_tally);
1453 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
1457 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
1460 lprocfs_oh_tally(oh, val);
1462 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
1464 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
1466 unsigned long ret = 0;
1469 for (i = 0; i < OBD_HIST_MAX; i++)
1470 ret += oh->oh_buckets[i];
1473 EXPORT_SYMBOL(lprocfs_oh_sum);
1475 void lprocfs_oh_clear(struct obd_histogram *oh)
1477 spin_lock(&oh->oh_lock);
1478 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
1479 spin_unlock(&oh->oh_lock);
1481 EXPORT_SYMBOL(lprocfs_oh_clear);
1483 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
1484 int count, int *eof, void *data)
1486 struct obd_device *obd = data;
1489 LASSERT(obd != NULL);
1490 LASSERT(count >= 0);
1492 /* Set start of user data returned to
1493 page + off since the user may have
1494 requested to read much smaller than
1495 what we need to read */
1496 *start = page + off;
1498 /* We know we are allocated a page here.
1499 Also we know that this function will
1500 not need to write more than a page
1501 so we can truncate at CFS_PAGE_SIZE. */
1502 size = min(count + (int)off + 1, (int)CFS_PAGE_SIZE);
1504 /* Initialize the page */
1505 memset(page, 0, size);
1507 if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
1510 if (obd->obd_max_recoverable_clients == 0) {
1511 if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
1517 /* sampled unlocked, but really... */
1518 if (obd->obd_recovering == 0) {
1519 if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
1522 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
1523 obd->obd_recovery_start) <= 0)
1526 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_end: %lu\n",
1527 obd->obd_recovery_end) <= 0)
1530 /* Number of clients have have completed recovery */
1531 if (lprocfs_obd_snprintf(&page, size, &len, "recovered_clients: %d\n",
1532 obd->obd_max_recoverable_clients - obd->obd_recoverable_clients) <= 0)
1535 if (lprocfs_obd_snprintf(&page, size, &len, "unrecovered_clients: %d\n",
1536 obd->obd_recoverable_clients) <= 0)
1539 if (lprocfs_obd_snprintf(&page, size, &len, "last_transno: "LPD64"\n",
1540 obd->obd_next_recovery_transno - 1) <= 0)
1543 lprocfs_obd_snprintf(&page, size, &len, "replayed_requests: %d\n", obd->obd_replayed_requests);
1547 if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
1550 if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
1551 obd->obd_recovery_start) <= 0)
1554 if (lprocfs_obd_snprintf(&page, size, &len, "time remaining: %lu\n",
1555 CURRENT_SECONDS >= obd->obd_recovery_end ? 0 :
1556 obd->obd_recovery_end - CURRENT_SECONDS) <= 0)
1559 if(lprocfs_obd_snprintf(&page, size, &len, "connected_clients: %d/%d\n",
1560 obd->obd_connected_clients,
1561 obd->obd_max_recoverable_clients) <= 0)
1564 /* Number of clients have have completed recovery */
1565 if (lprocfs_obd_snprintf(&page, size, &len, "completed_clients: %d/%d\n",
1566 obd->obd_max_recoverable_clients - obd->obd_recoverable_clients,
1567 obd->obd_max_recoverable_clients) <= 0)
1570 if (lprocfs_obd_snprintf(&page, size, &len, "replayed_requests: %d/??\n",
1571 obd->obd_replayed_requests) <= 0)
1574 if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
1575 obd->obd_requests_queued_for_recovery) <= 0)
1578 if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
1579 obd->obd_next_recovery_transno) <= 0)
1585 return min(count, len - (int)off);
1587 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
1589 int lprocfs_obd_rd_recovery_maxtime(char *page, char **start, off_t off,
1590 int count, int *eof, void *data)
1592 struct obd_device *obd = (struct obd_device *)data;
1593 LASSERT(obd != NULL);
1595 return snprintf(page, count, "%lu\n",
1596 obd->obd_recovery_max_time);
1598 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_maxtime);
1600 int lprocfs_obd_wr_recovery_maxtime(struct file *file, const char *buffer,
1601 unsigned long count, void *data)
1603 struct obd_device *obd = (struct obd_device *)data;
1605 LASSERT(obd != NULL);
1607 rc = lprocfs_write_helper(buffer, count, &val);
1611 obd->obd_recovery_max_time = val;
1614 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_maxtime);
1616 EXPORT_SYMBOL(lprocfs_register);
1617 EXPORT_SYMBOL(lprocfs_srch);
1618 EXPORT_SYMBOL(lprocfs_remove);
1619 EXPORT_SYMBOL(lprocfs_add_vars);
1620 EXPORT_SYMBOL(lprocfs_obd_setup);
1621 EXPORT_SYMBOL(lprocfs_obd_cleanup);
1622 EXPORT_SYMBOL(lprocfs_alloc_stats);
1623 EXPORT_SYMBOL(lprocfs_free_stats);
1624 EXPORT_SYMBOL(lprocfs_clear_stats);
1625 EXPORT_SYMBOL(lprocfs_register_stats);
1626 EXPORT_SYMBOL(lprocfs_init_ops_stats);
1627 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
1628 EXPORT_SYMBOL(lprocfs_free_obd_stats);
1629 EXPORT_SYMBOL(lprocfs_exp_setup);
1630 EXPORT_SYMBOL(lprocfs_exp_cleanup);
1632 EXPORT_SYMBOL(lprocfs_rd_u64);
1633 EXPORT_SYMBOL(lprocfs_rd_atomic);
1634 EXPORT_SYMBOL(lprocfs_wr_atomic);
1635 EXPORT_SYMBOL(lprocfs_rd_uint);
1636 EXPORT_SYMBOL(lprocfs_wr_uint);
1637 EXPORT_SYMBOL(lprocfs_rd_uuid);
1638 EXPORT_SYMBOL(lprocfs_rd_name);
1639 EXPORT_SYMBOL(lprocfs_rd_fstype);
1640 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
1641 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
1642 EXPORT_SYMBOL(lprocfs_rd_num_exports);
1643 EXPORT_SYMBOL(lprocfs_rd_numrefs);
1645 EXPORT_SYMBOL(lprocfs_rd_blksize);
1646 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
1647 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
1648 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
1649 EXPORT_SYMBOL(lprocfs_rd_filestotal);
1650 EXPORT_SYMBOL(lprocfs_rd_filesfree);
1652 EXPORT_SYMBOL(lprocfs_write_helper);
1653 EXPORT_SYMBOL(lprocfs_write_frac_helper);
1654 EXPORT_SYMBOL(lprocfs_read_frac_helper);
1655 EXPORT_SYMBOL(lprocfs_write_u64_helper);
1656 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);