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 <linux/config.h>
33 # include <linux/module.h>
34 # include <linux/version.h>
35 # include <linux/slab.h>
36 # include <linux/types.h>
37 # if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
38 # include <asm/statfs.h>
40 # include <linux/seq_file.h>
41 #else /* __KERNEL__ */
42 # include <liblustre.h>
45 #include <linux/obd_class.h>
46 #include <linux/lprocfs_status.h>
47 #include <linux/lustre_fsfilt.h>
51 struct proc_dir_entry *lprocfs_srch(struct proc_dir_entry *head,
54 struct proc_dir_entry *temp;
60 while (temp != NULL) {
61 if (strcmp(temp->name, name) == 0)
69 /* lprocfs API calls */
71 int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list,
74 if (root == NULL || list == NULL)
77 while (list->name != NULL) {
78 struct proc_dir_entry *cur_root, *proc;
79 char *pathcopy, *cur, *next, pathbuf[64];
80 int pathsize = strlen(list->name) + 1;
85 /* need copy of path for strsep */
86 if (strlen(list->name) > sizeof(pathbuf) - 1) {
87 OBD_ALLOC(pathcopy, pathsize);
95 strcpy(pathcopy, list->name);
97 while (cur_root != NULL && (cur = strsep(&next, "/"))) {
98 if (*cur =='\0') /* skip double/trailing "/" */
101 proc = lprocfs_srch(cur_root, cur);
102 CDEBUG(D_OTHER, "cur_root=%s, cur=%s, next=%s, (%s)\n",
103 cur_root->name, cur, next,
104 (proc ? "exists" : "new"));
106 cur_root = (proc ? proc :
107 proc_mkdir(cur, cur_root));
108 } else if (proc == NULL) {
112 if (list->write_fptr)
114 proc = create_proc_entry(cur, mode, cur_root);
118 if (pathcopy != pathbuf)
119 OBD_FREE(pathcopy, pathsize);
121 if (cur_root == NULL || proc == NULL) {
122 CERROR("LprocFS: No memory to create /proc entry %s",
127 proc->read_proc = list->read_fptr;
128 proc->write_proc = list->write_fptr;
129 proc->data = (list->data ? list->data : data);
135 void lprocfs_remove(struct proc_dir_entry *root)
137 struct proc_dir_entry *temp = root;
138 struct proc_dir_entry *rm_entry;
139 struct proc_dir_entry *parent;
141 LASSERT(root != NULL);
142 parent = root->parent;
143 LASSERT(parent != NULL);
146 while (temp->subdir != NULL)
152 /* Memory corruption once caused this to fail, and
153 without this LASSERT we would loop here forever. */
154 LASSERTF(strlen(rm_entry->name) == rm_entry->namelen,
155 "0x%p %s/%s len %d\n", rm_entry, temp->name,
156 rm_entry->name, (int)strlen(rm_entry->name));
158 remove_proc_entry(rm_entry->name, rm_entry->parent);
164 struct proc_dir_entry *lprocfs_register(const char *name,
165 struct proc_dir_entry *parent,
166 struct lprocfs_vars *list, void *data)
168 struct proc_dir_entry *newchild;
170 newchild = lprocfs_srch(parent, name);
171 if (newchild != NULL) {
172 CERROR(" Lproc: Attempting to register %s more than once \n",
174 return ERR_PTR(-EALREADY);
177 newchild = proc_mkdir(name, parent);
178 if (newchild != NULL && list != NULL) {
179 int rc = lprocfs_add_vars(newchild, list, data);
181 lprocfs_remove(newchild);
188 /* Generic callbacks */
190 int lprocfs_rd_u64(char *page, char **start, off_t off,
191 int count, int *eof, void *data)
193 LASSERT(data != NULL);
195 return snprintf(page, count, LPU64"\n", *(__u64 *)data);
198 int lprocfs_rd_atomic(char *page, char **start, off_t off,
199 int count, int *eof, void *data)
201 atomic_t *atom = (atomic_t *)data;
202 LASSERT(atom != NULL);
204 return snprintf(page, count, "%d\n", atomic_read(atom));
207 int lprocfs_rd_uuid(char *page, char **start, off_t off, int count,
208 int *eof, void *data)
210 struct obd_device *obd = (struct obd_device*)data;
212 LASSERT(obd != NULL);
214 return snprintf(page, count, "%s\n", obd->obd_uuid.uuid);
217 int lprocfs_rd_name(char *page, char **start, off_t off, int count,
218 int *eof, void* data)
220 struct obd_device *dev = (struct obd_device *)data;
222 LASSERT(dev != NULL);
223 LASSERT(dev->obd_name != NULL);
225 return snprintf(page, count, "%s\n", dev->obd_name);
228 int lprocfs_rd_fstype(char *page, char **start, off_t off, int count, int *eof,
231 struct obd_device *obd = (struct obd_device *)data;
233 LASSERT(obd != NULL);
234 LASSERT(obd->obd_fsops != NULL);
235 LASSERT(obd->obd_fsops->fs_type != NULL);
236 return snprintf(page, count, "%s\n", obd->obd_fsops->fs_type);
239 int lprocfs_rd_blksize(char *page, char **start, off_t off, int count,
240 int *eof, void *data)
242 struct obd_statfs osfs;
243 int rc = obd_statfs(data, &osfs, jiffies - HZ);
246 rc = snprintf(page, count, "%u\n", osfs.os_bsize);
251 int lprocfs_rd_kbytestotal(char *page, char **start, off_t off, int count,
252 int *eof, void *data)
254 struct obd_statfs osfs;
255 int rc = obd_statfs(data, &osfs, jiffies - HZ);
257 __u32 blk_size = osfs.os_bsize >> 10;
258 __u64 result = osfs.os_blocks;
260 while (blk_size >>= 1)
264 rc = snprintf(page, count, LPU64"\n", result);
269 int lprocfs_rd_kbytesfree(char *page, char **start, off_t off, int count,
270 int *eof, void *data)
272 struct obd_statfs osfs;
273 int rc = obd_statfs(data, &osfs, jiffies - HZ);
275 __u32 blk_size = osfs.os_bsize >> 10;
276 __u64 result = osfs.os_bfree;
278 while (blk_size >>= 1)
282 rc = snprintf(page, count, LPU64"\n", result);
287 int lprocfs_rd_kbytesavail(char *page, char **start, off_t off, int count,
288 int *eof, void *data)
290 struct obd_statfs osfs;
291 int rc = obd_statfs(data, &osfs, jiffies - HZ);
293 __u32 blk_size = osfs.os_bsize >> 10;
294 __u64 result = osfs.os_bavail;
296 while (blk_size >>= 1)
300 rc = snprintf(page, count, LPU64"\n", result);
305 int lprocfs_rd_filestotal(char *page, char **start, off_t off, int count,
306 int *eof, void *data)
308 struct obd_statfs osfs;
309 int rc = obd_statfs(data, &osfs, jiffies - HZ);
312 rc = snprintf(page, count, LPU64"\n", osfs.os_files);
318 int lprocfs_rd_filesfree(char *page, char **start, off_t off, int count,
319 int *eof, void *data)
321 struct obd_statfs osfs;
322 int rc = obd_statfs(data, &osfs, jiffies - HZ);
325 rc = snprintf(page, count, LPU64"\n", osfs.os_ffree);
330 int lprocfs_rd_server_uuid(char *page, char **start, off_t off, int count,
331 int *eof, void *data)
333 struct obd_device *obd = (struct obd_device *)data;
334 struct obd_import *imp;
335 char *imp_state_name = NULL;
337 LASSERT(obd != NULL);
338 imp = obd->u.cli.cl_import;
339 imp_state_name = ptlrpc_import_state_name(imp->imp_state);
341 return snprintf(page, count, "%s\t%s%s\n",
342 imp->imp_target_uuid.uuid, imp_state_name,
343 imp->imp_deactive ? "\tDEACTIVATED" : "");
346 int lprocfs_rd_conn_uuid(char *page, char **start, off_t off, int count,
347 int *eof, void *data)
349 struct obd_device *obd = (struct obd_device*)data;
350 struct ptlrpc_connection *conn;
352 LASSERT(obd != NULL);
353 conn = obd->u.cli.cl_import->imp_connection;
354 LASSERT(conn != NULL);
356 return snprintf(page, count, "%s\n", conn->c_remote_uuid.uuid);
359 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
360 int *eof, void *data)
362 struct obd_device *obd = (struct obd_device*)data;
364 LASSERT(obd != NULL);
366 return snprintf(page, count, "%u\n", obd->obd_num_exports);
369 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
370 int *eof, void *data)
372 struct obd_type *class = (struct obd_type*) data;
374 LASSERT(class != NULL);
376 return snprintf(page, count, "%d\n", class->typ_refcnt);
379 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list)
383 LASSERT(obd != NULL);
384 LASSERT(obd->obd_type != NULL);
385 LASSERT(obd->obd_type->typ_procroot != NULL);
387 obd->obd_proc_entry = lprocfs_register(obd->obd_name,
388 obd->obd_type->typ_procroot,
390 if (IS_ERR(obd->obd_proc_entry)) {
391 rc = PTR_ERR(obd->obd_proc_entry);
392 CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
393 obd->obd_proc_entry = NULL;
398 int lprocfs_obd_cleanup(struct obd_device *obd)
400 if (obd && obd->obd_proc_entry) {
401 lprocfs_remove(obd->obd_proc_entry);
402 obd->obd_proc_entry = NULL;
407 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num)
409 struct lprocfs_stats *stats;
410 struct lprocfs_percpu *percpu;
411 unsigned int percpusize;
417 OBD_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_online_cpus()]));
421 percpusize = L1_CACHE_ALIGN(offsetof(typeof(*percpu), lp_cntr[num]));
422 stats->ls_percpu_size = num_online_cpus() * percpusize;
423 OBD_ALLOC(stats->ls_percpu[0], stats->ls_percpu_size);
424 if (stats->ls_percpu[0] == NULL) {
425 OBD_FREE(stats, offsetof(typeof(*stats),
426 ls_percpu[num_online_cpus()]));
431 for (i = 1; i < num_online_cpus(); i++)
432 stats->ls_percpu[i] = (void *)(stats->ls_percpu[i - 1]) +
438 void lprocfs_free_stats(struct lprocfs_stats *stats)
440 if (stats->ls_num == 0)
443 OBD_FREE(stats->ls_percpu[0], stats->ls_percpu_size);
444 OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_online_cpus()]));
447 /* Reset counter under lock */
448 int lprocfs_counter_write(struct file *file, const char *buffer,
449 unsigned long count, void *data)
455 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
457 struct lprocfs_stats *stats = p->private;
458 /* return 1st cpu location */
459 return (*pos >= stats->ls_num) ? NULL :
460 &(stats->ls_percpu[0]->lp_cntr[*pos]);
463 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
467 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
469 struct lprocfs_stats *stats = p->private;
471 return (*pos >= stats->ls_num) ? NULL :
472 &(stats->ls_percpu[0]->lp_cntr[*pos]);
475 /* seq file export of one lprocfs counter */
476 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
478 struct lprocfs_stats *stats = p->private;
479 struct lprocfs_counter *cntr = v;
480 struct lprocfs_counter t, ret = { .lc_min = ~(__u64)0 };
483 if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) {
485 do_gettimeofday(&now);
486 rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
487 "snapshot_time", now.tv_sec, now.tv_usec);
491 idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0];
493 for (i = 0; i < num_online_cpus(); i++) {
494 struct lprocfs_counter *percpu_cntr =
495 &(stats->ls_percpu[i])->lp_cntr[idx];
499 centry = atomic_read(&percpu_cntr->lc_cntl.la_entry);
500 t.lc_count = percpu_cntr->lc_count;
501 t.lc_sum = percpu_cntr->lc_sum;
502 t.lc_min = percpu_cntr->lc_min;
503 t.lc_max = percpu_cntr->lc_max;
504 t.lc_sumsquare = percpu_cntr->lc_sumsquare;
505 } while (centry != atomic_read(&percpu_cntr->lc_cntl.la_entry) &&
506 centry != atomic_read(&percpu_cntr->lc_cntl.la_exit));
507 ret.lc_count += t.lc_count;
508 ret.lc_sum += t.lc_sum;
509 if (t.lc_min < ret.lc_min)
510 ret.lc_min = t.lc_min;
511 if (t.lc_max > ret.lc_max)
512 ret.lc_max = t.lc_max;
513 ret.lc_sumsquare += t.lc_sumsquare;
516 rc = seq_printf(p, "%-25s "LPU64" samples [%s]", cntr->lc_name,
517 ret.lc_count, cntr->lc_units);
521 if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) {
522 rc = seq_printf(p, " "LPU64" "LPU64" "LPU64,
523 ret.lc_min, ret.lc_max, ret.lc_sum);
526 if (cntr->lc_config & LPROCFS_CNTR_STDDEV)
527 rc = seq_printf(p, " "LPU64, ret.lc_sumsquare);
531 rc = seq_printf(p, "\n");
533 return (rc < 0) ? rc : 0;
536 struct seq_operations lprocfs_stats_seq_sops = {
537 start: lprocfs_stats_seq_start,
538 stop: lprocfs_stats_seq_stop,
539 next: lprocfs_stats_seq_next,
540 show: lprocfs_stats_seq_show,
543 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
545 struct proc_dir_entry *dp = PDE(inode);
546 struct seq_file *seq;
549 rc = seq_open(file, &lprocfs_stats_seq_sops);
552 seq = file->private_data;
553 seq->private = dp->data;
557 struct file_operations lprocfs_stats_seq_fops = {
558 .owner = THIS_MODULE,
559 .open = lprocfs_stats_seq_open,
562 .release = seq_release,
565 int lprocfs_register_stats(struct proc_dir_entry *root, const char *name,
566 struct lprocfs_stats *stats)
568 struct proc_dir_entry *entry;
569 LASSERT(root != NULL);
571 entry = create_proc_entry(name, 0444, root);
574 entry->proc_fops = &lprocfs_stats_seq_fops;
575 entry->data = (void *)stats;
576 entry->write_proc = lprocfs_counter_write;
580 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
581 unsigned conf, const char *name, const char *units)
583 struct lprocfs_counter *c;
586 LASSERT(stats != NULL);
587 for (i = 0; i < num_online_cpus(); i++) {
588 c = &(stats->ls_percpu[i]->lp_cntr[index]);
590 c->lc_min = ~(__u64)0;
595 EXPORT_SYMBOL(lprocfs_counter_init);
597 #define LPROCFS_OBD_OP_INIT(base, stats, op) \
599 unsigned int coffset = base + OBD_COUNTER_OFFSET(op); \
600 LASSERT(coffset < stats->ls_num); \
601 lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \
604 int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
606 struct lprocfs_stats *stats;
607 unsigned int num_stats;
610 LASSERT(obd->obd_stats == NULL);
611 LASSERT(obd->obd_proc_entry != NULL);
612 LASSERT(obd->obd_cntr_base == 0);
614 num_stats = 1 + OBD_COUNTER_OFFSET(quotactl) +
616 stats = lprocfs_alloc_stats(num_stats);
620 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
621 LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
622 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info);
623 LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
624 LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
625 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
626 LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
627 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
628 LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
629 LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
630 LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
631 LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
632 LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
633 LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
634 LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
635 LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
636 LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
637 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
638 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
639 LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
640 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
641 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
642 LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
643 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
644 LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
645 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
646 LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw_async);
647 LPROCFS_OBD_OP_INIT(num_private_stats, stats, prep_async_page);
648 LPROCFS_OBD_OP_INIT(num_private_stats, stats, queue_async_io);
649 LPROCFS_OBD_OP_INIT(num_private_stats, stats, queue_group_io);
650 LPROCFS_OBD_OP_INIT(num_private_stats, stats, trigger_group_io);
651 LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_async_flags);
652 LPROCFS_OBD_OP_INIT(num_private_stats, stats, teardown_async_page);
653 LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
654 LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
655 LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
656 LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
657 LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
658 LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
659 LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
660 LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
661 LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
662 LPROCFS_OBD_OP_INIT(num_private_stats, stats, match);
663 LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
664 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
665 LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
666 LPROCFS_OBD_OP_INIT(num_private_stats, stats, join_lru);
667 LPROCFS_OBD_OP_INIT(num_private_stats, stats, san_preprw);
668 LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
669 LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
670 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
671 LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
672 LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
673 LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
674 LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
675 LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
676 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
677 LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
678 LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
680 for (i = num_private_stats; i < num_stats; i++) {
681 /* If this LBUGs, it is likely that an obd
682 * operation was added to struct obd_ops in
683 * <linux/obd.h>, and that the corresponding line item
684 * LPROCFS_OBD_OP_INIT(.., .., opname)
685 * is missing from the list above. */
686 if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) {
687 CERROR("Missing obd_stat initializer obd_op "
688 "operation at offset %d. Aborting.\n",
689 i - num_private_stats);
693 rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
695 lprocfs_free_stats(stats);
697 obd->obd_stats = stats;
698 obd->obd_cntr_base = num_private_stats;
703 void lprocfs_free_obd_stats(struct obd_device *obd)
705 struct lprocfs_stats *stats = obd->obd_stats;
708 obd->obd_stats = NULL;
709 lprocfs_free_stats(stats);
713 int lprocfs_write_helper(const char *buffer, unsigned long count,
716 char kernbuf[20], *end;
718 if (count > (sizeof(kernbuf) - 1))
721 if (copy_from_user(kernbuf, buffer, count))
724 kernbuf[count] = '\0';
726 *val = simple_strtol(kernbuf, &end, 0);
733 int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val)
735 char kernbuf[22], *end;
737 if (count > (sizeof(kernbuf) - 1))
740 if (copy_from_user(kernbuf, buffer, count))
743 kernbuf[count] = '\0';
745 if (kernbuf[0] == '-')
746 *val = -simple_strtoull(kernbuf + 1, &end, 0);
748 *val = simple_strtoull(kernbuf, &end, 0);
755 int lprocfs_obd_seq_create(struct obd_device *dev, char *name, mode_t mode,
756 struct file_operations *seq_fops, void *data)
758 struct proc_dir_entry *entry;
761 entry = create_proc_entry(name, mode, dev->obd_proc_entry);
764 entry->proc_fops = seq_fops;
769 EXPORT_SYMBOL(lprocfs_obd_seq_create);
771 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
775 if (value >= OBD_HIST_MAX)
776 value = OBD_HIST_MAX - 1;
778 spin_lock_irqsave(&oh->oh_lock, flags);
779 oh->oh_buckets[value]++;
780 spin_unlock_irqrestore(&oh->oh_lock, flags);
782 EXPORT_SYMBOL(lprocfs_oh_tally);
784 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
788 for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
791 lprocfs_oh_tally(oh, val);
793 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
795 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
797 unsigned long ret = 0;
800 for (i = 0; i < OBD_HIST_MAX; i++)
801 ret += oh->oh_buckets[i];
804 EXPORT_SYMBOL(lprocfs_oh_sum);
806 void lprocfs_oh_clear(struct obd_histogram *oh)
809 spin_lock_irqsave(&oh->oh_lock, flags);
810 memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
811 spin_unlock_irqrestore(&oh->oh_lock, flags);
813 EXPORT_SYMBOL(lprocfs_oh_clear);
815 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
816 int count, int *eof, void *data)
818 struct obd_device *obd = data;
820 connected = obd->obd_connected_clients,
821 max_recoverable = obd->obd_max_recoverable_clients,
822 recoverable = obd->obd_recoverable_clients,
823 completed = max_recoverable - recoverable,
824 queue_len = obd->obd_requests_queued_for_recovery,
825 replayed = obd->obd_replayed_requests;
826 __u64 next_transno = obd->obd_next_recovery_transno;
828 LASSERT(obd != NULL);
831 n = snprintf(page, count, "status: ");
832 page += n; len += n; count -= n;
833 if (obd->obd_max_recoverable_clients == 0) {
834 n = snprintf(page, count, "INACTIVE\n");
838 /* sampled unlocked, but really... */
839 if (obd->obd_recovering == 0) {
840 n = snprintf(page, count, "COMPLETE\n");
841 page += n; len += n; count -= n;
843 n = snprintf(page, count, "recovery_start: %lu\n",
844 obd->obd_recovery_start);
845 page += n; len += n; count -= n;
846 n = snprintf(page, count, "recovery_end: %lu\n",
847 obd->obd_recovery_end);
848 page += n; len += n; count -= n;
849 n = snprintf(page, count, "recovered_clients: %d\n",
851 page += n; len += n; count -= n;
852 n = snprintf(page, count, "unrecovered_clients: %d\n",
853 obd->obd_recoverable_clients);
854 page += n; len += n; count -= n;
855 n = snprintf(page, count, "last_transno: "LPD64"\n",
857 page += n; len += n; count -= n;
858 n = snprintf(page, count, "replayed_requests: %d\n", replayed);
862 n = snprintf(page, count, "RECOVERING\n");
863 page += n; len += n; count -= n;
864 n = snprintf(page, count, "recovery_start: %lu\n",
865 obd->obd_recovery_start);
866 page += n; len += n; count -= n;
867 n = snprintf(page, count, "time remaining: %lu\n",
868 CURRENT_SECONDS >= obd->obd_recovery_end ? 0 :
869 obd->obd_recovery_end - CURRENT_SECONDS);
870 page += n; len += n; count -= n;
871 n = snprintf(page, count, "connected_clients: %d/%d\n",
872 connected, max_recoverable);
873 page += n; len += n; count -= n;
874 n = snprintf(page, count, "completed_clients: %d/%d\n",
875 completed, max_recoverable);
876 page += n; len += n; count -= n;
877 n = snprintf(page, count, "replayed_requests: %d/??\n", replayed);
878 page += n; len += n; count -= n;
879 n = snprintf(page, count, "queued_requests: %d\n", queue_len);
880 page += n; len += n; count -= n;
881 n = snprintf(page, count, "next_transno: "LPD64"\n", next_transno);
884 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
886 EXPORT_SYMBOL(lprocfs_register);
887 EXPORT_SYMBOL(lprocfs_srch);
888 EXPORT_SYMBOL(lprocfs_remove);
889 EXPORT_SYMBOL(lprocfs_add_vars);
890 EXPORT_SYMBOL(lprocfs_obd_setup);
891 EXPORT_SYMBOL(lprocfs_obd_cleanup);
892 EXPORT_SYMBOL(lprocfs_alloc_stats);
893 EXPORT_SYMBOL(lprocfs_free_stats);
894 EXPORT_SYMBOL(lprocfs_register_stats);
895 EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
896 EXPORT_SYMBOL(lprocfs_free_obd_stats);
898 EXPORT_SYMBOL(lprocfs_rd_u64);
899 EXPORT_SYMBOL(lprocfs_rd_atomic);
900 EXPORT_SYMBOL(lprocfs_rd_uuid);
901 EXPORT_SYMBOL(lprocfs_rd_name);
902 EXPORT_SYMBOL(lprocfs_rd_fstype);
903 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
904 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
905 EXPORT_SYMBOL(lprocfs_rd_num_exports);
906 EXPORT_SYMBOL(lprocfs_rd_numrefs);
908 EXPORT_SYMBOL(lprocfs_rd_blksize);
909 EXPORT_SYMBOL(lprocfs_rd_kbytestotal);
910 EXPORT_SYMBOL(lprocfs_rd_kbytesfree);
911 EXPORT_SYMBOL(lprocfs_rd_kbytesavail);
912 EXPORT_SYMBOL(lprocfs_rd_filestotal);
913 EXPORT_SYMBOL(lprocfs_rd_filesfree);
915 EXPORT_SYMBOL(lprocfs_write_helper);
916 EXPORT_SYMBOL(lprocfs_write_u64_helper);